@getvitops/generator 0.9.0 → 1.0.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.
@@ -62,7 +62,7 @@
62
62
  }
63
63
 
64
64
  &.list--divided .list__item + .list__item {
65
- border-block-start: 1px solid var(--list-divider-color, var(--color-surface-muted));
65
+ border-block-start: 1px solid var(--list-divider-color, var(--color-bg-surface-muted));
66
66
  }
67
67
 
68
68
  &.list--bordered {
@@ -110,7 +110,7 @@
110
110
  font-size: 0.75em;
111
111
  padding: 0.125rem 0.375rem;
112
112
  border-radius: var(--br-count, var(--br-pill, 999px));
113
- background: var(--color-surface-muted);
113
+ background: var(--color-bg-surface-muted);
114
114
  }
115
115
 
116
116
  .facet-list__item--active .facet-list__name {
@@ -140,7 +140,7 @@
140
140
  border-radius: var(--_br);
141
141
 
142
142
  &:focus {
143
- outline: 2px solid var(--filter-focus-color, var(--color-brand-primary-muted));
143
+ outline: 2px solid var(--filter-focus-color, var(--color-border-focus));
144
144
  outline-offset: 2px;
145
145
  }
146
146
  }
@@ -185,7 +185,7 @@
185
185
  .filtered-list__match {
186
186
  padding-inline: 0.125rem;
187
187
  border-radius: 0.125rem;
188
- background: var(--color-warning-muted);
188
+ background: var(--color-bg-warning-muted);
189
189
  }
190
190
  }
191
191
 
@@ -246,7 +246,7 @@
246
246
  }
247
247
 
248
248
  &:focus-within {
249
- outline: 2px solid var(--tag-list-focus-color, var(--color-brand-primary-muted));
249
+ outline: 2px solid var(--tag-list-focus-color, var(--color-border-focus));
250
250
  outline-offset: 2px;
251
251
  }
252
252
  }
@@ -43,7 +43,7 @@
43
43
  color: inherit;
44
44
 
45
45
  &:focus-visible {
46
- outline: 2px solid var(--tile-focus-color, var(--color-brand-primary-muted));
46
+ outline: 2px solid var(--tile-focus-color, var(--color-border-focus));
47
47
  outline-offset: 2px;
48
48
  }
49
49
 
@@ -13,7 +13,7 @@ nav:has(> .nav-items) {
13
13
 
14
14
  .nav-header {
15
15
  padding-bottom: 1rem;
16
- border-bottom: 1px solid var(--nav-border-color, var(--color-surface-muted));
16
+ border-bottom: 1px solid var(--nav-border-color, var(--color-bg-surface-muted));
17
17
  }
18
18
 
19
19
  .nav-items {
@@ -49,7 +49,7 @@ nav:has(> .nav-items) {
49
49
  flex-direction: column;
50
50
  gap: 1rem;
51
51
  padding-top: 1rem;
52
- border-top: 1px solid var(--nav-border-color, var(--color-surface-muted));
52
+ border-top: 1px solid var(--nav-border-color, var(--color-bg-surface-muted));
53
53
  }
54
54
 
55
55
  /* ── Dropdown submenu ─────────────────────────────────────────────────────── */
@@ -106,7 +106,7 @@ nav:has(> .nav-items) {
106
106
  border-radius: 0.375rem;
107
107
 
108
108
  &:hover {
109
- background-color: var(--color-surface-muted);
109
+ background-color: var(--color-bg-surface-muted);
110
110
  }
111
111
  }
112
112
  }
@@ -131,8 +131,8 @@ nav:has(> .nav-items) {
131
131
  inset: 0;
132
132
  height: 100dvh;
133
133
  width: 100%;
134
- background: var(--surface-bg);
135
- color: var(--surface-text);
134
+ background: var(--color-bg-surface);
135
+ color: var(--color-text-surface);
136
136
  opacity: 0;
137
137
  translate: -100%;
138
138
  transition-timing-function: var(--interact-easing, ease);
@@ -18,8 +18,8 @@
18
18
  border: var(--_b);
19
19
  border-radius: var(--_br);
20
20
  box-shadow: var(--_ds);
21
- background: var(--surface-bg);
22
- color: var(--surface-text);
21
+ background: var(--color-bg-surface);
22
+ color: var(--color-text-surface);
23
23
  animation: notification-enter 0.3s ease;
24
24
 
25
25
  &.notification--exiting {
@@ -77,7 +77,7 @@
77
77
  inset-block-end: 0;
78
78
  inset-inline: 0;
79
79
  block-size: 3px;
80
- background: var(--brand-primary-solid);
80
+ background: var(--color-bg-brand-primary-solid);
81
81
  border-radius: 0 0 var(--_br) var(--_br);
82
82
  transform-origin: left;
83
83
  animation: notification-progress var(--notification-duration, 5s) linear forwards;
@@ -123,7 +123,7 @@
123
123
 
124
124
  .scroll-progress__bar {
125
125
  block-size: 100%;
126
- background: var(--scroll-progress-color, var(--brand-primary-solid));
126
+ background: var(--scroll-progress-color, var(--color-bg-brand-primary-solid));
127
127
  transform-origin: left;
128
128
  animation: scroll-progress-grow linear;
129
129
  animation-timeline: scroll(root);
@@ -18,7 +18,7 @@
18
18
  (deferred.ts) on engines without `scroll-target-group` support. */
19
19
  .scroll-target-group a:target-current,
20
20
  .scroll-target-group a.is-current {
21
- color: var(--scroll-target-active-color, var(--brand-primary-solid));
21
+ color: var(--scroll-target-active-color, var(--color-bg-brand-primary-solid));
22
22
  }
23
23
 
24
24
  .scroll-target-group--indicator a {
@@ -47,7 +47,7 @@
47
47
  .scroll-target-group--bar a:target-current::before,
48
48
  .scroll-target-group--indicator a.is-current::before,
49
49
  .scroll-target-group--bar a.is-current::before {
50
- background-color: var(--scroll-target-active-color, var(--brand-primary-solid));
50
+ background-color: var(--scroll-target-active-color, var(--color-bg-brand-primary-solid));
51
51
  }
52
52
 
53
53
  .scroll-target-group--bar a {
@@ -107,7 +107,7 @@
107
107
 
108
108
  .toc-sidebar a:target-current,
109
109
  .toc-sidebar a.is-current {
110
- color: var(--scroll-target-active-color, var(--brand-primary-solid));
110
+ color: var(--scroll-target-active-color, var(--color-bg-brand-primary-solid));
111
111
  font-weight: 500;
112
112
  }
113
113
 
@@ -47,11 +47,11 @@
47
47
  border-radius: var(--br-control, 0.375rem);
48
48
 
49
49
  &:hover {
50
- background: var(--color-surface-muted);
50
+ background: var(--color-bg-surface-muted);
51
51
  }
52
52
 
53
53
  &:focus-visible {
54
- outline: 2px solid var(--sitenav-focus-color, var(--color-brand-primary-muted));
54
+ outline: 2px solid var(--sitenav-focus-color, var(--color-border-focus));
55
55
  outline-offset: 2px;
56
56
  }
57
57
  }
@@ -73,8 +73,8 @@
73
73
  max-inline-size: 100dvw;
74
74
  padding: 1.5rem;
75
75
  padding-block-start: 3.5rem; /* clearance for the close button */
76
- background: var(--surface-bg);
77
- color: var(--surface-text);
76
+ background: var(--color-bg-surface);
77
+ color: var(--color-text-surface);
78
78
  border: none;
79
79
  box-shadow: var(--ds-panel);
80
80
  overflow-y: auto;
@@ -149,11 +149,11 @@
149
149
  border-radius: var(--br-control, 0.375rem);
150
150
 
151
151
  &:hover {
152
- background: var(--color-surface-muted);
152
+ background: var(--color-bg-surface-muted);
153
153
  }
154
154
 
155
155
  &:focus-visible {
156
- outline: 2px solid var(--sitenav-focus-color, var(--color-brand-primary-muted));
156
+ outline: 2px solid var(--sitenav-focus-color, var(--color-border-focus));
157
157
  outline-offset: 2px;
158
158
  }
159
159
  }
@@ -280,8 +280,8 @@
280
280
  min-inline-size: 13rem;
281
281
  padding: 0.5rem;
282
282
  overflow: visible;
283
- background: var(--surface-bg);
284
- color: var(--surface-text);
283
+ background: var(--color-bg-surface);
284
+ color: var(--color-text-surface);
285
285
  border: var(--b-panel);
286
286
  border-radius: var(--br-panel);
287
287
  box-shadow: var(--ds-panel);
@@ -366,8 +366,8 @@
366
366
  min-inline-size: 13rem;
367
367
  padding: 0.5rem;
368
368
  overflow: visible;
369
- background: var(--surface-bg);
370
- color: var(--surface-text);
369
+ background: var(--color-bg-surface);
370
+ color: var(--color-text-surface);
371
371
  border: var(--b-panel);
372
372
  border-radius: var(--br-panel);
373
373
  box-shadow: var(--ds-panel);
@@ -453,8 +453,8 @@
453
453
  min-inline-size: 13rem;
454
454
  padding: 0.5rem;
455
455
  overflow: visible;
456
- background: var(--surface-bg);
457
- color: var(--surface-text);
456
+ background: var(--color-bg-surface);
457
+ color: var(--color-text-surface);
458
458
  border: var(--b-panel);
459
459
  border-radius: var(--br-panel);
460
460
  box-shadow: var(--ds-panel);
@@ -540,8 +540,8 @@
540
540
  min-inline-size: 13rem;
541
541
  padding: 0.5rem;
542
542
  overflow: visible;
543
- background: var(--surface-bg);
544
- color: var(--surface-text);
543
+ background: var(--color-bg-surface);
544
+ color: var(--color-text-surface);
545
545
  border: var(--b-panel);
546
546
  border-radius: var(--br-panel);
547
547
  box-shadow: var(--ds-panel);
@@ -38,11 +38,11 @@
38
38
  transition: background-color 0.15s ease;
39
39
 
40
40
  &:hover {
41
- background: var(--color-surface-muted);
41
+ background: var(--color-bg-surface-muted);
42
42
  }
43
43
 
44
44
  &:focus-visible {
45
- outline: 2px solid var(--split-link-focus-color, var(--color-brand-primary-muted));
45
+ outline: 2px solid var(--split-link-focus-color, var(--color-border-focus));
46
46
  outline-offset: 2px;
47
47
  }
48
48
 
@@ -71,8 +71,8 @@
71
71
  border: var(--_b);
72
72
  border-radius: var(--_br);
73
73
  box-shadow: var(--_ds);
74
- background: var(--surface-bg);
75
- color: var(--surface-text);
74
+ background: var(--color-bg-surface);
75
+ color: var(--color-text-surface);
76
76
  }
77
77
 
78
78
  /* Top-layer popover: anchored + placed via position-area. */
@@ -41,7 +41,7 @@
41
41
  font-weight: 600;
42
42
  line-height: 1;
43
43
  border-radius: var(--br-badge-indicator, var(--br-pill, 999px));
44
- background: var(--color-danger-bold);
44
+ background: var(--color-text-danger);
45
45
  color: #fff;
46
46
 
47
47
  &.badge-indicator--dot {
@@ -225,7 +225,7 @@
225
225
 
226
226
  /* ── Highlight sweep ──────────────────────────────────────────────────────── */
227
227
  .text-highlight {
228
- --_highlight-color: var(--text-highlight-color, var(--color-warning-muted));
228
+ --_highlight-color: var(--text-highlight-color, var(--color-bg-warning-muted));
229
229
  --_highlight-duration: var(--text-highlight-duration, 0.5s);
230
230
  --_highlight-pad-block: var(--text-highlight-pad-block, 0.1em);
231
231
  --_highlight-pad-inline: var(--text-highlight-pad-inline, 0);
@@ -64,7 +64,7 @@ wc-theme-editor {
64
64
  overflow: hidden;
65
65
  font-family: var(--font-mono, monospace);
66
66
  font-size: 0.9em;
67
- color: var(--surface-text-x-muted);
67
+ color: var(--color-text-surface-x-muted);
68
68
  text-overflow: ellipsis;
69
69
  white-space: nowrap;
70
70
  }
@@ -74,7 +74,7 @@ wc-theme-editor {
74
74
  padding: 0.3em 0.5em;
75
75
  border: var(--b-default);
76
76
  border-radius: var(--br-default);
77
- background: var(--surface-bg);
77
+ background: var(--color-bg-surface);
78
78
  color: inherit;
79
79
  font: inherit;
80
80
  }
@@ -107,16 +107,16 @@ wc-theme-editor {
107
107
  inset-block-start: 0;
108
108
  z-index: 1;
109
109
  padding-block: 0.5rem;
110
- background: var(--surface-bg);
110
+ background: var(--color-bg-surface);
111
111
  }
112
112
  .ed-segwrap {
113
113
  display: inline-flex;
114
114
  }
115
115
  .ed-seg.is-active {
116
- background: var(--ui-primary-solid);
117
- color: var(--ui-primary-on-solid);
116
+ background: var(--color-bg-ui-primary-solid);
117
+ color: var(--color-text-on-ui-primary);
118
118
  }
119
119
  .ed-danger {
120
- color: var(--danger-text);
120
+ color: var(--color-text-danger);
121
121
  }
122
122
  }
@@ -44,8 +44,8 @@
44
44
  padding: var(--_p);
45
45
  border-radius: var(--_br);
46
46
  box-shadow: var(--_ds);
47
- background: var(--surface-text);
48
- color: var(--surface-bg);
47
+ background: var(--color-text-surface);
48
+ color: var(--color-bg-surface);
49
49
  font-size: var(--_fs);
50
50
  white-space: nowrap;
51
51
  max-inline-size: 20rem;
@@ -18,7 +18,7 @@
18
18
  .tree__item > .tree {
19
19
  margin-inline-start: var(--tree-indent, 1.5rem);
20
20
  padding-inline-start: var(--tree-indent, 1.5rem);
21
- border-inline-start: 1px solid var(--color-surface-muted);
21
+ border-inline-start: 1px solid var(--color-bg-surface-muted);
22
22
  }
23
23
 
24
24
  .tree__content,
@@ -115,8 +115,8 @@
115
115
  inset-block-start: 0;
116
116
  block-size: 1rem;
117
117
  inline-size: calc(var(--tree-indent, 1.5rem) - 0.5rem);
118
- border-inline-start: 1px solid var(--color-surface-muted);
119
- border-block-end: 1px solid var(--color-surface-muted);
118
+ border-inline-start: 1px solid var(--color-bg-surface-muted);
119
+ border-block-end: 1px solid var(--color-bg-surface-muted);
120
120
  }
121
121
  }
122
122
 
@@ -1,2 +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 details--marker-start ed-section`,...t?{open:!0}:{}},[this.el(`summary`,{class:`font-eyebrow`},[this.el(`span`,{class:`details-icon`,"aria-hidden":`true`},[`▸`]),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:`manual`,class:`drawer drawer--right drawer--modeless 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`]);document.addEventListener(`keydown`,e=>{e.key===`Escape`&&n.matches(`:popover-open`)&&n.hidePopover()}),this.append(r,n)}};customElements.get(`wc-theme-editor`)||customElements.define(`wc-theme-editor`,i);
1
+ const e=`vitops:ds-overrides`,t=`/__vitops/design-system`,n=(e,t)=>{let n=t.indexOf(`-`),r=n===-1?t:t.slice(0,n),i=n===-1?``:t.slice(n+1);return i===`on`?`--color-${r}-on-${e}`:i.startsWith(`on-`)?`--color-${r}-on-${e}-${i.slice(3)}`:i?`--color-${r}-${e}-${i}`:`--color-${r}-${e}`},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=e.colors.roles.find(e=>e.name===t)?.kind??`chromatic`,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[n,r]of this.roles){let i=e.colors.roles.find(e=>e.name===n)?.kind??`chromatic`;this.deepSet(t,`colors.roles.${n}`,{hue:r,kind:i})}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 details--marker-start ed-section`,...t?{open:!0}:{}},[this.el(`summary`,{class:`font-eyebrow`},[this.el(`span`,{class:`details-icon`,"aria-hidden":`true`},[`▸`]),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:`manual`,class:`drawer drawer--right drawer--modeless 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`]);document.addEventListener(`keydown`,e=>{e.key===`Escape`&&n.matches(`:popover-open`)&&n.hidePopover()}),this.append(r,n)}};customElements.get(`wc-theme-editor`)||customElements.define(`wc-theme-editor`,i);