@viax.io/uxm 4.36.0 → 4.37.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/CHANGELOG.md +7 -0
- package/README.md +74 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js.map +1 -1
- package/dist/previews/index.cjs +3 -0
- package/dist/previews/index.cjs.map +1 -1
- package/dist/previews/index.d.ts +3 -2
- package/dist/previews/index.d.ts.map +1 -1
- package/dist/previews/index.js +2 -0
- package/dist/previews/index.js.map +1 -1
- package/dist/studio/index.cjs.map +1 -1
- package/dist/studio/index.d.ts +2 -2
- package/dist/studio/index.js.map +1 -1
- package/dist/studio/lib/registry/app.cjs +52 -0
- package/dist/studio/lib/registry/app.cjs.map +1 -1
- package/dist/studio/lib/registry/app.d.ts.map +1 -1
- package/dist/studio/lib/registry/app.js +52 -0
- package/dist/studio/lib/registry/app.js.map +1 -1
- package/dist/studio/lib/registry/buttons.cjs +2 -2
- package/dist/studio/lib/registry/buttons.cjs.map +1 -1
- package/dist/studio/lib/registry/buttons.js +2 -2
- package/dist/studio/lib/registry/buttons.js.map +1 -1
- package/dist/studio/lib/registry/composite.cjs +1 -1
- package/dist/studio/lib/registry/composite.cjs.map +1 -1
- package/dist/studio/lib/registry/composite.js +1 -1
- package/dist/studio/lib/registry/composite.js.map +1 -1
- package/dist/studio/lib/registry/diagram.cjs +1 -1
- package/dist/studio/lib/registry/diagram.cjs.map +1 -1
- package/dist/studio/lib/registry/diagram.js +1 -1
- package/dist/studio/lib/registry/diagram.js.map +1 -1
- package/dist/studio/lib/registry/display.cjs +2 -2
- package/dist/studio/lib/registry/display.cjs.map +1 -1
- package/dist/studio/lib/registry/display.js +2 -2
- package/dist/studio/lib/registry/display.js.map +1 -1
- package/dist/studio/lib/registry/feedback.cjs +3 -3
- package/dist/studio/lib/registry/feedback.cjs.map +1 -1
- package/dist/studio/lib/registry/feedback.js +3 -3
- package/dist/studio/lib/registry/feedback.js.map +1 -1
- package/dist/studio/lib/registry/inputs.cjs +12 -12
- package/dist/studio/lib/registry/inputs.cjs.map +1 -1
- package/dist/studio/lib/registry/inputs.js +12 -12
- package/dist/studio/lib/registry/inputs.js.map +1 -1
- package/dist/studio/lib/types.cjs.map +1 -1
- package/dist/studio/persistence/generate-css.cjs +15 -0
- package/dist/studio/persistence/generate-css.cjs.map +1 -1
- package/dist/studio/persistence/generate-css.d.ts.map +1 -1
- package/dist/studio/persistence/generate-css.js +15 -0
- package/dist/studio/persistence/generate-css.js.map +1 -1
- package/dist/studio/shell/canvas.cjs +1 -0
- package/dist/studio/shell/canvas.cjs.map +1 -1
- package/dist/studio/shell/canvas.d.ts.map +1 -1
- package/dist/studio/shell/canvas.js +2 -0
- package/dist/studio/shell/canvas.js.map +1 -1
- package/dist/ui/calendar/calendar.cjs +3 -1
- package/dist/ui/calendar/calendar.cjs.map +1 -1
- package/dist/ui/calendar/calendar.d.ts +6 -2
- package/dist/ui/calendar/calendar.d.ts.map +1 -1
- package/dist/ui/calendar/calendar.js +3 -1
- package/dist/ui/calendar/calendar.js.map +1 -1
- package/dist/ui/currency-input/currency-input.cjs +3 -1
- package/dist/ui/currency-input/currency-input.cjs.map +1 -1
- package/dist/ui/currency-input/currency-input.d.ts +4 -2
- package/dist/ui/currency-input/currency-input.d.ts.map +1 -1
- package/dist/ui/currency-input/currency-input.js +3 -1
- package/dist/ui/currency-input/currency-input.js.map +1 -1
- package/dist/ui/date-input/date-input.cjs +2 -1
- package/dist/ui/date-input/date-input.cjs.map +1 -1
- package/dist/ui/date-input/date-input.d.ts +11 -1
- package/dist/ui/date-input/date-input.d.ts.map +1 -1
- package/dist/ui/date-input/date-input.js +2 -1
- package/dist/ui/date-input/date-input.js.map +1 -1
- package/dist/ui/editable-cell/editable-cell.cjs +20 -6
- package/dist/ui/editable-cell/editable-cell.cjs.map +1 -1
- package/dist/ui/editable-cell/editable-cell.d.ts +24 -1
- package/dist/ui/editable-cell/editable-cell.d.ts.map +1 -1
- package/dist/ui/editable-cell/editable-cell.js +20 -6
- package/dist/ui/editable-cell/editable-cell.js.map +1 -1
- package/dist/ui/file-upload/file-upload.cjs +36 -9
- package/dist/ui/file-upload/file-upload.cjs.map +1 -1
- package/dist/ui/file-upload/file-upload.d.ts +46 -4
- package/dist/ui/file-upload/file-upload.d.ts.map +1 -1
- package/dist/ui/file-upload/file-upload.js +36 -9
- package/dist/ui/file-upload/file-upload.js.map +1 -1
- package/dist/ui/index.cjs +12 -2
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.ts +5 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +7 -1
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/language-switcher/index.cjs +29 -0
- package/dist/ui/language-switcher/index.cjs.map +1 -0
- package/dist/ui/language-switcher/index.d.ts +3 -0
- package/dist/ui/language-switcher/index.d.ts.map +1 -0
- package/dist/ui/language-switcher/index.js +5 -0
- package/dist/ui/language-switcher/index.js.map +1 -0
- package/dist/ui/language-switcher/language-switcher-preview.cjs +137 -0
- package/dist/ui/language-switcher/language-switcher-preview.cjs.map +1 -0
- package/dist/ui/language-switcher/language-switcher-preview.d.ts +3 -0
- package/dist/ui/language-switcher/language-switcher-preview.d.ts.map +1 -0
- package/dist/ui/language-switcher/language-switcher-preview.js +113 -0
- package/dist/ui/language-switcher/language-switcher-preview.js.map +1 -0
- package/dist/ui/language-switcher/language-switcher.cjs +127 -0
- package/dist/ui/language-switcher/language-switcher.cjs.map +1 -0
- package/dist/ui/language-switcher/language-switcher.css +95 -0
- package/dist/ui/language-switcher/language-switcher.d.ts +73 -0
- package/dist/ui/language-switcher/language-switcher.d.ts.map +1 -0
- package/dist/ui/language-switcher/language-switcher.js +103 -0
- package/dist/ui/language-switcher/language-switcher.js.map +1 -0
- package/dist/ui/locale/index.cjs +33 -0
- package/dist/ui/locale/index.cjs.map +1 -0
- package/dist/ui/locale/index.d.ts +3 -0
- package/dist/ui/locale/index.d.ts.map +1 -0
- package/dist/ui/locale/index.js +7 -0
- package/dist/ui/locale/index.js.map +1 -0
- package/dist/ui/locale/locale.cjs +43 -0
- package/dist/ui/locale/locale.cjs.map +1 -0
- package/dist/ui/locale/locale.d.ts +49 -0
- package/dist/ui/locale/locale.d.ts.map +1 -0
- package/dist/ui/locale/locale.js +17 -0
- package/dist/ui/locale/locale.js.map +1 -0
- package/dist/ui/page-shell/page-shell.cjs.map +1 -1
- package/dist/ui/page-shell/page-shell.d.ts +1 -1
- package/dist/ui/page-shell/page-shell.d.ts.map +1 -1
- package/dist/ui/page-shell/page-shell.js.map +1 -1
- package/dist/ui/range-slider/range-slider.cjs +7 -3
- package/dist/ui/range-slider/range-slider.cjs.map +1 -1
- package/dist/ui/range-slider/range-slider.d.ts +17 -1
- package/dist/ui/range-slider/range-slider.d.ts.map +1 -1
- package/dist/ui/range-slider/range-slider.js +7 -3
- package/dist/ui/range-slider/range-slider.js.map +1 -1
- package/dist/ui/styles.css +2 -1
- package/package.json +4 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/studio/persistence/generate-css.ts"],"sourcesContent":["import type { AllOverrides } from './types';\nimport type { BrandConfig } from '../lib/types';\n\n/**\n * Pure CSS generator for UXM Studio overrides.\n *\n * Single source of truth (R5): the modo Hono `/api/uxm/save` route imports\n * `generateOverridesCss` from here instead of keeping its own copy. No Node\n * APIs — runs in browser (client export) and server alike.\n *\n * Emits a stylesheet from per-component style overrides plus brand config\n * (font, logo/icon URLs, brand token blocks). All attacker-controlled brand\n * values are sanitised before interpolation because the output is served to\n * every browser session.\n */\n\nconst BRAND_FONT_WEIGHTS = 'wght@400;500;600;700';\n\nexport function fontFileUrl(fontFamily: string): string {\n const encoded = fontFamily.trim().replace(/\\s+/g, '+');\n return `https://fonts.googleapis.com/css2?family=${encoded}:${BRAND_FONT_WEIGHTS}&display=swap`;\n}\n\nconst REAL_CSS_PROPS = new Set([\n 'background', 'backgroundColor',\n 'color',\n 'border', 'borderColor', 'borderRadius', 'borderWidth', 'borderStyle',\n 'padding', 'paddingX', 'paddingY', 'margin',\n 'gap', 'rowGap', 'columnGap',\n 'width', 'height', 'minWidth', 'maxWidth', 'minHeight', 'maxHeight',\n 'fontSize', 'fontWeight', 'fontFamily', 'lineHeight',\n 'opacity',\n 'cursor', 'display', 'position', 'overflow', 'direction',\n]);\n\n// Per-component selector overrides for the emitted rule. Defaults to\n// `.uxm-{id}`. Override when the atom renders the styled element via a PORTAL\n// (Listbox / Popover panel mounts to document.body): CSS custom properties\n// cascade DOWN from the declaring element, so vars on the in-page wrapper\n// never reach a portaled descendant. Emit on BOTH wrapper and panel selector.\nconst PER_COMPONENT_SELECTOR: Record<string, string> = {\n listbox: '.uxm-listbox, .uxm-listbox__panel',\n // Menu mirrors Listbox: the `.uxm-menu` wrapper lives in-page around the\n // trigger, but the `.uxm-menu__panel` portals to document.body, so vars on\n // the wrapper never reach it. Emit on both so the panel carries them.\n menu: '.uxm-menu, .uxm-menu__panel',\n // PhoneInput no longer needs a panel-scoped selector: its country picker\n // now delegates to the shared `Listbox`, whose portaled panel already gets\n // its vars via the `listbox` entry above. All `--uxm-phone-input-*` knobs\n // target the in-page field, so the default `.uxm-phone-input` selector is\n // correct.\n};\n\n// One knob → one variable. A multi-target (string[]) form was briefly added so\n// Card's Row Gap could write both the Stack and Cluster gap vars; that was the\n// only use, and it was the wrong shape (see the `card` entry below), so the\n// mapping stays single-target on purpose — a knob that themes a SIBLING atom's\n// var cannot win against that atom's own knob.\nconst PER_COMPONENT_MAPPING: Record<string, Record<string, string>> = {\n 'input-with-icon': {\n backgroundColor: '--uxm-input-with-icon-bg',\n borderColor: '--uxm-input-with-icon-border-color',\n borderRadius: '--uxm-input-with-icon-radius',\n paddingX: '--uxm-input-with-icon-padding-x',\n paddingY: '--uxm-input-with-icon-padding-y',\n fontSize: '--uxm-input-with-icon-font-size',\n color: '--uxm-input-with-icon-color',\n },\n 'input-text': {\n backgroundColor: '--uxm-input-text-bg',\n borderColor: '--uxm-input-text-border-color',\n color: '--uxm-input-text-color',\n borderRadius: '--uxm-input-text-border-radius',\n paddingX: '--uxm-input-text-padding-x',\n paddingY: '--uxm-input-text-padding-y',\n fontSize: '--uxm-input-text-font-size',\n },\n 'number-input': {\n backgroundColor: '--uxm-number-input-bg',\n borderColor: '--uxm-number-input-border-color',\n color: '--uxm-number-input-color',\n borderRadius: '--uxm-number-input-border-radius',\n paddingX: '--uxm-number-input-padding-x',\n paddingY: '--uxm-number-input-padding-y',\n fontSize: '--uxm-number-input-font-size',\n },\n // Without this entry `fontSize` falls through REAL_CSS_PROPS and emits a\n // literal `font-size` on `.uxm-color-input`, which the atom's own children\n // (`__value-field`, `__format`) always beat — so the knob did nothing at all.\n 'color-input': {\n fontSize: '--uxm-color-input-font-size',\n },\n // Every key here collides with REAL_CSS_PROPS, where the generic fallback\n // emits a REAL property on `.uxm-code-editor` instead of a var. That root is\n // pure chrome — the text lives in `__input` / `__gutter-lines`, which declare\n // their own `color` / `font-size` / `line-height` and always beat inherited\n // values, so Text / Font Size / Line Height would be silent no-ops. Padding is\n // worse than a no-op: `padding-inline` on the root pads OUTSIDE the code while\n // `--uxm-code-editor-padding-x` stays unset, so the gutter's absolutely\n // positioned `left` keeps its 14px default and the numbers leave their column.\n // Same defect as the `color-input` entry above.\n 'code-editor': {\n backgroundColor: '--uxm-code-editor-bg',\n borderColor: '--uxm-code-editor-border-color',\n color: '--uxm-code-editor-color',\n borderRadius: '--uxm-code-editor-border-radius',\n paddingX: '--uxm-code-editor-padding-x',\n paddingY: '--uxm-code-editor-padding-y',\n fontSize: '--uxm-code-editor-font-size',\n lineHeight: '--uxm-code-editor-line-height',\n minHeight: '--uxm-code-editor-min-height',\n },\n 'currency-input': {\n backgroundColor: '--uxm-currency-input-background-color',\n borderColor: '--uxm-currency-input-border-color',\n borderRadius: '--uxm-currency-input-border-radius',\n paddingX: '--uxm-currency-input-padding-x',\n paddingY: '--uxm-currency-input-padding-y',\n fontSize: '--uxm-currency-input-font-size',\n color: '--uxm-currency-input-color',\n },\n textarea: {\n backgroundColor: '--uxm-textarea-bg',\n borderColor: '--uxm-textarea-border-color',\n color: '--uxm-textarea-color',\n minHeight: '--uxm-textarea-min-height',\n borderRadius: '--uxm-textarea-border-radius',\n paddingX: '--uxm-textarea-padding-x',\n paddingY: '--uxm-textarea-padding-y',\n fontSize: '--uxm-textarea-font-size',\n },\n 'file-upload': {\n backgroundColor: '--uxm-file-upload-bg',\n borderColor: '--uxm-file-upload-border-color',\n color: '--uxm-file-upload-color',\n borderRadius: '--uxm-file-upload-border-radius',\n borderStyle: '--uxm-file-upload-border-style',\n borderWidth: '--uxm-file-upload-border-width',\n paddingX: '--uxm-file-upload-padding-x',\n paddingY: '--uxm-file-upload-padding-y',\n minHeight: '--uxm-file-upload-min-height',\n gap: '--uxm-file-upload-gap',\n rowGap: '--uxm-file-upload-row-gap',\n },\n 'select-dropdown': {\n backgroundColor: '--uxm-select-dropdown-bg',\n borderColor: '--uxm-select-dropdown-border-color',\n color: '--uxm-select-dropdown-color',\n borderRadius: '--uxm-select-dropdown-border-radius',\n paddingX: '--uxm-select-dropdown-padding-x',\n paddingY: '--uxm-select-dropdown-padding-y',\n fontSize: '--uxm-select-dropdown-font-size',\n },\n 'date-input': {\n backgroundColor: '--uxm-date-input-background-color',\n borderColor: '--uxm-date-input-border-color',\n borderRadius: '--uxm-date-input-border-radius',\n paddingX: '--uxm-date-input-padding-x',\n paddingY: '--uxm-date-input-padding-y',\n fontSize: '--uxm-date-input-font-size',\n color: '--uxm-date-input-color',\n },\n 'password-input': {\n backgroundColor: '--uxm-password-input-background-color',\n borderColor: '--uxm-password-input-border-color',\n borderRadius: '--uxm-password-input-border-radius',\n paddingX: '--uxm-password-input-padding-x',\n paddingY: '--uxm-password-input-padding-y',\n fontSize: '--uxm-password-input-font-size',\n color: '--uxm-password-input-color',\n },\n 'time-input': {\n backgroundColor: '--uxm-time-input-background-color',\n borderColor: '--uxm-time-input-border-color',\n borderRadius: '--uxm-time-input-border-radius',\n paddingX: '--uxm-time-input-padding-x',\n paddingY: '--uxm-time-input-padding-y',\n fontSize: '--uxm-time-input-font-size',\n color: '--uxm-time-input-color',\n },\n 'phone-input': {\n backgroundColor: '--uxm-phone-input-background-color',\n borderColor: '--uxm-phone-input-border-color',\n borderRadius: '--uxm-phone-input-border-radius',\n paddingX: '--uxm-phone-input-padding-x',\n paddingY: '--uxm-phone-input-padding-y',\n fontSize: '--uxm-phone-input-font-size',\n color: '--uxm-phone-input-color',\n },\n calendar: {\n backgroundColor: '--uxm-calendar-background-color',\n borderColor: '--uxm-calendar-border-color',\n borderRadius: '--uxm-calendar-border-radius',\n padding: '--uxm-calendar-padding',\n },\n tabs: {\n gap: '--uxm-tabs-gap',\n paddingX: '--uxm-tabs-padding-x',\n paddingY: '--uxm-tabs-padding-y',\n fontSize: '--uxm-tabs-font-size',\n fontWeight: '--uxm-tabs-font-weight',\n },\n 'tabs-underline': {\n gap: '--uxm-tabs-underline-gap',\n paddingX: '--uxm-tabs-underline-padding-x',\n paddingY: '--uxm-tabs-underline-padding-y',\n fontSize: '--uxm-tabs-underline-font-size',\n fontWeight: '--uxm-tabs-underline-font-weight',\n },\n 'filter-tabs': {\n gap: '--uxm-filter-tabs-gap',\n paddingX: '--uxm-filter-tabs-padding-x',\n paddingY: '--uxm-filter-tabs-padding-y',\n fontSize: '--uxm-filter-tabs-font-size',\n fontWeight: '--uxm-filter-tabs-font-weight',\n },\n 'view-switcher': {\n gap: '--uxm-view-switcher-gap',\n },\n 'button-group': {\n borderColor: '--uxm-button-group-border-color',\n borderRadius: '--uxm-button-group-border-radius',\n paddingX: '--uxm-button-group-padding-x',\n paddingY: '--uxm-button-group-padding-y',\n fontSize: '--uxm-button-group-font-size',\n },\n checkbox: {\n borderRadius: '--uxm-checkbox-border-radius',\n gap: '--uxm-checkbox-gap',\n },\n card: {\n backgroundColor: '--uxm-card-bg',\n borderColor: '--uxm-card-border-color',\n borderRadius: '--uxm-card-radius',\n padding: '--uxm-card-padding',\n // `gap` (\"Header Gap\") collides with REAL_CSS_PROPS — the generic fallback\n // would emit a literal `gap` property that `.uxm-card` never activates (the\n // card is only a flex column via the `--gap` modifier). Route it to the var\n // the modifier actually reads.\n //\n // There is deliberately NO Card knob for the CONTENT's row gap. It looks\n // like it belongs here, but the row gap is owned by the nested Stack /\n // Cluster, which already have their own Gap knobs — and those emit\n // `--uxm-stack-gap` DIRECTLY on `.uxm-stack`, where a directly-set custom\n // property always beats one inherited from `.uxm-card`. A Card-side knob\n // would therefore lose the moment anyone themed Stack, while also leaking\n // to every Stack/Cluster at any depth inside any card (custom properties\n // inherit). One owner per visual property; Card owns only its own gap.\n gap: '--uxm-card-gap',\n },\n 'toggle-switch': {\n width: '--uxm-toggle-switch-width',\n height: '--uxm-toggle-switch-height',\n },\n 'radio-group': {\n gap: '--uxm-radio-group-gap',\n },\n loader: {\n color: '--uxm-loader-color',\n gap: '--uxm-loader-gap',\n },\n 'data-table': {\n borderColor: '--uxm-data-table-border-color',\n fontSize: '--uxm-data-table-font-size',\n borderRadius: '--uxm-data-table-border-radius',\n },\n 'app-sidebar': {\n borderColor: '--uxm-app-sidebar-border-color',\n backgroundColor: '--uxm-app-sidebar-background-color',\n },\n // Every key here collides with REAL_CSS_PROPS, where the generic fallback\n // emits the LITERAL css property on the root selector instead of the var.\n //\n // For `fontSize` / `fontWeight` that is a silent no-op rather than a mere\n // detour: the atom reads those vars on `.uxm-sidebar-nav-trigger__value`, and\n // a `font-size` landing on the root is beaten by the child's own declaration.\n // The live workbench hides it — that path projects custom properties through\n // the preview's `buildVars`, so the knob only dies once a brand is SAVED.\n //\n // The rest (padding, gap, radius) do sit on the root and would survive the\n // literal route on source order alone, but they are mapped too: the sibling\n // `sidebar-nav-item` maps all six, and leaving half of them to cascade luck\n // invites exactly the question of which half.\n 'sidebar-nav-trigger': {\n paddingX: '--uxm-sidebar-nav-trigger-padding-x',\n paddingY: '--uxm-sidebar-nav-trigger-padding-y',\n fontSize: '--uxm-sidebar-nav-trigger-font-size',\n fontWeight: '--uxm-sidebar-nav-trigger-font-weight',\n gap: '--uxm-sidebar-nav-trigger-gap',\n borderRadius: '--uxm-sidebar-nav-trigger-border-radius',\n },\n 'sidebar-nav-item': {\n paddingX: '--uxm-sidebar-nav-item-padding-x',\n paddingY: '--uxm-sidebar-nav-item-padding-y',\n fontSize: '--uxm-sidebar-nav-item-font-size',\n fontWeight: '--uxm-sidebar-nav-item-font-weight',\n gap: '--uxm-sidebar-nav-item-gap',\n borderRadius: '--uxm-sidebar-nav-item-border-radius',\n },\n 'explorer-list-item': {\n paddingX: '--uxm-explorer-list-item-padding-x',\n paddingY: '--uxm-explorer-list-item-padding-y',\n fontSize: '--uxm-explorer-list-item-font-size',\n fontWeight: '--uxm-explorer-list-item-font-weight',\n gap: '--uxm-explorer-list-item-gap',\n borderRadius: '--uxm-explorer-list-item-border-radius',\n },\n 'app-top-bar': {\n borderColor: '--uxm-app-top-bar-border-color',\n backgroundColor: '--uxm-app-top-bar-background-color',\n height: '--uxm-app-top-bar-height',\n paddingX: '--uxm-app-top-bar-padding-x',\n gap: '--uxm-app-top-bar-gap',\n },\n 'explorer-section': {\n paddingX: '--uxm-explorer-section-padding-x',\n paddingY: '--uxm-explorer-section-padding-y',\n borderRadius: '--uxm-explorer-section-border-radius',\n gap: '--uxm-explorer-section-gap',\n fontSize: '--uxm-explorer-section-font-size',\n fontWeight: '--uxm-explorer-section-font-weight',\n },\n 'number-field': {\n backgroundColor: '--uxm-number-field-input-bg',\n borderColor: '--uxm-number-field-input-border',\n color: '--uxm-number-field-input-color',\n borderRadius: '--uxm-number-field-input-radius',\n paddingX: '--uxm-number-field-input-padding-x',\n paddingY: '--uxm-number-field-input-padding-y',\n fontSize: '--uxm-number-field-font-size',\n gap: '--uxm-number-field-gap',\n },\n 'icon-button': {\n color: '--uxm-icon-button-color',\n backgroundColor: '--uxm-icon-button-bg',\n hoverBackgroundColor: '--uxm-icon-button-hover-bg',\n activeBackgroundColor: '--uxm-icon-button-active-bg',\n borderRadius: '--uxm-icon-button-radius',\n },\n 'button-primary': {\n backgroundColor: '--uxm-button-primary-background-color',\n color: '--uxm-button-primary-color',\n borderRadius: '--uxm-button-primary-border-radius',\n fontSize: '--uxm-button-primary-font-size',\n fontWeight: '--uxm-button-primary-font-weight',\n paddingX: '--uxm-button-primary-padding-x',\n paddingY: '--uxm-button-primary-padding-y',\n },\n 'button-secondary': {\n backgroundColor: '--uxm-button-secondary-background-color',\n color: '--uxm-button-secondary-color',\n borderColor: '--uxm-button-secondary-border-color',\n borderRadius: '--uxm-button-secondary-border-radius',\n fontSize: '--uxm-button-secondary-font-size',\n fontWeight: '--uxm-button-secondary-font-weight',\n paddingX: '--uxm-button-secondary-padding-x',\n paddingY: '--uxm-button-secondary-padding-y',\n },\n 'button-tertiary': {\n backgroundColor: '--uxm-button-tertiary-background-color',\n color: '--uxm-button-tertiary-color',\n borderColor: '--uxm-button-tertiary-border-color',\n borderRadius: '--uxm-button-tertiary-border-radius',\n fontSize: '--uxm-button-tertiary-font-size',\n fontWeight: '--uxm-button-tertiary-font-weight',\n paddingX: '--uxm-button-tertiary-padding-x',\n paddingY: '--uxm-button-tertiary-padding-y',\n },\n 'button-ghost': {\n backgroundColor: '--uxm-button-ghost-background-color',\n color: '--uxm-button-ghost-color',\n borderRadius: '--uxm-button-ghost-border-radius',\n fontSize: '--uxm-button-ghost-font-size',\n fontWeight: '--uxm-button-ghost-font-weight',\n paddingX: '--uxm-button-ghost-padding-x',\n paddingY: '--uxm-button-ghost-padding-y',\n },\n 'button-danger': {\n backgroundColor: '--uxm-button-danger-background-color',\n color: '--uxm-button-danger-color',\n borderColor: '--uxm-button-danger-border-color',\n borderRadius: '--uxm-button-danger-border-radius',\n fontSize: '--uxm-button-danger-font-size',\n fontWeight: '--uxm-button-danger-font-weight',\n paddingX: '--uxm-button-danger-padding-x',\n paddingY: '--uxm-button-danger-padding-y',\n },\n 'button-with-icon': {\n backgroundColor: '--uxm-button-with-icon-background-color',\n color: '--uxm-button-with-icon-color',\n borderColor: '--uxm-button-with-icon-border-color',\n borderRadius: '--uxm-button-with-icon-border-radius',\n fontSize: '--uxm-button-with-icon-font-size',\n fontWeight: '--uxm-button-with-icon-font-weight',\n paddingX: '--uxm-button-with-icon-padding-x',\n paddingY: '--uxm-button-with-icon-padding-y',\n },\n 'button-icon': {\n backgroundColor: '--uxm-button-icon-background-color',\n color: '--uxm-button-icon-color',\n borderRadius: '--uxm-button-icon-border-radius',\n },\n 'back-link': {\n color: '--uxm-back-link-color',\n fontSize: '--uxm-back-link-font-size',\n fontWeight: '--uxm-back-link-font-weight',\n gap: '--uxm-back-link-gap',\n },\n breadcrumb: {\n fontSize: '--uxm-breadcrumb-font-size',\n gap: '--uxm-breadcrumb-gap',\n },\n disclosure: {\n paddingX: '--uxm-disclosure-padding-x',\n paddingY: '--uxm-disclosure-padding-y',\n fontSize: '--uxm-disclosure-font-size',\n gap: '--uxm-disclosure-gap',\n borderRadius: '--uxm-disclosure-border-radius',\n },\n 'side-flexpane': {\n paddingX: '--uxm-side-flexpane-padding-x',\n paddingY: '--uxm-side-flexpane-padding-y',\n backgroundColor: '--uxm-side-flexpane-background-color',\n borderColor: '--uxm-side-flexpane-border-color',\n borderRadius: '--uxm-side-flexpane-border-radius',\n width: '--uxm-side-flexpane-width',\n },\n 'list-item': {\n paddingX: '--uxm-list-item-padding-x',\n paddingY: '--uxm-list-item-padding-y',\n fontSize: '--uxm-list-item-font-size',\n gap: '--uxm-list-item-gap',\n borderRadius: '--uxm-list-item-border-radius',\n borderColor: '--uxm-list-item-border-color',\n },\n 'pill-select': {\n backgroundColor: '--uxm-pill-select-bg',\n borderColor: '--uxm-pill-select-border-color',\n paddingX: '--uxm-pill-select-padding-x',\n paddingY: '--uxm-pill-select-padding-y',\n },\n modal: {\n backgroundColor: '--uxm-modal-background-color',\n borderColor: '--uxm-modal-border-color',\n borderRadius: '--uxm-modal-border-radius',\n paddingX: '--uxm-modal-padding-x',\n paddingY: '--uxm-modal-padding-y',\n },\n toast: {\n backgroundColor: '--uxm-toast-background-color',\n color: '--uxm-toast-color',\n borderColor: '--uxm-toast-border-color',\n borderRadius: '--uxm-toast-border-radius',\n paddingX: '--uxm-toast-padding-x',\n paddingY: '--uxm-toast-padding-y',\n fontSize: '--uxm-toast-font-size',\n },\n avatar: {\n backgroundColor: '--uxm-avatar-background-color',\n borderColor: '--uxm-avatar-border-color',\n borderRadius: '--uxm-avatar-border-radius',\n borderWidth: '--uxm-avatar-border-width',\n color: '--uxm-avatar-color',\n fontSize: '--uxm-avatar-font-size',\n fontWeight: '--uxm-avatar-font-weight',\n },\n banner: {\n borderRadius: '--uxm-banner-border-radius',\n paddingX: '--uxm-banner-padding-x',\n paddingY: '--uxm-banner-padding-y',\n fontSize: '--uxm-banner-font-size',\n },\n 'bulk-action-bar': {\n backgroundColor: '--uxm-bulk-action-bar-background-color',\n color: '--uxm-bulk-action-bar-color',\n borderColor: '--uxm-bulk-action-bar-border-color',\n borderRadius: '--uxm-bulk-action-bar-border-radius',\n paddingX: '--uxm-bulk-action-bar-padding-x',\n paddingY: '--uxm-bulk-action-bar-padding-y',\n gap: '--uxm-bulk-action-bar-gap',\n fontSize: '--uxm-bulk-action-bar-font-size',\n },\n cluster: {\n gap: '--uxm-cluster-gap',\n },\n 'config-component-row': {\n padding: '--uxm-config-component-row-padding',\n borderRadius: '--uxm-config-component-row-radius',\n },\n 'config-segment-item': {\n paddingX: '--uxm-config-segment-item-padding-x',\n paddingY: '--uxm-config-segment-item-padding-y',\n borderRadius: '--uxm-config-segment-item-radius',\n },\n 'detail-section': {\n backgroundColor: '--uxm-detail-section-bg',\n borderColor: '--uxm-detail-section-border-color',\n borderRadius: '--uxm-detail-section-radius',\n padding: '--uxm-detail-section-padding',\n },\n divider: {\n color: '--uxm-divider-color',\n gap: '--uxm-divider-gap',\n },\n 'editable-cell': {\n // Dimensions are per-size keys (smallPaddingX, mediumMaxWidth, …) that\n // resolve via the generic `--uxm-editable-cell-{kebab(key)}` fallback in\n // toCSS; only the value colour needs an explicit entry (`color` is in\n // REAL_CSS_PROPS, so the fallback would emit a real CSS property that\n // outranks the component layer).\n color: '--uxm-editable-cell-color',\n // RETIRED knobs, kept mapped on purpose. The per-size split replaced these\n // four, but `generateOverridesCss` emits whatever keys are PERSISTED — not\n // what the registry currently declares — so a config saved before the split\n // still carries them. Without an entry here they'd fall through to\n // REAL_CSS_PROPS / the paddingX-paddingY special case in toCSS and emit\n // REAL `min-height` / `padding-inline` / `padding-block` declarations on\n // `.uxm-editable-cell`, which land in a sheet loaded after the library CSS\n // and would hard-override BOTH size presets (killing `medium`) and\n // resurrect the min-height the size work deliberately removed. Mapped to\n // their old, now-unread custom properties they are true no-ops instead.\n // Safe to delete once persisted overrides are pruned against the registry.\n minHeight: '--uxm-editable-cell-min-height',\n paddingX: '--uxm-editable-cell-padding-x',\n paddingY: '--uxm-editable-cell-padding-y',\n // `maxWidth` joined them when the cap went per-size: it is in\n // REAL_CSS_PROPS, so without this it would emit a real `max-width` that\n // pins BOTH presets (and would silently re-cap `medium`, whose whole point\n // is filling its container).\n maxWidth: '--uxm-editable-cell-max-width',\n },\n 'empty-state': {\n padding: '--uxm-empty-state-padding',\n },\n 'form-field': {\n gap: '--uxm-form-field-gap',\n // Per-tint label colours — the component reads `--uxm-form-field-label-\n // tint-*` (see form-field.scss tone classes); the generic kebab fallback\n // would emit `--uxm-form-field-tint-strong-color` etc., which nothing\n // reads, so the saved colour would silently not apply.\n tintStrongColor: '--uxm-form-field-label-tint-strong',\n tintDefaultColor: '--uxm-form-field-label-tint-default',\n tintMutedColor: '--uxm-form-field-label-tint-muted',\n // MIGRATION — `labelColor` was the single label-colour knob the tints\n // replaced. It is gone from the registry, but `generateOverridesCss` emits\n // whatever is PERSISTED, and its generic fallback lands on\n // `--uxm-form-field-label-color` — the very var the tint classes assign,\n // at equal specificity from a later sheet. Left alone it would beat ALL\n // THREE tints and silently disable them, with no knob left in the panel to\n // notice or clear it. Routed to the STRONG tint instead: strong was the\n // old (only) label colour and is still the default tone, so a pre-split\n // theme keeps the exact look it saved. A newly-saved `tintStrongColor`\n // still wins — overrides are appended, so it emits after this one.\n labelColor: '--uxm-form-field-label-tint-strong',\n },\n 'icon-tile': {\n borderRadius: '--uxm-icon-tile-radius',\n iconBg: '--uxm-icon-tile-bg',\n iconColor: '--uxm-icon-tile-color',\n },\n icon: {\n color: '--uxm-icon-color',\n },\n 'inline-action': {\n color: '--uxm-inline-action-color',\n fontSize: '--uxm-inline-action-font-size',\n fontWeight: '--uxm-inline-action-font-weight',\n gap: '--uxm-inline-action-gap',\n },\n 'inline-filter': {\n gap: '--uxm-inline-filter-gap',\n },\n 'lifecycle-edge-label': {\n paddingX: '--uxm-lifecycle-edge-label-padding-x',\n paddingY: '--uxm-lifecycle-edge-label-padding-y',\n borderRadius: '--uxm-lifecycle-edge-label-radius',\n borderWidth: '--uxm-lifecycle-edge-label-border-width',\n fontSize: '--uxm-lifecycle-edge-label-font-size',\n fontWeight: '--uxm-lifecycle-edge-label-font-weight',\n },\n // Same rule as lifecycle-group-box below — only the REAL_CSS_PROPS collisions\n // need an entry. `color` is the one that matters: a real `color` declaration\n // on `.uxm-lifecycle-drop-slot` from a later sheet would paint the text but\n // leave the dashes on the token, splitting a pair the atom deliberately drives\n // from one variable. The shape-scoped knobs (`cardRadius`, `pillFontSize`, …)\n // and `bg` need nothing: the generic `--uxm-{id}-{kebab}` rule already lands\n // on the names the stylesheet reads.\n 'lifecycle-drop-slot': {\n borderColor: '--uxm-lifecycle-drop-slot-border-color',\n borderStyle: '--uxm-lifecycle-drop-slot-border-style',\n borderWidth: '--uxm-lifecycle-drop-slot-border-width',\n color: '--uxm-lifecycle-drop-slot-color',\n },\n // Only the knobs whose keys collide with REAL_CSS_PROPS need an entry: left\n // to the generic path they'd emit a real `background-color` / `border-width` /\n // `padding` on `.uxm-lifecycle-group-box` from a later sheet, hard-overriding\n // the rule's own `var(--uxm-… , token)` chain — and `padding` is read BY THE\n // CONSUMER off the custom property to inset the group's members, so a real\n // declaration would leave that value unreadable.\n //\n // `blur` and the three `target*` knobs are absent on purpose: the generic\n // `--uxm-{id}-{kebab}` rule already lands on the names the stylesheet reads.\n 'lifecycle-group-box': {\n backgroundColor: '--uxm-lifecycle-group-box-bg',\n borderColor: '--uxm-lifecycle-group-box-border-color',\n borderWidth: '--uxm-lifecycle-group-box-border-width',\n borderRadius: '--uxm-lifecycle-group-box-radius',\n padding: '--uxm-lifecycle-group-box-padding',\n },\n 'lifecycle-minimap': {\n backgroundColor: '--uxm-lifecycle-minimap-bg',\n borderColor: '--uxm-lifecycle-minimap-border-color',\n borderRadius: '--uxm-lifecycle-minimap-radius',\n width: '--uxm-lifecycle-minimap-width',\n height: '--uxm-lifecycle-minimap-height',\n },\n 'lifecycle-node-card': {\n backgroundColor: '--uxm-lifecycle-node-card-bg',\n borderColor: '--uxm-lifecycle-node-card-border-color',\n borderRadius: '--uxm-lifecycle-node-card-radius',\n paddingX: '--uxm-lifecycle-node-card-padding-x',\n paddingY: '--uxm-lifecycle-node-card-padding-y',\n width: '--uxm-lifecycle-node-card-width',\n minHeight: '--uxm-lifecycle-node-card-min-height',\n },\n 'lifecycle-terminal': {\n backgroundColor: '--uxm-lifecycle-terminal-bg',\n borderColor: '--uxm-lifecycle-terminal-border-color',\n color: '--uxm-lifecycle-terminal-color',\n borderRadius: '--uxm-lifecycle-terminal-radius',\n width: '--uxm-lifecycle-terminal-width',\n height: '--uxm-lifecycle-terminal-height',\n fontSize: '--uxm-lifecycle-terminal-font-size',\n fontWeight: '--uxm-lifecycle-terminal-font-weight',\n },\n 'lifecycle-zoom-control': {\n backgroundColor: '--uxm-lifecycle-zoom-bg',\n borderColor: '--uxm-lifecycle-zoom-border-color',\n borderRadius: '--uxm-lifecycle-zoom-radius',\n fontSize: '--uxm-lifecycle-zoom-font-size',\n color: '--uxm-lifecycle-zoom-color',\n buttonSize: '--uxm-lifecycle-zoom-button-size',\n iconColor: '--uxm-lifecycle-zoom-icon-color',\n },\n link: {\n fontSize: '--uxm-link-font-size',\n fontWeight: '--uxm-link-font-weight',\n },\n 'meta-row': {\n fontSize: '--uxm-meta-row-font-size',\n color: '--uxm-meta-row-color',\n gap: '--uxm-meta-row-gap',\n },\n 'number-stepper': {\n backgroundColor: '--uxm-number-stepper-input-bg',\n borderColor: '--uxm-number-stepper-input-border',\n color: '--uxm-number-stepper-input-color',\n borderRadius: '--uxm-number-stepper-input-radius',\n paddingX: '--uxm-number-stepper-input-padding-x',\n paddingY: '--uxm-number-stepper-input-padding-y',\n fontSize: '--uxm-number-stepper-font-size',\n gap: '--uxm-number-stepper-gap',\n },\n 'page-header': {\n gap: '--uxm-page-header-gap',\n paddingX: '--uxm-page-header-padding-x',\n paddingY: '--uxm-page-header-padding-y',\n },\n 'page-shell': {\n backgroundColor: '--uxm-page-shell-bg',\n },\n 'property-field': {\n gap: '--uxm-property-field-gap',\n },\n 'property-grid': {\n rowGap: '--uxm-property-grid-row-gap',\n columnGap: '--uxm-property-grid-column-gap',\n },\n 'responsive-grid': {\n gap: '--uxm-responsive-grid-gap',\n },\n 'section-header': {\n gap: '--uxm-section-header-gap',\n },\n stack: {\n gap: '--uxm-stack-gap',\n },\n 'stat-card': {\n backgroundColor: '--uxm-stat-card-background-color',\n borderColor: '--uxm-stat-card-border-color',\n borderRadius: '--uxm-stat-card-border-radius',\n padding: '--uxm-stat-card-padding',\n },\n tag: {\n borderRadius: '--uxm-tag-border-radius',\n fontWeight: '--uxm-tag-font-weight',\n },\n thumbnail: {\n borderRadius: '--uxm-thumbnail-border-radius',\n backgroundColor: '--uxm-thumbnail-background-color',\n borderColor: '--uxm-thumbnail-border-color',\n borderWidth: '--uxm-thumbnail-border-width',\n },\n 'timeline-entry': {\n gap: '--uxm-timeline-entry-gap',\n },\n 'segment-row': {\n paddingX: '--uxm-segment-row-padding-x',\n paddingY: '--uxm-segment-row-padding-y',\n gap: '--uxm-segment-row-gap',\n dragColor: '--uxm-segment-row-drag-color',\n dragHoverColor: '--uxm-segment-row-drag-hover-color',\n chevronColor: '--uxm-segment-row-chevron-color',\n chevronSize: '--uxm-segment-row-chevron-size',\n accentColor: '--uxm-segment-row-accent-color',\n accentWidth: '--uxm-segment-row-accent-width',\n accentRadius: '--uxm-segment-row-accent-radius',\n titleColor: '--uxm-segment-row-title-color',\n titleSize: '--uxm-segment-row-title-size',\n titleWeight: '--uxm-segment-row-title-weight',\n countBg: '--uxm-segment-row-count-bg',\n countColor: '--uxm-segment-row-count-color',\n countSize: '--uxm-segment-row-count-size',\n countPaddingX: '--uxm-segment-row-count-padding-x',\n countPaddingY: '--uxm-segment-row-count-padding-y',\n countRadius: '--uxm-segment-row-count-radius',\n rowHoverBg: '--uxm-segment-row-row-hover-bg',\n rowHoverRadius: '--uxm-segment-row-row-hover-radius',\n },\n 'segment-card': {\n borderColor: '--uxm-segment-card-border-color',\n borderWidth: '--uxm-segment-card-border-width',\n borderRadius: '--uxm-segment-card-border-radius',\n backgroundColor: '--uxm-segment-card-background',\n paddingX: '--uxm-segment-card-padding-x',\n paddingY: '--uxm-segment-card-padding-y',\n childrenInsetX: '--uxm-segment-card-children-inset-x',\n childrenInsetY: '--uxm-segment-card-children-inset-y',\n childrenGap: '--uxm-segment-card-children-gap',\n dividerColor: '--uxm-segment-card-divider-color',\n dividerWidth: '--uxm-segment-card-divider-width',\n },\n 'component-row': {\n paddingX: '--uxm-component-row-padding-x',\n paddingY: '--uxm-component-row-padding-y',\n gap: '--uxm-component-row-gap',\n backgroundColor: '--uxm-component-row-background',\n dragColor: '--uxm-component-row-drag-color',\n dragHoverColor: '--uxm-component-row-drag-hover-color',\n iconBadgeSize: '--uxm-component-row-icon-badge-size',\n iconBadgeRadius: '--uxm-component-row-icon-badge-radius',\n iconBadgePadding: '--uxm-component-row-icon-badge-padding',\n nameColor: '--uxm-component-row-name-color',\n nameSize: '--uxm-component-row-name-size',\n nameWeight: '--uxm-component-row-name-weight',\n typeLabelColor: '--uxm-component-row-type-label-color',\n typeLabelSize: '--uxm-component-row-type-label-size',\n typeLabelWeight: '--uxm-component-row-type-label-weight',\n chevronColor: '--uxm-component-row-chevron-color',\n chevronSize: '--uxm-component-row-chevron-size',\n rowHoverBg: '--uxm-component-row-row-hover-bg',\n rowHoverRadius: '--uxm-component-row-row-hover-radius',\n },\n 'option-list': {\n indent: '--uxm-option-list-indent',\n backgroundColor: '--uxm-option-list-background',\n borderColor: '--uxm-option-list-border-color',\n borderWidth: '--uxm-option-list-border-width',\n borderRadius: '--uxm-option-list-border-radius',\n paddingX: '--uxm-option-list-padding-x',\n paddingY: '--uxm-option-list-padding-y',\n gap: '--uxm-option-list-gap',\n rowPaddingX: '--uxm-option-list-row-padding-x',\n rowPaddingY: '--uxm-option-list-row-padding-y',\n dragColor: '--uxm-option-list-drag-color',\n dragHoverColor: '--uxm-option-list-drag-hover-color',\n bulletSize: '--uxm-option-list-bullet-size',\n bulletGap: '--uxm-option-list-bullet-gap',\n nameColor: '--uxm-option-list-name-color',\n nameSize: '--uxm-option-list-name-size',\n nameWeight: '--uxm-option-list-name-weight',\n rowHoverBg: '--uxm-option-list-row-hover-bg',\n rowHoverRadius: '--uxm-option-list-row-hover-radius',\n },\n tooltip: {\n backgroundColor: '--uxm-tooltip-background-color',\n color: '--uxm-tooltip-color',\n borderRadius: '--uxm-tooltip-border-radius',\n paddingX: '--uxm-tooltip-padding-x',\n paddingY: '--uxm-tooltip-padding-y',\n fontSize: '--uxm-tooltip-font-size',\n },\n 'content-tooltip': {\n backgroundColor: '--uxm-content-tooltip-background-color',\n borderColor: '--uxm-content-tooltip-border-color',\n borderRadius: '--uxm-content-tooltip-border-radius',\n padding: '--uxm-content-tooltip-padding',\n maxWidth: '--uxm-content-tooltip-max-width',\n },\n 'type-overview-card': {\n backgroundColor: '--uxm-typeoverview-bg',\n borderColor: '--uxm-typeoverview-border-color',\n borderRadius: '--uxm-typeoverview-radius',\n padding: '--uxm-typeoverview-padding',\n accentColor: '--uxm-typeoverview-accent-color',\n accentWidth: '--uxm-typeoverview-accent-width',\n iconBg: '--uxm-typeoverview-icon-bg',\n iconColor: '--uxm-typeoverview-icon-color',\n iconBoxSize: '--uxm-typeoverview-icon-tile-size',\n iconRadius: '--uxm-typeoverview-icon-tile-radius',\n labelSize: '--uxm-typeoverview-label-size',\n labelColor: '--uxm-typeoverview-label-color',\n valueSize: '--uxm-typeoverview-value-size',\n valueColor: '--uxm-typeoverview-value-color',\n },\n // Without an entry here every knob would fall through to the generic\n // `--uxm-{id}-{kebab}` rule and double the segment — `connectorIdleColor`\n // under id `lifecycle-connector` becomes\n // `--uxm-lifecycle-connector-connector-idle-color`. The stylesheet reads the\n // canonical single-`connector` names (and still accepts the doubled ones as\n // a fallback alias), so map the knobs explicitly.\n //\n // `connectorArrowSize` sizes an SVG polygon rather than setting any CSS\n // property, so no rule can consume it — `useThemedArrowSize` in\n // lifecycle-connector.tsx reads `--uxm-lifecycle-connector-arrow-size` back\n // off the element instead. It is published here for that reason, not for\n // naming tidiness: drop this line and a saved Arrow Size stops applying.\n 'lifecycle-connector': {\n connectorIdleColor: '--uxm-lifecycle-connector-idle-color',\n connectorActiveColor: '--uxm-lifecycle-connector-active-color',\n connectorIdleStrokeWidth: '--uxm-lifecycle-connector-idle-stroke-width',\n connectorActiveStrokeWidth: '--uxm-lifecycle-connector-active-stroke-width',\n connectorDashedColor: '--uxm-lifecycle-connector-dashed-color',\n connectorDashedStrokeWidth: '--uxm-lifecycle-connector-dashed-stroke-width',\n connectorDashPattern: '--uxm-lifecycle-connector-dash-pattern',\n connectorArrowSize: '--uxm-lifecycle-connector-arrow-size',\n },\n};\n\nfunction toCSS(key: string, componentId: string): string {\n const componentMapping = PER_COMPONENT_MAPPING[componentId];\n if (componentMapping?.[key]) return componentMapping[key];\n\n const mapping: Record<string, string> = {\n paddingX: 'padding-inline',\n paddingY: 'padding-block',\n };\n if (mapping[key]) return mapping[key];\n\n const kebab = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n if (REAL_CSS_PROPS.has(key)) return kebab;\n return `--uxm-${componentId}-${kebab}`;\n}\n\nfunction formatValue(value: string | number | boolean, key: string): string {\n if (typeof value === 'boolean') return value ? '1' : '0';\n if (typeof value === 'number') {\n // `lineHeight` is a ratio, not a length — without it here a knob saved as\n // 1.5 emits `line-height: 1.5px`, which collapses every line box.\n const unitless = ['fontWeight', 'titleWeight', 'nameWeight', 'typeLabelWeight', 'lineHeight', 'shadow', 'disabledOpacity'];\n // `opacity` is always unitless — match every *Opacity knob (e.g. the\n // per-element `itemDisabledOpacity` / `optionDisabledOpacity` variants)\n // so a saved value never gets a spurious `px` suffix.\n if (unitless.includes(key) || key.endsWith('Opacity')) return String(value);\n return `${value}px`;\n }\n // String style-override values are user/attacker-controlled and persisted\n // to a stylesheet served to every browser session — sanitise the same way\n // as brand token values so one can't break out of the declaration (e.g.\n // `red; } body{display:none}/*`). An unsafe value is dropped to '' rather\n // than throwing, so a single bad override can't blank the whole rule.\n return safeTokenValue(value) ?? '';\n}\n\n// CSS sanitizers — applied to every brand value before interpolation. The\n// output is persisted and served to all browser sessions, so attacker-\n// controlled values must not break out of the declaration they belong to.\nfunction safeUrl(v: unknown): string | undefined {\n if (typeof v !== 'string') return undefined;\n const trimmed = v.trim();\n if (!/^(https?:\\/\\/|\\/)/.test(trimmed)) return undefined;\n if (/[\")\\n\\r]/.test(trimmed)) return undefined;\n return trimmed;\n}\nexport function safeFontFamily(v: unknown): string | undefined {\n if (typeof v !== 'string') return undefined;\n const trimmed = v.trim();\n return /^[A-Za-z0-9 _-]+$/.test(trimmed) ? trimmed : undefined;\n}\n// Heading weight is a closed set (the editor offers exactly these three), so a\n// strict whitelist is both the sanitizer and the contract. Numbers are accepted\n// defensively — a persisted config may carry the JSON number rather than the\n// string the <select> yields.\nexport function safeFontWeight(v: unknown): string | undefined {\n const s = typeof v === 'number' ? String(v) : typeof v === 'string' ? v.trim() : undefined;\n return s !== undefined && /^(500|600|700)$/.test(s) ? s : undefined;\n}\n// Scales multiply a length inside calc(), which makes a bad value far worse\n// than a dropped declaration: `abc` or `1.2px` (length × length) is invalid at\n// computed-value time, so `font-size` resolves to `unset` and INHERITS — one\n// poisoned value on :root collapses the whole app to the parent's size. A\n// plain-number whitelist plus a sane range is the only safe gate; note\n// `safeTokenValue` is NOT sufficient (it passes `abc`, `-1` and unbalanced\n// parens). Range mirrors the editor's slider bounds.\nexport function safeTypeScale(v: unknown): string | undefined {\n const s = typeof v === 'number' ? String(v) : typeof v === 'string' ? v.trim() : undefined;\n if (s === undefined || !/^(?:0|[1-9]\\d?)(?:\\.\\d{1,3})?$/.test(s)) return undefined;\n const n = Number(s);\n return n >= 0.5 && n <= 2 ? s : undefined;\n}\n// Line height is a unitless ratio; same invalid-at-computed-value-time risk as\n// the scales, but it only affects the declarations that read it.\nexport function safeLineHeight(v: unknown): string | undefined {\n const s = typeof v === 'number' ? String(v) : typeof v === 'string' ? v.trim() : undefined;\n if (s === undefined || !/^[1-9](?:\\.\\d{1,2})?$/.test(s)) return undefined;\n const n = Number(s);\n return n >= 1 && n <= 2.5 ? s : undefined;\n}\nexport function safeTokenKey(v: string): boolean {\n return /^--[A-Za-z0-9-]+$/.test(v);\n}\nexport function safeTokenValue(v: unknown): string | undefined {\n if (typeof v !== 'string') return undefined;\n return /[{};\\n\\r]/.test(v) ? undefined : v;\n}\n\n// The three heading roles, in one place. Both the publish path below and the\n// live mirror (`brand-font-styles.tsx`) derive their emitted var names from\n// `role` by interpolation, so a rename here reaches both — keeping these in two\n// hand-maintained lists is how `--type-${role}-font` silently drifts away from\n// the names the stylesheets actually read.\nexport const TYPE_ROLES = [\n { role: 'display', family: 'displayFontFamily', weight: 'displayFontWeight', scale: 'displayScale' },\n { role: 'page-title', family: 'pageTitleFontFamily', weight: 'pageTitleFontWeight', scale: 'pageTitleScale' },\n { role: 'section-title', family: 'sectionTitleFontFamily', weight: 'sectionTitleFontWeight', scale: 'sectionTitleScale' },\n] as const satisfies ReadonlyArray<{\n role: string;\n family: keyof BrandConfig;\n weight: keyof BrandConfig;\n scale: keyof BrandConfig;\n}>;\n\n/** Sanitised per-role typography, shared by the generator and the live mirror. */\nexport function resolveTypeRoles(brand: BrandConfig) {\n return TYPE_ROLES.map((r) => ({\n role: r.role,\n family: safeFontFamily(brand[r.family]),\n weight: safeFontWeight(brand[r.weight]),\n scale: safeTypeScale(brand[r.scale]),\n }));\n}\n\n/** Generate the overrides stylesheet from style overrides + brand config. */\nexport function generateOverridesCss(allOverrides: AllOverrides, brand: BrandConfig): string {\n const lines: string[] = ['/* Auto-generated by UXM — do not edit manually */', ''];\n\n const fontFamily = safeFontFamily(brand.fontFamily);\n const headingFontFamily = safeFontFamily(brand.headingFontFamily);\n const headingFontWeight = safeFontWeight(brand.headingFontWeight);\n // Per-role refinements, layered under the umbrella heading vars above.\n const roles = resolveTypeRoles(brand);\n const typeScale = safeTypeScale(brand.typeScale);\n const bodyLineHeight = safeLineHeight(brand.bodyLineHeight);\n const logoUrl = safeUrl(brand.logoUrl);\n const iconUrl = safeUrl(brand.iconUrl);\n const logoUrlDark = safeUrl(brand.logoUrlDark);\n const iconUrlDark = safeUrl(brand.iconUrlDark);\n\n if (fontFamily) {\n lines.push(`@import url(\"${fontFileUrl(fontFamily)}\");`);\n lines.push('');\n }\n // Second font file only when the heading face is actually a different family\n // — picking the same one for both is a no-op, not a reason to fetch twice.\n if (headingFontFamily && headingFontFamily !== fontFamily) {\n lines.push(`@import url(\"${fontFileUrl(headingFontFamily)}\");`);\n lines.push('');\n }\n // A role may pick a face neither the body nor the umbrella uses — fetch each\n // distinct one exactly once (@import must stay above the rules below).\n const imported = new Set([fontFamily, headingFontFamily].filter(Boolean));\n for (const { family } of roles) {\n if (family && !imported.has(family)) {\n imported.add(family);\n lines.push(`@import url(\"${fontFileUrl(family)}\");`);\n lines.push('');\n }\n }\n\n const brandRules: string[] = [];\n if (fontFamily) {\n brandRules.push(` --brand-font: \"${fontFamily}\", var(--font-inter), system-ui, sans-serif;`);\n }\n // Heading vars are consumed by the components' own two-layer fallbacks (see\n // e.g. page-header.scss), so there is no `body` rule and no `!important`:\n // an unset var simply lets each component's own default paint.\n if (headingFontFamily) {\n brandRules.push(` --brand-heading-font: \"${headingFontFamily}\", var(--font-inter), system-ui, sans-serif;`);\n }\n if (headingFontWeight) {\n brandRules.push(` --brand-heading-weight: ${headingFontWeight};`);\n }\n // Role vars sit between the component var and the umbrella in each atom's\n // chain, so an unset role simply falls through to the umbrella.\n for (const { role, family, weight, scale } of roles) {\n if (family) {\n brandRules.push(` --type-${role}-font: \"${family}\", var(--font-inter), system-ui, sans-serif;`);\n }\n if (weight) brandRules.push(` --type-${role}-weight: ${weight};`);\n if (scale) brandRules.push(` --type-${role}-scale: ${scale};`);\n }\n if (typeScale) brandRules.push(` --type-scale: ${typeScale};`);\n if (bodyLineHeight) brandRules.push(` --type-body-line-height: ${bodyLineHeight};`);\n if (logoUrl) brandRules.push(` --brand-logo-url: url(\"${logoUrl}\");`);\n if (iconUrl) brandRules.push(` --brand-icon-url: url(\"${iconUrl}\");`);\n\n if (brandRules.length > 0) {\n lines.push(':root {');\n lines.push(...brandRules);\n lines.push('}');\n lines.push('');\n if (fontFamily) {\n lines.push('body { font-family: var(--brand-font) !important; }');\n lines.push('');\n }\n // Emitted ONLY when set. The library ships no element-level rules at all,\n // so an unconditional `body { line-height }` would reflow the host's own\n // content — same reasoning as the font-family rule above.\n if (bodyLineHeight) {\n // Explicit fallback: if the var is later cancelled (the studio mirror\n // re-declares it as `initial` on revert) a bare `var()` would be invalid\n // at computed-value time and `line-height` — being inherited — would\n // resolve to the parent's value, silently replacing whatever the host\n // had set on `body`. `normal` makes the wind-down state deliberate.\n lines.push(`body { line-height: var(--type-body-line-height, normal); }`);\n lines.push('');\n }\n }\n\n const darkBrandRules: string[] = [];\n if (logoUrlDark) darkBrandRules.push(` --brand-logo-url: url(\"${logoUrlDark}\");`);\n if (iconUrlDark) darkBrandRules.push(` --brand-icon-url: url(\"${iconUrlDark}\");`);\n if (darkBrandRules.length > 0) {\n lines.push('[data-theme=\"dark\"] {');\n lines.push(...darkBrandRules);\n lines.push('}');\n lines.push('');\n }\n\n const emitTokens = (selector: string, overrides: Record<string, string> | undefined) => {\n if (!overrides) return;\n const safeEntries = Object.entries(overrides).flatMap(([k, v]) => {\n if (!safeTokenKey(k)) return [];\n const safeValue = safeTokenValue(v);\n return safeValue === undefined ? [] : [[k, safeValue] as const];\n });\n if (safeEntries.length === 0) return;\n lines.push(`${selector} {`);\n for (const [cssVar, value] of safeEntries) {\n lines.push(` ${cssVar}: ${value};`);\n }\n lines.push('}');\n lines.push('');\n };\n // Scope customized light-mode color tokens to non-dark. `:root` and\n // `[data-theme=\"dark\"]` carry equal specificity, so an unconditional\n // `:root` block would win over this stylesheet's own dark block for any\n // token NOT also customized for dark (equal specificity, later source\n // order) — pinning that token to its light value in dark mode too. Scoping\n // lets an unset dark token fall through the cascade to tokens/index.css's\n // own `[data-theme=\"dark\"]` default instead.\n emitTokens(':root:not([data-theme=\"dark\"])', brand.tokens?.light);\n emitTokens('[data-theme=\"dark\"]', brand.tokens?.dark);\n\n const componentIds = Object.keys(allOverrides).sort();\n\n for (const id of componentIds) {\n const overrides = allOverrides[id];\n const entries = Object.entries(overrides);\n if (entries.length === 0) continue;\n\n const selector = PER_COMPONENT_SELECTOR[id] ?? `.uxm-${id}`;\n lines.push(`${selector} {`);\n for (const [key, value] of entries) {\n const cssProp = toCSS(key, id);\n const cssValue = formatValue(value, key);\n lines.push(` ${cssProp}: ${cssValue};`);\n }\n lines.push('}');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/studio/persistence/generate-css.ts"],"sourcesContent":["import type { AllOverrides } from './types';\nimport type { BrandConfig } from '../lib/types';\n\n/**\n * Pure CSS generator for UXM Studio overrides.\n *\n * Single source of truth (R5): the modo Hono `/api/uxm/save` route imports\n * `generateOverridesCss` from here instead of keeping its own copy. No Node\n * APIs — runs in browser (client export) and server alike.\n *\n * Emits a stylesheet from per-component style overrides plus brand config\n * (font, logo/icon URLs, brand token blocks). All attacker-controlled brand\n * values are sanitised before interpolation because the output is served to\n * every browser session.\n */\n\nconst BRAND_FONT_WEIGHTS = 'wght@400;500;600;700';\n\nexport function fontFileUrl(fontFamily: string): string {\n const encoded = fontFamily.trim().replace(/\\s+/g, '+');\n return `https://fonts.googleapis.com/css2?family=${encoded}:${BRAND_FONT_WEIGHTS}&display=swap`;\n}\n\nconst REAL_CSS_PROPS = new Set([\n 'background', 'backgroundColor',\n 'color',\n 'border', 'borderColor', 'borderRadius', 'borderWidth', 'borderStyle',\n 'padding', 'paddingX', 'paddingY', 'margin',\n 'gap', 'rowGap', 'columnGap',\n 'width', 'height', 'minWidth', 'maxWidth', 'minHeight', 'maxHeight',\n 'fontSize', 'fontWeight', 'fontFamily', 'lineHeight',\n 'opacity',\n 'cursor', 'display', 'position', 'overflow', 'direction',\n]);\n\n// Per-component selector overrides for the emitted rule. Defaults to\n// `.uxm-{id}`. Override when the atom renders the styled element via a PORTAL\n// (Listbox / Popover panel mounts to document.body): CSS custom properties\n// cascade DOWN from the declaring element, so vars on the in-page wrapper\n// never reach a portaled descendant. Emit on BOTH wrapper and panel selector.\nconst PER_COMPONENT_SELECTOR: Record<string, string> = {\n listbox: '.uxm-listbox, .uxm-listbox__panel',\n // Menu mirrors Listbox: the `.uxm-menu` wrapper lives in-page around the\n // trigger, but the `.uxm-menu__panel` portals to document.body, so vars on\n // the wrapper never reach it. Emit on both so the panel carries them.\n menu: '.uxm-menu, .uxm-menu__panel',\n // PhoneInput no longer needs a panel-scoped selector: its country picker\n // now delegates to the shared `Listbox`, whose portaled panel already gets\n // its vars via the `listbox` entry above. All `--uxm-phone-input-*` knobs\n // target the in-page field, so the default `.uxm-phone-input` selector is\n // correct.\n};\n\n// One knob → one variable. A multi-target (string[]) form was briefly added so\n// Card's Row Gap could write both the Stack and Cluster gap vars; that was the\n// only use, and it was the wrong shape (see the `card` entry below), so the\n// mapping stays single-target on purpose — a knob that themes a SIBLING atom's\n// var cannot win against that atom's own knob.\nconst PER_COMPONENT_MAPPING: Record<string, Record<string, string>> = {\n 'input-with-icon': {\n backgroundColor: '--uxm-input-with-icon-bg',\n borderColor: '--uxm-input-with-icon-border-color',\n borderRadius: '--uxm-input-with-icon-radius',\n paddingX: '--uxm-input-with-icon-padding-x',\n paddingY: '--uxm-input-with-icon-padding-y',\n fontSize: '--uxm-input-with-icon-font-size',\n color: '--uxm-input-with-icon-color',\n },\n 'input-text': {\n backgroundColor: '--uxm-input-text-bg',\n borderColor: '--uxm-input-text-border-color',\n color: '--uxm-input-text-color',\n borderRadius: '--uxm-input-text-border-radius',\n paddingX: '--uxm-input-text-padding-x',\n paddingY: '--uxm-input-text-padding-y',\n fontSize: '--uxm-input-text-font-size',\n },\n 'number-input': {\n backgroundColor: '--uxm-number-input-bg',\n borderColor: '--uxm-number-input-border-color',\n color: '--uxm-number-input-color',\n borderRadius: '--uxm-number-input-border-radius',\n paddingX: '--uxm-number-input-padding-x',\n paddingY: '--uxm-number-input-padding-y',\n fontSize: '--uxm-number-input-font-size',\n },\n // Every key below collides with REAL_CSS_PROPS. The atom passes its class to\n // `Listbox`, so the emitted rule lands on that in-page ROOT while the styled\n // element is the `__trigger` child, which declares its own `color`,\n // `border-color`, `font-size` and `gap` from `--uxm-language-switcher-*` and\n // therefore beats anything inherited — every one of these would be a silent\n // no-op. Padding is worse: `padding-inline` on the root pads OUTSIDE the\n // button while the trigger keeps its default 10px/7px.\n 'language-switcher': {\n color: '--uxm-language-switcher-color',\n borderColor: '--uxm-language-switcher-border-color',\n fontSize: '--uxm-language-switcher-font-size',\n gap: '--uxm-language-switcher-gap',\n paddingX: '--uxm-language-switcher-padding-x',\n paddingY: '--uxm-language-switcher-padding-y',\n },\n // Without this entry `fontSize` falls through REAL_CSS_PROPS and emits a\n // literal `font-size` on `.uxm-color-input`, which the atom's own children\n // (`__value-field`, `__format`) always beat — so the knob did nothing at all.\n 'color-input': {\n fontSize: '--uxm-color-input-font-size',\n },\n // Every key here collides with REAL_CSS_PROPS, where the generic fallback\n // emits a REAL property on `.uxm-code-editor` instead of a var. That root is\n // pure chrome — the text lives in `__input` / `__gutter-lines`, which declare\n // their own `color` / `font-size` / `line-height` and always beat inherited\n // values, so Text / Font Size / Line Height would be silent no-ops. Padding is\n // worse than a no-op: `padding-inline` on the root pads OUTSIDE the code while\n // `--uxm-code-editor-padding-x` stays unset, so the gutter's absolutely\n // positioned `left` keeps its 14px default and the numbers leave their column.\n // Same defect as the `color-input` entry above.\n 'code-editor': {\n backgroundColor: '--uxm-code-editor-bg',\n borderColor: '--uxm-code-editor-border-color',\n color: '--uxm-code-editor-color',\n borderRadius: '--uxm-code-editor-border-radius',\n paddingX: '--uxm-code-editor-padding-x',\n paddingY: '--uxm-code-editor-padding-y',\n fontSize: '--uxm-code-editor-font-size',\n lineHeight: '--uxm-code-editor-line-height',\n minHeight: '--uxm-code-editor-min-height',\n },\n 'currency-input': {\n backgroundColor: '--uxm-currency-input-background-color',\n borderColor: '--uxm-currency-input-border-color',\n borderRadius: '--uxm-currency-input-border-radius',\n paddingX: '--uxm-currency-input-padding-x',\n paddingY: '--uxm-currency-input-padding-y',\n fontSize: '--uxm-currency-input-font-size',\n color: '--uxm-currency-input-color',\n },\n textarea: {\n backgroundColor: '--uxm-textarea-bg',\n borderColor: '--uxm-textarea-border-color',\n color: '--uxm-textarea-color',\n minHeight: '--uxm-textarea-min-height',\n borderRadius: '--uxm-textarea-border-radius',\n paddingX: '--uxm-textarea-padding-x',\n paddingY: '--uxm-textarea-padding-y',\n fontSize: '--uxm-textarea-font-size',\n },\n 'file-upload': {\n backgroundColor: '--uxm-file-upload-bg',\n borderColor: '--uxm-file-upload-border-color',\n color: '--uxm-file-upload-color',\n borderRadius: '--uxm-file-upload-border-radius',\n borderStyle: '--uxm-file-upload-border-style',\n borderWidth: '--uxm-file-upload-border-width',\n paddingX: '--uxm-file-upload-padding-x',\n paddingY: '--uxm-file-upload-padding-y',\n minHeight: '--uxm-file-upload-min-height',\n gap: '--uxm-file-upload-gap',\n rowGap: '--uxm-file-upload-row-gap',\n },\n 'select-dropdown': {\n backgroundColor: '--uxm-select-dropdown-bg',\n borderColor: '--uxm-select-dropdown-border-color',\n color: '--uxm-select-dropdown-color',\n borderRadius: '--uxm-select-dropdown-border-radius',\n paddingX: '--uxm-select-dropdown-padding-x',\n paddingY: '--uxm-select-dropdown-padding-y',\n fontSize: '--uxm-select-dropdown-font-size',\n },\n 'date-input': {\n backgroundColor: '--uxm-date-input-background-color',\n borderColor: '--uxm-date-input-border-color',\n borderRadius: '--uxm-date-input-border-radius',\n paddingX: '--uxm-date-input-padding-x',\n paddingY: '--uxm-date-input-padding-y',\n fontSize: '--uxm-date-input-font-size',\n color: '--uxm-date-input-color',\n },\n 'password-input': {\n backgroundColor: '--uxm-password-input-background-color',\n borderColor: '--uxm-password-input-border-color',\n borderRadius: '--uxm-password-input-border-radius',\n paddingX: '--uxm-password-input-padding-x',\n paddingY: '--uxm-password-input-padding-y',\n fontSize: '--uxm-password-input-font-size',\n color: '--uxm-password-input-color',\n },\n 'time-input': {\n backgroundColor: '--uxm-time-input-background-color',\n borderColor: '--uxm-time-input-border-color',\n borderRadius: '--uxm-time-input-border-radius',\n paddingX: '--uxm-time-input-padding-x',\n paddingY: '--uxm-time-input-padding-y',\n fontSize: '--uxm-time-input-font-size',\n color: '--uxm-time-input-color',\n },\n 'phone-input': {\n backgroundColor: '--uxm-phone-input-background-color',\n borderColor: '--uxm-phone-input-border-color',\n borderRadius: '--uxm-phone-input-border-radius',\n paddingX: '--uxm-phone-input-padding-x',\n paddingY: '--uxm-phone-input-padding-y',\n fontSize: '--uxm-phone-input-font-size',\n color: '--uxm-phone-input-color',\n },\n calendar: {\n backgroundColor: '--uxm-calendar-background-color',\n borderColor: '--uxm-calendar-border-color',\n borderRadius: '--uxm-calendar-border-radius',\n padding: '--uxm-calendar-padding',\n },\n tabs: {\n gap: '--uxm-tabs-gap',\n paddingX: '--uxm-tabs-padding-x',\n paddingY: '--uxm-tabs-padding-y',\n fontSize: '--uxm-tabs-font-size',\n fontWeight: '--uxm-tabs-font-weight',\n },\n 'tabs-underline': {\n gap: '--uxm-tabs-underline-gap',\n paddingX: '--uxm-tabs-underline-padding-x',\n paddingY: '--uxm-tabs-underline-padding-y',\n fontSize: '--uxm-tabs-underline-font-size',\n fontWeight: '--uxm-tabs-underline-font-weight',\n },\n 'filter-tabs': {\n gap: '--uxm-filter-tabs-gap',\n paddingX: '--uxm-filter-tabs-padding-x',\n paddingY: '--uxm-filter-tabs-padding-y',\n fontSize: '--uxm-filter-tabs-font-size',\n fontWeight: '--uxm-filter-tabs-font-weight',\n },\n 'view-switcher': {\n gap: '--uxm-view-switcher-gap',\n },\n 'button-group': {\n borderColor: '--uxm-button-group-border-color',\n borderRadius: '--uxm-button-group-border-radius',\n paddingX: '--uxm-button-group-padding-x',\n paddingY: '--uxm-button-group-padding-y',\n fontSize: '--uxm-button-group-font-size',\n },\n checkbox: {\n borderRadius: '--uxm-checkbox-border-radius',\n gap: '--uxm-checkbox-gap',\n },\n card: {\n backgroundColor: '--uxm-card-bg',\n borderColor: '--uxm-card-border-color',\n borderRadius: '--uxm-card-radius',\n padding: '--uxm-card-padding',\n // `gap` (\"Header Gap\") collides with REAL_CSS_PROPS — the generic fallback\n // would emit a literal `gap` property that `.uxm-card` never activates (the\n // card is only a flex column via the `--gap` modifier). Route it to the var\n // the modifier actually reads.\n //\n // There is deliberately NO Card knob for the CONTENT's row gap. It looks\n // like it belongs here, but the row gap is owned by the nested Stack /\n // Cluster, which already have their own Gap knobs — and those emit\n // `--uxm-stack-gap` DIRECTLY on `.uxm-stack`, where a directly-set custom\n // property always beats one inherited from `.uxm-card`. A Card-side knob\n // would therefore lose the moment anyone themed Stack, while also leaking\n // to every Stack/Cluster at any depth inside any card (custom properties\n // inherit). One owner per visual property; Card owns only its own gap.\n gap: '--uxm-card-gap',\n },\n 'toggle-switch': {\n width: '--uxm-toggle-switch-width',\n height: '--uxm-toggle-switch-height',\n },\n 'radio-group': {\n gap: '--uxm-radio-group-gap',\n },\n loader: {\n color: '--uxm-loader-color',\n gap: '--uxm-loader-gap',\n },\n 'data-table': {\n borderColor: '--uxm-data-table-border-color',\n fontSize: '--uxm-data-table-font-size',\n borderRadius: '--uxm-data-table-border-radius',\n },\n 'app-sidebar': {\n borderColor: '--uxm-app-sidebar-border-color',\n backgroundColor: '--uxm-app-sidebar-background-color',\n },\n // Every key here collides with REAL_CSS_PROPS, where the generic fallback\n // emits the LITERAL css property on the root selector instead of the var.\n //\n // For `fontSize` / `fontWeight` that is a silent no-op rather than a mere\n // detour: the atom reads those vars on `.uxm-sidebar-nav-trigger__value`, and\n // a `font-size` landing on the root is beaten by the child's own declaration.\n // The live workbench hides it — that path projects custom properties through\n // the preview's `buildVars`, so the knob only dies once a brand is SAVED.\n //\n // The rest (padding, gap, radius) do sit on the root and would survive the\n // literal route on source order alone, but they are mapped too: the sibling\n // `sidebar-nav-item` maps all six, and leaving half of them to cascade luck\n // invites exactly the question of which half.\n 'sidebar-nav-trigger': {\n paddingX: '--uxm-sidebar-nav-trigger-padding-x',\n paddingY: '--uxm-sidebar-nav-trigger-padding-y',\n fontSize: '--uxm-sidebar-nav-trigger-font-size',\n fontWeight: '--uxm-sidebar-nav-trigger-font-weight',\n gap: '--uxm-sidebar-nav-trigger-gap',\n borderRadius: '--uxm-sidebar-nav-trigger-border-radius',\n },\n 'sidebar-nav-item': {\n paddingX: '--uxm-sidebar-nav-item-padding-x',\n paddingY: '--uxm-sidebar-nav-item-padding-y',\n fontSize: '--uxm-sidebar-nav-item-font-size',\n fontWeight: '--uxm-sidebar-nav-item-font-weight',\n gap: '--uxm-sidebar-nav-item-gap',\n borderRadius: '--uxm-sidebar-nav-item-border-radius',\n },\n 'explorer-list-item': {\n paddingX: '--uxm-explorer-list-item-padding-x',\n paddingY: '--uxm-explorer-list-item-padding-y',\n fontSize: '--uxm-explorer-list-item-font-size',\n fontWeight: '--uxm-explorer-list-item-font-weight',\n gap: '--uxm-explorer-list-item-gap',\n borderRadius: '--uxm-explorer-list-item-border-radius',\n },\n 'app-top-bar': {\n borderColor: '--uxm-app-top-bar-border-color',\n backgroundColor: '--uxm-app-top-bar-background-color',\n height: '--uxm-app-top-bar-height',\n paddingX: '--uxm-app-top-bar-padding-x',\n gap: '--uxm-app-top-bar-gap',\n },\n 'explorer-section': {\n paddingX: '--uxm-explorer-section-padding-x',\n paddingY: '--uxm-explorer-section-padding-y',\n borderRadius: '--uxm-explorer-section-border-radius',\n gap: '--uxm-explorer-section-gap',\n fontSize: '--uxm-explorer-section-font-size',\n fontWeight: '--uxm-explorer-section-font-weight',\n },\n 'number-field': {\n backgroundColor: '--uxm-number-field-input-bg',\n borderColor: '--uxm-number-field-input-border',\n color: '--uxm-number-field-input-color',\n borderRadius: '--uxm-number-field-input-radius',\n paddingX: '--uxm-number-field-input-padding-x',\n paddingY: '--uxm-number-field-input-padding-y',\n fontSize: '--uxm-number-field-font-size',\n gap: '--uxm-number-field-gap',\n },\n 'icon-button': {\n color: '--uxm-icon-button-color',\n backgroundColor: '--uxm-icon-button-bg',\n hoverBackgroundColor: '--uxm-icon-button-hover-bg',\n activeBackgroundColor: '--uxm-icon-button-active-bg',\n borderRadius: '--uxm-icon-button-radius',\n },\n 'button-primary': {\n backgroundColor: '--uxm-button-primary-background-color',\n color: '--uxm-button-primary-color',\n borderRadius: '--uxm-button-primary-border-radius',\n fontSize: '--uxm-button-primary-font-size',\n fontWeight: '--uxm-button-primary-font-weight',\n paddingX: '--uxm-button-primary-padding-x',\n paddingY: '--uxm-button-primary-padding-y',\n },\n 'button-secondary': {\n backgroundColor: '--uxm-button-secondary-background-color',\n color: '--uxm-button-secondary-color',\n borderColor: '--uxm-button-secondary-border-color',\n borderRadius: '--uxm-button-secondary-border-radius',\n fontSize: '--uxm-button-secondary-font-size',\n fontWeight: '--uxm-button-secondary-font-weight',\n paddingX: '--uxm-button-secondary-padding-x',\n paddingY: '--uxm-button-secondary-padding-y',\n },\n 'button-tertiary': {\n backgroundColor: '--uxm-button-tertiary-background-color',\n color: '--uxm-button-tertiary-color',\n borderColor: '--uxm-button-tertiary-border-color',\n borderRadius: '--uxm-button-tertiary-border-radius',\n fontSize: '--uxm-button-tertiary-font-size',\n fontWeight: '--uxm-button-tertiary-font-weight',\n paddingX: '--uxm-button-tertiary-padding-x',\n paddingY: '--uxm-button-tertiary-padding-y',\n },\n 'button-ghost': {\n backgroundColor: '--uxm-button-ghost-background-color',\n color: '--uxm-button-ghost-color',\n borderRadius: '--uxm-button-ghost-border-radius',\n fontSize: '--uxm-button-ghost-font-size',\n fontWeight: '--uxm-button-ghost-font-weight',\n paddingX: '--uxm-button-ghost-padding-x',\n paddingY: '--uxm-button-ghost-padding-y',\n },\n 'button-danger': {\n backgroundColor: '--uxm-button-danger-background-color',\n color: '--uxm-button-danger-color',\n borderColor: '--uxm-button-danger-border-color',\n borderRadius: '--uxm-button-danger-border-radius',\n fontSize: '--uxm-button-danger-font-size',\n fontWeight: '--uxm-button-danger-font-weight',\n paddingX: '--uxm-button-danger-padding-x',\n paddingY: '--uxm-button-danger-padding-y',\n },\n 'button-with-icon': {\n backgroundColor: '--uxm-button-with-icon-background-color',\n color: '--uxm-button-with-icon-color',\n borderColor: '--uxm-button-with-icon-border-color',\n borderRadius: '--uxm-button-with-icon-border-radius',\n fontSize: '--uxm-button-with-icon-font-size',\n fontWeight: '--uxm-button-with-icon-font-weight',\n paddingX: '--uxm-button-with-icon-padding-x',\n paddingY: '--uxm-button-with-icon-padding-y',\n },\n 'button-icon': {\n backgroundColor: '--uxm-button-icon-background-color',\n color: '--uxm-button-icon-color',\n borderRadius: '--uxm-button-icon-border-radius',\n },\n 'back-link': {\n color: '--uxm-back-link-color',\n fontSize: '--uxm-back-link-font-size',\n fontWeight: '--uxm-back-link-font-weight',\n gap: '--uxm-back-link-gap',\n },\n breadcrumb: {\n fontSize: '--uxm-breadcrumb-font-size',\n gap: '--uxm-breadcrumb-gap',\n },\n disclosure: {\n paddingX: '--uxm-disclosure-padding-x',\n paddingY: '--uxm-disclosure-padding-y',\n fontSize: '--uxm-disclosure-font-size',\n gap: '--uxm-disclosure-gap',\n borderRadius: '--uxm-disclosure-border-radius',\n },\n 'side-flexpane': {\n paddingX: '--uxm-side-flexpane-padding-x',\n paddingY: '--uxm-side-flexpane-padding-y',\n backgroundColor: '--uxm-side-flexpane-background-color',\n borderColor: '--uxm-side-flexpane-border-color',\n borderRadius: '--uxm-side-flexpane-border-radius',\n width: '--uxm-side-flexpane-width',\n },\n 'list-item': {\n paddingX: '--uxm-list-item-padding-x',\n paddingY: '--uxm-list-item-padding-y',\n fontSize: '--uxm-list-item-font-size',\n gap: '--uxm-list-item-gap',\n borderRadius: '--uxm-list-item-border-radius',\n borderColor: '--uxm-list-item-border-color',\n },\n 'pill-select': {\n backgroundColor: '--uxm-pill-select-bg',\n borderColor: '--uxm-pill-select-border-color',\n paddingX: '--uxm-pill-select-padding-x',\n paddingY: '--uxm-pill-select-padding-y',\n },\n modal: {\n backgroundColor: '--uxm-modal-background-color',\n borderColor: '--uxm-modal-border-color',\n borderRadius: '--uxm-modal-border-radius',\n paddingX: '--uxm-modal-padding-x',\n paddingY: '--uxm-modal-padding-y',\n },\n toast: {\n backgroundColor: '--uxm-toast-background-color',\n color: '--uxm-toast-color',\n borderColor: '--uxm-toast-border-color',\n borderRadius: '--uxm-toast-border-radius',\n paddingX: '--uxm-toast-padding-x',\n paddingY: '--uxm-toast-padding-y',\n fontSize: '--uxm-toast-font-size',\n },\n avatar: {\n backgroundColor: '--uxm-avatar-background-color',\n borderColor: '--uxm-avatar-border-color',\n borderRadius: '--uxm-avatar-border-radius',\n borderWidth: '--uxm-avatar-border-width',\n color: '--uxm-avatar-color',\n fontSize: '--uxm-avatar-font-size',\n fontWeight: '--uxm-avatar-font-weight',\n },\n banner: {\n borderRadius: '--uxm-banner-border-radius',\n paddingX: '--uxm-banner-padding-x',\n paddingY: '--uxm-banner-padding-y',\n fontSize: '--uxm-banner-font-size',\n },\n 'bulk-action-bar': {\n backgroundColor: '--uxm-bulk-action-bar-background-color',\n color: '--uxm-bulk-action-bar-color',\n borderColor: '--uxm-bulk-action-bar-border-color',\n borderRadius: '--uxm-bulk-action-bar-border-radius',\n paddingX: '--uxm-bulk-action-bar-padding-x',\n paddingY: '--uxm-bulk-action-bar-padding-y',\n gap: '--uxm-bulk-action-bar-gap',\n fontSize: '--uxm-bulk-action-bar-font-size',\n },\n cluster: {\n gap: '--uxm-cluster-gap',\n },\n 'config-component-row': {\n padding: '--uxm-config-component-row-padding',\n borderRadius: '--uxm-config-component-row-radius',\n },\n 'config-segment-item': {\n paddingX: '--uxm-config-segment-item-padding-x',\n paddingY: '--uxm-config-segment-item-padding-y',\n borderRadius: '--uxm-config-segment-item-radius',\n },\n 'detail-section': {\n backgroundColor: '--uxm-detail-section-bg',\n borderColor: '--uxm-detail-section-border-color',\n borderRadius: '--uxm-detail-section-radius',\n padding: '--uxm-detail-section-padding',\n },\n divider: {\n color: '--uxm-divider-color',\n gap: '--uxm-divider-gap',\n },\n 'editable-cell': {\n // Dimensions are per-size keys (smallPaddingX, mediumMaxWidth, …) that\n // resolve via the generic `--uxm-editable-cell-{kebab(key)}` fallback in\n // toCSS; only the value colour needs an explicit entry (`color` is in\n // REAL_CSS_PROPS, so the fallback would emit a real CSS property that\n // outranks the component layer).\n color: '--uxm-editable-cell-color',\n // RETIRED knobs, kept mapped on purpose. The per-size split replaced these\n // four, but `generateOverridesCss` emits whatever keys are PERSISTED — not\n // what the registry currently declares — so a config saved before the split\n // still carries them. Without an entry here they'd fall through to\n // REAL_CSS_PROPS / the paddingX-paddingY special case in toCSS and emit\n // REAL `min-height` / `padding-inline` / `padding-block` declarations on\n // `.uxm-editable-cell`, which land in a sheet loaded after the library CSS\n // and would hard-override BOTH size presets (killing `medium`) and\n // resurrect the min-height the size work deliberately removed. Mapped to\n // their old, now-unread custom properties they are true no-ops instead.\n // Safe to delete once persisted overrides are pruned against the registry.\n minHeight: '--uxm-editable-cell-min-height',\n paddingX: '--uxm-editable-cell-padding-x',\n paddingY: '--uxm-editable-cell-padding-y',\n // `maxWidth` joined them when the cap went per-size: it is in\n // REAL_CSS_PROPS, so without this it would emit a real `max-width` that\n // pins BOTH presets (and would silently re-cap `medium`, whose whole point\n // is filling its container).\n maxWidth: '--uxm-editable-cell-max-width',\n },\n 'empty-state': {\n padding: '--uxm-empty-state-padding',\n },\n 'form-field': {\n gap: '--uxm-form-field-gap',\n // Per-tint label colours — the component reads `--uxm-form-field-label-\n // tint-*` (see form-field.scss tone classes); the generic kebab fallback\n // would emit `--uxm-form-field-tint-strong-color` etc., which nothing\n // reads, so the saved colour would silently not apply.\n tintStrongColor: '--uxm-form-field-label-tint-strong',\n tintDefaultColor: '--uxm-form-field-label-tint-default',\n tintMutedColor: '--uxm-form-field-label-tint-muted',\n // MIGRATION — `labelColor` was the single label-colour knob the tints\n // replaced. It is gone from the registry, but `generateOverridesCss` emits\n // whatever is PERSISTED, and its generic fallback lands on\n // `--uxm-form-field-label-color` — the very var the tint classes assign,\n // at equal specificity from a later sheet. Left alone it would beat ALL\n // THREE tints and silently disable them, with no knob left in the panel to\n // notice or clear it. Routed to the STRONG tint instead: strong was the\n // old (only) label colour and is still the default tone, so a pre-split\n // theme keeps the exact look it saved. A newly-saved `tintStrongColor`\n // still wins — overrides are appended, so it emits after this one.\n labelColor: '--uxm-form-field-label-tint-strong',\n },\n 'icon-tile': {\n borderRadius: '--uxm-icon-tile-radius',\n iconBg: '--uxm-icon-tile-bg',\n iconColor: '--uxm-icon-tile-color',\n },\n icon: {\n color: '--uxm-icon-color',\n },\n 'inline-action': {\n color: '--uxm-inline-action-color',\n fontSize: '--uxm-inline-action-font-size',\n fontWeight: '--uxm-inline-action-font-weight',\n gap: '--uxm-inline-action-gap',\n },\n 'inline-filter': {\n gap: '--uxm-inline-filter-gap',\n },\n 'lifecycle-edge-label': {\n paddingX: '--uxm-lifecycle-edge-label-padding-x',\n paddingY: '--uxm-lifecycle-edge-label-padding-y',\n borderRadius: '--uxm-lifecycle-edge-label-radius',\n borderWidth: '--uxm-lifecycle-edge-label-border-width',\n fontSize: '--uxm-lifecycle-edge-label-font-size',\n fontWeight: '--uxm-lifecycle-edge-label-font-weight',\n },\n // Same rule as lifecycle-group-box below — only the REAL_CSS_PROPS collisions\n // need an entry. `color` is the one that matters: a real `color` declaration\n // on `.uxm-lifecycle-drop-slot` from a later sheet would paint the text but\n // leave the dashes on the token, splitting a pair the atom deliberately drives\n // from one variable. The shape-scoped knobs (`cardRadius`, `pillFontSize`, …)\n // and `bg` need nothing: the generic `--uxm-{id}-{kebab}` rule already lands\n // on the names the stylesheet reads.\n 'lifecycle-drop-slot': {\n borderColor: '--uxm-lifecycle-drop-slot-border-color',\n borderStyle: '--uxm-lifecycle-drop-slot-border-style',\n borderWidth: '--uxm-lifecycle-drop-slot-border-width',\n color: '--uxm-lifecycle-drop-slot-color',\n },\n // Only the knobs whose keys collide with REAL_CSS_PROPS need an entry: left\n // to the generic path they'd emit a real `background-color` / `border-width` /\n // `padding` on `.uxm-lifecycle-group-box` from a later sheet, hard-overriding\n // the rule's own `var(--uxm-… , token)` chain — and `padding` is read BY THE\n // CONSUMER off the custom property to inset the group's members, so a real\n // declaration would leave that value unreadable.\n //\n // `blur` and the three `target*` knobs are absent on purpose: the generic\n // `--uxm-{id}-{kebab}` rule already lands on the names the stylesheet reads.\n 'lifecycle-group-box': {\n backgroundColor: '--uxm-lifecycle-group-box-bg',\n borderColor: '--uxm-lifecycle-group-box-border-color',\n borderWidth: '--uxm-lifecycle-group-box-border-width',\n borderRadius: '--uxm-lifecycle-group-box-radius',\n padding: '--uxm-lifecycle-group-box-padding',\n },\n 'lifecycle-minimap': {\n backgroundColor: '--uxm-lifecycle-minimap-bg',\n borderColor: '--uxm-lifecycle-minimap-border-color',\n borderRadius: '--uxm-lifecycle-minimap-radius',\n width: '--uxm-lifecycle-minimap-width',\n height: '--uxm-lifecycle-minimap-height',\n },\n 'lifecycle-node-card': {\n backgroundColor: '--uxm-lifecycle-node-card-bg',\n borderColor: '--uxm-lifecycle-node-card-border-color',\n borderRadius: '--uxm-lifecycle-node-card-radius',\n paddingX: '--uxm-lifecycle-node-card-padding-x',\n paddingY: '--uxm-lifecycle-node-card-padding-y',\n width: '--uxm-lifecycle-node-card-width',\n minHeight: '--uxm-lifecycle-node-card-min-height',\n },\n 'lifecycle-terminal': {\n backgroundColor: '--uxm-lifecycle-terminal-bg',\n borderColor: '--uxm-lifecycle-terminal-border-color',\n color: '--uxm-lifecycle-terminal-color',\n borderRadius: '--uxm-lifecycle-terminal-radius',\n width: '--uxm-lifecycle-terminal-width',\n height: '--uxm-lifecycle-terminal-height',\n fontSize: '--uxm-lifecycle-terminal-font-size',\n fontWeight: '--uxm-lifecycle-terminal-font-weight',\n },\n 'lifecycle-zoom-control': {\n backgroundColor: '--uxm-lifecycle-zoom-bg',\n borderColor: '--uxm-lifecycle-zoom-border-color',\n borderRadius: '--uxm-lifecycle-zoom-radius',\n fontSize: '--uxm-lifecycle-zoom-font-size',\n color: '--uxm-lifecycle-zoom-color',\n buttonSize: '--uxm-lifecycle-zoom-button-size',\n iconColor: '--uxm-lifecycle-zoom-icon-color',\n },\n link: {\n fontSize: '--uxm-link-font-size',\n fontWeight: '--uxm-link-font-weight',\n },\n 'meta-row': {\n fontSize: '--uxm-meta-row-font-size',\n color: '--uxm-meta-row-color',\n gap: '--uxm-meta-row-gap',\n },\n 'number-stepper': {\n backgroundColor: '--uxm-number-stepper-input-bg',\n borderColor: '--uxm-number-stepper-input-border',\n color: '--uxm-number-stepper-input-color',\n borderRadius: '--uxm-number-stepper-input-radius',\n paddingX: '--uxm-number-stepper-input-padding-x',\n paddingY: '--uxm-number-stepper-input-padding-y',\n fontSize: '--uxm-number-stepper-font-size',\n gap: '--uxm-number-stepper-gap',\n },\n 'page-header': {\n gap: '--uxm-page-header-gap',\n paddingX: '--uxm-page-header-padding-x',\n paddingY: '--uxm-page-header-padding-y',\n },\n 'page-shell': {\n backgroundColor: '--uxm-page-shell-bg',\n },\n 'property-field': {\n gap: '--uxm-property-field-gap',\n },\n 'property-grid': {\n rowGap: '--uxm-property-grid-row-gap',\n columnGap: '--uxm-property-grid-column-gap',\n },\n 'responsive-grid': {\n gap: '--uxm-responsive-grid-gap',\n },\n 'section-header': {\n gap: '--uxm-section-header-gap',\n },\n stack: {\n gap: '--uxm-stack-gap',\n },\n 'stat-card': {\n backgroundColor: '--uxm-stat-card-background-color',\n borderColor: '--uxm-stat-card-border-color',\n borderRadius: '--uxm-stat-card-border-radius',\n padding: '--uxm-stat-card-padding',\n },\n tag: {\n borderRadius: '--uxm-tag-border-radius',\n fontWeight: '--uxm-tag-font-weight',\n },\n thumbnail: {\n borderRadius: '--uxm-thumbnail-border-radius',\n backgroundColor: '--uxm-thumbnail-background-color',\n borderColor: '--uxm-thumbnail-border-color',\n borderWidth: '--uxm-thumbnail-border-width',\n },\n 'timeline-entry': {\n gap: '--uxm-timeline-entry-gap',\n },\n 'segment-row': {\n paddingX: '--uxm-segment-row-padding-x',\n paddingY: '--uxm-segment-row-padding-y',\n gap: '--uxm-segment-row-gap',\n dragColor: '--uxm-segment-row-drag-color',\n dragHoverColor: '--uxm-segment-row-drag-hover-color',\n chevronColor: '--uxm-segment-row-chevron-color',\n chevronSize: '--uxm-segment-row-chevron-size',\n accentColor: '--uxm-segment-row-accent-color',\n accentWidth: '--uxm-segment-row-accent-width',\n accentRadius: '--uxm-segment-row-accent-radius',\n titleColor: '--uxm-segment-row-title-color',\n titleSize: '--uxm-segment-row-title-size',\n titleWeight: '--uxm-segment-row-title-weight',\n countBg: '--uxm-segment-row-count-bg',\n countColor: '--uxm-segment-row-count-color',\n countSize: '--uxm-segment-row-count-size',\n countPaddingX: '--uxm-segment-row-count-padding-x',\n countPaddingY: '--uxm-segment-row-count-padding-y',\n countRadius: '--uxm-segment-row-count-radius',\n rowHoverBg: '--uxm-segment-row-row-hover-bg',\n rowHoverRadius: '--uxm-segment-row-row-hover-radius',\n },\n 'segment-card': {\n borderColor: '--uxm-segment-card-border-color',\n borderWidth: '--uxm-segment-card-border-width',\n borderRadius: '--uxm-segment-card-border-radius',\n backgroundColor: '--uxm-segment-card-background',\n paddingX: '--uxm-segment-card-padding-x',\n paddingY: '--uxm-segment-card-padding-y',\n childrenInsetX: '--uxm-segment-card-children-inset-x',\n childrenInsetY: '--uxm-segment-card-children-inset-y',\n childrenGap: '--uxm-segment-card-children-gap',\n dividerColor: '--uxm-segment-card-divider-color',\n dividerWidth: '--uxm-segment-card-divider-width',\n },\n 'component-row': {\n paddingX: '--uxm-component-row-padding-x',\n paddingY: '--uxm-component-row-padding-y',\n gap: '--uxm-component-row-gap',\n backgroundColor: '--uxm-component-row-background',\n dragColor: '--uxm-component-row-drag-color',\n dragHoverColor: '--uxm-component-row-drag-hover-color',\n iconBadgeSize: '--uxm-component-row-icon-badge-size',\n iconBadgeRadius: '--uxm-component-row-icon-badge-radius',\n iconBadgePadding: '--uxm-component-row-icon-badge-padding',\n nameColor: '--uxm-component-row-name-color',\n nameSize: '--uxm-component-row-name-size',\n nameWeight: '--uxm-component-row-name-weight',\n typeLabelColor: '--uxm-component-row-type-label-color',\n typeLabelSize: '--uxm-component-row-type-label-size',\n typeLabelWeight: '--uxm-component-row-type-label-weight',\n chevronColor: '--uxm-component-row-chevron-color',\n chevronSize: '--uxm-component-row-chevron-size',\n rowHoverBg: '--uxm-component-row-row-hover-bg',\n rowHoverRadius: '--uxm-component-row-row-hover-radius',\n },\n 'option-list': {\n indent: '--uxm-option-list-indent',\n backgroundColor: '--uxm-option-list-background',\n borderColor: '--uxm-option-list-border-color',\n borderWidth: '--uxm-option-list-border-width',\n borderRadius: '--uxm-option-list-border-radius',\n paddingX: '--uxm-option-list-padding-x',\n paddingY: '--uxm-option-list-padding-y',\n gap: '--uxm-option-list-gap',\n rowPaddingX: '--uxm-option-list-row-padding-x',\n rowPaddingY: '--uxm-option-list-row-padding-y',\n dragColor: '--uxm-option-list-drag-color',\n dragHoverColor: '--uxm-option-list-drag-hover-color',\n bulletSize: '--uxm-option-list-bullet-size',\n bulletGap: '--uxm-option-list-bullet-gap',\n nameColor: '--uxm-option-list-name-color',\n nameSize: '--uxm-option-list-name-size',\n nameWeight: '--uxm-option-list-name-weight',\n rowHoverBg: '--uxm-option-list-row-hover-bg',\n rowHoverRadius: '--uxm-option-list-row-hover-radius',\n },\n tooltip: {\n backgroundColor: '--uxm-tooltip-background-color',\n color: '--uxm-tooltip-color',\n borderRadius: '--uxm-tooltip-border-radius',\n paddingX: '--uxm-tooltip-padding-x',\n paddingY: '--uxm-tooltip-padding-y',\n fontSize: '--uxm-tooltip-font-size',\n },\n 'content-tooltip': {\n backgroundColor: '--uxm-content-tooltip-background-color',\n borderColor: '--uxm-content-tooltip-border-color',\n borderRadius: '--uxm-content-tooltip-border-radius',\n padding: '--uxm-content-tooltip-padding',\n maxWidth: '--uxm-content-tooltip-max-width',\n },\n 'type-overview-card': {\n backgroundColor: '--uxm-typeoverview-bg',\n borderColor: '--uxm-typeoverview-border-color',\n borderRadius: '--uxm-typeoverview-radius',\n padding: '--uxm-typeoverview-padding',\n accentColor: '--uxm-typeoverview-accent-color',\n accentWidth: '--uxm-typeoverview-accent-width',\n iconBg: '--uxm-typeoverview-icon-bg',\n iconColor: '--uxm-typeoverview-icon-color',\n iconBoxSize: '--uxm-typeoverview-icon-tile-size',\n iconRadius: '--uxm-typeoverview-icon-tile-radius',\n labelSize: '--uxm-typeoverview-label-size',\n labelColor: '--uxm-typeoverview-label-color',\n valueSize: '--uxm-typeoverview-value-size',\n valueColor: '--uxm-typeoverview-value-color',\n },\n // Without an entry here every knob would fall through to the generic\n // `--uxm-{id}-{kebab}` rule and double the segment — `connectorIdleColor`\n // under id `lifecycle-connector` becomes\n // `--uxm-lifecycle-connector-connector-idle-color`. The stylesheet reads the\n // canonical single-`connector` names (and still accepts the doubled ones as\n // a fallback alias), so map the knobs explicitly.\n //\n // `connectorArrowSize` sizes an SVG polygon rather than setting any CSS\n // property, so no rule can consume it — `useThemedArrowSize` in\n // lifecycle-connector.tsx reads `--uxm-lifecycle-connector-arrow-size` back\n // off the element instead. It is published here for that reason, not for\n // naming tidiness: drop this line and a saved Arrow Size stops applying.\n 'lifecycle-connector': {\n connectorIdleColor: '--uxm-lifecycle-connector-idle-color',\n connectorActiveColor: '--uxm-lifecycle-connector-active-color',\n connectorIdleStrokeWidth: '--uxm-lifecycle-connector-idle-stroke-width',\n connectorActiveStrokeWidth: '--uxm-lifecycle-connector-active-stroke-width',\n connectorDashedColor: '--uxm-lifecycle-connector-dashed-color',\n connectorDashedStrokeWidth: '--uxm-lifecycle-connector-dashed-stroke-width',\n connectorDashPattern: '--uxm-lifecycle-connector-dash-pattern',\n connectorArrowSize: '--uxm-lifecycle-connector-arrow-size',\n },\n};\n\nfunction toCSS(key: string, componentId: string): string {\n const componentMapping = PER_COMPONENT_MAPPING[componentId];\n if (componentMapping?.[key]) return componentMapping[key];\n\n const mapping: Record<string, string> = {\n paddingX: 'padding-inline',\n paddingY: 'padding-block',\n };\n if (mapping[key]) return mapping[key];\n\n const kebab = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n if (REAL_CSS_PROPS.has(key)) return kebab;\n return `--uxm-${componentId}-${kebab}`;\n}\n\nfunction formatValue(value: string | number | boolean, key: string): string {\n if (typeof value === 'boolean') return value ? '1' : '0';\n if (typeof value === 'number') {\n // `lineHeight` is a ratio, not a length — without it here a knob saved as\n // 1.5 emits `line-height: 1.5px`, which collapses every line box.\n const unitless = ['fontWeight', 'titleWeight', 'nameWeight', 'typeLabelWeight', 'lineHeight', 'shadow', 'disabledOpacity'];\n // `opacity` is always unitless — match every *Opacity knob (e.g. the\n // per-element `itemDisabledOpacity` / `optionDisabledOpacity` variants)\n // so a saved value never gets a spurious `px` suffix.\n if (unitless.includes(key) || key.endsWith('Opacity')) return String(value);\n return `${value}px`;\n }\n // String style-override values are user/attacker-controlled and persisted\n // to a stylesheet served to every browser session — sanitise the same way\n // as brand token values so one can't break out of the declaration (e.g.\n // `red; } body{display:none}/*`). An unsafe value is dropped to '' rather\n // than throwing, so a single bad override can't blank the whole rule.\n return safeTokenValue(value) ?? '';\n}\n\n// CSS sanitizers — applied to every brand value before interpolation. The\n// output is persisted and served to all browser sessions, so attacker-\n// controlled values must not break out of the declaration they belong to.\nfunction safeUrl(v: unknown): string | undefined {\n if (typeof v !== 'string') return undefined;\n const trimmed = v.trim();\n if (!/^(https?:\\/\\/|\\/)/.test(trimmed)) return undefined;\n if (/[\")\\n\\r]/.test(trimmed)) return undefined;\n return trimmed;\n}\nexport function safeFontFamily(v: unknown): string | undefined {\n if (typeof v !== 'string') return undefined;\n const trimmed = v.trim();\n return /^[A-Za-z0-9 _-]+$/.test(trimmed) ? trimmed : undefined;\n}\n// Heading weight is a closed set (the editor offers exactly these three), so a\n// strict whitelist is both the sanitizer and the contract. Numbers are accepted\n// defensively — a persisted config may carry the JSON number rather than the\n// string the <select> yields.\nexport function safeFontWeight(v: unknown): string | undefined {\n const s = typeof v === 'number' ? String(v) : typeof v === 'string' ? v.trim() : undefined;\n return s !== undefined && /^(500|600|700)$/.test(s) ? s : undefined;\n}\n// Scales multiply a length inside calc(), which makes a bad value far worse\n// than a dropped declaration: `abc` or `1.2px` (length × length) is invalid at\n// computed-value time, so `font-size` resolves to `unset` and INHERITS — one\n// poisoned value on :root collapses the whole app to the parent's size. A\n// plain-number whitelist plus a sane range is the only safe gate; note\n// `safeTokenValue` is NOT sufficient (it passes `abc`, `-1` and unbalanced\n// parens). Range mirrors the editor's slider bounds.\nexport function safeTypeScale(v: unknown): string | undefined {\n const s = typeof v === 'number' ? String(v) : typeof v === 'string' ? v.trim() : undefined;\n if (s === undefined || !/^(?:0|[1-9]\\d?)(?:\\.\\d{1,3})?$/.test(s)) return undefined;\n const n = Number(s);\n return n >= 0.5 && n <= 2 ? s : undefined;\n}\n// Line height is a unitless ratio; same invalid-at-computed-value-time risk as\n// the scales, but it only affects the declarations that read it.\nexport function safeLineHeight(v: unknown): string | undefined {\n const s = typeof v === 'number' ? String(v) : typeof v === 'string' ? v.trim() : undefined;\n if (s === undefined || !/^[1-9](?:\\.\\d{1,2})?$/.test(s)) return undefined;\n const n = Number(s);\n return n >= 1 && n <= 2.5 ? s : undefined;\n}\nexport function safeTokenKey(v: string): boolean {\n return /^--[A-Za-z0-9-]+$/.test(v);\n}\nexport function safeTokenValue(v: unknown): string | undefined {\n if (typeof v !== 'string') return undefined;\n return /[{};\\n\\r]/.test(v) ? undefined : v;\n}\n\n// The three heading roles, in one place. Both the publish path below and the\n// live mirror (`brand-font-styles.tsx`) derive their emitted var names from\n// `role` by interpolation, so a rename here reaches both — keeping these in two\n// hand-maintained lists is how `--type-${role}-font` silently drifts away from\n// the names the stylesheets actually read.\nexport const TYPE_ROLES = [\n { role: 'display', family: 'displayFontFamily', weight: 'displayFontWeight', scale: 'displayScale' },\n { role: 'page-title', family: 'pageTitleFontFamily', weight: 'pageTitleFontWeight', scale: 'pageTitleScale' },\n { role: 'section-title', family: 'sectionTitleFontFamily', weight: 'sectionTitleFontWeight', scale: 'sectionTitleScale' },\n] as const satisfies ReadonlyArray<{\n role: string;\n family: keyof BrandConfig;\n weight: keyof BrandConfig;\n scale: keyof BrandConfig;\n}>;\n\n/** Sanitised per-role typography, shared by the generator and the live mirror. */\nexport function resolveTypeRoles(brand: BrandConfig) {\n return TYPE_ROLES.map((r) => ({\n role: r.role,\n family: safeFontFamily(brand[r.family]),\n weight: safeFontWeight(brand[r.weight]),\n scale: safeTypeScale(brand[r.scale]),\n }));\n}\n\n/** Generate the overrides stylesheet from style overrides + brand config. */\nexport function generateOverridesCss(allOverrides: AllOverrides, brand: BrandConfig): string {\n const lines: string[] = ['/* Auto-generated by UXM — do not edit manually */', ''];\n\n const fontFamily = safeFontFamily(brand.fontFamily);\n const headingFontFamily = safeFontFamily(brand.headingFontFamily);\n const headingFontWeight = safeFontWeight(brand.headingFontWeight);\n // Per-role refinements, layered under the umbrella heading vars above.\n const roles = resolveTypeRoles(brand);\n const typeScale = safeTypeScale(brand.typeScale);\n const bodyLineHeight = safeLineHeight(brand.bodyLineHeight);\n const logoUrl = safeUrl(brand.logoUrl);\n const iconUrl = safeUrl(brand.iconUrl);\n const logoUrlDark = safeUrl(brand.logoUrlDark);\n const iconUrlDark = safeUrl(brand.iconUrlDark);\n\n if (fontFamily) {\n lines.push(`@import url(\"${fontFileUrl(fontFamily)}\");`);\n lines.push('');\n }\n // Second font file only when the heading face is actually a different family\n // — picking the same one for both is a no-op, not a reason to fetch twice.\n if (headingFontFamily && headingFontFamily !== fontFamily) {\n lines.push(`@import url(\"${fontFileUrl(headingFontFamily)}\");`);\n lines.push('');\n }\n // A role may pick a face neither the body nor the umbrella uses — fetch each\n // distinct one exactly once (@import must stay above the rules below).\n const imported = new Set([fontFamily, headingFontFamily].filter(Boolean));\n for (const { family } of roles) {\n if (family && !imported.has(family)) {\n imported.add(family);\n lines.push(`@import url(\"${fontFileUrl(family)}\");`);\n lines.push('');\n }\n }\n\n const brandRules: string[] = [];\n if (fontFamily) {\n brandRules.push(` --brand-font: \"${fontFamily}\", var(--font-inter), system-ui, sans-serif;`);\n }\n // Heading vars are consumed by the components' own two-layer fallbacks (see\n // e.g. page-header.scss), so there is no `body` rule and no `!important`:\n // an unset var simply lets each component's own default paint.\n if (headingFontFamily) {\n brandRules.push(` --brand-heading-font: \"${headingFontFamily}\", var(--font-inter), system-ui, sans-serif;`);\n }\n if (headingFontWeight) {\n brandRules.push(` --brand-heading-weight: ${headingFontWeight};`);\n }\n // Role vars sit between the component var and the umbrella in each atom's\n // chain, so an unset role simply falls through to the umbrella.\n for (const { role, family, weight, scale } of roles) {\n if (family) {\n brandRules.push(` --type-${role}-font: \"${family}\", var(--font-inter), system-ui, sans-serif;`);\n }\n if (weight) brandRules.push(` --type-${role}-weight: ${weight};`);\n if (scale) brandRules.push(` --type-${role}-scale: ${scale};`);\n }\n if (typeScale) brandRules.push(` --type-scale: ${typeScale};`);\n if (bodyLineHeight) brandRules.push(` --type-body-line-height: ${bodyLineHeight};`);\n if (logoUrl) brandRules.push(` --brand-logo-url: url(\"${logoUrl}\");`);\n if (iconUrl) brandRules.push(` --brand-icon-url: url(\"${iconUrl}\");`);\n\n if (brandRules.length > 0) {\n lines.push(':root {');\n lines.push(...brandRules);\n lines.push('}');\n lines.push('');\n if (fontFamily) {\n lines.push('body { font-family: var(--brand-font) !important; }');\n lines.push('');\n }\n // Emitted ONLY when set. The library ships no element-level rules at all,\n // so an unconditional `body { line-height }` would reflow the host's own\n // content — same reasoning as the font-family rule above.\n if (bodyLineHeight) {\n // Explicit fallback: if the var is later cancelled (the studio mirror\n // re-declares it as `initial` on revert) a bare `var()` would be invalid\n // at computed-value time and `line-height` — being inherited — would\n // resolve to the parent's value, silently replacing whatever the host\n // had set on `body`. `normal` makes the wind-down state deliberate.\n lines.push(`body { line-height: var(--type-body-line-height, normal); }`);\n lines.push('');\n }\n }\n\n const darkBrandRules: string[] = [];\n if (logoUrlDark) darkBrandRules.push(` --brand-logo-url: url(\"${logoUrlDark}\");`);\n if (iconUrlDark) darkBrandRules.push(` --brand-icon-url: url(\"${iconUrlDark}\");`);\n if (darkBrandRules.length > 0) {\n lines.push('[data-theme=\"dark\"] {');\n lines.push(...darkBrandRules);\n lines.push('}');\n lines.push('');\n }\n\n const emitTokens = (selector: string, overrides: Record<string, string> | undefined) => {\n if (!overrides) return;\n const safeEntries = Object.entries(overrides).flatMap(([k, v]) => {\n if (!safeTokenKey(k)) return [];\n const safeValue = safeTokenValue(v);\n return safeValue === undefined ? [] : [[k, safeValue] as const];\n });\n if (safeEntries.length === 0) return;\n lines.push(`${selector} {`);\n for (const [cssVar, value] of safeEntries) {\n lines.push(` ${cssVar}: ${value};`);\n }\n lines.push('}');\n lines.push('');\n };\n // Scope customized light-mode color tokens to non-dark. `:root` and\n // `[data-theme=\"dark\"]` carry equal specificity, so an unconditional\n // `:root` block would win over this stylesheet's own dark block for any\n // token NOT also customized for dark (equal specificity, later source\n // order) — pinning that token to its light value in dark mode too. Scoping\n // lets an unset dark token fall through the cascade to tokens/index.css's\n // own `[data-theme=\"dark\"]` default instead.\n emitTokens(':root:not([data-theme=\"dark\"])', brand.tokens?.light);\n emitTokens('[data-theme=\"dark\"]', brand.tokens?.dark);\n\n const componentIds = Object.keys(allOverrides).sort();\n\n for (const id of componentIds) {\n const overrides = allOverrides[id];\n const entries = Object.entries(overrides);\n if (entries.length === 0) continue;\n\n const selector = PER_COMPONENT_SELECTOR[id] ?? `.uxm-${id}`;\n lines.push(`${selector} {`);\n for (const [key, value] of entries) {\n const cssProp = toCSS(key, id);\n const cssValue = formatValue(value, key);\n lines.push(` ${cssProp}: ${cssValue};`);\n }\n lines.push('}');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n"],"mappings":"AAgBA,MAAM,qBAAqB;AAEpB,SAAS,YAAY,YAA4B;AACtD,QAAM,UAAU,WAAW,KAAK,EAAE,QAAQ,QAAQ,GAAG;AACrD,SAAO,4CAA4C,OAAO,IAAI,kBAAkB;AAClF;AAEA,MAAM,iBAAiB,oBAAI,IAAI;AAAA,EAC7B;AAAA,EAAc;AAAA,EACd;AAAA,EACA;AAAA,EAAU;AAAA,EAAe;AAAA,EAAgB;AAAA,EAAe;AAAA,EACxD;AAAA,EAAW;AAAA,EAAY;AAAA,EAAY;AAAA,EACnC;AAAA,EAAO;AAAA,EAAU;AAAA,EACjB;AAAA,EAAS;AAAA,EAAU;AAAA,EAAY;AAAA,EAAY;AAAA,EAAa;AAAA,EACxD;AAAA,EAAY;AAAA,EAAc;AAAA,EAAc;AAAA,EACxC;AAAA,EACA;AAAA,EAAU;AAAA,EAAW;AAAA,EAAY;AAAA,EAAY;AAC/C,CAAC;AAOD,MAAM,yBAAiD;AAAA,EACrD,SAAS;AAAA;AAAA;AAAA;AAAA,EAIT,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAMR;AAOA,MAAM,wBAAgE;AAAA,EACpE,mBAAmB;AAAA,IACjB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,EACT;AAAA,EACA,cAAc;AAAA,IACZ,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,OAAO;AAAA,IACP,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,gBAAgB;AAAA,IACd,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,OAAO;AAAA,IACP,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,qBAAqB;AAAA,IACnB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,IACV,KAAK;AAAA,IACL,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAIA,eAAe;AAAA,IACb,UAAU;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,eAAe;AAAA,IACb,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,OAAO;AAAA,IACP,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAAA,EACA,kBAAkB;AAAA,IAChB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,EACT;AAAA,EACA,UAAU;AAAA,IACR,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,OAAO;AAAA,IACP,WAAW;AAAA,IACX,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,eAAe;AAAA,IACb,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,OAAO;AAAA,IACP,cAAc;AAAA,IACd,aAAa;AAAA,IACb,aAAa;AAAA,IACb,UAAU;AAAA,IACV,UAAU;AAAA,IACV,WAAW;AAAA,IACX,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AAAA,EACA,mBAAmB;AAAA,IACjB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,OAAO;AAAA,IACP,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,cAAc;AAAA,IACZ,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,EACT;AAAA,EACA,kBAAkB;AAAA,IAChB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,EACT;AAAA,EACA,cAAc;AAAA,IACZ,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,EACT;AAAA,EACA,eAAe;AAAA,IACb,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,EACT;AAAA,EACA,UAAU;AAAA,IACR,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA,EACX;AAAA,EACA,MAAM;AAAA,IACJ,KAAK;AAAA,IACL,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,kBAAkB;AAAA,IAChB,KAAK;AAAA,IACL,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,eAAe;AAAA,IACb,KAAK;AAAA,IACL,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,iBAAiB;AAAA,IACf,KAAK;AAAA,EACP;AAAA,EACA,gBAAgB;AAAA,IACd,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,UAAU;AAAA,IACR,cAAc;AAAA,IACd,KAAK;AAAA,EACP;AAAA,EACA,MAAM;AAAA,IACJ,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAcT,KAAK;AAAA,EACP;AAAA,EACA,iBAAiB;AAAA,IACf,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAAA,EACA,eAAe;AAAA,IACb,KAAK;AAAA,EACP;AAAA,EACA,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AAAA,EACA,cAAc;AAAA,IACZ,aAAa;AAAA,IACb,UAAU;AAAA,IACV,cAAc;AAAA,EAChB;AAAA,EACA,eAAe;AAAA,IACb,aAAa;AAAA,IACb,iBAAiB;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,uBAAuB;AAAA,IACrB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,cAAc;AAAA,EAChB;AAAA,EACA,oBAAoB;AAAA,IAClB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,cAAc;AAAA,EAChB;AAAA,EACA,sBAAsB;AAAA,IACpB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,cAAc;AAAA,EAChB;AAAA,EACA,eAAe;AAAA,IACb,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,KAAK;AAAA,EACP;AAAA,EACA,oBAAoB;AAAA,IAClB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,cAAc;AAAA,IACd,KAAK;AAAA,IACL,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,gBAAgB;AAAA,IACd,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,OAAO;AAAA,IACP,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,KAAK;AAAA,EACP;AAAA,EACA,eAAe;AAAA,IACb,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,sBAAsB;AAAA,IACtB,uBAAuB;AAAA,IACvB,cAAc;AAAA,EAChB;AAAA,EACA,kBAAkB;AAAA,IAChB,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,cAAc;AAAA,IACd,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,oBAAoB;AAAA,IAClB,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,mBAAmB;AAAA,IACjB,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,gBAAgB;AAAA,IACd,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,cAAc;AAAA,IACd,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,iBAAiB;AAAA,IACf,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,oBAAoB;AAAA,IAClB,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,eAAe;AAAA,IACb,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,cAAc;AAAA,EAChB;AAAA,EACA,aAAa;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,KAAK;AAAA,EACP;AAAA,EACA,YAAY;AAAA,IACV,UAAU;AAAA,IACV,KAAK;AAAA,EACP;AAAA,EACA,YAAY;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,KAAK;AAAA,IACL,cAAc;AAAA,EAChB;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,OAAO;AAAA,EACT;AAAA,EACA,aAAa;AAAA,IACX,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,KAAK;AAAA,IACL,cAAc;AAAA,IACd,aAAa;AAAA,EACf;AAAA,EACA,eAAe;AAAA,IACb,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,OAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,OAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa;AAAA,IACb,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,mBAAmB;AAAA,IACjB,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,KAAK;AAAA,IACL,UAAU;AAAA,EACZ;AAAA,EACA,SAAS;AAAA,IACP,KAAK;AAAA,EACP;AAAA,EACA,wBAAwB;AAAA,IACtB,SAAS;AAAA,IACT,cAAc;AAAA,EAChB;AAAA,EACA,uBAAuB;AAAA,IACrB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,cAAc;AAAA,EAChB;AAAA,EACA,kBAAkB;AAAA,IAChB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA,EACX;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AAAA,EACA,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMf,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYP,WAAW;AAAA,IACX,UAAU;AAAA,IACV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,IAKV,UAAU;AAAA,EACZ;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,EACX;AAAA,EACA,cAAc;AAAA,IACZ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,IAKL,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWhB,YAAY;AAAA,EACd;AAAA,EACA,aAAa;AAAA,IACX,cAAc;AAAA,IACd,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,MAAM;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA,iBAAiB;AAAA,IACf,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,KAAK;AAAA,EACP;AAAA,EACA,iBAAiB;AAAA,IACf,KAAK;AAAA,EACP;AAAA,EACA,wBAAwB;AAAA,IACtB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,cAAc;AAAA,IACd,aAAa;AAAA,IACb,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,uBAAuB;AAAA,IACrB,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa;AAAA,IACb,OAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,uBAAuB;AAAA,IACrB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA,EACX;AAAA,EACA,qBAAqB;AAAA,IACnB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAAA,EACA,uBAAuB;AAAA,IACrB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA,sBAAsB;AAAA,IACpB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,OAAO;AAAA,IACP,cAAc;AAAA,IACd,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,0BAA0B;AAAA,IACxB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAAA,EACA,MAAM;AAAA,IACJ,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,YAAY;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,IACP,KAAK;AAAA,EACP;AAAA,EACA,kBAAkB;AAAA,IAChB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,OAAO;AAAA,IACP,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,KAAK;AAAA,EACP;AAAA,EACA,eAAe;AAAA,IACb,KAAK;AAAA,IACL,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,cAAc;AAAA,IACZ,iBAAiB;AAAA,EACnB;AAAA,EACA,kBAAkB;AAAA,IAChB,KAAK;AAAA,EACP;AAAA,EACA,iBAAiB;AAAA,IACf,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,mBAAmB;AAAA,IACjB,KAAK;AAAA,EACP;AAAA,EACA,kBAAkB;AAAA,IAChB,KAAK;AAAA,EACP;AAAA,EACA,OAAO;AAAA,IACL,KAAK;AAAA,EACP;AAAA,EACA,aAAa;AAAA,IACX,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA,EACX;AAAA,EACA,KAAK;AAAA,IACH,cAAc;AAAA,IACd,YAAY;AAAA,EACd;AAAA,EACA,WAAW;AAAA,IACT,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,aAAa;AAAA,EACf;AAAA,EACA,kBAAkB;AAAA,IAChB,KAAK;AAAA,EACP;AAAA,EACA,eAAe;AAAA,IACb,UAAU;AAAA,IACV,UAAU;AAAA,IACV,KAAK;AAAA,IACL,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,aAAa;AAAA,IACb,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,eAAe;AAAA,IACf,eAAe;AAAA,IACf,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,gBAAgB;AAAA,EAClB;AAAA,EACA,gBAAgB;AAAA,IACd,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,cAAc;AAAA,EAChB;AAAA,EACA,iBAAiB;AAAA,IACf,UAAU;AAAA,IACV,UAAU;AAAA,IACV,KAAK;AAAA,IACL,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,gBAAgB;AAAA,EAClB;AAAA,EACA,eAAe;AAAA,IACb,QAAQ;AAAA,IACR,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,KAAK;AAAA,IACL,aAAa;AAAA,IACb,aAAa;AAAA,IACb,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,gBAAgB;AAAA,EAClB;AAAA,EACA,SAAS;AAAA,IACP,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,mBAAmB;AAAA,IACjB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA,EACA,sBAAsB;AAAA,IACpB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,SAAS;AAAA,IACT,aAAa;AAAA,IACb,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,YAAY;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,uBAAuB;AAAA,IACrB,oBAAoB;AAAA,IACpB,sBAAsB;AAAA,IACtB,0BAA0B;AAAA,IAC1B,4BAA4B;AAAA,IAC5B,sBAAsB;AAAA,IACtB,4BAA4B;AAAA,IAC5B,sBAAsB;AAAA,IACtB,oBAAoB;AAAA,EACtB;AACF;AAEA,SAAS,MAAM,KAAa,aAA6B;AACvD,QAAM,mBAAmB,sBAAsB,WAAW;AAC1D,MAAI,mBAAmB,GAAG,EAAG,QAAO,iBAAiB,GAAG;AAExD,QAAM,UAAkC;AAAA,IACtC,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AACA,MAAI,QAAQ,GAAG,EAAG,QAAO,QAAQ,GAAG;AAEpC,QAAM,QAAQ,IAAI,QAAQ,YAAY,KAAK,EAAE,YAAY;AACzD,MAAI,eAAe,IAAI,GAAG,EAAG,QAAO;AACpC,SAAO,SAAS,WAAW,IAAI,KAAK;AACtC;AAEA,SAAS,YAAY,OAAkC,KAAqB;AAC1E,MAAI,OAAO,UAAU,UAAW,QAAO,QAAQ,MAAM;AACrD,MAAI,OAAO,UAAU,UAAU;AAG7B,UAAM,WAAW,CAAC,cAAc,eAAe,cAAc,mBAAmB,cAAc,UAAU,iBAAiB;AAIzH,QAAI,SAAS,SAAS,GAAG,KAAK,IAAI,SAAS,SAAS,EAAG,QAAO,OAAO,KAAK;AAC1E,WAAO,GAAG,KAAK;AAAA,EACjB;AAMA,SAAO,eAAe,KAAK,KAAK;AAClC;AAKA,SAAS,QAAQ,GAAgC;AAC/C,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,QAAM,UAAU,EAAE,KAAK;AACvB,MAAI,CAAC,oBAAoB,KAAK,OAAO,EAAG,QAAO;AAC/C,MAAI,WAAW,KAAK,OAAO,EAAG,QAAO;AACrC,SAAO;AACT;AACO,SAAS,eAAe,GAAgC;AAC7D,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,QAAM,UAAU,EAAE,KAAK;AACvB,SAAO,oBAAoB,KAAK,OAAO,IAAI,UAAU;AACvD;AAKO,SAAS,eAAe,GAAgC;AAC7D,QAAM,IAAI,OAAO,MAAM,WAAW,OAAO,CAAC,IAAI,OAAO,MAAM,WAAW,EAAE,KAAK,IAAI;AACjF,SAAO,MAAM,UAAa,kBAAkB,KAAK,CAAC,IAAI,IAAI;AAC5D;AAQO,SAAS,cAAc,GAAgC;AAC5D,QAAM,IAAI,OAAO,MAAM,WAAW,OAAO,CAAC,IAAI,OAAO,MAAM,WAAW,EAAE,KAAK,IAAI;AACjF,MAAI,MAAM,UAAa,CAAC,iCAAiC,KAAK,CAAC,EAAG,QAAO;AACzE,QAAM,IAAI,OAAO,CAAC;AAClB,SAAO,KAAK,OAAO,KAAK,IAAI,IAAI;AAClC;AAGO,SAAS,eAAe,GAAgC;AAC7D,QAAM,IAAI,OAAO,MAAM,WAAW,OAAO,CAAC,IAAI,OAAO,MAAM,WAAW,EAAE,KAAK,IAAI;AACjF,MAAI,MAAM,UAAa,CAAC,wBAAwB,KAAK,CAAC,EAAG,QAAO;AAChE,QAAM,IAAI,OAAO,CAAC;AAClB,SAAO,KAAK,KAAK,KAAK,MAAM,IAAI;AAClC;AACO,SAAS,aAAa,GAAoB;AAC/C,SAAO,oBAAoB,KAAK,CAAC;AACnC;AACO,SAAS,eAAe,GAAgC;AAC7D,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,SAAO,YAAY,KAAK,CAAC,IAAI,SAAY;AAC3C;AAOO,MAAM,aAAa;AAAA,EACxB,EAAE,MAAM,WAAW,QAAQ,qBAAqB,QAAQ,qBAAqB,OAAO,eAAe;AAAA,EACnG,EAAE,MAAM,cAAc,QAAQ,uBAAuB,QAAQ,uBAAuB,OAAO,iBAAiB;AAAA,EAC5G,EAAE,MAAM,iBAAiB,QAAQ,0BAA0B,QAAQ,0BAA0B,OAAO,oBAAoB;AAC1H;AAQO,SAAS,iBAAiB,OAAoB;AACnD,SAAO,WAAW,IAAI,CAAC,OAAO;AAAA,IAC5B,MAAM,EAAE;AAAA,IACR,QAAQ,eAAe,MAAM,EAAE,MAAM,CAAC;AAAA,IACtC,QAAQ,eAAe,MAAM,EAAE,MAAM,CAAC;AAAA,IACtC,OAAO,cAAc,MAAM,EAAE,KAAK,CAAC;AAAA,EACrC,EAAE;AACJ;AAGO,SAAS,qBAAqB,cAA4B,OAA4B;AAC3F,QAAM,QAAkB,CAAC,2DAAsD,EAAE;AAEjF,QAAM,aAAa,eAAe,MAAM,UAAU;AAClD,QAAM,oBAAoB,eAAe,MAAM,iBAAiB;AAChE,QAAM,oBAAoB,eAAe,MAAM,iBAAiB;AAEhE,QAAM,QAAQ,iBAAiB,KAAK;AACpC,QAAM,YAAY,cAAc,MAAM,SAAS;AAC/C,QAAM,iBAAiB,eAAe,MAAM,cAAc;AAC1D,QAAM,UAAU,QAAQ,MAAM,OAAO;AACrC,QAAM,UAAU,QAAQ,MAAM,OAAO;AACrC,QAAM,cAAc,QAAQ,MAAM,WAAW;AAC7C,QAAM,cAAc,QAAQ,MAAM,WAAW;AAE7C,MAAI,YAAY;AACd,UAAM,KAAK,gBAAgB,YAAY,UAAU,CAAC,KAAK;AACvD,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,MAAI,qBAAqB,sBAAsB,YAAY;AACzD,UAAM,KAAK,gBAAgB,YAAY,iBAAiB,CAAC,KAAK;AAC9D,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,QAAM,WAAW,IAAI,IAAI,CAAC,YAAY,iBAAiB,EAAE,OAAO,OAAO,CAAC;AACxE,aAAW,EAAE,OAAO,KAAK,OAAO;AAC9B,QAAI,UAAU,CAAC,SAAS,IAAI,MAAM,GAAG;AACnC,eAAS,IAAI,MAAM;AACnB,YAAM,KAAK,gBAAgB,YAAY,MAAM,CAAC,KAAK;AACnD,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,QAAM,aAAuB,CAAC;AAC9B,MAAI,YAAY;AACd,eAAW,KAAK,oBAAoB,UAAU,8CAA8C;AAAA,EAC9F;AAIA,MAAI,mBAAmB;AACrB,eAAW,KAAK,4BAA4B,iBAAiB,8CAA8C;AAAA,EAC7G;AACA,MAAI,mBAAmB;AACrB,eAAW,KAAK,6BAA6B,iBAAiB,GAAG;AAAA,EACnE;AAGA,aAAW,EAAE,MAAM,QAAQ,QAAQ,MAAM,KAAK,OAAO;AACnD,QAAI,QAAQ;AACV,iBAAW,KAAK,YAAY,IAAI,WAAW,MAAM,8CAA8C;AAAA,IACjG;AACA,QAAI,OAAQ,YAAW,KAAK,YAAY,IAAI,YAAY,MAAM,GAAG;AACjE,QAAI,MAAO,YAAW,KAAK,YAAY,IAAI,WAAW,KAAK,GAAG;AAAA,EAChE;AACA,MAAI,UAAW,YAAW,KAAK,mBAAmB,SAAS,GAAG;AAC9D,MAAI,eAAgB,YAAW,KAAK,8BAA8B,cAAc,GAAG;AACnF,MAAI,QAAS,YAAW,KAAK,4BAA4B,OAAO,KAAK;AACrE,MAAI,QAAS,YAAW,KAAK,4BAA4B,OAAO,KAAK;AAErE,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,KAAK,SAAS;AACpB,UAAM,KAAK,GAAG,UAAU;AACxB,UAAM,KAAK,GAAG;AACd,UAAM,KAAK,EAAE;AACb,QAAI,YAAY;AACd,YAAM,KAAK,qDAAqD;AAChE,YAAM,KAAK,EAAE;AAAA,IACf;AAIA,QAAI,gBAAgB;AAMlB,YAAM,KAAK,6DAA6D;AACxE,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,QAAM,iBAA2B,CAAC;AAClC,MAAI,YAAa,gBAAe,KAAK,4BAA4B,WAAW,KAAK;AACjF,MAAI,YAAa,gBAAe,KAAK,4BAA4B,WAAW,KAAK;AACjF,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,KAAK,uBAAuB;AAClC,UAAM,KAAK,GAAG,cAAc;AAC5B,UAAM,KAAK,GAAG;AACd,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,aAAa,CAAC,UAAkB,cAAkD;AACtF,QAAI,CAAC,UAAW;AAChB,UAAM,cAAc,OAAO,QAAQ,SAAS,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM;AAChE,UAAI,CAAC,aAAa,CAAC,EAAG,QAAO,CAAC;AAC9B,YAAM,YAAY,eAAe,CAAC;AAClC,aAAO,cAAc,SAAY,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAU;AAAA,IAChE,CAAC;AACD,QAAI,YAAY,WAAW,EAAG;AAC9B,UAAM,KAAK,GAAG,QAAQ,IAAI;AAC1B,eAAW,CAAC,QAAQ,KAAK,KAAK,aAAa;AACzC,YAAM,KAAK,KAAK,MAAM,KAAK,KAAK,GAAG;AAAA,IACrC;AACA,UAAM,KAAK,GAAG;AACd,UAAM,KAAK,EAAE;AAAA,EACf;AAQA,aAAW,kCAAkC,MAAM,QAAQ,KAAK;AAChE,aAAW,uBAAuB,MAAM,QAAQ,IAAI;AAEpD,QAAM,eAAe,OAAO,KAAK,YAAY,EAAE,KAAK;AAEpD,aAAW,MAAM,cAAc;AAC7B,UAAM,YAAY,aAAa,EAAE;AACjC,UAAM,UAAU,OAAO,QAAQ,SAAS;AACxC,QAAI,QAAQ,WAAW,EAAG;AAE1B,UAAM,WAAW,uBAAuB,EAAE,KAAK,QAAQ,EAAE;AACzD,UAAM,KAAK,GAAG,QAAQ,IAAI;AAC1B,eAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AAClC,YAAM,UAAU,MAAM,KAAK,EAAE;AAC7B,YAAM,WAAW,YAAY,OAAO,GAAG;AACvC,YAAM,KAAK,KAAK,OAAO,KAAK,QAAQ,GAAG;AAAA,IACzC;AACA,UAAM,KAAK,GAAG;AACd,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;","names":[]}
|
|
@@ -90,6 +90,7 @@ const previewMap = {
|
|
|
90
90
|
"number-input": import_previews.NumberInputPreview,
|
|
91
91
|
"currency-input": import_previews.CurrencyInputPreview,
|
|
92
92
|
"search-dropdown": import_previews.SearchDropdownPreview,
|
|
93
|
+
"language-switcher": import_previews.LanguageSwitcherPreview,
|
|
93
94
|
listbox: import_previews.ListboxPreview,
|
|
94
95
|
menu: import_previews.MenuPreview,
|
|
95
96
|
"editable-cell": import_previews.EditableCellPreview,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/studio/shell/canvas.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\n\n\nimport {\n BannerPreview,\n BulkActionBarPreview,\n AppSidebarPreview,\n AppTopBarPreview,\n AvatarPreview,\n BackLinkPreview,\n BadgePreview,\n BrandSettingsPreview,\n BreadcrumbPreview,\n ButtonGroupPreview,\n ButtonPreview,\n ButtonWithIconPreview,\n CalendarPreview,\n CardPreview,\n CheckboxPreview,\n ChipPreview,\n ClusterPreview,\n CodeEditorPreview,\n ColorInputPreview,\n ComponentRowPreview,\n ConfigComponentRowPreview,\n ConfigSegmentItemPreview,\n ContentTooltipPreview,\n CurrencyInputPreview,\n DataTablePreview,\n DateInputPreview,\n DetailSectionPreview,\n DisclosurePreview,\n DividerPreview,\n EditableCellPreview,\n EmptyStatePreview,\n ErrorPagePreview,\n ExplorerListItemPreview,\n ExplorerSectionPreview,\n FileUploadPreview,\n FilterTabsPreview,\n FormFieldPreview,\n FormPreview,\n IconButtonPreview,\n IconPreview,\n IconTilePreview,\n InlineActionPreview,\n InlineFilterPreview,\n InputPreview,\n InputWithIconPreview,\n LifecycleActionRowPreview,\n LifecycleConnectorKnobsPreview,\n LifecycleConnectorPreview,\n LifecycleDropSlotPreview,\n LifecycleEdgeLabelPreview,\n LifecycleGroupBoxPreview,\n LifecycleMinimapPreview,\n LifecycleNodeCardPreview,\n LifecyclePlusButtonPreview,\n LifecycleTerminalPreview,\n LifecycleZoomControlPreview,\n LinkPreview,\n ListItemPreview,\n ListboxPreview,\n LoaderPreview,\n LoginPagePreview,\n MenuPreview,\n MetaRowPreview,\n ModalPreview,\n MultirowFormPreview,\n NumberStepperPreview,\n NumberInputPreview,\n OptionListPreview,\n PageHeaderPreview,\n PageShellPreview,\n PasswordInputPreview,\n PhoneInputPreview,\n PillSelectPreview,\n ProgressBarPreview,\n PropertyFieldPreview,\n PropertyGridPreview,\n RadioGroupPreview,\n ResponsiveGridPreview,\n SearchDropdownPreview,\n SectionHeaderPreview,\n SegmentCardPreview,\n SegmentRowPreview,\n SelectPreview,\n SideFlexpanePreview,\n SidebarNavItemPreview,\n SidebarNavTriggerPreview,\n SliderPreview,\n StackPreview,\n StatCardPreview,\n TabsPreview,\n TabsUnderlinePreview,\n TagPreview,\n TextareaPreview,\n ThumbnailPreview,\n TimeInputPreview,\n TimelineEntryPreview,\n ToastPreview,\n TogglePreview,\n TooltipPreview,\n TypeOverviewCardPreview,\n ViewSwitcherPreview,\n} from '@/previews';\nimport { ButtonGhost, ButtonPrimary, IconButton } from '@/ui';\nimport { Icon } from '@/ui';\n\nimport { useUxm } from '../lib/context';\nimport { usePreviewShell } from '../lib/preview-shell';\nimport { getComponentDef } from '../lib/registry';\n\nimport { PreviewModal } from './preview-modal';\n\nimport type { PreviewProps } from '../lib/types';\nimport type { ReactNode } from 'react';\n\n\ntype PreviewComponent = React.ComponentType<PreviewProps>;\n\n/**\n * Text-entry surfaces (typeable inputs + textarea + contenteditable) where\n * `onInput` / React's mapped `onChange` fires per keystroke. Capturing those\n * events into the UXM event log triggers a context re-render on every\n * character, which races the controlled-input flow and silently drops\n * typed values mid-keystroke (Chrome / Safari / Firefox alike — repro'd\n * by typing into TextInput, PasswordInput, PhoneInput, etc. in the\n * canvas while the side-panel inputs work fine because they aren't\n * wrapped in the capture handlers). The fix: skip these surfaces in\n * the high-frequency capture handlers and rely on `onBlur` to log the\n * committed value once the user leaves the field.\n */\nfunction isHighFrequencyTextEntry(el: HTMLElement | null): boolean {\n if (!el) return false;\n if (el.tagName === 'TEXTAREA') return true;\n if ((el as HTMLElement).isContentEditable) return true;\n if (el.tagName === 'INPUT') {\n const type = (el as HTMLInputElement).type;\n return (\n type === 'text' ||\n type === 'tel' ||\n type === 'email' ||\n type === 'password' ||\n type === 'url' ||\n type === 'search' ||\n type === 'number'\n );\n }\n return false;\n}\n\nexport const previewMap: Record<string, PreviewComponent> = {\n 'app-sidebar': AppSidebarPreview,\n 'app-top-bar': AppTopBarPreview,\n 'button-primary': ButtonPreview,\n 'button-secondary': ButtonPreview,\n 'button-tertiary': ButtonPreview,\n 'button-ghost': ButtonPreview,\n 'button-danger': ButtonPreview,\n 'button-icon': ButtonPreview,\n 'button-with-icon': ButtonWithIconPreview,\n 'input-text': InputPreview,\n 'input-with-icon': InputWithIconPreview,\n 'color-input': ColorInputPreview,\n textarea: TextareaPreview,\n 'file-upload': FileUploadPreview,\n 'select-dropdown': SelectPreview,\n checkbox: CheckboxPreview,\n 'toggle-switch': TogglePreview,\n 'radio-group': RadioGroupPreview,\n chip: ChipPreview,\n 'code-editor': CodeEditorPreview,\n tag: TagPreview,\n card: CardPreview,\n avatar: AvatarPreview,\n 'empty-state': EmptyStatePreview,\n banner: BannerPreview,\n 'bulk-action-bar': BulkActionBarPreview,\n toast: ToastPreview,\n tooltip: TooltipPreview,\n 'form-login': FormPreview,\n 'form-contact': FormPreview,\n 'pill-select': PillSelectPreview,\n 'inline-filter': InlineFilterPreview,\n 'content-tooltip': ContentTooltipPreview,\n 'form-multirow': MultirowFormPreview,\n 'data-table': DataTablePreview,\n 'button-group': ButtonGroupPreview,\n 'stat-card': StatCardPreview,\n 'type-overview-card': TypeOverviewCardPreview,\n 'page-shell': PageShellPreview,\n 'sidebar-nav-item': SidebarNavItemPreview,\n 'sidebar-nav-trigger': SidebarNavTriggerPreview,\n 'explorer-list-item': ExplorerListItemPreview,\n 'explorer-section': ExplorerSectionPreview,\n 'inline-action': InlineActionPreview,\n 'number-stepper': NumberStepperPreview,\n 'number-input': NumberInputPreview,\n 'currency-input': CurrencyInputPreview,\n 'search-dropdown': SearchDropdownPreview,\n listbox: ListboxPreview,\n menu: MenuPreview,\n 'editable-cell': EditableCellPreview,\n 'section-header': SectionHeaderPreview,\n slider: SliderPreview,\n 'error-page': ErrorPagePreview,\n 'login-page': LoginPagePreview,\n loader: LoaderPreview,\n 'progress-bar': ProgressBarPreview,\n 'timeline-entry': TimelineEntryPreview,\n 'segment-card': SegmentCardPreview,\n 'segment-row': SegmentRowPreview,\n 'component-row': ComponentRowPreview,\n 'option-list': OptionListPreview,\n 'config-segment-item': ConfigSegmentItemPreview,\n 'config-component-row': ConfigComponentRowPreview,\n 'icon-tile': IconTilePreview,\n 'meta-row': MetaRowPreview,\n icon: IconPreview,\n 'icon-button': IconButtonPreview,\n 'detail-section': DetailSectionPreview,\n 'back-link': BackLinkPreview,\n badge: BadgePreview,\n thumbnail: ThumbnailPreview,\n 'date-input': DateInputPreview,\n 'password-input': PasswordInputPreview,\n 'phone-input': PhoneInputPreview,\n 'time-input': TimeInputPreview,\n calendar: CalendarPreview,\n disclosure: DisclosurePreview,\n 'link': LinkPreview,\n 'breadcrumb': BreadcrumbPreview,\n 'property-field': PropertyFieldPreview,\n 'property-grid': PropertyGridPreview,\n 'form-field': FormFieldPreview,\n 'list-item': ListItemPreview,\n 'side-flexpane': SideFlexpanePreview,\n 'page-header': PageHeaderPreview,\n 'divider': DividerPreview,\n 'filter-tabs': FilterTabsPreview,\n 'view-switcher': ViewSwitcherPreview,\n 'tabs': TabsPreview,\n 'tabs-underline': TabsUnderlinePreview,\n 'brand-settings': BrandSettingsPreview,\n 'lifecycle-node-card': LifecycleNodeCardPreview,\n 'lifecycle-terminal': LifecycleTerminalPreview,\n 'lifecycle-edge-label': LifecycleEdgeLabelPreview,\n 'lifecycle-plus-button': LifecyclePlusButtonPreview,\n 'lifecycle-zoom-control': LifecycleZoomControlPreview,\n 'lifecycle-minimap': LifecycleMinimapPreview,\n 'lifecycle-group-box': LifecycleGroupBoxPreview,\n 'lifecycle-drop-slot': LifecycleDropSlotPreview,\n 'lifecycle-action-row': LifecycleActionRowPreview,\n modal: ModalPreview,\n 'lifecycle-connector': LifecycleConnectorPreview,\n 'lifecycle-connector-knobs': LifecycleConnectorKnobsPreview,\n 'responsive-grid': ResponsiveGridPreview,\n stack: StackPreview,\n cluster: ClusterPreview,\n};\n\nexport function Canvas({\n embed = false,\n headerActions,\n}: {\n embed?: boolean;\n /** Optional host-provided actions rendered at the end of the top-bar\n cluster, right after the Preview & Publish button (e.g. a user avatar). */\n headerActions?: ReactNode;\n}) {\n const [previewOpen, setPreviewOpen] = useState(false);\n const { selectedId, getOverrides, resetOverrides, getCurrentVariants, pushEvent, capabilities, theme, setTheme } = useUxm();\n const shell = usePreviewShell();\n const def = getComponentDef(selectedId);\n const overrides = getOverrides(selectedId);\n const currentVariants = getCurrentVariants();\n\n const resolved = useMemo(() => {\n if (!def) return { styles: {}, variants: {} };\n const styles: Record<string, string | number | boolean> = {};\n for (const prop of def.styleProperties) {\n styles[prop.key] = overrides[prop.key] ?? prop.defaultValue;\n }\n // Variants read from ephemeral session state, NOT from overrides.\n // Variant selections decide which knobs are visible in the panel —\n // they don't persist and never get saved to components.css/json.\n const variants: Record<string, string> = {};\n for (const v of def.layoutVariants) {\n variants[v.key] = (currentVariants[v.key] as string | undefined) ?? v.defaultValue;\n }\n return { styles, variants };\n }, [def, overrides, currentVariants]);\n\n if (!def) return null;\n\n const Preview = previewMap[def.id];\n const hasOverrides = Object.keys(overrides).length > 0;\n\n return (\n <div className=\"flex h-full flex-col bg-card\">\n {/* Toolbar — uses container queries so the layout adapts to the\n canvas's actual width, not the viewport. The canvas can be\n much narrower than the viewport when the sidebar + properties\n pane are open; viewport breakpoints would respond to the\n wrong dimension. Three steps:\n ≥640px full (name + description + labelled buttons)\n 480-640 hide description, keep labels\n <480px icon-only secondary buttons; primary CTA stays\n labelled (Preview & Publish is moment-of-truth). */}\n <div className=\"@container flex items-center justify-between gap-3 border-b border-border px-6 py-4\">\n {/* min-w-0 enables `truncate` on the children — without it the\n flex item ignores the constraint and pushes the actions\n cluster off-screen. */}\n <div className=\"min-w-0 flex-1\">\n <h2 className=\"text-[15px] font-semibold text-text truncate\">{def.name}</h2>\n <p className=\"text-xs text-text-muted mt-0.5 hidden @[640px]:block truncate\">\n {def.description}\n </p>\n </div>\n {/* flex-shrink-0 keeps the actions cluster from wrapping; the\n label spans inside the secondary buttons hide first when\n space gets tight. */}\n <div className=\"flex items-center gap-2 flex-shrink-0\">\n {hasOverrides && (\n <ButtonGhost onClick={() => resetOverrides(selectedId)} title=\"Reset overrides\">\n <Icon glyph=\"refresh\" size={14} />\n <span className=\"hidden @[480px]:inline\">Reset</span>\n </ButtonGhost>\n )}\n {/* Light/dark toggle — only in the standalone portal (the studio\n owns the theme here; ThemeSync mirrors it onto data-theme). An\n embedded host renders its own theme control. */}\n {!embed && (\n <IconButton\n onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}\n aria-label={theme === 'dark' ? 'Switch to light theme' : 'Switch to dark theme'}\n title={theme === 'dark' ? 'Switch to light theme' : 'Switch to dark theme'}\n >\n <Icon glyph={theme === 'dark' ? 'sun' : 'moon'} size={16} />\n </IconButton>\n )}\n <ButtonPrimary onClick={() => setPreviewOpen(true)}>\n <Icon glyph=\"eye\" size={14} />\n {capabilities.persist ? 'Preview & Publish' : 'Preview'}\n </ButtonPrimary>\n {headerActions}\n </div>\n </div>\n\n {/* Preview area with optional dot grid */}\n <div\n className=\"flex-1 overflow-auto p-12\"\n style={def.canvasBackground === false ? undefined : {\n backgroundImage: 'radial-gradient(circle, var(--color-canvas-dot) 1px, transparent 1px)',\n backgroundSize: '20px 20px',\n }}\n >\n <div className={def.canvasFill ? 'min-h-full' : 'min-h-full flex items-center justify-center'}>\n {Preview ? (\n // Wrap the preview in a capture-phase event listener so any\n // native event the rendered atom fires gets logged to the\n // Events tab. Capture (rather than bubble) sees the event\n // before the atom's own handler — so we log first, the atom\n // behaves second. We don't `preventDefault`, so the rendered\n // component still works normally.\n <div\n onClickCapture={(e) =>\n pushEvent({\n name: 'onClick',\n target: (e.target as HTMLElement).tagName.toLowerCase(),\n payload: JSON.stringify({ x: e.clientX, y: e.clientY, button: e.button }),\n })\n }\n onChangeCapture={(e) => {\n const t = e.target as HTMLInputElement;\n // Skip text-entry surfaces here too — React maps onChange\n // to the native `input` event for text inputs / textareas /\n // contenteditable, so this capture would fire on EVERY\n // keystroke. Combined with onInputCapture below, that's\n // two `setEventLog` calls per character, each triggering\n // a context re-render that races the controlled-input\n // flow and eats typed values mid-keystroke (focus is fine,\n // but the value never lands). The final committed value\n // is captured via onBlurCapture below instead.\n if (isHighFrequencyTextEntry(t)) return;\n pushEvent({\n name: 'onChange',\n target: t.tagName.toLowerCase(),\n payload: JSON.stringify({\n value: t.value,\n checked: t.type === 'checkbox' ? t.checked : undefined,\n }),\n });\n }}\n onInputCapture={(e) => {\n const t = e.target as HTMLInputElement;\n // Skip the input types where `input` is either redundant\n // or pathologically high-frequency:\n // - checkbox/radio fire `change` AND `input` for a single\n // toggle — the `change` is the meaningful one.\n // - range fires `input` on every drag tick (30-60Hz).\n // - text / tel / email / password / url / search / number\n // inputs and <textarea> fire `input` per keystroke —\n // same hazard as range, but worse because text fields\n // are controlled and the cascading re-render replaces\n // the inner DOM (or interferes with React's value\n // reconciliation) and drops typed characters. The blur\n // handler logs the final committed value instead.\n // Each captured event pushes to a context-managed log\n // that triggers a re-render of the UXM shell. Slow\n // renders during this loop visibly stutter range thumbs\n // AND silently eat keystrokes for text fields.\n if (t.type === 'checkbox' || t.type === 'radio' || t.type === 'range') return;\n if (isHighFrequencyTextEntry(t)) return;\n pushEvent({\n name: 'onInput',\n target: t.tagName.toLowerCase(),\n payload: JSON.stringify({ value: t.value }),\n });\n }}\n onFocusCapture={(e) =>\n pushEvent({\n name: 'onFocus',\n target: (e.target as HTMLElement).tagName.toLowerCase(),\n payload: JSON.stringify({}),\n })\n }\n onBlurCapture={(e) => {\n const t = e.target as HTMLElement;\n // For text-entry surfaces we suppressed the per-keystroke\n // onChange / onInput log entries (those caused mid-typing\n // re-render races that dropped characters). Include the\n // committed value here so designers can still see what\n // landed in the field once the user leaves it.\n const payload: Record<string, unknown> = {};\n if (isHighFrequencyTextEntry(t)) {\n payload.value = (t as HTMLInputElement | HTMLTextAreaElement).value;\n }\n pushEvent({\n name: 'onBlur',\n target: t.tagName.toLowerCase(),\n payload: JSON.stringify(payload),\n });\n }}\n onSubmitCapture={(e) => {\n pushEvent({\n name: 'onSubmit',\n target: (e.target as HTMLElement).tagName.toLowerCase(),\n payload: JSON.stringify({}),\n });\n // Forms in the preview shouldn't navigate — they're not\n // backed by anything. The atoms themselves don't always\n // remember to preventDefault, so we do it here.\n e.preventDefault();\n }}\n onKeyDownCapture={(e) => {\n // Log only \"meaningful\" keystrokes — Enter, Escape, Space,\n // and arrow keys. Logging every keystroke during typing\n // would drown the log; onInput already covers value changes.\n const meaningful = ['Enter', 'Escape', ' ', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Tab'];\n if (!meaningful.includes(e.key)) return;\n pushEvent({\n name: 'onKeyDown',\n target: (e.target as HTMLElement).tagName.toLowerCase(),\n payload: JSON.stringify({ key: e.key }),\n });\n }}\n >\n <Preview styles={resolved.styles} variants={resolved.variants} componentId={def.id} shell={shell} />\n </div>\n ) : (\n <p className=\"text-sm text-text-muted\">No preview available.</p>\n )}\n </div>\n </div>\n\n {previewOpen && <PreviewModal onClose={() => setPreviewOpen(false)} />}\n </div>\n );\n}\n"],"mappings":"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","names":["import_ui"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/studio/shell/canvas.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\n\n\nimport {\n BannerPreview,\n BulkActionBarPreview,\n AppSidebarPreview,\n AppTopBarPreview,\n AvatarPreview,\n BackLinkPreview,\n BadgePreview,\n BrandSettingsPreview,\n BreadcrumbPreview,\n ButtonGroupPreview,\n ButtonPreview,\n ButtonWithIconPreview,\n CalendarPreview,\n CardPreview,\n CheckboxPreview,\n ChipPreview,\n ClusterPreview,\n CodeEditorPreview,\n ColorInputPreview,\n ComponentRowPreview,\n ConfigComponentRowPreview,\n ConfigSegmentItemPreview,\n ContentTooltipPreview,\n CurrencyInputPreview,\n DataTablePreview,\n DateInputPreview,\n DetailSectionPreview,\n DisclosurePreview,\n DividerPreview,\n EditableCellPreview,\n EmptyStatePreview,\n ErrorPagePreview,\n ExplorerListItemPreview,\n ExplorerSectionPreview,\n FileUploadPreview,\n FilterTabsPreview,\n FormFieldPreview,\n FormPreview,\n IconButtonPreview,\n IconPreview,\n IconTilePreview,\n InlineActionPreview,\n InlineFilterPreview,\n InputPreview,\n InputWithIconPreview,\n LanguageSwitcherPreview,\n LifecycleActionRowPreview,\n LifecycleConnectorKnobsPreview,\n LifecycleConnectorPreview,\n LifecycleDropSlotPreview,\n LifecycleEdgeLabelPreview,\n LifecycleGroupBoxPreview,\n LifecycleMinimapPreview,\n LifecycleNodeCardPreview,\n LifecyclePlusButtonPreview,\n LifecycleTerminalPreview,\n LifecycleZoomControlPreview,\n LinkPreview,\n ListItemPreview,\n ListboxPreview,\n LoaderPreview,\n LoginPagePreview,\n MenuPreview,\n MetaRowPreview,\n ModalPreview,\n MultirowFormPreview,\n NumberStepperPreview,\n NumberInputPreview,\n OptionListPreview,\n PageHeaderPreview,\n PageShellPreview,\n PasswordInputPreview,\n PhoneInputPreview,\n PillSelectPreview,\n ProgressBarPreview,\n PropertyFieldPreview,\n PropertyGridPreview,\n RadioGroupPreview,\n ResponsiveGridPreview,\n SearchDropdownPreview,\n SectionHeaderPreview,\n SegmentCardPreview,\n SegmentRowPreview,\n SelectPreview,\n SideFlexpanePreview,\n SidebarNavItemPreview,\n SidebarNavTriggerPreview,\n SliderPreview,\n StackPreview,\n StatCardPreview,\n TabsPreview,\n TabsUnderlinePreview,\n TagPreview,\n TextareaPreview,\n ThumbnailPreview,\n TimeInputPreview,\n TimelineEntryPreview,\n ToastPreview,\n TogglePreview,\n TooltipPreview,\n TypeOverviewCardPreview,\n ViewSwitcherPreview,\n} from '@/previews';\nimport { ButtonGhost, ButtonPrimary, IconButton } from '@/ui';\nimport { Icon } from '@/ui';\n\nimport { useUxm } from '../lib/context';\nimport { usePreviewShell } from '../lib/preview-shell';\nimport { getComponentDef } from '../lib/registry';\n\nimport { PreviewModal } from './preview-modal';\n\nimport type { PreviewProps } from '../lib/types';\nimport type { ReactNode } from 'react';\n\n\ntype PreviewComponent = React.ComponentType<PreviewProps>;\n\n/**\n * Text-entry surfaces (typeable inputs + textarea + contenteditable) where\n * `onInput` / React's mapped `onChange` fires per keystroke. Capturing those\n * events into the UXM event log triggers a context re-render on every\n * character, which races the controlled-input flow and silently drops\n * typed values mid-keystroke (Chrome / Safari / Firefox alike — repro'd\n * by typing into TextInput, PasswordInput, PhoneInput, etc. in the\n * canvas while the side-panel inputs work fine because they aren't\n * wrapped in the capture handlers). The fix: skip these surfaces in\n * the high-frequency capture handlers and rely on `onBlur` to log the\n * committed value once the user leaves the field.\n */\nfunction isHighFrequencyTextEntry(el: HTMLElement | null): boolean {\n if (!el) return false;\n if (el.tagName === 'TEXTAREA') return true;\n if ((el as HTMLElement).isContentEditable) return true;\n if (el.tagName === 'INPUT') {\n const type = (el as HTMLInputElement).type;\n return (\n type === 'text' ||\n type === 'tel' ||\n type === 'email' ||\n type === 'password' ||\n type === 'url' ||\n type === 'search' ||\n type === 'number'\n );\n }\n return false;\n}\n\nexport const previewMap: Record<string, PreviewComponent> = {\n 'app-sidebar': AppSidebarPreview,\n 'app-top-bar': AppTopBarPreview,\n 'button-primary': ButtonPreview,\n 'button-secondary': ButtonPreview,\n 'button-tertiary': ButtonPreview,\n 'button-ghost': ButtonPreview,\n 'button-danger': ButtonPreview,\n 'button-icon': ButtonPreview,\n 'button-with-icon': ButtonWithIconPreview,\n 'input-text': InputPreview,\n 'input-with-icon': InputWithIconPreview,\n 'color-input': ColorInputPreview,\n textarea: TextareaPreview,\n 'file-upload': FileUploadPreview,\n 'select-dropdown': SelectPreview,\n checkbox: CheckboxPreview,\n 'toggle-switch': TogglePreview,\n 'radio-group': RadioGroupPreview,\n chip: ChipPreview,\n 'code-editor': CodeEditorPreview,\n tag: TagPreview,\n card: CardPreview,\n avatar: AvatarPreview,\n 'empty-state': EmptyStatePreview,\n banner: BannerPreview,\n 'bulk-action-bar': BulkActionBarPreview,\n toast: ToastPreview,\n tooltip: TooltipPreview,\n 'form-login': FormPreview,\n 'form-contact': FormPreview,\n 'pill-select': PillSelectPreview,\n 'inline-filter': InlineFilterPreview,\n 'content-tooltip': ContentTooltipPreview,\n 'form-multirow': MultirowFormPreview,\n 'data-table': DataTablePreview,\n 'button-group': ButtonGroupPreview,\n 'stat-card': StatCardPreview,\n 'type-overview-card': TypeOverviewCardPreview,\n 'page-shell': PageShellPreview,\n 'sidebar-nav-item': SidebarNavItemPreview,\n 'sidebar-nav-trigger': SidebarNavTriggerPreview,\n 'explorer-list-item': ExplorerListItemPreview,\n 'explorer-section': ExplorerSectionPreview,\n 'inline-action': InlineActionPreview,\n 'number-stepper': NumberStepperPreview,\n 'number-input': NumberInputPreview,\n 'currency-input': CurrencyInputPreview,\n 'search-dropdown': SearchDropdownPreview,\n 'language-switcher': LanguageSwitcherPreview,\n listbox: ListboxPreview,\n menu: MenuPreview,\n 'editable-cell': EditableCellPreview,\n 'section-header': SectionHeaderPreview,\n slider: SliderPreview,\n 'error-page': ErrorPagePreview,\n 'login-page': LoginPagePreview,\n loader: LoaderPreview,\n 'progress-bar': ProgressBarPreview,\n 'timeline-entry': TimelineEntryPreview,\n 'segment-card': SegmentCardPreview,\n 'segment-row': SegmentRowPreview,\n 'component-row': ComponentRowPreview,\n 'option-list': OptionListPreview,\n 'config-segment-item': ConfigSegmentItemPreview,\n 'config-component-row': ConfigComponentRowPreview,\n 'icon-tile': IconTilePreview,\n 'meta-row': MetaRowPreview,\n icon: IconPreview,\n 'icon-button': IconButtonPreview,\n 'detail-section': DetailSectionPreview,\n 'back-link': BackLinkPreview,\n badge: BadgePreview,\n thumbnail: ThumbnailPreview,\n 'date-input': DateInputPreview,\n 'password-input': PasswordInputPreview,\n 'phone-input': PhoneInputPreview,\n 'time-input': TimeInputPreview,\n calendar: CalendarPreview,\n disclosure: DisclosurePreview,\n 'link': LinkPreview,\n 'breadcrumb': BreadcrumbPreview,\n 'property-field': PropertyFieldPreview,\n 'property-grid': PropertyGridPreview,\n 'form-field': FormFieldPreview,\n 'list-item': ListItemPreview,\n 'side-flexpane': SideFlexpanePreview,\n 'page-header': PageHeaderPreview,\n 'divider': DividerPreview,\n 'filter-tabs': FilterTabsPreview,\n 'view-switcher': ViewSwitcherPreview,\n 'tabs': TabsPreview,\n 'tabs-underline': TabsUnderlinePreview,\n 'brand-settings': BrandSettingsPreview,\n 'lifecycle-node-card': LifecycleNodeCardPreview,\n 'lifecycle-terminal': LifecycleTerminalPreview,\n 'lifecycle-edge-label': LifecycleEdgeLabelPreview,\n 'lifecycle-plus-button': LifecyclePlusButtonPreview,\n 'lifecycle-zoom-control': LifecycleZoomControlPreview,\n 'lifecycle-minimap': LifecycleMinimapPreview,\n 'lifecycle-group-box': LifecycleGroupBoxPreview,\n 'lifecycle-drop-slot': LifecycleDropSlotPreview,\n 'lifecycle-action-row': LifecycleActionRowPreview,\n modal: ModalPreview,\n 'lifecycle-connector': LifecycleConnectorPreview,\n 'lifecycle-connector-knobs': LifecycleConnectorKnobsPreview,\n 'responsive-grid': ResponsiveGridPreview,\n stack: StackPreview,\n cluster: ClusterPreview,\n};\n\nexport function Canvas({\n embed = false,\n headerActions,\n}: {\n embed?: boolean;\n /** Optional host-provided actions rendered at the end of the top-bar\n cluster, right after the Preview & Publish button (e.g. a user avatar). */\n headerActions?: ReactNode;\n}) {\n const [previewOpen, setPreviewOpen] = useState(false);\n const { selectedId, getOverrides, resetOverrides, getCurrentVariants, pushEvent, capabilities, theme, setTheme } = useUxm();\n const shell = usePreviewShell();\n const def = getComponentDef(selectedId);\n const overrides = getOverrides(selectedId);\n const currentVariants = getCurrentVariants();\n\n const resolved = useMemo(() => {\n if (!def) return { styles: {}, variants: {} };\n const styles: Record<string, string | number | boolean> = {};\n for (const prop of def.styleProperties) {\n styles[prop.key] = overrides[prop.key] ?? prop.defaultValue;\n }\n // Variants read from ephemeral session state, NOT from overrides.\n // Variant selections decide which knobs are visible in the panel —\n // they don't persist and never get saved to components.css/json.\n const variants: Record<string, string> = {};\n for (const v of def.layoutVariants) {\n variants[v.key] = (currentVariants[v.key] as string | undefined) ?? v.defaultValue;\n }\n return { styles, variants };\n }, [def, overrides, currentVariants]);\n\n if (!def) return null;\n\n const Preview = previewMap[def.id];\n const hasOverrides = Object.keys(overrides).length > 0;\n\n return (\n <div className=\"flex h-full flex-col bg-card\">\n {/* Toolbar — uses container queries so the layout adapts to the\n canvas's actual width, not the viewport. The canvas can be\n much narrower than the viewport when the sidebar + properties\n pane are open; viewport breakpoints would respond to the\n wrong dimension. Three steps:\n ≥640px full (name + description + labelled buttons)\n 480-640 hide description, keep labels\n <480px icon-only secondary buttons; primary CTA stays\n labelled (Preview & Publish is moment-of-truth). */}\n <div className=\"@container flex items-center justify-between gap-3 border-b border-border px-6 py-4\">\n {/* min-w-0 enables `truncate` on the children — without it the\n flex item ignores the constraint and pushes the actions\n cluster off-screen. */}\n <div className=\"min-w-0 flex-1\">\n <h2 className=\"text-[15px] font-semibold text-text truncate\">{def.name}</h2>\n <p className=\"text-xs text-text-muted mt-0.5 hidden @[640px]:block truncate\">\n {def.description}\n </p>\n </div>\n {/* flex-shrink-0 keeps the actions cluster from wrapping; the\n label spans inside the secondary buttons hide first when\n space gets tight. */}\n <div className=\"flex items-center gap-2 flex-shrink-0\">\n {hasOverrides && (\n <ButtonGhost onClick={() => resetOverrides(selectedId)} title=\"Reset overrides\">\n <Icon glyph=\"refresh\" size={14} />\n <span className=\"hidden @[480px]:inline\">Reset</span>\n </ButtonGhost>\n )}\n {/* Light/dark toggle — only in the standalone portal (the studio\n owns the theme here; ThemeSync mirrors it onto data-theme). An\n embedded host renders its own theme control. */}\n {!embed && (\n <IconButton\n onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}\n aria-label={theme === 'dark' ? 'Switch to light theme' : 'Switch to dark theme'}\n title={theme === 'dark' ? 'Switch to light theme' : 'Switch to dark theme'}\n >\n <Icon glyph={theme === 'dark' ? 'sun' : 'moon'} size={16} />\n </IconButton>\n )}\n <ButtonPrimary onClick={() => setPreviewOpen(true)}>\n <Icon glyph=\"eye\" size={14} />\n {capabilities.persist ? 'Preview & Publish' : 'Preview'}\n </ButtonPrimary>\n {headerActions}\n </div>\n </div>\n\n {/* Preview area with optional dot grid */}\n <div\n className=\"flex-1 overflow-auto p-12\"\n style={def.canvasBackground === false ? undefined : {\n backgroundImage: 'radial-gradient(circle, var(--color-canvas-dot) 1px, transparent 1px)',\n backgroundSize: '20px 20px',\n }}\n >\n <div className={def.canvasFill ? 'min-h-full' : 'min-h-full flex items-center justify-center'}>\n {Preview ? (\n // Wrap the preview in a capture-phase event listener so any\n // native event the rendered atom fires gets logged to the\n // Events tab. Capture (rather than bubble) sees the event\n // before the atom's own handler — so we log first, the atom\n // behaves second. We don't `preventDefault`, so the rendered\n // component still works normally.\n <div\n onClickCapture={(e) =>\n pushEvent({\n name: 'onClick',\n target: (e.target as HTMLElement).tagName.toLowerCase(),\n payload: JSON.stringify({ x: e.clientX, y: e.clientY, button: e.button }),\n })\n }\n onChangeCapture={(e) => {\n const t = e.target as HTMLInputElement;\n // Skip text-entry surfaces here too — React maps onChange\n // to the native `input` event for text inputs / textareas /\n // contenteditable, so this capture would fire on EVERY\n // keystroke. Combined with onInputCapture below, that's\n // two `setEventLog` calls per character, each triggering\n // a context re-render that races the controlled-input\n // flow and eats typed values mid-keystroke (focus is fine,\n // but the value never lands). The final committed value\n // is captured via onBlurCapture below instead.\n if (isHighFrequencyTextEntry(t)) return;\n pushEvent({\n name: 'onChange',\n target: t.tagName.toLowerCase(),\n payload: JSON.stringify({\n value: t.value,\n checked: t.type === 'checkbox' ? t.checked : undefined,\n }),\n });\n }}\n onInputCapture={(e) => {\n const t = e.target as HTMLInputElement;\n // Skip the input types where `input` is either redundant\n // or pathologically high-frequency:\n // - checkbox/radio fire `change` AND `input` for a single\n // toggle — the `change` is the meaningful one.\n // - range fires `input` on every drag tick (30-60Hz).\n // - text / tel / email / password / url / search / number\n // inputs and <textarea> fire `input` per keystroke —\n // same hazard as range, but worse because text fields\n // are controlled and the cascading re-render replaces\n // the inner DOM (or interferes with React's value\n // reconciliation) and drops typed characters. The blur\n // handler logs the final committed value instead.\n // Each captured event pushes to a context-managed log\n // that triggers a re-render of the UXM shell. Slow\n // renders during this loop visibly stutter range thumbs\n // AND silently eat keystrokes for text fields.\n if (t.type === 'checkbox' || t.type === 'radio' || t.type === 'range') return;\n if (isHighFrequencyTextEntry(t)) return;\n pushEvent({\n name: 'onInput',\n target: t.tagName.toLowerCase(),\n payload: JSON.stringify({ value: t.value }),\n });\n }}\n onFocusCapture={(e) =>\n pushEvent({\n name: 'onFocus',\n target: (e.target as HTMLElement).tagName.toLowerCase(),\n payload: JSON.stringify({}),\n })\n }\n onBlurCapture={(e) => {\n const t = e.target as HTMLElement;\n // For text-entry surfaces we suppressed the per-keystroke\n // onChange / onInput log entries (those caused mid-typing\n // re-render races that dropped characters). Include the\n // committed value here so designers can still see what\n // landed in the field once the user leaves it.\n const payload: Record<string, unknown> = {};\n if (isHighFrequencyTextEntry(t)) {\n payload.value = (t as HTMLInputElement | HTMLTextAreaElement).value;\n }\n pushEvent({\n name: 'onBlur',\n target: t.tagName.toLowerCase(),\n payload: JSON.stringify(payload),\n });\n }}\n onSubmitCapture={(e) => {\n pushEvent({\n name: 'onSubmit',\n target: (e.target as HTMLElement).tagName.toLowerCase(),\n payload: JSON.stringify({}),\n });\n // Forms in the preview shouldn't navigate — they're not\n // backed by anything. The atoms themselves don't always\n // remember to preventDefault, so we do it here.\n e.preventDefault();\n }}\n onKeyDownCapture={(e) => {\n // Log only \"meaningful\" keystrokes — Enter, Escape, Space,\n // and arrow keys. Logging every keystroke during typing\n // would drown the log; onInput already covers value changes.\n const meaningful = ['Enter', 'Escape', ' ', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Tab'];\n if (!meaningful.includes(e.key)) return;\n pushEvent({\n name: 'onKeyDown',\n target: (e.target as HTMLElement).tagName.toLowerCase(),\n payload: JSON.stringify({ key: e.key }),\n });\n }}\n >\n <Preview styles={resolved.styles} variants={resolved.variants} componentId={def.id} shell={shell} />\n </div>\n ) : (\n <p className=\"text-sm text-text-muted\">No preview available.</p>\n )}\n </div>\n </div>\n\n {previewOpen && <PreviewModal onClose={() => setPreviewOpen(false)} />}\n </div>\n );\n}\n"],"mappings":"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","names":["import_ui"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../../src/studio/shell/canvas.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../../src/studio/shell/canvas.tsx"],"names":[],"mappings":"AAoHA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,KAAK,gBAAgB,GAAG,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;AAiC1D,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CA6GvD,CAAC;AAEF,wBAAgB,MAAM,CAAC,EACrB,KAAa,EACb,aAAa,GACd,EAAE;IACD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;kFAC8E;IAC9E,aAAa,CAAC,EAAE,SAAS,CAAC;CAC3B,kDAkNA"}
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
InlineFilterPreview,
|
|
47
47
|
InputPreview,
|
|
48
48
|
InputWithIconPreview,
|
|
49
|
+
LanguageSwitcherPreview,
|
|
49
50
|
LifecycleActionRowPreview,
|
|
50
51
|
LifecycleConnectorKnobsPreview,
|
|
51
52
|
LifecycleConnectorPreview,
|
|
@@ -168,6 +169,7 @@ const previewMap = {
|
|
|
168
169
|
"number-input": NumberInputPreview,
|
|
169
170
|
"currency-input": CurrencyInputPreview,
|
|
170
171
|
"search-dropdown": SearchDropdownPreview,
|
|
172
|
+
"language-switcher": LanguageSwitcherPreview,
|
|
171
173
|
listbox: ListboxPreview,
|
|
172
174
|
menu: MenuPreview,
|
|
173
175
|
"editable-cell": EditableCellPreview,
|