@react-spectrum/s2 3.0.0-nightly-63d4359d6-250428 → 3.0.0-nightly-1dd65ffc5-250429
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/dist/Accordion.cjs +4 -5
- package/dist/Accordion.cjs.map +1 -1
- package/dist/Accordion.css +2 -4
- package/dist/Accordion.css.map +1 -1
- package/dist/Accordion.mjs +4 -5
- package/dist/Accordion.mjs.map +1 -1
- package/dist/ActionBar.cjs +72 -63
- package/dist/ActionBar.cjs.map +1 -1
- package/dist/ActionBar.css +70 -63
- package/dist/ActionBar.css.map +1 -1
- package/dist/ActionBar.mjs +72 -63
- package/dist/ActionBar.mjs.map +1 -1
- package/dist/ActionButton.cjs +161 -160
- package/dist/ActionButton.cjs.map +1 -1
- package/dist/ActionButton.css +174 -168
- package/dist/ActionButton.css.map +1 -1
- package/dist/ActionButton.mjs +161 -160
- package/dist/ActionButton.mjs.map +1 -1
- package/dist/ActionButtonGroup.cjs +17 -18
- package/dist/ActionButtonGroup.cjs.map +1 -1
- package/dist/ActionButtonGroup.css +9 -11
- package/dist/ActionButtonGroup.css.map +1 -1
- package/dist/ActionButtonGroup.mjs +17 -18
- package/dist/ActionButtonGroup.mjs.map +1 -1
- package/dist/AlertDialog.cjs +4 -4
- package/dist/AlertDialog.css +3 -5
- package/dist/AlertDialog.css.map +1 -1
- package/dist/AlertDialog.mjs +4 -4
- package/dist/Avatar.cjs +21 -21
- package/dist/Avatar.css +14 -16
- package/dist/Avatar.css.map +1 -1
- package/dist/Avatar.mjs +21 -21
- package/dist/AvatarGroup.cjs +131 -110
- package/dist/AvatarGroup.cjs.map +1 -1
- package/dist/AvatarGroup.css +43 -49
- package/dist/AvatarGroup.css.map +1 -1
- package/dist/AvatarGroup.mjs +131 -110
- package/dist/AvatarGroup.mjs.map +1 -1
- package/dist/Badge.cjs +150 -149
- package/dist/Badge.cjs.map +1 -1
- package/dist/Badge.css +140 -134
- package/dist/Badge.css.map +1 -1
- package/dist/Badge.mjs +150 -149
- package/dist/Badge.mjs.map +1 -1
- package/dist/Breadcrumbs.cjs +169 -154
- package/dist/Breadcrumbs.cjs.map +1 -1
- package/dist/Breadcrumbs.css +119 -105
- package/dist/Breadcrumbs.css.map +1 -1
- package/dist/Breadcrumbs.mjs +169 -154
- package/dist/Breadcrumbs.mjs.map +1 -1
- package/dist/Button.cjs +321 -275
- package/dist/Button.cjs.map +1 -1
- package/dist/Button.css +245 -215
- package/dist/Button.css.map +1 -1
- package/dist/Button.mjs +321 -275
- package/dist/Button.mjs.map +1 -1
- package/dist/ButtonGroup.cjs +27 -25
- package/dist/ButtonGroup.cjs.map +1 -1
- package/dist/ButtonGroup.css +15 -17
- package/dist/ButtonGroup.css.map +1 -1
- package/dist/ButtonGroup.mjs +27 -25
- package/dist/ButtonGroup.mjs.map +1 -1
- package/dist/Card.cjs +316 -299
- package/dist/Card.cjs.map +1 -1
- package/dist/Card.css +242 -215
- package/dist/Card.css.map +1 -1
- package/dist/Card.mjs +316 -299
- package/dist/Card.mjs.map +1 -1
- package/dist/CardView.cjs +29 -30
- package/dist/CardView.cjs.map +1 -1
- package/dist/CardView.css +19 -19
- package/dist/CardView.mjs +29 -30
- package/dist/CardView.mjs.map +1 -1
- package/dist/CenterBaseline.cjs +2 -2
- package/dist/CenterBaseline.css +3 -5
- package/dist/CenterBaseline.css.map +1 -1
- package/dist/CenterBaseline.mjs +2 -2
- package/dist/Checkbox.cjs +114 -112
- package/dist/Checkbox.cjs.map +1 -1
- package/dist/Checkbox.css +99 -93
- package/dist/Checkbox.css.map +1 -1
- package/dist/Checkbox.mjs +114 -112
- package/dist/Checkbox.mjs.map +1 -1
- package/dist/CheckboxGroup.cjs +54 -54
- package/dist/CheckboxGroup.css +42 -42
- package/dist/CheckboxGroup.mjs +54 -54
- package/dist/ClearButton.cjs +19 -19
- package/dist/ClearButton.css +19 -21
- package/dist/ClearButton.css.map +1 -1
- package/dist/ClearButton.mjs +19 -19
- package/dist/CloseButton.cjs +64 -62
- package/dist/CloseButton.cjs.map +1 -1
- package/dist/CloseButton.css +48 -48
- package/dist/CloseButton.mjs +64 -62
- package/dist/CloseButton.mjs.map +1 -1
- package/dist/ColorArea.cjs +28 -28
- package/dist/ColorArea.css +17 -17
- package/dist/ColorArea.mjs +28 -28
- package/dist/ColorField.cjs +41 -41
- package/dist/ColorField.css +33 -33
- package/dist/ColorField.mjs +41 -41
- package/dist/ColorHandle.cjs +29 -29
- package/dist/ColorHandle.css +45 -45
- package/dist/ColorHandle.mjs +29 -29
- package/dist/ColorSlider.cjs +68 -64
- package/dist/ColorSlider.cjs.map +1 -1
- package/dist/ColorSlider.css +64 -58
- package/dist/ColorSlider.css.map +1 -1
- package/dist/ColorSlider.mjs +68 -64
- package/dist/ColorSlider.mjs.map +1 -1
- package/dist/ColorSwatch.cjs +44 -38
- package/dist/ColorSwatch.cjs.map +1 -1
- package/dist/ColorSwatch.css +29 -31
- package/dist/ColorSwatch.css.map +1 -1
- package/dist/ColorSwatch.mjs +44 -38
- package/dist/ColorSwatch.mjs.map +1 -1
- package/dist/ColorSwatchPicker.cjs +31 -32
- package/dist/ColorSwatchPicker.cjs.map +1 -1
- package/dist/ColorSwatchPicker.css +48 -48
- package/dist/ColorSwatchPicker.css.map +1 -1
- package/dist/ColorSwatchPicker.mjs +31 -32
- package/dist/ColorSwatchPicker.mjs.map +1 -1
- package/dist/ColorWheel.cjs +28 -28
- package/dist/ColorWheel.css +18 -18
- package/dist/ColorWheel.mjs +28 -28
- package/dist/ComboBox.cjs +108 -108
- package/dist/ComboBox.css +101 -101
- package/dist/ComboBox.mjs +108 -108
- package/dist/ContextualHelp.cjs +5 -5
- package/dist/ContextualHelp.css +58 -44
- package/dist/ContextualHelp.css.map +1 -1
- package/dist/ContextualHelp.mjs +5 -5
- package/dist/CustomDialog.cjs +38 -38
- package/dist/CustomDialog.css +26 -26
- package/dist/CustomDialog.mjs +38 -38
- package/dist/Dialog.cjs +18 -18
- package/dist/Dialog.css +86 -72
- package/dist/Dialog.css.map +1 -1
- package/dist/Dialog.mjs +18 -18
- package/dist/Disclosure.cjs +139 -133
- package/dist/Disclosure.cjs.map +1 -1
- package/dist/Disclosure.css +144 -120
- package/dist/Disclosure.css.map +1 -1
- package/dist/Disclosure.mjs +139 -133
- package/dist/Disclosure.mjs.map +1 -1
- package/dist/Divider.cjs +47 -47
- package/dist/Divider.css +26 -26
- package/dist/Divider.mjs +47 -47
- package/dist/DropZone.cjs +68 -64
- package/dist/DropZone.cjs.map +1 -1
- package/dist/DropZone.css +66 -60
- package/dist/DropZone.css.map +1 -1
- package/dist/DropZone.mjs +68 -64
- package/dist/DropZone.mjs.map +1 -1
- package/dist/Field.cjs +192 -186
- package/dist/Field.cjs.map +1 -1
- package/dist/Field.css +167 -159
- package/dist/Field.css.map +1 -1
- package/dist/Field.mjs +192 -186
- package/dist/Field.mjs.map +1 -1
- package/dist/Form.cjs +11 -12
- package/dist/Form.cjs.map +1 -1
- package/dist/Form.css +9 -11
- package/dist/Form.css.map +1 -1
- package/dist/Form.mjs +11 -12
- package/dist/Form.mjs.map +1 -1
- package/dist/FullscreenDialog.cjs +5 -5
- package/dist/FullscreenDialog.css +94 -80
- package/dist/FullscreenDialog.css.map +1 -1
- package/dist/FullscreenDialog.mjs +5 -5
- package/dist/IllustratedMessage.cjs +185 -160
- package/dist/IllustratedMessage.cjs.map +1 -1
- package/dist/IllustratedMessage.css +93 -91
- package/dist/IllustratedMessage.css.map +1 -1
- package/dist/IllustratedMessage.mjs +185 -160
- package/dist/IllustratedMessage.mjs.map +1 -1
- package/dist/Image.cjs +14 -14
- package/dist/Image.css +14 -16
- package/dist/Image.css.map +1 -1
- package/dist/Image.mjs +14 -14
- package/dist/InlineAlert.cjs +130 -122
- package/dist/InlineAlert.cjs.map +1 -1
- package/dist/InlineAlert.css +109 -95
- package/dist/InlineAlert.css.map +1 -1
- package/dist/InlineAlert.mjs +130 -122
- package/dist/InlineAlert.mjs.map +1 -1
- package/dist/Link.cjs +57 -47
- package/dist/Link.cjs.map +1 -1
- package/dist/Link.css +52 -44
- package/dist/Link.css.map +1 -1
- package/dist/Link.mjs +57 -47
- package/dist/Link.mjs.map +1 -1
- package/dist/Menu.cjs +353 -325
- package/dist/Menu.cjs.map +1 -1
- package/dist/Menu.css +189 -189
- package/dist/Menu.css.map +1 -1
- package/dist/Menu.mjs +353 -325
- package/dist/Menu.mjs.map +1 -1
- package/dist/Meter.cjs +116 -114
- package/dist/Meter.cjs.map +1 -1
- package/dist/Meter.css +106 -104
- package/dist/Meter.css.map +1 -1
- package/dist/Meter.mjs +116 -114
- package/dist/Meter.mjs.map +1 -1
- package/dist/Modal.cjs +62 -59
- package/dist/Modal.cjs.map +1 -1
- package/dist/Modal.css +52 -51
- package/dist/Modal.css.map +1 -1
- package/dist/Modal.mjs +62 -59
- package/dist/Modal.mjs.map +1 -1
- package/dist/NotificationBadge.cjs +66 -62
- package/dist/NotificationBadge.cjs.map +1 -1
- package/dist/NotificationBadge.css +78 -72
- package/dist/NotificationBadge.css.map +1 -1
- package/dist/NotificationBadge.mjs +66 -62
- package/dist/NotificationBadge.mjs.map +1 -1
- package/dist/NumberField.cjs +133 -133
- package/dist/NumberField.css +120 -120
- package/dist/NumberField.mjs +133 -133
- package/dist/Picker.cjs +209 -207
- package/dist/Picker.cjs.map +1 -1
- package/dist/Picker.css +179 -173
- package/dist/Picker.css.map +1 -1
- package/dist/Picker.mjs +209 -207
- package/dist/Picker.mjs.map +1 -1
- package/dist/Popover.cjs +124 -93
- package/dist/Popover.cjs.map +1 -1
- package/dist/Popover.css +67 -83
- package/dist/Popover.css.map +1 -1
- package/dist/Popover.mjs +124 -93
- package/dist/Popover.mjs.map +1 -1
- package/dist/ProgressBar.cjs +132 -130
- package/dist/ProgressBar.cjs.map +1 -1
- package/dist/ProgressBar.css +119 -117
- package/dist/ProgressBar.css.map +1 -1
- package/dist/ProgressBar.mjs +132 -130
- package/dist/ProgressBar.mjs.map +1 -1
- package/dist/ProgressCircle.cjs +32 -32
- package/dist/ProgressCircle.css +20 -20
- package/dist/ProgressCircle.css.map +1 -1
- package/dist/ProgressCircle.mjs +32 -32
- package/dist/Provider.cjs +11 -11
- package/dist/Provider.css +9 -11
- package/dist/Provider.css.map +1 -1
- package/dist/Provider.mjs +11 -11
- package/dist/Radio.cjs +101 -99
- package/dist/Radio.cjs.map +1 -1
- package/dist/Radio.css +101 -95
- package/dist/Radio.css.map +1 -1
- package/dist/Radio.mjs +101 -99
- package/dist/Radio.mjs.map +1 -1
- package/dist/RadioGroup.cjs +52 -52
- package/dist/RadioGroup.css +42 -42
- package/dist/RadioGroup.mjs +52 -52
- package/dist/SearchField.cjs +52 -52
- package/dist/SearchField.css +54 -54
- package/dist/SearchField.mjs +52 -52
- package/dist/SegmentedControl.cjs +123 -119
- package/dist/SegmentedControl.cjs.map +1 -1
- package/dist/SegmentedControl.css +110 -104
- package/dist/SegmentedControl.css.map +1 -1
- package/dist/SegmentedControl.mjs +123 -119
- package/dist/SegmentedControl.mjs.map +1 -1
- package/dist/Slider.cjs +251 -248
- package/dist/Slider.cjs.map +1 -1
- package/dist/Slider.css +166 -157
- package/dist/Slider.css.map +1 -1
- package/dist/Slider.mjs +251 -248
- package/dist/Slider.mjs.map +1 -1
- package/dist/StatusLight.cjs +74 -70
- package/dist/StatusLight.cjs.map +1 -1
- package/dist/StatusLight.css +70 -64
- package/dist/StatusLight.css.map +1 -1
- package/dist/StatusLight.mjs +74 -70
- package/dist/StatusLight.mjs.map +1 -1
- package/dist/Switch.cjs +110 -108
- package/dist/Switch.cjs.map +1 -1
- package/dist/Switch.css +86 -80
- package/dist/Switch.css.map +1 -1
- package/dist/Switch.mjs +110 -108
- package/dist/Switch.mjs.map +1 -1
- package/dist/TableView.cjs +334 -329
- package/dist/TableView.cjs.map +1 -1
- package/dist/TableView.css +193 -193
- package/dist/TableView.css.map +1 -1
- package/dist/TableView.mjs +334 -329
- package/dist/TableView.mjs.map +1 -1
- package/dist/Tabs.cjs +153 -149
- package/dist/Tabs.cjs.map +1 -1
- package/dist/Tabs.css +102 -96
- package/dist/Tabs.css.map +1 -1
- package/dist/Tabs.mjs +153 -149
- package/dist/Tabs.mjs.map +1 -1
- package/dist/TabsPicker.cjs +131 -129
- package/dist/TabsPicker.cjs.map +1 -1
- package/dist/TabsPicker.css +132 -126
- package/dist/TabsPicker.css.map +1 -1
- package/dist/TabsPicker.mjs +131 -129
- package/dist/TabsPicker.mjs.map +1 -1
- package/dist/TagGroup.cjs +197 -193
- package/dist/TagGroup.cjs.map +1 -1
- package/dist/TagGroup.css +164 -158
- package/dist/TagGroup.css.map +1 -1
- package/dist/TagGroup.mjs +197 -193
- package/dist/TagGroup.mjs.map +1 -1
- package/dist/TextField.cjs +67 -65
- package/dist/TextField.cjs.map +1 -1
- package/dist/TextField.css +71 -65
- package/dist/TextField.css.map +1 -1
- package/dist/TextField.mjs +67 -65
- package/dist/TextField.mjs.map +1 -1
- package/dist/Toast.cjs +138 -136
- package/dist/Toast.cjs.map +1 -1
- package/dist/Toast.css +117 -111
- package/dist/Toast.css.map +1 -1
- package/dist/Toast.mjs +138 -136
- package/dist/Toast.mjs.map +1 -1
- package/dist/ToggleButton.cjs +3 -3
- package/dist/ToggleButton.css +12 -14
- package/dist/ToggleButton.css.map +1 -1
- package/dist/ToggleButton.mjs +3 -3
- package/dist/Tooltip.cjs +99 -72
- package/dist/Tooltip.cjs.map +1 -1
- package/dist/Tooltip.css +87 -87
- package/dist/Tooltip.css.map +1 -1
- package/dist/Tooltip.mjs +99 -72
- package/dist/Tooltip.mjs.map +1 -1
- package/dist/TreeView.cjs +169 -157
- package/dist/TreeView.cjs.map +1 -1
- package/dist/TreeView.css +155 -153
- package/dist/TreeView.css.map +1 -1
- package/dist/TreeView.mjs +169 -157
- package/dist/TreeView.mjs.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/icons/Skeleton.cjs +3 -3
- package/icons/Skeleton.cjs.map +1 -1
- package/icons/Skeleton.css +8 -10
- package/icons/Skeleton.css.map +1 -1
- package/icons/Skeleton.mjs +3 -3
- package/icons/Skeleton.mjs.map +1 -1
- package/package.json +22 -22
- package/src/Card.tsx +3 -3
- package/src/Disclosure.tsx +3 -3
- package/src/TableView.tsx +1 -4
- package/src/style-utils.ts +0 -2
- package/style/__tests__/style-macro.test.js +323 -27
- package/style/dist/properties.cjs +4 -0
- package/style/dist/properties.cjs.map +1 -0
- package/style/dist/properties.mjs +6 -0
- package/style/dist/properties.mjs.map +1 -0
- package/style/dist/spectrum-theme.cjs +123 -124
- package/style/dist/spectrum-theme.cjs.map +1 -1
- package/style/dist/spectrum-theme.mjs +124 -125
- package/style/dist/spectrum-theme.mjs.map +1 -1
- package/style/dist/style-macro.cjs +244 -263
- package/style/dist/style-macro.cjs.map +1 -1
- package/style/dist/style-macro.mjs +240 -259
- package/style/dist/style-macro.mjs.map +1 -1
- package/style/dist/types.d.ts +84 -80
- package/style/dist/types.d.ts.map +1 -1
- package/style/properties.json +2422 -0
- package/style/spectrum-theme.ts +101 -110
- package/style/style-macro.ts +319 -220
- package/style/types.ts +8 -4
package/style/style-macro.ts
CHANGED
|
@@ -10,84 +10,115 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import type {Condition, CSSProperties, CSSValue, CustomValue,
|
|
13
|
+
import type {Condition, CSSProperties, CSSValue, CustomValue, Property, PropertyValueDefinition, PropertyValueMap, RenderProps, ShorthandProperty, StyleFunction, StyleValue, Theme, ThemeProperties, Value} from './types';
|
|
14
|
+
import * as propertyInfo from './properties.json';
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
let selector = Array.isArray(value) ? generateArbitraryValueSelector(value.map(v => JSON.stringify(v)).join('')) : generateArbitraryValueSelector(JSON.stringify(value));
|
|
19
|
-
return {default: [fn(value, property), selector]};
|
|
20
|
-
};
|
|
21
|
-
}
|
|
16
|
+
export class ArbitraryProperty<T extends Value> implements Property<T> {
|
|
17
|
+
property: string;
|
|
18
|
+
toCSS: (value: T) => CSSValue;
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
constructor(property: string, toCSS?: (value: T) => CSSValue) {
|
|
21
|
+
this.property = property;
|
|
22
|
+
this.toCSS = toCSS || ((value) => String(value));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get cssProperties(): string[] {
|
|
26
|
+
return [this.property];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
toCSSValue(value: T): PropertyValueDefinition<Value> {
|
|
30
|
+
return this.toCSS(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
toCSSProperties(customProperty: string | null, value: PropertyValueDefinition<Value>): PropertyValueDefinition<[CSSProperties]> {
|
|
34
|
+
return mapConditionalValue(value, value => [{[customProperty || this.property]: String(value)}]);
|
|
35
|
+
}
|
|
25
36
|
}
|
|
26
37
|
|
|
27
|
-
export
|
|
28
|
-
|
|
29
|
-
return (value, property) => {
|
|
30
|
-
let v = parseArbitraryValue(value);
|
|
31
|
-
if (v) {
|
|
32
|
-
return {default: [fn(v[0], property), v[1]]};
|
|
33
|
-
}
|
|
38
|
+
export class MappedProperty<T extends CSSValue> extends ArbitraryProperty<T> implements Property<T> {
|
|
39
|
+
mapping: PropertyValueMap<T> | string[];
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
constructor(property: string, mapping: PropertyValueMap<T> | string[]) {
|
|
42
|
+
super(property);
|
|
43
|
+
this.mapping = mapping;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
toCSSValue(value: T): PropertyValueDefinition<Value> {
|
|
47
|
+
if (Array.isArray(this.mapping)) {
|
|
48
|
+
if (!this.mapping.includes(String(value))) {
|
|
49
|
+
throw new Error('Invalid style value: ' + value);
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
} else {
|
|
53
|
+
let res = this.mapping[String(value)];
|
|
54
|
+
if (res == null) {
|
|
55
|
+
throw new Error('Invalid style value: ' + value);
|
|
56
|
+
}
|
|
57
|
+
return res;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
40
60
|
}
|
|
41
61
|
|
|
42
|
-
export
|
|
43
|
-
|
|
62
|
+
export type Color<C extends string> = C | `${string}/${number}`;
|
|
63
|
+
export class ColorProperty<C extends string> extends MappedProperty<C> implements Property<Color<C>> {
|
|
64
|
+
toCSSValue(value: Color<C>): PropertyValueDefinition<Value> {
|
|
65
|
+
let [color, opacity] = value.split('/');
|
|
66
|
+
return mapConditionalValue(this.mapping[color], value => {
|
|
67
|
+
return opacity ? `rgb(from ${value} r g b / ${opacity}%)` : value;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
44
70
|
}
|
|
45
71
|
|
|
46
|
-
export
|
|
47
|
-
|
|
48
|
-
return (value, property) => {
|
|
49
|
-
let v = parseArbitraryValue(value);
|
|
50
|
-
if (v) {
|
|
51
|
-
return {default: [{[property]: v[0]}, v[1]]};
|
|
52
|
-
}
|
|
72
|
+
export class SizingProperty<T extends CSSValue> extends MappedProperty<T> implements Property<T | number> {
|
|
73
|
+
numberToCSS: (value: number) => string;
|
|
53
74
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
});
|
|
59
|
-
}
|
|
75
|
+
constructor(property: string, mapping: PropertyValueMap<T> | string[], numberToCSS: (value: number) => string) {
|
|
76
|
+
super(property, mapping);
|
|
77
|
+
this.numberToCSS = numberToCSS;
|
|
78
|
+
}
|
|
60
79
|
|
|
80
|
+
toCSSValue(value: T | number): PropertyValueDefinition<Value> {
|
|
61
81
|
if (typeof value === 'number') {
|
|
62
|
-
|
|
63
|
-
return {default: [{[property]: cssValue}, generateName(value + valueMap.size)]};
|
|
82
|
+
return value === 0 ? '0px' : this.numberToCSS(value);
|
|
64
83
|
}
|
|
65
84
|
|
|
66
|
-
|
|
67
|
-
}
|
|
85
|
+
return super.toCSSValue(value);
|
|
86
|
+
}
|
|
68
87
|
}
|
|
69
88
|
|
|
70
|
-
export
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
89
|
+
export class ExpandedProperty<T extends Value> implements Property<T> {
|
|
90
|
+
cssProperties: string[];
|
|
91
|
+
mapping: PropertyValueMap<CSSValue> | null;
|
|
92
|
+
expand: (v: T | CSSValue) => CSSProperties;
|
|
93
|
+
|
|
94
|
+
constructor(properties: string[], expand: (v: T | CSSValue) => CSSProperties, mapping?: PropertyValueMap<CSSValue>) {
|
|
95
|
+
this.cssProperties = properties;
|
|
96
|
+
this.expand = expand;
|
|
97
|
+
this.mapping = mapping || null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
toCSSValue(value: T): PropertyValueDefinition<Value> {
|
|
101
|
+
if (!this.mapping) {
|
|
102
|
+
return value;
|
|
77
103
|
}
|
|
78
104
|
|
|
79
|
-
let
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
105
|
+
let res = this.mapping[String(value)];
|
|
106
|
+
if (res == null) {
|
|
107
|
+
throw new Error('Invalid style value: ' + value);
|
|
108
|
+
}
|
|
109
|
+
return res;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
toCSSProperties(customProperty: string | null, value: PropertyValueDefinition<T>): PropertyValueDefinition<[CSSProperties]> {
|
|
113
|
+
if (customProperty) {
|
|
114
|
+
throw new Error('Style properties that expand into multiple CSS properties cannot be set as CSS variables.');
|
|
115
|
+
}
|
|
116
|
+
return mapConditionalValue(value, value => [this.expand(value)]);
|
|
117
|
+
}
|
|
87
118
|
}
|
|
88
119
|
|
|
89
120
|
function mapConditionalValue<T, U>(value: PropertyValueDefinition<T>, fn: (value: T) => U): PropertyValueDefinition<U> {
|
|
90
|
-
if (typeof value === 'object') {
|
|
121
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
91
122
|
let res: PropertyValueDefinition<U> = {};
|
|
92
123
|
for (let condition in value) {
|
|
93
124
|
res[condition] = mapConditionalValue((value as any)[condition], fn);
|
|
@@ -114,23 +145,29 @@ function mapConditionalShorthand<T, C extends string, R extends RenderProps<stri
|
|
|
114
145
|
}
|
|
115
146
|
}
|
|
116
147
|
|
|
117
|
-
function
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
148
|
+
export function parseArbitraryValue(value: Value): string | undefined {
|
|
149
|
+
if (typeof value === 'string' && value.startsWith('--')) {
|
|
150
|
+
return `var(${value})`;
|
|
151
|
+
} else if (typeof value === 'string' && value[0] === '[' && value[value.length - 1] === ']') {
|
|
152
|
+
return value.slice(1, -1);
|
|
123
153
|
}
|
|
124
|
-
return map;
|
|
125
154
|
}
|
|
126
155
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
156
|
+
function shortCSSPropertyName(property: string) {
|
|
157
|
+
return propertyInfo.properties[property] ?? generateArbitraryValueSelector(property, true);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function classNamePrefix(property: string, cssProperty: string) {
|
|
161
|
+
let className = propertyInfo.properties[cssProperty];
|
|
162
|
+
if (className && property === '--' + className) {
|
|
163
|
+
return '-' + className + '_-';
|
|
133
164
|
}
|
|
165
|
+
|
|
166
|
+
if (className && !property.startsWith('--')) {
|
|
167
|
+
return className;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return '-' + generateArbitraryValueSelector(property, true) + '-';
|
|
134
171
|
}
|
|
135
172
|
|
|
136
173
|
interface MacroContext {
|
|
@@ -138,13 +175,12 @@ interface MacroContext {
|
|
|
138
175
|
}
|
|
139
176
|
|
|
140
177
|
export function createTheme<T extends Theme>(theme: T): StyleFunction<ThemeProperties<T>, 'default' | Extract<keyof T['conditions'], string>> {
|
|
141
|
-
let
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (typeof v === 'function') {
|
|
145
|
-
return [k, v];
|
|
178
|
+
let properties = new Map<string, Property<any>>(Object.entries(theme.properties).map(([k, v]) => {
|
|
179
|
+
if (!Array.isArray(v) && v.cssProperties) {
|
|
180
|
+
return [k, v as Property<any>];
|
|
146
181
|
}
|
|
147
|
-
|
|
182
|
+
|
|
183
|
+
return [k, new MappedProperty(k, v as any)];
|
|
148
184
|
}));
|
|
149
185
|
|
|
150
186
|
let dependencies = new Set<string>();
|
|
@@ -160,13 +196,13 @@ export function createTheme<T extends Theme>(theme: T): StyleFunction<ThemePrope
|
|
|
160
196
|
}
|
|
161
197
|
|
|
162
198
|
// Generate rules for each property.
|
|
163
|
-
let rules = new Map<string, Rule
|
|
199
|
+
let rules = new Map<string, Rule>();
|
|
164
200
|
let values = new Map();
|
|
165
201
|
dependencies.clear();
|
|
166
|
-
let usedPriorities =
|
|
202
|
+
let usedPriorities = 0;
|
|
167
203
|
let setRules = (key: string, value: [number, Rule[]]) => {
|
|
168
204
|
usedPriorities = Math.max(usedPriorities, value[0]);
|
|
169
|
-
rules.set(key, value[1]);
|
|
205
|
+
rules.set(key, new GroupRule(value[1]));
|
|
170
206
|
};
|
|
171
207
|
|
|
172
208
|
hasConditions = false;
|
|
@@ -210,7 +246,8 @@ export function createTheme<T extends Theme>(theme: T): StyleFunction<ThemePrope
|
|
|
210
246
|
if (!(dep in theme.properties)) {
|
|
211
247
|
throw new Error(`Unknown dependency ${dep}`);
|
|
212
248
|
}
|
|
213
|
-
let
|
|
249
|
+
let prop = properties.get(dep)!;
|
|
250
|
+
let name = `--${shortCSSPropertyName(prop.cssProperties[0])}`;
|
|
214
251
|
// Could potentially use @property to prevent the var from inheriting in children.
|
|
215
252
|
setRules(name, compileValue(name, dep, value));
|
|
216
253
|
setRules(dep, compileValue(dep, dep, name));
|
|
@@ -218,10 +255,6 @@ export function createTheme<T extends Theme>(theme: T): StyleFunction<ThemePrope
|
|
|
218
255
|
}
|
|
219
256
|
dependencies.clear();
|
|
220
257
|
|
|
221
|
-
// Prevent all global styles from leaking into this element.
|
|
222
|
-
// The :not(#a#b) raises the specificity of the selector by 2 ids,
|
|
223
|
-
// which can never occur on a real element, and will win over other
|
|
224
|
-
// selectors such as class and element selectors.
|
|
225
258
|
let css = '';
|
|
226
259
|
|
|
227
260
|
// Declare layers for each priority ahead of time so the order is always correct.
|
|
@@ -241,28 +274,46 @@ export function createTheme<T extends Theme>(theme: T): StyleFunction<ThemePrope
|
|
|
241
274
|
// Also generate a variable for each overridable property that overlaps with the style definition. If those are defined,
|
|
242
275
|
// the defaults from the style definition are omitted.
|
|
243
276
|
let allowedOverridesSet = new Set<string>();
|
|
244
|
-
let js = 'let rules = "
|
|
277
|
+
let js = 'let rules = " ";\n';
|
|
245
278
|
if (allowedOverrides?.length) {
|
|
246
279
|
for (let property of allowedOverrides) {
|
|
247
|
-
|
|
248
|
-
|
|
280
|
+
let shorthand = theme.shorthands[property];
|
|
281
|
+
let props = Array.isArray(shorthand) ? shorthand : [property];
|
|
282
|
+
for (let property of props) {
|
|
283
|
+
let prop = properties.get(property);
|
|
284
|
+
if (!prop) {
|
|
285
|
+
throw new Error(`Invalid property ${property} in allowedOverrides`);
|
|
286
|
+
}
|
|
287
|
+
for (let property of prop.cssProperties) {
|
|
288
|
+
allowedOverridesSet.add(property);
|
|
289
|
+
}
|
|
249
290
|
}
|
|
250
291
|
}
|
|
251
292
|
|
|
252
|
-
js += `let matches = (overrides || '').match(/(?:^|\\s)(?:${[...allowedOverridesSet].join('|')})[^\\s]+/g) || [];\n`;
|
|
253
|
-
js += 'rules += matches.join(\'\');\n';
|
|
254
293
|
let loop = '';
|
|
255
294
|
for (let property of rules.keys()) {
|
|
256
|
-
let
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
|
|
295
|
+
let prop = properties.get(property);
|
|
296
|
+
if (prop) {
|
|
297
|
+
for (let property of prop.cssProperties) {
|
|
298
|
+
if (property && allowedOverridesSet.has(property)) {
|
|
299
|
+
let selector = classNamePrefix(property, property);
|
|
300
|
+
let p = property.replace('--', '__');
|
|
301
|
+
js += `let ${p} = false;\n`;
|
|
302
|
+
loop += ` if (p[1] === ${JSON.stringify(selector)}) ${p} = true;\n`;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
260
305
|
}
|
|
261
306
|
}
|
|
307
|
+
|
|
308
|
+
let regex = `/(?:^|\\s)(${[...allowedOverridesSet].map(p => classNamePrefix(p, p)).join('|')})[^\\s]+/g`;
|
|
262
309
|
if (loop) {
|
|
310
|
+
js += `let matches = (overrides || '').matchAll(${regex});\n`;
|
|
263
311
|
js += 'for (let p of matches) {\n';
|
|
264
312
|
js += loop;
|
|
313
|
+
js += ' rules += p[0];\n';
|
|
265
314
|
js += '}\n';
|
|
315
|
+
} else {
|
|
316
|
+
js += `rules += ((overrides || '').match(${regex}) || []).join('')\n`;
|
|
266
317
|
}
|
|
267
318
|
}
|
|
268
319
|
|
|
@@ -270,25 +321,13 @@ export function createTheme<T extends Theme>(theme: T): StyleFunction<ThemePrope
|
|
|
270
321
|
let isStatic = !(hasConditions || allowedOverrides);
|
|
271
322
|
let className = '';
|
|
272
323
|
let rulesByLayer = new Map<string, string[]>();
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
let allowsOverrides = themeProperty && allowedOverridesSet.has(themeProperty);
|
|
279
|
-
if (allowsOverrides) {
|
|
280
|
-
// Omit the value if an override was passed in.
|
|
281
|
-
js += `if (!$${themeProperty}) {\n`;
|
|
282
|
-
}
|
|
283
|
-
js += printJS(propertyRules) + '\n';
|
|
284
|
-
if (allowsOverrides) {
|
|
285
|
-
js += '}\n';
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
for (let rule of propertyRules) {
|
|
289
|
-
printRule(rule, rulesByLayer);
|
|
290
|
-
}
|
|
324
|
+
let rootRule = new GroupRule([...rules.values()]);
|
|
325
|
+
if (isStatic) {
|
|
326
|
+
className += rootRule.getStaticClassName();
|
|
327
|
+
} else {
|
|
328
|
+
js += rootRule.toJS(allowedOverridesSet) + '\n';
|
|
291
329
|
}
|
|
330
|
+
rootRule.toCSS(rulesByLayer);
|
|
292
331
|
|
|
293
332
|
for (let [layer, rules] of rulesByLayer) {
|
|
294
333
|
css += `@layer ${layerName(layer)} {\n`;
|
|
@@ -352,7 +391,7 @@ export function createTheme<T extends Theme>(theme: T): StyleFunction<ThemePrope
|
|
|
352
391
|
// The @layer order in the generated CSS will ensure that it overrides classes applied by runtime conditions.
|
|
353
392
|
let isCSSCondition = condition in theme.conditions || /^[@:]/.test(condition);
|
|
354
393
|
if (!wasCSSCondition && isCSSCondition && rules.length) {
|
|
355
|
-
rules = [
|
|
394
|
+
rules = [new GroupRule(rules)];
|
|
356
395
|
}
|
|
357
396
|
wasCSSCondition = isCSSCondition;
|
|
358
397
|
|
|
@@ -390,56 +429,42 @@ export function createTheme<T extends Theme>(theme: T): StyleFunction<ThemePrope
|
|
|
390
429
|
|
|
391
430
|
function compileCondition(conditions: Set<string>, condition: string, priority: number, rules: Rule[]): Rule[] {
|
|
392
431
|
if (condition === 'default' || conditions.has(condition)) {
|
|
393
|
-
return [
|
|
432
|
+
return [new GroupRule(rules)];
|
|
394
433
|
}
|
|
395
434
|
|
|
396
435
|
if (condition in theme.conditions || /^[@:]/.test(condition)) {
|
|
397
436
|
// Conditions starting with : are CSS pseudo classes. Nest them inside the parent rule.
|
|
398
437
|
let prelude = theme.conditions[condition] || condition;
|
|
399
438
|
if (prelude.startsWith(':')) {
|
|
400
|
-
|
|
401
|
-
prelude
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}];
|
|
439
|
+
for (let rule of rules) {
|
|
440
|
+
rule.addPseudo(prelude);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return [new GroupRule(rules, generateName(priority, true))];
|
|
406
444
|
}
|
|
407
445
|
|
|
408
446
|
// Otherwise, wrap the rule in the condition (e.g. @media).
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
prelude,
|
|
414
|
-
body: rules,
|
|
415
|
-
condition: ''
|
|
416
|
-
}];
|
|
447
|
+
// Top level layer is based on the priority of the rule, not the condition.
|
|
448
|
+
// Also group in a sub-layer based on the condition so that lightningcss can more effectively deduplicate rules.
|
|
449
|
+
let layer = `${generateName(priority, true)}.${propertyInfo.conditions[theme.conditions[condition] || condition] || generateArbitraryValueSelector(condition, true)}`;
|
|
450
|
+
return [new AtRule(rules, prelude, layer)];
|
|
417
451
|
}
|
|
418
452
|
|
|
419
453
|
hasConditions = true;
|
|
420
|
-
return [
|
|
454
|
+
return [new ConditionalRule(rules, condition)];
|
|
421
455
|
}
|
|
422
456
|
|
|
423
457
|
function compileRule(property: string, themeProperty: string, value: Value, priority: number, conditions: Set<string>, skipConditions: Set<string>): [number, Rule[]] {
|
|
424
|
-
|
|
425
|
-
// 1. Property. For custom properties we use a hash. For theme properties, we use the index within the theme.
|
|
426
|
-
// 2. Conditions. This uses the index within the theme.
|
|
427
|
-
// 3. Value. The index in the theme, or a hash for arbitrary values.
|
|
428
|
-
let prelude = '.';
|
|
429
|
-
if (property.startsWith('--')) {
|
|
430
|
-
// Include both custom property name and theme property in case the same var is reused between multiple theme properties.
|
|
431
|
-
prelude += generateArbitraryValueSelector(property, true) + '_' + themePropertyMap.get(themeProperty) + '-';
|
|
432
|
-
} else {
|
|
433
|
-
prelude += themePropertyMap.get(themeProperty);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
let propertyFunction = propertyFunctions.get(themeProperty);
|
|
458
|
+
let propertyFunction = properties.get(themeProperty);
|
|
437
459
|
if (propertyFunction) {
|
|
438
460
|
// Expand value to conditional CSS values, and then to rules.
|
|
439
|
-
let
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
461
|
+
let arbitrary = parseArbitraryValue(value);
|
|
462
|
+
let cssValue = arbitrary ? arbitrary : propertyFunction.toCSSValue(value);
|
|
463
|
+
let cssProperties = propertyFunction.toCSSProperties(property.startsWith('--') ? property : null, cssValue);
|
|
464
|
+
|
|
465
|
+
return conditionalToRules(cssProperties, priority, conditions, skipConditions, (value, priority, conditions) => {
|
|
466
|
+
let [obj] = value;
|
|
467
|
+
let rules: Rule[] = [];
|
|
443
468
|
for (let key in obj) {
|
|
444
469
|
let k = key as any;
|
|
445
470
|
let value = obj[k];
|
|
@@ -449,26 +474,39 @@ export function createTheme<T extends Theme>(theme: T): StyleFunction<ThemePrope
|
|
|
449
474
|
if (typeof value === 'string') {
|
|
450
475
|
// Replace self() references with variables and track the dependencies.
|
|
451
476
|
value = value.replace(/self\(([a-zA-Z]+)/g, (_, v) => {
|
|
477
|
+
let prop = properties.get(v);
|
|
478
|
+
if (!prop) {
|
|
479
|
+
throw new Error(`self(${v}) is invalid. ${v} is not a known property.`);
|
|
480
|
+
}
|
|
481
|
+
let cssProperties = prop.cssProperties;
|
|
482
|
+
if (cssProperties.length !== 1) {
|
|
483
|
+
throw new Error(`self(${v}) is not supported. ${v} expands to multiple CSS properties.`);
|
|
484
|
+
}
|
|
452
485
|
dependencies.add(v);
|
|
453
|
-
return `var(--${
|
|
486
|
+
return `var(--${shortCSSPropertyName(cssProperties[0])}`;
|
|
454
487
|
});
|
|
455
488
|
}
|
|
456
|
-
body += `${kebab(key)}: ${value};`;
|
|
457
|
-
}
|
|
458
489
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
490
|
+
// Generate selector. This consists of three parts: property, conditions, value.
|
|
491
|
+
let cssProperty = key;
|
|
492
|
+
if (property.startsWith('--')) {
|
|
493
|
+
cssProperty = propertyFunction.cssProperties[0];
|
|
463
494
|
}
|
|
464
|
-
}
|
|
465
495
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
496
|
+
let className = classNamePrefix(key, cssProperty);
|
|
497
|
+
if (conditions.size > 0) {
|
|
498
|
+
for (let condition of conditions) {
|
|
499
|
+
className += propertyInfo.conditions[theme.conditions[condition] || condition] || generateArbitraryValueSelector(condition);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (cssProperty !== key) {
|
|
504
|
+
className += shortCSSPropertyName(cssProperty);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
className += propertyInfo.values[cssProperty]?.[String(value)] ?? generateArbitraryValueSelector(String(value));
|
|
508
|
+
rules.push(new StyleRule(className, key, String(value)));
|
|
509
|
+
}
|
|
472
510
|
|
|
473
511
|
return [0, rules];
|
|
474
512
|
});
|
|
@@ -478,24 +516,6 @@ export function createTheme<T extends Theme>(theme: T): StyleFunction<ThemePrope
|
|
|
478
516
|
}
|
|
479
517
|
}
|
|
480
518
|
|
|
481
|
-
function nestRule(rule: Rule, prelude: string): Rule {
|
|
482
|
-
if (Array.isArray(rule.body)) {
|
|
483
|
-
return {
|
|
484
|
-
prelude: rule.prelude,
|
|
485
|
-
layer: rule.layer,
|
|
486
|
-
body: rule.body.map(r => nestRule(r, prelude)),
|
|
487
|
-
condition: rule.condition
|
|
488
|
-
};
|
|
489
|
-
} else {
|
|
490
|
-
return {
|
|
491
|
-
prelude: rule.prelude,
|
|
492
|
-
layer: rule.layer,
|
|
493
|
-
body: [{...rule, prelude: '&' + prelude}],
|
|
494
|
-
condition: ''
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
519
|
function kebab(property: string) {
|
|
500
520
|
if (property.startsWith('--')) {
|
|
501
521
|
return property;
|
|
@@ -503,13 +523,6 @@ function kebab(property: string) {
|
|
|
503
523
|
return property.replace(/([a-z])([A-Z])/g, (_, a, b) => `${a}-${b.toLowerCase()}`);
|
|
504
524
|
}
|
|
505
525
|
|
|
506
|
-
interface Rule {
|
|
507
|
-
prelude: string,
|
|
508
|
-
layer: string,
|
|
509
|
-
condition: string,
|
|
510
|
-
body: string | Rule[]
|
|
511
|
-
}
|
|
512
|
-
|
|
513
526
|
// Generate a class name from a number, e.g. index within the theme.
|
|
514
527
|
// This maps to an alphabet containing lower case letters, upper case letters, and numbers.
|
|
515
528
|
// For numbers larger than 62, an underscore is prepended.
|
|
@@ -535,11 +548,26 @@ function generateName(index: number, atStart = false): string {
|
|
|
535
548
|
|
|
536
549
|
// For arbitrary values, we use a hash of the string to generate the class name.
|
|
537
550
|
function generateArbitraryValueSelector(v: string, atStart = false) {
|
|
538
|
-
let c = hash(v)
|
|
551
|
+
let c = toBase62(hash(v));
|
|
539
552
|
if (atStart && /^[0-9]/.test(c)) {
|
|
540
553
|
c = `_${c}`;
|
|
541
554
|
}
|
|
542
|
-
return
|
|
555
|
+
return c;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
function toBase62(value: number) {
|
|
559
|
+
if (value === 0) {
|
|
560
|
+
return generateName(value);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
let res = '';
|
|
564
|
+
while (value) {
|
|
565
|
+
let remainder = value % 62;
|
|
566
|
+
res += generateName(remainder);
|
|
567
|
+
value = Math.floor((value - remainder) / 62);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return res;
|
|
543
571
|
}
|
|
544
572
|
|
|
545
573
|
// djb2 hash function.
|
|
@@ -558,75 +586,146 @@ function layerName(name: string) {
|
|
|
558
586
|
return `_.${name}`;
|
|
559
587
|
}
|
|
560
588
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
589
|
+
interface Rule {
|
|
590
|
+
addPseudo(prelude: string): void,
|
|
591
|
+
getStaticClassName(): string,
|
|
592
|
+
toCSS(rulesByLayer: Map<string, string[]>, preludes?: string[], layer?: string): void,
|
|
593
|
+
toJS(allowedOverridesSet: Set<string>, indent?: string): string
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/** A CSS style rule. */
|
|
597
|
+
class StyleRule implements Rule {
|
|
598
|
+
className: string;
|
|
599
|
+
pseudos: string;
|
|
600
|
+
property: string;
|
|
601
|
+
value: string;
|
|
602
|
+
|
|
603
|
+
constructor(className: string, property: string, value: string) {
|
|
604
|
+
this.className = className;
|
|
605
|
+
this.pseudos = '';
|
|
606
|
+
this.property = property;
|
|
607
|
+
this.value = value;
|
|
564
608
|
}
|
|
565
609
|
|
|
566
|
-
|
|
610
|
+
addPseudo(prelude: string) {
|
|
611
|
+
this.pseudos += prelude;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
getStaticClassName(): string {
|
|
615
|
+
return ' ' + this.className;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
toCSS(rulesByLayer: Map<string, string[]>, preludes: string[] = [], layer = 'a') {
|
|
619
|
+
let prelude = `.${this.className}${this.pseudos}`;
|
|
620
|
+
preludes.push(prelude);
|
|
621
|
+
|
|
567
622
|
// Nest rule in our stack of preludes (e.g. media queries/selectors).
|
|
568
623
|
let content = ' ';
|
|
569
624
|
preludes.forEach((p, i) => {
|
|
570
625
|
content += `${p} {\n${' '.repeat((i + 2) * 2)}`;
|
|
571
626
|
});
|
|
572
|
-
content +=
|
|
627
|
+
content += `${kebab(this.property)}: ${this.value};\n`;
|
|
573
628
|
preludes.map((_, i) => {
|
|
574
629
|
content += `${' '.repeat((preludes.length - i) * 2)}}\n`;
|
|
575
630
|
});
|
|
576
631
|
|
|
577
632
|
// Group rule into the appropriate layer.
|
|
578
|
-
let rules = rulesByLayer.get(
|
|
633
|
+
let rules = rulesByLayer.get(layer);
|
|
579
634
|
if (!rules) {
|
|
580
635
|
rules = [];
|
|
581
|
-
rulesByLayer.set(
|
|
636
|
+
rulesByLayer.set(layer, rules);
|
|
582
637
|
}
|
|
583
638
|
rules.push(content);
|
|
584
|
-
|
|
585
|
-
for (let b of rule.body) {
|
|
586
|
-
printRule(b, rulesByLayer, preludes, rule.layer || layer);
|
|
587
|
-
}
|
|
639
|
+
preludes.pop();
|
|
588
640
|
}
|
|
589
641
|
|
|
590
|
-
|
|
591
|
-
|
|
642
|
+
toJS(allowedOverridesSet: Set<string>, indent = ''): string {
|
|
643
|
+
let res = '';
|
|
644
|
+
if (allowedOverridesSet.has(this.property)) {
|
|
645
|
+
res += `${indent}if (!${this.property.replace('--', '__')}) `;
|
|
646
|
+
}
|
|
647
|
+
res += `${indent}rules += ' ${this.className}';`;
|
|
648
|
+
return res;
|
|
592
649
|
}
|
|
593
650
|
}
|
|
594
651
|
|
|
595
|
-
|
|
596
|
-
|
|
652
|
+
/** Base class for rules that contain other rules. */
|
|
653
|
+
class GroupRule implements Rule {
|
|
654
|
+
rules: Rule[];
|
|
655
|
+
layer: string | null;
|
|
597
656
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
657
|
+
constructor(rules: Rule[], layer?: string) {
|
|
658
|
+
this.rules = rules;
|
|
659
|
+
this.layer = layer ?? null;
|
|
660
|
+
}
|
|
601
661
|
|
|
602
|
-
|
|
662
|
+
addPseudo(prelude: string) {
|
|
663
|
+
for (let rule of this.rules) {
|
|
664
|
+
rule.addPseudo(prelude);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
603
667
|
|
|
604
|
-
|
|
605
|
-
return
|
|
668
|
+
getStaticClassName(): string {
|
|
669
|
+
return this.rules.map(rule => rule.getStaticClassName()).join('');
|
|
606
670
|
}
|
|
607
671
|
|
|
608
|
-
|
|
609
|
-
|
|
672
|
+
toCSS(rulesByLayer: Map<string, string[]>, preludes?: string[], layer?: string) {
|
|
673
|
+
for (let rule of this.rules) {
|
|
674
|
+
rule.toCSS(rulesByLayer, preludes, this.layer || layer);
|
|
675
|
+
}
|
|
610
676
|
}
|
|
611
677
|
|
|
612
|
-
|
|
613
|
-
|
|
678
|
+
toJS(allowedOverridesSet: Set<string>, indent = ''): string {
|
|
679
|
+
let rules = this.rules.slice();
|
|
680
|
+
let conditional = rules.filter(rule => rule instanceof ConditionalRule).reverse().map((rule, i) => {
|
|
681
|
+
return `${i > 0 ? ' else ' : ''}${rule.toJS(allowedOverridesSet, indent)}`;
|
|
682
|
+
});
|
|
614
683
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
684
|
+
let elseCases = rules.filter(rule => !(rule instanceof ConditionalRule)).map(rule => rule.toJS(allowedOverridesSet, indent));
|
|
685
|
+
if (conditional.length && elseCases.length) {
|
|
686
|
+
return `${conditional.join('')} else {\n${indent} ${elseCases.join('\n' + indent + ' ')}\n${indent}}`;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
if (conditional.length) {
|
|
690
|
+
return conditional.join('');
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return elseCases.join('\n' + indent);
|
|
619
694
|
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/** A rule that applies conditionally in CSS (e.g. @media). */
|
|
698
|
+
class AtRule extends GroupRule {
|
|
699
|
+
prelude: string;
|
|
620
700
|
|
|
621
|
-
|
|
622
|
-
|
|
701
|
+
constructor(rules: Rule[], prelude: string, layer: string) {
|
|
702
|
+
super(rules, layer);
|
|
703
|
+
this.prelude = prelude;
|
|
623
704
|
}
|
|
624
705
|
|
|
625
|
-
|
|
706
|
+
toCSS(rulesByLayer: Map<string, string[]>, preludes: string[] = [], layer?: string): void {
|
|
707
|
+
preludes.push(this.prelude);
|
|
708
|
+
super.toCSS(rulesByLayer, preludes, layer);
|
|
709
|
+
preludes?.pop();
|
|
710
|
+
}
|
|
626
711
|
}
|
|
627
712
|
|
|
628
|
-
|
|
629
|
-
|
|
713
|
+
/** A rule that applies conditionally at runtime. */
|
|
714
|
+
class ConditionalRule extends GroupRule {
|
|
715
|
+
condition: string;
|
|
716
|
+
|
|
717
|
+
constructor(rules: Rule[], condition: string) {
|
|
718
|
+
super(rules);
|
|
719
|
+
this.condition = condition;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
getStaticClassName(): string {
|
|
723
|
+
throw new Error('Conditional rules cannot be compiled to a static class name. This is a bug.');
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
toJS(allowedOverridesSet: Set<string>, indent = ''): string {
|
|
727
|
+
return `${indent}if (props.${this.condition}) {\n${super.toJS(allowedOverridesSet, indent + ' ')}\n${indent}}`;
|
|
728
|
+
}
|
|
630
729
|
}
|
|
631
730
|
|
|
632
731
|
export function raw(this: MacroContext | void, css: string, layer = '_.a'): string {
|