@pure-ds/core 0.6.9 → 0.6.11
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/custom-elements.json +865 -35
- package/dist/types/pds.d.ts +31 -0
- package/dist/types/public/assets/js/pds-manager.d.ts +100 -2
- package/dist/types/public/assets/js/pds-manager.d.ts.map +1 -1
- package/dist/types/public/assets/js/pds.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-form.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-live-converter.d.ts +8 -0
- package/dist/types/public/assets/pds/components/pds-live-converter.d.ts.map +1 -0
- package/dist/types/public/assets/pds/components/pds-live-edit.d.ts +1 -195
- package/dist/types/public/assets/pds/components/pds-live-edit.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-live-importer.d.ts +2 -0
- package/dist/types/public/assets/pds/components/pds-live-importer.d.ts.map +1 -0
- package/dist/types/public/assets/pds/components/pds-live-template-canvas.d.ts +2 -0
- package/dist/types/public/assets/pds/components/pds-live-template-canvas.d.ts.map +1 -0
- package/dist/types/public/assets/pds/components/pds-omnibox.d.ts +0 -2
- package/dist/types/public/assets/pds/components/pds-omnibox.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts +20 -0
- package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-toaster.d.ts +1 -1
- package/dist/types/public/assets/pds/components/pds-toaster.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-treeview.d.ts +37 -0
- package/dist/types/public/assets/pds/components/pds-treeview.d.ts.map +1 -0
- package/dist/types/src/js/common/toast.d.ts +8 -0
- package/dist/types/src/js/common/toast.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-config.d.ts +1306 -13
- package/dist/types/src/js/pds-core/pds-config.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-enhancers-meta.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-enhancers.d.ts.map +1 -1
- 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 +2 -1
- package/dist/types/src/js/pds-core/pds-live.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-ontology.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-start-helpers.d.ts +1 -4
- package/dist/types/src/js/pds-core/pds-start-helpers.d.ts.map +1 -1
- package/dist/types/src/js/pds-live-manager/conversion-service.d.ts +66 -0
- package/dist/types/src/js/pds-live-manager/conversion-service.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-manager/import-contract.d.ts +15 -0
- package/dist/types/src/js/pds-live-manager/import-contract.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-manager/import-history-service.d.ts +32 -0
- package/dist/types/src/js/pds-live-manager/import-history-service.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-manager/import-service.d.ts +21 -0
- package/dist/types/src/js/pds-live-manager/import-service.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-manager/template-service.d.ts +17 -0
- package/dist/types/src/js/pds-live-manager/template-service.d.ts.map +1 -0
- package/dist/types/src/js/pds-manager.d.ts +4 -0
- package/dist/types/src/js/pds.d.ts.map +1 -1
- package/package.json +7 -3
- package/packages/pds-cli/README.md +51 -0
- package/packages/pds-cli/bin/pds-import.js +176 -0
- package/packages/pds-cli/bin/pds-static.js +31 -1
- package/packages/pds-cli/bin/postinstall.mjs +17 -8
- package/public/assets/js/app.js +23 -147
- package/public/assets/js/pds-manager.js +481 -248
- package/public/assets/js/pds.js +16 -16
- package/public/assets/pds/components/pds-form.js +124 -27
- package/public/assets/pds/components/pds-live-converter.js +47 -0
- package/public/assets/pds/components/pds-live-edit.js +1626 -211
- package/public/assets/pds/components/pds-live-importer.js +772 -0
- package/public/assets/pds/components/pds-live-template-canvas.js +171 -0
- package/public/assets/pds/components/pds-omnibox.js +146 -20
- package/public/assets/pds/components/pds-scrollrow.js +56 -1
- package/public/assets/pds/components/pds-toaster.js +50 -5
- package/public/assets/pds/components/pds-treeview.js +972 -0
- package/public/assets/pds/custom-elements.json +865 -35
- package/public/assets/pds/pds-css-complete.json +7 -7
- package/public/assets/pds/pds.css-data.json +5 -35
- package/public/assets/pds/templates/commerce-scroll-explorer.html +115 -0
- package/public/assets/pds/templates/content-brand-showcase.html +110 -0
- package/public/assets/pds/templates/feedback-ops-dashboard.html +91 -0
- package/public/assets/pds/templates/release-readiness-radar.html +69 -0
- package/public/assets/pds/templates/support-command-center.html +92 -0
- package/public/assets/pds/templates/templates.json +53 -0
- package/public/assets/pds/templates/workspace-settings-lab.html +131 -0
- package/public/assets/pds/vscode-custom-data.json +54 -4
- package/readme.md +34 -0
- package/src/js/pds-core/pds-config.js +831 -40
- package/src/js/pds-core/pds-enhancers-meta.js +11 -0
- package/src/js/pds-core/pds-enhancers.js +259 -5
- package/src/js/pds-core/pds-generator.js +353 -52
- package/src/js/pds-core/pds-live.js +630 -15
- package/src/js/pds-core/pds-ontology.js +6 -0
- package/src/js/pds-core/pds-start-helpers.js +14 -6
- package/src/js/pds-live-manager/conversion-service.js +3136 -0
- package/src/js/pds-live-manager/import-contract.js +57 -0
- package/src/js/pds-live-manager/import-history-service.js +145 -0
- package/src/js/pds-live-manager/import-service.js +255 -0
- package/src/js/pds-live-manager/tailwind-conversion-rules.json +383 -0
- package/src/js/pds-live-manager/template-service.js +170 -0
- package/src/js/pds.d.ts +31 -0
- package/src/js/pds.js +71 -60
|
@@ -689,14 +689,16 @@ export class Generator {
|
|
|
689
689
|
const validBase = Number.isFinite(Number(baseBorderWidth))
|
|
690
690
|
? Number(baseBorderWidth)
|
|
691
691
|
: enums.BorderWidths.medium;
|
|
692
|
-
|
|
692
|
+
// Snap to whole CSS pixels to avoid subpixel border widths that can render
|
|
693
|
+
// identically across browsers/DPIs (e.g. 0.5px and 1.5px both appearing as 1px).
|
|
694
|
+
const toRenderablePx = (value) => `${Math.max(1, Math.ceil(value))}px`;
|
|
693
695
|
|
|
694
696
|
// Generate a derived border width scale based on configured base width
|
|
695
697
|
return {
|
|
696
|
-
hairline:
|
|
697
|
-
thin:
|
|
698
|
-
medium:
|
|
699
|
-
thick:
|
|
698
|
+
hairline: toRenderablePx(validBase * 0.25),
|
|
699
|
+
thin: toRenderablePx(validBase * 0.5),
|
|
700
|
+
medium: toRenderablePx(validBase),
|
|
701
|
+
thick: toRenderablePx(validBase * 1.5),
|
|
700
702
|
};
|
|
701
703
|
}
|
|
702
704
|
|
|
@@ -805,7 +807,6 @@ export class Generator {
|
|
|
805
807
|
|
|
806
808
|
#generateLayoutTokens(layoutConfig) {
|
|
807
809
|
const {
|
|
808
|
-
maxWidth = 1200,
|
|
809
810
|
containerPadding = 16,
|
|
810
811
|
breakpoints = {
|
|
811
812
|
sm: 640,
|
|
@@ -815,10 +816,19 @@ export class Generator {
|
|
|
815
816
|
},
|
|
816
817
|
} = layoutConfig;
|
|
817
818
|
|
|
818
|
-
const
|
|
819
|
+
const hasExplicitMaxWidth =
|
|
820
|
+
this.#hasDefinedConfigValue(layoutConfig, "maxWidth");
|
|
821
|
+
|
|
822
|
+
const explicitMaxWidthValue = layoutConfig.maxWidth;
|
|
823
|
+
|
|
824
|
+
const resolvedMaxWidths = this.#resolveLayoutMaxWidths(layoutConfig, {
|
|
825
|
+
emitFallbacks: false,
|
|
826
|
+
});
|
|
819
827
|
|
|
820
828
|
return {
|
|
821
|
-
maxWidth:
|
|
829
|
+
maxWidth: hasExplicitMaxWidth
|
|
830
|
+
? this.#formatLength(explicitMaxWidthValue, "1200px")
|
|
831
|
+
: undefined,
|
|
822
832
|
maxWidthSm: resolvedMaxWidths.sm,
|
|
823
833
|
maxWidthMd: resolvedMaxWidths.md,
|
|
824
834
|
maxWidthLg: resolvedMaxWidths.lg,
|
|
@@ -841,7 +851,8 @@ export class Generator {
|
|
|
841
851
|
};
|
|
842
852
|
}
|
|
843
853
|
|
|
844
|
-
#resolveLayoutMaxWidths(layoutConfig = {}) {
|
|
854
|
+
#resolveLayoutMaxWidths(layoutConfig = {}, options = {}) {
|
|
855
|
+
const { emitFallbacks = true } = options;
|
|
845
856
|
const defaultBreakpoints = {
|
|
846
857
|
sm: 640,
|
|
847
858
|
md: 768,
|
|
@@ -849,15 +860,29 @@ export class Generator {
|
|
|
849
860
|
xl: 1280,
|
|
850
861
|
};
|
|
851
862
|
|
|
852
|
-
const {
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
863
|
+
const { maxWidths = {}, containerPadding = 16, breakpoints = defaultBreakpoints } =
|
|
864
|
+
layoutConfig || {};
|
|
865
|
+
|
|
866
|
+
const hasExplicitMaxWidth =
|
|
867
|
+
this.#hasDefinedConfigValue(layoutConfig, "maxWidth");
|
|
868
|
+
|
|
869
|
+
const hasExplicitMaxWidths = ["sm", "md", "lg", "xl"].some((key) =>
|
|
870
|
+
this.#hasDefinedConfigValue(maxWidths, key),
|
|
871
|
+
);
|
|
872
|
+
|
|
873
|
+
if (!emitFallbacks && !hasExplicitMaxWidth && !hasExplicitMaxWidths) {
|
|
874
|
+
return {
|
|
875
|
+
sm: undefined,
|
|
876
|
+
md: undefined,
|
|
877
|
+
lg: undefined,
|
|
878
|
+
xl: undefined,
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
const maxWidthValue = layoutConfig?.maxWidth;
|
|
858
883
|
|
|
859
884
|
const paddingValue = this.#toNumber(containerPadding, 16);
|
|
860
|
-
const baseMaxWidth = this.#toNumber(
|
|
885
|
+
const baseMaxWidth = this.#toNumber(maxWidthValue, defaultBreakpoints.xl);
|
|
861
886
|
|
|
862
887
|
const resolvedBreakpoints = {
|
|
863
888
|
sm: this.#toNumber(breakpoints.sm, defaultBreakpoints.sm),
|
|
@@ -888,6 +913,15 @@ export class Generator {
|
|
|
888
913
|
};
|
|
889
914
|
}
|
|
890
915
|
|
|
916
|
+
#hasDefinedConfigValue(source, key) {
|
|
917
|
+
if (!source || typeof source !== "object") return false;
|
|
918
|
+
if (!Object.prototype.hasOwnProperty.call(source, key)) return false;
|
|
919
|
+
const value = source[key];
|
|
920
|
+
if (value === undefined || value === null) return false;
|
|
921
|
+
if (typeof value === "string" && value.trim().length === 0) return false;
|
|
922
|
+
return true;
|
|
923
|
+
}
|
|
924
|
+
|
|
891
925
|
#formatLength(value, fallback) {
|
|
892
926
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
893
927
|
return `${value}px`;
|
|
@@ -1186,6 +1220,10 @@ export class Generator {
|
|
|
1186
1220
|
// Convert camelCase keys to kebab-case
|
|
1187
1221
|
const kebabKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
1188
1222
|
|
|
1223
|
+
if (value === undefined || value === null) {
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1189
1227
|
// Skip breakpoints object - it's used in JS but doesn't belong in CSS variables
|
|
1190
1228
|
// Breakpoints are used in @media queries, not as CSS custom properties
|
|
1191
1229
|
if (key === "breakpoints") {
|
|
@@ -1279,7 +1317,7 @@ export class Generator {
|
|
|
1279
1317
|
smartLines.push(`\n`);
|
|
1280
1318
|
}
|
|
1281
1319
|
|
|
1282
|
-
const semantic = ` --color-text-primary: var(--color-gray-100);\n --color-text-secondary: var(--color-gray-300);\n --color-text-muted: var(--color-gray-
|
|
1320
|
+
const semantic = ` --color-text-primary: var(--color-gray-100);\n --color-text-secondary: var(--color-gray-300);\n --color-text-muted: var(--color-gray-600);\n --color-border: var(--color-gray-700);\n --color-input-bg: var(--color-gray-800);\n --color-input-disabled-bg: var(--color-gray-900);\n --color-input-disabled-text: var(--color-gray-600);\n --color-code-bg: var(--color-gray-800);\n`;
|
|
1283
1321
|
|
|
1284
1322
|
const backdrop = ` /* Backdrop tokens - dark mode */\n --backdrop-bg: linear-gradient(\n 135deg,\n rgba(0, 0, 0, 0.6),\n rgba(0, 0, 0, 0.4)\n );\n --backdrop-blur: 10px;\n --backdrop-saturate: 120%;\n --backdrop-brightness: 0.7;\n --backdrop-filter: blur(var(--backdrop-blur)) saturate(var(--backdrop-saturate)) brightness(var(--backdrop-brightness));\n --backdrop-opacity: 1;\n \n /* Legacy alias for backwards compatibility */\n --backdrop-background: var(--backdrop-bg);\n`;
|
|
1285
1323
|
|
|
@@ -1377,7 +1415,7 @@ export class Generator {
|
|
|
1377
1415
|
const semantic = [
|
|
1378
1416
|
` --color-text-primary: var(--color-gray-100);\n`,
|
|
1379
1417
|
` --color-text-secondary: var(--color-gray-300);\n`,
|
|
1380
|
-
` --color-text-muted: var(--color-gray-
|
|
1418
|
+
` --color-text-muted: var(--color-gray-600);\n`,
|
|
1381
1419
|
` --color-border: var(--color-gray-700);\n`,
|
|
1382
1420
|
` --color-input-bg: var(--color-gray-800);\n`,
|
|
1383
1421
|
` --color-input-disabled-bg: var(--color-gray-900);\n`,
|
|
@@ -1605,7 +1643,7 @@ html[data-theme="dark"] .liquid-glass {
|
|
|
1605
1643
|
.border-gradient {
|
|
1606
1644
|
border: var(--border-width-medium) solid transparent;
|
|
1607
1645
|
background:
|
|
1608
|
-
linear-gradient(var(--color-surface-base), var(--color-surface-base)) padding-box,
|
|
1646
|
+
linear-gradient(var(--border-gradient-fill, var(--color-surface-base)), var(--border-gradient-fill, var(--color-surface-base))) padding-box,
|
|
1609
1647
|
linear-gradient(var(--gradient-angle, 135deg),
|
|
1610
1648
|
var(--color-primary-400),
|
|
1611
1649
|
var(--color-accent-400)
|
|
@@ -1616,7 +1654,7 @@ html[data-theme="dark"] .liquid-glass {
|
|
|
1616
1654
|
.border-gradient-primary {
|
|
1617
1655
|
border: var(--border-width-medium) solid transparent;
|
|
1618
1656
|
background:
|
|
1619
|
-
linear-gradient(var(--color-surface-base), var(--color-surface-base)) padding-box,
|
|
1657
|
+
linear-gradient(var(--border-gradient-fill, var(--color-surface-base)), var(--border-gradient-fill, var(--color-surface-base))) padding-box,
|
|
1620
1658
|
linear-gradient(var(--gradient-angle, 135deg),
|
|
1621
1659
|
var(--color-primary-300),
|
|
1622
1660
|
var(--color-primary-600)
|
|
@@ -1626,7 +1664,7 @@ html[data-theme="dark"] .liquid-glass {
|
|
|
1626
1664
|
.border-gradient-accent {
|
|
1627
1665
|
border: var(--border-width-medium) solid transparent;
|
|
1628
1666
|
background:
|
|
1629
|
-
linear-gradient(var(--color-surface-base), var(--color-surface-base)) padding-box,
|
|
1667
|
+
linear-gradient(var(--border-gradient-fill, var(--color-surface-base)), var(--border-gradient-fill, var(--color-surface-base))) padding-box,
|
|
1630
1668
|
linear-gradient(var(--gradient-angle, 135deg),
|
|
1631
1669
|
var(--color-accent-300),
|
|
1632
1670
|
var(--color-accent-600)
|
|
@@ -1636,7 +1674,7 @@ html[data-theme="dark"] .liquid-glass {
|
|
|
1636
1674
|
.border-gradient-secondary {
|
|
1637
1675
|
border: var(--border-width-medium) solid transparent;
|
|
1638
1676
|
background:
|
|
1639
|
-
linear-gradient(var(--color-surface-base), var(--color-surface-base)) padding-box,
|
|
1677
|
+
linear-gradient(var(--border-gradient-fill, var(--color-surface-base)), var(--border-gradient-fill, var(--color-surface-base))) padding-box,
|
|
1640
1678
|
linear-gradient(var(--gradient-angle, 135deg),
|
|
1641
1679
|
var(--color-secondary-300),
|
|
1642
1680
|
var(--color-secondary-600)
|
|
@@ -1647,7 +1685,7 @@ html[data-theme="dark"] .liquid-glass {
|
|
|
1647
1685
|
.border-gradient-soft {
|
|
1648
1686
|
border: var(--border-width-thin) solid transparent;
|
|
1649
1687
|
background:
|
|
1650
|
-
linear-gradient(var(--color-surface-base), var(--color-surface-base)) padding-box,
|
|
1688
|
+
linear-gradient(var(--border-gradient-fill, var(--color-surface-base)), var(--border-gradient-fill, var(--color-surface-base))) padding-box,
|
|
1651
1689
|
linear-gradient(var(--gradient-angle, 135deg),
|
|
1652
1690
|
var(--color-primary-400),
|
|
1653
1691
|
var(--color-accent-400)
|
|
@@ -1657,7 +1695,7 @@ html[data-theme="dark"] .liquid-glass {
|
|
|
1657
1695
|
.border-gradient-medium {
|
|
1658
1696
|
border: var(--border-width-medium) solid transparent;
|
|
1659
1697
|
background:
|
|
1660
|
-
linear-gradient(var(--color-surface-base), var(--color-surface-base)) padding-box,
|
|
1698
|
+
linear-gradient(var(--border-gradient-fill, var(--color-surface-base)), var(--border-gradient-fill, var(--color-surface-base))) padding-box,
|
|
1661
1699
|
linear-gradient(var(--gradient-angle, 135deg),
|
|
1662
1700
|
var(--color-primary-400),
|
|
1663
1701
|
var(--color-accent-400)
|
|
@@ -1667,7 +1705,7 @@ html[data-theme="dark"] .liquid-glass {
|
|
|
1667
1705
|
.border-gradient-strong {
|
|
1668
1706
|
border: var(--border-width-thick) solid transparent;
|
|
1669
1707
|
background:
|
|
1670
|
-
linear-gradient(var(--color-surface-base), var(--color-surface-base)) padding-box,
|
|
1708
|
+
linear-gradient(var(--border-gradient-fill, var(--color-surface-base)), var(--border-gradient-fill, var(--color-surface-base))) padding-box,
|
|
1671
1709
|
linear-gradient(var(--gradient-angle, 135deg),
|
|
1672
1710
|
var(--color-primary-400),
|
|
1673
1711
|
var(--color-accent-400)
|
|
@@ -1691,7 +1729,7 @@ html[data-theme="dark"] .liquid-glass {
|
|
|
1691
1729
|
.border-gradient-glow {
|
|
1692
1730
|
border: var(--border-width-medium) solid transparent;
|
|
1693
1731
|
background:
|
|
1694
|
-
linear-gradient(var(--color-surface-base), var(--color-surface-base)) padding-box,
|
|
1732
|
+
linear-gradient(var(--border-gradient-fill, var(--color-surface-base)), var(--border-gradient-fill, var(--color-surface-base))) padding-box,
|
|
1695
1733
|
linear-gradient(135deg,
|
|
1696
1734
|
var(--color-primary-400),
|
|
1697
1735
|
var(--color-accent-400)
|
|
@@ -1945,7 +1983,7 @@ html[data-theme="dark"] .liquid-glass {
|
|
|
1945
1983
|
#generateFormStyles() {
|
|
1946
1984
|
const {
|
|
1947
1985
|
shape = {},
|
|
1948
|
-
|
|
1986
|
+
spatialRhythm = {},
|
|
1949
1987
|
inputPadding,
|
|
1950
1988
|
buttonPadding,
|
|
1951
1989
|
focusRingWidth,
|
|
@@ -1963,14 +2001,15 @@ html[data-theme="dark"] .liquid-glass {
|
|
|
1963
2001
|
? (enums.BorderWidths[shape.borderWidth] ?? null)
|
|
1964
2002
|
: null;
|
|
1965
2003
|
|
|
1966
|
-
const inputPaddingValue = inputPadding
|
|
1967
|
-
const buttonPaddingValue =
|
|
2004
|
+
const inputPaddingValue = spatialRhythm.inputPadding ?? inputPadding ?? 0.75;
|
|
2005
|
+
const buttonPaddingValue =
|
|
2006
|
+
spatialRhythm.buttonPadding ?? buttonPadding ?? 1.0;
|
|
1968
2007
|
const focusWidth = focusRingWidth || 3;
|
|
1969
2008
|
const borderWidth =
|
|
1970
2009
|
borderWidthThin || shapeBorderWidth || enums.BorderWidths.thin;
|
|
1971
|
-
const
|
|
1972
|
-
|
|
1973
|
-
const minButtonHeight = buttonMinHeight ||
|
|
2010
|
+
const sectionSpacingValue =
|
|
2011
|
+
spatialRhythm.sectionSpacing ?? sectionSpacing ?? 2.0;
|
|
2012
|
+
const minButtonHeight = buttonMinHeight || 30;
|
|
1974
2013
|
const minInputHeight = inputMinHeight || 40;
|
|
1975
2014
|
|
|
1976
2015
|
return /*css*/ `/* Mobile-First Form Styles - Generated from Design Config */
|
|
@@ -2235,24 +2274,31 @@ input[type="range"]:active::-moz-range-thumb {
|
|
|
2235
2274
|
|
|
2236
2275
|
input[type="color"] {
|
|
2237
2276
|
-webkit-appearance: none;
|
|
2277
|
+
appearance: none;
|
|
2238
2278
|
padding: 0;
|
|
2239
|
-
width:
|
|
2240
|
-
height:
|
|
2241
|
-
|
|
2242
|
-
|
|
2279
|
+
width: calc(var(--spacing-8) + var(--spacing-1));
|
|
2280
|
+
height: calc(var(--spacing-8) + var(--spacing-1));
|
|
2281
|
+
min-height: auto;
|
|
2282
|
+
border-radius: var(--radius-sm);
|
|
2283
|
+
border: var(--border-width-thin) solid var(--color-border);
|
|
2284
|
+
overflow: hidden;
|
|
2243
2285
|
cursor: pointer;
|
|
2286
|
+
background: transparent;
|
|
2244
2287
|
|
|
2245
|
-
/* The wrapper */
|
|
2246
2288
|
&::-webkit-color-swatch-wrapper {
|
|
2247
2289
|
padding: 0;
|
|
2248
2290
|
border-radius: inherit;
|
|
2249
2291
|
}
|
|
2250
2292
|
|
|
2251
|
-
/* The swatch (the actual color box) */
|
|
2252
2293
|
&::-webkit-color-swatch {
|
|
2253
2294
|
border: none;
|
|
2254
2295
|
border-radius: inherit;
|
|
2255
2296
|
}
|
|
2297
|
+
|
|
2298
|
+
&::-moz-color-swatch {
|
|
2299
|
+
border: none;
|
|
2300
|
+
border-radius: inherit;
|
|
2301
|
+
}
|
|
2256
2302
|
}
|
|
2257
2303
|
|
|
2258
2304
|
/* Button-style checkbox inputs outside of fieldsets */
|
|
@@ -2555,6 +2601,116 @@ label[data-toggle] {
|
|
|
2555
2601
|
}
|
|
2556
2602
|
}
|
|
2557
2603
|
|
|
2604
|
+
/* Color input enhancement shell - applied by enhanceColorInput on label[data-color] */
|
|
2605
|
+
label[data-color] {
|
|
2606
|
+
display: grid;
|
|
2607
|
+
gap: var(--spacing-2);
|
|
2608
|
+
|
|
2609
|
+
.color-control {
|
|
2610
|
+
display: inline-flex;
|
|
2611
|
+
align-items: center;
|
|
2612
|
+
gap: var(--spacing-3);
|
|
2613
|
+
width: fit-content;
|
|
2614
|
+
min-height: var(--input-min-height, 40px);
|
|
2615
|
+
padding: var(--spacing-2) var(--spacing-3);
|
|
2616
|
+
border: var(--border-width-thin) solid var(--color-border);
|
|
2617
|
+
border-radius: var(--radius-md);
|
|
2618
|
+
background: var(--color-surface-base);
|
|
2619
|
+
color: var(--color-text-primary);
|
|
2620
|
+
transition: border-color var(--transition-fast), box-shadow var(--transition-fast), background-color var(--transition-fast);
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
.color-control .color-swatch {
|
|
2624
|
+
position: relative;
|
|
2625
|
+
display: inline-flex;
|
|
2626
|
+
width: calc(var(--spacing-8) + var(--spacing-1));
|
|
2627
|
+
height: calc(var(--spacing-8) + var(--spacing-1));
|
|
2628
|
+
border-radius: var(--radius-sm);
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
.color-control output {
|
|
2632
|
+
margin: 0;
|
|
2633
|
+
min-width: 8ch;
|
|
2634
|
+
font-family: var(--font-family-mono);
|
|
2635
|
+
font-size: var(--font-size-sm);
|
|
2636
|
+
line-height: var(--font-line-height-tight);
|
|
2637
|
+
color: var(--color-text-secondary);
|
|
2638
|
+
text-transform: lowercase;
|
|
2639
|
+
}
|
|
2640
|
+
|
|
2641
|
+
.color-control[data-unset="1"] output {
|
|
2642
|
+
font-style: italic;
|
|
2643
|
+
color: var(--color-text-muted);
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2646
|
+
.color-control input[type="color"] {
|
|
2647
|
+
width: calc(var(--spacing-8) + var(--spacing-1));
|
|
2648
|
+
height: calc(var(--spacing-8) + var(--spacing-1));
|
|
2649
|
+
border-radius: var(--radius-sm);
|
|
2650
|
+
border: var(--border-width-thin) solid var(--color-border);
|
|
2651
|
+
background: transparent;
|
|
2652
|
+
padding: 0;
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
.color-control input[type="color"]::-webkit-color-swatch {
|
|
2656
|
+
border: none;
|
|
2657
|
+
border-radius: calc(var(--radius-sm) - var(--border-width-thin));
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
.color-control input[type="color"]::-moz-color-swatch {
|
|
2661
|
+
border: none;
|
|
2662
|
+
border-radius: calc(var(--radius-sm) - var(--border-width-thin));
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
.color-control .color-swatch[data-unset="1"]::after {
|
|
2666
|
+
content: "";
|
|
2667
|
+
position: absolute;
|
|
2668
|
+
inset: 0;
|
|
2669
|
+
border-radius: var(--radius-sm);
|
|
2670
|
+
border: var(--border-width-thin) solid var(--color-border);
|
|
2671
|
+
background-color: color-mix(in oklab, var(--color-surface-subtle) 78%, var(--color-text-primary) 22%);
|
|
2672
|
+
background-image:
|
|
2673
|
+
linear-gradient(
|
|
2674
|
+
45deg,
|
|
2675
|
+
color-mix(in oklab, var(--color-surface-base) 88%, var(--color-text-primary) 12%) 25%,
|
|
2676
|
+
transparent 25%,
|
|
2677
|
+
transparent 75%,
|
|
2678
|
+
color-mix(in oklab, var(--color-surface-base) 88%, var(--color-text-primary) 12%) 75%,
|
|
2679
|
+
color-mix(in oklab, var(--color-surface-base) 88%, var(--color-text-primary) 12%)
|
|
2680
|
+
),
|
|
2681
|
+
linear-gradient(
|
|
2682
|
+
45deg,
|
|
2683
|
+
color-mix(in oklab, var(--color-surface-base) 88%, var(--color-text-primary) 12%) 25%,
|
|
2684
|
+
transparent 25%,
|
|
2685
|
+
transparent 75%,
|
|
2686
|
+
color-mix(in oklab, var(--color-surface-base) 88%, var(--color-text-primary) 12%) 75%,
|
|
2687
|
+
color-mix(in oklab, var(--color-surface-base) 88%, var(--color-text-primary) 12%)
|
|
2688
|
+
);
|
|
2689
|
+
background-size: calc(var(--spacing-2) * 1.25) calc(var(--spacing-2) * 1.25);
|
|
2690
|
+
background-position:
|
|
2691
|
+
0 0,
|
|
2692
|
+
calc(var(--spacing-2) * 0.625) calc(var(--spacing-2) * 0.625);
|
|
2693
|
+
pointer-events: none;
|
|
2694
|
+
}
|
|
2695
|
+
|
|
2696
|
+
.color-control .color-swatch[data-unset="1"] input[type="color"] {
|
|
2697
|
+
opacity: 0;
|
|
2698
|
+
}
|
|
2699
|
+
|
|
2700
|
+
&:focus-within .color-control {
|
|
2701
|
+
border-color: var(--color-primary-500);
|
|
2702
|
+
box-shadow: 0 0 0 ${focusWidth}px color-mix(in oklab, var(--color-primary-500) ${Math.round(
|
|
2703
|
+
(focusRingOpacity || 0.3) * 100,
|
|
2704
|
+
)}%, transparent);
|
|
2705
|
+
}
|
|
2706
|
+
|
|
2707
|
+
&:has(input[type="color"]:disabled) .color-control {
|
|
2708
|
+
background: var(--color-input-disabled-bg);
|
|
2709
|
+
color: var(--color-input-disabled-text);
|
|
2710
|
+
cursor: not-allowed;
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2558
2714
|
input[type="file"] {
|
|
2559
2715
|
padding: var(--spacing-2) var(--spacing-4);
|
|
2560
2716
|
cursor: pointer;
|
|
@@ -2762,7 +2918,7 @@ a.btn-working {
|
|
|
2762
2918
|
color: var(--color-text-secondary);
|
|
2763
2919
|
padding: var(--spacing-6) var(--spacing-4);
|
|
2764
2920
|
background-color: var(--color-surface-subtle);
|
|
2765
|
-
max-width: var(--layout-max-width-md);
|
|
2921
|
+
max-width: var(--layout-max-width-md, 736px);
|
|
2766
2922
|
border-radius: var(--radius-md);
|
|
2767
2923
|
nav {
|
|
2768
2924
|
margin-top: var(--spacing-4);
|
|
@@ -3126,12 +3282,15 @@ tbody {
|
|
|
3126
3282
|
overflow: hidden;
|
|
3127
3283
|
|
|
3128
3284
|
&[open] {
|
|
3285
|
+
overflow: visible;
|
|
3286
|
+
|
|
3129
3287
|
& > summary::after {
|
|
3130
3288
|
transform: rotate(45deg);
|
|
3131
3289
|
}
|
|
3132
3290
|
|
|
3133
3291
|
&::details-content {
|
|
3134
3292
|
block-size: auto;
|
|
3293
|
+
overflow: visible;
|
|
3135
3294
|
}
|
|
3136
3295
|
}
|
|
3137
3296
|
|
|
@@ -3205,6 +3364,7 @@ tbody {
|
|
|
3205
3364
|
|
|
3206
3365
|
&[open] > :not(summary) {
|
|
3207
3366
|
grid-template-rows: 1fr;
|
|
3367
|
+
overflow: visible;
|
|
3208
3368
|
}
|
|
3209
3369
|
}
|
|
3210
3370
|
}
|
|
@@ -3508,6 +3668,12 @@ dialog.dialog-full { width: calc(100vw - var(--spacing-8)); max-width: calc(100v
|
|
|
3508
3668
|
dialog, dialog::backdrop { transition-duration: 0.01s !important; }
|
|
3509
3669
|
}
|
|
3510
3670
|
|
|
3671
|
+
html:has(dialog[open]:modal) {
|
|
3672
|
+
overflow: hidden;
|
|
3673
|
+
scrollbar-gutter: stable;
|
|
3674
|
+
}
|
|
3675
|
+
|
|
3676
|
+
|
|
3511
3677
|
`;
|
|
3512
3678
|
}
|
|
3513
3679
|
|
|
@@ -3651,9 +3817,8 @@ pds-tabstrip {
|
|
|
3651
3817
|
}
|
|
3652
3818
|
|
|
3653
3819
|
#generateIconStyles() {
|
|
3654
|
-
const {
|
|
3655
|
-
const
|
|
3656
|
-
a11y.minTouchTarget || enums.TouchTargetSizes.standard;
|
|
3820
|
+
const { layout = {} } = this.options.design;
|
|
3821
|
+
const iconOnlySize = layout.buttonMinHeight || 30;
|
|
3657
3822
|
|
|
3658
3823
|
return /*css*/ `/* Icon System */
|
|
3659
3824
|
|
|
@@ -3700,13 +3865,31 @@ button, a {
|
|
|
3700
3865
|
|
|
3701
3866
|
&.icon-only {
|
|
3702
3867
|
padding: var(--spacing-2);
|
|
3703
|
-
min-width: ${
|
|
3704
|
-
width: ${
|
|
3705
|
-
height: ${
|
|
3868
|
+
min-width: ${iconOnlySize}px;
|
|
3869
|
+
width: ${iconOnlySize}px;
|
|
3870
|
+
height: ${iconOnlySize}px;
|
|
3706
3871
|
display: inline-flex;
|
|
3707
3872
|
align-items: center;
|
|
3708
3873
|
justify-content: center;
|
|
3709
3874
|
}
|
|
3875
|
+
|
|
3876
|
+
&.btn-sm.icon-only {
|
|
3877
|
+
min-width: calc(${iconOnlySize}px * 0.8);
|
|
3878
|
+
width: calc(${iconOnlySize}px * 0.8);
|
|
3879
|
+
height: calc(${iconOnlySize}px * 0.8);
|
|
3880
|
+
}
|
|
3881
|
+
|
|
3882
|
+
&.btn-xs.icon-only {
|
|
3883
|
+
min-width: calc(${iconOnlySize}px * 0.6);
|
|
3884
|
+
width: calc(${iconOnlySize}px * 0.6);
|
|
3885
|
+
height: calc(${iconOnlySize}px * 0.6);
|
|
3886
|
+
}
|
|
3887
|
+
|
|
3888
|
+
&.btn-lg.icon-only {
|
|
3889
|
+
min-width: calc(${iconOnlySize}px * 1.2);
|
|
3890
|
+
width: calc(${iconOnlySize}px * 1.2);
|
|
3891
|
+
height: calc(${iconOnlySize}px * 1.2);
|
|
3892
|
+
}
|
|
3710
3893
|
}
|
|
3711
3894
|
|
|
3712
3895
|
/* Icon in inputs */
|
|
@@ -3757,17 +3940,16 @@ nav[data-dropdown] {
|
|
|
3757
3940
|
max-width: none;
|
|
3758
3941
|
max-inline-size: none;
|
|
3759
3942
|
opacity: 0;
|
|
3760
|
-
scale: 0.95;
|
|
3761
3943
|
visibility: hidden;
|
|
3762
3944
|
display: none;
|
|
3763
3945
|
pointer-events: none;
|
|
3764
3946
|
transform-origin: top center;
|
|
3765
3947
|
z-index: var(--z-dropdown, 1050);
|
|
3766
3948
|
max-height: min(60vh, 24rem);
|
|
3949
|
+
overflow-x: hidden;
|
|
3767
3950
|
overflow-y: auto;
|
|
3768
3951
|
transition:
|
|
3769
3952
|
opacity var(--dropdown-transition-duration) ease,
|
|
3770
|
-
scale var(--dropdown-transition-duration) ease,
|
|
3771
3953
|
visibility 0s linear var(--dropdown-transition-duration),
|
|
3772
3954
|
display 0s linear var(--dropdown-transition-duration);
|
|
3773
3955
|
transition-behavior: allow-discrete;
|
|
@@ -3776,12 +3958,10 @@ nav[data-dropdown] {
|
|
|
3776
3958
|
& > :last-child[aria-hidden="false"] {
|
|
3777
3959
|
display: inline-block;
|
|
3778
3960
|
opacity: 1;
|
|
3779
|
-
scale: 1;
|
|
3780
3961
|
visibility: visible;
|
|
3781
3962
|
pointer-events: auto;
|
|
3782
3963
|
transition:
|
|
3783
3964
|
opacity var(--dropdown-transition-duration) ease,
|
|
3784
|
-
scale var(--dropdown-transition-duration) ease,
|
|
3785
3965
|
visibility 0s linear 0s,
|
|
3786
3966
|
display 0s linear 0s;
|
|
3787
3967
|
}
|
|
@@ -3879,7 +4059,6 @@ nav[data-dropdown] {
|
|
|
3879
4059
|
@starting-style {
|
|
3880
4060
|
nav[data-dropdown] > :last-child[aria-hidden="false"] {
|
|
3881
4061
|
opacity: 0;
|
|
3882
|
-
scale: 0.95;
|
|
3883
4062
|
}
|
|
3884
4063
|
}
|
|
3885
4064
|
`;
|
|
@@ -4108,7 +4287,7 @@ nav[data-dropdown] {
|
|
|
4108
4287
|
/* Touch device optimizations */
|
|
4109
4288
|
@media (hover: none) and (pointer: coarse) {
|
|
4110
4289
|
/* Touch devices - larger touch targets for interactive elements */
|
|
4111
|
-
button, a, select, textarea,
|
|
4290
|
+
button:not(.icon-only), a:not(.icon-only), select, textarea,
|
|
4112
4291
|
input:not([type="radio"]):not([type="checkbox"]) {
|
|
4113
4292
|
min-height: ${minTouchTarget}px;
|
|
4114
4293
|
min-width: ${minTouchTarget}px;
|
|
@@ -4795,39 +4974,48 @@ ${this.#generateBorderGradientUtilities()}
|
|
|
4795
4974
|
|
|
4796
4975
|
.surface {
|
|
4797
4976
|
background-color: var(--color-surface-base);
|
|
4977
|
+
--border-gradient-fill: var(--color-surface-base);
|
|
4798
4978
|
}
|
|
4799
4979
|
|
|
4800
4980
|
.surface-subtle {
|
|
4801
4981
|
background-color: var(--color-surface-subtle);
|
|
4982
|
+
--border-gradient-fill: var(--color-surface-subtle);
|
|
4802
4983
|
}
|
|
4803
4984
|
|
|
4804
4985
|
.surface-elevated {
|
|
4805
4986
|
background-color: var(--color-surface-elevated);
|
|
4987
|
+
--border-gradient-fill: var(--color-surface-elevated);
|
|
4806
4988
|
}
|
|
4807
4989
|
|
|
4808
4990
|
.surface-sunken {
|
|
4809
4991
|
background-color: var(--color-surface-sunken);
|
|
4992
|
+
--border-gradient-fill: var(--color-surface-sunken);
|
|
4810
4993
|
}
|
|
4811
4994
|
|
|
4812
4995
|
.surface-overlay {
|
|
4813
4996
|
background-color: var(--color-surface-overlay);
|
|
4997
|
+
--border-gradient-fill: var(--color-surface-overlay);
|
|
4814
4998
|
}
|
|
4815
4999
|
|
|
4816
5000
|
/* Translucent semantic variants */
|
|
4817
5001
|
.surface-translucent {
|
|
4818
5002
|
background-color: var(--color-surface-translucent-50);
|
|
5003
|
+
--border-gradient-fill: var(--color-surface-translucent-50);
|
|
4819
5004
|
}
|
|
4820
5005
|
|
|
4821
5006
|
.surface-translucent-25 {
|
|
4822
5007
|
background-color: var(--color-surface-translucent-25);
|
|
5008
|
+
--border-gradient-fill: var(--color-surface-translucent-25);
|
|
4823
5009
|
}
|
|
4824
5010
|
|
|
4825
5011
|
.surface-translucent-50 {
|
|
4826
5012
|
background-color: var(--color-surface-translucent-50);
|
|
5013
|
+
--border-gradient-fill: var(--color-surface-translucent-50);
|
|
4827
5014
|
}
|
|
4828
5015
|
|
|
4829
5016
|
.surface-translucent-75 {
|
|
4830
5017
|
background-color: var(--color-surface-translucent-75);
|
|
5018
|
+
--border-gradient-fill: var(--color-surface-translucent-75);
|
|
4831
5019
|
}
|
|
4832
5020
|
|
|
4833
5021
|
/* Legacy utility retained for backwards compatibility (opinionated overlay) */
|
|
@@ -4853,6 +5041,7 @@ ${this.#generateBorderGradientUtilities()}
|
|
|
4853
5041
|
/* Surface-inverse visual properties (shared, uses smart surface tokens) */
|
|
4854
5042
|
.surface-inverse {
|
|
4855
5043
|
background-color: var(--color-surface-inverse);
|
|
5044
|
+
--border-gradient-fill: var(--color-surface-inverse);
|
|
4856
5045
|
color: var(--surface-inverse-text);
|
|
4857
5046
|
|
|
4858
5047
|
pds-icon {
|
|
@@ -4876,7 +5065,7 @@ ${this.#generateBorderGradientUtilities()}
|
|
|
4876
5065
|
html:not([data-theme="dark"]) .surface-inverse {
|
|
4877
5066
|
--color-text-primary: var(--color-gray-100);
|
|
4878
5067
|
--color-text-secondary: var(--color-gray-300);
|
|
4879
|
-
--color-text-muted: var(--color-gray-
|
|
5068
|
+
--color-text-muted: var(--color-gray-600);
|
|
4880
5069
|
--color-border: var(--color-gray-700);
|
|
4881
5070
|
--color-input-bg: var(--color-gray-800);
|
|
4882
5071
|
--color-input-disabled-bg: var(--color-gray-900);
|
|
@@ -5326,6 +5515,8 @@ export const ${name}CSS = \`${escapedCSS}\`;
|
|
|
5326
5515
|
*/
|
|
5327
5516
|
export function validateDesign(designConfig = {}, options = {}) {
|
|
5328
5517
|
const MIN = Number(options.minContrast || 4.5);
|
|
5518
|
+
const MIN_MUTED = Number(options.minMutedContrast || 3.0);
|
|
5519
|
+
const EXTENDED = Boolean(options.extendedChecks);
|
|
5329
5520
|
|
|
5330
5521
|
// Local helpers (keep public; no dependency on private Generator methods)
|
|
5331
5522
|
const hexToRgb = (hex) => {
|
|
@@ -5366,10 +5557,20 @@ export function validateDesign(designConfig = {}, options = {}) {
|
|
|
5366
5557
|
const light = {
|
|
5367
5558
|
surfaceBg: c.surface?.base,
|
|
5368
5559
|
surfaceText: c.gray?.[900] || "#000000",
|
|
5560
|
+
surfaceTextSecondary: c.gray?.[700] || c.gray?.[800] || c.gray?.[900],
|
|
5561
|
+
surfaceTextMuted: c.gray?.[500] || c.gray?.[600] || c.gray?.[700],
|
|
5562
|
+
surfaceElevated: c.surface?.elevated || c.surface?.base,
|
|
5369
5563
|
primaryFill: c.interactive?.light?.fill || c.primary?.[600],
|
|
5370
5564
|
primaryText: c.interactive?.light?.text || c.primary?.[600],
|
|
5565
|
+
accentFill: c.accent?.[600] || c.accent?.[500],
|
|
5566
|
+
successFill: c.success?.[600] || c.success?.[500],
|
|
5567
|
+
warningFill: c.warning?.[600] || c.warning?.[500],
|
|
5568
|
+
dangerFill: c.danger?.[600] || c.danger?.[500],
|
|
5569
|
+
infoFill: c.info?.[600] || c.info?.[500],
|
|
5371
5570
|
};
|
|
5372
5571
|
|
|
5572
|
+
const bestTextContrast = (bg) => Math.max(contrast(bg, "#ffffff"), contrast(bg, "#000000"));
|
|
5573
|
+
|
|
5373
5574
|
// Primary button (light): check button fill with white text
|
|
5374
5575
|
const lightBtnRatio = contrast(light.primaryFill, "#ffffff");
|
|
5375
5576
|
if (lightBtnRatio < MIN) {
|
|
@@ -5398,6 +5599,50 @@ export function validateDesign(designConfig = {}, options = {}) {
|
|
|
5398
5599
|
});
|
|
5399
5600
|
}
|
|
5400
5601
|
|
|
5602
|
+
if (EXTENDED) {
|
|
5603
|
+
// Secondary body text (light)
|
|
5604
|
+
const lightSecondaryRatio = contrast(light.surfaceBg, light.surfaceTextSecondary);
|
|
5605
|
+
if (lightSecondaryRatio < MIN) {
|
|
5606
|
+
issues.push({
|
|
5607
|
+
path: "/colors/secondary",
|
|
5608
|
+
message: `Secondary text contrast on base surface (light) is too low (${lightSecondaryRatio.toFixed(
|
|
5609
|
+
2,
|
|
5610
|
+
)} < ${MIN}).`,
|
|
5611
|
+
ratio: lightSecondaryRatio,
|
|
5612
|
+
min: MIN,
|
|
5613
|
+
context: "light/surface-text-secondary",
|
|
5614
|
+
});
|
|
5615
|
+
}
|
|
5616
|
+
|
|
5617
|
+
// Muted text should still be readable for helper text
|
|
5618
|
+
const lightMutedRatio = contrast(light.surfaceBg, light.surfaceTextMuted);
|
|
5619
|
+
if (lightMutedRatio < MIN_MUTED) {
|
|
5620
|
+
issues.push({
|
|
5621
|
+
path: "/colors/secondary",
|
|
5622
|
+
message: `Muted text contrast on base surface (light) is too low (${lightMutedRatio.toFixed(
|
|
5623
|
+
2,
|
|
5624
|
+
)} < ${MIN_MUTED}).`,
|
|
5625
|
+
ratio: lightMutedRatio,
|
|
5626
|
+
min: MIN_MUTED,
|
|
5627
|
+
context: "light/surface-text-muted",
|
|
5628
|
+
});
|
|
5629
|
+
}
|
|
5630
|
+
|
|
5631
|
+
// Elevated cards often dominate page UI; enforce readable default text
|
|
5632
|
+
const elevatedTextRatio = contrast(light.surfaceElevated, light.surfaceText);
|
|
5633
|
+
if (elevatedTextRatio < MIN) {
|
|
5634
|
+
issues.push({
|
|
5635
|
+
path: "/colors/background",
|
|
5636
|
+
message: `Elevated surface text contrast (light) is too low (${elevatedTextRatio.toFixed(
|
|
5637
|
+
2,
|
|
5638
|
+
)} < ${MIN}).`,
|
|
5639
|
+
ratio: elevatedTextRatio,
|
|
5640
|
+
min: MIN,
|
|
5641
|
+
context: "light/surface-elevated-text",
|
|
5642
|
+
});
|
|
5643
|
+
}
|
|
5644
|
+
}
|
|
5645
|
+
|
|
5401
5646
|
// Primary text for outline/link: check link text on surface
|
|
5402
5647
|
const lightOutlineRatio = contrast(light.primaryText, light.surfaceBg);
|
|
5403
5648
|
if (lightOutlineRatio < MIN) {
|
|
@@ -5412,11 +5657,39 @@ export function validateDesign(designConfig = {}, options = {}) {
|
|
|
5412
5657
|
});
|
|
5413
5658
|
}
|
|
5414
5659
|
|
|
5660
|
+
if (EXTENDED) {
|
|
5661
|
+
// Semantic/accent fills must support readable foreground (white or black)
|
|
5662
|
+
const semanticFills = [
|
|
5663
|
+
{ path: "/colors/accent", key: "accent", value: light.accentFill },
|
|
5664
|
+
{ path: "/colors/success", key: "success", value: light.successFill },
|
|
5665
|
+
{ path: "/colors/warning", key: "warning", value: light.warningFill },
|
|
5666
|
+
{ path: "/colors/danger", key: "danger", value: light.dangerFill },
|
|
5667
|
+
{ path: "/colors/info", key: "info", value: light.infoFill },
|
|
5668
|
+
];
|
|
5669
|
+
semanticFills.forEach((entry) => {
|
|
5670
|
+
if (!entry?.value) return;
|
|
5671
|
+
const ratio = bestTextContrast(entry.value);
|
|
5672
|
+
if (ratio < MIN) {
|
|
5673
|
+
issues.push({
|
|
5674
|
+
path: entry.path,
|
|
5675
|
+
message: `${entry.key} fill color cannot achieve accessible text contrast (${ratio.toFixed(
|
|
5676
|
+
2,
|
|
5677
|
+
)} < ${MIN}) with either white or black text.`,
|
|
5678
|
+
ratio,
|
|
5679
|
+
min: MIN,
|
|
5680
|
+
context: `light/${entry.key}-fill`,
|
|
5681
|
+
});
|
|
5682
|
+
}
|
|
5683
|
+
});
|
|
5684
|
+
}
|
|
5685
|
+
|
|
5415
5686
|
// Dark theme checks - use computed interactive tokens
|
|
5416
5687
|
const d = c.dark;
|
|
5417
5688
|
if (d) {
|
|
5418
5689
|
const dark = {
|
|
5419
5690
|
surfaceBg: d.surface?.base || c.surface?.inverse,
|
|
5691
|
+
surfaceText: d.gray?.[50] || d.gray?.[100] || "#ffffff",
|
|
5692
|
+
surfaceTextMuted: d.gray?.[300] || d.gray?.[400] || d.gray?.[500],
|
|
5420
5693
|
primaryFill: c.interactive?.dark?.fill || d.primary?.[600],
|
|
5421
5694
|
primaryText: c.interactive?.dark?.text || d.primary?.[600],
|
|
5422
5695
|
};
|
|
@@ -5448,6 +5721,34 @@ export function validateDesign(designConfig = {}, options = {}) {
|
|
|
5448
5721
|
context: "dark/outline",
|
|
5449
5722
|
});
|
|
5450
5723
|
}
|
|
5724
|
+
|
|
5725
|
+
if (EXTENDED) {
|
|
5726
|
+
const darkTextRatio = contrast(dark.surfaceBg, dark.surfaceText);
|
|
5727
|
+
if (darkTextRatio < MIN) {
|
|
5728
|
+
issues.push({
|
|
5729
|
+
path: "/colors/darkMode/background",
|
|
5730
|
+
message: `Base text contrast on surface (dark) is too low (${darkTextRatio.toFixed(
|
|
5731
|
+
2,
|
|
5732
|
+
)} < ${MIN}).`,
|
|
5733
|
+
ratio: darkTextRatio,
|
|
5734
|
+
min: MIN,
|
|
5735
|
+
context: "dark/surface-text",
|
|
5736
|
+
});
|
|
5737
|
+
}
|
|
5738
|
+
|
|
5739
|
+
const darkMutedRatio = contrast(dark.surfaceBg, dark.surfaceTextMuted);
|
|
5740
|
+
if (darkMutedRatio < MIN_MUTED) {
|
|
5741
|
+
issues.push({
|
|
5742
|
+
path: "/colors/darkMode/secondary",
|
|
5743
|
+
message: `Muted text contrast on surface (dark) is too low (${darkMutedRatio.toFixed(
|
|
5744
|
+
2,
|
|
5745
|
+
)} < ${MIN_MUTED}).`,
|
|
5746
|
+
ratio: darkMutedRatio,
|
|
5747
|
+
min: MIN_MUTED,
|
|
5748
|
+
context: "dark/surface-text-muted",
|
|
5749
|
+
});
|
|
5750
|
+
}
|
|
5751
|
+
}
|
|
5451
5752
|
}
|
|
5452
5753
|
} catch (err) {
|
|
5453
5754
|
issues.push({
|