@mui/system 9.0.0-alpha.4 → 9.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/Box/Box.d.mts +1 -1
  2. package/Box/Box.d.ts +1 -1
  3. package/CHANGELOG.md +71 -4
  4. package/Stack/StackProps.d.mts +1 -2
  5. package/Stack/StackProps.d.ts +1 -2
  6. package/Stack/createStack.js +1 -3
  7. package/Stack/createStack.mjs +1 -3
  8. package/breakpoints/breakpoints.d.mts +4 -1
  9. package/breakpoints/breakpoints.d.ts +4 -1
  10. package/breakpoints/breakpoints.js +90 -49
  11. package/breakpoints/breakpoints.mjs +86 -49
  12. package/compose/compose.js +6 -6
  13. package/compose/compose.mjs +6 -6
  14. package/createBox/createBox.js +2 -2
  15. package/createBox/createBox.mjs +2 -2
  16. package/createBreakpoints/createBreakpoints.d.mts +5 -0
  17. package/createBreakpoints/createBreakpoints.d.ts +5 -0
  18. package/createBreakpoints/createBreakpoints.js +5 -0
  19. package/createBreakpoints/createBreakpoints.mjs +5 -0
  20. package/createStyled/createStyled.js +2 -8
  21. package/createStyled/createStyled.mjs +1 -7
  22. package/createTheme/createTheme.js +1 -0
  23. package/createTheme/createTheme.mjs +1 -0
  24. package/cssContainerQueries/cssContainerQueries.d.mts +1 -0
  25. package/cssContainerQueries/cssContainerQueries.d.ts +1 -0
  26. package/cssContainerQueries/cssContainerQueries.js +27 -14
  27. package/cssContainerQueries/cssContainerQueries.mjs +27 -14
  28. package/cssVars/createCssVarsTheme.js +1 -0
  29. package/cssVars/createCssVarsTheme.mjs +1 -0
  30. package/index.js +1 -1
  31. package/index.mjs +1 -1
  32. package/merge/merge.js +4 -3
  33. package/merge/merge.mjs +4 -3
  34. package/package.json +6 -6
  35. package/spacing/spacing.js +45 -45
  36. package/spacing/spacing.mjs +47 -45
  37. package/style/index.d.mts +1 -0
  38. package/style/index.d.ts +1 -0
  39. package/style/index.js +9 -1
  40. package/style/index.mjs +1 -0
  41. package/style/style.d.mts +36 -7
  42. package/style/style.d.ts +36 -7
  43. package/style/style.js +85 -34
  44. package/style/style.mjs +84 -34
  45. package/styleFunctionSx/styleFunctionSx.js +95 -100
  46. package/styleFunctionSx/styleFunctionSx.mjs +98 -102
  47. package/version/index.js +2 -2
  48. package/version/index.mjs +2 -2
@@ -1,8 +1,12 @@
1
1
  import responsivePropType from "../responsivePropType/index.mjs";
2
- import { handleBreakpoints } from "../breakpoints/index.mjs";
2
+ import { iterateBreakpoints } from "../breakpoints/index.mjs";
3
3
  import { getPath } from "../style/index.mjs";
4
- import merge from "../merge/index.mjs";
5
- import memoize from "../memoize/index.mjs";
4
+
5
+ /* eslint-disable guard-for-in */
6
+
7
+ const EMPTY_THEME = {
8
+ internal_cache: {}
9
+ };
6
10
  const properties = {
7
11
  m: 'margin',
8
12
  p: 'padding'
@@ -21,27 +25,24 @@ const aliases = {
21
25
  paddingX: 'px',
22
26
  paddingY: 'py'
23
27
  };
24
-
25
- // memoize() impact:
26
- // From 300,000 ops/sec
27
- // To 350,000 ops/sec
28
- const getCssProperties = memoize(prop => {
29
- // It's not a shorthand notation.
30
- if (prop.length > 2) {
31
- if (aliases[prop]) {
32
- prop = aliases[prop];
33
- } else {
34
- return [prop];
35
- }
28
+ const CSS_PROPERTIES = {};
29
+ for (const key in properties) {
30
+ CSS_PROPERTIES[key] = [properties[key]];
31
+ }
32
+ for (const keyProperty in properties) {
33
+ for (const keyDirection in directions) {
34
+ const property = properties[keyProperty];
35
+ const direction = directions[keyDirection];
36
+ const value = Array.isArray(direction) ? direction.map(dir => property + dir) : [property + direction];
37
+ CSS_PROPERTIES[keyProperty + keyDirection] = value;
36
38
  }
37
- const [a, b] = prop.split('');
38
- const property = properties[a];
39
- const direction = directions[b] || '';
40
- return Array.isArray(direction) ? direction.map(dir => property + dir) : [property + direction];
41
- });
42
- export const marginKeys = ['m', 'mt', 'mr', 'mb', 'ml', 'mx', 'my', 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'marginX', 'marginY', 'marginInline', 'marginInlineStart', 'marginInlineEnd', 'marginBlock', 'marginBlockStart', 'marginBlockEnd'];
43
- export const paddingKeys = ['p', 'pt', 'pr', 'pb', 'pl', 'px', 'py', 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'paddingX', 'paddingY', 'paddingInline', 'paddingInlineStart', 'paddingInlineEnd', 'paddingBlock', 'paddingBlockStart', 'paddingBlockEnd'];
44
- const spacingKeys = [...marginKeys, ...paddingKeys];
39
+ }
40
+ for (const key in aliases) {
41
+ CSS_PROPERTIES[key] = CSS_PROPERTIES[aliases[key]];
42
+ }
43
+ export const marginKeys = new Set(['m', 'mt', 'mr', 'mb', 'ml', 'mx', 'my', 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft', 'marginX', 'marginY', 'marginInline', 'marginInlineStart', 'marginInlineEnd', 'marginBlock', 'marginBlockStart', 'marginBlockEnd']);
44
+ export const paddingKeys = new Set(['p', 'pt', 'pr', 'pb', 'pl', 'px', 'py', 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'paddingX', 'paddingY', 'paddingInline', 'paddingInlineStart', 'paddingInlineEnd', 'paddingBlock', 'paddingBlockStart', 'paddingBlockEnd']);
45
+ const spacingKeys = new Set([...marginKeys, ...paddingKeys]);
45
46
  export function createUnaryUnit(theme, themeKey, defaultValue, propName) {
46
47
  const themeSpacing = getPath(theme, themeKey, true) ?? defaultValue;
47
48
  if (typeof themeSpacing === 'number' || typeof themeSpacing === 'string') {
@@ -109,31 +110,32 @@ export function getValue(transformer, propValue) {
109
110
  }
110
111
  return transformer(propValue);
111
112
  }
112
- export function getStyleFromPropValue(cssProperties, transformer) {
113
- return propValue => cssProperties.reduce((acc, cssProperty) => {
114
- acc[cssProperty] = getValue(transformer, propValue);
115
- return acc;
116
- }, {});
117
- }
118
- function resolveCssProperty(props, keys, prop, transformer) {
119
- // Using a hash computation over an array iteration could be faster, but with only 28 items,
120
- // it's doesn't worth the bundle size.
121
- if (!keys.includes(prop)) {
122
- return null;
123
- }
124
- const cssProperties = getCssProperties(prop);
125
- const styleFromPropValue = getStyleFromPropValue(cssProperties, transformer);
126
- const propValue = props[prop];
127
- return handleBreakpoints(props, propValue, styleFromPropValue);
128
- }
113
+
114
+ // Avoid allocations
115
+ const container = [''];
129
116
  function style(props, keys) {
130
- const transformer = createUnarySpacing(props.theme);
131
- return Object.keys(props).map(prop => resolveCssProperty(props, keys, prop, transformer)).reduce(merge, {});
117
+ const theme = props.theme ?? EMPTY_THEME;
118
+ const transformer = theme?.internal_cache?.unarySpacing ?? createUnarySpacing(theme);
119
+ const result = {};
120
+ for (const prop in props) {
121
+ if (!keys.has(prop)) {
122
+ continue;
123
+ }
124
+ const cssProperties = CSS_PROPERTIES[prop] ?? (container[0] = prop, container);
125
+ const propValue = props[prop];
126
+ iterateBreakpoints(result, props.theme, propValue, (mediaKey, value) => {
127
+ const target = mediaKey ? result[mediaKey] : result;
128
+ for (let i = 0; i < cssProperties.length; i += 1) {
129
+ target[cssProperties[i]] = getValue(transformer, value);
130
+ }
131
+ });
132
+ }
133
+ return result;
132
134
  }
133
135
  export function margin(props) {
134
136
  return style(props, marginKeys);
135
137
  }
136
- margin.propTypes = process.env.NODE_ENV !== 'production' ? marginKeys.reduce((obj, key) => {
138
+ margin.propTypes = process.env.NODE_ENV !== 'production' ? Array.from(marginKeys).reduce((obj, key) => {
137
139
  obj[key] = responsivePropType;
138
140
  return obj;
139
141
  }, {}) : {};
@@ -141,7 +143,7 @@ margin.filterProps = marginKeys;
141
143
  export function padding(props) {
142
144
  return style(props, paddingKeys);
143
145
  }
144
- padding.propTypes = process.env.NODE_ENV !== 'production' ? paddingKeys.reduce((obj, key) => {
146
+ padding.propTypes = process.env.NODE_ENV !== 'production' ? Array.from(paddingKeys).reduce((obj, key) => {
145
147
  obj[key] = responsivePropType;
146
148
  return obj;
147
149
  }, {}) : {};
@@ -149,7 +151,7 @@ padding.filterProps = paddingKeys;
149
151
  function spacing(props) {
150
152
  return style(props, spacingKeys);
151
153
  }
152
- spacing.propTypes = process.env.NODE_ENV !== 'production' ? spacingKeys.reduce((obj, key) => {
154
+ spacing.propTypes = process.env.NODE_ENV !== 'production' ? Array.from(spacingKeys).reduce((obj, key) => {
153
155
  obj[key] = responsivePropType;
154
156
  return obj;
155
157
  }, {}) : {};
package/style/index.d.mts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { default } from "./style.mjs";
2
+ export { default as style } from "./style.mjs";
2
3
  export * from "./style.mjs";
package/style/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { default } from "./style.js";
2
+ export { default as style } from "./style.js";
2
3
  export * from "./style.js";
package/style/index.js CHANGED
@@ -4,13 +4,21 @@ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWild
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- var _exportNames = {};
7
+ var _exportNames = {
8
+ style: true
9
+ };
8
10
  Object.defineProperty(exports, "default", {
9
11
  enumerable: true,
10
12
  get: function () {
11
13
  return _style.default;
12
14
  }
13
15
  });
16
+ Object.defineProperty(exports, "style", {
17
+ enumerable: true,
18
+ get: function () {
19
+ return _style.default;
20
+ }
21
+ });
14
22
  var _style = _interopRequireWildcard(require("./style"));
15
23
  Object.keys(_style).forEach(function (key) {
16
24
  if (key === "default" || key === "__esModule") return;
package/style/index.mjs CHANGED
@@ -1,2 +1,3 @@
1
1
  export { default } from "./style.mjs";
2
+ export { default as style } from "./style.mjs";
2
3
  export * from "./style.mjs";
package/style/style.d.mts CHANGED
@@ -1,10 +1,10 @@
1
- import { CSSObject } from '@mui/styled-engine';
2
- export type PropsFor<SomeStyleFunction> = SomeStyleFunction extends StyleFunction<infer Props> ? Props : never;
1
+ import type { CSSObject } from '@mui/styled-engine';
3
2
  export type StyleFunction<Props> = (props: Props) => any;
3
+ export type PropsFor<SomeStyleFunction> = SomeStyleFunction extends StyleFunction<infer Props> ? Props : never;
4
4
  export type SimpleStyleFunction<PropKey extends keyof any> = StyleFunction<Partial<Record<PropKey, any>>> & {
5
5
  filterProps: string[];
6
6
  };
7
- export type TransformFunction = (cssValue: unknown, userValue: unknown) => number | string | React.CSSProperties | CSSObject;
7
+ export type TransformFunction = (cssValue: unknown, userValue: unknown, transform: object | ((arg: any) => any) | undefined | null) => number | string | React.CSSProperties | CSSObject;
8
8
  export interface StyleOptions<PropKey> {
9
9
  cssProperty?: PropKey | keyof React.CSSProperties | false | undefined;
10
10
  prop: PropKey;
@@ -14,10 +14,39 @@ export interface StyleOptions<PropKey> {
14
14
  themeKey?: string | undefined;
15
15
  transform?: TransformFunction | undefined;
16
16
  }
17
- export function getPath<T>(obj: T, path: string | undefined, checkVars?: boolean): null | unknown;
18
- export function getStyleValue(themeMapping: object | ((arg: any) => any), transform: TransformFunction | null, propValueFinal: unknown, userValue?: unknown): any;
19
- export default function style<PropKey extends string, Theme extends object>(options: StyleOptions<PropKey>): StyleFunction<{ [K in PropKey]?: unknown } & {
17
+ /**
18
+ * TODO(v7): Keep either this one or `getStyleValue2`
19
+ */
20
+ export declare function getStyleValue(themeMapping: object | ((arg: any) => any) | null | undefined, transform: TransformFunction | null | undefined, valueFinal: unknown, userValue?: unknown): any;
21
+ /**
22
+ * HACK: The `alternateProp` logic is there because our theme looks like this:
23
+ * {
24
+ * typography: {
25
+ * fontFamily: 'comic sans',
26
+ * fontFamilyCode: 'courrier new',
27
+ * }
28
+ * }
29
+ * And we support targetting:
30
+ * - `typography.fontFamily` with `sx={{ fontFamily: 'default' }}`
31
+ * - `typography.fontFamilyCode` with `sx={{ fontFamily: 'code' }}`
32
+ *
33
+ * TODO(v7): Refactor our theme to look like this and remove the horrendous logic:
34
+ * {
35
+ * typography: {
36
+ * fontFamily: {
37
+ * default: 'comic sans',
38
+ * code: 'courrier new',
39
+ * }
40
+ * }
41
+ * }
42
+ */
43
+ export declare function getStyleValue2(themeMapping: object | ((arg: any) => any) | null | undefined, transform: TransformFunction | null | undefined, userValue: unknown, alternateProp: string | undefined): any;
44
+ export declare function getPath<T extends Record<string, any> | undefined | null>(obj: T, pathInput: string | undefined, checkVars?: boolean, alternateProp?: string | undefined): null | unknown;
45
+ type StyleResult<PropKey extends string | number | symbol, Theme> = StyleFunction<{ [K in PropKey]?: unknown } & {
20
46
  theme?: Theme | undefined;
21
47
  }> & {
22
48
  filterProps: string[];
23
- };
49
+ propTypes: any;
50
+ };
51
+ export default function style<PropKey extends string, Theme extends object>(options: StyleOptions<PropKey>): StyleResult<PropKey, Theme>;
52
+ export {};
package/style/style.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { CSSObject } from '@mui/styled-engine';
2
- export type PropsFor<SomeStyleFunction> = SomeStyleFunction extends StyleFunction<infer Props> ? Props : never;
1
+ import type { CSSObject } from '@mui/styled-engine';
3
2
  export type StyleFunction<Props> = (props: Props) => any;
3
+ export type PropsFor<SomeStyleFunction> = SomeStyleFunction extends StyleFunction<infer Props> ? Props : never;
4
4
  export type SimpleStyleFunction<PropKey extends keyof any> = StyleFunction<Partial<Record<PropKey, any>>> & {
5
5
  filterProps: string[];
6
6
  };
7
- export type TransformFunction = (cssValue: unknown, userValue: unknown) => number | string | React.CSSProperties | CSSObject;
7
+ export type TransformFunction = (cssValue: unknown, userValue: unknown, transform: object | ((arg: any) => any) | undefined | null) => number | string | React.CSSProperties | CSSObject;
8
8
  export interface StyleOptions<PropKey> {
9
9
  cssProperty?: PropKey | keyof React.CSSProperties | false | undefined;
10
10
  prop: PropKey;
@@ -14,10 +14,39 @@ export interface StyleOptions<PropKey> {
14
14
  themeKey?: string | undefined;
15
15
  transform?: TransformFunction | undefined;
16
16
  }
17
- export function getPath<T>(obj: T, path: string | undefined, checkVars?: boolean): null | unknown;
18
- export function getStyleValue(themeMapping: object | ((arg: any) => any), transform: TransformFunction | null, propValueFinal: unknown, userValue?: unknown): any;
19
- export default function style<PropKey extends string, Theme extends object>(options: StyleOptions<PropKey>): StyleFunction<{ [K in PropKey]?: unknown } & {
17
+ /**
18
+ * TODO(v7): Keep either this one or `getStyleValue2`
19
+ */
20
+ export declare function getStyleValue(themeMapping: object | ((arg: any) => any) | null | undefined, transform: TransformFunction | null | undefined, valueFinal: unknown, userValue?: unknown): any;
21
+ /**
22
+ * HACK: The `alternateProp` logic is there because our theme looks like this:
23
+ * {
24
+ * typography: {
25
+ * fontFamily: 'comic sans',
26
+ * fontFamilyCode: 'courrier new',
27
+ * }
28
+ * }
29
+ * And we support targetting:
30
+ * - `typography.fontFamily` with `sx={{ fontFamily: 'default' }}`
31
+ * - `typography.fontFamilyCode` with `sx={{ fontFamily: 'code' }}`
32
+ *
33
+ * TODO(v7): Refactor our theme to look like this and remove the horrendous logic:
34
+ * {
35
+ * typography: {
36
+ * fontFamily: {
37
+ * default: 'comic sans',
38
+ * code: 'courrier new',
39
+ * }
40
+ * }
41
+ * }
42
+ */
43
+ export declare function getStyleValue2(themeMapping: object | ((arg: any) => any) | null | undefined, transform: TransformFunction | null | undefined, userValue: unknown, alternateProp: string | undefined): any;
44
+ export declare function getPath<T extends Record<string, any> | undefined | null>(obj: T, pathInput: string | undefined, checkVars?: boolean, alternateProp?: string | undefined): null | unknown;
45
+ type StyleResult<PropKey extends string | number | symbol, Theme> = StyleFunction<{ [K in PropKey]?: unknown } & {
20
46
  theme?: Theme | undefined;
21
47
  }> & {
22
48
  filterProps: string[];
23
- };
49
+ propTypes: any;
50
+ };
51
+ export default function style<PropKey extends string, Theme extends object>(options: StyleOptions<PropKey>): StyleResult<PropKey, Theme>;
52
+ export {};
package/style/style.js CHANGED
@@ -4,45 +4,105 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.default = void 0;
7
+ exports.default = style;
8
8
  exports.getPath = getPath;
9
9
  exports.getStyleValue = getStyleValue;
10
+ exports.getStyleValue2 = getStyleValue2;
10
11
  var _capitalize = _interopRequireDefault(require("@mui/utils/capitalize"));
11
12
  var _responsivePropType = _interopRequireDefault(require("../responsivePropType"));
12
13
  var _breakpoints = require("../breakpoints");
13
- function getPath(obj, path, checkVars = true) {
14
- if (!path || typeof path !== 'string') {
15
- return null;
14
+ /**
15
+ * TODO(v7): Keep either this one or `getStyleValue2`
16
+ */
17
+ function getStyleValue(themeMapping, transform, valueFinal, userValue = valueFinal) {
18
+ let value;
19
+ if (typeof themeMapping === 'function') {
20
+ value = themeMapping(valueFinal);
21
+ } else if (Array.isArray(themeMapping)) {
22
+ value = themeMapping[valueFinal] || userValue;
23
+ } else if (typeof valueFinal === 'string') {
24
+ value = getPath(themeMapping, valueFinal) || userValue;
25
+ } else {
26
+ value = userValue;
16
27
  }
17
-
18
- // Check if CSS variables are used
19
- if (obj && obj.vars && checkVars) {
20
- const val = `vars.${path}`.split('.').reduce((acc, item) => acc && acc[item] ? acc[item] : null, obj);
21
- if (val != null) {
22
- return val;
23
- }
28
+ if (transform) {
29
+ value = transform(value, userValue, themeMapping);
24
30
  }
25
- return path.split('.').reduce((acc, item) => {
26
- if (acc && acc[item] != null) {
27
- return acc[item];
28
- }
29
- return null;
30
- }, obj);
31
+ return value;
31
32
  }
32
- function getStyleValue(themeMapping, transform, propValueFinal, userValue = propValueFinal) {
33
+
34
+ /**
35
+ * HACK: The `alternateProp` logic is there because our theme looks like this:
36
+ * {
37
+ * typography: {
38
+ * fontFamily: 'comic sans',
39
+ * fontFamilyCode: 'courrier new',
40
+ * }
41
+ * }
42
+ * And we support targetting:
43
+ * - `typography.fontFamily` with `sx={{ fontFamily: 'default' }}`
44
+ * - `typography.fontFamilyCode` with `sx={{ fontFamily: 'code' }}`
45
+ *
46
+ * TODO(v7): Refactor our theme to look like this and remove the horrendous logic:
47
+ * {
48
+ * typography: {
49
+ * fontFamily: {
50
+ * default: 'comic sans',
51
+ * code: 'courrier new',
52
+ * }
53
+ * }
54
+ * }
55
+ */
56
+ function getStyleValue2(themeMapping, transform, userValue, alternateProp) {
33
57
  let value;
34
58
  if (typeof themeMapping === 'function') {
35
- value = themeMapping(propValueFinal);
59
+ value = themeMapping(userValue);
36
60
  } else if (Array.isArray(themeMapping)) {
37
- value = themeMapping[propValueFinal] || userValue;
61
+ value = themeMapping[userValue] || userValue;
62
+ } else if (typeof userValue === 'string') {
63
+ value = getPath(themeMapping, userValue, true, alternateProp) || userValue;
38
64
  } else {
39
- value = getPath(themeMapping, propValueFinal) || userValue;
65
+ value = userValue;
40
66
  }
41
67
  if (transform) {
42
68
  value = transform(value, userValue, themeMapping);
43
69
  }
44
70
  return value;
45
71
  }
72
+ function getPath(obj, pathInput, checkVars = true, alternateProp = undefined) {
73
+ if (!obj || !pathInput) {
74
+ return null;
75
+ }
76
+ const path = pathInput.split('.');
77
+
78
+ // Check if CSS variables are used
79
+ if (obj.vars && checkVars) {
80
+ const val = getPathImpl(obj.vars, path, alternateProp);
81
+ if (val != null) {
82
+ return val;
83
+ }
84
+ }
85
+ return getPathImpl(obj, path, alternateProp);
86
+ }
87
+ function getPathImpl(object, path, alternateProp = undefined) {
88
+ let lastResult = undefined;
89
+ let result = object;
90
+ let index = 0;
91
+ while (index < path.length) {
92
+ if (result === null || result === undefined) {
93
+ return result;
94
+ }
95
+ lastResult = result;
96
+ result = result[path[index]];
97
+ index += 1;
98
+ }
99
+ if (alternateProp && result === undefined) {
100
+ const lastKey = path[path.length - 1];
101
+ const alternateKey = `${alternateProp}${lastKey === 'default' ? '' : (0, _capitalize.default)(lastKey)}`;
102
+ return lastResult?.[alternateKey];
103
+ }
104
+ return result;
105
+ }
46
106
  function style(options) {
47
107
  const {
48
108
  prop,
@@ -51,7 +111,6 @@ function style(options) {
51
111
  transform
52
112
  } = options;
53
113
 
54
- // false positive
55
114
  // eslint-disable-next-line react/function-component-definition
56
115
  const fn = props => {
57
116
  if (props[prop] == null) {
@@ -60,16 +119,9 @@ function style(options) {
60
119
  const propValue = props[prop];
61
120
  const theme = props.theme;
62
121
  const themeMapping = getPath(theme, themeKey) || {};
63
- const styleFromPropValue = propValueFinal => {
64
- let value = getStyleValue(themeMapping, transform, propValueFinal);
65
- if (propValueFinal === value && typeof propValueFinal === 'string') {
66
- // Haven't found value
67
- value = getStyleValue(themeMapping, transform, `${prop}${propValueFinal === 'default' ? '' : (0, _capitalize.default)(propValueFinal)}`, propValueFinal);
68
- }
69
- if (cssProperty === false) {
70
- return value;
71
- }
72
- return {
122
+ const styleFromPropValue = valueFinal => {
123
+ const value = getStyleValue2(themeMapping, transform, valueFinal, prop);
124
+ return cssProperty === false ? value : {
73
125
  [cssProperty]: value
74
126
  };
75
127
  };
@@ -80,5 +132,4 @@ function style(options) {
80
132
  } : {};
81
133
  fn.filterProps = [prop];
82
134
  return fn;
83
- }
84
- var _default = exports.default = style;
135
+ }
package/style/style.mjs CHANGED
@@ -1,40 +1,99 @@
1
1
  import capitalize from '@mui/utils/capitalize';
2
2
  import responsivePropType from "../responsivePropType/index.mjs";
3
3
  import { handleBreakpoints } from "../breakpoints/index.mjs";
4
- export function getPath(obj, path, checkVars = true) {
5
- if (!path || typeof path !== 'string') {
6
- return null;
4
+ /**
5
+ * TODO(v7): Keep either this one or `getStyleValue2`
6
+ */
7
+ export function getStyleValue(themeMapping, transform, valueFinal, userValue = valueFinal) {
8
+ let value;
9
+ if (typeof themeMapping === 'function') {
10
+ value = themeMapping(valueFinal);
11
+ } else if (Array.isArray(themeMapping)) {
12
+ value = themeMapping[valueFinal] || userValue;
13
+ } else if (typeof valueFinal === 'string') {
14
+ value = getPath(themeMapping, valueFinal) || userValue;
15
+ } else {
16
+ value = userValue;
7
17
  }
8
-
9
- // Check if CSS variables are used
10
- if (obj && obj.vars && checkVars) {
11
- const val = `vars.${path}`.split('.').reduce((acc, item) => acc && acc[item] ? acc[item] : null, obj);
12
- if (val != null) {
13
- return val;
14
- }
18
+ if (transform) {
19
+ value = transform(value, userValue, themeMapping);
15
20
  }
16
- return path.split('.').reduce((acc, item) => {
17
- if (acc && acc[item] != null) {
18
- return acc[item];
19
- }
20
- return null;
21
- }, obj);
21
+ return value;
22
22
  }
23
- export function getStyleValue(themeMapping, transform, propValueFinal, userValue = propValueFinal) {
23
+
24
+ /**
25
+ * HACK: The `alternateProp` logic is there because our theme looks like this:
26
+ * {
27
+ * typography: {
28
+ * fontFamily: 'comic sans',
29
+ * fontFamilyCode: 'courrier new',
30
+ * }
31
+ * }
32
+ * And we support targetting:
33
+ * - `typography.fontFamily` with `sx={{ fontFamily: 'default' }}`
34
+ * - `typography.fontFamilyCode` with `sx={{ fontFamily: 'code' }}`
35
+ *
36
+ * TODO(v7): Refactor our theme to look like this and remove the horrendous logic:
37
+ * {
38
+ * typography: {
39
+ * fontFamily: {
40
+ * default: 'comic sans',
41
+ * code: 'courrier new',
42
+ * }
43
+ * }
44
+ * }
45
+ */
46
+ export function getStyleValue2(themeMapping, transform, userValue, alternateProp) {
24
47
  let value;
25
48
  if (typeof themeMapping === 'function') {
26
- value = themeMapping(propValueFinal);
49
+ value = themeMapping(userValue);
27
50
  } else if (Array.isArray(themeMapping)) {
28
- value = themeMapping[propValueFinal] || userValue;
51
+ value = themeMapping[userValue] || userValue;
52
+ } else if (typeof userValue === 'string') {
53
+ value = getPath(themeMapping, userValue, true, alternateProp) || userValue;
29
54
  } else {
30
- value = getPath(themeMapping, propValueFinal) || userValue;
55
+ value = userValue;
31
56
  }
32
57
  if (transform) {
33
58
  value = transform(value, userValue, themeMapping);
34
59
  }
35
60
  return value;
36
61
  }
37
- function style(options) {
62
+ export function getPath(obj, pathInput, checkVars = true, alternateProp = undefined) {
63
+ if (!obj || !pathInput) {
64
+ return null;
65
+ }
66
+ const path = pathInput.split('.');
67
+
68
+ // Check if CSS variables are used
69
+ if (obj.vars && checkVars) {
70
+ const val = getPathImpl(obj.vars, path, alternateProp);
71
+ if (val != null) {
72
+ return val;
73
+ }
74
+ }
75
+ return getPathImpl(obj, path, alternateProp);
76
+ }
77
+ function getPathImpl(object, path, alternateProp = undefined) {
78
+ let lastResult = undefined;
79
+ let result = object;
80
+ let index = 0;
81
+ while (index < path.length) {
82
+ if (result === null || result === undefined) {
83
+ return result;
84
+ }
85
+ lastResult = result;
86
+ result = result[path[index]];
87
+ index += 1;
88
+ }
89
+ if (alternateProp && result === undefined) {
90
+ const lastKey = path[path.length - 1];
91
+ const alternateKey = `${alternateProp}${lastKey === 'default' ? '' : capitalize(lastKey)}`;
92
+ return lastResult?.[alternateKey];
93
+ }
94
+ return result;
95
+ }
96
+ export default function style(options) {
38
97
  const {
39
98
  prop,
40
99
  cssProperty = options.prop,
@@ -42,7 +101,6 @@ function style(options) {
42
101
  transform
43
102
  } = options;
44
103
 
45
- // false positive
46
104
  // eslint-disable-next-line react/function-component-definition
47
105
  const fn = props => {
48
106
  if (props[prop] == null) {
@@ -51,16 +109,9 @@ function style(options) {
51
109
  const propValue = props[prop];
52
110
  const theme = props.theme;
53
111
  const themeMapping = getPath(theme, themeKey) || {};
54
- const styleFromPropValue = propValueFinal => {
55
- let value = getStyleValue(themeMapping, transform, propValueFinal);
56
- if (propValueFinal === value && typeof propValueFinal === 'string') {
57
- // Haven't found value
58
- value = getStyleValue(themeMapping, transform, `${prop}${propValueFinal === 'default' ? '' : capitalize(propValueFinal)}`, propValueFinal);
59
- }
60
- if (cssProperty === false) {
61
- return value;
62
- }
63
- return {
112
+ const styleFromPropValue = valueFinal => {
113
+ const value = getStyleValue2(themeMapping, transform, valueFinal, prop);
114
+ return cssProperty === false ? value : {
64
115
  [cssProperty]: value
65
116
  };
66
117
  };
@@ -71,5 +122,4 @@ function style(options) {
71
122
  } : {};
72
123
  fn.filterProps = [prop];
73
124
  return fn;
74
- }
75
- export default style;
125
+ }