@pure-ds/core 0.4.37 → 0.5.1
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/types/pds.d.ts +32 -11
- package/dist/types/public/assets/auto-definer-XWHRBQPU.d.ts +9 -0
- package/dist/types/public/assets/auto-definer-XWHRBQPU.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-746HIXIK.d.ts +52 -0
- package/dist/types/public/assets/chunk-746HIXIK.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-APJV5T3J.d.ts +106 -0
- package/dist/types/public/assets/chunk-APJV5T3J.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-BEPKFFM7.d.ts +398 -0
- package/dist/types/public/assets/chunk-BEPKFFM7.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-ISS7UH5H.d.ts +2424 -0
- package/dist/types/public/assets/chunk-ISS7UH5H.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-RUPLQUDG.d.ts +582 -0
- package/dist/types/public/assets/chunk-RUPLQUDG.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-USML4NYF.d.ts +18 -0
- package/dist/types/public/assets/chunk-USML4NYF.d.ts.map +1 -0
- package/dist/types/public/assets/chunk-Z47A3HLT.d.ts +3 -0
- package/dist/types/public/assets/chunk-Z47A3HLT.d.ts.map +1 -0
- package/dist/types/public/assets/js/auto-definer-HZLD2XF4.d.ts +9 -0
- package/dist/types/public/assets/js/auto-definer-HZLD2XF4.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-6A6DFAIG.d.ts +88 -0
- package/dist/types/public/assets/js/chunk-6A6DFAIG.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-746HIXIK.d.ts +52 -0
- package/dist/types/public/assets/js/chunk-746HIXIK.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-A3TZGIYX.d.ts +4 -0
- package/dist/types/public/assets/js/chunk-A3TZGIYX.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-BEPKFFM7.d.ts +398 -0
- package/dist/types/public/assets/js/chunk-BEPKFFM7.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-OTTRJ5MB.d.ts +1695 -0
- package/dist/types/public/assets/js/chunk-OTTRJ5MB.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-RBPKHG76.d.ts +747 -0
- package/dist/types/public/assets/js/chunk-RBPKHG76.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-RUPLQUDG.d.ts +582 -0
- package/dist/types/public/assets/js/chunk-RUPLQUDG.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-SMD2R3CX.d.ts +68 -0
- package/dist/types/public/assets/js/chunk-SMD2R3CX.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunk-Y73DA2D5.d.ts +15 -0
- package/dist/types/public/assets/js/chunk-Y73DA2D5.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/auto-definer-X7MSXKTU.d.ts +9 -0
- package/dist/types/public/assets/js/chunks/auto-definer-X7MSXKTU.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/chunk-7BDQH5CT.d.ts +485 -0
- package/dist/types/public/assets/js/chunks/chunk-7BDQH5CT.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/chunk-MWB3S7NG.d.ts +3 -0
- package/dist/types/public/assets/js/chunks/chunk-MWB3S7NG.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/chunk-WIMLORAU.d.ts +5 -0
- package/dist/types/public/assets/js/chunks/chunk-WIMLORAU.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/chunk-WN4Y2ELN.d.ts +833 -0
- package/dist/types/public/assets/js/chunks/chunk-WN4Y2ELN.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/chunk-XQOUIBLO.d.ts +1687 -0
- package/dist/types/public/assets/js/chunks/chunk-XQOUIBLO.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/font-loader-VN5SRNOD.d.ts +5 -0
- package/dist/types/public/assets/js/chunks/font-loader-VN5SRNOD.d.ts.map +1 -0
- package/dist/types/public/assets/js/chunks/pds-live-validation-BQPWN5JG.d.ts +38 -0
- package/dist/types/public/assets/js/chunks/pds-live-validation-BQPWN5JG.d.ts.map +1 -0
- package/dist/types/public/assets/js/common-WIAC4WAJ.d.ts +4 -0
- package/dist/types/public/assets/js/common-WIAC4WAJ.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-config-WEBAXXSM.d.ts +4 -0
- package/dist/types/public/assets/js/pds-config-WEBAXXSM.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-core/pds-generator.d.ts +700 -0
- package/dist/types/public/assets/js/pds-core/pds-generator.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-core/pds-utilities.d.ts +27 -0
- package/dist/types/public/assets/js/pds-core/pds-utilities.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-enums-DCBZHS64.d.ts +3 -0
- package/dist/types/public/assets/js/pds-enums-DCBZHS64.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-gen.d.ts +106 -0
- package/dist/types/public/assets/js/pds-gen.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-live.d.ts +11 -0
- package/dist/types/public/assets/js/pds-live.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-manager.d.ts +1328 -0
- package/dist/types/public/assets/js/pds-manager.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-ontology-2DICJXHO.d.ts +9 -0
- package/dist/types/public/assets/js/pds-ontology-2DICJXHO.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds-query-B54LBKKR.d.ts +70 -0
- package/dist/types/public/assets/js/pds-query-B54LBKKR.d.ts.map +1 -0
- package/dist/types/public/assets/js/pds.d.ts +2 -18
- package/dist/types/public/assets/js/pds.d.ts.map +1 -1
- package/dist/types/public/assets/pds-ontology-ZO6TJHO3.d.ts +9 -0
- package/dist/types/public/assets/pds-ontology-ZO6TJHO3.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-config.d.ts +757 -0
- package/dist/types/src/js/common/pds-core/pds-config.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-enhancers.d.ts +28 -0
- package/dist/types/src/js/common/pds-core/pds-enhancers.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-enums.d.ts +87 -0
- package/dist/types/src/js/common/pds-core/pds-enums.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-generator.d.ts +700 -0
- package/dist/types/src/js/common/pds-core/pds-generator.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-ontology.d.ts +380 -0
- package/dist/types/src/js/common/pds-core/pds-ontology.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-paths.d.ts +37 -0
- package/dist/types/src/js/common/pds-core/pds-paths.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-query.d.ts +102 -0
- package/dist/types/src/js/common/pds-core/pds-query.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-registry.d.ts +35 -0
- package/dist/types/src/js/common/pds-core/pds-registry.d.ts.map +1 -0
- package/dist/types/src/js/common/pds-core/pds-utilities.d.ts +27 -0
- package/dist/types/src/js/common/pds-core/pds-utilities.d.ts.map +1 -0
- package/dist/types/src/js/pds-core/pds-generator.d.ts +38 -46
- package/dist/types/src/js/pds-core/pds-generator.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-live.d.ts +39 -0
- package/dist/types/src/js/pds-core/pds-live.d.ts.map +1 -0
- package/dist/types/src/js/pds-core/pds-runtime.d.ts +39 -0
- package/dist/types/src/js/pds-core/pds-runtime.d.ts.map +1 -0
- package/dist/types/src/js/pds-core/pds-start-helpers.d.ts +60 -0
- package/dist/types/src/js/pds-core/pds-start-helpers.d.ts.map +1 -0
- package/dist/types/src/js/pds-core/pds-utilities.d.ts +27 -0
- package/dist/types/src/js/pds-core/pds-utilities.d.ts.map +1 -0
- package/dist/types/src/js/pds-gen.d.ts +48 -0
- package/dist/types/src/js/pds-gen.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-runtime.d.ts +7 -0
- package/dist/types/src/js/pds-live-runtime.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-validation.d.ts +44 -0
- package/dist/types/src/js/pds-live-validation.d.ts.map +1 -0
- package/dist/types/src/js/pds-live.d.ts +11 -0
- package/dist/types/src/js/pds-live.d.ts.map +1 -0
- package/dist/types/src/js/pds-manager.d.ts +2 -0
- package/dist/types/src/js/pds-manager.d.ts.map +1 -0
- package/dist/types/src/js/pds.d.ts +6 -33
- package/dist/types/src/js/pds.d.ts.map +1 -1
- package/package.json +11 -12
- package/packages/pds-cli/bin/{generate-css-data.mjs → generate-css-data.js} +563 -563
- package/packages/pds-cli/bin/{generate-manifest.mjs → generate-manifest.js} +352 -352
- package/packages/pds-cli/bin/{pds-build-icons.mjs → pds-build-icons.js} +152 -152
- package/packages/pds-cli/bin/{pds-dx.mjs → pds-dx.js} +114 -114
- package/packages/pds-cli/bin/{pds-init-config.mjs → pds-init-config.js} +34 -34
- package/packages/pds-cli/bin/{pds-setup-copilot.mjs → pds-setup-copilot.js} +106 -106
- package/packages/pds-cli/bin/{pds-static.mjs → pds-static.js} +581 -581
- package/packages/pds-cli/bin/{pds.mjs → pds.js} +127 -127
- package/packages/pds-cli/bin/postinstall.mjs +522 -563
- package/packages/pds-cli/bin/{sync-assets.mjs → sync-assets.js} +251 -251
- package/packages/pds-cli/lib/{asset-roots.mjs → asset-roots.js} +47 -47
- package/packages/pds-cli/lib/{fs-writer.mjs → fs-writer.js} +75 -75
- package/public/assets/js/app.js +95 -118
- package/public/assets/js/pds-manager.js +3251 -0
- package/public/assets/js/pds.js +10 -3201
- package/readme.md +2014 -2016
- package/src/js/pds-core/pds-enhancers.js +518 -518
- package/src/js/pds-core/pds-enums.js +86 -86
- package/src/js/pds-core/pds-generator.js +255 -185
- package/src/js/pds-core/pds-live.js +434 -0
- package/src/js/pds-core/pds-paths.js +109 -109
- package/src/js/pds-core/pds-registry.js +79 -79
- package/src/js/pds-core/pds-runtime.js +184 -0
- package/src/js/pds-core/pds-start-helpers.js +404 -0
- package/src/js/pds.d.ts +32 -11
- package/src/js/pds.js +37 -1182
- package/getting-started.md +0 -626
- package/src/js/pds-core/pds.d.ts +0 -129
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
// Static enums for design system values
|
|
2
|
-
export const enums = {
|
|
3
|
-
FontWeights: {
|
|
4
|
-
light: 300,
|
|
5
|
-
normal: 400,
|
|
6
|
-
medium: 500,
|
|
7
|
-
semibold: 600,
|
|
8
|
-
bold: 700,
|
|
9
|
-
},
|
|
10
|
-
LineHeights: {
|
|
11
|
-
tight: 1.25,
|
|
12
|
-
normal: 1.5,
|
|
13
|
-
relaxed: 1.75,
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
BorderWidths: {
|
|
17
|
-
hairline: 0.5,
|
|
18
|
-
thin: 1,
|
|
19
|
-
medium: 2,
|
|
20
|
-
thick: 3,
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
RadiusSizes: {
|
|
24
|
-
none: 0,
|
|
25
|
-
small: 4,
|
|
26
|
-
medium: 8,
|
|
27
|
-
large: 16,
|
|
28
|
-
xlarge: 24,
|
|
29
|
-
xxlarge: 32
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
ShadowDepths: {
|
|
33
|
-
none: "none",
|
|
34
|
-
light: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
|
35
|
-
medium:
|
|
36
|
-
"0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
|
37
|
-
deep: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",
|
|
38
|
-
extreme: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
|
|
39
|
-
},
|
|
40
|
-
TransitionSpeeds: {
|
|
41
|
-
fast: 150,
|
|
42
|
-
normal: 250,
|
|
43
|
-
slow: 350,
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
AnimationEasings: {
|
|
47
|
-
linear: "linear",
|
|
48
|
-
ease: "ease",
|
|
49
|
-
"ease-in": "ease-in",
|
|
50
|
-
"ease-out": "ease-out",
|
|
51
|
-
"ease-in-out": "ease-in-out",
|
|
52
|
-
bounce: "cubic-bezier(0.68, -0.55, 0.265, 1.55)",
|
|
53
|
-
},
|
|
54
|
-
TouchTargetSizes: {
|
|
55
|
-
compact: 36,
|
|
56
|
-
standard: 44, // iOS/Android accessibility standard
|
|
57
|
-
comfortable: 48,
|
|
58
|
-
spacious: 56,
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
LinkStyles: {
|
|
62
|
-
inline: "inline", // Normal inline text links
|
|
63
|
-
block: "block", // Block-level links
|
|
64
|
-
button: "button", // Button-like links (flex with touch target)
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
FocusStyles: {
|
|
68
|
-
ring: "ring", // Box-shadow ring (default)
|
|
69
|
-
outline: "outline", // Browser outline
|
|
70
|
-
border: "border", // Border change
|
|
71
|
-
glow: "glow", // Subtle glow effect
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
TabSizes: {
|
|
75
|
-
compact: 2,
|
|
76
|
-
standard: 4,
|
|
77
|
-
wide: 8,
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
SelectIcons: {
|
|
81
|
-
chevron: "chevron", // Standard chevron down
|
|
82
|
-
arrow: "arrow", // Simple arrow
|
|
83
|
-
caret: "caret", // Triangle caret
|
|
84
|
-
none: "none", // No icon
|
|
85
|
-
},
|
|
86
|
-
};
|
|
1
|
+
// Static enums for design system values
|
|
2
|
+
export const enums = {
|
|
3
|
+
FontWeights: {
|
|
4
|
+
light: 300,
|
|
5
|
+
normal: 400,
|
|
6
|
+
medium: 500,
|
|
7
|
+
semibold: 600,
|
|
8
|
+
bold: 700,
|
|
9
|
+
},
|
|
10
|
+
LineHeights: {
|
|
11
|
+
tight: 1.25,
|
|
12
|
+
normal: 1.5,
|
|
13
|
+
relaxed: 1.75,
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
BorderWidths: {
|
|
17
|
+
hairline: 0.5,
|
|
18
|
+
thin: 1,
|
|
19
|
+
medium: 2,
|
|
20
|
+
thick: 3,
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
RadiusSizes: {
|
|
24
|
+
none: 0,
|
|
25
|
+
small: 4,
|
|
26
|
+
medium: 8,
|
|
27
|
+
large: 16,
|
|
28
|
+
xlarge: 24,
|
|
29
|
+
xxlarge: 32
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
ShadowDepths: {
|
|
33
|
+
none: "none",
|
|
34
|
+
light: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
|
35
|
+
medium:
|
|
36
|
+
"0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
|
37
|
+
deep: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",
|
|
38
|
+
extreme: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
|
|
39
|
+
},
|
|
40
|
+
TransitionSpeeds: {
|
|
41
|
+
fast: 150,
|
|
42
|
+
normal: 250,
|
|
43
|
+
slow: 350,
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
AnimationEasings: {
|
|
47
|
+
linear: "linear",
|
|
48
|
+
ease: "ease",
|
|
49
|
+
"ease-in": "ease-in",
|
|
50
|
+
"ease-out": "ease-out",
|
|
51
|
+
"ease-in-out": "ease-in-out",
|
|
52
|
+
bounce: "cubic-bezier(0.68, -0.55, 0.265, 1.55)",
|
|
53
|
+
},
|
|
54
|
+
TouchTargetSizes: {
|
|
55
|
+
compact: 36,
|
|
56
|
+
standard: 44, // iOS/Android accessibility standard
|
|
57
|
+
comfortable: 48,
|
|
58
|
+
spacious: 56,
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
LinkStyles: {
|
|
62
|
+
inline: "inline", // Normal inline text links
|
|
63
|
+
block: "block", // Block-level links
|
|
64
|
+
button: "button", // Button-like links (flex with touch target)
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
FocusStyles: {
|
|
68
|
+
ring: "ring", // Box-shadow ring (default)
|
|
69
|
+
outline: "outline", // Browser outline
|
|
70
|
+
border: "border", // Border change
|
|
71
|
+
glow: "glow", // Subtle glow effect
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
TabSizes: {
|
|
75
|
+
compact: 2,
|
|
76
|
+
standard: 4,
|
|
77
|
+
wide: 8,
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
SelectIcons: {
|
|
81
|
+
chevron: "chevron", // Standard chevron down
|
|
82
|
+
arrow: "arrow", // Simple arrow
|
|
83
|
+
caret: "caret", // Triangle caret
|
|
84
|
+
none: "none", // No icon
|
|
85
|
+
},
|
|
86
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { presets } from "./pds-config.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Generator - A JS-config-first design system
|
|
@@ -4987,216 +4987,286 @@ export const ${name}CSS = \`${escapedCSS}\`;
|
|
|
4987
4987
|
`;
|
|
4988
4988
|
}
|
|
4989
4989
|
|
|
4990
|
-
|
|
4991
|
-
* Static method to apply styles to document
|
|
4992
|
-
* Creates a link element with BLOB URL
|
|
4993
|
-
* @param {Generator} [generator] - Optional Generator instance (defaults to singleton)
|
|
4994
|
-
*/
|
|
4995
|
-
static applyStyles(generator) {
|
|
4996
|
-
// Use provided generator or singleton instance
|
|
4997
|
-
const target = generator || Generator.instance;
|
|
4998
|
-
|
|
4999
|
-
// Validate parameter
|
|
5000
|
-
if (!target || typeof target !== "object") {
|
|
5001
|
-
console.error("[Generator] applyStyles requires a generator object or active singleton");
|
|
5002
|
-
return;
|
|
5003
|
-
}
|
|
5004
|
-
|
|
5005
|
-
// Preferred: apply layered CSS so tokens + primitives + components + utilities
|
|
5006
|
-
// are available in light DOM (ensures primitives like :where(button):active apply)
|
|
5007
|
-
const cssText = target.layeredCSS || target.css || "";
|
|
5008
|
-
if (!cssText) {
|
|
5009
|
-
target.options?.log?.(
|
|
5010
|
-
"warn",
|
|
5011
|
-
"[Generator] No CSS available on designer to apply"
|
|
5012
|
-
);
|
|
5013
|
-
return;
|
|
5014
|
-
}
|
|
5015
|
-
|
|
5016
|
-
// Install/update runtime styles atomically to avoid flicker caused by
|
|
5017
|
-
// creating/removing <link> or swapping blob URLs.
|
|
5018
|
-
Generator.installRuntimeStyles(cssText);
|
|
5019
|
-
// if (designer && designer.#blobURLs && designer.options?.debug) {
|
|
5020
|
-
// designer.options?.log?.(
|
|
5021
|
-
// "debug",
|
|
5022
|
-
// "[Generator] Applied live styles via in-place stylesheet"
|
|
5023
|
-
// );
|
|
5024
|
-
// }
|
|
5025
|
-
}
|
|
5026
|
-
|
|
5027
|
-
/**
|
|
5028
|
-
* Install runtime styles for PDS using constructable stylesheets when
|
|
5029
|
-
* available, otherwise update a single <style id="pds-runtime-stylesheet">.
|
|
5030
|
-
* This approach reduces flicker and avoids link/blob swapping.
|
|
5031
|
-
*/
|
|
5032
|
-
static installRuntimeStyles(cssText) {
|
|
5033
|
-
//console.log(cssText);
|
|
5034
|
-
try {
|
|
5035
|
-
if (typeof document === "undefined") return; // server-side guard
|
|
4990
|
+
}
|
|
5036
4991
|
|
|
5037
|
-
// Preferred: constructable stylesheet (fast, atomic)
|
|
5038
|
-
if (
|
|
5039
|
-
typeof CSSStyleSheet !== "undefined" &&
|
|
5040
|
-
"adoptedStyleSheets" in Document.prototype
|
|
5041
|
-
) {
|
|
5042
|
-
const sheet = new CSSStyleSheet();
|
|
5043
|
-
// replaceSync is synchronous and atomic for the stylesheet
|
|
5044
|
-
sheet.replaceSync(cssText);
|
|
5045
4992
|
|
|
5046
|
-
|
|
5047
|
-
|
|
4993
|
+
/**
|
|
4994
|
+
* Validate a design configuration for accessibility sanity checks.
|
|
4995
|
+
* Currently validates color contrast for primary buttons and base surface text
|
|
4996
|
+
* in both light and dark themes.
|
|
4997
|
+
*
|
|
4998
|
+
* @param {object} designConfig - A full or partial PDS config object
|
|
4999
|
+
* @param {object} [options]
|
|
5000
|
+
* @param {number} [options.minContrast=4.5] - Minimum contrast ratio for normal text
|
|
5001
|
+
* @returns {{ ok: boolean, issues: Array<{path:string, message:string, ratio:number, min:number, context?:string}> }}
|
|
5002
|
+
*/
|
|
5003
|
+
export function validateDesign(designConfig = {}, options = {}) {
|
|
5004
|
+
const MIN = Number(options.minContrast || 4.5);
|
|
5048
5005
|
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5006
|
+
// Local helpers (keep public; no dependency on private Generator methods)
|
|
5007
|
+
const hexToRgb = (hex) => {
|
|
5008
|
+
const h = String(hex || "").replace("#", "");
|
|
5009
|
+
const full =
|
|
5010
|
+
h.length === 3
|
|
5011
|
+
? h
|
|
5012
|
+
.split("")
|
|
5013
|
+
.map((c) => c + c)
|
|
5014
|
+
.join("")
|
|
5015
|
+
: h;
|
|
5016
|
+
const num = parseInt(full || "0", 16);
|
|
5017
|
+
return { r: (num >> 16) & 255, g: (num >> 8) & 255, b: num & 255 };
|
|
5018
|
+
};
|
|
5019
|
+
const luminance = (hex) => {
|
|
5020
|
+
const { r, g, b } = hexToRgb(hex);
|
|
5021
|
+
const srgb = [r / 255, g / 255, b / 255].map((v) =>
|
|
5022
|
+
v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4)
|
|
5023
|
+
);
|
|
5024
|
+
return 0.2126 * srgb[0] + 0.7152 * srgb[1] + 0.0722 * srgb[2];
|
|
5025
|
+
};
|
|
5026
|
+
const contrast = (a, b) => {
|
|
5027
|
+
if (!a || !b) return 0;
|
|
5028
|
+
const L1 = luminance(a);
|
|
5029
|
+
const L2 = luminance(b);
|
|
5030
|
+
const lighter = Math.max(L1, L2);
|
|
5031
|
+
const darker = Math.min(L1, L2);
|
|
5032
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
5033
|
+
};
|
|
5053
5034
|
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5035
|
+
const issues = [];
|
|
5036
|
+
try {
|
|
5037
|
+
// Build tokens from the candidate config
|
|
5038
|
+
const gen = new Generator({ design: structuredClone(designConfig) });
|
|
5039
|
+
const c = gen.tokens.colors;
|
|
5040
|
+
|
|
5041
|
+
// Light theme checks - use computed interactive tokens
|
|
5042
|
+
const light = {
|
|
5043
|
+
surfaceBg: c.surface?.base,
|
|
5044
|
+
surfaceText: c.gray?.[900] || "#000000",
|
|
5045
|
+
primaryFill: c.interactive?.light?.fill || c.primary?.[600],
|
|
5046
|
+
primaryText: c.interactive?.light?.text || c.primary?.[600],
|
|
5047
|
+
};
|
|
5058
5048
|
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5049
|
+
// Primary button (light): check button fill with white text
|
|
5050
|
+
const lightBtnRatio = contrast(light.primaryFill, "#ffffff");
|
|
5051
|
+
if (lightBtnRatio < MIN) {
|
|
5052
|
+
issues.push({
|
|
5053
|
+
path: "/colors/primary",
|
|
5054
|
+
message: `Primary button contrast too low in light theme (${lightBtnRatio.toFixed(
|
|
5055
|
+
2
|
|
5056
|
+
)} < ${MIN}). Choose a darker primary.`,
|
|
5057
|
+
ratio: lightBtnRatio,
|
|
5058
|
+
min: MIN,
|
|
5059
|
+
context: "light/btn-primary",
|
|
5060
|
+
});
|
|
5061
|
+
}
|
|
5070
5062
|
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5063
|
+
// Surface text (light): text vs surface base
|
|
5064
|
+
const lightTextRatio = contrast(light.surfaceBg, light.surfaceText);
|
|
5065
|
+
if (lightTextRatio < MIN) {
|
|
5066
|
+
issues.push({
|
|
5067
|
+
path: "/colors/background",
|
|
5068
|
+
message: `Base text contrast on surface (light) is too low (${lightTextRatio.toFixed(
|
|
5069
|
+
2
|
|
5070
|
+
)} < ${MIN}). Adjust background or secondary (gray).`,
|
|
5071
|
+
ratio: lightTextRatio,
|
|
5072
|
+
min: MIN,
|
|
5073
|
+
context: "light/surface-text",
|
|
5074
|
+
});
|
|
5076
5075
|
}
|
|
5077
|
-
}
|
|
5078
|
-
}
|
|
5079
5076
|
|
|
5080
|
-
//
|
|
5081
|
-
|
|
5082
|
-
|
|
5077
|
+
// Primary text for outline/link: check link text on surface
|
|
5078
|
+
const lightOutlineRatio = contrast(light.primaryText, light.surfaceBg);
|
|
5079
|
+
if (lightOutlineRatio < MIN) {
|
|
5080
|
+
issues.push({
|
|
5081
|
+
path: "/colors/primary",
|
|
5082
|
+
message: `Primary text on surface is too low for outline/link styles (light) (${lightOutlineRatio.toFixed(
|
|
5083
|
+
2
|
|
5084
|
+
)} < ${MIN}). Choose a darker primary or lighter surface.`,
|
|
5085
|
+
ratio: lightOutlineRatio,
|
|
5086
|
+
min: MIN,
|
|
5087
|
+
context: "light/outline",
|
|
5088
|
+
});
|
|
5089
|
+
}
|
|
5083
5090
|
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
* @example
|
|
5093
|
-
* // In your web component:
|
|
5094
|
-
* import { PDS } from 'pure-ds';
|
|
5095
|
-
*
|
|
5096
|
-
* async connectedCallback() {
|
|
5097
|
-
* this.attachShadow({ mode: 'open' });
|
|
5098
|
-
*
|
|
5099
|
-
* const componentStyles = new CSSStyleSheet();
|
|
5100
|
-
* componentStyles.replaceSync(`...your styles...`);
|
|
5101
|
-
*
|
|
5102
|
-
* await PDS.adoptPrimitives(this.shadowRoot, [componentStyles]);
|
|
5103
|
-
* }
|
|
5104
|
-
*/
|
|
5105
|
-
export async function adoptPrimitives(shadowRoot, additionalSheets = []) {
|
|
5106
|
-
try {
|
|
5107
|
-
// Get primitives stylesheet (live or static)
|
|
5108
|
-
const primitives = await PDS.registry.getStylesheet("primitives");
|
|
5091
|
+
// Dark theme checks - use computed interactive tokens
|
|
5092
|
+
const d = c.dark;
|
|
5093
|
+
if (d) {
|
|
5094
|
+
const dark = {
|
|
5095
|
+
surfaceBg: d.surface?.base || c.surface?.inverse,
|
|
5096
|
+
primaryFill: c.interactive?.dark?.fill || d.primary?.[600],
|
|
5097
|
+
primaryText: c.interactive?.dark?.text || d.primary?.[600],
|
|
5098
|
+
};
|
|
5109
5099
|
|
|
5110
|
-
|
|
5111
|
-
|
|
5100
|
+
// Primary button (dark): check button fill with white text
|
|
5101
|
+
const darkBtnRatio = contrast(dark.primaryFill, "#ffffff");
|
|
5102
|
+
if (darkBtnRatio < MIN) {
|
|
5103
|
+
issues.push({
|
|
5104
|
+
path: "/colors/darkMode/primary",
|
|
5105
|
+
message: `Primary button contrast too low in dark theme (${darkBtnRatio.toFixed(
|
|
5106
|
+
2
|
|
5107
|
+
)} < ${MIN}). Override darkMode.primary or pick a brighter hue.`,
|
|
5108
|
+
ratio: darkBtnRatio,
|
|
5109
|
+
min: MIN,
|
|
5110
|
+
context: "dark/btn-primary",
|
|
5111
|
+
});
|
|
5112
|
+
}
|
|
5112
5113
|
|
|
5113
|
-
|
|
5114
|
-
const
|
|
5115
|
-
|
|
5114
|
+
// Outline/link style in dark: check link text on dark surface
|
|
5115
|
+
const darkOutlineRatio = contrast(dark.primaryText, dark.surfaceBg);
|
|
5116
|
+
if (darkOutlineRatio < MIN) {
|
|
5117
|
+
issues.push({
|
|
5118
|
+
path: "/colors/darkMode/primary",
|
|
5119
|
+
message: `Primary text on surface is too low for outline/link styles (dark) (${darkOutlineRatio.toFixed(
|
|
5120
|
+
2
|
|
5121
|
+
)} < ${MIN}). Override darkMode.primary/background.`,
|
|
5122
|
+
ratio: darkOutlineRatio,
|
|
5123
|
+
min: MIN,
|
|
5124
|
+
context: "dark/outline",
|
|
5125
|
+
});
|
|
5126
|
+
}
|
|
5116
5127
|
}
|
|
5117
|
-
} catch (
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
);
|
|
5124
|
-
// Continue with just additional sheets as fallback
|
|
5125
|
-
shadowRoot.adoptedStyleSheets = additionalSheets;
|
|
5128
|
+
} catch (err) {
|
|
5129
|
+
issues.push({
|
|
5130
|
+
path: "/",
|
|
5131
|
+
message: `Validation failed: ${String(err?.message || err)}`,
|
|
5132
|
+
ratio: 0,
|
|
5133
|
+
min: 0,
|
|
5134
|
+
});
|
|
5126
5135
|
}
|
|
5136
|
+
|
|
5137
|
+
return { ok: issues.length === 0, issues };
|
|
5127
5138
|
}
|
|
5128
5139
|
|
|
5129
5140
|
/**
|
|
5130
|
-
*
|
|
5131
|
-
*
|
|
5141
|
+
* Validate multiple design configurations at once.
|
|
5142
|
+
* Useful for build-time enforcement of preset compliance.
|
|
5132
5143
|
*
|
|
5133
|
-
* @param {
|
|
5134
|
-
* @param {
|
|
5135
|
-
* @
|
|
5136
|
-
* @returns {Promise<void>}
|
|
5144
|
+
* @param {Array<object>} designs - Array of design configs; items may include an optional `name` property.
|
|
5145
|
+
* @param {object} [options] - Options forwarded to validateDesign (e.g., { minContrast })
|
|
5146
|
+
* @returns {{ ok: boolean, results: Array<{ name?: string, ok: boolean, issues: Array<{path:string, message:string, ratio:number, min:number, context?:string}> }> }}
|
|
5137
5147
|
*/
|
|
5138
|
-
export
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5148
|
+
export function validateDesigns(designs = [], options = {}) {
|
|
5149
|
+
const results = [];
|
|
5150
|
+
|
|
5151
|
+
const list = Array.isArray(designs)
|
|
5152
|
+
? designs
|
|
5153
|
+
: designs && typeof designs === "object"
|
|
5154
|
+
? Object.values(designs)
|
|
5155
|
+
: [];
|
|
5156
|
+
|
|
5157
|
+
for (const item of list) {
|
|
5158
|
+
let name;
|
|
5159
|
+
let configToValidate = null;
|
|
5160
|
+
|
|
5161
|
+
// Accept a few shapes:
|
|
5162
|
+
// - string => treat as preset id/name
|
|
5163
|
+
// - { preset, design?, name? } => resolve preset then merge overrides
|
|
5164
|
+
// - full config object (legacy) => validate directly
|
|
5165
|
+
if (typeof item === "string") {
|
|
5166
|
+
const id = String(item).toLowerCase();
|
|
5167
|
+
const found =
|
|
5168
|
+
presets?.[id] ||
|
|
5169
|
+
Object.values(presets || {}).find(
|
|
5170
|
+
(p) =>
|
|
5171
|
+
__slugify(p.name) === id ||
|
|
5172
|
+
String(p.name || "").toLowerCase() === id
|
|
5173
|
+
);
|
|
5174
|
+
if (!found) {
|
|
5175
|
+
results.push({
|
|
5176
|
+
name: item,
|
|
5177
|
+
ok: false,
|
|
5178
|
+
issues: [
|
|
5179
|
+
{
|
|
5180
|
+
path: "/",
|
|
5181
|
+
message: `Preset not found: ${item}`,
|
|
5182
|
+
ratio: 0,
|
|
5183
|
+
min: 0,
|
|
5184
|
+
},
|
|
5185
|
+
],
|
|
5186
|
+
});
|
|
5187
|
+
continue;
|
|
5188
|
+
}
|
|
5189
|
+
name = found.name || id;
|
|
5190
|
+
configToValidate = structuredClone(found);
|
|
5191
|
+
} else if (item && typeof item === "object") {
|
|
5192
|
+
name = item.name || item.preset || undefined;
|
|
5193
|
+
if ("preset" in item || "design" in item) {
|
|
5194
|
+
const effectivePreset = String(item.preset || "default").toLowerCase();
|
|
5195
|
+
const found =
|
|
5196
|
+
presets?.[effectivePreset] ||
|
|
5197
|
+
Object.values(presets || {}).find(
|
|
5198
|
+
(p) =>
|
|
5199
|
+
__slugify(p.name) === effectivePreset ||
|
|
5200
|
+
String(p.name || "").toLowerCase() === effectivePreset
|
|
5201
|
+
);
|
|
5202
|
+
if (!found) {
|
|
5203
|
+
results.push({
|
|
5204
|
+
name,
|
|
5205
|
+
ok: false,
|
|
5206
|
+
issues: [
|
|
5207
|
+
{
|
|
5208
|
+
path: "/",
|
|
5209
|
+
message: `Preset not found: ${item.preset}`,
|
|
5210
|
+
ratio: 0,
|
|
5211
|
+
min: 0,
|
|
5212
|
+
},
|
|
5213
|
+
],
|
|
5214
|
+
});
|
|
5215
|
+
continue;
|
|
5162
5216
|
}
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5217
|
+
let base = structuredClone(found);
|
|
5218
|
+
if (item.design && typeof item.design === "object") {
|
|
5219
|
+
base = __deepMerge(base, structuredClone(item.design));
|
|
5220
|
+
}
|
|
5221
|
+
configToValidate = base;
|
|
5222
|
+
} else {
|
|
5223
|
+
// Assume a full config object
|
|
5224
|
+
configToValidate = item;
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
|
|
5228
|
+
if (!configToValidate) {
|
|
5229
|
+
results.push({
|
|
5230
|
+
name,
|
|
5231
|
+
ok: false,
|
|
5232
|
+
issues: [
|
|
5233
|
+
{ path: "/", message: "Invalid design entry", ratio: 0, min: 0 },
|
|
5234
|
+
],
|
|
5235
|
+
});
|
|
5236
|
+
continue;
|
|
5237
|
+
}
|
|
5166
5238
|
|
|
5167
|
-
|
|
5168
|
-
|
|
5239
|
+
const { ok, issues } = validateDesign(configToValidate, options);
|
|
5240
|
+
results.push({ name, ok, issues });
|
|
5241
|
+
}
|
|
5169
5242
|
|
|
5170
|
-
|
|
5171
|
-
|
|
5243
|
+
return { ok: results.every((r) => r.ok), results };
|
|
5244
|
+
}
|
|
5172
5245
|
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5246
|
+
// Internal: deep merge utility (arrays replace; objects merge)
|
|
5247
|
+
function __deepMerge(target = {}, source = {}) {
|
|
5248
|
+
if (!source || typeof source !== "object") return target;
|
|
5249
|
+
const out = Array.isArray(target) ? [...target] : { ...target };
|
|
5250
|
+
for (const [key, value] of Object.entries(source)) {
|
|
5251
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
5252
|
+
out[key] = __deepMerge(
|
|
5253
|
+
out[key] && typeof out[key] === "object" ? out[key] : {},
|
|
5254
|
+
value
|
|
5255
|
+
);
|
|
5256
|
+
} else {
|
|
5257
|
+
out[key] = value;
|
|
5176
5258
|
}
|
|
5177
|
-
} catch (error) {
|
|
5178
|
-
const componentName = shadowRoot.host?.tagName?.toLowerCase() || "unknown";
|
|
5179
|
-
// No access to config in this context, fall back to console
|
|
5180
|
-
console.error(
|
|
5181
|
-
`[PDS Adopter] <${componentName}> failed to adopt layers:`,
|
|
5182
|
-
error
|
|
5183
|
-
);
|
|
5184
|
-
// Continue with just additional sheets as fallback
|
|
5185
|
-
shadowRoot.adoptedStyleSheets = additionalSheets;
|
|
5186
5259
|
}
|
|
5260
|
+
return out;
|
|
5187
5261
|
}
|
|
5188
5262
|
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
export function createStylesheet(css) {
|
|
5197
|
-
const sheet = new CSSStyleSheet();
|
|
5198
|
-
sheet.replaceSync(css);
|
|
5199
|
-
return sheet;
|
|
5263
|
+
// Internal: create a slug for matching names like "Paper & Ink" -> "paper-and-ink"
|
|
5264
|
+
function __slugify(str = "") {
|
|
5265
|
+
return String(str)
|
|
5266
|
+
.toLowerCase()
|
|
5267
|
+
.replace(/&/g, " and ")
|
|
5268
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
5269
|
+
.replace(/^-+|-+$/g, "");
|
|
5200
5270
|
}
|
|
5201
5271
|
|
|
5202
5272
|
|