@multiplatform.one/theme 7.34.3 → 7.35.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.
- package/package.json +20 -5
- package/src/audit/constraintAudit.spec.ts +274 -87
- package/src/audit/constraintAudit.ts +135 -120
- package/src/audit/constraintScope.spec.ts +1 -1
- package/src/audit/designTokens.ts +42 -0
- package/src/audit/themeMatrix.spec.ts +83 -2
- package/src/audit/themeMatrix.ts +33 -1
- package/src/figma/figmaTokens.spec.ts +26 -34
- package/src/figma/figmaTokens.ts +26 -50
- package/src/fonts/createFontLoader.ts +4 -1
- package/src/menuRow.ts +4 -1
- package/src/theme/FontKnobStyles.tsx +2 -1
- package/src/theme/Preset.stories.tsx +0 -1
- package/src/theme/Preset.tsx +6 -1
- package/src/theme/PresetContext.ts +4 -0
- package/src/theme/Surface.spec.tsx +114 -67
- package/src/theme/Surface.stories.tsx +8 -25
- package/src/theme/Surface.tsx +87 -43
- package/src/theme/accentFloor.spec.ts +37 -11
- package/src/theme/activateThemeConfig.ts +22 -6
- package/src/theme/animations/animations.spec.ts +62 -0
- package/src/theme/animations/css.ts +9 -35
- package/src/theme/animations/reactNative.ts +98 -25
- package/src/theme/boundaryFloor.spec.ts +57 -0
- package/src/theme/chartPalette.spec.ts +56 -27
- package/src/theme/chartPalette.ts +33 -28
- package/src/theme/colorRules.spec.ts +32 -72
- package/src/theme/cookies.spec.ts +49 -18
- package/src/theme/cookies.ts +36 -7
- package/src/theme/cookiesPersistence.spec.ts +5 -5
- package/src/theme/createDefaultThemeConfig.spec.ts +182 -20
- package/src/theme/createDefaultThemeConfig.ts +34 -28
- package/src/theme/createThemes.ts +169 -218
- package/src/theme/defaults/accent.ts +3 -35
- package/src/theme/defaults/base.ts +14 -53
- package/src/theme/defaults/builderOptions.ts +68 -85
- package/src/theme/defaults/categoryFonts.ts +10 -0
- package/src/theme/defaults/fonts.spec.ts +84 -4
- package/src/theme/defaults/fonts.ts +166 -124
- package/src/theme/defaults/house.ts +48 -0
- package/src/theme/defaults/index.ts +1 -0
- package/src/theme/defaults/neutralRamp.spec.ts +52 -47
- package/src/theme/devtools/ColorLineVisualizer.tsx +6 -6
- package/src/theme/devtools/ThemeDevtoolsPanel.setMarkers.spec.tsx +13 -6
- package/src/theme/devtools/ThemeDevtoolsPanel.tsx +14 -77
- package/src/theme/devtools/animationOptions.spec.ts +23 -37
- package/src/theme/devtools/animationOptions.ts +4 -6
- package/src/theme/devtools/buildSnapshot.ts +0 -3
- package/src/theme/devtools/knobIcons.tsx +4 -24
- package/src/theme/focusState.spec.ts +9 -30
- package/src/theme/index.ts +17 -0
- package/src/theme/intentFill.spec.ts +42 -0
- package/src/theme/knobs.ts +14 -42
- package/src/theme/layoutTokens.ts +15 -1
- package/src/theme/layoutTokensHooks.spec.tsx +8 -4
- package/src/theme/mergedTokens.ts +20 -0
- package/src/theme/motion.spec.ts +84 -0
- package/src/theme/motion.ts +53 -0
- package/src/theme/motionStops.ts +17 -0
- package/src/theme/motionTiming.ts +59 -0
- package/src/theme/mpo13Proof.spec.ts +43 -46
- package/src/theme/mpo19Proof.spec.ts +13 -14
- package/src/theme/namedInkFloor.spec.ts +60 -0
- package/src/theme/overlaySurfaces.tsx +330 -0
- package/src/theme/preset.types.ts +16 -0
- package/src/theme/presetPreview.ts +32 -0
- package/src/theme/presetRoot.spec.tsx +89 -0
- package/src/theme/presetStore.persistence.spec.ts +141 -0
- package/src/theme/presetStore.spec.ts +205 -0
- package/src/theme/presetStore.ts +286 -0
- package/src/theme/presetUserSync.spec.tsx +168 -0
- package/src/theme/presetUserSync.ts +47 -0
- package/src/theme/presets.spec.ts +22 -15
- package/src/theme/presets.ts +22 -10
- package/src/theme/radiusClass.spec.ts +60 -41
- package/src/theme/radiusClass.ts +17 -4
- package/src/theme/radiusClassTable.generated.ts +3 -3
- package/src/theme/readableColor.spec.ts +59 -152
- package/src/theme/readableColor.ts +34 -174
- package/src/theme/recipeInputs.ts +153 -295
- package/src/theme/recipes.ts +58 -18
- package/src/theme/resolveKnobs.spec.ts +528 -588
- package/src/theme/resolveKnobs.ts +250 -325
- package/src/theme/scale/ScaleStyles.native.tsx +19 -0
- package/src/theme/scale/ScaleStyles.tsx +48 -0
- package/src/theme/scale/activeScale.ts +30 -0
- package/src/theme/scale/deriveRecipeInputs.ts +110 -0
- package/src/theme/scale/generateScale.spec.ts +260 -0
- package/src/theme/scale/generateScale.ts +147 -0
- package/src/theme/scale/index.ts +54 -0
- package/src/theme/scale/installScaleConfig.native.spec.ts +77 -0
- package/src/theme/scale/installScaleConfig.native.ts +57 -0
- package/src/theme/scale/installScaleConfig.ts +7 -0
- package/src/theme/scale/scaleAttribute.ts +21 -0
- package/src/theme/scale/scaleCss.probe.spec.tsx +64 -0
- package/src/theme/scale/scaleCss.spec.ts +132 -0
- package/src/theme/scale/scaleCss.ts +95 -0
- package/src/theme/scale/scaleFonts.ts +106 -0
- package/src/theme/scale/scaleInputs.ts +322 -0
- package/src/theme/scale/themeScales.ts +181 -0
- package/src/theme/scale/useActiveScale.spec.tsx +129 -0
- package/src/theme/scale/useActiveScale.ts +95 -0
- package/src/theme/schemeStore.spec.ts +81 -0
- package/src/theme/schemeStore.ts +67 -0
- package/src/theme/shared.spec.ts +7 -6
- package/src/theme/shared.tsx +37 -3
- package/src/theme/sizeLadder.spec.ts +37 -36
- package/src/theme/sizeRecipes.spec.ts +179 -85
- package/src/theme/sizeRecipes.ts +48 -25
- package/src/theme/subsetThemes.spec.ts +9 -3
- package/src/theme/switchThumb.spec.ts +69 -0
- package/src/theme/syntaxFloor.spec.ts +11 -8
- package/src/theme/theme.hydration.native.spec.tsx +51 -0
- package/src/theme/theme.native.tsx +59 -21
- package/src/theme/theme.palette.spec.tsx +76 -0
- package/src/theme/theme.preset.native.spec.tsx +73 -0
- package/src/theme/theme.provider.spec.ts +143 -1
- package/src/theme/theme.tsx +61 -25
- package/src/theme/tileSizes.ts +6 -7
- package/src/theme/transitionProps.native.ts +25 -2
- package/src/theme/transitionProps.spec.ts +34 -0
- package/src/theme/transitionProps.ts +26 -2
- package/src/theme/usePresetSwitch.native.spec.tsx +68 -0
- package/src/theme/usePresetSwitch.native.ts +32 -0
- package/src/theme/usePresetSwitch.spec.tsx +103 -0
- package/src/theme/usePresetSwitch.ts +54 -0
- package/src/theme/useResolvedKnobs.hydration.spec.tsx +2 -2
- package/src/theme/useResolvedKnobs.ts +23 -90
- package/src/theme/useResolvedKnobsBehavior.spec.tsx +25 -30
- package/src/theme/useSchemePreference.native.ts +33 -0
- package/src/theme/useSchemePreference.spec.tsx +51 -0
- package/src/theme/useSchemePreference.ts +32 -0
- package/src/theme/useSchemePreference.web.spec.tsx +32 -0
- package/src/theme/useTheme.native.spec.tsx +68 -0
- package/src/theme/useTheme.native.ts +49 -24
- package/src/theme/useTheme.ts +7 -4
- package/types/audit/constraintAudit.d.ts +6 -5
- package/types/audit/constraintAudit.d.ts.map +1 -1
- package/types/audit/designTokens.d.ts +13 -0
- package/types/audit/designTokens.d.ts.map +1 -0
- package/types/audit/themeMatrix.d.ts +10 -0
- package/types/audit/themeMatrix.d.ts.map +1 -1
- package/types/figma/figmaTokens.d.ts +11 -28
- package/types/figma/figmaTokens.d.ts.map +1 -1
- package/types/fonts/createFontLoader.d.ts.map +1 -1
- package/types/menuRow.d.ts +4 -1
- package/types/menuRow.d.ts.map +1 -1
- package/types/theme/FontKnobStyles.d.ts.map +1 -1
- package/types/theme/Preset.d.ts.map +1 -1
- package/types/theme/PresetContext.d.ts +4 -0
- package/types/theme/PresetContext.d.ts.map +1 -1
- package/types/theme/Surface.d.ts +57 -26
- package/types/theme/Surface.d.ts.map +1 -1
- package/types/theme/activateThemeConfig.d.ts +5 -3
- package/types/theme/activateThemeConfig.d.ts.map +1 -1
- package/types/theme/animations/css.d.ts +27 -34
- package/types/theme/animations/css.d.ts.map +1 -1
- package/types/theme/animations/reactNative.d.ts +196 -45
- package/types/theme/animations/reactNative.d.ts.map +1 -1
- package/types/theme/chartPalette.d.ts +11 -3
- package/types/theme/chartPalette.d.ts.map +1 -1
- package/types/theme/colorRules.d.ts +1 -1
- package/types/theme/cookies.d.ts +12 -1
- package/types/theme/cookies.d.ts.map +1 -1
- package/types/theme/createDefaultThemeConfig.d.ts +13 -13
- package/types/theme/createDefaultThemeConfig.d.ts.map +1 -1
- package/types/theme/createThemes.d.ts +58 -2
- package/types/theme/createThemes.d.ts.map +1 -1
- package/types/theme/defaults/accent.d.ts.map +1 -1
- package/types/theme/defaults/base.d.ts.map +1 -1
- package/types/theme/defaults/builderOptions.d.ts.map +1 -1
- package/types/theme/defaults/categoryFonts.d.ts +10 -0
- package/types/theme/defaults/categoryFonts.d.ts.map +1 -1
- package/types/theme/defaults/fonts.d.ts +330 -30
- package/types/theme/defaults/fonts.d.ts.map +1 -1
- package/types/theme/defaults/house.d.ts +8 -0
- package/types/theme/defaults/house.d.ts.map +1 -0
- package/types/theme/defaults/index.d.ts +1 -0
- package/types/theme/defaults/index.d.ts.map +1 -1
- package/types/theme/devtools/ThemeDevtoolsPanel.d.ts +3 -3
- package/types/theme/devtools/ThemeDevtoolsPanel.d.ts.map +1 -1
- package/types/theme/devtools/animationOptions.d.ts.map +1 -1
- package/types/theme/devtools/buildSnapshot.d.ts.map +1 -1
- package/types/theme/devtools/knobIcons.d.ts +0 -3
- package/types/theme/devtools/knobIcons.d.ts.map +1 -1
- package/types/theme/index.d.ts +11 -0
- package/types/theme/index.d.ts.map +1 -1
- package/types/theme/knobs.d.ts +8 -36
- package/types/theme/knobs.d.ts.map +1 -1
- package/types/theme/layoutTokens.d.ts +13 -1
- package/types/theme/layoutTokens.d.ts.map +1 -1
- package/types/theme/mergedTokens.d.ts +11 -0
- package/types/theme/mergedTokens.d.ts.map +1 -0
- package/types/theme/motion.d.ts +17 -0
- package/types/theme/motion.d.ts.map +1 -0
- package/types/theme/motionStops.d.ts +3 -0
- package/types/theme/motionStops.d.ts.map +1 -0
- package/types/theme/motionTiming.d.ts +36 -0
- package/types/theme/motionTiming.d.ts.map +1 -0
- package/types/theme/overlaySurfaces.d.ts +70 -0
- package/types/theme/overlaySurfaces.d.ts.map +1 -0
- package/types/theme/preset.types.d.ts +16 -0
- package/types/theme/preset.types.d.ts.map +1 -1
- package/types/theme/presetPreview.d.ts +14 -0
- package/types/theme/presetPreview.d.ts.map +1 -0
- package/types/theme/presetStore.d.ts +40 -0
- package/types/theme/presetStore.d.ts.map +1 -0
- package/types/theme/presetUserSync.d.ts +7 -0
- package/types/theme/presetUserSync.d.ts.map +1 -0
- package/types/theme/presets.d.ts +12 -4
- package/types/theme/presets.d.ts.map +1 -1
- package/types/theme/radiusClass.d.ts +5 -2
- package/types/theme/radiusClass.d.ts.map +1 -1
- package/types/theme/radiusClassTable.generated.d.ts +3 -3
- package/types/theme/readableColor.d.ts +11 -49
- package/types/theme/readableColor.d.ts.map +1 -1
- package/types/theme/recipeInputs.d.ts +39 -70
- package/types/theme/recipeInputs.d.ts.map +1 -1
- package/types/theme/recipes.d.ts +79 -18
- package/types/theme/recipes.d.ts.map +1 -1
- package/types/theme/resolveKnobs.d.ts +64 -32
- package/types/theme/resolveKnobs.d.ts.map +1 -1
- package/types/theme/scale/ScaleStyles.d.ts +18 -0
- package/types/theme/scale/ScaleStyles.d.ts.map +1 -0
- package/types/theme/scale/ScaleStyles.native.d.ts +10 -0
- package/types/theme/scale/ScaleStyles.native.d.ts.map +1 -0
- package/types/theme/scale/activeScale.d.ts +13 -0
- package/types/theme/scale/activeScale.d.ts.map +1 -0
- package/types/theme/scale/deriveRecipeInputs.d.ts +10 -0
- package/types/theme/scale/deriveRecipeInputs.d.ts.map +1 -0
- package/types/theme/scale/generateScale.d.ts +38 -0
- package/types/theme/scale/generateScale.d.ts.map +1 -0
- package/types/theme/scale/index.d.ts +17 -0
- package/types/theme/scale/index.d.ts.map +1 -0
- package/types/theme/scale/installScaleConfig.d.ts +4 -0
- package/types/theme/scale/installScaleConfig.d.ts.map +1 -0
- package/types/theme/scale/installScaleConfig.native.d.ts +13 -0
- package/types/theme/scale/installScaleConfig.native.d.ts.map +1 -0
- package/types/theme/scale/scaleAttribute.d.ts +14 -0
- package/types/theme/scale/scaleAttribute.d.ts.map +1 -0
- package/types/theme/scale/scaleCss.d.ts +25 -0
- package/types/theme/scale/scaleCss.d.ts.map +1 -0
- package/types/theme/scale/scaleFonts.d.ts +16 -0
- package/types/theme/scale/scaleFonts.d.ts.map +1 -0
- package/types/theme/scale/scaleInputs.d.ts +66 -0
- package/types/theme/scale/scaleInputs.d.ts.map +1 -0
- package/types/theme/scale/themeScales.d.ts +52 -0
- package/types/theme/scale/themeScales.d.ts.map +1 -0
- package/types/theme/scale/useActiveScale.d.ts +31 -0
- package/types/theme/scale/useActiveScale.d.ts.map +1 -0
- package/types/theme/schemeStore.d.ts +6 -0
- package/types/theme/schemeStore.d.ts.map +1 -0
- package/types/theme/shared.d.ts +18 -0
- package/types/theme/shared.d.ts.map +1 -1
- package/types/theme/sizeRecipes.d.ts +20 -15
- package/types/theme/sizeRecipes.d.ts.map +1 -1
- package/types/theme/theme.d.ts +2 -1
- package/types/theme/theme.d.ts.map +1 -1
- package/types/theme/theme.native.d.ts +10 -1
- package/types/theme/theme.native.d.ts.map +1 -1
- package/types/theme/tileSizes.d.ts +6 -7
- package/types/theme/tileSizes.d.ts.map +1 -1
- package/types/theme/transitionProps.d.ts +3 -1
- package/types/theme/transitionProps.d.ts.map +1 -1
- package/types/theme/transitionProps.native.d.ts +3 -1
- package/types/theme/transitionProps.native.d.ts.map +1 -1
- package/types/theme/usePresetSwitch.d.ts +10 -0
- package/types/theme/usePresetSwitch.d.ts.map +1 -0
- package/types/theme/usePresetSwitch.native.d.ts +10 -0
- package/types/theme/usePresetSwitch.native.d.ts.map +1 -0
- package/types/theme/useResolvedKnobs.d.ts +13 -13
- package/types/theme/useResolvedKnobs.d.ts.map +1 -1
- package/types/theme/useSchemePreference.d.ts +8 -0
- package/types/theme/useSchemePreference.d.ts.map +1 -0
- package/types/theme/useSchemePreference.native.d.ts +8 -0
- package/types/theme/useSchemePreference.native.d.ts.map +1 -0
- package/types/theme/useTheme.d.ts +4 -2
- package/types/theme/useTheme.d.ts.map +1 -1
- package/types/theme/useTheme.native.d.ts +10 -1
- package/types/theme/useTheme.native.d.ts.map +1 -1
|
@@ -38,9 +38,6 @@ const minimalPreset: Preset = {
|
|
|
38
38
|
borderRadius: "none",
|
|
39
39
|
borderWidth: "none",
|
|
40
40
|
elevation: "none",
|
|
41
|
-
space: "small",
|
|
42
|
-
size: "small",
|
|
43
|
-
density: "comfortable",
|
|
44
41
|
textAccent: "low",
|
|
45
42
|
headingFont: "sans-serif",
|
|
46
43
|
bodyFont: "sans-serif",
|
|
@@ -63,9 +60,6 @@ const boldPreset: Preset = {
|
|
|
63
60
|
borderRadius: "full",
|
|
64
61
|
borderWidth: "large",
|
|
65
62
|
elevation: "medium",
|
|
66
|
-
space: "large",
|
|
67
|
-
size: "large",
|
|
68
|
-
density: "comfortable",
|
|
69
63
|
textAccent: "high",
|
|
70
64
|
headingFont: "sans-serif",
|
|
71
65
|
bodyFont: "sans-serif",
|
|
@@ -88,9 +82,6 @@ const roundedPreset: Preset = {
|
|
|
88
82
|
borderRadius: "large",
|
|
89
83
|
borderWidth: "small",
|
|
90
84
|
elevation: "small",
|
|
91
|
-
space: "medium",
|
|
92
|
-
size: "medium",
|
|
93
|
-
density: "comfortable",
|
|
94
85
|
textAccent: "high",
|
|
95
86
|
headingFont: "sans-serif",
|
|
96
87
|
bodyFont: "sans-serif",
|
|
@@ -142,10 +133,10 @@ describe("Theme Preset System", () => {
|
|
|
142
133
|
registerPreset("minimal", minimalPreset);
|
|
143
134
|
const updated: Preset = {
|
|
144
135
|
...minimalPreset,
|
|
145
|
-
knobs: { ...minimalPreset.knobs,
|
|
136
|
+
knobs: { ...minimalPreset.knobs, textAccent: "high" },
|
|
146
137
|
};
|
|
147
138
|
registerPreset("minimal", updated);
|
|
148
|
-
expect(getPreset("minimal")?.knobs.
|
|
139
|
+
expect(getPreset("minimal")?.knobs.textAccent).toBe("high");
|
|
149
140
|
});
|
|
150
141
|
});
|
|
151
142
|
|
|
@@ -158,16 +149,16 @@ describe("Theme Preset System", () => {
|
|
|
158
149
|
const resolved = resolveThemeFromPreset("minimal", {});
|
|
159
150
|
expect(resolved.knobs.borderRadius).toBe("none");
|
|
160
151
|
expect(resolved.knobs.elevation).toBe("none");
|
|
161
|
-
expect(resolved.knobs.
|
|
152
|
+
expect(resolved.knobs.textAccent).toBe("low");
|
|
162
153
|
});
|
|
163
154
|
|
|
164
155
|
it("merges overrides on top of preset config", () => {
|
|
165
156
|
registerPreset("minimal", minimalPreset);
|
|
166
|
-
const overrides = { borderRadius: "full" as const,
|
|
157
|
+
const overrides = { borderRadius: "full" as const, textAccent: "high" as const };
|
|
167
158
|
const resolved = resolveThemeFromPreset("minimal", overrides);
|
|
168
159
|
// Overrides win
|
|
169
160
|
expect(resolved.knobs.borderRadius).toBe("full");
|
|
170
|
-
expect(resolved.knobs.
|
|
161
|
+
expect(resolved.knobs.textAccent).toBe("high");
|
|
171
162
|
// Preset defaults preserved for non-overridden props
|
|
172
163
|
expect(resolved.knobs.elevation).toBe("none");
|
|
173
164
|
expect(resolved.knobs.fillStyle).toBe("outlined");
|
|
@@ -201,7 +192,7 @@ describe("Theme Preset System", () => {
|
|
|
201
192
|
const resolved2 = resolveThemeFromPreset("bold", {});
|
|
202
193
|
expect(resolved2.knobs.elevation).toBe("medium"); // bold preset's value
|
|
203
194
|
expect(resolved2.knobs.borderRadius).toBe("full"); // bold preset's value
|
|
204
|
-
expect(resolved2.knobs.
|
|
195
|
+
expect(resolved2.knobs.fontWeight).toBe("bold"); // bold preset's value
|
|
205
196
|
});
|
|
206
197
|
});
|
|
207
198
|
|
|
@@ -267,3 +258,19 @@ describe("Theme Preset System", () => {
|
|
|
267
258
|
});
|
|
268
259
|
});
|
|
269
260
|
});
|
|
261
|
+
|
|
262
|
+
describe("token-scale presets (FZ-7158 WP-a2)", () => {
|
|
263
|
+
it("dense and roomy differ from the default only in their token scale", async () => {
|
|
264
|
+
const { defaultPreset, densePreset, roomyPreset } = await import("./presets");
|
|
265
|
+
expect(JSON.stringify(densePreset.knobs)).toBe(JSON.stringify(defaultPreset.knobs));
|
|
266
|
+
expect(JSON.stringify(roomyPreset.knobs)).toBe(JSON.stringify(defaultPreset.knobs));
|
|
267
|
+
const { scale: _dense, ...denseRest } = densePreset;
|
|
268
|
+
const { scale: _roomy, ...roomyRest } = roomyPreset;
|
|
269
|
+
const { scale: _default, ...defaultRest } = defaultPreset;
|
|
270
|
+
expect(denseRest).toEqual(defaultRest);
|
|
271
|
+
expect(roomyRest).toEqual(defaultRest);
|
|
272
|
+
expect(densePreset.scale).toEqual({ control: 36, type: 14 });
|
|
273
|
+
expect(roomyPreset.scale).toEqual({ control: 48, type: 16 });
|
|
274
|
+
expect(defaultPreset.scale).toEqual({ control: 40, type: 15 });
|
|
275
|
+
});
|
|
276
|
+
});
|
package/src/theme/presets.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ThemeName } from "@tamagui/web";
|
|
2
2
|
import { defaultIntents } from "./intents";
|
|
3
3
|
import type { Preset } from "./preset.types";
|
|
4
|
+
import { defaultScaleInputs } from "./scale/scaleInputs";
|
|
4
5
|
|
|
5
6
|
export const defaultPreset: Preset = {
|
|
6
7
|
theme: "" as ThemeName,
|
|
@@ -10,9 +11,6 @@ export const defaultPreset: Preset = {
|
|
|
10
11
|
cornerSmoothing: "round",
|
|
11
12
|
borderWidth: "medium",
|
|
12
13
|
elevation: "small",
|
|
13
|
-
space: "medium",
|
|
14
|
-
size: "medium",
|
|
15
|
-
density: "comfortable",
|
|
16
14
|
textAccent: "high",
|
|
17
15
|
headingFont: "sans-serif",
|
|
18
16
|
bodyFont: "sans-serif",
|
|
@@ -34,6 +32,7 @@ export const defaultPreset: Preset = {
|
|
|
34
32
|
},
|
|
35
33
|
intents: defaultIntents,
|
|
36
34
|
tints: ["orange", "blue", "purple", "pink"] as ThemeName[],
|
|
35
|
+
scale: defaultScaleInputs,
|
|
37
36
|
};
|
|
38
37
|
|
|
39
38
|
export const boldPreset: Preset = {
|
|
@@ -44,9 +43,6 @@ export const boldPreset: Preset = {
|
|
|
44
43
|
cornerSmoothing: "round",
|
|
45
44
|
borderWidth: "none",
|
|
46
45
|
elevation: "none",
|
|
47
|
-
space: "small",
|
|
48
|
-
size: "medium",
|
|
49
|
-
density: "comfortable",
|
|
50
46
|
textAccent: "high",
|
|
51
47
|
headingFont: "sans-serif",
|
|
52
48
|
bodyFont: "sans-serif",
|
|
@@ -71,10 +67,8 @@ export const boldPreset: Preset = {
|
|
|
71
67
|
};
|
|
72
68
|
|
|
73
69
|
/**
|
|
74
|
-
* Marketing / hero
|
|
75
|
-
*
|
|
76
|
-
* the display step ($10 = 64px): product screens are wayfinding and take the
|
|
77
|
-
* moderate step by default, so the loud scale has to be ASKED for.
|
|
70
|
+
* Marketing / hero preset: default knobs with the display title step
|
|
71
|
+
* ($12 = 52px at type 15). Product presets keep the moderate step.
|
|
78
72
|
*
|
|
79
73
|
* @example Whole marketing app
|
|
80
74
|
* createDefaultThemeConfig({ presets: { default: defaultPreset, hero: heroPreset } })
|
|
@@ -88,3 +82,21 @@ export const heroPreset: Preset = {
|
|
|
88
82
|
...defaultPreset,
|
|
89
83
|
knobs: { ...defaultPreset.knobs, pageTitleScale: "display" },
|
|
90
84
|
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* `defaultPreset` on a tighter token scale ($4 = 36, body 14). Knobs are
|
|
88
|
+
* identical to the default's: every px it saves comes from token values.
|
|
89
|
+
*/
|
|
90
|
+
export const densePreset: Preset = {
|
|
91
|
+
...defaultPreset,
|
|
92
|
+
scale: { control: 36, type: 14 },
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* `defaultPreset` on a roomier token scale ($4 = 48, body 16). Knobs are
|
|
97
|
+
* identical to the default's: every px it adds comes from token values.
|
|
98
|
+
*/
|
|
99
|
+
export const roomyPreset: Preset = {
|
|
100
|
+
...defaultPreset,
|
|
101
|
+
scale: { control: 48, type: 16 },
|
|
102
|
+
};
|
|
@@ -3,6 +3,8 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
import { afterAll, describe, expect, it } from "vitest";
|
|
6
|
+
import { generateScale } from "./scale/generateScale";
|
|
7
|
+
import { defaultScaleInputs } from "./scale/scaleInputs";
|
|
6
8
|
import type { BorderRadius } from "./knobs";
|
|
7
9
|
import { radiusOverrideFor, resolveRadiusClass, resolveRadiusForPart } from "./radiusClass";
|
|
8
10
|
import {
|
|
@@ -12,7 +14,7 @@ import {
|
|
|
12
14
|
RADIUS_RESOLUTION_STOPS,
|
|
13
15
|
RADIUS_RESOLUTION_TABLE,
|
|
14
16
|
} from "./radiusClassTable.generated";
|
|
15
|
-
import { capContainerRadius } from "./resolveKnobs";
|
|
17
|
+
import { capContainerRadius, panelPaddingPx } from "./resolveKnobs";
|
|
16
18
|
|
|
17
19
|
// The generator is the doctrine's reading end — the spec imports it directly so a
|
|
18
20
|
// doctrine edit and a generated-table edit are compared in the same run. Vite
|
|
@@ -25,15 +27,29 @@ const doctrine = registry.readRadiusClassDoctrine();
|
|
|
25
27
|
|
|
26
28
|
const STOPS = ["none", "small", "medium", "large", "full"] as const;
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
const
|
|
30
|
+
const scale = generateScale(defaultScaleInputs).tokens;
|
|
31
|
+
const H = scale.size.$4;
|
|
32
|
+
const PADS = { small: scale.space.$3, medium: scale.space.$4, large: scale.space.$6 } as const;
|
|
33
|
+
const radiusStops = {
|
|
34
|
+
none: scale.radius[0],
|
|
35
|
+
small: scale.radius[2],
|
|
36
|
+
medium: scale.radius[4],
|
|
37
|
+
large: scale.radius[6],
|
|
38
|
+
full: scale.radius[12],
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const containerStops = {
|
|
42
|
+
none: 0,
|
|
43
|
+
small: scale.radius[4],
|
|
44
|
+
medium: scale.radius[6],
|
|
45
|
+
large: scale.radius[8],
|
|
46
|
+
full: scale.radius[12],
|
|
47
|
+
};
|
|
32
48
|
|
|
33
49
|
describe("the doctrine table, cell by cell (DG-RAD-01..04)", () => {
|
|
34
50
|
const expected: Record<string, Record<BorderRadius, number>> = {
|
|
35
|
-
DEFAULT:
|
|
36
|
-
"CIRCULAR-AT-FULL": {
|
|
51
|
+
DEFAULT: radiusStops,
|
|
52
|
+
"CIRCULAR-AT-FULL": { ...radiusStops, full: H / 2 },
|
|
37
53
|
BINARY: { none: 0, small: H / 2, medium: H / 2, large: H / 2, full: H / 2 },
|
|
38
54
|
};
|
|
39
55
|
|
|
@@ -49,11 +65,12 @@ describe("the doctrine table, cell by cell (DG-RAD-01..04)", () => {
|
|
|
49
65
|
}
|
|
50
66
|
}
|
|
51
67
|
|
|
52
|
-
const containerCap
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
68
|
+
const containerCap = Object.fromEntries(
|
|
69
|
+
Object.entries(PADS).map(([name, padding]) => [
|
|
70
|
+
name,
|
|
71
|
+
Object.fromEntries(STOPS.map((stop) => [stop, Math.min(containerStops[stop], padding)])),
|
|
72
|
+
]),
|
|
73
|
+
) as Record<keyof typeof PADS, Record<BorderRadius, number>>;
|
|
57
74
|
|
|
58
75
|
for (const space of Object.keys(containerCap) as (keyof typeof PADS)[]) {
|
|
59
76
|
for (const stop of STOPS) {
|
|
@@ -66,36 +83,38 @@ describe("the doctrine table, cell by cell (DG-RAD-01..04)", () => {
|
|
|
66
83
|
}
|
|
67
84
|
});
|
|
68
85
|
|
|
69
|
-
describe("capContainerRadius agrees with the CONTAINER-CAP column (DG-RAD-04
|
|
86
|
+
describe("capContainerRadius agrees with the CONTAINER-CAP column (DG-RAD-04)", () => {
|
|
70
87
|
// capContainerRadius returns the TOKEN while it fits and the padding px once
|
|
71
88
|
// it would exceed; mirror the token px scale to compare resolutions.
|
|
72
|
-
const tokenPx: Record<string, number> = {
|
|
89
|
+
const tokenPx: Record<string, number> = {
|
|
90
|
+
$0: scale.radius[0],
|
|
91
|
+
$2: scale.radius[2],
|
|
92
|
+
$4: scale.radius[4],
|
|
93
|
+
$6: scale.radius[6],
|
|
94
|
+
$8: scale.radius[8],
|
|
95
|
+
$12: scale.radius[12],
|
|
96
|
+
};
|
|
73
97
|
const asPx = (value: string | number): number =>
|
|
74
98
|
typeof value === "number" ? value : tokenPx[value];
|
|
75
99
|
|
|
76
|
-
for (const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
});
|
|
83
|
-
}
|
|
100
|
+
for (const stop of STOPS) {
|
|
101
|
+
it(`at ${stop} on the panelPadding role`, () => {
|
|
102
|
+
expect(asPx(capContainerRadius(stop))).toBe(
|
|
103
|
+
resolveRadiusClass("CONTAINER-CAP", stop, { paddingPx: panelPaddingPx() }),
|
|
104
|
+
);
|
|
105
|
+
});
|
|
84
106
|
}
|
|
85
107
|
|
|
86
|
-
it("the cap is the container's own padding at full
|
|
87
|
-
expect(capContainerRadius("full"
|
|
88
|
-
expect(
|
|
89
|
-
expect(capContainerRadius("full", "large")).toBe(32);
|
|
108
|
+
it("the cap is the container's own padding at full", () => {
|
|
109
|
+
expect(capContainerRadius("full")).toBe(panelPaddingPx());
|
|
110
|
+
expect(panelPaddingPx()).toBe(scale.space.$4);
|
|
90
111
|
});
|
|
91
112
|
|
|
92
|
-
it("the cap bites at large
|
|
93
|
-
expect(capContainerRadius("large"
|
|
94
|
-
expect(capContainerRadius("
|
|
95
|
-
expect(capContainerRadius("
|
|
96
|
-
expect(capContainerRadius("
|
|
97
|
-
expect(capContainerRadius("small", "small")).toBe("$2");
|
|
98
|
-
expect(capContainerRadius("none", "small")).toBe("$0");
|
|
113
|
+
it("the cap bites at large and full on the default scale", () => {
|
|
114
|
+
expect(capContainerRadius("large")).toBe(16);
|
|
115
|
+
expect(capContainerRadius("medium")).toBe("$6");
|
|
116
|
+
expect(capContainerRadius("small")).toBe("$4");
|
|
117
|
+
expect(capContainerRadius("none")).toBe("$0");
|
|
99
118
|
});
|
|
100
119
|
});
|
|
101
120
|
|
|
@@ -235,20 +254,20 @@ describe("the override layer wins over the class layer (DG-RAD-05)", () => {
|
|
|
235
254
|
heightPx: glyph,
|
|
236
255
|
});
|
|
237
256
|
expect(resolved.source).toBe("override");
|
|
238
|
-
expect(resolved.px).toBe(stop === "none" ? 0 :
|
|
257
|
+
expect(resolved.px).toBe(stop === "none" ? 0 : scale.radius[2]);
|
|
239
258
|
expect(resolved.px).not.toBe(glyph / 2);
|
|
240
259
|
expect(resolved.overrideWhy).toMatch(/reads as a radio/);
|
|
241
260
|
}
|
|
242
261
|
});
|
|
243
262
|
|
|
244
|
-
it("Checkbox at full
|
|
263
|
+
it("Checkbox at full uses the small token clamp", () => {
|
|
245
264
|
const resolved = resolveRadiusForPart({
|
|
246
265
|
part: "Checkbox",
|
|
247
266
|
radiusClass: "CIRCULAR-AT-FULL",
|
|
248
267
|
stop: "full",
|
|
249
268
|
heightPx: 20,
|
|
250
269
|
});
|
|
251
|
-
expect(resolved.px).toBe(
|
|
270
|
+
expect(resolved.px).toBe(scale.radius[2]);
|
|
252
271
|
});
|
|
253
272
|
|
|
254
273
|
it("the Radio disc is round at every stop, including none (R2c — R2b inverted)", () => {
|
|
@@ -274,7 +293,7 @@ describe("the override layer wins over the class layer (DG-RAD-05)", () => {
|
|
|
274
293
|
it("an UNDECLARED part still resolves by its class", () => {
|
|
275
294
|
const resolved = resolveRadiusForPart({ part: "Button", radiusClass: "DEFAULT", stop: "full" });
|
|
276
295
|
expect(resolved.source).toBe("class");
|
|
277
|
-
expect(resolved.px).toBe(
|
|
296
|
+
expect(resolved.px).toBe(scale.radius[12]);
|
|
278
297
|
expect(resolved.overrideWhy).toBeUndefined();
|
|
279
298
|
// and with no part at all, the class is the resolution
|
|
280
299
|
expect(resolveRadiusForPart({ radiusClass: "BINARY", stop: "medium", heightPx: H }).px).toBe(
|
|
@@ -340,7 +359,7 @@ describe("open adjudications are REPORTED, never silently skipped (MPO-56 AC-6)"
|
|
|
340
359
|
});
|
|
341
360
|
|
|
342
361
|
describe("closed R2 leftovers (RULINGS-2026-08-28)", () => {
|
|
343
|
-
it("a single-line control at full is the DEFAULT pill token
|
|
362
|
+
it("a single-line control at full is the DEFAULT pill token, not clampRadiusForControl's 16 (R2d)", () => {
|
|
344
363
|
const resolved = resolveRadiusForPart({
|
|
345
364
|
part: "Input",
|
|
346
365
|
radiusClass: "DEFAULT",
|
|
@@ -348,7 +367,7 @@ describe("closed R2 leftovers (RULINGS-2026-08-28)", () => {
|
|
|
348
367
|
heightPx: 44,
|
|
349
368
|
});
|
|
350
369
|
expect(resolved.source).toBe("class");
|
|
351
|
-
expect(resolved.px).toBe(
|
|
370
|
+
expect(resolved.px).toBe(scale.radius[12]);
|
|
352
371
|
expect(resolved.px).not.toBe(16);
|
|
353
372
|
});
|
|
354
373
|
|
|
@@ -365,10 +384,10 @@ describe("closed R2 leftovers (RULINGS-2026-08-28)", () => {
|
|
|
365
384
|
expect(atNone.px).toBe(0);
|
|
366
385
|
expect(
|
|
367
386
|
resolveRadiusForPart({ part: "empty icon well", radiusClass: "DEFAULT", stop: "medium" }).px,
|
|
368
|
-
).toBe(
|
|
387
|
+
).toBe(scale.radius[4]);
|
|
369
388
|
expect(
|
|
370
389
|
resolveRadiusForPart({ part: "empty icon well", radiusClass: "DEFAULT", stop: "full" }).px,
|
|
371
|
-
).toBe(
|
|
390
|
+
).toBe(scale.radius[12]);
|
|
372
391
|
});
|
|
373
392
|
|
|
374
393
|
it("BINARY at none is 0 for thumb AND track — they square together (R2f)", () => {
|
package/src/theme/radiusClass.ts
CHANGED
|
@@ -35,6 +35,9 @@
|
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
37
|
import type { BorderRadius } from "./knobs";
|
|
38
|
+
import { getActiveScaleTokens } from "./scale/activeScale";
|
|
39
|
+
import { generateScale } from "./scale/generateScale";
|
|
40
|
+
import { RADIUS_KEYS, v5ScaleInputs } from "./scale/scaleInputs";
|
|
38
41
|
import {
|
|
39
42
|
RADIUS_OVERRIDE_TABLE,
|
|
40
43
|
RADIUS_RESOLUTION_COMPOSITION,
|
|
@@ -48,7 +51,7 @@ import {
|
|
|
48
51
|
* The radius classes whose parts stay round at `borderRadius:none`.
|
|
49
52
|
*
|
|
50
53
|
* - `R-PILL` — a pill/circle at every radius value (ornamental dots, badge
|
|
51
|
-
* indicators). Size still tracks the size
|
|
54
|
+
* indicators). Size still tracks the size token. Icon wells are DEFAULT,
|
|
52
55
|
* not R-PILL (R2e) — unless the well IS a count badge.
|
|
53
56
|
* - `R-IDENTITY` — the shape IS the part's identity (Avatar, brand marks,
|
|
54
57
|
* Radio disc). Membership is enumerated in the spec table and enforced
|
|
@@ -102,15 +105,25 @@ export function radiusResolutionProps(radiusClass: "BINARY"): RadiusResolutionDe
|
|
|
102
105
|
// ── Radius resolution (DG-RAD-01..05) ─────────────────────────
|
|
103
106
|
|
|
104
107
|
/**
|
|
108
|
+
* Doctrine px cells are v5 `$radius` values; they resolve to the installed
|
|
109
|
+
* scale's radius at the same key.
|
|
110
|
+
*
|
|
105
111
|
* The geometry a doctrine cell may need. `h/2` cells need the part's own
|
|
106
112
|
* painted height (shorter edge); CONTAINER-CAP cells need the container's own
|
|
107
|
-
* padding
|
|
113
|
+
* padding (the `panelPadding` role on the installed scale, `panelPaddingPx()`).
|
|
108
114
|
*/
|
|
109
115
|
export interface RadiusClassGeometry {
|
|
110
116
|
heightPx?: number;
|
|
111
117
|
paddingPx?: number;
|
|
112
118
|
}
|
|
113
119
|
|
|
120
|
+
const doctrineRadius = generateScale(v5ScaleInputs).tokens.radius;
|
|
121
|
+
|
|
122
|
+
function doctrineRadiusPx(px: number): number {
|
|
123
|
+
const key = RADIUS_KEYS.find((key) => key !== "true" && doctrineRadius[key] === px);
|
|
124
|
+
return key === undefined ? px : getActiveScaleTokens().radius[key];
|
|
125
|
+
}
|
|
126
|
+
|
|
114
127
|
function resolveCell(
|
|
115
128
|
cell: RadiusResolutionCell,
|
|
116
129
|
geometry: RadiusClassGeometry,
|
|
@@ -118,7 +131,7 @@ function resolveCell(
|
|
|
118
131
|
): number {
|
|
119
132
|
switch (cell.kind) {
|
|
120
133
|
case "px":
|
|
121
|
-
return cell.px;
|
|
134
|
+
return doctrineRadiusPx(cell.px);
|
|
122
135
|
case "half-height": {
|
|
123
136
|
if (geometry.heightPx === undefined || geometry.heightPx <= 0) {
|
|
124
137
|
throw new Error(
|
|
@@ -133,7 +146,7 @@ function resolveCell(
|
|
|
133
146
|
`resolveRadiusClass: ${where} caps at the container's own padding and needs geometry.paddingPx`,
|
|
134
147
|
);
|
|
135
148
|
}
|
|
136
|
-
return Math.min(cell.tokenPx, geometry.paddingPx);
|
|
149
|
+
return Math.min(doctrineRadiusPx(cell.tokenPx), geometry.paddingPx);
|
|
137
150
|
}
|
|
138
151
|
case "padding": {
|
|
139
152
|
if (geometry.paddingPx === undefined || geometry.paddingPx < 0) {
|
|
@@ -53,9 +53,9 @@ export const RADIUS_RESOLUTION_TABLE = {
|
|
|
53
53
|
},
|
|
54
54
|
"CONTAINER-CAP": {
|
|
55
55
|
none: { kind: "px", px: 0 },
|
|
56
|
-
small: { kind: "min-token-padding", tokenPx:
|
|
57
|
-
medium: { kind: "min-token-padding", tokenPx:
|
|
58
|
-
large: { kind: "min-token-padding", tokenPx:
|
|
56
|
+
small: { kind: "min-token-padding", tokenPx: 9 },
|
|
57
|
+
medium: { kind: "min-token-padding", tokenPx: 16 },
|
|
58
|
+
large: { kind: "min-token-padding", tokenPx: 22 },
|
|
59
59
|
full: { kind: "padding" },
|
|
60
60
|
},
|
|
61
61
|
} as const satisfies Record<string, RadiusResolutionRow>;
|