@getvitops/core 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 +62 -0
- package/css/global.css +10 -0
- package/css/index.css +1 -0
- package/css/patterns/forms.css +31 -0
- package/css/patterns/popover.css +18 -1
- package/css/patterns/theme-editor.css +114 -0
- package/dist/editor.js +2 -0
- package/dist/elements.js +2 -2
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,67 @@
|
|
|
1
1
|
# @getvitops/core
|
|
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
|
package/css/global.css
CHANGED
|
@@ -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;
|
package/css/index.css
CHANGED
package/css/patterns/forms.css
CHANGED
|
@@ -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)));
|
package/css/patterns/popover.css
CHANGED
|
@@ -4,14 +4,31 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
/* ── Popover — native Popover API reset + anchored position variants ───────── */
|
|
7
|
-
|
|
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
|
+
}
|
package/dist/editor.js
ADDED
|
@@ -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);
|
package/dist/elements.js
CHANGED
|
@@ -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
|
|
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getvitops/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "The Vitops design-system framework — CSS partials, Lit web components, and browser polyfills.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"type": "module",
|
|
12
12
|
"exports": {
|
|
13
13
|
"./elements": "./dist/elements.js",
|
|
14
|
+
"./editor": "./dist/editor.js",
|
|
14
15
|
"./polyfills": "./dist/polyfills.js",
|
|
15
16
|
"./deferred": "./dist/deferred.js",
|
|
16
17
|
"./css/*": "./css/*",
|
|
@@ -30,6 +31,6 @@
|
|
|
30
31
|
"lit": "^3.3.3",
|
|
31
32
|
"scroll-timeline-polyfill": "^1.1.0",
|
|
32
33
|
"temporal-polyfill": "^1.0.1",
|
|
33
|
-
"@getvitops/utils": "0.
|
|
34
|
+
"@getvitops/utils": "0.8.0"
|
|
34
35
|
}
|
|
35
36
|
}
|