@aglyn/shared-data-enums 1.0.0-beta.143
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.
- package/LICENSE +201 -0
- package/README.md +3 -0
- package/package.json +39 -0
- package/src/enums.d.ts +26 -0
- package/src/enums.js +27 -0
- package/src/enums.js.map +1 -0
- package/src/index.d.ts +17 -0
- package/src/index.js +18 -0
- package/src/index.js.map +1 -0
- package/src/lib/aglyn-applications.d.ts +39 -0
- package/src/lib/aglyn-applications.js +53 -0
- package/src/lib/aglyn-applications.js.map +1 -0
- package/src/lib/aglyn.d.ts +49 -0
- package/src/lib/aglyn.js +86 -0
- package/src/lib/aglyn.js.map +1 -0
- package/src/lib/breakpoint-span.d.ts +66 -0
- package/src/lib/breakpoint-span.js +117 -0
- package/src/lib/breakpoint-span.js.map +1 -0
- package/src/lib/data-table.d.ts +107 -0
- package/src/lib/data-table.js +225 -0
- package/src/lib/data-table.js.map +1 -0
- package/src/lib/firebase-auth.d.ts +73 -0
- package/src/lib/firebase-auth.js +178 -0
- package/src/lib/firebase-auth.js.map +1 -0
- package/src/lib/global.d.ts +32 -0
- package/src/lib/global.js +33 -0
- package/src/lib/global.js.map +1 -0
- package/src/lib/http.d.ts +145 -0
- package/src/lib/http.js +155 -0
- package/src/lib/http.js.map +1 -0
- package/src/lib/icons.d.ts +108 -0
- package/src/lib/icons.js +130 -0
- package/src/lib/icons.js.map +1 -0
- package/src/lib/palette-token-css-var.d.ts +111 -0
- package/src/lib/palette-token-css-var.js +221 -0
- package/src/lib/palette-token-css-var.js.map +1 -0
- package/src/lib/styles.d.ts +170 -0
- package/src/lib/styles.js +315 -0
- package/src/lib/styles.js.map +1 -0
- package/src/lib/sx-property-aliases.d.ts +129 -0
- package/src/lib/sx-property-aliases.js +231 -0
- package/src/lib/sx-property-aliases.js.map +1 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* One spelling per style property (AGL-2207).
|
|
19
|
+
*
|
|
20
|
+
* Node `sx` is an MUI `sx` record, and MUI honours TWO names for the same
|
|
21
|
+
* declaration: its system-prop aliases (`bgcolor`, `p`/`px`/`py`/…,
|
|
22
|
+
* `m`/`mx`/`my`/…) and the CSS longhands. The Styles panel only ever names
|
|
23
|
+
* the longhands — `buildStyleFieldGroups` declares `backgroundColor`, and
|
|
24
|
+
* `ElementStylesForm` reads `paddingTop`…`marginLeft` for the box model —
|
|
25
|
+
* so a stored alias RENDERS but reaches no field: the control shows empty,
|
|
26
|
+
* and clearing the field deletes a key that was never the one painting.
|
|
27
|
+
*
|
|
28
|
+
* The longhand is therefore canonical. Not because the renderer prefers it
|
|
29
|
+
* (it resolves both, so the renderer cannot arbitrate) but because the
|
|
30
|
+
* panel's field names are the only schema the product has.
|
|
31
|
+
*
|
|
32
|
+
* This module is the single table, plus the expansion every read/write
|
|
33
|
+
* seam applies. Nothing REMOVES the alias spelling from the corpus: live
|
|
34
|
+
* documents carry it, the Custom CSS builder is free-solo and its JSON tab
|
|
35
|
+
* takes any key at all, so an alias can arrive at any time. Expanding on
|
|
36
|
+
* read is what makes those documents editable; expanding the colliding
|
|
37
|
+
* keys on write is what makes clearing actually clear.
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* Alias → the CSS longhands it stands for.
|
|
41
|
+
*
|
|
42
|
+
* Ground truth is MUI's own tables, not this file's memory:
|
|
43
|
+
* `@mui/system/styleFunctionSx/defaultSxConfig` gives
|
|
44
|
+
* `bgcolor.cssProperty === 'backgroundColor'`, and `@mui/system/spacing`
|
|
45
|
+
* builds its `CSS_PROPERTIES` table by crossing the two property roots
|
|
46
|
+
* (`m` is margin, `p` is padding) with six direction suffixes — `t` Top,
|
|
47
|
+
* `r` Right, `b` Bottom, `l` Left, `x` Left and Right, `y` Top and Bottom
|
|
48
|
+
* — and then points `paddingX`/`paddingY`/`marginX`/`marginY` at
|
|
49
|
+
* `px`/`py`/`mx`/`my`. `sx-property-aliases.spec.ts` asserts
|
|
50
|
+
* this table against those modules so a MUI upgrade cannot open a spelling
|
|
51
|
+
* we do not know about.
|
|
52
|
+
*
|
|
53
|
+
* Deliberately NOT here:
|
|
54
|
+
*
|
|
55
|
+
* - `p` and `m` map to the CSS shorthands `padding`/`margin` in MUI, but
|
|
56
|
+
* the panel has no shorthand field — BoxStyler owns four per-side
|
|
57
|
+
* controls — so they expand to the four longhands. That is exact for the
|
|
58
|
+
* atomic values {@link isAtomicSxValue} admits and refused for the rest.
|
|
59
|
+
* - `padding`/`margin` themselves. They are real CSS properties whose
|
|
60
|
+
* value may be a multi-side shorthand, and no panel field owns them
|
|
61
|
+
* either; rewriting them is a value-parsing problem, not a naming one.
|
|
62
|
+
* - Logical properties (`paddingInline*`, `marginBlock*`, …). MUI lists
|
|
63
|
+
* them in its spacing set, but each maps to the SAME-named CSS property
|
|
64
|
+
* — they are not aliases, they are direction-agnostic properties whose
|
|
65
|
+
* whole point is that they differ from `left`/`right` under RTL.
|
|
66
|
+
*/
|
|
67
|
+
export declare const SX_PROPERTY_ALIASES: Readonly<Record<string, readonly string[]>>;
|
|
68
|
+
/** Every alias spelling, for guards and callers that only need the set. */
|
|
69
|
+
export declare const SX_ALIAS_PROPERTIES: readonly string[];
|
|
70
|
+
/** Whether `name` is a stray spelling of a canonical style property. */
|
|
71
|
+
export declare function isSxAliasProperty(name: string): boolean;
|
|
72
|
+
/** The canonical longhands `name` stands for; empty when it IS canonical. */
|
|
73
|
+
export declare function canonicalSxProperties(name: string): readonly string[];
|
|
74
|
+
/** Aliases that would write `property` — the keys an edit to it must clear. */
|
|
75
|
+
export declare function sxAliasesFor(property: string): string[];
|
|
76
|
+
/**
|
|
77
|
+
* Whether a value survives being copied onto EACH longhand an alias covers.
|
|
78
|
+
*
|
|
79
|
+
* A number does (`p: 2` → four `padding*: 2`, each through the same MUI
|
|
80
|
+
* spacing transform, so 16px on all four sides either way). A single-token
|
|
81
|
+
* string does (`px: '2rem'`). A multi-token string does NOT: a value like
|
|
82
|
+
* `'10px 20px'` is the CSS shorthand's own per-side syntax, and copying it
|
|
83
|
+
* onto `paddingTop` would silently turn 10px into a two-value declaration
|
|
84
|
+
* CSS drops. Those are left as they are: still rendering, still not editable,
|
|
85
|
+
* but not corrupted either. The panel has no control that could express
|
|
86
|
+
* them anyway.
|
|
87
|
+
*
|
|
88
|
+
* A responsive object (`{xs: 2, md: 4}`) is atomic when every slice is,
|
|
89
|
+
* because the expansion just carries the whole object onto each longhand
|
|
90
|
+
* and MUI resolves it per breakpoint exactly as before.
|
|
91
|
+
*/
|
|
92
|
+
export declare function isAtomicSxValue(value: unknown): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Whether an alias key in this record could be expanded — the guard's
|
|
95
|
+
* question, and the identity fast-path's.
|
|
96
|
+
*/
|
|
97
|
+
export declare function hasExpandableSxAlias(sx: unknown): boolean;
|
|
98
|
+
/** Options for {@link expandSxAliases}. */
|
|
99
|
+
export interface ExpandSxAliasesOptions {
|
|
100
|
+
/**
|
|
101
|
+
* Expand only aliases that stand for one of these properties. Used by
|
|
102
|
+
* the panel's write seam, which must not rewrite keys the author is not
|
|
103
|
+
* editing. Omitted = expand every expandable alias.
|
|
104
|
+
*/
|
|
105
|
+
only?: readonly string[];
|
|
106
|
+
/**
|
|
107
|
+
* Also expand nested records — the `@scheme dark` slice, breakpoint
|
|
108
|
+
* media keys, `&:hover` blocks. Off by default so a caller that only
|
|
109
|
+
* cares about the top level pays for nothing.
|
|
110
|
+
*/
|
|
111
|
+
deep?: boolean;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Rewrites alias keys to their canonical longhands, IN PLACE in the key
|
|
115
|
+
* order (AGL-2207).
|
|
116
|
+
*
|
|
117
|
+
* Order is the whole correctness argument. MUI's `styleFunctionSx` walks
|
|
118
|
+
* `sx` with `for…in` and later keys overwrite earlier ones, so
|
|
119
|
+
* `{p: 2, paddingTop: 8}` renders 8px on top and `{paddingTop: 8, p: 2}`
|
|
120
|
+
* renders 2 × the spacing unit. Expanding each alias where it stands —
|
|
121
|
+
* rather than appending the longhands — reproduces both, so the expansion
|
|
122
|
+
* is a pure renaming of what already renders and never a restyle.
|
|
123
|
+
*
|
|
124
|
+
* Returns the input BY IDENTITY when there is nothing to expand, which is
|
|
125
|
+
* every node in a corpus once the presets stop writing aliases, so this
|
|
126
|
+
* sitting on a render path costs one key scan and no allocation.
|
|
127
|
+
*/
|
|
128
|
+
export declare function expandSxAliases<T>(sx: T, options?: ExpandSxAliasesOptions): T;
|
|
129
|
+
export default expandSxAliases;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* One spelling per style property (AGL-2207).
|
|
18
|
+
*
|
|
19
|
+
* Node `sx` is an MUI `sx` record, and MUI honours TWO names for the same
|
|
20
|
+
* declaration: its system-prop aliases (`bgcolor`, `p`/`px`/`py`/…,
|
|
21
|
+
* `m`/`mx`/`my`/…) and the CSS longhands. The Styles panel only ever names
|
|
22
|
+
* the longhands — `buildStyleFieldGroups` declares `backgroundColor`, and
|
|
23
|
+
* `ElementStylesForm` reads `paddingTop`…`marginLeft` for the box model —
|
|
24
|
+
* so a stored alias RENDERS but reaches no field: the control shows empty,
|
|
25
|
+
* and clearing the field deletes a key that was never the one painting.
|
|
26
|
+
*
|
|
27
|
+
* The longhand is therefore canonical. Not because the renderer prefers it
|
|
28
|
+
* (it resolves both, so the renderer cannot arbitrate) but because the
|
|
29
|
+
* panel's field names are the only schema the product has.
|
|
30
|
+
*
|
|
31
|
+
* This module is the single table, plus the expansion every read/write
|
|
32
|
+
* seam applies. Nothing REMOVES the alias spelling from the corpus: live
|
|
33
|
+
* documents carry it, the Custom CSS builder is free-solo and its JSON tab
|
|
34
|
+
* takes any key at all, so an alias can arrive at any time. Expanding on
|
|
35
|
+
* read is what makes those documents editable; expanding the colliding
|
|
36
|
+
* keys on write is what makes clearing actually clear.
|
|
37
|
+
*/ /**
|
|
38
|
+
* Alias → the CSS longhands it stands for.
|
|
39
|
+
*
|
|
40
|
+
* Ground truth is MUI's own tables, not this file's memory:
|
|
41
|
+
* `@mui/system/styleFunctionSx/defaultSxConfig` gives
|
|
42
|
+
* `bgcolor.cssProperty === 'backgroundColor'`, and `@mui/system/spacing`
|
|
43
|
+
* builds its `CSS_PROPERTIES` table by crossing the two property roots
|
|
44
|
+
* (`m` is margin, `p` is padding) with six direction suffixes — `t` Top,
|
|
45
|
+
* `r` Right, `b` Bottom, `l` Left, `x` Left and Right, `y` Top and Bottom
|
|
46
|
+
* — and then points `paddingX`/`paddingY`/`marginX`/`marginY` at
|
|
47
|
+
* `px`/`py`/`mx`/`my`. `sx-property-aliases.spec.ts` asserts
|
|
48
|
+
* this table against those modules so a MUI upgrade cannot open a spelling
|
|
49
|
+
* we do not know about.
|
|
50
|
+
*
|
|
51
|
+
* Deliberately NOT here:
|
|
52
|
+
*
|
|
53
|
+
* - `p` and `m` map to the CSS shorthands `padding`/`margin` in MUI, but
|
|
54
|
+
* the panel has no shorthand field — BoxStyler owns four per-side
|
|
55
|
+
* controls — so they expand to the four longhands. That is exact for the
|
|
56
|
+
* atomic values {@link isAtomicSxValue} admits and refused for the rest.
|
|
57
|
+
* - `padding`/`margin` themselves. They are real CSS properties whose
|
|
58
|
+
* value may be a multi-side shorthand, and no panel field owns them
|
|
59
|
+
* either; rewriting them is a value-parsing problem, not a naming one.
|
|
60
|
+
* - Logical properties (`paddingInline*`, `marginBlock*`, …). MUI lists
|
|
61
|
+
* them in its spacing set, but each maps to the SAME-named CSS property
|
|
62
|
+
* — they are not aliases, they are direction-agnostic properties whose
|
|
63
|
+
* whole point is that they differ from `left`/`right` under RTL.
|
|
64
|
+
*/ export const SX_PROPERTY_ALIASES = Object.freeze({
|
|
65
|
+
bgcolor: [
|
|
66
|
+
'backgroundColor'
|
|
67
|
+
],
|
|
68
|
+
p: [
|
|
69
|
+
'paddingTop',
|
|
70
|
+
'paddingRight',
|
|
71
|
+
'paddingBottom',
|
|
72
|
+
'paddingLeft'
|
|
73
|
+
],
|
|
74
|
+
pt: [
|
|
75
|
+
'paddingTop'
|
|
76
|
+
],
|
|
77
|
+
pr: [
|
|
78
|
+
'paddingRight'
|
|
79
|
+
],
|
|
80
|
+
pb: [
|
|
81
|
+
'paddingBottom'
|
|
82
|
+
],
|
|
83
|
+
pl: [
|
|
84
|
+
'paddingLeft'
|
|
85
|
+
],
|
|
86
|
+
px: [
|
|
87
|
+
'paddingLeft',
|
|
88
|
+
'paddingRight'
|
|
89
|
+
],
|
|
90
|
+
py: [
|
|
91
|
+
'paddingTop',
|
|
92
|
+
'paddingBottom'
|
|
93
|
+
],
|
|
94
|
+
paddingX: [
|
|
95
|
+
'paddingLeft',
|
|
96
|
+
'paddingRight'
|
|
97
|
+
],
|
|
98
|
+
paddingY: [
|
|
99
|
+
'paddingTop',
|
|
100
|
+
'paddingBottom'
|
|
101
|
+
],
|
|
102
|
+
m: [
|
|
103
|
+
'marginTop',
|
|
104
|
+
'marginRight',
|
|
105
|
+
'marginBottom',
|
|
106
|
+
'marginLeft'
|
|
107
|
+
],
|
|
108
|
+
mt: [
|
|
109
|
+
'marginTop'
|
|
110
|
+
],
|
|
111
|
+
mr: [
|
|
112
|
+
'marginRight'
|
|
113
|
+
],
|
|
114
|
+
mb: [
|
|
115
|
+
'marginBottom'
|
|
116
|
+
],
|
|
117
|
+
ml: [
|
|
118
|
+
'marginLeft'
|
|
119
|
+
],
|
|
120
|
+
mx: [
|
|
121
|
+
'marginLeft',
|
|
122
|
+
'marginRight'
|
|
123
|
+
],
|
|
124
|
+
my: [
|
|
125
|
+
'marginTop',
|
|
126
|
+
'marginBottom'
|
|
127
|
+
],
|
|
128
|
+
marginX: [
|
|
129
|
+
'marginLeft',
|
|
130
|
+
'marginRight'
|
|
131
|
+
],
|
|
132
|
+
marginY: [
|
|
133
|
+
'marginTop',
|
|
134
|
+
'marginBottom'
|
|
135
|
+
]
|
|
136
|
+
});
|
|
137
|
+
/** Every alias spelling, for guards and callers that only need the set. */ export const SX_ALIAS_PROPERTIES = Object.freeze(Object.keys(SX_PROPERTY_ALIASES));
|
|
138
|
+
/** Whether `name` is a stray spelling of a canonical style property. */ export function isSxAliasProperty(name) {
|
|
139
|
+
return Object.prototype.hasOwnProperty.call(SX_PROPERTY_ALIASES, name);
|
|
140
|
+
}
|
|
141
|
+
/** The canonical longhands `name` stands for; empty when it IS canonical. */ export function canonicalSxProperties(name) {
|
|
142
|
+
var _SX_PROPERTY_ALIASES_name;
|
|
143
|
+
return (_SX_PROPERTY_ALIASES_name = SX_PROPERTY_ALIASES[name]) != null ? _SX_PROPERTY_ALIASES_name : [];
|
|
144
|
+
}
|
|
145
|
+
/** Aliases that would write `property` — the keys an edit to it must clear. */ export function sxAliasesFor(property) {
|
|
146
|
+
return SX_ALIAS_PROPERTIES.filter((alias)=>SX_PROPERTY_ALIASES[alias].includes(property));
|
|
147
|
+
}
|
|
148
|
+
const isPlainObject = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
149
|
+
/**
|
|
150
|
+
* Whether a value survives being copied onto EACH longhand an alias covers.
|
|
151
|
+
*
|
|
152
|
+
* A number does (`p: 2` → four `padding*: 2`, each through the same MUI
|
|
153
|
+
* spacing transform, so 16px on all four sides either way). A single-token
|
|
154
|
+
* string does (`px: '2rem'`). A multi-token string does NOT: a value like
|
|
155
|
+
* `'10px 20px'` is the CSS shorthand's own per-side syntax, and copying it
|
|
156
|
+
* onto `paddingTop` would silently turn 10px into a two-value declaration
|
|
157
|
+
* CSS drops. Those are left as they are: still rendering, still not editable,
|
|
158
|
+
* but not corrupted either. The panel has no control that could express
|
|
159
|
+
* them anyway.
|
|
160
|
+
*
|
|
161
|
+
* A responsive object (`{xs: 2, md: 4}`) is atomic when every slice is,
|
|
162
|
+
* because the expansion just carries the whole object onto each longhand
|
|
163
|
+
* and MUI resolves it per breakpoint exactly as before.
|
|
164
|
+
*/ export function isAtomicSxValue(value) {
|
|
165
|
+
if (typeof value === 'number') return true;
|
|
166
|
+
if (typeof value === 'string') {
|
|
167
|
+
const trimmed = value.trim();
|
|
168
|
+
return trimmed.length > 0 && !/[\s,]/.test(trimmed);
|
|
169
|
+
}
|
|
170
|
+
if (isPlainObject(value)) {
|
|
171
|
+
const entries = Object.values(value);
|
|
172
|
+
return entries.length > 0 && entries.every(isAtomicSxValue);
|
|
173
|
+
}
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Whether an alias key in this record could be expanded — the guard's
|
|
178
|
+
* question, and the identity fast-path's.
|
|
179
|
+
*/ export function hasExpandableSxAlias(sx) {
|
|
180
|
+
if (!isPlainObject(sx)) return false;
|
|
181
|
+
for (const [key, value] of Object.entries(sx)){
|
|
182
|
+
if (isSxAliasProperty(key)) {
|
|
183
|
+
if (SX_PROPERTY_ALIASES[key].length === 1 || isAtomicSxValue(value)) {
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Rewrites alias keys to their canonical longhands, IN PLACE in the key
|
|
192
|
+
* order (AGL-2207).
|
|
193
|
+
*
|
|
194
|
+
* Order is the whole correctness argument. MUI's `styleFunctionSx` walks
|
|
195
|
+
* `sx` with `for…in` and later keys overwrite earlier ones, so
|
|
196
|
+
* `{p: 2, paddingTop: 8}` renders 8px on top and `{paddingTop: 8, p: 2}`
|
|
197
|
+
* renders 2 × the spacing unit. Expanding each alias where it stands —
|
|
198
|
+
* rather than appending the longhands — reproduces both, so the expansion
|
|
199
|
+
* is a pure renaming of what already renders and never a restyle.
|
|
200
|
+
*
|
|
201
|
+
* Returns the input BY IDENTITY when there is nothing to expand, which is
|
|
202
|
+
* every node in a corpus once the presets stop writing aliases, so this
|
|
203
|
+
* sitting on a render path costs one key scan and no allocation.
|
|
204
|
+
*/ export function expandSxAliases(sx, options) {
|
|
205
|
+
var _ref;
|
|
206
|
+
if (!isPlainObject(sx)) return sx;
|
|
207
|
+
const only = options == null ? void 0 : options.only;
|
|
208
|
+
const deep = (_ref = options == null ? void 0 : options.deep) != null ? _ref : false;
|
|
209
|
+
let changed = false;
|
|
210
|
+
const out = {};
|
|
211
|
+
for (const [key, value] of Object.entries(sx)){
|
|
212
|
+
const canonical = SX_PROPERTY_ALIASES[key];
|
|
213
|
+
const wanted = canonical && (!only || canonical.some((name)=>only.includes(name))) && (canonical.length === 1 || isAtomicSxValue(value));
|
|
214
|
+
if (wanted) {
|
|
215
|
+
changed = true;
|
|
216
|
+
for (const name of canonical)out[name] = value;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (deep && isPlainObject(value)) {
|
|
220
|
+
const nested = expandSxAliases(value, options);
|
|
221
|
+
if (nested !== value) changed = true;
|
|
222
|
+
out[key] = nested;
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
out[key] = value;
|
|
226
|
+
}
|
|
227
|
+
return changed ? out : sx;
|
|
228
|
+
}
|
|
229
|
+
export default expandSxAliases;
|
|
230
|
+
|
|
231
|
+
//# sourceMappingURL=sx-property-aliases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/shared/data/enums/src/lib/sx-property-aliases.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * One spelling per style property (AGL-2207).\n *\n * Node `sx` is an MUI `sx` record, and MUI honours TWO names for the same\n * declaration: its system-prop aliases (`bgcolor`, `p`/`px`/`py`/…,\n * `m`/`mx`/`my`/…) and the CSS longhands. The Styles panel only ever names\n * the longhands — `buildStyleFieldGroups` declares `backgroundColor`, and\n * `ElementStylesForm` reads `paddingTop`…`marginLeft` for the box model —\n * so a stored alias RENDERS but reaches no field: the control shows empty,\n * and clearing the field deletes a key that was never the one painting.\n *\n * The longhand is therefore canonical. Not because the renderer prefers it\n * (it resolves both, so the renderer cannot arbitrate) but because the\n * panel's field names are the only schema the product has.\n *\n * This module is the single table, plus the expansion every read/write\n * seam applies. Nothing REMOVES the alias spelling from the corpus: live\n * documents carry it, the Custom CSS builder is free-solo and its JSON tab\n * takes any key at all, so an alias can arrive at any time. Expanding on\n * read is what makes those documents editable; expanding the colliding\n * keys on write is what makes clearing actually clear.\n */\n\n/**\n * Alias → the CSS longhands it stands for.\n *\n * Ground truth is MUI's own tables, not this file's memory:\n * `@mui/system/styleFunctionSx/defaultSxConfig` gives\n * `bgcolor.cssProperty === 'backgroundColor'`, and `@mui/system/spacing`\n * builds its `CSS_PROPERTIES` table by crossing the two property roots\n * (`m` is margin, `p` is padding) with six direction suffixes — `t` Top,\n * `r` Right, `b` Bottom, `l` Left, `x` Left and Right, `y` Top and Bottom\n * — and then points `paddingX`/`paddingY`/`marginX`/`marginY` at\n * `px`/`py`/`mx`/`my`. `sx-property-aliases.spec.ts` asserts\n * this table against those modules so a MUI upgrade cannot open a spelling\n * we do not know about.\n *\n * Deliberately NOT here:\n *\n * - `p` and `m` map to the CSS shorthands `padding`/`margin` in MUI, but\n * the panel has no shorthand field — BoxStyler owns four per-side\n * controls — so they expand to the four longhands. That is exact for the\n * atomic values {@link isAtomicSxValue} admits and refused for the rest.\n * - `padding`/`margin` themselves. They are real CSS properties whose\n * value may be a multi-side shorthand, and no panel field owns them\n * either; rewriting them is a value-parsing problem, not a naming one.\n * - Logical properties (`paddingInline*`, `marginBlock*`, …). MUI lists\n * them in its spacing set, but each maps to the SAME-named CSS property\n * — they are not aliases, they are direction-agnostic properties whose\n * whole point is that they differ from `left`/`right` under RTL.\n */\nexport const SX_PROPERTY_ALIASES: Readonly<\n Record<string, readonly string[]>\n> = Object.freeze({\n bgcolor: ['backgroundColor'],\n\n p: ['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'],\n pt: ['paddingTop'],\n pr: ['paddingRight'],\n pb: ['paddingBottom'],\n pl: ['paddingLeft'],\n px: ['paddingLeft', 'paddingRight'],\n py: ['paddingTop', 'paddingBottom'],\n paddingX: ['paddingLeft', 'paddingRight'],\n paddingY: ['paddingTop', 'paddingBottom'],\n\n m: ['marginTop', 'marginRight', 'marginBottom', 'marginLeft'],\n mt: ['marginTop'],\n mr: ['marginRight'],\n mb: ['marginBottom'],\n ml: ['marginLeft'],\n mx: ['marginLeft', 'marginRight'],\n my: ['marginTop', 'marginBottom'],\n marginX: ['marginLeft', 'marginRight'],\n marginY: ['marginTop', 'marginBottom'],\n})\n\n/** Every alias spelling, for guards and callers that only need the set. */\nexport const SX_ALIAS_PROPERTIES: readonly string[] = Object.freeze(\n Object.keys(SX_PROPERTY_ALIASES),\n)\n\n/** Whether `name` is a stray spelling of a canonical style property. */\nexport function isSxAliasProperty(name: string): boolean {\n return Object.prototype.hasOwnProperty.call(SX_PROPERTY_ALIASES, name)\n}\n\n/** The canonical longhands `name` stands for; empty when it IS canonical. */\nexport function canonicalSxProperties(name: string): readonly string[] {\n return SX_PROPERTY_ALIASES[name] ?? []\n}\n\n/** Aliases that would write `property` — the keys an edit to it must clear. */\nexport function sxAliasesFor(property: string): string[] {\n return SX_ALIAS_PROPERTIES.filter((alias) =>\n SX_PROPERTY_ALIASES[alias].includes(property),\n )\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * Whether a value survives being copied onto EACH longhand an alias covers.\n *\n * A number does (`p: 2` → four `padding*: 2`, each through the same MUI\n * spacing transform, so 16px on all four sides either way). A single-token\n * string does (`px: '2rem'`). A multi-token string does NOT: a value like\n * `'10px 20px'` is the CSS shorthand's own per-side syntax, and copying it\n * onto `paddingTop` would silently turn 10px into a two-value declaration\n * CSS drops. Those are left as they are: still rendering, still not editable,\n * but not corrupted either. The panel has no control that could express\n * them anyway.\n *\n * A responsive object (`{xs: 2, md: 4}`) is atomic when every slice is,\n * because the expansion just carries the whole object onto each longhand\n * and MUI resolves it per breakpoint exactly as before.\n */\nexport function isAtomicSxValue(value: unknown): boolean {\n if (typeof value === 'number') return true\n if (typeof value === 'string') {\n const trimmed = value.trim()\n return trimmed.length > 0 && !/[\\s,]/.test(trimmed)\n }\n if (isPlainObject(value)) {\n const entries = Object.values(value)\n return entries.length > 0 && entries.every(isAtomicSxValue)\n }\n return false\n}\n\n/**\n * Whether an alias key in this record could be expanded — the guard's\n * question, and the identity fast-path's.\n */\nexport function hasExpandableSxAlias(sx: unknown): boolean {\n if (!isPlainObject(sx)) return false\n for (const [key, value] of Object.entries(sx)) {\n if (isSxAliasProperty(key)) {\n if (SX_PROPERTY_ALIASES[key].length === 1 || isAtomicSxValue(value)) {\n return true\n }\n }\n }\n return false\n}\n\n/** Options for {@link expandSxAliases}. */\nexport interface ExpandSxAliasesOptions {\n /**\n * Expand only aliases that stand for one of these properties. Used by\n * the panel's write seam, which must not rewrite keys the author is not\n * editing. Omitted = expand every expandable alias.\n */\n only?: readonly string[]\n /**\n * Also expand nested records — the `@scheme dark` slice, breakpoint\n * media keys, `&:hover` blocks. Off by default so a caller that only\n * cares about the top level pays for nothing.\n */\n deep?: boolean\n}\n\n/**\n * Rewrites alias keys to their canonical longhands, IN PLACE in the key\n * order (AGL-2207).\n *\n * Order is the whole correctness argument. MUI's `styleFunctionSx` walks\n * `sx` with `for…in` and later keys overwrite earlier ones, so\n * `{p: 2, paddingTop: 8}` renders 8px on top and `{paddingTop: 8, p: 2}`\n * renders 2 × the spacing unit. Expanding each alias where it stands —\n * rather than appending the longhands — reproduces both, so the expansion\n * is a pure renaming of what already renders and never a restyle.\n *\n * Returns the input BY IDENTITY when there is nothing to expand, which is\n * every node in a corpus once the presets stop writing aliases, so this\n * sitting on a render path costs one key scan and no allocation.\n */\nexport function expandSxAliases<T>(sx: T, options?: ExpandSxAliasesOptions): T {\n if (!isPlainObject(sx)) return sx\n const only = options?.only\n const deep = options?.deep ?? false\n\n let changed = false\n const out: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(sx)) {\n const canonical = SX_PROPERTY_ALIASES[key]\n const wanted =\n canonical &&\n (!only || canonical.some((name) => only.includes(name))) &&\n (canonical.length === 1 || isAtomicSxValue(value))\n if (wanted) {\n changed = true\n for (const name of canonical) out[name] = value\n continue\n }\n if (deep && isPlainObject(value)) {\n const nested = expandSxAliases(value, options)\n if (nested !== value) changed = true\n out[key] = nested\n continue\n }\n out[key] = value\n }\n return (changed ? out : sx) as T\n}\n\nexport default expandSxAliases\n"],"names":["SX_PROPERTY_ALIASES","Object","freeze","bgcolor","p","pt","pr","pb","pl","px","py","paddingX","paddingY","m","mt","mr","mb","ml","mx","my","marginX","marginY","SX_ALIAS_PROPERTIES","keys","isSxAliasProperty","name","prototype","hasOwnProperty","call","canonicalSxProperties","sxAliasesFor","property","filter","alias","includes","isPlainObject","value","Array","isArray","isAtomicSxValue","trimmed","trim","length","test","entries","values","every","hasExpandableSxAlias","sx","key","expandSxAliases","options","only","deep","changed","out","canonical","wanted","some","nested"],"mappings":"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"}
|