@multiplatform.one/theme 7.34.4 → 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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/theme",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.35.0",
|
|
4
4
|
"description": "Tamagui theme system for multiplatform.one",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"multiplatform",
|
|
@@ -38,14 +38,29 @@
|
|
|
38
38
|
"source": "./src/audit/index.ts",
|
|
39
39
|
"types": "./types/audit/index.d.ts",
|
|
40
40
|
"default": "./src/audit/index.ts"
|
|
41
|
+
},
|
|
42
|
+
"./scale-attribute": {
|
|
43
|
+
"source": "./src/theme/scale/scaleAttribute.ts",
|
|
44
|
+
"types": "./types/theme/scale/scaleAttribute.d.ts",
|
|
45
|
+
"default": "./src/theme/scale/scaleAttribute.ts"
|
|
46
|
+
},
|
|
47
|
+
"./design-tokens": {
|
|
48
|
+
"source": "./src/audit/designTokens.ts",
|
|
49
|
+
"types": "./types/audit/designTokens.d.ts",
|
|
50
|
+
"default": "./src/audit/designTokens.ts"
|
|
51
|
+
},
|
|
52
|
+
"./motion": {
|
|
53
|
+
"source": "./src/theme/motionTiming.ts",
|
|
54
|
+
"types": "./types/theme/motionTiming.d.ts",
|
|
55
|
+
"default": "./src/theme/motionTiming.ts"
|
|
41
56
|
}
|
|
42
57
|
},
|
|
43
58
|
"publishConfig": {
|
|
44
59
|
"access": "public"
|
|
45
60
|
},
|
|
46
61
|
"dependencies": {
|
|
47
|
-
"@multiplatform.one/platform": "^7.
|
|
48
|
-
"@multiplatform.one/store": "^7.
|
|
62
|
+
"@multiplatform.one/platform": "^7.35.0",
|
|
63
|
+
"@multiplatform.one/store": "^7.35.0",
|
|
49
64
|
"@tamagui/animations-react-native": "2.7.6",
|
|
50
65
|
"@tamagui/colors": "2.7.6",
|
|
51
66
|
"@tamagui/config": "2.7.6",
|
|
@@ -58,8 +73,8 @@
|
|
|
58
73
|
"react-cookie": "^8.1.2"
|
|
59
74
|
},
|
|
60
75
|
"devDependencies": {
|
|
61
|
-
"@multiplatform.one/config": "7.
|
|
62
|
-
"@multiplatform.one/test-utils": "7.
|
|
76
|
+
"@multiplatform.one/config": "7.35.0",
|
|
77
|
+
"@multiplatform.one/test-utils": "7.35.0",
|
|
63
78
|
"@tamagui/animations-css": "2.7.6",
|
|
64
79
|
"@tamagui/animations-reanimated": "2.7.6",
|
|
65
80
|
"@tamagui/font-inter": "2.7.6",
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { afterEach, describe, expect, it } from "vitest";
|
|
2
2
|
import { defaultConfig } from "@tamagui/config/v5";
|
|
3
3
|
import { defaultHeadingFont } from "../theme/defaults/fonts";
|
|
4
|
+
import { fontCategoryStacks } from "../theme/fontCategoryStacks";
|
|
4
5
|
import { defaultKnobs } from "../theme/knobs";
|
|
5
6
|
import { resolveKnobs } from "../theme/resolveKnobs";
|
|
7
|
+
import { deriveRecipeInputs } from "../theme/scale/deriveRecipeInputs";
|
|
8
|
+
import { generateScale } from "../theme/scale/generateScale";
|
|
9
|
+
import { defaultScaleInputs } from "../theme/scale/scaleInputs";
|
|
6
10
|
import { GAP_KNOB, GAP_LG_KNOB, runConstraintAudit } from "./constraintAudit";
|
|
7
11
|
|
|
8
12
|
afterEach(() => {
|
|
9
13
|
document.body.innerHTML = "";
|
|
14
|
+
delete (globalThis as { __MPO_SCALE__?: unknown }).__MPO_SCALE__;
|
|
10
15
|
});
|
|
11
16
|
|
|
12
17
|
// Deliberately loses module scope, like Playwright page.evaluate.
|
|
@@ -27,34 +32,48 @@ function measured() {
|
|
|
27
32
|
return audit().elements.find((el) => el.id === "specimen");
|
|
28
33
|
}
|
|
29
34
|
|
|
30
|
-
function card(radius: string,
|
|
35
|
+
function card(radius: string, tier = "content") {
|
|
31
36
|
return {
|
|
32
37
|
"data-constraint-container": "Card",
|
|
33
38
|
"data-tier": tier,
|
|
34
39
|
"data-radius-knob": radius,
|
|
35
|
-
"data-space-knob": space,
|
|
36
40
|
};
|
|
37
41
|
}
|
|
38
42
|
|
|
43
|
+
function recipeGaps(scale: ReturnType<typeof generateScale>) {
|
|
44
|
+
const { tokenTable, chipTokenTable } = deriveRecipeInputs(scale);
|
|
45
|
+
return [
|
|
46
|
+
...new Set(
|
|
47
|
+
[...Object.values(tokenTable), ...Object.values(chipTokenTable)].map((row) => row.radius),
|
|
48
|
+
),
|
|
49
|
+
].sort((a, b) => a - b);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function publish(scale: ReturnType<typeof generateScale>) {
|
|
53
|
+
(globalThis as { __MPO_SCALE__?: unknown }).__MPO_SCALE__ = {
|
|
54
|
+
...scale,
|
|
55
|
+
controlGaps: recipeGaps(scale),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const tokens = generateScale(defaultScaleInputs).tokens;
|
|
60
|
+
const inset = tokens.space.$4;
|
|
61
|
+
|
|
39
62
|
describe("Card container cap, independently measured against canonical stops", () => {
|
|
40
63
|
for (const tier of ["content", "elevated"]) {
|
|
41
64
|
for (const [radius, stop] of Object.entries({
|
|
42
65
|
none: 0,
|
|
43
|
-
small:
|
|
44
|
-
medium:
|
|
45
|
-
large:
|
|
46
|
-
full:
|
|
66
|
+
small: tokens.radius[4],
|
|
67
|
+
medium: tokens.radius[6],
|
|
68
|
+
large: tokens.radius[8],
|
|
69
|
+
full: tokens.radius[12],
|
|
47
70
|
})) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
expect(measured()?.violations).toEqual([]);
|
|
55
|
-
expect(measured()?.paddingTop?.value).toBe(inset);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
71
|
+
it(`${tier}/${radius} accepts all four corners capped at the panelPadding role`, () => {
|
|
72
|
+
specimen(`border-radius:${Math.min(stop, inset)}px;padding:${inset}px`, card(radius, tier));
|
|
73
|
+
expect(measured()?.violations).toEqual([]);
|
|
74
|
+
expect(measured()?.paddingTop?.value).toBe(inset);
|
|
75
|
+
expect(measured()?.paddingTop?.knob).toBe("Card panelPadding");
|
|
76
|
+
});
|
|
58
77
|
}
|
|
59
78
|
}
|
|
60
79
|
|
|
@@ -65,30 +84,22 @@ describe("Card container cap, independently measured against canonical stops", (
|
|
|
65
84
|
"border-radius:13px;padding:13px",
|
|
66
85
|
{ "data-tier": "content" },
|
|
67
86
|
],
|
|
68
|
-
["
|
|
69
|
-
["
|
|
70
|
-
["
|
|
71
|
-
["
|
|
72
|
-
["
|
|
73
|
-
["missing inset", "border-radius:0;padding:0", card("none"
|
|
74
|
-
[
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
card("full", "small"),
|
|
78
|
-
],
|
|
79
|
-
["percent radius cannot bypass cap", "border-radius:50%;padding:13px", card("full", "small")],
|
|
80
|
-
[
|
|
81
|
-
"elliptical corner cannot bypass cap",
|
|
82
|
-
"border-radius:13px / 16px;padding:13px",
|
|
83
|
-
card("full", "small"),
|
|
84
|
-
],
|
|
87
|
+
["a 13px inset is not the panelPadding role", "border-radius:13px;padding:13px", card("full")],
|
|
88
|
+
["radius past the inset", "border-radius:24px;padding:18px", card("full")],
|
|
89
|
+
["wrong last corner", "border-radius:18px 18px 18px 9px;padding:18px", card("full")],
|
|
90
|
+
["nonzero at none", "border-radius:5px;padding:18px", card("none")],
|
|
91
|
+
["arbitrary matching inset", "border-radius:14px;padding:14px", card("full")],
|
|
92
|
+
["missing inset", "border-radius:0;padding:0", card("none")],
|
|
93
|
+
["wrong individual inset", "border-radius:16px;padding:16px 13px 16px 16px", card("full")],
|
|
94
|
+
["percent radius cannot bypass cap", "border-radius:50%;padding:18px", card("full")],
|
|
95
|
+
["elliptical corner cannot bypass cap", "border-radius:18px / 24px;padding:18px", card("full")],
|
|
85
96
|
])("rejects %s", (_label, style, attrs) => {
|
|
86
97
|
specimen(style, attrs);
|
|
87
98
|
expect(measured()?.violations.length).toBeGreaterThan(0);
|
|
88
99
|
});
|
|
89
100
|
|
|
90
101
|
it("leaves ordinary control radius rules intact", () => {
|
|
91
|
-
specimen("border-radius:
|
|
102
|
+
specimen("border-radius:14px;padding:16px");
|
|
92
103
|
expect(measured()?.violations).toEqual([]);
|
|
93
104
|
});
|
|
94
105
|
|
|
@@ -98,33 +109,138 @@ describe("Card container cap, independently measured against canonical stops", (
|
|
|
98
109
|
"border-bottom-right-radius",
|
|
99
110
|
"border-bottom-left-radius",
|
|
100
111
|
])("rejects a wrong %s even when every radius is on the generic scale", (corner) => {
|
|
101
|
-
const el = specimen("border-radius:
|
|
102
|
-
el.style.setProperty(corner, "
|
|
112
|
+
const el = specimen("border-radius:14px;padding:16px", card("medium"));
|
|
113
|
+
el.style.setProperty(corner, "4px");
|
|
103
114
|
expect(measured()?.borderRadius?.offScale).toBe(true);
|
|
104
115
|
expect(measured()?.violations).toHaveLength(1);
|
|
105
116
|
});
|
|
106
117
|
});
|
|
107
118
|
|
|
108
|
-
describe("
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
119
|
+
describe("spacing-role parity in the serialized audit", () => {
|
|
120
|
+
const { knobProps } = resolveKnobs(defaultKnobs);
|
|
121
|
+
const px = (token: string) => tokens.space[token as keyof typeof tokens.space];
|
|
122
|
+
|
|
123
|
+
it("the module tables are the resolver's roles", () => {
|
|
124
|
+
expect(GAP_KNOB).toEqual({ gapSm: px(knobProps.gapSm.gap), gap: px(knobProps.gap.gap) });
|
|
125
|
+
expect(GAP_LG_KNOB).toEqual({ gapLg: px(knobProps.gapLg.gap) });
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it.each([
|
|
129
|
+
["gapSm", knobProps.gapSm.gap],
|
|
130
|
+
["gap", knobProps.gap.gap],
|
|
131
|
+
["gapLg", knobProps.gapLg.gap],
|
|
132
|
+
])("accepts the %s role", (_role, token) => {
|
|
133
|
+
specimen(`row-gap:${px(token)}px`);
|
|
134
|
+
expect(measured()?.rowGap?.offScale).toBe(false);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("accepts the panelPadding role as a surface inset", () => {
|
|
138
|
+
specimen(`border-radius:8px;padding:${px(knobProps.panelPadding.padding)}px`);
|
|
139
|
+
expect(measured()?.paddingTop?.offScale).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it.each([18, 22, 25, 31, 33])("rejects non-role gap %i", (gap) => {
|
|
123
143
|
specimen(`row-gap:${gap}px`);
|
|
124
144
|
expect(measured()?.rowGap?.offScale).toBe(true);
|
|
125
145
|
});
|
|
126
146
|
});
|
|
127
147
|
|
|
148
|
+
describe("the serialized audit reads the page's published scale", () => {
|
|
149
|
+
it("module tables are the default generated scale's tokens", () => {
|
|
150
|
+
const { space } = generateScale(defaultScaleInputs).tokens;
|
|
151
|
+
expect(GAP_KNOB).toEqual({ gapSm: space.$2, gap: space.$3 });
|
|
152
|
+
expect(GAP_LG_KNOB).toEqual({ gapLg: space.$5 });
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("without a published scale its fallbacks are the default scale", () => {
|
|
156
|
+
specimen(`row-gap:${generateScale(defaultScaleInputs).tokens.space.$3}px`);
|
|
157
|
+
expect(measured()?.rowGap?.offScale).toBe(false);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("a published scale moves the role px with it", () => {
|
|
161
|
+
const scale = generateScale({ control: 44, type: 15 });
|
|
162
|
+
specimen(`row-gap:${scale.tokens.space.$3}px`);
|
|
163
|
+
expect(measured()?.rowGap?.offScale).toBe(true);
|
|
164
|
+
publish(scale);
|
|
165
|
+
expect(measured()?.rowGap?.offScale).toBe(false);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("a control's inner gap is the published scale's $radius at any size key (LC-75)", () => {
|
|
169
|
+
const scale = generateScale({ control: 42, type: 15, radius: 0.3 });
|
|
170
|
+
const gap3 = scale.tokens.radius["3"];
|
|
171
|
+
expect(gap3).toBe(10);
|
|
172
|
+
specimen(`row-gap:${gap3}px`);
|
|
173
|
+
expect(measured()?.rowGap?.offScale).toBe(true);
|
|
174
|
+
publish(scale);
|
|
175
|
+
expect(measured()?.rowGap?.offScale).toBe(false);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("rejects a radius that the published recipe does not use as a gap", () => {
|
|
179
|
+
const scale = generateScale({ control: 42, type: 15, radius: 0.3 });
|
|
180
|
+
const gap = scale.tokens.radius["7"];
|
|
181
|
+
expect(recipeGaps(scale)).not.toContain(gap);
|
|
182
|
+
publish(scale);
|
|
183
|
+
specimen(`row-gap:${gap}px`);
|
|
184
|
+
expect(measured()?.rowGap?.offScale).toBe(true);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("uses the published recipe gaps instead of reconstructing them from radius tokens", () => {
|
|
188
|
+
const scale = generateScale({ control: 42, type: 15, radius: 0.3 });
|
|
189
|
+
(globalThis as { __MPO_SCALE__?: unknown }).__MPO_SCALE__ = { ...scale, controlGaps: [23] };
|
|
190
|
+
specimen("row-gap:23px");
|
|
191
|
+
expect(measured()?.rowGap?.offScale).toBe(false);
|
|
192
|
+
document.getElementById("specimen")!.style.rowGap = `${scale.tokens.radius["3"]}px`;
|
|
193
|
+
expect(measured()?.rowGap?.offScale).toBe(true);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it("keeps the serialized fallback exactly equal to the default recipe gaps", () => {
|
|
197
|
+
const fallback = runConstraintAudit.toString().match(/controlGaps\s*\?\?\s*(\[[^\]]*\])/);
|
|
198
|
+
expect(fallback).not.toBeNull();
|
|
199
|
+
expect(JSON.parse(fallback![1])).toEqual(recipeGaps(generateScale(defaultScaleInputs)));
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("a Card on a published scale caps at that scale's panelPadding", () => {
|
|
203
|
+
const scale = generateScale({ control: 36, type: 14 });
|
|
204
|
+
const scaleInset = scale.tokens.space.$4;
|
|
205
|
+
publish(scale);
|
|
206
|
+
specimen(`border-radius:${scaleInset}px;padding:${scaleInset}px`, card("full"));
|
|
207
|
+
expect(measured()?.violations).toEqual([]);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
describe("font family provenance", () => {
|
|
212
|
+
it.each(Object.entries(fontCategoryStacks))(
|
|
213
|
+
"accepts the canonical %s stack",
|
|
214
|
+
(_category, stack) => {
|
|
215
|
+
specimen(`font-family:${stack}`).textContent = "Configured typography";
|
|
216
|
+
for (const run of [audit, runConstraintAudit]) {
|
|
217
|
+
const entry = run().elements.find((el) => el.id === "specimen");
|
|
218
|
+
expect(entry?.fontFamily?.offScale).toBe(false);
|
|
219
|
+
expect(entry?.violations).toEqual([]);
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
it("recognizes Slate's configured primary font as mono", () => {
|
|
225
|
+
specimen(`font-family:${fontCategoryStacks.mono}`).textContent = "Slate heading";
|
|
226
|
+
expect(measured()?.fontFamily).toMatchObject({ knob: "mono", offScale: false });
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it.each(["Papyrus", "ui-serif", "Fira Code", "'Comic Neue', monospace"])(
|
|
230
|
+
"rejects unregistered primary family %s",
|
|
231
|
+
(stack) => {
|
|
232
|
+
specimen(`font-family:${stack}`).textContent = "Unregistered typography";
|
|
233
|
+
for (const run of [audit, runConstraintAudit]) {
|
|
234
|
+
const entry = run().elements.find((el) => el.id === "specimen");
|
|
235
|
+
expect(entry?.fontFamily?.offScale).toBe(true);
|
|
236
|
+
expect(entry?.violations).toEqual([
|
|
237
|
+
expect.stringContaining("is not a registered font token"),
|
|
238
|
+
]);
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
);
|
|
242
|
+
});
|
|
243
|
+
|
|
128
244
|
describe("font weight provenance", () => {
|
|
129
245
|
it("pins the configured heading source behind the self-contained whitelist", () => {
|
|
130
246
|
expect([...new Set(Object.values(defaultHeadingFont.weight).map(Number))].sort()).toEqual([
|
|
@@ -137,6 +253,33 @@ describe("font weight provenance", () => {
|
|
|
137
253
|
expect(measured()?.fontWeight).toMatchObject({ value: weight, unit: "", offScale: false });
|
|
138
254
|
expect(measured()?.fontWeight?.knob).toContain("configured heading");
|
|
139
255
|
});
|
|
256
|
+
it.each([600, 800])("accepts semantic headings at %i in both audit entry paths", (weight) => {
|
|
257
|
+
for (const tag of ["h1", "h2", "h3", "h4", "h5", "h6"]) {
|
|
258
|
+
const el = document.createElement(tag);
|
|
259
|
+
el.id = "specimen";
|
|
260
|
+
el.style.fontWeight = String(weight);
|
|
261
|
+
document.body.replaceChildren(el);
|
|
262
|
+
for (const run of [audit, runConstraintAudit]) {
|
|
263
|
+
expect(run().elements.find((entry) => entry.id === "specimen")?.fontWeight?.offScale).toBe(
|
|
264
|
+
false,
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
it.each([
|
|
270
|
+
["role", "heading"],
|
|
271
|
+
["class", "font_headingSerif"],
|
|
272
|
+
])("accepts heading provenance %s=%s", (attribute, value) => {
|
|
273
|
+
specimen("font-weight:800", { [attribute]: value });
|
|
274
|
+
expect(measured()?.fontWeight?.offScale).toBe(false);
|
|
275
|
+
});
|
|
276
|
+
it("rejects a plain span at 600", () => {
|
|
277
|
+
const el = document.createElement("span");
|
|
278
|
+
el.id = "specimen";
|
|
279
|
+
el.style.fontWeight = "600";
|
|
280
|
+
document.body.append(el);
|
|
281
|
+
expect(measured()?.fontWeight?.offScale).toBe(true);
|
|
282
|
+
});
|
|
140
283
|
it.each([500, 650, 900])("rejects unconfigured weight %i", (weight) => {
|
|
141
284
|
specimen(`font-weight:${weight}`, { class: "font_heading" });
|
|
142
285
|
expect(measured()?.fontWeight?.offScale).toBe(true);
|
|
@@ -199,93 +342,89 @@ describe("BINARY parts measure 0 or their own h/2 (DG-RAD-03)", () => {
|
|
|
199
342
|
});
|
|
200
343
|
|
|
201
344
|
describe("declared capped containers beyond Card (DG-RAD-04)", () => {
|
|
202
|
-
const declared = (container: string, radius: string
|
|
345
|
+
const declared = (container: string, radius: string) => ({
|
|
203
346
|
"data-constraint-container": container,
|
|
204
347
|
"data-radius-knob": radius,
|
|
205
|
-
"data-space-knob": space,
|
|
206
348
|
});
|
|
207
349
|
|
|
208
350
|
it("accepts a PageSection surface capped at its own panelPadding", () => {
|
|
209
|
-
specimen("border-radius:
|
|
351
|
+
specimen("border-radius:16px;padding:16px", declared("PageSection", "full"));
|
|
210
352
|
expect(measured()?.violations).toEqual([]);
|
|
211
353
|
});
|
|
212
354
|
|
|
213
355
|
it("measures a PageSection surface inset like a Card's", () => {
|
|
214
|
-
specimen("border-radius:
|
|
215
|
-
expect(measured()?.violations.join(" ")).toContain("PageSection panelPadding
|
|
356
|
+
specimen("border-radius:18px;padding:12px", declared("PageSection", "full"));
|
|
357
|
+
expect(measured()?.violations.join(" ")).toContain("PageSection panelPadding");
|
|
216
358
|
});
|
|
217
359
|
|
|
218
360
|
it("accepts a TextArea box at the cap whatever its field inset", () => {
|
|
219
|
-
specimen("border-radius:
|
|
361
|
+
specimen("border-radius:16px;padding:0", declared("TextArea", "full"));
|
|
220
362
|
expect(measured()?.violations).toEqual([]);
|
|
221
|
-
expect(measured()?.borderRadius?.knob).toBe("TextArea min(radius:full, panelPadding
|
|
363
|
+
expect(measured()?.borderRadius?.knob).toBe("TextArea min(radius:full, panelPadding)");
|
|
222
364
|
});
|
|
223
365
|
|
|
224
366
|
it("audits a TextArea box's own padding on the ordinary scale", () => {
|
|
225
|
-
specimen("border-radius:9px;padding:15px", declared("TextArea", "medium"
|
|
367
|
+
specimen("border-radius:9px;padding:15px", declared("TextArea", "medium"));
|
|
226
368
|
expect(measured()?.violations.join(" ")).toContain("paddingTop: 15px is off-scale");
|
|
227
369
|
});
|
|
228
370
|
|
|
229
371
|
it.each([
|
|
230
|
-
["the uncapped token", "border-radius:50px", declared("TextArea", "full"
|
|
231
|
-
["a cap
|
|
232
|
-
["
|
|
233
|
-
["an unknown radius stop", "border-radius:13px", declared("TextArea", "round"
|
|
372
|
+
["the uncapped token", "border-radius:50px", declared("TextArea", "full")],
|
|
373
|
+
["a cap off the panelPadding role", "border-radius:13px", declared("TextArea", "full")],
|
|
374
|
+
["a radius past the cap", "border-radius:24px", declared("TextArea", "full")],
|
|
375
|
+
["an unknown radius stop", "border-radius:13px", declared("TextArea", "round")],
|
|
234
376
|
])("rejects %s", (_label, style, attrs) => {
|
|
235
377
|
specimen(style, attrs);
|
|
236
378
|
expect(measured()?.borderRadius?.offScale).toBe(true);
|
|
237
379
|
});
|
|
238
380
|
|
|
239
381
|
it("names a container the audit does not know instead of trusting it", () => {
|
|
240
|
-
specimen("border-radius:13px;padding:13px", declared("Tile", "full"
|
|
382
|
+
specimen("border-radius:13px;padding:13px", declared("Tile", "full"));
|
|
241
383
|
expect(measured()?.violations.join(" ")).toContain('"Tile" is not a container');
|
|
242
384
|
});
|
|
243
385
|
});
|
|
244
386
|
|
|
245
387
|
describe("stacked rows cap their outer corners and square the inner ones (MPO-56)", () => {
|
|
246
|
-
const row = (position: string, radius: string
|
|
388
|
+
const row = (position: string, radius: string) => ({
|
|
247
389
|
"data-constraint-container": "StackedRow",
|
|
248
390
|
"data-stack-position": position,
|
|
249
391
|
"data-radius-knob": radius,
|
|
250
|
-
"data-space-knob": space,
|
|
251
392
|
});
|
|
252
393
|
const corners = (tl: number, tr: number, br: number, bl: number) =>
|
|
253
394
|
`border-top-left-radius:${tl}px;border-top-right-radius:${tr}px;` +
|
|
254
|
-
`border-bottom-right-radius:${br}px;border-bottom-left-radius:${bl}px;padding:
|
|
395
|
+
`border-bottom-right-radius:${br}px;border-bottom-left-radius:${bl}px;padding:6px 12px`;
|
|
255
396
|
|
|
256
397
|
it.each([
|
|
257
|
-
["first", corners(
|
|
398
|
+
["first", corners(16, 16, 0, 0)],
|
|
258
399
|
["middle", corners(0, 0, 0, 0)],
|
|
259
|
-
["last", corners(0, 0,
|
|
260
|
-
["only", corners(
|
|
261
|
-
])("accepts a %s row capped at the
|
|
262
|
-
specimen(style, row(position, "
|
|
400
|
+
["last", corners(0, 0, 16, 16)],
|
|
401
|
+
["only", corners(16, 16, 16, 16)],
|
|
402
|
+
])("accepts a %s row capped at the panelPadding role", (position, style) => {
|
|
403
|
+
specimen(style, row(position, "full"));
|
|
263
404
|
expect(measured()?.violations).toEqual([]);
|
|
264
405
|
});
|
|
265
406
|
|
|
266
407
|
it("names the stop it resolved on an outer corner", () => {
|
|
267
|
-
specimen(corners(
|
|
268
|
-
expect(measured()?.borderTopLeftRadius?.knob).toBe(
|
|
269
|
-
"StackedRow min(radius:full, panelPadding:medium)",
|
|
270
|
-
);
|
|
408
|
+
specimen(corners(16, 16, 0, 0), row("first", "full"));
|
|
409
|
+
expect(measured()?.borderTopLeftRadius?.knob).toBe("StackedRow min(radius:full, panelPadding)");
|
|
271
410
|
});
|
|
272
411
|
|
|
273
412
|
it.each([
|
|
274
|
-
["an uncapped outer corner", corners(
|
|
275
|
-
["a rounded inner corner", corners(
|
|
276
|
-
["a rounded middle row", corners(
|
|
277
|
-
["a missing position", corners(
|
|
413
|
+
["an uncapped outer corner", corners(24, 24, 0, 0), row("first", "full")],
|
|
414
|
+
["a rounded inner corner", corners(16, 16, 16, 0), row("first", "full")],
|
|
415
|
+
["a rounded middle row", corners(16, 0, 0, 0), row("middle", "full")],
|
|
416
|
+
["a missing position", corners(16, 16, 16, 16), row("", "full")],
|
|
278
417
|
])("rejects %s", (_label, style, attrs) => {
|
|
279
418
|
specimen(style, attrs);
|
|
280
419
|
expect(measured()?.borderRadius?.offScale).toBe(true);
|
|
281
420
|
});
|
|
282
421
|
|
|
283
422
|
it("says which corner is inner", () => {
|
|
284
|
-
specimen(corners(0, 0,
|
|
423
|
+
specimen(corners(0, 0, 16, 9), row("last", "full"));
|
|
285
424
|
expect(measured()?.violations).toEqual([
|
|
286
|
-
"borderBottomLeftRadius: 9px does not match StackedRow cap (
|
|
425
|
+
"borderBottomLeftRadius: 9px does not match StackedRow cap (16px)",
|
|
287
426
|
]);
|
|
288
|
-
specimen(corners(9, 0,
|
|
427
|
+
specimen(corners(9, 0, 16, 16), row("last", "full")).id = "other";
|
|
289
428
|
const other = audit().elements.find((el) => el.id === "other");
|
|
290
429
|
expect(other?.violations).toEqual([
|
|
291
430
|
"borderTopLeftRadius: 9px is an inner corner of a last StackedRow (0px)",
|
|
@@ -313,17 +452,16 @@ describe("a fixed-padding container caps at the padding it has (DG-RAD-04, MPO-5
|
|
|
313
452
|
const own = (radius: string) => ({
|
|
314
453
|
"data-constraint-container": "OwnInset",
|
|
315
454
|
"data-radius-knob": radius,
|
|
316
|
-
"data-space-knob": "medium",
|
|
317
455
|
});
|
|
318
456
|
|
|
319
|
-
it("accepts full capped at its own
|
|
320
|
-
specimen("border-radius:
|
|
457
|
+
it("accepts full capped at its own 12px padding", () => {
|
|
458
|
+
specimen("border-radius:12px;padding:12px", own("full"));
|
|
321
459
|
expect(measured()?.violations).toEqual([]);
|
|
322
460
|
expect(measured()?.borderRadius?.knob).toBe("OwnInset min(radius:full, own padding)");
|
|
323
461
|
});
|
|
324
462
|
|
|
325
463
|
it("accepts the token while it fits", () => {
|
|
326
|
-
specimen("border-radius:
|
|
464
|
+
specimen("border-radius:8px;padding:12px", own("small"));
|
|
327
465
|
expect(measured()?.violations).toEqual([]);
|
|
328
466
|
});
|
|
329
467
|
|
|
@@ -335,3 +473,52 @@ describe("a fixed-padding container caps at the padding it has (DG-RAD-04, MPO-5
|
|
|
335
473
|
expect(measured()?.borderRadius?.offScale).toBe(true);
|
|
336
474
|
});
|
|
337
475
|
});
|
|
476
|
+
|
|
477
|
+
describe("container and field keys on every scale", () => {
|
|
478
|
+
for (const [control, type] of [
|
|
479
|
+
[40, 15],
|
|
480
|
+
[44, 15],
|
|
481
|
+
[36, 14],
|
|
482
|
+
]) {
|
|
483
|
+
for (const [stop, controlKey, containerKey] of [
|
|
484
|
+
["none", 0, 0],
|
|
485
|
+
["small", 2, 4],
|
|
486
|
+
["medium", 4, 6],
|
|
487
|
+
["large", 6, 8],
|
|
488
|
+
["full", 12, 12],
|
|
489
|
+
] as const) {
|
|
490
|
+
for (const part of ["Card", "PageSection", "StackedRow", "OwnInset", "TextArea"]) {
|
|
491
|
+
it(`${part}/${stop} reads ${control}/${type} by key`, () => {
|
|
492
|
+
const scale = generateScale({ control, type });
|
|
493
|
+
publish(scale);
|
|
494
|
+
const pad = scale.tokens.space.$4;
|
|
495
|
+
const radius = scale.tokens.radius[part === "TextArea" ? controlKey : containerKey];
|
|
496
|
+
specimen(`border-radius:${Math.min(radius, pad)}px;padding:${pad}px`, {
|
|
497
|
+
"data-constraint-container": part,
|
|
498
|
+
"data-radius-knob": stop,
|
|
499
|
+
"data-tier": "content",
|
|
500
|
+
"data-stack-position": "only",
|
|
501
|
+
});
|
|
502
|
+
expect(measured()?.violations).toEqual([]);
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
it("every serialized fallback equals its generated default token", () => {
|
|
509
|
+
const fallbacks = [
|
|
510
|
+
...runConstraintAudit.toString().matchAll(/_(radius|space|size)\("([^"]+)", ([\d.]+)\)/g),
|
|
511
|
+
];
|
|
512
|
+
expect(fallbacks.length).toBeGreaterThan(20);
|
|
513
|
+
for (const [, group, key, value] of fallbacks) {
|
|
514
|
+
const table = tokens[group as keyof typeof tokens] as Record<string, number>;
|
|
515
|
+
expect(Number(value), `${group}/${key}`).toBe(table[group === "radius" ? key : `$${key}`]);
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
it.each([20, 16])("container radius %i is on the generic radius scale", (radius) => {
|
|
520
|
+
specimen(`border-radius:${radius}px`);
|
|
521
|
+
expect(measured()?.borderRadius?.offScale).toBe(false);
|
|
522
|
+
expect(measured()?.borderRadius?.knob).toContain("container");
|
|
523
|
+
});
|
|
524
|
+
});
|