index.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
  2. import * as React from 'react';
  3. import classnames from 'classnames';
  4. // ========================= ClassNames =========================
  5. export function mergeClassNames(schema, ...classNames) {
  6. const mergedSchema = schema || {};
  7. return classNames.reduce((acc, cur) => {
  8. // Loop keys of the current classNames
  9. Object.keys(cur || {}).forEach(key => {
  10. const keySchema = mergedSchema[key];
  11. const curVal = cur[key];
  12. if (keySchema && typeof keySchema === 'object') {
  13. if (curVal && typeof curVal === 'object') {
  14. // Loop fill
  15. acc[key] = mergeClassNames(keySchema, acc[key], curVal);
  16. } else {
  17. // Covert string to object structure
  18. const {
  19. _default: defaultField
  20. } = keySchema;
  21. acc[key] = acc[key] || {};
  22. acc[key][defaultField] = classnames(acc[key][defaultField], curVal);
  23. }
  24. } else {
  25. // Flatten fill
  26. acc[key] = classnames(acc[key], curVal);
  27. }
  28. });
  29. return acc;
  30. }, {});
  31. }
  32. function useSemanticClassNames(schema, ...classNames) {
  33. return React.useMemo(() => mergeClassNames.apply(void 0, [schema].concat(classNames)), [classNames]);
  34. }
  35. // =========================== Styles ===========================
  36. function useSemanticStyles(...styles) {
  37. return React.useMemo(() => {
  38. return styles.reduce((acc, cur = {}) => {
  39. Object.keys(cur).forEach(key => {
  40. acc[key] = Object.assign(Object.assign({}, acc[key]), cur[key]);
  41. });
  42. return acc;
  43. }, {});
  44. }, [styles]);
  45. }
  46. // =========================== Export ===========================
  47. function fillObjectBySchema(obj, schema) {
  48. const newObj = Object.assign({}, obj);
  49. Object.keys(schema).forEach(key => {
  50. if (key !== '_default') {
  51. const nestSchema = schema[key];
  52. const nextValue = newObj[key] || {};
  53. newObj[key] = nestSchema ? fillObjectBySchema(nextValue, nestSchema) : nextValue;
  54. }
  55. });
  56. return newObj;
  57. }
  58. /**
  59. * Merge classNames and styles from multiple sources.
  60. * When `schema` is provided, it will **must** provide the nest object structure.
  61. */
  62. export default function useMergeSemantic(classNamesList, stylesList, schema) {
  63. const mergedClassNames = useSemanticClassNames.apply(void 0, [schema].concat(_toConsumableArray(classNamesList)));
  64. const mergedStyles = useSemanticStyles.apply(void 0, _toConsumableArray(stylesList));
  65. return React.useMemo(() => {
  66. return [fillObjectBySchema(mergedClassNames, schema), fillObjectBySchema(mergedStyles, schema)];
  67. }, [mergedClassNames, mergedStyles]);
  68. }