@getvitops/generator 0.7.0 → 0.8.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 CHANGED
@@ -1,5 +1,67 @@
1
1
  # @getvitops/generator
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - **New: `<wc-theme-editor>`, a live theme editor you can ship with your site.**
8
+
9
+ Tune the whole design system in the browser — palette, semantic roles, type roles, spacing, layout,
10
+ pattern geometry, radii, shadows — with no rebuild. Edits are layered as `:root` custom-property
11
+ overrides, persist to localStorage, and export as CSS or as a `design-system.json` patch. It follows
12
+ your site's colour scheme and drives the same `data-theme` + storage key as `<color-scheme-toggle>`,
13
+ so the two no longer fight.
14
+
15
+ It ships as a **separate, opt-in bundle** (`@getvitops/core/editor`, ~13 kB, no Lit) and is never
16
+ registered in `elements.js`: a page that doesn't ask for it pays nothing.
17
+
18
+ ```js
19
+ // astro.config.mjs
20
+ getvitops({
21
+ css: { input: 'design-system.json', format: 'css', out: 'src/styles' },
22
+ editor: true,
23
+ });
24
+ ```
25
+
26
+ ```html
27
+ <!-- anywhere in your layout -->
28
+ <wc-theme-editor></wc-theme-editor>
29
+ ```
30
+
31
+ `editor: true` copies `editor.js` into `public/vitops/`, loads it from `<Head />`, and mirrors
32
+ `design-manifest.json` to `/vitops/design-manifest.json` (override with the `manifest` attribute).
33
+ Outside Astro, load the bundle yourself and point `manifest` at the file.
34
+
35
+ **Save straight back to your config, in dev.** `@getvitops/vite` now serves a dev-only
36
+ `/__vitops/design-system` endpoint: the editor POSTs its patch, the plugin deep-merges it into your
37
+ `design-system.json`, validates the _merged_ result, writes it back preserving the file's formatting,
38
+ then regenerates and reloads. The endpoint exists only under `vite dev` — on a static deploy the
39
+ editor detects its absence and hides the button, while everything else still works.
40
+
41
+ **Added:** `colors.roleTokens` in `design-manifest.json` — the functional token set (bg / border /
42
+ solid / on-solid / text / emphasis stops) precomputed per hue, in `default` and `surface` variants for
43
+ both appearances. Re-pointing a role at another hue needs these: `solid` is chosen by scanning the hue
44
+ and `on-solid` is a computed contrast value, so neither is derivable by a browser client.
45
+
46
+ **Removed:** the dead `interaction` block from `design-manifest.json` — a hardcoded
47
+ `{duration, easing}` literal with no schema key, no reverse-index entry, and no corresponding CSS
48
+ variable. Nothing could have consumed it meaningfully. The real animation knobs are
49
+ `--animation-duration-*` / `--custom-ease-*`.
50
+
51
+ **Fixed:** a `[popover]` reset in `popover.css` was stripping the background, padding and border from
52
+ any pattern used as a popover. It is imported after `drawer.css`, so at equal specificity it beat
53
+ `.drawer` — and `dialog` (0-0-1) too — leaving a `.drawer[popover]` transparent and unpadded despite
54
+ drawer.css documenting popover as supported. The reset now sits in `:where()` at zero specificity, so
55
+ it still overrides the UA stylesheet but any pattern class takes its surface back. Open/closed
56
+ behaviour is unchanged.
57
+
58
+ **Added:** `input[type="range"]` and `input[type="color"]` now have baseline styling in `forms.css`
59
+ (accent colour from `--ui-primary-solid`; the colour swatch picks up the control border and radius).
60
+
61
+ ### Patch Changes
62
+
63
+ - @getvitops/utils@0.8.0
64
+
3
65
  ## 0.7.0
4
66
 
5
67
  ### Patch Changes
@@ -8,6 +8,16 @@
8
8
  font-size: 100% !important;
9
9
  }
10
10
 
11
+ /* Drop the UA's 8px body margin. The framework owns page gutters via `.centered`
12
+ (--gutter), so the UA default just offsets every full-bleed surface — sticky
13
+ headers and `bg-*` bands end up inset by 8px with a sliver of canvas showing
14
+ around them. This is the only UA reset the framework makes: it deliberately
15
+ does NOT ship a general reset (no global box-sizing change), because that
16
+ would silently reflow existing consumer layouts. */
17
+ body {
18
+ margin: 0;
19
+ }
20
+
11
21
  @media (prefers-reduced-motion: no-preference) {
12
22
  html {
13
23
  scrollbar-gutter: stable;
@@ -56,3 +56,4 @@
56
56
  @import './patterns/nav.css';
57
57
  @import './patterns/carousel.css';
58
58
  @import './patterns/copy.css';
59
+ @import './patterns/theme-editor.css';
@@ -90,6 +90,37 @@ fieldset.fieldset,
90
90
  background: var(--surface-bg);
91
91
  }
92
92
 
93
+ /* ── Range + colour controls ───────────────────────────────────────────────── */
94
+ /* `accent-color` is the whole job for range: it themes the track fill and thumb
95
+ * natively, in both appearances, with no pseudo-element rewriting. The colour
96
+ * swatch only needs its chrome removed so the well fills the control box. */
97
+ input[type='range'] {
98
+ accent-color: var(--range-accent, var(--ui-primary-solid));
99
+ inline-size: 100%;
100
+ min-inline-size: 0;
101
+ }
102
+
103
+ input[type='color'] {
104
+ --_br: var(--br-input, var(--br-control, var(--br-default)));
105
+
106
+ inline-size: var(--color-swatch-size, 2rem);
107
+ block-size: var(--color-swatch-size, 2rem);
108
+ padding: 0;
109
+ border: var(--b-input, var(--b-control, var(--b-default)));
110
+ border-radius: var(--_br);
111
+ background: none;
112
+ cursor: pointer;
113
+
114
+ &::-webkit-color-swatch-wrapper {
115
+ padding: 2px;
116
+ }
117
+ &::-webkit-color-swatch,
118
+ &::-moz-color-swatch {
119
+ border: none;
120
+ border-radius: calc(var(--_br) - 2px);
121
+ }
122
+ }
123
+
93
124
  /* ── Input group — input flanked by icons/addons ───────────────────────────── */
94
125
  .input-group {
95
126
  --_br: var(--br-input-group, var(--br-control, var(--br-default)));
@@ -4,14 +4,31 @@
4
4
  */
5
5
 
6
6
  /* ── Popover — native Popover API reset + anchored position variants ───────── */
7
- [popover] {
7
+
8
+ /**
9
+ * The UA gives `[popover]` a padding, border and canvas background; a bare
10
+ * popover wants none of that. But this partial is imported *after* drawer.css /
11
+ * dialog.css, so at plain `[popover]` specificity (0-1-0) the reset also beat
12
+ * `.drawer` (0-1-0, earlier) and `dialog` (0-0-1) — silently stripping the
13
+ * surface off any pattern used as a popover, which is exactly what drawer.css
14
+ * documents itself as supporting.
15
+ *
16
+ * So the reset sits in `:where()` at zero specificity: it still overrides the UA
17
+ * stylesheet, and *any* explicit class takes it back. Same mechanism the `btn`
18
+ * pattern uses with `:where(button, .btn)`. Keep the visual reset here and the
19
+ * open/closed behaviour below — that must stay at real specificity so a
20
+ * component's own rules can't accidentally reveal a closed popover.
21
+ */
22
+ :where([popover]) {
8
23
  padding: 0;
9
24
  border: none;
10
25
  background: transparent;
11
26
  color: inherit;
12
27
  overflow: visible;
13
28
  inset: auto;
29
+ }
14
30
 
31
+ [popover] {
15
32
  &:popover-open {
16
33
  opacity: 1;
17
34
  }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Theme editor — chrome for `<wc-theme-editor>` (@getvitops/core/editor).
3
+ *
4
+ * Deliberately thin: the panel is a `.drawer.drawer--right` popover, its sections
5
+ * are `.details`, its controls come from `forms.css` and its buttons from the
6
+ * generated `btn`/`cta` patterns. What's left here is only what those don't cover
7
+ * — the launcher's fixed position, the label/control row, and the density the
8
+ * panel needs to fit a whole design system in a sidebar.
9
+ *
10
+ * This partial is imported by the bundle like any other, so a consumer who never
11
+ * loads the editor bundle still pays for it (~1KB) but sees nothing: every rule is
12
+ * scoped under `wc-theme-editor`, which only exists once the element is defined.
13
+ */
14
+
15
+ wc-theme-editor {
16
+ /* Density: the panel packs ~200 controls, so it runs a step down from body. */
17
+ --_fs: var(--text-xs, 0.78rem);
18
+
19
+ .ed-launch {
20
+ position: fixed;
21
+ inset-block-end: 1rem;
22
+ inset-inline-end: 1rem;
23
+ z-index: var(--z-tier-top, 100);
24
+ }
25
+
26
+ .ed-panel {
27
+ --drawer-max-inline-size: min(28rem, 100vw);
28
+
29
+ overflow-y: auto;
30
+ padding: 1rem;
31
+ font-size: var(--_fs);
32
+ }
33
+
34
+ /* Sections: the drawer supplies the surface, so these only need separation. */
35
+ .ed-section {
36
+ border-block-start: var(--b-default);
37
+ padding-block-start: 0.5rem;
38
+ }
39
+ .ed-section > summary {
40
+ padding-block: 0.35rem;
41
+ }
42
+ .ed-sub {
43
+ border: var(--b-default);
44
+ border-radius: var(--br-default);
45
+ padding: 0.4rem 0.6rem;
46
+ }
47
+
48
+ /* A control row: fixed-width var name, control takes the rest. */
49
+ .ed-row {
50
+ display: flex;
51
+ align-items: center;
52
+ gap: 0.5rem;
53
+ }
54
+ .ed-label {
55
+ flex: 0 0 8.5rem;
56
+ overflow: hidden;
57
+ font-family: var(--font-mono, monospace);
58
+ font-size: 0.9em;
59
+ color: var(--surface-text-x-muted);
60
+ text-overflow: ellipsis;
61
+ white-space: nowrap;
62
+ }
63
+ .ed-input {
64
+ flex: 1;
65
+ min-inline-size: 0;
66
+ padding: 0.3em 0.5em;
67
+ border: var(--b-default);
68
+ border-radius: var(--br-default);
69
+ background: var(--surface-bg);
70
+ color: inherit;
71
+ font: inherit;
72
+ }
73
+ .ed-mono {
74
+ font-family: var(--font-mono, monospace);
75
+ }
76
+ .ed-pair {
77
+ flex: 1;
78
+ display: flex;
79
+ align-items: center;
80
+ gap: 0.4rem;
81
+ min-inline-size: 0;
82
+ }
83
+ .ed-color {
84
+ flex: 0 0 auto;
85
+ --color-swatch-size: 1.8rem;
86
+ }
87
+ .ed-out {
88
+ flex: 0 0 4.5rem;
89
+ font-family: var(--font-mono, monospace);
90
+ font-size: 0.9em;
91
+ text-align: end;
92
+ }
93
+
94
+ /* Toolbar: a segmented light/dark pair plus actions. */
95
+ .ed-toolbar {
96
+ flex-wrap: wrap;
97
+ gap: 0.4rem;
98
+ position: sticky;
99
+ inset-block-start: 0;
100
+ z-index: 1;
101
+ padding-block: 0.5rem;
102
+ background: var(--surface-bg);
103
+ }
104
+ .ed-segwrap {
105
+ display: inline-flex;
106
+ }
107
+ .ed-seg.is-active {
108
+ background: var(--ui-primary-solid);
109
+ color: var(--ui-primary-on-solid);
110
+ }
111
+ .ed-danger {
112
+ color: var(--danger-text);
113
+ }
114
+ }
@@ -0,0 +1,2 @@
1
+ const e=`vitops:ds-overrides`,t=`/__vitops/design-system`,n=(e,t)=>t.startsWith(`stop-`)?`--color-${e}-${t.slice(5)}`:`--${e}-${t}`,r=(e,t)=>`--color-${e}-${t}`;var i=class extends HTMLElement{constructor(...e){super(...e),this.store={light:new Map,dark:new Map},this.roles=new Map,this.roleVars=new Set,this.syncers=new Set,this.scheme=`light`,this.canSave=!1}static{this.observedAttributes=[`manifest`]}connectedCallback(){this.boot()}async boot(){let e=this.getAttribute(`manifest`)??`/vitops/design-manifest.json`;try{let t=await fetch(e);if(!t.ok)throw Error(`manifest ${t.status}`);this.manifest=await t.json()}catch(t){console.warn(`[wc-theme-editor] manifest unavailable at ${e} — editor disabled`,t);return}this.styleEl=document.createElement(`style`),this.styleEl.id=`ds-overrides`,document.head.append(this.styleEl),this.hydrate(),this.render(),this.scheme=this.currentScheme(),new MutationObserver(()=>{let e=this.currentScheme();e!==this.scheme&&(this.scheme=e,this.syncers.forEach(e=>e()))}).observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]}),this.canSave=await this.probeSave(),this.build(this.manifest)}async probeSave(){try{let e=await fetch(t);return e.ok?(await e.json()).writable===!0:!1}catch{return!1}}block(e,t){return t.size?`${e} {\n${[...t].map(([e,t])=>` ${e}: ${t};`).join(`
2
+ `)}\n}\n`:``}serializeCSS(){return this.block(`:root`,this.store.light)+this.block(`:root[data-brx-theme="dark"], :root[data-theme="dark"]`,this.store.dark)}render(){this.styleEl&&(this.styleEl.textContent=this.serializeCSS())}persist(){try{localStorage.setItem(e,JSON.stringify({light:[...this.store.light],dark:[...this.store.dark],roles:[...this.roles]}))}catch{}}hydrate(){try{let t=localStorage.getItem(e);if(!t)return;let n=JSON.parse(t);this.store.light=new Map(n.light??[]),this.store.dark=new Map(n.dark??[]),this.roles=new Map(n.roles??[]);for(let[e,t]of this.roles)this.markRoleVars(e,t)}catch{}}setOverride(e,t,n){let r=this.store[n];t==null||t===``?r.delete(e):r.set(e,t),this.render(),this.persist()}effective(e,t,n){return this.store[t].has(e)?this.store[t].get(e):t===`dark`&&this.store.light.has(e)?this.store.light.get(e):n}reset(){this.store.light.clear(),this.store.dark.clear(),this.roles.clear(),this.roleVars.clear(),this.render(),this.persist(),this.syncers.forEach(e=>e())}currentScheme(){let e=document.documentElement;return e.dataset.theme===`dark`||e.getAttribute(`data-brx-theme`)===`dark`?`dark`:`light`}setScheme(e){this.scheme=e,document.documentElement.dataset.theme=e,document.documentElement.style.colorScheme=`${e} only`;try{localStorage.setItem(`vitops-color-scheme`,e)}catch{}this.syncers.forEach(e=>e())}roleTokenNames(e,t,r){let i=t===`surface`?`surface`:`default`,a=e.colors.roleTokens?.[r]?.[i];if(!a)return[];let o=[];for(let e of[`light`,`dark`])for(let[r,i]of Object.entries(a[e]))o.push([n(t,r),i,e]);return o}markRoleVars(e,t){if(this.manifest)for(let[n]of this.roleTokenNames(this.manifest,e,t))this.roleVars.add(n)}remapRole(e,t,n){let r=this.roleTokenNames(e,t,n);if(r.length){this.roles.set(t,n);for(let[e,t,n]of r)this.roleVars.add(e),this.store[n].set(e,t);this.render(),this.persist()}}deepSet(e,t,n){let r=t.split(`.`),i=e;for(let e=0;e<r.length-1;e++){let t=r[e];(typeof i[t]!=`object`||i[t]==null)&&(i[t]={}),i=i[t]}i[r[r.length-1]]=n}buildPatch(e){let t={},n=[];for(let[e,n]of this.roles)this.deepSet(t,`colors.roles.${e}`,n);for(let[r,i]of this.store.light){if(this.roleVars.has(r))continue;let a=e.reverseIndex[r];a?this.deepSet(t,a,i):n.push(r)}for(let e of this.store.dark.keys())this.roleVars.has(e)||n.push(`${e} (dark)`);return{patch:t,skipped:n}}el(e,t={},n=[]){let r=document.createElement(e),i=r;for(let[e,n]of Object.entries(t))n===!0?i.setAttribute(e,``):n!==!1&&i.setAttribute(e,String(n));for(let e of n)i.append(e);return r}row(e,t,n){return this.syncers.add(n),n(),this.el(`label`,{class:`ed-row`},[this.el(`span`,{class:`ed-label`,title:e},[e.replace(/^--/,``)]),t])}textInput(e,t,n=``){let r=this.el(`input`,{type:`text`,class:`ed-input`});return r.addEventListener(`input`,()=>this.setOverride(e,r.value.trim()||null,this.scheme)),this.row(e,r,()=>{r.value=this.store[this.scheme].get(e)??``,r.placeholder=n||t})}colorInput(e,t){let n=this.el(`input`,{type:`color`,class:`ed-color`}),r=this.el(`input`,{type:`text`,class:`ed-input ed-mono`}),i=t=>this.setOverride(e,t||null,`light`);n.addEventListener(`input`,()=>{r.value=n.value,i(n.value)}),r.addEventListener(`input`,()=>{/^#[0-9a-f]{6}$/i.test(r.value)&&(n.value=r.value),i(r.value.trim())});let a=this.el(`span`,{class:`ed-pair`},[n,r]);return this.row(e,a,()=>{let i=this.store.light.get(e)??t;r.value=i,/^#[0-9a-f]{6}$/i.test(i)&&(n.value=i)})}selectInput(e,t){let n=this.el(`select`,{class:`ed-input`});n.append(this.el(`option`,{value:``},[`— default —`]));for(let e of t)n.append(this.el(`option`,{value:e.value},[e.label]));return n.addEventListener(`change`,()=>this.setOverride(e,n.value||null,this.scheme)),this.row(e,n,()=>{n.value=this.store[this.scheme].get(e)??``})}remSlider(e,t){let n=parseFloat(t)||1,r=this.el(`input`,{type:`range`,class:`ed-range`,min:`0`,max:String(Math.max(4,Math.ceil(n*2))),step:`0.05`}),i=this.el(`output`,{class:`ed-out`});r.addEventListener(`input`,()=>{i.textContent=`${r.value}rem`,this.setOverride(e,`${r.value}rem`,this.scheme)});let a=this.el(`span`,{class:`ed-pair`},[r,i]);return this.row(e,a,()=>{r.value=String(parseFloat(this.effective(e,this.scheme,t))||n),i.textContent=this.store[this.scheme].get(e)??`auto`})}slider(e,t){let n=t.toValue??(e=>`${e}${t.unit??``}`),r=t.fromValue??(e=>Number.isNaN(parseFloat(e))?t.def:parseFloat(e)),i=this.el(`input`,{type:`range`,class:`ed-range`,min:String(t.min),max:String(t.max),step:String(t.step)}),a=this.el(`output`,{class:`ed-out`});i.addEventListener(`input`,()=>{let t=n(parseFloat(i.value));a.textContent=t,this.setOverride(e,t,this.scheme)});let o=this.el(`span`,{class:`ed-pair`},[i,a]);return this.row(e,o,()=>{let n=this.store[this.scheme].get(e);i.value=String(n==null?t.def:r(n)),a.textContent=n??`${t.def}${t.unit??``}`})}section(e,t=!1){let n=this.el(`div`,{class:`ed-body rhythm`});return{details:this.el(`details`,{class:`details ed-section`,...t?{open:!0}:{}},[this.el(`summary`,{class:`font-eyebrow`},[e]),n]),body:n}}hint(e){return this.el(`p`,{class:`font-footnote text-surface-x-muted`},[e])}sub(e){let t=this.section(e);return t.details.classList.add(`ed-sub`),t}buildPalette(e){let{details:t,body:n}=this.section(`Palette`,!0);n.append(this.hint(`Hues feed the semantic roles below — edit a hue and every role mapped to it follows. Hue edits are scheme-global: dark mode re-points which step a token reads, it never redefines the hue itself.`));for(let t of e.colors.ramps){let i=this.sub(t);for(let n of e.colors.steps){let a=e.colors.palette[t]?.[n];a!=null&&i.body.append(this.colorInput(r(t,n),a))}n.append(i.details)}return n.append(this.buildRoles(e)),t}buildRoles(e){let{details:t,body:n}=this.sub(`Semantic roles`);n.append(this.hint(`Point a role at another hue — its whole functional token set (bg / border / solid / on-solid / text) is rewritten for both appearances.`));let r=e.colors.ramps;for(let{name:t,ramp:i}of e.colors.roles){let a=this.el(`select`,{class:`ed-input`});for(let e of r)a.append(this.el(`option`,{value:e},[e]));a.addEventListener(`change`,()=>this.remapRole(e,t,a.value)),n.append(this.row(`--${t}`,a,()=>{a.value=this.roles.get(t)??i}))}return t}buildTypography(e){let{details:t,body:n}=this.section(`Typography`),r=Object.keys(e.fonts).map(e=>({label:e,value:`var(--font-${e})`})),i=e.scales.text.map(e=>({label:e.name,value:`var(--text-${e.name})`})),a={tt:[`none`,`uppercase`,`lowercase`,`capitalize`],fst:[`normal`,`italic`,`oblique`],td:[`none`,`underline`,`line-through`],tw:[`wrap`,`balance`,`pretty`,`nowrap`]};for(let t of e.typography.roles){let o=e.typography.specs[t]??{},s=this.sub(t);for(let[n,{key:c}]of Object.entries(e.typography.hooks)){let e=`--${t}-${n}`,l=o[c]==null?``:String(o[c]);n===`ff`?s.body.append(this.selectInput(e,r)):n===`fs`?s.body.append(this.selectInput(e,i)):a[n]?s.body.append(this.selectInput(e,a[n].map(e=>({label:e,value:e})))):s.body.append(this.textInput(e,l,l||c))}n.append(s.details)}return t}buildSpacing(e){let{details:t,body:n}=this.section(`Spacing`);n.append(this.hint(`Each step overrides to a fixed rem (dropping the fluid clamp). Reset restores it.`));for(let t of e.scales.space)n.append(this.remSlider(`--space-${t.name}`,t.max));return t}buildLayout(){let{details:e,body:t}=this.section(`Layout`);return t.append(this.hint(`Vertical rhythm and the .centered track widths — global structure.`)),t.append(this.slider(`--rhythm-scale`,{min:.5,max:2.5,step:.05,def:1}),this.slider(`--width-measure`,{min:30,max:110,step:1,def:65,unit:`ch`}),this.slider(`--width-breakout`,{min:40,max:150,step:1,def:90,unit:`ch`}),this.slider(`--width-spotlight`,{min:60,max:200,step:1,def:120,unit:`ch`}),this.slider(`--gutter`,{min:0,max:6,step:.1,def:3,toValue:e=>`clamp(1rem, 4cqi, ${e}rem)`,fromValue:e=>{let t=/clamp\([^,]+,[^,]+,\s*([\d.]+)/.exec(e);return t?parseFloat(t[1]):3}})),e}buildPatterns(e){let t=this.section(`Pattern defaults`);for(let[n,r]of Object.entries(e.patterns.defaults))t.body.append(this.textInput(`--${n}-default`,r,r));let n=this.section(`Radii`);for(let[t,r]of Object.entries(e.patterns.radii))n.body.append(this.textInput(`--br-${t}`,r,r));let r=this.section(`Pattern groups`);for(let[t,n]of Object.entries(e.patterns.groups)){let e=this.sub(t);for(let[r,i]of Object.entries(n))e.body.append(this.textInput(`--${r}-${t}`,i,i));r.body.append(e.details)}let i=this.section(`Components`);i.body.append(this.hint(`Per-component geometry — overrides the group defaults for just this component.`));for(let t of e.patterns.items){if(!t.wrappable.length)continue;let e=this.sub(t.name);for(let{sfx:n,prop:r}of t.wrappable){let i=t.base[r]??``;e.body.append(this.textInput(`--${n}-${t.name}`,i,i))}i.body.append(e.details)}let a=this.section(`Shadows`);for(let[t,n]of Object.entries(e.shadows))a.body.append(this.textInput(`--shadow-${t}`,n,n));return[t.details,n.details,r.details,i.details,a.details]}async flash(e,t){let n=e.textContent;e.textContent=t,setTimeout(()=>e.textContent=n,1400)}async copy(e,t){try{await navigator.clipboard.writeText(e),this.flash(t,`Copied ✓`)}catch{this.flash(t,`Copy failed`)}}async save(e,n){let{patch:r}=this.buildPatch(e);if(!Object.keys(r).length)return void this.flash(n,`Nothing to save`);try{let e=await fetch(t,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({patch:r})});if(!e.ok){let t=await e.json().catch(()=>({}));console.error(`[wc-theme-editor] save rejected`,t.errors??e.statusText),this.flash(n,`Rejected ✗`);return}this.reset(),this.flash(n,`Saved ✓`)}catch(e){console.error(`[wc-theme-editor] save failed`,e),this.flash(n,`Failed ✗`)}}buildToolbar(e){let t=this.el(`div`,{class:`cluster-start ed-toolbar`}),n=this.el(`button`,{type:`button`,class:`btn ed-seg`},[`Light`]),r=this.el(`button`,{type:`button`,class:`btn ed-seg`},[`Dark`]),i=()=>{n.classList.toggle(`is-active`,this.scheme===`light`),r.classList.toggle(`is-active`,this.scheme===`dark`)};this.syncers.add(i),n.addEventListener(`click`,()=>this.setScheme(`light`)),r.addEventListener(`click`,()=>this.setScheme(`dark`)),i(),t.append(this.el(`span`,{class:`ed-segwrap`,role:`group`},[n,r]));let a=this.el(`button`,{type:`button`,class:`btn`},[`Copy CSS`]);a.addEventListener(`click`,()=>this.copy(this.serializeCSS()||`/* no overrides yet */`,a));let o=this.el(`button`,{type:`button`,class:`btn`},[`Copy JSON patch`]);if(o.addEventListener(`click`,()=>{let{patch:t,skipped:n}=this.buildPatch(e),r=n.length?`\n// runtime-only (no source mapping): ${n.join(`, `)}`:``;this.copy(JSON.stringify(t,null,2)+r,o)}),t.append(a,o),this.canSave){let n=this.el(`button`,{type:`button`,class:`cta`},[`Save to source`]);n.addEventListener(`click`,()=>void this.save(e,n)),t.append(n)}let s=this.el(`button`,{type:`button`,class:`btn ed-danger`},[`Reset all`]);return s.addEventListener(`click`,()=>this.reset()),t.append(s),t}build(e){let t=`ds-editor-panel`,n=this.el(`div`,{id:t,popover:`auto`,class:`drawer drawer--right ed-panel bg-surface text-surface rhythm`,"aria-label":`Design-system editor`});n.append(this.el(`header`,{class:`cluster-between`},[this.el(`strong`,{class:`font-heading`},[`Theme editor`]),(()=>{let e=this.el(`button`,{type:`button`,class:`btn`,popovertarget:t,popovertargetaction:`hide`},[`×`]);return e.setAttribute(`aria-label`,`Close editor`),e})()]),this.buildToolbar(e),this.buildPalette(e),this.buildTypography(e),this.buildSpacing(e),this.buildLayout(),...this.buildPatterns(e));let r=this.el(`button`,{type:`button`,class:`cta ed-launch`,popovertarget:t},[`🎨 Theme`]);this.append(r,n)}};customElements.get(`wc-theme-editor`)||customElements.define(`wc-theme-editor`,i);
@@ -543,7 +543,7 @@ let Tt=!1;const Et=new Y.subtle.Watcher(async()=>{Tt||(Tt=!0,queueMicrotask(()=>
543
543
  >
544
544
  <span class=${e} part="icon" aria-hidden="true"></span>
545
545
  </button>
546
- `}};customElements.get(`copy-button`)||customElements.define(`copy-button`,Nt);var Pt=class extends ${static{this.properties={autoplay:{type:Number,reflect:!0}}}createRenderRoot(){return this}#e=[];#t=[];#n=!1;#r=!1;#i=null;#a=!1;#o=null;#s=!1;init(){this.autoplay=0}constructor(){super(),this.init()}connectedCallback(){super.connectedCallback(),this.hasAttribute(`role`)||this.setAttribute(`role`,`region`),this.hasAttribute(`aria-roledescription`)||this.setAttribute(`aria-roledescription`,`carousel`),this.#e=[...this.children].filter(e=>!e.hasAttribute(`slot`)),!(this.#e.length<2)&&(this.#n=this.classList.contains(`carousel--auto-pages`),this.#n||(this.#c(),this.#d(),this.addEventListener(`scrollsnapchange`,this.#p)),!this.autoplay&&this.hasAttribute(`autoplay`)&&(this.autoplay=Number(this.getAttribute(`autoplay`))||0),this.#s=matchMedia(`(prefers-reduced-motion: reduce)`).matches,this.autoplay>0&&(this.#y(),this.#s?(this.#a=!0,this.setAttribute(`aria-live`,`polite`),this.#b()):this.#m(),this.addEventListener(`pointerenter`,this.#g),this.addEventListener(`pointerleave`,this.#_),this.addEventListener(`focusin`,this.#g),this.addEventListener(`focusout`,this.#_)))}disconnectedCallback(){super.disconnectedCallback(),this.#n||(this.removeEventListener(`scrollsnapchange`,this.#p),this.#u()),this.removeEventListener(`pointerenter`,this.#g),this.removeEventListener(`pointerleave`,this.#_),this.removeEventListener(`focusin`,this.#g),this.removeEventListener(`focusout`,this.#_),this.#h(),this.#o&&=(this.#o.removeEventListener(`click`,this.#v),this.#o.hasAttribute(`slot`)||this.#o.remove(),null),this.removeAttribute(`aria-live`)}#c(){let e=[],t=[];for(let n=0;n<this.#e.length;n++){let r=this.#e[n];e.push(this.#l(r,n)),t.push(this.#l(r,n))}for(let t=e.length-1;t>=0;t--)this.prepend(e[t]);for(let e of t)this.append(e);this.#t=[...e,...t]}#l(e,t){let n=e.cloneNode(!0);n.setAttribute(`data-carousel-clone`,String(t)),n.setAttribute(`aria-hidden`,`true`);for(let e of[n,...n.querySelectorAll(`[tabindex], a, button, input, select, textarea`)])e.tabIndex=-1;return n}#u(){for(let e of this.#t)e.remove();this.#t=[]}#d(){requestAnimationFrame(()=>{let e=this.#e[0];e&&(this.style.scrollBehavior=`auto`,this.scrollLeft=e.offsetLeft-this.offsetLeft-(parseFloat(getComputedStyle(this).scrollPaddingLeft)||0)+(parseFloat(getComputedStyle(this).paddingLeft)||0),requestAnimationFrame(()=>{this.style.scrollBehavior=``}))})}#f(){this.scrollBy({left:this.clientWidth,behavior:`smooth`})}#p=e=>{if(this.#r){this.#r=!1;return}let t=e.snapTargetInline;if(!t||!t.hasAttribute(`data-carousel-clone`))return;let n=Number(t.getAttribute(`data-carousel-clone`)),r=this.#e[n];if(!r)return;let i=r.offsetLeft-t.offsetLeft;this.#r=!0,this.style.scrollBehavior=`auto`,this.scrollLeft+=i,requestAnimationFrame(()=>{this.style.scrollBehavior=``})};#m(){this.#i||this.autoplay<=0||(this.#a=!1,this.#i=setInterval(()=>this.#f(),this.autoplay),this.setAttribute(`aria-live`,`off`),this.#b())}#h(){this.#i&&=(clearInterval(this.#i),null)}#g=()=>{this.#h(),this.#a=!0,this.setAttribute(`aria-live`,`polite`),this.#b()};#_=()=>{this.#s||this.#m()};#v=()=>{this.#a?(this.#s=!1,this.#m()):this.#g()};#y(){let e=this.querySelector(`[slot="autoplay"]`);if(e)this.#o=e;else{let e=document.createElement(`button`);e.type=`button`,this.append(e),this.#o=e}this.#o.setAttribute(`part`,`autoplay`),this.#o.addEventListener(`click`,this.#v),this.#b()}#b(){this.#o&&(this.#o.setAttribute(`aria-label`,this.#a?`Play`:`Pause`),this.#o.setAttribute(`aria-pressed`,String(!this.#a)),this.#o.hasAttribute(`slot`)||(this.#o.textContent=this.#a?`▶`:`⏸`))}};customElements.get(`wc-carousel`)||customElements.define(`wc-carousel`,Pt);var Ft=class extends ${static{this.properties={breakpoint:{type:String,reflect:!0},projection:{type:Boolean,reflect:!0},singular:{type:Boolean,reflect:!0}}}createRenderRoot(){return this}#e=[];#t=[];#n=[];#r=null;#i=null;#a=null;#o=[];#s=[];#c=0;#l=!1;#u=null;#d=0;init(){this.breakpoint=`40rem`,this.projection=!1,this.singular=!1}constructor(){super(),this.init()}connectedCallback(){super.connectedCallback(),this.#f(),this.#e.length!==0&&(this.#m(),this.projection&&(this.#p(),this.#h(),this.#g(),this.singular&&(this.classList.add(`entries--singular`),this.#v(0))),this.#d=this.#b(),this.#x())}disconnectedCallback(){super.disconnectedCallback(),this.#u?.disconnect(),this.#u=null,this.#a?.remove(),this.#a=null,this.#o=[],this.#i?this.#i.remove():this.#r?.remove(),this.#r=null,this.#i=null,this.#s=[],this.classList.remove(`entries--wide`,`entries--projection`,`entries--singular`)}#f(){this.#e=[];let e=new Set,t=new Map,n=null;for(let r of this.children){let i=r.tagName.toLowerCase();if(/^h[1-6]$/.test(i))n=r;else if(i===`dl`&&n){let i=new Map,a=r.querySelectorAll(`dt`),o=r.querySelectorAll(`dd`);for(let n=0;n<a.length;n++){let r=a[n],s=r.textContent?.trim()??``,c=o[n]?.innerHTML??``;if(s){i.set(s,c),e.add(s);let n=r.getAttribute(`data-label`);n&&!t.has(s)&&t.set(s,n)}}this.#e.push({title:n.innerHTML,heading:n,dl:r,properties:i}),n=null}}this.#t=[...e],this.#n=this.#t.map(e=>t.get(e)??e)}#p(){this.classList.add(`entries--projection`)}#m(){let e=document.createElement(`table`);e.classList.add(`entries__table`),e.setAttribute(`aria-hidden`,`true`);let t=document.createElement(`thead`),n=document.createElement(`tr`),r=document.createElement(`th`);r.textContent=``,n.appendChild(r),this.#s=[];for(let e of this.#t){let t=document.createElement(`th`);t.textContent=e,n.appendChild(t),this.#s.push(t)}t.appendChild(n),e.appendChild(t);let i=document.createElement(`tbody`);for(let e of this.#e){let t=document.createElement(`tr`),n=document.createElement(`td`);n.innerHTML=e.title,n.style.fontWeight=`600`,t.appendChild(n);for(let n of this.#t){let r=document.createElement(`td`);r.innerHTML=e.properties.get(n)??``,t.appendChild(r)}i.appendChild(t)}e.appendChild(i),this.appendChild(e),this.#r=e}#h(){if(!this.#r)return;let e=document.createElement(`div`);e.classList.add(`entries__scroll`),this.#r.replaceWith(e),e.appendChild(this.#r),this.#i=e}#g(){let e=document.createElement(`nav`);e.classList.add(`entries__nav`),e.setAttribute(`aria-label`,`Column selector`),e.setAttribute(`aria-hidden`,`true`),this.#o=this.#t.map((t,n)=>{let r=document.createElement(`button`);return r.type=`button`,r.classList.add(`entries__nav-btn`),r.textContent=this.#n[n]??t,r.setAttribute(`aria-pressed`,String(n===0)),r.addEventListener(`click`,()=>this.#_(n)),e.appendChild(r),r}),this.#i.before(e),this.#a=e}#_(e){this.#c=e;for(let t=0;t<this.#o.length;t++)this.#o[t]?.setAttribute(`aria-pressed`,String(t===e));if(this.singular)this.#v(e);else{let t=this.#s[e];t&&this.#i&&t.scrollIntoView({behavior:`smooth`,block:`nearest`,inline:`start`})}this.dispatchEvent(new CustomEvent(`entries-column-change`,{detail:{column:e,header:this.#t[e]},bubbles:!0,composed:!0}))}#v(e){if(!this.#r)return;let t=e+1;for(let e of this.#r.rows)for(let n=1;n<e.cells.length;n++){let r=e.cells[n];r&&(r.hidden=n!==t)}}#y(){if(this.#r)for(let e of this.#r.rows)for(let t=1;t<e.cells.length;t++){let n=e.cells[t];n&&(n.hidden=!1)}}#b(){let e=this.breakpoint||`40rem`,t=document.createElement(`div`);t.style.width=e,t.style.position=`absolute`,t.style.visibility=`hidden`,this.appendChild(t);let n=t.offsetWidth;return t.remove(),n}#x(){this.#u=new ResizeObserver(this.#S),this.#u.observe(this)}#S=e=>{let t=e[0];if(!t)return;let n=t.contentBoxSize?.[0]?.inlineSize??t.contentRect.width;this.#l=n>=this.#d,this.#l?(this.classList.add(`entries--wide`),this.singular&&this.projection&&this.#y()):(this.classList.remove(`entries--wide`),this.singular&&this.projection&&this.#v(this.#c))}};customElements.get(`wc-entries`)||customElements.define(`wc-entries`,Ft);var It=class extends ${static{this.styles=[$.styles,o`
546
+ `}};customElements.get(`copy-button`)||customElements.define(`copy-button`,Nt);var Pt=class extends ${static{this.properties={autoplay:{type:Number,reflect:!0}}}createRenderRoot(){return this}#e=[];#t=[];#n=!1;#r=!1;#i=null;#a=!1;#o=null;#s=!1;init(){this.autoplay=0}constructor(){super(),this.init()}connectedCallback(){super.connectedCallback(),this.hasAttribute(`role`)||this.setAttribute(`role`,`region`),this.hasAttribute(`aria-roledescription`)||this.setAttribute(`aria-roledescription`,`carousel`),this.#e=[...this.children].filter(e=>!e.hasAttribute(`slot`)),!(this.#e.length<2)&&(this.#n=this.classList.contains(`carousel--auto-pages`),this.#n||(this.#c(),this.#d(),this.addEventListener(`scrollsnapchange`,this.#p)),!this.autoplay&&this.hasAttribute(`autoplay`)&&(this.autoplay=Number(this.getAttribute(`autoplay`))||0),this.#s=matchMedia(`(prefers-reduced-motion: reduce)`).matches,this.autoplay>0&&(this.#y(),this.#s?(this.#a=!0,this.setAttribute(`aria-live`,`polite`),this.#b()):this.#m(),this.addEventListener(`pointerenter`,this.#g),this.addEventListener(`pointerleave`,this.#_),this.addEventListener(`focusin`,this.#g),this.addEventListener(`focusout`,this.#_)))}disconnectedCallback(){super.disconnectedCallback(),this.#n||(this.removeEventListener(`scrollsnapchange`,this.#p),this.#u()),this.removeEventListener(`pointerenter`,this.#g),this.removeEventListener(`pointerleave`,this.#_),this.removeEventListener(`focusin`,this.#g),this.removeEventListener(`focusout`,this.#_),this.#h(),this.#o&&=(this.#o.removeEventListener(`click`,this.#v),this.#o.hasAttribute(`slot`)||this.#o.remove(),null),this.removeAttribute(`aria-live`)}#c(){let e=[],t=[];for(let n=0;n<this.#e.length;n++){let r=this.#e[n];e.push(this.#l(r,n)),t.push(this.#l(r,n))}for(let t=e.length-1;t>=0;t--)this.prepend(e[t]);for(let e of t)this.append(e);this.#t=[...e,...t]}#l(e,t){let n=e.cloneNode(!0);n.setAttribute(`data-carousel-clone`,String(t)),n.setAttribute(`aria-hidden`,`true`);for(let e of[n,...n.querySelectorAll(`[tabindex], a, button, input, select, textarea`)])e.tabIndex=-1;return n}#u(){for(let e of this.#t)e.remove();this.#t=[]}#d(){requestAnimationFrame(()=>{let e=this.#e[0];e&&(this.style.scrollBehavior=`auto`,this.scrollLeft=e.offsetLeft-this.offsetLeft-(parseFloat(getComputedStyle(this).scrollPaddingLeft)||0)+(parseFloat(getComputedStyle(this).paddingLeft)||0),requestAnimationFrame(()=>{this.style.scrollBehavior=``}))})}#f(){this.scrollBy({left:this.clientWidth,behavior:`smooth`})}#p=e=>{if(this.#r){this.#r=!1;return}let t=e.snapTargetInline;if(!t||!t.hasAttribute(`data-carousel-clone`))return;let n=Number(t.getAttribute(`data-carousel-clone`)),r=this.#e[n];if(!r)return;let i=r.offsetLeft-t.offsetLeft;this.#r=!0,this.style.scrollBehavior=`auto`,this.scrollLeft+=i,requestAnimationFrame(()=>{this.style.scrollBehavior=``})};#m(){this.#i||this.autoplay<=0||(this.#a=!1,this.#i=setInterval(()=>this.#f(),this.autoplay),this.setAttribute(`aria-live`,`off`),this.#b())}#h(){this.#i&&=(clearInterval(this.#i),null)}#g=()=>{this.#h(),this.#a=!0,this.setAttribute(`aria-live`,`polite`),this.#b()};#_=()=>{this.#s||this.#m()};#v=()=>{this.#a?(this.#s=!1,this.#m()):this.#g()};#y(){let e=this.querySelector(`[slot="autoplay"]`);if(e)this.#o=e;else{let e=document.createElement(`button`);e.type=`button`,this.append(e),this.#o=e}this.#o.setAttribute(`part`,`autoplay`),this.#o.addEventListener(`click`,this.#v),this.#b()}#b(){this.#o&&(this.#o.setAttribute(`aria-label`,this.#a?`Play`:`Pause`),this.#o.setAttribute(`aria-pressed`,String(!this.#a)),this.#o.hasAttribute(`slot`)||(this.#o.textContent=this.#a?`▶`:`⏸`))}};customElements.get(`wc-carousel`)||customElements.define(`wc-carousel`,Pt);var Ft=class extends ${static{this.properties={breakpoint:{type:String,reflect:!0},projection:{type:Boolean,reflect:!0},singular:{type:Boolean,reflect:!0}}}createRenderRoot(){return this}#e=[];#t=[];#n=[];#r=null;#i=null;#a=null;#o=[];#s=[];#c=0;#l=!1;#u=null;#d=0;init(){this.breakpoint=`40rem`,this.projection=!1,this.singular=!1}constructor(){super(),this.init()}connectedCallback(){super.connectedCallback(),this.#f(),this.#e.length!==0&&(this.#m(),this.projection&&(this.#p(),this.#h(),this.#g(),this.singular&&(this.classList.add(`entries--singular`),this.#v(0))),this.#d=this.#b(),this.#x())}disconnectedCallback(){super.disconnectedCallback(),this.#u?.disconnect(),this.#u=null,this.#a?.remove(),this.#a=null,this.#o=[],this.#i?this.#i.remove():this.#r?.remove(),this.#r=null,this.#i=null,this.#s=[],this.classList.remove(`entries--wide`,`entries--projection`,`entries--singular`)}#f(){this.#e=[];let e=new Set,t=new Map,n=null;for(let r of this.children){let i=r.tagName.toLowerCase();if(/^h[1-6]$/.test(i))n=r;else if(i===`dl`&&n){let i=new Map,a=r.querySelectorAll(`dt`),o=r.querySelectorAll(`dd`);for(let n=0;n<a.length;n++){let r=a[n],s=r.textContent?.trim()??``,c=o[n]?.innerHTML??``;if(s){i.set(s,c),e.add(s);let n=r.getAttribute(`data-label`);n&&!t.has(s)&&t.set(s,n)}}this.#e.push({title:n.innerHTML,heading:n,dl:r,properties:i}),n=null}}this.#t=[...e],this.#n=this.#t.map(e=>t.get(e)??e)}#p(){this.classList.add(`entries--projection`)}#m(){let e=document.createElement(`table`);e.classList.add(`entries__table`),e.setAttribute(`aria-hidden`,`true`);let t=document.createElement(`thead`),n=document.createElement(`tr`),r=document.createElement(`th`);r.textContent=``,n.appendChild(r),this.#s=[];for(let e of this.#t){let t=document.createElement(`th`);t.textContent=e,n.appendChild(t),this.#s.push(t)}t.appendChild(n),e.appendChild(t);let i=document.createElement(`tbody`);for(let e of this.#e){let t=document.createElement(`tr`),n=document.createElement(`td`);n.innerHTML=e.title,n.style.fontWeight=`600`,t.appendChild(n);for(let n of this.#t){let r=document.createElement(`td`);r.innerHTML=e.properties.get(n)??``,t.appendChild(r)}i.appendChild(t)}e.appendChild(i),this.appendChild(e),this.#r=e}#h(){if(!this.#r)return;let e=document.createElement(`div`);e.classList.add(`entries__scroll`),this.#r.replaceWith(e),e.appendChild(this.#r),this.#i=e}#g(){let e=document.createElement(`nav`);e.classList.add(`entries__nav`),e.setAttribute(`aria-label`,`Column selector`),e.setAttribute(`aria-hidden`,`true`),this.#o=this.#t.map((t,n)=>{let r=document.createElement(`button`);return r.type=`button`,r.classList.add(`entries__nav-btn`),r.textContent=this.#n[n]??t,r.setAttribute(`aria-pressed`,String(n===0)),r.addEventListener(`click`,()=>this.#_(n)),e.appendChild(r),r}),this.#i.before(e),this.#a=e}#_(e){this.#c=e;for(let t=0;t<this.#o.length;t++)this.#o[t]?.setAttribute(`aria-pressed`,String(t===e));if(this.singular)this.#v(e);else{let t=this.#s[e];t&&this.#i&&t.scrollIntoView({behavior:`smooth`,block:`nearest`,inline:`start`})}this.dispatchEvent(new CustomEvent(`entries-column-change`,{detail:{column:e,header:this.#t[e]},bubbles:!0,composed:!0}))}#v(e){if(!this.#r)return;let t=e+1;for(let e of this.#r.rows)for(let n=1;n<e.cells.length;n++){let r=e.cells[n];r&&(r.hidden=n!==t)}}#y(){if(this.#r)for(let e of this.#r.rows)for(let t=1;t<e.cells.length;t++){let n=e.cells[t];n&&(n.hidden=!1)}}#b(){let e=this.breakpoint||`40rem`,t=document.createElement(`div`);t.style.width=e,t.style.position=`absolute`,t.style.visibility=`hidden`,this.appendChild(t);let n=t.offsetWidth;return t.remove(),n}#x(){this.#u=new ResizeObserver(this.#S),this.#u.observe(this)}#S=e=>{let t=e[0];if(!t)return;let n=t.contentBoxSize?.[0]?.inlineSize??t.contentRect.width;this.#l=n>=this.#d,this.#l?(this.classList.add(`entries--wide`),this.singular&&this.projection&&this.#y()):(this.classList.remove(`entries--wide`),this.singular&&this.projection&&this.#v(this.#c))}};customElements.get(`wc-entries`)||customElements.define(`wc-entries`,Ft);var It=class e extends ${static{this.styles=[$.styles,o`
547
547
  :host {
548
548
  display: none;
549
549
  }
@@ -641,7 +641,7 @@ let Tt=!1;const Et=new Y.subtle.Watcher(async()=>{Tt||(Tt=!0,queueMicrotask(()=>
641
641
  transition: none;
642
642
  }
643
643
  }
644
- `]}static{this.properties={scheme:{type:String,reflect:!0}}}constructor(){super(),this._mediaQuery=null,this._boundMediaHandler=null,this.init()}init(){this.scheme=`system`}connectedCallback(){super.connectedCallback(),this._mediaQuery=window.matchMedia(`(prefers-color-scheme: dark)`),this._boundMediaHandler=this._handleMediaChange.bind(this),this._mediaQuery.addEventListener(`change`,this._boundMediaHandler),this._applyColorScheme()}disconnectedCallback(){super.disconnectedCallback(),this._mediaQuery&&this._boundMediaHandler&&this._mediaQuery.removeEventListener(`change`,this._boundMediaHandler),document.documentElement.style.removeProperty(`color-scheme`),delete document.documentElement.dataset.theme}_handleMediaChange(e){this.scheme===`system`&&this.requestUpdate()}_applyColorScheme(){let e=document.documentElement;this.scheme===`system`?(e.style.removeProperty(`color-scheme`),delete e.dataset.theme):(e.style.colorScheme=`${this.scheme} only`,e.dataset.theme=this.scheme)}_handleSegmentClick(e){this.scheme!==e&&(this.scheme=e,this._applyColorScheme(),this.dispatchEvent(new CustomEvent(`scheme-change`,{detail:{scheme:this.scheme},bubbles:!0,composed:!0})))}updated(e){e.has(`scheme`)&&this._applyColorScheme()}_getEffectiveScheme(){return this.scheme===`system`?this._mediaQuery?.matches?`dark`:`light`:this.scheme}render(){return this._getEffectiveScheme(),Q`
644
+ `]}static{this.properties={scheme:{type:String,reflect:!0}}}constructor(){super(),this._mediaQuery=null,this._boundMediaHandler=null,this.init()}init(){this.scheme=e.readStored()??`system`}static{this.STORAGE_KEY=`vitops-color-scheme`}static readStored(){try{let t=localStorage.getItem(e.STORAGE_KEY);return t===`light`||t===`dark`||t===`system`?t:null}catch{return null}}_persist(){try{this.scheme===`system`?localStorage.removeItem(e.STORAGE_KEY):localStorage.setItem(e.STORAGE_KEY,this.scheme)}catch{}}connectedCallback(){super.connectedCallback(),this._mediaQuery=window.matchMedia(`(prefers-color-scheme: dark)`),this._boundMediaHandler=this._handleMediaChange.bind(this),this._mediaQuery.addEventListener(`change`,this._boundMediaHandler),this._applyColorScheme()}disconnectedCallback(){super.disconnectedCallback(),this._mediaQuery&&this._boundMediaHandler&&this._mediaQuery.removeEventListener(`change`,this._boundMediaHandler)}_handleMediaChange(e){this.scheme===`system`&&this.requestUpdate()}_applyColorScheme(){let e=document.documentElement;this.scheme===`system`?(e.style.removeProperty(`color-scheme`),delete e.dataset.theme):(e.style.colorScheme=`${this.scheme} only`,e.dataset.theme=this.scheme)}_handleSegmentClick(e){this.scheme!==e&&(this.scheme=e,this._applyColorScheme(),this._persist(),this.dispatchEvent(new CustomEvent(`scheme-change`,{detail:{scheme:this.scheme},bubbles:!0,composed:!0})))}updated(e){e.has(`scheme`)&&this._applyColorScheme()}render(){return Q`
645
645
  <div class="toggle__group" role="group" aria-label="Color scheme" part="group">
646
646
  <button
647
647
  class="toggle__segment"
package/dist/index.d.mts CHANGED
@@ -238,12 +238,20 @@ type ValidationResult = {
238
238
  ok: true;
239
239
  data: DesignSystem;
240
240
  errors: [];
241
+ warnings: string[];
241
242
  } | {
242
243
  ok: false;
243
244
  data: undefined;
244
245
  errors: z.core.$ZodIssue[];
246
+ warnings: string[];
245
247
  };
246
- /** Validate an unknown value against the design-system schema. */
248
+ /**
249
+ * Validate an unknown value against the design-system schema.
250
+ *
251
+ * `warnings` are configurations that parse and generate, but produce output that
252
+ * won't behave as authored — currently only the token-namespace collisions the
253
+ * flat `--<prop>-<name>` grammar makes possible.
254
+ */
247
255
  declare function validate(input: unknown): ValidationResult;
248
256
  //#endregion
249
257
  //#region src/generate.d.ts
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/schema.ts","../src/generate.ts","../src/docs.ts","../src/shared.ts","../src/site.ts","../src/index.ts"],"mappings":";;;cA+Oa,kBAAA,EAAkB,CAAA,CAAA,aAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2BnB,YAAA,GAAe,CAAA,CAAE,KAAK,QAAQ,kBAAA;;;;;;cAsB7B,UAAA;;cAGA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAKD,gBAAA;EACN,EAAA;EAAU,IAAA,EAAM,YAAA;EAAc,MAAA;AAAA;EAC9B,EAAA;EAAW,IAAA;EAAiB,MAAA,EAAQ,CAAA,CAAE,IAAA,CAAK,SAAS;AAAA;;iBAG1C,QAAA,CAAS,KAAA,YAAiB,gBAAgB;;;KChR9C,MAAA;AAAA,UAEK,eAAA;EDgNJ;EC9MX,KAAA,WAAgB,YAAA;;EAEhB,MAAA,GAAS,MAAM;;EAEf,MAAA;;EAEA,SAAA;AAAA;AAAA,UAGe,cAAA;EACf,MAAA,EAAQ,MAAM;EACd,MAAA;EACA,OAAA;AAAA;AAAA,iBAgoCoB,QAAA,CAAS,OAAA,EAAS,eAAA,GAAkB,OAAA,CAAQ,cAAA;;;;;AD97BlE;;iBEk5BgB,YAAA,CAAa,EAAA,EAAI,YAAA,EAAc,SAAA,WAAoB,MAAM;;;;;;AFl5BzE;;;;;;;;cGnOa,SAAA,EAAW,MAAM;;;;;;cAajB,QAAA,EAAU,WAAW;;;cCmYrB,gBAAA,EAAgB,CAAA,CAAA,aAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmRjB,UAAA,GAAa,CAAA,CAAE,KAAK,QAAQ,gBAAA;AAAA,cAI3B,eAAA;;cAGA,cAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAKD,oBAAA;EACN,EAAA;EAAU,IAAA,EAAM,UAAA;EAAY,MAAA;AAAA;EAC5B,EAAA;EAAW,IAAA;EAAiB,MAAA,EAAQ,CAAA,CAAE,IAAA,CAAK,SAAS;AAAA;;;;;;iBAW1C,YAAA,CAAa,KAAA,YAAiB,oBAAoB;AAAA,KAoF7D,kBAAA,GAAqB,OAAO,CAAC,YAAA;EAAkB,WAAA;EAAuB,OAAA;AAAA;;;;;;;iBAQ3D,YAAA,CACd,YAAA,EAAc,MAAA,SAAe,kBAAA,GAC7B,GAAA,WACC,YAAA;;;;;;;;;iBA4Ba,iBAAA,CAAkB,KAAA,WAAgB,OAAA,YAAyB,UAAU;;iBA4BrE,UAAA,CAAW,GAAY;;iBAevB,SAAA,CAAU,MAAA,EAAQ,MAAA,mBAAyB,MAAA,EAAQ,MAAM;;;;;;;;iBC50BzD,aAAA,IAAiB,YAAY"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/schema.ts","../src/generate.ts","../src/docs.ts","../src/shared.ts","../src/site.ts","../src/index.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -122,13 +122,20 @@ const jsonSchema = {
122
122
  $id: SCHEMA_URL,
123
123
  ...z.toJSONSchema(DesignSystemSchema, { target: "draft-2020-12" })
124
124
  };
125
- /** Validate an unknown value against the design-system schema. */
125
+ /**
126
+ * Validate an unknown value against the design-system schema.
127
+ *
128
+ * `warnings` are configurations that parse and generate, but produce output that
129
+ * won't behave as authored — currently only the token-namespace collisions the
130
+ * flat `--<prop>-<name>` grammar makes possible.
131
+ */
126
132
  function validate(input) {
127
133
  const result = z.safeParse(DesignSystemSchema, input);
128
134
  if (!result.success) return {
129
135
  ok: false,
130
136
  data: void 0,
131
- errors: result.error.issues
137
+ errors: result.error.issues,
138
+ warnings: []
132
139
  };
133
140
  const { palette, roles } = result.data.colors;
134
141
  for (const [role, hue] of Object.entries(roles)) if (palette[hue] == null) return {
@@ -142,12 +149,18 @@ function validate(input) {
142
149
  role
143
150
  ],
144
151
  message: `role "${role}" references unknown palette hue "${hue}"`
145
- }]
152
+ }],
153
+ warnings: []
146
154
  };
155
+ const warnings = [];
156
+ const radii = Object.keys(result.data.patterns?.radii ?? {});
157
+ const items = new Set(Object.keys(result.data.patterns?.items ?? {}));
158
+ for (const name of radii) if (items.has(name)) warnings.push(`patterns.radii.${name} collides with the "${name}" pattern on --br-${name}; the pattern's override hook wins — rename the radius`);
147
159
  return {
148
160
  ok: true,
149
161
  data: result.data,
150
- errors: []
162
+ errors: [],
163
+ warnings
151
164
  };
152
165
  }
153
166
 
@@ -1492,6 +1505,22 @@ function generateDocs(ds, assetsDir) {
1492
1505
  * and the pre-built JS bundles) live under `assets/` in this package and are read /
1493
1506
  * copied from there — they are the same for every consumer.
1494
1507
  */
1508
+ /**
1509
+ * Selector the dark functional-token flip hangs off.
1510
+ *
1511
+ * `data-brx-theme` is Bricks' own attribute — Bricks sets it, so it's what the
1512
+ * WordPress target needs. Nothing sets it anywhere else, which meant the dark
1513
+ * flip was unreachable outside Bricks: the shipped `<color-scheme-toggle>` web
1514
+ * component writes `documentElement.dataset.theme` (i.e. `data-theme`), so
1515
+ * clicking "Dark" changed an attribute no rule matched. Matching both makes the
1516
+ * component work on every target without changing what Bricks already does.
1517
+ *
1518
+ * Note this covers the explicit choice only — there is deliberately no
1519
+ * `prefers-color-scheme` block, so the toggle's "System" position currently
1520
+ * resolves to light. Adding one would flip every existing consumer site dark for
1521
+ * dark-OS users, which is a product decision, not a bug fix.
1522
+ */
1523
+ const DARK_SEL = ":root[data-brx-theme=\"dark\"], :root[data-theme=\"dark\"]";
1495
1524
  const DEFAULT_ASSETS = join(dirname(fileURLToPath(import.meta.url)), "..", "assets");
1496
1525
  const UTILITY_PROPS = {
1497
1526
  bg: "background-color",
@@ -1631,7 +1660,7 @@ function build(ds, format, assetsDir) {
1631
1660
  if (surfaceRole) fb += ` --overlay: color-mix(in oklch, var(--color-${surfaceRole.hue}-950) 60%, transparent);\n`;
1632
1661
  if (fb) {
1633
1662
  css += `/* Functional role tokens (dark) */\n`;
1634
- css += `:root[data-brx-theme="dark"] {\n color-scheme: dark;\n${fb}}\n\n`;
1663
+ css += `${DARK_SEL} {\n color-scheme: dark;\n${fb}}\n\n`;
1635
1664
  }
1636
1665
  }
1637
1666
  const allTokens = [];
@@ -1936,11 +1965,25 @@ function build(ds, format, assetsDir) {
1936
1965
  }, null, 2),
1937
1966
  designManifest: (() => {
1938
1967
  const reverseIndex = {};
1939
- for (const [name, hue] of Object.entries(expandedPalette)) for (const n of Object.keys(hue.numeric)) reverseIndex[`--color-${name}-${n}`] = `colors.palette.${name}.seed`;
1968
+ for (const [name, hue] of Object.entries(expandedPalette)) for (const n of Object.keys(hue.numeric)) reverseIndex[`--color-${name}-${n}`] = `colors.palette.${name}.anchors.${n}`;
1940
1969
  const colorRoles = Object.entries(roleMap).map(([name, ramp]) => ({
1941
1970
  name,
1942
1971
  ramp
1943
1972
  }));
1973
+ const roleTokens = Object.fromEntries(Object.entries(expandedPalette).map(([hueName, hue]) => {
1974
+ const def = functionalRole("_", hueName, hue);
1975
+ const sfc = functionalRole("surface", hueName, hue);
1976
+ return [hueName, {
1977
+ default: {
1978
+ light: def.light,
1979
+ dark: def.dark
1980
+ },
1981
+ surface: {
1982
+ light: sfc.light,
1983
+ dark: sfc.dark
1984
+ }
1985
+ }];
1986
+ }));
1944
1987
  const typoRoles = typography?.roles ?? {};
1945
1988
  const hooks = {};
1946
1989
  for (const [key, [prop, sfx]] of Object.entries(TYPO_KEYMAP)) hooks[sfx] = {
@@ -1953,7 +1996,6 @@ function build(ds, format, assetsDir) {
1953
1996
  const pGroups = patterns?.groups ?? {};
1954
1997
  const pItems = patterns?.items ?? {};
1955
1998
  for (const prop of Object.keys(pDefaults)) reverseIndex[`--${prop}-default`] = `patterns.defaults.${prop}`;
1956
- for (const name of Object.keys(pRadii)) reverseIndex[`--br-${name}`] = `patterns.radii.${name}`;
1957
1999
  for (const [group, props] of Object.entries(pGroups)) for (const prop of Object.keys(props)) reverseIndex[`--${prop}-${group}`] = `patterns.groups.${group}.${prop}`;
1958
2000
  const items = Object.entries(pItems).map(([name, p]) => {
1959
2001
  const base = p.base ?? {};
@@ -1970,12 +2012,14 @@ function build(ds, format, assetsDir) {
1970
2012
  roles: p.roles ?? []
1971
2013
  };
1972
2014
  });
2015
+ for (const name of Object.keys(pRadii)) if (!(`--br-${name}` in reverseIndex)) reverseIndex[`--br-${name}`] = `patterns.radii.${name}`;
1973
2016
  return JSON.stringify({
1974
2017
  colors: {
1975
2018
  ramps: Object.keys(expandedPalette),
1976
2019
  steps: NUMERIC_STEPS,
1977
2020
  palette: numericPalette,
1978
- roles: colorRoles
2021
+ roles: colorRoles,
2022
+ roleTokens
1979
2023
  },
1980
2024
  typography: {
1981
2025
  roles: Object.keys(typoRoles),
@@ -2003,10 +2047,6 @@ function build(ds, format, assetsDir) {
2003
2047
  items
2004
2048
  },
2005
2049
  shadows: shadows ?? {},
2006
- interaction: {
2007
- duration: "200ms",
2008
- easing: "ease"
2009
- },
2010
2050
  reverseIndex
2011
2051
  }, null, 2);
2012
2052
  })(),
@@ -2070,7 +2110,7 @@ function emitTailwind(ctx) {
2070
2110
  const surface = scaleRoles.find((r) => r.role === "surface");
2071
2111
  if (surface) darkBlock += ` --overlay: color-mix(in oklch, var(--color-${surface.hue}-950) 60%, transparent);\n`;
2072
2112
  }
2073
- if (darkBlock) parts.push(`/* Functional role tokens (dark) */\n:root[data-brx-theme="dark"] {\n color-scheme: dark;\n${darkBlock}}\n`);
2113
+ if (darkBlock) parts.push(`/* Functional role tokens (dark) */\n${DARK_SEL} {\n color-scheme: dark;\n${darkBlock}}\n`);
2074
2114
  parts.push("/* State variant for the active flip (hover/focus-visible are built in). */\n@custom-variant is-active (&.is-active, &[data-active]);\n");
2075
2115
  const util = [];
2076
2116
  if (scaleRoles.length) {
@@ -2327,6 +2367,7 @@ function loadConfig(input) {
2327
2367
  const lines = result.errors.slice(0, 12).map((e) => ` • ${e.path.join(".") || "(root)"}: ${e.message}`).join("\n");
2328
2368
  throw new Error(`Invalid design-system.json:\n${lines}`);
2329
2369
  }
2370
+ for (const w of result.warnings) console.warn(`[vitops] ${w}`);
2330
2371
  return result.data;
2331
2372
  }
2332
2373
  async function generate(options) {
@@ -3144,7 +3185,7 @@ function defaultConfig() {
3144
3185
  group: "control",
3145
3186
  class: "cta",
3146
3187
  fill: true,
3147
- default_role: "brand-primary",
3188
+ default_role: "ui-primary",
3148
3189
  overrides: {
3149
3190
  p: "0.75em 1.5em",
3150
3191
  b: "none",
@@ -3164,7 +3205,7 @@ function defaultConfig() {
3164
3205
  "font-weight": "600",
3165
3206
  "text-decoration": "none",
3166
3207
  cursor: "pointer",
3167
- color: "var(--brand-primary-on-solid)",
3208
+ color: "var(--ui-primary-on-solid)",
3168
3209
  "box-shadow": "var(--ds-cta-group)"
3169
3210
  },
3170
3211
  states: {