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