@loworbitstudio/visor-theme-engine 0.24.0 → 0.28.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/dist/adapters/index.js +3 -1
- package/dist/{chunk-D5XSLWXP.js → chunk-X2SWJPM2.js} +251 -13
- package/dist/index.d.ts +93 -5
- package/dist/index.js +65 -5
- package/package.json +1 -1
- package/src/visor-theme.schema.json +60 -4
package/dist/adapters/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
collectDeclaredProperties,
|
|
10
10
|
fontStack,
|
|
11
11
|
generateDarkCss,
|
|
12
|
+
generateFontMetricDecls,
|
|
12
13
|
generateFontSizeDecls,
|
|
13
14
|
generateFontWeightDecls,
|
|
14
15
|
generateHairlineDecls,
|
|
@@ -25,7 +26,7 @@ import {
|
|
|
25
26
|
resolveThemeBrand,
|
|
26
27
|
resolveThemeFonts,
|
|
27
28
|
sectionComment
|
|
28
|
-
} from "../chunk-
|
|
29
|
+
} from "../chunk-X2SWJPM2.js";
|
|
29
30
|
|
|
30
31
|
// src/adapters/brand-passthrough.ts
|
|
31
32
|
var SENTINEL_COLOR = "#ff00ff";
|
|
@@ -559,6 +560,7 @@ function generateTypographyDecls(config, aliases) {
|
|
|
559
560
|
decls.push(`--font-body: ${fontStack(config.typography.body.family, aliases)};`);
|
|
560
561
|
decls.push(`--font-mono: ${fontStack(config.typography.mono.family, aliases)};`);
|
|
561
562
|
decls.push(...generateFontSizeDecls(config.typography.scale));
|
|
563
|
+
decls.push(...generateFontMetricDecls(config.typography.body.family));
|
|
562
564
|
decls.push(...generateFontWeightDecls(config.typography));
|
|
563
565
|
const lineHeights = {
|
|
564
566
|
none: 1,
|
|
@@ -1261,6 +1261,8 @@ var SKELETON = "components/ui/skeleton/skeleton.module.css";
|
|
|
1261
1261
|
var SPINNER = "components/ui/spinner/spinner.module.css";
|
|
1262
1262
|
var CHECKBOX = "components/ui/checkbox/checkbox.module.css";
|
|
1263
1263
|
var INPUT = "components/ui/input/input.module.css";
|
|
1264
|
+
var SEPARATOR = "components/ui/separator/separator.module.css";
|
|
1265
|
+
var NUMBER_INPUT = "components/ui/number-input/number-input.module.css";
|
|
1264
1266
|
var TEXTAREA = "components/ui/textarea/textarea.module.css";
|
|
1265
1267
|
var SELECT = "components/ui/select/select.module.css";
|
|
1266
1268
|
var SWITCH = "components/ui/switch/switch.module.css";
|
|
@@ -1271,7 +1273,10 @@ var FIELD = "components/ui/field/field.module.css";
|
|
|
1271
1273
|
var TEXT = "components/ui/text/text.module.css";
|
|
1272
1274
|
var INLINE_EDIT = "components/ui/inline-edit/inline-edit.module.css";
|
|
1273
1275
|
var SAVE_STATUS = "components/ui/save-status/save-status.module.css";
|
|
1276
|
+
var SEGMENTED_CONTROL = "components/ui/segmented-control/segmented-control.module.css";
|
|
1274
1277
|
var TOOLTIP = "components/ui/tooltip/tooltip.module.css";
|
|
1278
|
+
var ACTION_ROW = "components/ui/action-row/action-row.module.css";
|
|
1279
|
+
var DIALOG_FIELD = "blocks/dialog-field/dialog-field.module.css";
|
|
1275
1280
|
function at(file, fallback) {
|
|
1276
1281
|
return [{ file, fallback }];
|
|
1277
1282
|
}
|
|
@@ -1536,6 +1541,7 @@ var emptyStateFamily = {
|
|
|
1536
1541
|
{ key: "heading-color", property: "color", description: "Heading colour.", consumers: at(EMPTY_STATE, "var(--text-primary, #111827)") },
|
|
1537
1542
|
{ key: "description-font-size", property: "font-size", description: "Description type size.", consumers: at(EMPTY_STATE, "var(--font-size-sm, 0.875rem)") },
|
|
1538
1543
|
{ key: "description-color", property: "color", description: "Description colour.", consumers: at(EMPTY_STATE, "var(--text-secondary, #6b7280)") },
|
|
1544
|
+
{ key: "error-color", property: "color", description: 'Icon, chip glyph and heading colour for `intent="error"`.', consumers: at(EMPTY_STATE, "var(--destructive, #dc2626)") },
|
|
1539
1545
|
{ key: "actions-gap", property: "gap", description: "Gap between placard actions.", consumers: at(EMPTY_STATE, "var(--spacing-2, 0.5rem)") }
|
|
1540
1546
|
]
|
|
1541
1547
|
};
|
|
@@ -1689,7 +1695,84 @@ var checkboxFamily = {
|
|
|
1689
1695
|
{ key: "border-checked", property: "outline-color", description: "Checked edge colour.", consumers: at(CHECKBOX, "var(--interactive-primary-bg, var(--primary, #111827))") }
|
|
1690
1696
|
]
|
|
1691
1697
|
};
|
|
1692
|
-
var
|
|
1698
|
+
var INPUT_MD_PADDING = "var(--spacing-3_5, 0.875rem) var(--spacing-4, 1rem)";
|
|
1699
|
+
var INPUT_MD_PADDING_NUDGED = "calc(var(--spacing-3_5, 0.875rem) + var(--input-nudge, 0px)) var(--spacing-4, 1rem) calc(var(--spacing-3_5, 0.875rem) - var(--input-nudge, 0px))";
|
|
1700
|
+
var inputFamily = {
|
|
1701
|
+
family: "input",
|
|
1702
|
+
prefix: "input",
|
|
1703
|
+
description: "Input shape at the default `md` size. Each key falls back to the matching `--input-*-md` variable, so a scope that sets one still applies while the key is unbound; a bound key wins.",
|
|
1704
|
+
tokens: [
|
|
1705
|
+
{
|
|
1706
|
+
key: "md-height",
|
|
1707
|
+
property: "height",
|
|
1708
|
+
description: "`md` height. Unbound, the height follows the padding and the line. Bind `md-padding` with it.",
|
|
1709
|
+
consumers: at(INPUT, "var(--input-height-md, auto)")
|
|
1710
|
+
},
|
|
1711
|
+
{
|
|
1712
|
+
key: "md-padding",
|
|
1713
|
+
property: "padding",
|
|
1714
|
+
description: "`md` padding. Also the padding of DialogField's medium well, so the well tracks the field.",
|
|
1715
|
+
consumers: [
|
|
1716
|
+
{ file: INPUT, fallback: `var(--input-padding-md, ${INPUT_MD_PADDING})` },
|
|
1717
|
+
{ file: INPUT, fallback: `var(--input-padding-md, ${INPUT_MD_PADDING_NUDGED})` },
|
|
1718
|
+
{ file: DIALOG_FIELD, fallback: `var(--input-padding-md, ${INPUT_MD_PADDING})` }
|
|
1719
|
+
]
|
|
1720
|
+
},
|
|
1721
|
+
{
|
|
1722
|
+
key: "md-radius",
|
|
1723
|
+
property: "border-radius",
|
|
1724
|
+
description: "`md` corner rounding. Also the rounding of DialogField's well.",
|
|
1725
|
+
consumers: each([INPUT, DIALOG_FIELD], "var(--input-radius-md, var(--radius-sm, 0.5rem))")
|
|
1726
|
+
}
|
|
1727
|
+
]
|
|
1728
|
+
};
|
|
1729
|
+
var textareaFamily = {
|
|
1730
|
+
family: "textarea",
|
|
1731
|
+
prefix: "textarea",
|
|
1732
|
+
description: "Textarea shape at the default `md` size.",
|
|
1733
|
+
tokens: [
|
|
1734
|
+
{ key: "padding", property: "padding", description: "`md` padding.", consumers: at(TEXTAREA, INPUT_MD_PADDING) },
|
|
1735
|
+
{ key: "radius", property: "border-radius", description: "`md` corner rounding.", consumers: at(TEXTAREA, "var(--radius-sm, 0.5rem)") }
|
|
1736
|
+
]
|
|
1737
|
+
};
|
|
1738
|
+
var selectFamily = {
|
|
1739
|
+
family: "select",
|
|
1740
|
+
prefix: "select",
|
|
1741
|
+
description: "Select trigger shape at the default `md` size.",
|
|
1742
|
+
tokens: [
|
|
1743
|
+
{
|
|
1744
|
+
key: "height",
|
|
1745
|
+
property: "height",
|
|
1746
|
+
description: "`md` trigger height. Unbound, the height follows the padding and the line. Bind `padding` with it.",
|
|
1747
|
+
consumers: [
|
|
1748
|
+
{ file: SELECT, fallback: "auto" },
|
|
1749
|
+
{ file: SELECT, fallback: "calc(1lh + var(--spacing-3_5, 0.875rem) * 2 + 2px)" }
|
|
1750
|
+
]
|
|
1751
|
+
},
|
|
1752
|
+
{ key: "padding", property: "padding", description: "`md` trigger padding.", consumers: at(SELECT, INPUT_MD_PADDING) },
|
|
1753
|
+
{ key: "radius", property: "border-radius", description: "`md` trigger corner rounding.", consumers: at(SELECT, "var(--radius-sm, 0.5rem)") }
|
|
1754
|
+
]
|
|
1755
|
+
};
|
|
1756
|
+
var tagInputFamily = {
|
|
1757
|
+
family: "tag-input",
|
|
1758
|
+
prefix: "tag-input",
|
|
1759
|
+
description: 'TagInput \u2014 the field around the tags, each held tag, and the opt-in typing slot (`entryAs="slot"`). The slot follows the tag\'s shape unless its own keys are set.',
|
|
1760
|
+
tokens: [
|
|
1761
|
+
{ key: "min-height", property: "min-height", description: "Field minimum height. The field grows as tags wrap.", consumers: at(TAG_INPUT, "2.25rem") },
|
|
1762
|
+
{ key: "padding", property: "padding", description: "Field padding around the tags.", consumers: at(TAG_INPUT, "var(--spacing-1, 0.25rem) var(--spacing-2, 0.5rem)") },
|
|
1763
|
+
{ key: "radius", property: "border-radius", description: "Field corner rounding.", consumers: at(TAG_INPUT, "var(--radius-md, 0.375rem)") },
|
|
1764
|
+
{ key: "tag-height", property: "height", description: "Held-tag height. Unbound, the tag is as tall as its line.", consumers: at(TAG_INPUT, "auto") },
|
|
1765
|
+
{ key: "tag-padding-x", property: "padding-left / padding-right", description: "Held-tag horizontal padding.", consumers: at(TAG_INPUT, "var(--spacing-2, 0.5rem)") },
|
|
1766
|
+
{ key: "tag-font-size", property: "font-size", description: "Held-tag type size. The typing slot types at it too.", consumers: each([TAG_INPUT, TAG_INPUT], "var(--font-size-xs, 0.75rem)") },
|
|
1767
|
+
{ key: "tag-font-weight", property: "font-weight", description: "Held-tag weight. Unbound, the tag inherits its row's weight.", consumers: at(TAG_INPUT, "revert-layer") },
|
|
1768
|
+
{ key: "tag-radius", property: "border-radius", description: "Held-tag corner rounding (a pill today).", consumers: at(TAG_INPUT, "var(--radius-full, 9999px)") },
|
|
1769
|
+
{ key: "slot-height", property: "height", description: "Typing-slot height. Follows `tag-height`.", consumers: at(TAG_INPUT, "var(--tag-input-tag-height, 1.375rem)") },
|
|
1770
|
+
{ key: "slot-padding-x", property: "padding-left / padding-right", description: "Typing-slot horizontal padding. Follows `tag-padding-x`.", consumers: at(TAG_INPUT, "var(--tag-input-tag-padding-x, var(--spacing-2, 0.5rem))") },
|
|
1771
|
+
{ key: "slot-radius", property: "border-radius", description: "Typing-slot corner rounding. Follows `tag-radius`.", consumers: at(TAG_INPUT, "var(--tag-input-tag-radius, var(--radius-full, 9999px))") },
|
|
1772
|
+
{ key: "slot-min-width", property: "min-width", description: "Typing-slot minimum width. The slot grows with what is typed.", consumers: at(TAG_INPUT, "4rem") }
|
|
1773
|
+
]
|
|
1774
|
+
};
|
|
1775
|
+
var EDGE_CONTROLS = [INPUT, NUMBER_INPUT, TEXTAREA, SELECT, CHECKBOX, SWITCH, TAG_INPUT, BUTTON];
|
|
1693
1776
|
var controlFamily = {
|
|
1694
1777
|
family: "control",
|
|
1695
1778
|
prefix: "control",
|
|
@@ -1710,7 +1793,7 @@ var controlFamily = {
|
|
|
1710
1793
|
key: "edge-color",
|
|
1711
1794
|
property: "outline-color",
|
|
1712
1795
|
description: "Resting-edge colour. A component's own `--<component>-border` override still wins over it.",
|
|
1713
|
-
consumers: each([INPUT, TEXTAREA, SELECT, CHECKBOX, TAG_INPUT, CHIP, FILE_UPLOAD, EMPTY_STATE, BUTTON], "var(--border-default, #e5e7eb)")
|
|
1796
|
+
consumers: each([INPUT, NUMBER_INPUT, TEXTAREA, SELECT, CHECKBOX, TAG_INPUT, CHIP, FILE_UPLOAD, EMPTY_STATE, BUTTON], "var(--border-default, #e5e7eb)")
|
|
1714
1797
|
},
|
|
1715
1798
|
{
|
|
1716
1799
|
key: "edge-style",
|
|
@@ -1722,19 +1805,40 @@ var controlFamily = {
|
|
|
1722
1805
|
key: "drop-edge-width",
|
|
1723
1806
|
property: "outline-width",
|
|
1724
1807
|
description: "Dashed-edge weight (file-upload draws it at 2\xD7). Follows `edge-width` unless set \u2014 set it alone to keep dashed edges while solid edges are off.",
|
|
1725
|
-
consumers: each([FILE_UPLOAD, EMPTY_STATE], "var(--control-edge-width, 1px)")
|
|
1808
|
+
consumers: each([FILE_UPLOAD, EMPTY_STATE, TAG_INPUT], "var(--control-edge-width, 1px)")
|
|
1726
1809
|
},
|
|
1727
1810
|
{
|
|
1728
1811
|
key: "drop-edge-style",
|
|
1729
1812
|
property: "outline-style",
|
|
1730
|
-
description: "Dashed-edge style for drop targets and
|
|
1731
|
-
consumers: each([FILE_UPLOAD, EMPTY_STATE], "dashed")
|
|
1813
|
+
description: "Dashed-edge style for drop targets, empty states and the TagInput typing slot.",
|
|
1814
|
+
consumers: each([FILE_UPLOAD, EMPTY_STATE, TAG_INPUT], "dashed")
|
|
1732
1815
|
},
|
|
1733
1816
|
{
|
|
1734
1817
|
key: "state-edge-width",
|
|
1735
1818
|
property: "outline-width",
|
|
1736
1819
|
description: "Focus and invalid edge weight. Independent of `edge-width`, so focus and invalid stay visible with edges off.",
|
|
1737
|
-
consumers: each([INPUT, TEXTAREA, SELECT, CHECKBOX, SWITCH, TAG_INPUT], "1px")
|
|
1820
|
+
consumers: each([INPUT, NUMBER_INPUT, TEXTAREA, SELECT, CHECKBOX, SWITCH, TAG_INPUT], "1px")
|
|
1821
|
+
},
|
|
1822
|
+
// VI-663: the refused-value look on Input, Textarea and Select — a ring in
|
|
1823
|
+
// the error colour plus a halo around it. Neither reads `edge-width`, so
|
|
1824
|
+
// invalid stays visible with edges off.
|
|
1825
|
+
{
|
|
1826
|
+
key: "invalid-ring-width",
|
|
1827
|
+
property: "box-shadow (Input) / outline-width",
|
|
1828
|
+
description: "Width of the error-colour ring on a refused value. Unbound, Input draws a 1.5px inset ring and Textarea and Select draw it at `state-edge-width`.",
|
|
1829
|
+
consumers: [
|
|
1830
|
+
...each([INPUT, INPUT], "1.5px"),
|
|
1831
|
+
...each([TEXTAREA, TEXTAREA, SELECT, SELECT], "var(--control-state-edge-width, 1px)")
|
|
1832
|
+
]
|
|
1833
|
+
},
|
|
1834
|
+
{
|
|
1835
|
+
key: "invalid-halo-width",
|
|
1836
|
+
property: "box-shadow",
|
|
1837
|
+
description: "Width of the soft error-colour halo outside the ring. Unbound, Input draws none and Textarea and Select draw it at `--focus-ring-width`.",
|
|
1838
|
+
consumers: [
|
|
1839
|
+
{ file: INPUT, fallback: "0px" },
|
|
1840
|
+
...each([TEXTAREA, SELECT], "var(--focus-ring-width, 2px)")
|
|
1841
|
+
]
|
|
1738
1842
|
}
|
|
1739
1843
|
]
|
|
1740
1844
|
};
|
|
@@ -1766,10 +1870,10 @@ var fieldFamily = {
|
|
|
1766
1870
|
]
|
|
1767
1871
|
};
|
|
1768
1872
|
var BUTTON_SIZES = [
|
|
1769
|
-
{ size: "sm", fontSize: ["var(--font-size-xs, 0.75rem)", "0.8125rem"], radius: "var(--radius-md, 0.375rem)" },
|
|
1770
|
-
{ size: "md", fontSize: ["var(--font-size-sm, 0.875rem)"], radius: "var(--radius-md, 0.375rem)" },
|
|
1771
|
-
{ size: "lg", fontSize: ["var(--font-size-base, 1rem)"], radius: "var(--radius-md, 0.375rem)" },
|
|
1772
|
-
{ size: "dlg", fontSize: ["var(--font-size-2xs, 0.6875rem)"], radius: "var(--radius-lg, 0.5rem)" }
|
|
1873
|
+
{ size: "sm", fontSize: ["var(--font-size-xs, 0.75rem)", "0.8125rem"], fontWeight: "var(--font-weight-medium, 500)", radius: "var(--radius-md, 0.375rem)" },
|
|
1874
|
+
{ size: "md", fontSize: ["var(--font-size-sm, 0.875rem)"], fontWeight: "var(--font-weight-medium, 500)", radius: "var(--radius-md, 0.375rem)" },
|
|
1875
|
+
{ size: "lg", fontSize: ["var(--font-size-base, 1rem)"], fontWeight: "var(--font-weight-medium, 500)", radius: "var(--radius-md, 0.375rem)" },
|
|
1876
|
+
{ size: "dlg", fontSize: ["var(--font-size-2xs, 0.6875rem)"], fontWeight: "var(--font-weight-semibold, 600)", radius: "var(--radius-lg, 0.5rem)" }
|
|
1773
1877
|
];
|
|
1774
1878
|
var buttonFamily = {
|
|
1775
1879
|
family: "button",
|
|
@@ -1788,6 +1892,12 @@ var buttonFamily = {
|
|
|
1788
1892
|
description: "Tracking for every size.",
|
|
1789
1893
|
consumers: BUTTON_SIZES.map(() => ({ file: BUTTON, fallback: "revert-layer" }))
|
|
1790
1894
|
},
|
|
1895
|
+
{
|
|
1896
|
+
key: "font-weight",
|
|
1897
|
+
property: "font-weight",
|
|
1898
|
+
description: "Weight for every size.",
|
|
1899
|
+
consumers: BUTTON_SIZES.map(({ fontWeight }) => ({ file: BUTTON, fallback: fontWeight }))
|
|
1900
|
+
},
|
|
1791
1901
|
{
|
|
1792
1902
|
key: "radius",
|
|
1793
1903
|
property: "border-radius",
|
|
@@ -1797,13 +1907,19 @@ var buttonFamily = {
|
|
|
1797
1907
|
{ file: BUTTON, fallback: "var(--radius-md, 0.375rem)" }
|
|
1798
1908
|
]
|
|
1799
1909
|
},
|
|
1800
|
-
...BUTTON_SIZES.flatMap(({ size, fontSize, radius }) => [
|
|
1910
|
+
...BUTTON_SIZES.flatMap(({ size, fontSize, fontWeight, radius }) => [
|
|
1801
1911
|
{
|
|
1802
1912
|
key: `${size}-font-size`,
|
|
1803
1913
|
property: "font-size",
|
|
1804
1914
|
description: fontSize.length > 1 ? `\`${size}\` type size. Drives both the standard and editorial-density steps.` : `\`${size}\` type size.`,
|
|
1805
1915
|
consumers: fontSize.map((fallback) => ({ file: BUTTON, fallback }))
|
|
1806
1916
|
},
|
|
1917
|
+
{
|
|
1918
|
+
key: `${size}-font-weight`,
|
|
1919
|
+
property: "font-weight",
|
|
1920
|
+
description: `\`${size}\` weight.`,
|
|
1921
|
+
consumers: at(BUTTON, `var(--button-font-weight, ${fontWeight})`)
|
|
1922
|
+
},
|
|
1807
1923
|
{
|
|
1808
1924
|
key: `${size}-text-transform`,
|
|
1809
1925
|
property: "text-transform",
|
|
@@ -1899,9 +2015,26 @@ var switchFamily = {
|
|
|
1899
2015
|
var saveStatusFamily = {
|
|
1900
2016
|
family: "save-status",
|
|
1901
2017
|
prefix: "save-status",
|
|
1902
|
-
description: "SaveStatus readout \u2014 the fixed-width slot
|
|
2018
|
+
description: "SaveStatus readout \u2014 the fixed-width slot, its type, the Syncing ink and the Unsaved dot, so the readout never reflows its row.",
|
|
1903
2019
|
tokens: [
|
|
1904
|
-
{ key: "width", property: "width", description: "Slot width.
|
|
2020
|
+
{ key: "width", property: "width", description: "Slot width. Unbound, the slot is as wide as the longest label in the current font plus the retry mark, the same in every state. Bind it to pin a width; a longer label then truncates inside it.", consumers: at(SAVE_STATUS, "auto") },
|
|
2021
|
+
{ key: "syncing-color", property: "color", description: "Ink of the Syncing state (a first sync from an outside source). Unbound it reads `--text-secondary`.", consumers: at(SAVE_STATUS, "var(--text-secondary, #6b7280)") },
|
|
2022
|
+
{ key: "font-size", property: "font-size", description: "Readout type size.", consumers: at(SAVE_STATUS, "var(--font-size-xs, 0.75rem)") },
|
|
2023
|
+
{
|
|
2024
|
+
key: "dot-size",
|
|
2025
|
+
property: "width / height",
|
|
2026
|
+
description: "Diameter of the status dot (`dot`), in every state but Unsaved. Also the Unsaved dot's, until `unsaved-dot-size` is set. The slot width does not change.",
|
|
2027
|
+
consumers: [
|
|
2028
|
+
{ file: SAVE_STATUS, fallback: "var(--spacing-2, 0.5rem)" },
|
|
2029
|
+
{ file: SAVE_STATUS, fallback: "var(--spacing-2, 0.5rem)" }
|
|
2030
|
+
]
|
|
2031
|
+
},
|
|
2032
|
+
{
|
|
2033
|
+
key: "unsaved-dot-size",
|
|
2034
|
+
property: "width / height",
|
|
2035
|
+
description: 'Diameter of the dot that draws Unsaved \u2014 the status dot while Unsaved, and the dot alone of `unsavedAs="dot"`. Follows `dot-size`.',
|
|
2036
|
+
consumers: each([SAVE_STATUS, SAVE_STATUS], "var(--save-status-dot-size, var(--spacing-2, 0.5rem))")
|
|
2037
|
+
},
|
|
1905
2038
|
{ key: "font-family", property: "font-family", description: "Readout family (e.g. the theme's mono).", consumers: at(SAVE_STATUS, "revert-layer") },
|
|
1906
2039
|
{ key: "text-transform", property: "text-transform", description: "Readout casing.", consumers: at(SAVE_STATUS, "revert-layer") },
|
|
1907
2040
|
{ key: "letter-spacing", property: "letter-spacing", description: "Readout tracking.", consumers: at(SAVE_STATUS, "revert-layer") }
|
|
@@ -1916,6 +2049,59 @@ var tooltipFamily = {
|
|
|
1916
2049
|
{ key: "text", property: "color", description: "Tooltip label colour.", consumers: at(TOOLTIP, "var(--text-inverse, #ffffff)") }
|
|
1917
2050
|
]
|
|
1918
2051
|
};
|
|
2052
|
+
var actionRowFamily = {
|
|
2053
|
+
family: "action-row",
|
|
2054
|
+
prefix: "action-row",
|
|
2055
|
+
description: "ActionRow state fills, edge and geometry: rest, hover, open, selected and disabled each read their own token.",
|
|
2056
|
+
tokens: [
|
|
2057
|
+
{ key: "min-height", property: "min-height", description: "Row floor height; the whole row is the target.", consumers: at(ACTION_ROW, "2.75rem") },
|
|
2058
|
+
{ key: "padding", property: "padding", description: "Row inset, kept inside the hover and selected fills.", consumers: at(ACTION_ROW, "var(--spacing-2, 0.5rem) var(--spacing-3, 0.75rem)") },
|
|
2059
|
+
{ key: "gap", property: "gap", description: "Gap between the leading slot, the title block and the trailing slot.", consumers: at(ACTION_ROW, "var(--spacing-3, 0.75rem)") },
|
|
2060
|
+
{ key: "radius", property: "border-radius", description: "Row corner rounding (the hover and selected fill).", consumers: at(ACTION_ROW, "var(--radius-md, 0.375rem)") },
|
|
2061
|
+
{ key: "hover-bg", property: "background-color", description: "Hover fill.", consumers: at(ACTION_ROW, "var(--surface-interactive-hover, #f3f4f6)") },
|
|
2062
|
+
{ key: "open-bg", property: "background-color", description: "Fill of a row that has opened a picker or popover (`aria-expanded`).", consumers: at(ACTION_ROW, "var(--surface-interactive-hover, #f3f4f6)") },
|
|
2063
|
+
{ key: "selected-bg", property: "background-color", description: "Selected fill. A lifted fill, never white.", consumers: at(ACTION_ROW, "var(--surface-interactive-active, #e5e7eb)") },
|
|
2064
|
+
{ key: "selected-edge-color", property: "outline-color", description: "Selected row's inset edge colour. Its width is `--control-state-edge-width`, so `edges: off` keeps it.", consumers: at(ACTION_ROW, "var(--text-secondary, #6b7280)") },
|
|
2065
|
+
{ key: "disabled-opacity", property: "opacity", description: "Disabled row opacity.", consumers: at(ACTION_ROW, "var(--opacity-50, 0.5)") },
|
|
2066
|
+
{ key: "title-weight", property: "font-weight", description: "Title weight.", consumers: at(ACTION_ROW, "var(--font-weight-medium, 500)") },
|
|
2067
|
+
{ key: "line-color", property: "color", description: "Second-line colour.", consumers: at(ACTION_ROW, "var(--text-secondary, #6b7280)") },
|
|
2068
|
+
{ key: "leading-color", property: "color", description: "Leading icon colour.", consumers: at(ACTION_ROW, "var(--text-secondary, #6b7280)") },
|
|
2069
|
+
{ key: "leading-size", property: "font-size", description: "Leading icon size.", consumers: at(ACTION_ROW, "1.25rem") },
|
|
2070
|
+
{ key: "trailing-color", property: "color", description: "Trailing value or caret colour.", consumers: at(ACTION_ROW, "var(--text-secondary, #6b7280)") }
|
|
2071
|
+
]
|
|
2072
|
+
};
|
|
2073
|
+
var inputAffixFamily = {
|
|
2074
|
+
family: "input-affix",
|
|
2075
|
+
prefix: "input-affix",
|
|
2076
|
+
description: "Input and NumberInput prefix and suffix: the gap between a fixed affix and the value, and the affix's ink.",
|
|
2077
|
+
tokens: [
|
|
2078
|
+
{
|
|
2079
|
+
key: "gap",
|
|
2080
|
+
property: "gap",
|
|
2081
|
+
description: "Space between a prefix or suffix and the value.",
|
|
2082
|
+
consumers: [...at(INPUT, "var(--spacing-2, 0.5rem)"), ...at(NUMBER_INPUT, "var(--spacing-2, 0.5rem)")]
|
|
2083
|
+
},
|
|
2084
|
+
{
|
|
2085
|
+
key: "color",
|
|
2086
|
+
property: "color",
|
|
2087
|
+
description: "Prefix and suffix ink.",
|
|
2088
|
+
consumers: [...at(INPUT, "var(--text-secondary, #6b7280)"), ...at(NUMBER_INPUT, "var(--text-secondary, #6b7280)")]
|
|
2089
|
+
}
|
|
2090
|
+
]
|
|
2091
|
+
};
|
|
2092
|
+
var separatorFamily = {
|
|
2093
|
+
family: "separator",
|
|
2094
|
+
prefix: "separator",
|
|
2095
|
+
description: "Separator rule: the colour of the line, bare or on both sides of a label.",
|
|
2096
|
+
tokens: [
|
|
2097
|
+
{
|
|
2098
|
+
key: "color",
|
|
2099
|
+
property: "background-color",
|
|
2100
|
+
description: "Rule colour. Falls back to the default border colour.",
|
|
2101
|
+
consumers: at(SEPARATOR, "var(--border-default, #e5e7eb)")
|
|
2102
|
+
}
|
|
2103
|
+
]
|
|
2104
|
+
};
|
|
1919
2105
|
var HAIRLINE_PX = [
|
|
1920
2106
|
"components/ui/bulk-action-bar/bulk-action-bar.module.css",
|
|
1921
2107
|
"components/ui/dialog/dialog.module.css",
|
|
@@ -1925,6 +2111,7 @@ var HAIRLINE_PX = [
|
|
|
1925
2111
|
TABS
|
|
1926
2112
|
];
|
|
1927
2113
|
var HAIRLINE_THIN = [
|
|
2114
|
+
ACTION_ROW,
|
|
1928
2115
|
"blocks/dialog-form/dialog-form.module.css",
|
|
1929
2116
|
"components/ui/coherence-check/coherence-check.module.css",
|
|
1930
2117
|
"components/ui/doc-frame/doc-frame.module.css",
|
|
@@ -1954,6 +2141,29 @@ var hairlineFamily = {
|
|
|
1954
2141
|
}
|
|
1955
2142
|
]
|
|
1956
2143
|
};
|
|
2144
|
+
var segmentedControlFamily = {
|
|
2145
|
+
family: "segmented-control",
|
|
2146
|
+
prefix: "segmented-control",
|
|
2147
|
+
description: "SegmentedControl \u2014 the well, its corner radius, the sliding pill, the ink and the state edge on it. The resting edge is the shared `control` edge.",
|
|
2148
|
+
tokens: [
|
|
2149
|
+
{ key: "track-bg", property: "background-color", description: "The well the pill slides in. Default is the page nudged 12% toward the ink, so it reads as a well in light and dark.", consumers: at(SEGMENTED_CONTROL, "color-mix(in srgb, var(--text-primary, #111827) 12%, var(--surface-page, #ffffff))") },
|
|
2150
|
+
{
|
|
2151
|
+
key: "radius",
|
|
2152
|
+
property: "border-radius",
|
|
2153
|
+
description: "Track corner radius. Unset, each size keeps its ToggleGroup radius (md and sm `--radius-lg`, xs `--radius-md`, lg `--radius-xl`).",
|
|
2154
|
+
consumers: [
|
|
2155
|
+
{ file: SEGMENTED_CONTROL, fallback: "var(--radius-md, 0.375rem)" },
|
|
2156
|
+
{ file: SEGMENTED_CONTROL, fallback: "var(--radius-lg, 0.5rem)" },
|
|
2157
|
+
{ file: SEGMENTED_CONTROL, fallback: "var(--radius-xl, 0.75rem)" }
|
|
2158
|
+
]
|
|
2159
|
+
},
|
|
2160
|
+
{ key: "indicator-bg", property: "background-color", description: "Sliding active pill. Bind a lifted dark fill where the theme wants one.", consumers: at(SEGMENTED_CONTROL, "var(--interactive-primary-bg, var(--primary, #111827))") },
|
|
2161
|
+
{ key: "indicator-text", property: "color", description: "Active segment label ink, on the pill.", consumers: at(SEGMENTED_CONTROL, "var(--interactive-primary-text, #f9fafb)") },
|
|
2162
|
+
{ key: "indicator-edge", property: "box-shadow (inset, at --control-state-edge-width)", description: "Colour of the 1px state edge on the active pill. Set `transparent` where the fill already clears 3:1 against the well.", consumers: at(SEGMENTED_CONTROL, "var(--text-primary, #111827)") },
|
|
2163
|
+
{ key: "inactive-text", property: "color", description: "Inactive segment label colour.", consumers: at(SEGMENTED_CONTROL, "var(--text-primary, #111827)") },
|
|
2164
|
+
{ key: "active-weight", property: "font-weight", description: "Active segment label weight.", consumers: at(SEGMENTED_CONTROL, "var(--font-weight-medium, 500)") }
|
|
2165
|
+
]
|
|
2166
|
+
};
|
|
1957
2167
|
var adminUiFamily = {
|
|
1958
2168
|
family: "admin-ui",
|
|
1959
2169
|
prefix: "admin-ui",
|
|
@@ -1982,6 +2192,10 @@ var COMPONENT_TOKEN_FAMILIES = [
|
|
|
1982
2192
|
skeletonFamily,
|
|
1983
2193
|
spinnerFamily,
|
|
1984
2194
|
checkboxFamily,
|
|
2195
|
+
inputFamily,
|
|
2196
|
+
textareaFamily,
|
|
2197
|
+
selectFamily,
|
|
2198
|
+
tagInputFamily,
|
|
1985
2199
|
controlFamily,
|
|
1986
2200
|
hairlineFamily,
|
|
1987
2201
|
fieldFamily,
|
|
@@ -1989,7 +2203,11 @@ var COMPONENT_TOKEN_FAMILIES = [
|
|
|
1989
2203
|
textFamily,
|
|
1990
2204
|
switchFamily,
|
|
1991
2205
|
saveStatusFamily,
|
|
2206
|
+
segmentedControlFamily,
|
|
1992
2207
|
tooltipFamily,
|
|
2208
|
+
actionRowFamily,
|
|
2209
|
+
inputAffixFamily,
|
|
2210
|
+
separatorFamily,
|
|
1993
2211
|
adminUiFamily
|
|
1994
2212
|
];
|
|
1995
2213
|
var COMPONENT_TOKEN_FAMILY_BY_NAME = new Map(
|
|
@@ -2279,6 +2497,23 @@ function applyOverrides(tokens, overrides) {
|
|
|
2279
2497
|
return result;
|
|
2280
2498
|
}
|
|
2281
2499
|
|
|
2500
|
+
// src/font-metrics.ts
|
|
2501
|
+
var FONT_VERTICAL_METRICS = {
|
|
2502
|
+
arial: { ascent: 0.905, descent: 0.212 },
|
|
2503
|
+
inter: { ascent: 0.969, descent: 0.241 },
|
|
2504
|
+
outfit: { ascent: 1, descent: 0.26 },
|
|
2505
|
+
"pitch sans": { ascent: 0.9, descent: 0.32 },
|
|
2506
|
+
"pp model mono": { ascent: 1.02, descent: 0.288 },
|
|
2507
|
+
"product sans": { ascent: 0.96, descent: 0.253 },
|
|
2508
|
+
satoshi: { ascent: 1.01, descent: 0.24 },
|
|
2509
|
+
"system-ui": { ascent: 0.967, descent: 0.211 }
|
|
2510
|
+
};
|
|
2511
|
+
function generateFontMetricDecls(family) {
|
|
2512
|
+
const key = family.trim().replace(/^["']|["']$/g, "").toLowerCase();
|
|
2513
|
+
const m = FONT_VERTICAL_METRICS[key];
|
|
2514
|
+
return m ? [`--font-ascent: ${m.ascent};`, `--font-descent: ${m.descent};`] : [];
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2282
2517
|
// src/font-weights.ts
|
|
2283
2518
|
var WEIGHT_RAMP_TARGETS = {
|
|
2284
2519
|
medium: 500,
|
|
@@ -2493,6 +2728,7 @@ function generateTypographyPrimitives(config, aliases = EMPTY_ALIASES) {
|
|
|
2493
2728
|
decls.push(`--font-body: ${fontStack(config.typography.body.family, aliases)};`);
|
|
2494
2729
|
decls.push(`--font-mono: ${fontStack(config.typography.mono.family, aliases)};`);
|
|
2495
2730
|
decls.push(...generateFontSizeDecls(config.typography.scale));
|
|
2731
|
+
decls.push(...generateFontMetricDecls(config.typography.body.family));
|
|
2496
2732
|
decls.push(...generateFontWeightDecls(config.typography));
|
|
2497
2733
|
const lineHeights = {
|
|
2498
2734
|
none: 1,
|
|
@@ -2987,6 +3223,8 @@ export {
|
|
|
2987
3223
|
collectBrandPassthrough,
|
|
2988
3224
|
hasBrandPassthrough,
|
|
2989
3225
|
applyOverrides,
|
|
3226
|
+
FONT_VERTICAL_METRICS,
|
|
3227
|
+
generateFontMetricDecls,
|
|
2990
3228
|
WEIGHT_RAMP_TARGETS,
|
|
2991
3229
|
loadedWeights,
|
|
2992
3230
|
declaresWeights,
|
package/dist/index.d.ts
CHANGED
|
@@ -1097,7 +1097,7 @@ var properties = {
|
|
|
1097
1097
|
},
|
|
1098
1098
|
"empty-state": {
|
|
1099
1099
|
type: "object",
|
|
1100
|
-
description: "Empty-state placard — surface, icon chip and copy scale. Keys: radius, text-color, gap, padding, bg, border, icon-size, icon-radius, icon-bg, icon-color, heading-font-family, heading-font-size, heading-font-weight, heading-color, description-font-size, description-color, actions-gap.",
|
|
1100
|
+
description: "Empty-state placard — surface, icon chip and copy scale. Keys: radius, text-color, gap, padding, bg, border, icon-size, icon-radius, icon-bg, icon-color, heading-font-family, heading-font-size, heading-font-weight, heading-color, description-font-size, description-color, error-color, actions-gap.",
|
|
1101
1101
|
additionalProperties: {
|
|
1102
1102
|
$ref: "#/$defs/componentTokenBinding"
|
|
1103
1103
|
}
|
|
@@ -1144,6 +1144,34 @@ var properties = {
|
|
|
1144
1144
|
$ref: "#/$defs/componentTokenBinding"
|
|
1145
1145
|
}
|
|
1146
1146
|
},
|
|
1147
|
+
input: {
|
|
1148
|
+
type: "object",
|
|
1149
|
+
description: "Input shape at the default `md` size. Each key falls back to the matching `--input-*-md` variable, so a scope that sets one still applies while the key is unbound; a bound key wins. Keys: md-height, md-padding, md-radius.",
|
|
1150
|
+
additionalProperties: {
|
|
1151
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1152
|
+
}
|
|
1153
|
+
},
|
|
1154
|
+
textarea: {
|
|
1155
|
+
type: "object",
|
|
1156
|
+
description: "Textarea shape at the default `md` size. Keys: padding, radius.",
|
|
1157
|
+
additionalProperties: {
|
|
1158
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1159
|
+
}
|
|
1160
|
+
},
|
|
1161
|
+
select: {
|
|
1162
|
+
type: "object",
|
|
1163
|
+
description: "Select trigger shape at the default `md` size. Keys: height, padding, radius.",
|
|
1164
|
+
additionalProperties: {
|
|
1165
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1166
|
+
}
|
|
1167
|
+
},
|
|
1168
|
+
"tag-input": {
|
|
1169
|
+
type: "object",
|
|
1170
|
+
description: "TagInput — the field around the tags, each held tag, and the opt-in typing slot (`entryAs=\"slot\"`). The slot follows the tag's shape unless its own keys are set. Keys: min-height, padding, radius, tag-height, tag-padding-x, tag-font-size, tag-font-weight, tag-radius, slot-height, slot-padding-x, slot-radius, slot-min-width.",
|
|
1171
|
+
additionalProperties: {
|
|
1172
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1173
|
+
}
|
|
1174
|
+
},
|
|
1147
1175
|
hairline: {
|
|
1148
1176
|
type: "object",
|
|
1149
1177
|
description: "The one switch for hairlines (VI-680). Every hairline rule, divider and ring reads its weight from `--hairline-width`, so `width: 0` removes them all at once. Independent of the `control` edge switch. Keys: width.",
|
|
@@ -1153,7 +1181,7 @@ var properties = {
|
|
|
1153
1181
|
},
|
|
1154
1182
|
control: {
|
|
1155
1183
|
type: "object",
|
|
1156
|
-
description: "The one switch for form-control edges (VI-655). Every form control draws its resting edge from these, so `edge-width: 0` removes every resting edge at once, dashed edges included, with no layout shift. Keys: edge-width, edge-color, edge-style, drop-edge-width, drop-edge-style, state-edge-width.",
|
|
1184
|
+
description: "The one switch for form-control edges (VI-655). Every form control draws its resting edge from these, so `edge-width: 0` removes every resting edge at once, dashed edges included, with no layout shift. Keys: edge-width, edge-color, edge-style, drop-edge-width, drop-edge-style, state-edge-width, invalid-ring-width, invalid-halo-width.",
|
|
1157
1185
|
additionalProperties: {
|
|
1158
1186
|
$ref: "#/$defs/componentTokenBinding"
|
|
1159
1187
|
}
|
|
@@ -1174,7 +1202,7 @@ var properties = {
|
|
|
1174
1202
|
},
|
|
1175
1203
|
button: {
|
|
1176
1204
|
type: "object",
|
|
1177
|
-
description: "Button type treatment and rounding. The unprefixed keys set every size at once; a size key (`dlg-radius`) overrides one size. Keys: text-transform, letter-spacing, radius, sm-font-size, sm-text-transform, sm-letter-spacing, sm-radius, md-font-size, md-text-transform, md-letter-spacing, md-radius, lg-font-size, lg-text-transform, lg-letter-spacing, lg-radius, dlg-font-size, dlg-text-transform, dlg-letter-spacing, dlg-radius, icon-size, icon-pad, icon-radius, icon-ghost-color.",
|
|
1205
|
+
description: "Button type treatment and rounding. The unprefixed keys set every size at once; a size key (`dlg-radius`) overrides one size. Keys: text-transform, letter-spacing, font-weight, radius, sm-font-size, sm-font-weight, sm-text-transform, sm-letter-spacing, sm-radius, md-font-size, md-font-weight, md-text-transform, md-letter-spacing, md-radius, lg-font-size, lg-font-weight, lg-text-transform, lg-letter-spacing, lg-radius, dlg-font-size, dlg-font-weight, dlg-text-transform, dlg-letter-spacing, dlg-radius, icon-size, icon-pad, icon-radius, icon-ghost-color.",
|
|
1178
1206
|
additionalProperties: {
|
|
1179
1207
|
$ref: "#/$defs/componentTokenBinding"
|
|
1180
1208
|
}
|
|
@@ -1195,7 +1223,14 @@ var properties = {
|
|
|
1195
1223
|
},
|
|
1196
1224
|
"save-status": {
|
|
1197
1225
|
type: "object",
|
|
1198
|
-
description: "SaveStatus readout — the fixed-width slot
|
|
1226
|
+
description: "SaveStatus readout — the fixed-width slot, its type, the Syncing ink and the Unsaved dot, so the readout never reflows its row. Keys: width, syncing-color, font-size, dot-size, unsaved-dot-size, font-family, text-transform, letter-spacing.",
|
|
1227
|
+
additionalProperties: {
|
|
1228
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1229
|
+
}
|
|
1230
|
+
},
|
|
1231
|
+
"segmented-control": {
|
|
1232
|
+
type: "object",
|
|
1233
|
+
description: "SegmentedControl — the well, its corner radius, the sliding pill, the ink and the state edge on it. The resting edge is the shared `control` edge. Keys: track-bg, radius, indicator-bg, indicator-text, indicator-edge, inactive-text, active-weight.",
|
|
1199
1234
|
additionalProperties: {
|
|
1200
1235
|
$ref: "#/$defs/componentTokenBinding"
|
|
1201
1236
|
}
|
|
@@ -1207,6 +1242,27 @@ var properties = {
|
|
|
1207
1242
|
$ref: "#/$defs/componentTokenBinding"
|
|
1208
1243
|
}
|
|
1209
1244
|
},
|
|
1245
|
+
"action-row": {
|
|
1246
|
+
type: "object",
|
|
1247
|
+
description: "ActionRow state fills, edge and geometry: rest, hover, open, selected and disabled each read their own token. Keys: min-height, padding, gap, radius, hover-bg, open-bg, selected-bg, selected-edge-color, disabled-opacity, title-weight, line-color, leading-color, leading-size, trailing-color.",
|
|
1248
|
+
additionalProperties: {
|
|
1249
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1250
|
+
}
|
|
1251
|
+
},
|
|
1252
|
+
"input-affix": {
|
|
1253
|
+
type: "object",
|
|
1254
|
+
description: "Input and NumberInput prefix and suffix: the gap between a fixed affix and the value, and the affix's ink. Keys: gap, color.",
|
|
1255
|
+
additionalProperties: {
|
|
1256
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1257
|
+
}
|
|
1258
|
+
},
|
|
1259
|
+
separator: {
|
|
1260
|
+
type: "object",
|
|
1261
|
+
description: "Separator rule colour, bare or either side of a label. Keys: color.",
|
|
1262
|
+
additionalProperties: {
|
|
1263
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1264
|
+
}
|
|
1265
|
+
},
|
|
1210
1266
|
"admin-ui": {
|
|
1211
1267
|
type: "object",
|
|
1212
1268
|
description: "Structural roles the admin-ui pattern owns. `marquee-family` is the display face for KPI hero figures and marquee page titles — the role the admin-ui portability audit named as the one piece of ENTR brand coupling a new theme must rebind. Keys: marquee-family.",
|
|
@@ -2279,4 +2335,36 @@ declare function cleanFontValue(val: string): string;
|
|
|
2279
2335
|
*/
|
|
2280
2336
|
declare function extractFromCSS(files: CSSFile[], name?: string): ExtractionResult;
|
|
2281
2337
|
|
|
2282
|
-
|
|
2338
|
+
/**
|
|
2339
|
+
* Vertical font metrics for centring a native <input>'s text (VI-684).
|
|
2340
|
+
*
|
|
2341
|
+
* A native input cannot be trimmed to its capital band without clipping
|
|
2342
|
+
* descenders and accents, so its capitals sit wherever the font's line box puts
|
|
2343
|
+
* them: half a line above the box centre plus (ascent - descent) / 2, each
|
|
2344
|
+
* rounded to a whole px. That depends on the face, so input.module.css reads
|
|
2345
|
+
* `--font-ascent` / `--font-descent` (unitless em ratios) to work out the
|
|
2346
|
+
* padding that lands the baseline on the right pixel.
|
|
2347
|
+
*
|
|
2348
|
+
* The ratios are Chromium's own `fontBoundingBoxAscent` / `Descent` at 1000px
|
|
2349
|
+
* (what its line layout rounds), measured once from the real faces by
|
|
2350
|
+
* scripts/measure-font-metrics.mjs and committed here. Measuring at build time
|
|
2351
|
+
* would put a network fetch and a font parser on every theme build.
|
|
2352
|
+
*
|
|
2353
|
+
* A face with no entry emits no tokens, and the input takes no nudge: it renders
|
|
2354
|
+
* as it did before VI-684 (within about 1px of centre), never worse.
|
|
2355
|
+
*
|
|
2356
|
+
* `system-ui` is platform-dependent. The entry is what Chromium resolves on
|
|
2357
|
+
* macOS (San Francisco). Windows and Linux resolve another face, so the nudge
|
|
2358
|
+
* there is a best effort; override it with --font-ascent / --font-descent.
|
|
2359
|
+
*/
|
|
2360
|
+
interface FontVerticalMetrics {
|
|
2361
|
+
/** Ascent as a fraction of the font size. */
|
|
2362
|
+
ascent: number;
|
|
2363
|
+
/** Descent as a fraction of the font size. */
|
|
2364
|
+
descent: number;
|
|
2365
|
+
}
|
|
2366
|
+
declare const FONT_VERTICAL_METRICS: Record<string, FontVerticalMetrics>;
|
|
2367
|
+
/** The `--font-ascent` / `--font-descent` declarations for a body family, or none when the face is unmeasured. */
|
|
2368
|
+
declare function generateFontMetricDecls(family: string): string[];
|
|
2369
|
+
|
|
2370
|
+
export { type BrandPassthrough, BrandResolution, BrandSlot, BrandSource, BrandStrategy, BrandStrategyContext, BrandStrategyIssue, BrandStrategyValidationResult, type CSSFile, ColorRole, type Confidence, DEFAULT_VISOR_BRAND, type ExtractedToken, type ExtractionResult, FONT_VERTICAL_METRICS, FONT_WEIGHT_ALIASES, type FontCoverageError, type FontCoverageResult, FontDisplayStrategy, type FontFaceDeclaration, FontResolution, FontResolveOptions, type FontVerticalMetrics, FullShadeScale, GeneratedPrimitives, GoogleFontEntry, OKLCH, ParsedColor, RGB, ResolvedThemeConfig, type ResolvedWeightRamp, SEMANTIC_MAP, SelectiveShadeScale, SemanticTokens, SerializedBrandStrategy, ShadeStep, TAILWIND_GRAY, ThemeBrandResult, ThemeData, ThemeFontResult, ThemeOutput, type ThemeValidationResult, VISOR_BRANDS_CDN, VISOR_CORE_SEMANTIC_ALIASES, VISOR_DEFAULT_BRAND_PATH, VISOR_FONTS_CDN, type ValidateOptions, type ValidationIssue, type ValidationSeverity, VisorBrand, VisorThemeConfig, VisorTypography, WEIGHT_RAMP_TARGETS, applyOverrides, assignSemanticTokens, buildVisorBrandUrl, buildVisorFontUrl, checkBrandStrategyCoherence, checkBrandStrategyStructure, clampToSrgb, cleanFontValue, collectBrandPassthrough, collectDeclaredProperties, compositeOverBackground, declaresWeights, exportTheme, extractFromCSS, formatFontCoverageError, generateDarkCss, generateFontMetricDecls, generateFontWeightDecls, generateFullBundleCss, generateLightCss, generatePreloadLinks, generatePrimitives, generatePrimitivesCss, generateSemanticAliasDecls, generateSemanticCss, generateShadeScale, generateStylesheetLinks, generateTheme, generateThemeData, generateThemeDataFromConfig, generateThemeFromConfig, getContrastRatio, getKnownTokenRefs, getLuminance, googleFontsCatalog, hasBrandPassthrough, hexToOklch, hexToRgb, isValidColor, isValidHex, isVisorThemeConfig, loadedWeights, lookupFontWeightAlias, lookupGoogleFont, matchLoadedWeight, normalizeHex, oklchToHex, parseCSSDeclarations, parseColor, parseConfig, parseFontFaceDeclarations, parseHex, parseHsla, parseOklch, parseRgba, resolveBrandSlot, resolveBrandSource, resolveConfig, resolveFont, resolveRoleWeight, resolveThemeBrand, resolveThemeFonts, resolveWeightRamp, rgbToHex, serializeBrandStrategy, serializeColor, validate, validateBrandStrategy, validateConfig, validateFontCoverage, visorTheme_schema as visorThemeSchema };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
COMPONENT_TOKEN_FAMILIES,
|
|
4
4
|
COMPONENT_TOKEN_FAMILY_BY_NAME,
|
|
5
5
|
DEFAULT_VISOR_BRAND,
|
|
6
|
+
FONT_VERTICAL_METRICS,
|
|
6
7
|
FONT_WEIGHT_ALIASES,
|
|
7
8
|
MATERIAL_TEXT_SLOTS,
|
|
8
9
|
TAILWIND_GRAY,
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
compositeOverBackground,
|
|
23
24
|
declaresWeights,
|
|
24
25
|
generateDarkCss,
|
|
26
|
+
generateFontMetricDecls,
|
|
25
27
|
generateFontWeightDecls,
|
|
26
28
|
generateFullBundleCss,
|
|
27
29
|
generateLightCss,
|
|
@@ -63,7 +65,7 @@ import {
|
|
|
63
65
|
rgbToOklch,
|
|
64
66
|
serializeColor,
|
|
65
67
|
validateComponentBindings
|
|
66
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-X2SWJPM2.js";
|
|
67
69
|
|
|
68
70
|
// src/fonts/validate-coverage.ts
|
|
69
71
|
var FONT_VAR_RE = /--font-(heading|display|body|sans|mono)\s*:\s*([^;]+);/g;
|
|
@@ -1133,7 +1135,7 @@ var visor_theme_schema_default = {
|
|
|
1133
1135
|
},
|
|
1134
1136
|
"empty-state": {
|
|
1135
1137
|
type: "object",
|
|
1136
|
-
description: "Empty-state placard \u2014 surface, icon chip and copy scale. Keys: radius, text-color, gap, padding, bg, border, icon-size, icon-radius, icon-bg, icon-color, heading-font-family, heading-font-size, heading-font-weight, heading-color, description-font-size, description-color, actions-gap.",
|
|
1138
|
+
description: "Empty-state placard \u2014 surface, icon chip and copy scale. Keys: radius, text-color, gap, padding, bg, border, icon-size, icon-radius, icon-bg, icon-color, heading-font-family, heading-font-size, heading-font-weight, heading-color, description-font-size, description-color, error-color, actions-gap.",
|
|
1137
1139
|
additionalProperties: {
|
|
1138
1140
|
$ref: "#/$defs/componentTokenBinding"
|
|
1139
1141
|
}
|
|
@@ -1180,6 +1182,34 @@ var visor_theme_schema_default = {
|
|
|
1180
1182
|
$ref: "#/$defs/componentTokenBinding"
|
|
1181
1183
|
}
|
|
1182
1184
|
},
|
|
1185
|
+
input: {
|
|
1186
|
+
type: "object",
|
|
1187
|
+
description: "Input shape at the default `md` size. Each key falls back to the matching `--input-*-md` variable, so a scope that sets one still applies while the key is unbound; a bound key wins. Keys: md-height, md-padding, md-radius.",
|
|
1188
|
+
additionalProperties: {
|
|
1189
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1190
|
+
}
|
|
1191
|
+
},
|
|
1192
|
+
textarea: {
|
|
1193
|
+
type: "object",
|
|
1194
|
+
description: "Textarea shape at the default `md` size. Keys: padding, radius.",
|
|
1195
|
+
additionalProperties: {
|
|
1196
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1197
|
+
}
|
|
1198
|
+
},
|
|
1199
|
+
select: {
|
|
1200
|
+
type: "object",
|
|
1201
|
+
description: "Select trigger shape at the default `md` size. Keys: height, padding, radius.",
|
|
1202
|
+
additionalProperties: {
|
|
1203
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1204
|
+
}
|
|
1205
|
+
},
|
|
1206
|
+
"tag-input": {
|
|
1207
|
+
type: "object",
|
|
1208
|
+
description: 'TagInput \u2014 the field around the tags, each held tag, and the opt-in typing slot (`entryAs="slot"`). The slot follows the tag\'s shape unless its own keys are set. Keys: min-height, padding, radius, tag-height, tag-padding-x, tag-font-size, tag-font-weight, tag-radius, slot-height, slot-padding-x, slot-radius, slot-min-width.',
|
|
1209
|
+
additionalProperties: {
|
|
1210
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1211
|
+
}
|
|
1212
|
+
},
|
|
1183
1213
|
hairline: {
|
|
1184
1214
|
type: "object",
|
|
1185
1215
|
description: "The one switch for hairlines (VI-680). Every hairline rule, divider and ring reads its weight from `--hairline-width`, so `width: 0` removes them all at once. Independent of the `control` edge switch. Keys: width.",
|
|
@@ -1189,7 +1219,7 @@ var visor_theme_schema_default = {
|
|
|
1189
1219
|
},
|
|
1190
1220
|
control: {
|
|
1191
1221
|
type: "object",
|
|
1192
|
-
description: "The one switch for form-control edges (VI-655). Every form control draws its resting edge from these, so `edge-width: 0` removes every resting edge at once, dashed edges included, with no layout shift. Keys: edge-width, edge-color, edge-style, drop-edge-width, drop-edge-style, state-edge-width.",
|
|
1222
|
+
description: "The one switch for form-control edges (VI-655). Every form control draws its resting edge from these, so `edge-width: 0` removes every resting edge at once, dashed edges included, with no layout shift. Keys: edge-width, edge-color, edge-style, drop-edge-width, drop-edge-style, state-edge-width, invalid-ring-width, invalid-halo-width.",
|
|
1193
1223
|
additionalProperties: {
|
|
1194
1224
|
$ref: "#/$defs/componentTokenBinding"
|
|
1195
1225
|
}
|
|
@@ -1210,7 +1240,7 @@ var visor_theme_schema_default = {
|
|
|
1210
1240
|
},
|
|
1211
1241
|
button: {
|
|
1212
1242
|
type: "object",
|
|
1213
|
-
description: "Button type treatment and rounding. The unprefixed keys set every size at once; a size key (`dlg-radius`) overrides one size. Keys: text-transform, letter-spacing, radius, sm-font-size, sm-text-transform, sm-letter-spacing, sm-radius, md-font-size, md-text-transform, md-letter-spacing, md-radius, lg-font-size, lg-text-transform, lg-letter-spacing, lg-radius, dlg-font-size, dlg-text-transform, dlg-letter-spacing, dlg-radius, icon-size, icon-pad, icon-radius, icon-ghost-color.",
|
|
1243
|
+
description: "Button type treatment and rounding. The unprefixed keys set every size at once; a size key (`dlg-radius`) overrides one size. Keys: text-transform, letter-spacing, font-weight, radius, sm-font-size, sm-font-weight, sm-text-transform, sm-letter-spacing, sm-radius, md-font-size, md-font-weight, md-text-transform, md-letter-spacing, md-radius, lg-font-size, lg-font-weight, lg-text-transform, lg-letter-spacing, lg-radius, dlg-font-size, dlg-font-weight, dlg-text-transform, dlg-letter-spacing, dlg-radius, icon-size, icon-pad, icon-radius, icon-ghost-color.",
|
|
1214
1244
|
additionalProperties: {
|
|
1215
1245
|
$ref: "#/$defs/componentTokenBinding"
|
|
1216
1246
|
}
|
|
@@ -1231,7 +1261,14 @@ var visor_theme_schema_default = {
|
|
|
1231
1261
|
},
|
|
1232
1262
|
"save-status": {
|
|
1233
1263
|
type: "object",
|
|
1234
|
-
description: "SaveStatus readout \u2014 the fixed-width slot
|
|
1264
|
+
description: "SaveStatus readout \u2014 the fixed-width slot, its type, the Syncing ink and the Unsaved dot, so the readout never reflows its row. Keys: width, syncing-color, font-size, dot-size, unsaved-dot-size, font-family, text-transform, letter-spacing.",
|
|
1265
|
+
additionalProperties: {
|
|
1266
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1267
|
+
}
|
|
1268
|
+
},
|
|
1269
|
+
"segmented-control": {
|
|
1270
|
+
type: "object",
|
|
1271
|
+
description: "SegmentedControl \u2014 the well, its corner radius, the sliding pill, the ink and the state edge on it. The resting edge is the shared `control` edge. Keys: track-bg, radius, indicator-bg, indicator-text, indicator-edge, inactive-text, active-weight.",
|
|
1235
1272
|
additionalProperties: {
|
|
1236
1273
|
$ref: "#/$defs/componentTokenBinding"
|
|
1237
1274
|
}
|
|
@@ -1243,6 +1280,27 @@ var visor_theme_schema_default = {
|
|
|
1243
1280
|
$ref: "#/$defs/componentTokenBinding"
|
|
1244
1281
|
}
|
|
1245
1282
|
},
|
|
1283
|
+
"action-row": {
|
|
1284
|
+
type: "object",
|
|
1285
|
+
description: "ActionRow state fills, edge and geometry: rest, hover, open, selected and disabled each read their own token. Keys: min-height, padding, gap, radius, hover-bg, open-bg, selected-bg, selected-edge-color, disabled-opacity, title-weight, line-color, leading-color, leading-size, trailing-color.",
|
|
1286
|
+
additionalProperties: {
|
|
1287
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1288
|
+
}
|
|
1289
|
+
},
|
|
1290
|
+
"input-affix": {
|
|
1291
|
+
type: "object",
|
|
1292
|
+
description: "Input and NumberInput prefix and suffix: the gap between a fixed affix and the value, and the affix's ink. Keys: gap, color.",
|
|
1293
|
+
additionalProperties: {
|
|
1294
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1295
|
+
}
|
|
1296
|
+
},
|
|
1297
|
+
separator: {
|
|
1298
|
+
type: "object",
|
|
1299
|
+
description: "Separator rule colour, bare or either side of a label. Keys: color.",
|
|
1300
|
+
additionalProperties: {
|
|
1301
|
+
$ref: "#/$defs/componentTokenBinding"
|
|
1302
|
+
}
|
|
1303
|
+
},
|
|
1246
1304
|
"admin-ui": {
|
|
1247
1305
|
type: "object",
|
|
1248
1306
|
description: "Structural roles the admin-ui pattern owns. `marquee-family` is the display face for KPI hero figures and marquee page titles \u2014 the role the admin-ui portability audit named as the one piece of ENTR brand coupling a new theme must rebind. Keys: marquee-family.",
|
|
@@ -4346,6 +4404,7 @@ export {
|
|
|
4346
4404
|
DEFAULT_BRAND_STRATEGY_SURFACES,
|
|
4347
4405
|
DEFAULT_BRAND_STRATEGY_TONE_STATES,
|
|
4348
4406
|
DEFAULT_VISOR_BRAND,
|
|
4407
|
+
FONT_VERTICAL_METRICS,
|
|
4349
4408
|
FONT_WEIGHT_ALIASES,
|
|
4350
4409
|
GOVERNS_WILDCARD,
|
|
4351
4410
|
SEMANTIC_MAP,
|
|
@@ -4373,6 +4432,7 @@ export {
|
|
|
4373
4432
|
extractFromCSS,
|
|
4374
4433
|
formatFontCoverageError,
|
|
4375
4434
|
generateDarkCss,
|
|
4435
|
+
generateFontMetricDecls,
|
|
4376
4436
|
generateFontWeightDecls,
|
|
4377
4437
|
generateFullBundleCss,
|
|
4378
4438
|
generateLightCss,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loworbitstudio/visor-theme-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Theme engine for the Visor design system — shade generation, token mapping, font resolution, and import/export for .visor.yaml themes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -517,7 +517,7 @@
|
|
|
517
517
|
},
|
|
518
518
|
"empty-state": {
|
|
519
519
|
"type": "object",
|
|
520
|
-
"description": "Empty-state placard — surface, icon chip and copy scale. Keys: radius, text-color, gap, padding, bg, border, icon-size, icon-radius, icon-bg, icon-color, heading-font-family, heading-font-size, heading-font-weight, heading-color, description-font-size, description-color, actions-gap.",
|
|
520
|
+
"description": "Empty-state placard — surface, icon chip and copy scale. Keys: radius, text-color, gap, padding, bg, border, icon-size, icon-radius, icon-bg, icon-color, heading-font-family, heading-font-size, heading-font-weight, heading-color, description-font-size, description-color, error-color, actions-gap.",
|
|
521
521
|
"additionalProperties": {
|
|
522
522
|
"$ref": "#/$defs/componentTokenBinding"
|
|
523
523
|
}
|
|
@@ -564,6 +564,34 @@
|
|
|
564
564
|
"$ref": "#/$defs/componentTokenBinding"
|
|
565
565
|
}
|
|
566
566
|
},
|
|
567
|
+
"input": {
|
|
568
|
+
"type": "object",
|
|
569
|
+
"description": "Input shape at the default `md` size. Each key falls back to the matching `--input-*-md` variable, so a scope that sets one still applies while the key is unbound; a bound key wins. Keys: md-height, md-padding, md-radius.",
|
|
570
|
+
"additionalProperties": {
|
|
571
|
+
"$ref": "#/$defs/componentTokenBinding"
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
"textarea": {
|
|
575
|
+
"type": "object",
|
|
576
|
+
"description": "Textarea shape at the default `md` size. Keys: padding, radius.",
|
|
577
|
+
"additionalProperties": {
|
|
578
|
+
"$ref": "#/$defs/componentTokenBinding"
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
"select": {
|
|
582
|
+
"type": "object",
|
|
583
|
+
"description": "Select trigger shape at the default `md` size. Keys: height, padding, radius.",
|
|
584
|
+
"additionalProperties": {
|
|
585
|
+
"$ref": "#/$defs/componentTokenBinding"
|
|
586
|
+
}
|
|
587
|
+
},
|
|
588
|
+
"tag-input": {
|
|
589
|
+
"type": "object",
|
|
590
|
+
"description": "TagInput — the field around the tags, each held tag, and the opt-in typing slot (`entryAs=\"slot\"`). The slot follows the tag's shape unless its own keys are set. Keys: min-height, padding, radius, tag-height, tag-padding-x, tag-font-size, tag-font-weight, tag-radius, slot-height, slot-padding-x, slot-radius, slot-min-width.",
|
|
591
|
+
"additionalProperties": {
|
|
592
|
+
"$ref": "#/$defs/componentTokenBinding"
|
|
593
|
+
}
|
|
594
|
+
},
|
|
567
595
|
"hairline": {
|
|
568
596
|
"type": "object",
|
|
569
597
|
"description": "The one switch for hairlines (VI-680). Every hairline rule, divider and ring reads its weight from `--hairline-width`, so `width: 0` removes them all at once. Independent of the `control` edge switch. Keys: width.",
|
|
@@ -573,7 +601,7 @@
|
|
|
573
601
|
},
|
|
574
602
|
"control": {
|
|
575
603
|
"type": "object",
|
|
576
|
-
"description": "The one switch for form-control edges (VI-655). Every form control draws its resting edge from these, so `edge-width: 0` removes every resting edge at once, dashed edges included, with no layout shift. Keys: edge-width, edge-color, edge-style, drop-edge-width, drop-edge-style, state-edge-width.",
|
|
604
|
+
"description": "The one switch for form-control edges (VI-655). Every form control draws its resting edge from these, so `edge-width: 0` removes every resting edge at once, dashed edges included, with no layout shift. Keys: edge-width, edge-color, edge-style, drop-edge-width, drop-edge-style, state-edge-width, invalid-ring-width, invalid-halo-width.",
|
|
577
605
|
"additionalProperties": {
|
|
578
606
|
"$ref": "#/$defs/componentTokenBinding"
|
|
579
607
|
}
|
|
@@ -594,7 +622,7 @@
|
|
|
594
622
|
},
|
|
595
623
|
"button": {
|
|
596
624
|
"type": "object",
|
|
597
|
-
"description": "Button type treatment and rounding. The unprefixed keys set every size at once; a size key (`dlg-radius`) overrides one size. Keys: text-transform, letter-spacing, radius, sm-font-size, sm-text-transform, sm-letter-spacing, sm-radius, md-font-size, md-text-transform, md-letter-spacing, md-radius, lg-font-size, lg-text-transform, lg-letter-spacing, lg-radius, dlg-font-size, dlg-text-transform, dlg-letter-spacing, dlg-radius, icon-size, icon-pad, icon-radius, icon-ghost-color.",
|
|
625
|
+
"description": "Button type treatment and rounding. The unprefixed keys set every size at once; a size key (`dlg-radius`) overrides one size. Keys: text-transform, letter-spacing, font-weight, radius, sm-font-size, sm-font-weight, sm-text-transform, sm-letter-spacing, sm-radius, md-font-size, md-font-weight, md-text-transform, md-letter-spacing, md-radius, lg-font-size, lg-font-weight, lg-text-transform, lg-letter-spacing, lg-radius, dlg-font-size, dlg-font-weight, dlg-text-transform, dlg-letter-spacing, dlg-radius, icon-size, icon-pad, icon-radius, icon-ghost-color.",
|
|
598
626
|
"additionalProperties": {
|
|
599
627
|
"$ref": "#/$defs/componentTokenBinding"
|
|
600
628
|
}
|
|
@@ -615,7 +643,14 @@
|
|
|
615
643
|
},
|
|
616
644
|
"save-status": {
|
|
617
645
|
"type": "object",
|
|
618
|
-
"description": "SaveStatus readout — the fixed-width slot
|
|
646
|
+
"description": "SaveStatus readout — the fixed-width slot, its type, the Syncing ink and the Unsaved dot, so the readout never reflows its row. Keys: width, syncing-color, font-size, dot-size, unsaved-dot-size, font-family, text-transform, letter-spacing.",
|
|
647
|
+
"additionalProperties": {
|
|
648
|
+
"$ref": "#/$defs/componentTokenBinding"
|
|
649
|
+
}
|
|
650
|
+
},
|
|
651
|
+
"segmented-control": {
|
|
652
|
+
"type": "object",
|
|
653
|
+
"description": "SegmentedControl \u2014 the well, its corner radius, the sliding pill, the ink and the state edge on it. The resting edge is the shared `control` edge. Keys: track-bg, radius, indicator-bg, indicator-text, indicator-edge, inactive-text, active-weight.",
|
|
619
654
|
"additionalProperties": {
|
|
620
655
|
"$ref": "#/$defs/componentTokenBinding"
|
|
621
656
|
}
|
|
@@ -627,6 +662,27 @@
|
|
|
627
662
|
"$ref": "#/$defs/componentTokenBinding"
|
|
628
663
|
}
|
|
629
664
|
},
|
|
665
|
+
"action-row": {
|
|
666
|
+
"type": "object",
|
|
667
|
+
"description": "ActionRow state fills, edge and geometry: rest, hover, open, selected and disabled each read their own token. Keys: min-height, padding, gap, radius, hover-bg, open-bg, selected-bg, selected-edge-color, disabled-opacity, title-weight, line-color, leading-color, leading-size, trailing-color.",
|
|
668
|
+
"additionalProperties": {
|
|
669
|
+
"$ref": "#/$defs/componentTokenBinding"
|
|
670
|
+
}
|
|
671
|
+
},
|
|
672
|
+
"input-affix": {
|
|
673
|
+
"type": "object",
|
|
674
|
+
"description": "Input and NumberInput prefix and suffix: the gap between a fixed affix and the value, and the affix's ink. Keys: gap, color.",
|
|
675
|
+
"additionalProperties": {
|
|
676
|
+
"$ref": "#/$defs/componentTokenBinding"
|
|
677
|
+
}
|
|
678
|
+
},
|
|
679
|
+
"separator": {
|
|
680
|
+
"type": "object",
|
|
681
|
+
"description": "Separator rule colour, bare or either side of a label. Keys: color.",
|
|
682
|
+
"additionalProperties": {
|
|
683
|
+
"$ref": "#/$defs/componentTokenBinding"
|
|
684
|
+
}
|
|
685
|
+
},
|
|
630
686
|
"admin-ui": {
|
|
631
687
|
"type": "object",
|
|
632
688
|
"description": "Structural roles the admin-ui pattern owns. `marquee-family` is the display face for KPI hero figures and marquee page titles — the role the admin-ui portability audit named as the one piece of ENTR brand coupling a new theme must rebind. Keys: marquee-family.",
|