@threadlabs/looma 0.2.19 → 0.3.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.
Files changed (51) hide show
  1. package/dist/{chunk-A5MSXQ7Y.js → chunk-3NVMCHGR.js} +2225 -1255
  2. package/dist/chunk-XDNZIKNI.js +2721 -0
  3. package/dist/declarative-generated.cjs +93 -79
  4. package/dist/declarative-generated.d.cts +7 -1
  5. package/dist/declarative-generated.d.ts +7 -1
  6. package/dist/declarative-generated.js +91 -78
  7. package/dist/declarative.cjs +1499 -1702
  8. package/dist/declarative.d.cts +77 -3
  9. package/dist/declarative.d.ts +77 -3
  10. package/dist/declarative.js +5 -3
  11. package/dist/index.cjs +3732 -3025
  12. package/dist/index.d.cts +211 -35
  13. package/dist/index.d.ts +211 -35
  14. package/dist/index.js +6 -61
  15. package/dist/loader.cjs +3725 -2962
  16. package/dist/loader.js +2 -2
  17. package/editor/{chunk-WI7ZA44X.js → chunk-U36XNFJN.js} +111 -77
  18. package/editor/extensions/index.d.ts +272 -27
  19. package/editor/index.d.ts +1 -1
  20. package/editor/index.js +1 -1
  21. package/editor/{table-overlay-DoiLie4h.d.ts → table-overlay-DZFGHQDt.d.ts} +48 -6
  22. package/editor/ui.d.ts +15 -11
  23. package/editor/ui.js +1 -1
  24. package/layout/index.cjs +197 -340
  25. package/layout/index.d.cts +11 -0
  26. package/layout/index.d.ts +11 -0
  27. package/layout/index.js +197 -340
  28. package/layout.css +31 -134
  29. package/package.json +24 -11
  30. package/react/index.d.ts +1276 -0
  31. package/react/index.js +1526 -0
  32. package/styles.css +5 -10
  33. package/svelte/index.d.ts +204 -0
  34. package/svelte/index.js +1881 -0
  35. package/theme-dark.css +81 -2
  36. package/theme-high-contrast.css +14 -0
  37. package/theme-light.css +30 -1
  38. package/tokens.css +45 -1
  39. package/vue/chunk-UZMTYDP6.js +4355 -0
  40. package/vue/editor/index.d.ts +78 -8
  41. package/vue/editor/index.js +59 -49
  42. package/vue/index.d.ts +67 -78
  43. package/vue/index.js +3 -9
  44. package/dist/chunk-ECJQ4YGC.js +0 -2925
  45. package/dist/valibot.cjs +0 -31
  46. package/dist/valibot.d.cts +0 -10
  47. package/dist/valibot.d.ts +0 -10
  48. package/dist/valibot.js +0 -9
  49. package/dist/validation-bxcou-l-.d.cts +0 -58
  50. package/dist/validation-bxcou-l-.d.ts +0 -58
  51. package/vue/chunk-P7BZ2KJZ.js +0 -3559
package/layout/index.js CHANGED
@@ -7,7 +7,7 @@ var __export = (target, all) => {
7
7
  // src/declarative-index.ts
8
8
  import { registerLoomaPackage } from "@threadlabs/looma/core/declarative";
9
9
 
10
- // ../../tools/migrate-html-next/generated/layout/components/controllers/ui-reel.js
10
+ // src/declarative/components/controllers/ui-reel.js
11
11
  var ui_reel_exports = {};
12
12
  __export(ui_reel_exports, {
13
13
  default: () => controller
@@ -18,7 +18,7 @@ function controller(host) {
18
18
  if (!element.hasAttribute("tabindex")) element.setAttribute("tabindex", "0");
19
19
  }
20
20
 
21
- // ../../tools/migrate-html-next/generated/layout/components/controllers/ui-separator.js
21
+ // src/declarative/components/controllers/ui-separator.js
22
22
  var ui_separator_exports = {};
23
23
  __export(ui_separator_exports, {
24
24
  default: () => controller2
@@ -43,63 +43,41 @@ function controller2(host) {
43
43
  };
44
44
  }
45
45
 
46
- // ../../tools/migrate-html-next/generated/layout/components/controllers/ui-sidebar.js
46
+ // src/declarative/components/controllers/ui-sidebar.js
47
47
  var ui_sidebar_exports = {};
48
48
  __export(ui_sidebar_exports, {
49
49
  default: () => controller3
50
50
  });
51
+ var BREAKPOINTS = { sm: "40rem", md: "48rem", lg: "64rem" };
51
52
  function positive(value, fallback) {
52
53
  const number = Number(value);
53
54
  return Number.isFinite(number) && number > 0 ? number : fallback;
54
55
  }
55
56
  function controller3(host) {
56
57
  const element = host.element;
58
+ const document = element.ownerDocument;
59
+ const view = document.defaultView;
57
60
  let resizeHandle;
58
61
  let pointerAbort;
62
+ let media;
63
+ let lastCollapsed = Boolean(host.state.collapsed);
64
+ let lastWidth = Number(host.state.width) || 0;
65
+ host.state.internalCollapsed = lastCollapsed;
66
+ host.state.drawer = false;
59
67
  const bounds = () => {
60
- const min = positive(host.state.minWidth, 176);
68
+ const min = positive(host.state.minWidth, 200);
61
69
  return { min, max: Math.max(min, positive(host.state.maxWidth, 480)), step: positive(host.state.resizeStep, 16) };
62
70
  };
63
- const defaultWidth = () => host.state.width === "narrow" ? 224 : host.state.width === "wide" ? 384 : 288;
64
- const storageId = () => {
65
- const key = String(host.state.storageKey ?? "").trim();
66
- return key ? `looma:sidebar-width:${key}` : null;
67
- };
68
- const readStoredWidth = () => {
69
- const key = storageId();
70
- if (!key || typeof localStorage === "undefined") return null;
71
- try {
72
- const value = Number(localStorage.getItem(key));
73
- return Number.isFinite(value) && value > 0 ? value : null;
74
- } catch {
75
- return null;
76
- }
77
- };
78
- const persistWidth = (width) => {
79
- const key = storageId();
80
- if (!key || typeof localStorage === "undefined") return;
81
- try {
82
- localStorage.setItem(key, String(width));
83
- } catch {
84
- }
85
- };
86
- const currentWidth = () => {
87
- const inline = Number.parseFloat(element.style.getPropertyValue("--ui-sidebar-width"));
88
- if (Number.isFinite(inline)) return inline;
89
- const children = [...element.children].filter((child) => !child.hasAttribute("data-ui-sidebar-resizer"));
90
- const region = host.state.side === "end" ? children.at(-1) : children[0];
91
- return region?.getBoundingClientRect().width || defaultWidth();
92
- };
93
- const setWidth = (value, persist = false, trigger = "programmatic") => {
71
+ const currentWidth = () => element.getBoundingClientRect().width || 280;
72
+ const setWidth = (value, trigger = "programmatic") => {
94
73
  const { min, max } = bounds();
95
74
  const width = Math.round(Math.max(min, Math.min(max, value)));
96
- const previous = Number.parseFloat(element.style.getPropertyValue("--ui-sidebar-width"));
97
- element.style.setProperty("--ui-sidebar-width", `${width}px`);
75
+ const previous = Number.parseFloat(element.style.getPropertyValue("--_sidebar-width"));
76
+ element.style.setProperty("--_sidebar-width", `${width}px`);
98
77
  resizeHandle?.setAttribute("aria-valuemin", String(min));
99
78
  resizeHandle?.setAttribute("aria-valuemax", String(max));
100
79
  resizeHandle?.setAttribute("aria-valuenow", String(width));
101
- if (persist && previous !== width) persistWidth(width);
102
- if (!Number.isFinite(previous) || previous !== width) host.dispatch("resize", { width, trigger });
80
+ if (previous !== width) host.dispatch("resize", { width, trigger });
103
81
  };
104
82
  const onKeydown = (event) => {
105
83
  const { min, max, step } = bounds();
@@ -112,7 +90,7 @@ function controller3(host) {
112
90
  }
113
91
  if (next === null) return;
114
92
  event.preventDefault();
115
- setWidth(next, true, "keyboard");
93
+ setWidth(next, "keyboard");
116
94
  };
117
95
  const onPointerdown = (event) => {
118
96
  if (event.button !== 0 || pointerAbort) return;
@@ -123,15 +101,14 @@ function controller3(host) {
123
101
  pointerAbort = new AbortController();
124
102
  const signal = pointerAbort.signal;
125
103
  const finish = () => {
126
- persistWidth(currentWidth());
127
104
  pointerAbort?.abort();
128
105
  pointerAbort = void 0;
129
106
  };
130
- window.addEventListener("pointermove", (move) => {
131
- setWidth(startWidth + (move.clientX - startX) * multiplier, false, "pointer");
107
+ view.addEventListener("pointermove", (move) => {
108
+ setWidth(startWidth + (move.clientX - startX) * multiplier, "pointer");
132
109
  }, { signal });
133
- window.addEventListener("pointerup", finish, { once: true, signal });
134
- window.addEventListener("pointercancel", finish, { once: true, signal });
110
+ view.addEventListener("pointerup", finish, { once: true, signal });
111
+ view.addEventListener("pointercancel", finish, { once: true, signal });
135
112
  };
136
113
  const removeHandle = () => {
137
114
  pointerAbort?.abort();
@@ -139,8 +116,8 @@ function controller3(host) {
139
116
  resizeHandle?.remove();
140
117
  resizeHandle = void 0;
141
118
  };
142
- const sync = () => {
143
- if (!host.state.resizable) {
119
+ const syncHandle = () => {
120
+ if (!host.state.resizable || host.state.drawer || host.state.internalCollapsed) {
144
121
  removeHandle();
145
122
  return;
146
123
  }
@@ -157,328 +134,208 @@ function controller3(host) {
157
134
  resizeHandle.append(guide);
158
135
  resizeHandle.addEventListener("keydown", onKeydown);
159
136
  resizeHandle.addEventListener("pointerdown", onPointerdown);
160
- resizeHandle.addEventListener("dblclick", () => setWidth(defaultWidth(), true, "pointer"));
137
+ resizeHandle.addEventListener("dblclick", () => {
138
+ element.style.removeProperty("--_sidebar-width");
139
+ setWidth(currentWidth(), "pointer");
140
+ });
161
141
  element.append(resizeHandle);
162
- setWidth(readStoredWidth() ?? currentWidth());
163
142
  }
164
143
  resizeHandle.setAttribute("aria-label", String(host.state.resizeLabel || "Resize sidebar"));
165
- setWidth(currentWidth());
144
+ const { min, max } = bounds();
145
+ resizeHandle.setAttribute("aria-valuemin", String(min));
146
+ resizeHandle.setAttribute("aria-valuemax", String(max));
147
+ resizeHandle.setAttribute("aria-valuenow", String(Math.round(currentWidth())));
166
148
  };
167
- const stop = host.effect(sync);
168
- sync();
149
+ const applyMode = () => {
150
+ const drawer = media?.matches ?? false;
151
+ if (drawer === host.state.drawer) return;
152
+ host.state.drawer = drawer;
153
+ if (drawer) {
154
+ element.setAttribute("popover", "auto");
155
+ } else {
156
+ if (element.matches(":popover-open")) element.hidePopover();
157
+ element.removeAttribute("popover");
158
+ }
159
+ syncHandle();
160
+ };
161
+ const watchBreakpoint = () => {
162
+ media?.removeEventListener("change", applyMode);
163
+ if (typeof view.matchMedia !== "function") return;
164
+ const width = BREAKPOINTS[host.state.breakpoint] ?? BREAKPOINTS.md;
165
+ media = view.matchMedia(`(width < ${width})`);
166
+ media.addEventListener("change", applyMode);
167
+ applyMode();
168
+ };
169
+ const toggle = (trigger) => {
170
+ if (host.state.drawer) {
171
+ element.togglePopover();
172
+ return;
173
+ }
174
+ host.state.internalCollapsed = !host.state.internalCollapsed;
175
+ syncHandle();
176
+ host.dispatch("toggle", { open: !host.state.internalCollapsed, mode: "docked", trigger });
177
+ };
178
+ const triggerOf = (source) => source?.matches?.(":focus-visible") ? "keyboard" : "pointer";
179
+ const onCommand = (event) => {
180
+ if (event.command !== "--toggle") return;
181
+ toggle(triggerOf(event.source));
182
+ };
183
+ const invokerCommands = typeof view.HTMLButtonElement?.prototype === "object" && "commandForElement" in view.HTMLButtonElement.prototype;
184
+ const onDocumentClick = (event) => {
185
+ const invoker = event.target.closest?.("[commandfor][command='--toggle']");
186
+ if (!invoker || !element.id || invoker.getAttribute("commandfor") !== element.id) return;
187
+ toggle(triggerOf(invoker));
188
+ };
189
+ const onPopoverToggle = (event) => {
190
+ if (!host.state.drawer) return;
191
+ host.dispatch("toggle", { open: event.newState === "open", mode: "drawer", trigger: "programmatic" });
192
+ };
193
+ const apply = () => {
194
+ const collapsed = Boolean(host.state.collapsed);
195
+ if (collapsed !== lastCollapsed) {
196
+ lastCollapsed = collapsed;
197
+ host.state.internalCollapsed = collapsed;
198
+ }
199
+ const width = Number(host.state.width) || 0;
200
+ if (width !== lastWidth) {
201
+ lastWidth = width;
202
+ if (width > 0) setWidth(width);
203
+ else element.style.removeProperty("--_sidebar-width");
204
+ }
205
+ syncHandle();
206
+ };
207
+ element.addEventListener("command", onCommand);
208
+ element.addEventListener("toggle", onPopoverToggle);
209
+ if (!invokerCommands) document.addEventListener("click", onDocumentClick);
210
+ if (lastWidth > 0) setWidth(lastWidth);
211
+ watchBreakpoint();
212
+ let lastBreakpoint = host.state.breakpoint;
213
+ const stop = host.effect(() => {
214
+ if (host.state.breakpoint !== lastBreakpoint) {
215
+ lastBreakpoint = host.state.breakpoint;
216
+ watchBreakpoint();
217
+ }
218
+ apply();
219
+ });
220
+ apply();
169
221
  return () => {
170
222
  stop();
171
223
  removeHandle();
224
+ media?.removeEventListener("change", applyMode);
225
+ element.removeEventListener("command", onCommand);
226
+ element.removeEventListener("toggle", onPopoverToggle);
227
+ document.removeEventListener("click", onDocumentClick);
172
228
  };
173
229
  }
174
230
 
175
- // ../../tools/migrate-html-next/generated/adoption/layout/registry.js
231
+ // src/declarative/registry.js
176
232
  var records = [
177
- { tag: "ui-center", source: '<template component="ui-center" status="early" summary="Looma ui-center layout primitive.">\n <defs>\n <prop name="measure" type="narrow | wide">measure token.</prop>\n <prop name="gutters" type="s | m | l">gutters token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: void 0 },
178
- { tag: "ui-cluster", source: '<template component="ui-cluster" status="early" summary="Looma ui-cluster layout primitive.">\n <defs>\n <prop name="gap" type="xs | s | m | l | xl">gap token.</prop>\n <prop name="align" type="start | center | end | stretch">align token.</prop>\n <prop name="justify" type="start | center | end | between">justify token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: void 0 },
233
+ { tag: "ui-cluster", source: '<template component="ui-cluster" status="early" summary="Wrapping row of items with consistent gaps, for tags, buttons, and other content that flows onto new lines.">\n <defs>\n <prop name="gap" type="xs | s | m | l | xl">gap token.</prop>\n <prop name="align" type="start | center | end | stretch">align token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: void 0 },
234
+ { tag: "ui-container", source: '<template component="ui-container" status="early" summary="Looma ui-container layout primitive.">\n <defs>\n <prop name="measure" type="narrow | wide">measure token.</prop>\n <prop name="gutters" type="s | m | l">gutters token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: void 0 },
179
235
  { tag: "ui-grid", source: '<template component="ui-grid" status="early" summary="Looma ui-grid layout primitive.">\n <defs>\n <prop name="gap" type="xs | s | m | l | xl">gap token.</prop>\n <prop name="min" type="sm | md | lg">min token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: void 0 },
180
- { tag: "ui-inline", source: '<template component="ui-inline" status="early" summary="Looma ui-inline layout primitive.">\n <defs>\n <prop name="gap" type="xs | s | m | l | xl">gap token.</prop>\n <prop name="align" type="start | center | end | stretch">align token.</prop>\n <prop name="justify" type="start | center | end | between">justify token.</prop>\n <prop name="wrap" type="wrap | nowrap">wrap token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: void 0 },
181
236
  { tag: "ui-reel", source: '<template component="ui-reel" status="early" summary="Looma ui-reel layout primitive." controller="./controllers/ui-reel.js">\n <defs>\n <prop name="gap" type="xs | s | m | l | xl">gap token.</prop>\n <prop name="itemWidth" type="sm | md | lg">itemWidth token.</prop>\n <prop name="snap" type="start | center">snap token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: ui_reel_exports },
182
237
  { tag: "ui-separator", source: '<template component="ui-separator" status="early" summary="Looma ui-separator layout primitive." controller="./controllers/ui-separator.js">\n <defs>\n <prop name="orientation" type="horizontal | vertical" default="horizontal">orientation token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: ui_separator_exports },
183
- { tag: "ui-sidebar", source: '<template component="ui-sidebar" status="early" summary="Looma ui-sidebar layout primitive." controller="./controllers/ui-sidebar.js">\n <defs>\n <prop name="gap" type="xs | s | m | l | xl">gap token.</prop>\n <prop name="side" type="start | end" default="start">side token.</prop>\n <prop name="width" type="narrow | default | wide" default="default">width token.</prop>\n <prop name="align" type="start | center | end | stretch">align token.</prop>\n <prop name="resizable" type="boolean" default="false">resizable token.</prop>\n <prop name="storageKey" type="string">storageKey token.</prop>\n <prop name="minWidth" type="number" default="176">minWidth token.</prop>\n <prop name="maxWidth" type="number" default="480">maxWidth token.</prop>\n <prop name="resizeStep" type="number" default="16">resizeStep token.</prop>\n <prop name="resizeLabel" type="string" default="Resize sidebar">resizeLabel token.</prop>\n <event name="resize" type="object({ width: number, trigger: keyboard | pointer | programmatic })"></event>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: ui_sidebar_exports },
184
- { tag: "ui-stack", source: '<template component="ui-stack" status="early" summary="Looma ui-stack layout primitive.">\n <defs>\n <prop name="gap" type="xs | s | m | l | xl">gap token.</prop>\n <prop name="align" type="start | center | end | stretch">align token.</prop>\n <prop name="justify" type="start | center | end | between">justify token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: void 0 },
185
- { tag: "ui-switcher", source: '<template component="ui-switcher" status="early" summary="Looma ui-switcher layout primitive.">\n <defs>\n <prop name="gap" type="xs | s | m | l | xl">gap token.</prop>\n <prop name="threshold" type="xs | sm | md | lg">threshold token.</prop>\n <prop name="align" type="start | center | end | stretch">align token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: void 0 }
186
- ];
187
- var styles = `/* Unlayered: box-model guarantees that remain safe for host composition. */
188
- :where([data-component-root~="ui-stack"], [data-component-root~="ui-inline"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-center"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]),
189
- :where([data-component-root~="ui-stack"], [data-component-root~="ui-inline"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-center"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]) *,
190
- :where([data-component-root~="ui-stack"], [data-component-root~="ui-inline"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-center"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]) *::before,
191
- :where([data-component-root~="ui-stack"], [data-component-root~="ui-inline"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-center"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]) *::after {
238
+ { tag: "ui-sidebar", source: `<template component="ui-sidebar" status="early" summary="An application sidebar panel: resizable and collapsible when docked, an off-canvas drawer on narrow screens." controller="./controllers/ui-sidebar.js">
239
+ <defs>
240
+ <prop name="side" type="start | end" default="start">The edge the sidebar sits on. The page places it beside its main content.</prop>
241
+ <prop name="width" type="number" default="0">Docked width in pixels. 0 uses --ui-sidebar-width (280px by default); dragging the handle updates it.</prop>
242
+ <prop name="minWidth" type="number" default="200">The narrowest width the resize handle allows, in pixels.</prop>
243
+ <prop name="maxWidth" type="number" default="480">The widest width the resize handle allows, in pixels.</prop>
244
+ <prop name="resizable" type="boolean" default="false">Adds a resize handle on the inner edge (drag, or arrow keys, Home, and End).</prop>
245
+ <prop name="resizeStep" type="number" default="16">Arrow-key resize step in pixels.</prop>
246
+ <prop name="resizeLabel" type="string" default="Resize sidebar">Accessible name of the resize handle.</prop>
247
+ <prop name="collapsed" type="boolean" default="false">Whether the docked sidebar is collapsed.</prop>
248
+ <prop name="breakpoint" type="sm | md | lg" default="md">Below this viewport width (40rem, 48rem, 64rem) the sidebar becomes an off-canvas drawer, closed until toggled.</prop>
249
+ <state name="internalCollapsed" :value="false"></state>
250
+ <state name="drawer" :value="false"></state>
251
+ <event name="resize" type="object({ width: number, trigger: keyboard | pointer | programmatic })"></event>
252
+ <event name="toggle" type="object({ open: boolean, mode: docked | drawer, trigger: keyboard | pointer | programmatic })"></event>
253
+ </defs>
254
+ <aside :data-state-collapsed="internalCollapsed" :data-state-drawer="drawer"><div class="sidebar__content"><slot></slot></div></aside>
255
+ <style>:scope {
256
+ --_sidebar-default-width: 280px;
257
+ position: relative;
192
258
  box-sizing: border-box;
259
+ display: flex;
260
+ flex-direction: column;
261
+ flex: none;
262
+ inline-size: var(--_sidebar-width, var(--ui-sidebar-width, var(--_sidebar-default-width)));
263
+ max-inline-size: 100%;
264
+ min-block-size: 0;
265
+ background: var(--ui-sidebar-surface, var(--ui-surface-default));
266
+ border-inline-end: 1px solid var(--ui-sidebar-border, var(--ui-border-default));
193
267
  }
194
268
 
195
- :where([data-component-root~="ui-stack"], [data-component-root~="ui-inline"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-center"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]) {
196
- /* Reveal Looma's component layer instead of reverting past it. */
197
- all: revert-layer;
198
- box-sizing: border-box;
199
- font-family: var(--ui-font-family-sans);
200
- font-size: var(--ui-font-size-md);
201
- line-height: var(--ui-line-height-md);
202
- color: var(--ui-text-primary);
269
+ :scope[data-side='end'] {
270
+ border-inline-end: 0;
271
+ border-inline-start: 1px solid var(--ui-sidebar-border, var(--ui-border-default));
203
272
  }
204
273
 
205
- :where([data-component-root~="ui-stack"], [data-component-root~="ui-inline"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-center"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"])[data-ui-inherit-typography] {
206
- font-family: inherit;
207
- font-size: inherit;
208
- line-height: inherit;
209
- font-weight: inherit;
210
- color: inherit;
211
- direction: inherit;
212
- writing-mode: inherit;
213
- text-orientation: inherit;
214
- text-rendering: inherit;
215
- font-feature-settings: inherit;
216
- font-variation-settings: inherit;
274
+ .sidebar__content {
275
+ flex: 1;
276
+ min-block-size: 0;
277
+ overflow: auto;
217
278
  }
218
279
 
219
- @layer components {
220
- :where([data-component-root~="ui-stack"], [data-component-root~="ui-inline"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-center"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]) {
221
- min-inline-size: 0;
222
- max-inline-size: 100%;
223
- margin: 0;
224
- }
225
-
226
- [data-component-root~="ui-stack"] {
227
- --ui-layout-gap: var(--ui-space-4, 1rem);
228
- --ui-layout-align: stretch;
229
- --ui-layout-justify: flex-start;
230
- display: flex;
231
- flex-direction: column;
232
- gap: var(--ui-layout-gap);
233
- align-items: var(--ui-layout-align);
234
- justify-content: var(--ui-layout-justify);
235
- }
236
-
237
- [data-component-root~="ui-stack"][data-gap="xs"] { --ui-layout-gap: var(--ui-space-2, 0.5rem); }
238
- [data-component-root~="ui-stack"][data-gap="s"] { --ui-layout-gap: var(--ui-space-3, 0.75rem); }
239
- [data-component-root~="ui-stack"][data-gap="m"] { --ui-layout-gap: var(--ui-space-4, 1rem); }
240
- [data-component-root~="ui-stack"][data-gap="l"] { --ui-layout-gap: var(--ui-space-5, 1.5rem); }
241
- [data-component-root~="ui-stack"][data-gap="xl"] { --ui-layout-gap: var(--ui-space-6, 2rem); }
242
- [data-component-root~="ui-stack"][data-align="start"] { --ui-layout-align: flex-start; }
243
- [data-component-root~="ui-stack"][data-align="center"] { --ui-layout-align: center; }
244
- [data-component-root~="ui-stack"][data-align="end"] { --ui-layout-align: flex-end; }
245
- [data-component-root~="ui-stack"][data-justify="center"] { --ui-layout-justify: center; }
246
- [data-component-root~="ui-stack"][data-justify="end"] { --ui-layout-justify: flex-end; }
247
- [data-component-root~="ui-stack"][data-justify="between"] { --ui-layout-justify: space-between; }
248
-
249
- [data-component-root~="ui-inline"],
250
- [data-component-root~="ui-cluster"] {
251
- --ui-layout-gap: var(--ui-space-3, 0.75rem);
252
- --ui-layout-align: center;
253
- --ui-layout-justify: flex-start;
254
- display: flex;
255
- flex-wrap: wrap;
256
- align-items: var(--ui-layout-align);
257
- justify-content: var(--ui-layout-justify);
258
- gap: var(--ui-layout-gap);
259
- }
260
-
261
- [data-component-root~="ui-inline"][data-wrap="nowrap"] { flex-wrap: nowrap; }
262
- [data-component-root~="ui-inline"][data-gap="xs"],
263
- [data-component-root~="ui-cluster"][data-gap="xs"] { --ui-layout-gap: var(--ui-space-2, 0.5rem); }
264
- [data-component-root~="ui-inline"][data-gap="s"],
265
- [data-component-root~="ui-cluster"][data-gap="s"] { --ui-layout-gap: var(--ui-space-3, 0.75rem); }
266
- [data-component-root~="ui-inline"][data-gap="m"],
267
- [data-component-root~="ui-cluster"][data-gap="m"] { --ui-layout-gap: var(--ui-space-4, 1rem); }
268
-
269
- [data-component-root~="ui-grid"] {
270
- --ui-grid-gap: var(--ui-space-4, 1rem);
271
- --ui-grid-min: 16rem;
272
- display: grid;
273
- gap: var(--ui-grid-gap);
274
- grid-template-columns: repeat(auto-fit, minmax(min(var(--ui-grid-min), 100%), 1fr));
275
- }
276
-
277
- [data-component-root~="ui-grid"][data-gap="xs"] { --ui-grid-gap: var(--ui-space-2, 0.5rem); }
278
- [data-component-root~="ui-grid"][data-gap="s"] { --ui-grid-gap: var(--ui-space-3, 0.75rem); }
279
- [data-component-root~="ui-grid"][data-gap="m"] { --ui-grid-gap: var(--ui-space-4, 1rem); }
280
- [data-component-root~="ui-grid"][data-gap="l"] { --ui-grid-gap: var(--ui-space-5, 1.5rem); }
281
- [data-component-root~="ui-grid"][data-min="sm"] { --ui-grid-min: 12rem; }
282
- [data-component-root~="ui-grid"][data-min="md"] { --ui-grid-min: 16rem; }
283
- [data-component-root~="ui-grid"][data-min="lg"] { --ui-grid-min: 20rem; }
284
-
285
- [data-component-root~="ui-center"] {
286
- --ui-center-measure: 65ch;
287
- --ui-center-gutters: var(--ui-space-4, 1rem);
288
- display: block;
289
- inline-size: 100%;
290
- max-inline-size: var(--ui-center-measure);
291
- margin-inline: auto;
292
- padding-inline: var(--ui-center-gutters);
293
- }
294
-
295
- [data-component-root~="ui-center"][data-measure="narrow"] { --ui-center-measure: 45ch; }
296
- [data-component-root~="ui-center"][data-measure="wide"] { --ui-center-measure: 80ch; }
297
- [data-component-root~="ui-center"][data-gutters="s"] { --ui-center-gutters: var(--ui-space-3, 0.75rem); }
298
- [data-component-root~="ui-center"][data-gutters="m"] { --ui-center-gutters: var(--ui-space-4, 1rem); }
299
- [data-component-root~="ui-center"][data-gutters="l"] { --ui-center-gutters: var(--ui-space-5, 1.5rem); }
300
-
301
- [data-component-root~="ui-switcher"] {
302
- --ui-switcher-gap: var(--ui-space-4, 1rem);
303
- --ui-switcher-threshold: 30rem;
304
- --ui-switcher-align: stretch;
305
- display: flex;
306
- flex-wrap: wrap;
307
- gap: var(--ui-switcher-gap);
308
- align-items: var(--ui-switcher-align);
309
- }
310
-
311
- [data-component-root~="ui-switcher"] > * {
312
- min-inline-size: 0;
313
- flex-grow: 1;
314
- flex-basis: calc((var(--ui-switcher-threshold) - 100%) * 999);
315
- }
280
+ /* Collapsed while docked. */
281
+ :scope:is([data-state-collapsed=''], [data-state-collapsed='true']):not([popover]) {
282
+ display: none;
283
+ }
316
284
 
317
- [data-component-root~="ui-switcher"][data-gap="xs"] { --ui-switcher-gap: var(--ui-space-2, 0.5rem); }
318
- [data-component-root~="ui-switcher"][data-gap="s"] { --ui-switcher-gap: var(--ui-space-3, 0.75rem); }
319
- [data-component-root~="ui-switcher"][data-gap="m"] { --ui-switcher-gap: var(--ui-space-4, 1rem); }
320
- [data-component-root~="ui-switcher"][data-gap="l"] { --ui-switcher-gap: var(--ui-space-5, 1.5rem); }
321
- [data-component-root~="ui-switcher"][data-threshold="xs"] { --ui-switcher-threshold: 20rem; }
322
- [data-component-root~="ui-switcher"][data-threshold="sm"] { --ui-switcher-threshold: 30rem; }
323
- [data-component-root~="ui-switcher"][data-threshold="md"] { --ui-switcher-threshold: 45rem; }
324
- [data-component-root~="ui-switcher"][data-threshold="lg"] { --ui-switcher-threshold: 60rem; }
325
- [data-component-root~="ui-switcher"][data-align="start"] { --ui-switcher-align: flex-start; }
326
- [data-component-root~="ui-switcher"][data-align="center"] { --ui-switcher-align: center; }
327
- [data-component-root~="ui-switcher"][data-align="end"] { --ui-switcher-align: flex-end; }
285
+ /* Drawer: a popover in the top layer, sliding in from its edge. Closed popovers are hidden by the UA. */
286
+ :scope[popover] {
287
+ position: fixed;
288
+ inset-block: 0;
289
+ inset-inline-start: 0;
290
+ inset-inline-end: auto;
291
+ margin: 0;
292
+ padding: 0;
293
+ inline-size: min(var(--_sidebar-width, var(--ui-sidebar-width, var(--_sidebar-default-width))), 85vw);
294
+ max-block-size: none;
295
+ block-size: 100dvh;
296
+ border-block: 0;
297
+ box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));
298
+ transform: translateX(0);
299
+ transition:
300
+ transform var(--ui-motion-base, 0.2s) var(--ui-motion-ease-out, ease-out),
301
+ display var(--ui-motion-base, 0.2s) allow-discrete,
302
+ overlay var(--ui-motion-base, 0.2s) allow-discrete;
303
+ }
328
304
 
329
- [data-component-root~="ui-sidebar"] {
330
- --ui-sidebar-gap: var(--ui-space-4, 1rem);
331
- --ui-sidebar-width: 18rem;
332
- --ui-sidebar-content-min: 50%;
333
- --ui-sidebar-align: stretch;
334
- display: flex;
335
- flex-wrap: wrap;
336
- gap: var(--ui-sidebar-gap);
337
- align-items: var(--ui-sidebar-align);
338
- }
305
+ /* The author display above would otherwise override the UA rule that hides a closed popover. */
306
+ :scope[popover]:not(:popover-open) {
307
+ display: none;
308
+ transform: translateX(-100%);
309
+ }
339
310
 
340
- [data-component-root~="ui-sidebar"] > :not([data-ui-sidebar-resizer]) { min-inline-size: 0; }
341
- [data-component-root~="ui-sidebar"] > :first-child {
342
- flex-basis: var(--ui-sidebar-width);
343
- flex-grow: 1;
344
- }
345
- [data-component-root~="ui-sidebar"] > :last-child:not([data-ui-sidebar-resizer]),
346
- [data-component-root~="ui-sidebar"][data-resizable='true'] > :nth-last-child(2):not([data-ui-sidebar-resizer]) {
347
- flex-basis: 0;
348
- flex-grow: 999;
349
- min-inline-size: min(var(--ui-sidebar-content-min), 100%);
350
- }
351
- [data-component-root~="ui-sidebar"][data-side="end"] > :first-child {
352
- flex-basis: 0;
353
- flex-grow: 999;
354
- min-inline-size: min(var(--ui-sidebar-content-min), 100%);
355
- }
356
- [data-component-root~="ui-sidebar"][data-side="end"] > :last-child:not([data-ui-sidebar-resizer]),
357
- [data-component-root~="ui-sidebar"][data-side="end"][data-resizable='true'] > :nth-last-child(2):not([data-ui-sidebar-resizer]) {
358
- flex-basis: var(--ui-sidebar-width);
359
- flex-grow: 1;
360
- min-inline-size: 0;
361
- }
362
- [data-component-root~="ui-sidebar"][data-gap="xs"] { --ui-sidebar-gap: var(--ui-space-2, 0.5rem); }
363
- [data-component-root~="ui-sidebar"][data-gap="s"] { --ui-sidebar-gap: var(--ui-space-3, 0.75rem); }
364
- [data-component-root~="ui-sidebar"][data-gap="m"] { --ui-sidebar-gap: var(--ui-space-4, 1rem); }
365
- [data-component-root~="ui-sidebar"][data-gap="l"] { --ui-sidebar-gap: var(--ui-space-5, 1.5rem); }
366
- [data-component-root~="ui-sidebar"][data-width="narrow"] { --ui-sidebar-width: 14rem; }
367
- [data-component-root~="ui-sidebar"][data-width="wide"] { --ui-sidebar-width: 24rem; }
368
- [data-component-root~="ui-sidebar"][data-align="start"] { --ui-sidebar-align: flex-start; }
369
- [data-component-root~="ui-sidebar"][data-align="center"] { --ui-sidebar-align: center; }
370
- [data-component-root~="ui-sidebar"][data-align="end"] { --ui-sidebar-align: flex-end; }
371
- [data-component-root~="ui-sidebar"][data-resizable='true'] {
372
- position: relative;
373
- flex-wrap: nowrap;
374
- }
375
- [data-component-root~="ui-sidebar"][data-resizable='true'] > :first-child:not([data-ui-sidebar-resizer]) {
376
- flex: 0 0 var(--ui-sidebar-width);
377
- }
378
- [data-component-root~="ui-sidebar"][data-side="end"][data-resizable='true'] > :first-child:not([data-ui-sidebar-resizer]) {
379
- flex: 1 1 0;
380
- }
381
- [data-component-root~="ui-sidebar"][data-side="end"][data-resizable='true'] > :nth-last-child(2):not([data-ui-sidebar-resizer]) {
382
- flex: 0 0 var(--ui-sidebar-width);
383
- }
384
- [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer] {
385
- position: absolute;
386
- z-index: 1;
387
- inset-block: 0;
388
- inset-inline-start: var(--ui-sidebar-width);
389
- inline-size: 8px;
390
- min-inline-size: 8px;
391
- transform: translateX(-50%);
392
- cursor: col-resize;
393
- touch-action: none;
394
- outline: none;
395
- }
396
- [data-component-root~="ui-sidebar"][data-side="end"] > [data-ui-sidebar-resizer] {
397
- inset-inline-start: auto;
398
- inset-inline-end: var(--ui-sidebar-width);
399
- transform: translateX(50%);
400
- }
401
- [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer]::after {
402
- content: "";
403
- position: absolute;
404
- inset-block: 0;
405
- inset-inline-start: 3px;
406
- inline-size: 2px;
407
- background: color-mix(in srgb, var(--ui-affordance-guide-color, var(--ui-border-strong)) 45%, transparent);
408
- opacity: var(--ui-affordance-guide-opacity, 0.42);
409
- transition:
410
- background-color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
411
- opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
412
- }
413
- [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer] > [data-ui-guide] {
414
- position: absolute;
415
- inset-block-start: 50%;
416
- inset-inline-start: 50%;
417
- inline-size: 6px;
418
- block-size: 22px;
419
- border: 1px solid var(--ui-border-strong, #c8c8c4);
420
- border-radius: var(--ui-radius-round, 999px);
421
- background: var(--ui-surface-elevated, #fff);
422
- opacity: 0;
423
- transform: translate(-50%, -50%);
424
- transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
425
- pointer-events: none;
426
- }
427
- [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer]:hover::after,
428
- [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer]:focus-visible::after {
429
- background: var(--ui-affordance-direct-color, var(--ui-accent-solid, var(--ui-color-focus, Highlight)));
430
- opacity: 1;
431
- }
432
- [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer]:is(:hover, :focus-visible) > [data-ui-guide] {
433
- opacity: 1;
434
- }
311
+ :scope[popover][data-side='end'] {
312
+ inset-inline-start: auto;
313
+ inset-inline-end: 0;
314
+ }
435
315
 
436
- [data-component-root~="ui-reel"] {
437
- --ui-reel-gap: var(--ui-space-4, 1rem);
438
- --ui-reel-item-width: auto;
439
- display: flex;
440
- inline-size: 100%;
441
- gap: var(--ui-reel-gap);
442
- overflow-x: auto;
443
- overflow-y: hidden;
444
- overscroll-behavior-inline: contain;
445
- -webkit-overflow-scrolling: touch;
446
- }
316
+ :scope[popover][data-side='end']:not(:popover-open) {
317
+ transform: translateX(100%);
318
+ }
447
319
 
448
- [data-component-root~="ui-reel"] > * {
449
- min-inline-size: 0;
450
- flex: 0 0 var(--ui-reel-item-width);
451
- }
452
- [data-component-root~="ui-reel"][data-gap="xs"] { --ui-reel-gap: var(--ui-space-2, 0.5rem); }
453
- [data-component-root~="ui-reel"][data-gap="s"] { --ui-reel-gap: var(--ui-space-3, 0.75rem); }
454
- [data-component-root~="ui-reel"][data-gap="m"] { --ui-reel-gap: var(--ui-space-4, 1rem); }
455
- [data-component-root~="ui-reel"][data-gap="l"] { --ui-reel-gap: var(--ui-space-5, 1.5rem); }
456
- [data-component-root~="ui-reel"][data-item-width="sm"] { --ui-reel-item-width: 12rem; }
457
- [data-component-root~="ui-reel"][data-item-width="md"] { --ui-reel-item-width: 16rem; }
458
- [data-component-root~="ui-reel"][data-item-width="lg"] { --ui-reel-item-width: 20rem; }
459
- [data-component-root~="ui-reel"][data-snap="start"],
460
- [data-component-root~="ui-reel"][data-snap="center"] { scroll-snap-type: inline mandatory; }
461
- [data-component-root~="ui-reel"][data-snap="start"] > * { scroll-snap-align: start; }
462
- [data-component-root~="ui-reel"][data-snap="center"] > * { scroll-snap-align: center; }
320
+ @starting-style {
321
+ :scope[popover]:popover-open { transform: translateX(-100%); }
322
+ :scope[popover][data-side='end']:popover-open { transform: translateX(100%); }
323
+ }
463
324
 
464
- [data-component-root~="ui-separator"] {
465
- --ui-separator-color: var(--ui-border-default, #d0d5dd);
466
- --ui-separator-space: var(--ui-space-4, 1rem);
467
- display: block;
468
- margin: 0;
469
- border: 0;
470
- border-block-start: 1px solid var(--ui-separator-color);
471
- padding: 0;
472
- }
325
+ :scope[popover]::backdrop {
326
+ background: var(--ui-sidebar-backdrop, rgb(0 0 0 / 0.32));
327
+ }
473
328
 
474
- [data-component-root~="ui-separator"][data-orientation="vertical"] {
475
- inline-size: 1px;
476
- block-size: 100%;
477
- border-block-start: 0;
478
- border-inline-start: 1px solid var(--ui-separator-color);
479
- }
329
+ @media (prefers-reduced-motion: reduce) {
330
+ :scope[popover] { transition: none; }
480
331
  }
481
- `;
332
+ </style>
333
+ </template>
334
+ `, controller: ui_sidebar_exports },
335
+ { tag: "ui-stack", source: '<template component="ui-stack" status="early" summary="Looma ui-stack layout primitive.">\n <defs>\n <prop name="gap" type="xs | s | m | l | xl">gap token.</prop>\n <prop name="align" type="start | center | end | stretch">align token.</prop>\n <prop name="justify" type="start | center | end | between">justify token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: void 0 },
336
+ { tag: "ui-switcher", source: '<template component="ui-switcher" status="early" summary="Looma ui-switcher layout primitive.">\n <defs>\n <prop name="gap" type="xs | s | m | l | xl">gap token.</prop>\n <prop name="threshold" type="xs | sm | md | lg">threshold token.</prop>\n <prop name="align" type="start | center | end | stretch">align token.</prop>\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: void 0 }
337
+ ];
338
+ var styles = '/*\n * Keep the box model outside `@layer components`: these are composition\n * guarantees for authored light-DOM children, not themeable component styles.\n */\n:where([data-component-root~="ui-stack"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-container"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]),\n:where([data-component-root~="ui-stack"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-container"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]) *,\n:where([data-component-root~="ui-stack"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-container"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]) *::before,\n:where([data-component-root~="ui-stack"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-container"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]) *::after {\n box-sizing: border-box;\n}\n\n:where([data-component-root~="ui-stack"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-container"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]) {\n /* `revert-layer` exposes `@layer components`; `revert` would skip the author layer entirely. */\n all: revert-layer;\n box-sizing: border-box;\n font-family: var(--ui-font-family-sans);\n font-size: var(--ui-font-size-md);\n line-height: var(--ui-line-height-md);\n color: var(--ui-text-primary);\n}\n\n:where([data-component-root~="ui-stack"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-container"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"])[data-ui-inherit-typography] {\n /* Consumers opt into surrounding prose styles; isolated component defaults remain the safe default. */\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n font-weight: inherit;\n color: inherit;\n direction: inherit;\n writing-mode: inherit;\n text-orientation: inherit;\n text-rendering: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n}\n\n@layer components {\n :where([data-component-root~="ui-stack"], [data-component-root~="ui-cluster"], [data-component-root~="ui-grid"], [data-component-root~="ui-container"], [data-component-root~="ui-switcher"], [data-component-root~="ui-sidebar"], [data-component-root~="ui-reel"], [data-component-root~="ui-separator"]) {\n min-inline-size: 0;\n max-inline-size: 100%;\n margin: 0;\n }\n\n [data-component-root~="ui-stack"] {\n --ui-layout-gap: var(--ui-space-4, 1rem);\n --ui-layout-align: stretch;\n --ui-layout-justify: flex-start;\n display: flex;\n flex-direction: column;\n gap: var(--ui-layout-gap);\n align-items: var(--ui-layout-align);\n justify-content: var(--ui-layout-justify);\n }\n\n [data-component-root~="ui-stack"][data-gap="xs"] { --ui-layout-gap: var(--ui-space-2, 0.5rem); }\n [data-component-root~="ui-stack"][data-gap="s"] { --ui-layout-gap: var(--ui-space-3, 0.75rem); }\n [data-component-root~="ui-stack"][data-gap="m"] { --ui-layout-gap: var(--ui-space-4, 1rem); }\n [data-component-root~="ui-stack"][data-gap="l"] { --ui-layout-gap: var(--ui-space-5, 1.5rem); }\n [data-component-root~="ui-stack"][data-gap="xl"] { --ui-layout-gap: var(--ui-space-6, 2rem); }\n [data-component-root~="ui-stack"][data-align="start"] { --ui-layout-align: flex-start; }\n [data-component-root~="ui-stack"][data-align="center"] { --ui-layout-align: center; }\n [data-component-root~="ui-stack"][data-align="end"] { --ui-layout-align: flex-end; }\n [data-component-root~="ui-stack"][data-justify="center"] { --ui-layout-justify: center; }\n [data-component-root~="ui-stack"][data-justify="end"] { --ui-layout-justify: flex-end; }\n [data-component-root~="ui-stack"][data-justify="between"] { --ui-layout-justify: space-between; }\n\n [data-component-root~="ui-cluster"] {\n --ui-layout-gap: var(--ui-space-3, 0.75rem);\n --ui-layout-align: center;\n display: flex;\n flex-wrap: wrap;\n align-items: var(--ui-layout-align);\n gap: var(--ui-layout-gap);\n }\n\n [data-component-root~="ui-cluster"][data-gap="xs"] { --ui-layout-gap: var(--ui-space-2, 0.5rem); }\n [data-component-root~="ui-cluster"][data-gap="s"] { --ui-layout-gap: var(--ui-space-3, 0.75rem); }\n [data-component-root~="ui-cluster"][data-gap="m"] { --ui-layout-gap: var(--ui-space-4, 1rem); }\n [data-component-root~="ui-cluster"][data-gap="l"] { --ui-layout-gap: var(--ui-space-5, 1.5rem); }\n [data-component-root~="ui-cluster"][data-gap="xl"] { --ui-layout-gap: var(--ui-space-6, 2rem); }\n [data-component-root~="ui-cluster"][data-align="start"] { --ui-layout-align: flex-start; }\n [data-component-root~="ui-cluster"][data-align="center"] { --ui-layout-align: center; }\n [data-component-root~="ui-cluster"][data-align="end"] { --ui-layout-align: flex-end; }\n [data-component-root~="ui-cluster"][data-align="stretch"] { --ui-layout-align: stretch; }\n\n [data-component-root~="ui-grid"] {\n --ui-grid-gap: var(--ui-space-4, 1rem);\n --ui-grid-min: 12rem;\n display: grid;\n gap: var(--ui-grid-gap);\n grid-template-columns: repeat(auto-fit, minmax(min(var(--ui-grid-min), 100%), 1fr));\n }\n\n [data-component-root~="ui-grid"][data-gap="xs"] { --ui-grid-gap: var(--ui-space-2, 0.5rem); }\n [data-component-root~="ui-grid"][data-gap="s"] { --ui-grid-gap: var(--ui-space-3, 0.75rem); }\n [data-component-root~="ui-grid"][data-gap="m"] { --ui-grid-gap: var(--ui-space-4, 1rem); }\n [data-component-root~="ui-grid"][data-gap="l"] { --ui-grid-gap: var(--ui-space-5, 1.5rem); }\n [data-component-root~="ui-grid"][data-min="sm"] { --ui-grid-min: 12rem; }\n [data-component-root~="ui-grid"][data-min="md"] { --ui-grid-min: 16rem; }\n [data-component-root~="ui-grid"][data-min="lg"] { --ui-grid-min: 20rem; }\n\n [data-component-root~="ui-container"] {\n --ui-container-measure: 65ch;\n --ui-container-gutters: var(--ui-space-4, 1rem);\n display: block;\n inline-size: 100%;\n max-inline-size: var(--ui-container-measure);\n margin-inline: auto;\n padding-inline: var(--ui-container-gutters);\n }\n\n [data-component-root~="ui-container"][data-measure="narrow"] { --ui-container-measure: 45ch; }\n [data-component-root~="ui-container"][data-measure="wide"] { --ui-container-measure: 80ch; }\n [data-component-root~="ui-container"][data-gutters="s"] { --ui-container-gutters: var(--ui-space-3, 0.75rem); }\n [data-component-root~="ui-container"][data-gutters="m"] { --ui-container-gutters: var(--ui-space-4, 1rem); }\n [data-component-root~="ui-container"][data-gutters="l"] { --ui-container-gutters: var(--ui-space-5, 1.5rem); }\n\n [data-component-root~="ui-switcher"] {\n --ui-switcher-gap: var(--ui-space-4, 1rem);\n --ui-switcher-threshold: 30rem;\n --ui-switcher-align: stretch;\n display: flex;\n flex-wrap: wrap;\n gap: var(--ui-switcher-gap);\n align-items: var(--ui-switcher-align);\n }\n\n [data-component-root~="ui-switcher"] > * {\n min-inline-size: 0;\n flex-grow: 1;\n /* The large multiplier makes the basis flip as a group at the intrinsic threshold. */\n flex-basis: calc((var(--ui-switcher-threshold) - 100%) * 999);\n }\n\n [data-component-root~="ui-switcher"][data-gap="xs"] { --ui-switcher-gap: var(--ui-space-2, 0.5rem); }\n [data-component-root~="ui-switcher"][data-gap="s"] { --ui-switcher-gap: var(--ui-space-3, 0.75rem); }\n [data-component-root~="ui-switcher"][data-gap="m"] { --ui-switcher-gap: var(--ui-space-4, 1rem); }\n [data-component-root~="ui-switcher"][data-gap="l"] { --ui-switcher-gap: var(--ui-space-5, 1.5rem); }\n [data-component-root~="ui-switcher"][data-threshold="xs"] { --ui-switcher-threshold: 20rem; }\n [data-component-root~="ui-switcher"][data-threshold="sm"] { --ui-switcher-threshold: 30rem; }\n [data-component-root~="ui-switcher"][data-threshold="md"] { --ui-switcher-threshold: 45rem; }\n [data-component-root~="ui-switcher"][data-threshold="lg"] { --ui-switcher-threshold: 60rem; }\n [data-component-root~="ui-switcher"][data-align="start"] { --ui-switcher-align: flex-start; }\n [data-component-root~="ui-switcher"][data-align="center"] { --ui-switcher-align: center; }\n [data-component-root~="ui-switcher"][data-align="end"] { --ui-switcher-align: flex-end; }\n [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer] {\n position: absolute;\n z-index: 1;\n inset-block: 0;\n /* On the panel\'s inner edge: the end edge of a start sidebar. */\n inset-inline-end: 0;\n inline-size: 8px;\n min-inline-size: 8px;\n transform: translateX(50%);\n cursor: col-resize;\n touch-action: none;\n outline: none;\n }\n [data-component-root~="ui-sidebar"][data-side="end"] > [data-ui-sidebar-resizer] {\n inset-inline-end: auto;\n inset-inline-start: 0;\n transform: translateX(-50%);\n }\n [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer]::after {\n content: "";\n position: absolute;\n inset-block: 0;\n inset-inline-start: 3px;\n inline-size: 2px;\n background: color-mix(in srgb, var(--ui-affordance-guide-color, var(--ui-border-strong)) 45%, transparent);\n opacity: var(--ui-affordance-guide-opacity, 0.42);\n transition:\n background-color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),\n opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);\n }\n [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer] > [data-ui-guide] {\n position: absolute;\n inset-block-start: 50%;\n inset-inline-start: 50%;\n inline-size: 6px;\n block-size: 22px;\n border: 1px solid var(--ui-border-strong, #c8c8c4);\n border-radius: var(--ui-radius-round, 999px);\n background: var(--ui-surface-elevated, #fff);\n opacity: 0;\n transform: translate(-50%, -50%);\n transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);\n pointer-events: none;\n }\n [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer]:hover::after,\n [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer]:focus-visible::after {\n background: var(--ui-affordance-direct-color, var(--ui-accent-solid, var(--ui-color-focus, Highlight)));\n opacity: 1;\n }\n [data-component-root~="ui-sidebar"] > [data-ui-sidebar-resizer]:is(:hover, :focus-visible) > [data-ui-guide] {\n opacity: 1;\n }\n\n [data-component-root~="ui-reel"] {\n --ui-reel-gap: var(--ui-space-4, 1rem);\n --ui-reel-item-width: auto;\n display: flex;\n inline-size: 100%;\n gap: var(--ui-reel-gap);\n overflow-x: auto;\n overflow-y: hidden;\n overscroll-behavior-inline: contain;\n -webkit-overflow-scrolling: touch;\n }\n\n [data-component-root~="ui-reel"] > * {\n min-inline-size: 0;\n flex: 0 0 var(--ui-reel-item-width);\n }\n [data-component-root~="ui-reel"][data-gap="xs"] { --ui-reel-gap: var(--ui-space-2, 0.5rem); }\n [data-component-root~="ui-reel"][data-gap="s"] { --ui-reel-gap: var(--ui-space-3, 0.75rem); }\n [data-component-root~="ui-reel"][data-gap="m"] { --ui-reel-gap: var(--ui-space-4, 1rem); }\n [data-component-root~="ui-reel"][data-gap="l"] { --ui-reel-gap: var(--ui-space-5, 1.5rem); }\n [data-component-root~="ui-reel"][data-item-width="sm"] { --ui-reel-item-width: 12rem; }\n [data-component-root~="ui-reel"][data-item-width="md"] { --ui-reel-item-width: 16rem; }\n [data-component-root~="ui-reel"][data-item-width="lg"] { --ui-reel-item-width: 20rem; }\n [data-component-root~="ui-reel"][data-snap="start"],\n [data-component-root~="ui-reel"][data-snap="center"] { scroll-snap-type: inline mandatory; }\n [data-component-root~="ui-reel"][data-snap="start"] > * { scroll-snap-align: start; }\n [data-component-root~="ui-reel"][data-snap="center"] > * { scroll-snap-align: center; }\n\n [data-component-root~="ui-separator"] {\n --ui-separator-color: var(--ui-border-default, #d0d5dd);\n --ui-separator-space: var(--ui-space-4, 1rem);\n display: block;\n margin: 0;\n border: 0;\n border-block-start: 1px solid var(--ui-separator-color);\n padding: 0;\n }\n\n [data-component-root~="ui-separator"][data-orientation="vertical"] {\n inline-size: 1px;\n block-size: 100%;\n border-block-start: 0;\n border-inline-start: 1px solid var(--ui-separator-color);\n }\n}\n';
482
339
 
483
340
  // src/declarative-index.ts
484
341
  registerLoomaPackage("layout", records, styles);