rei-kit 2.18.1 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/web.js CHANGED
@@ -1,23 +1,23 @@
1
1
  import { n as inertOutside, o as ensureSheetRoot, r as useBoundValue, t as BaseSheet_default } from "./BaseSheet-B7401rS7.js";
2
- import { n as BaseSkeleton_default, r as useMediaQuery, t as BaseListbox_default } from "./BaseListbox-BnaHlmMN.js";
2
+ import { i as useMediaQuery, n as BaseSkeleton_default, r as useMenuKeys, t as BaseListbox_default } from "./BaseListbox-Btibgnaf.js";
3
3
  import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BOaGB7Aw.js";
4
4
  import { t as BaseButton_default } from "./BaseButton-RN2an975.js";
5
5
  import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, mergeModels, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, shallowRef, toDisplayString, unref, useId, useModel, useTemplateRef, vModelText, vShow, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
6
- import { ArrowDown, ArrowUp, ChevronDown, ChevronLeft, ChevronRight, ChevronsUpDown, Search } from "lucide-vue-next";
6
+ import { ArrowDown, ArrowUp, ChevronDown, ChevronLeft, ChevronRight, ChevronsUpDown, Search, X } from "lucide-vue-next";
7
7
  import { RouterLink } from "vue-router";
8
8
  //#region src/web/BaseAccordion.vue?vue&type=script&setup=true&lang.ts
9
- var _hoisted_1$15 = { class: "rk-accordion" };
10
- var _hoisted_2$12 = [
9
+ var _hoisted_1$18 = { class: "rk-accordion" };
10
+ var _hoisted_2$13 = [
11
11
  "aria-expanded",
12
12
  "aria-controls",
13
13
  "onClick"
14
14
  ];
15
- var _hoisted_3$11 = { class: "rk-accordion-title" };
16
- var _hoisted_4$9 = {
15
+ var _hoisted_3$12 = { class: "rk-accordion-title" };
16
+ var _hoisted_4$10 = {
17
17
  class: "rk-accordion-mark",
18
18
  "aria-hidden": "true"
19
19
  };
20
- var _hoisted_5$7 = ["id"];
20
+ var _hoisted_5$8 = ["id"];
21
21
  var _hoisted_6$6 = { class: "rk-accordion-clip" };
22
22
  //#endregion
23
23
  //#region src/web/BaseAccordion.vue
@@ -40,7 +40,7 @@ var BaseAccordion_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
40
40
  else open.value = __props.multiple ? [...open.value, key] : [key];
41
41
  }
42
42
  return (_ctx, _cache) => {
43
- return openBlock(), createElementBlock("ul", _hoisted_1$15, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item) => {
43
+ return openBlock(), createElementBlock("ul", _hoisted_1$18, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item) => {
44
44
  return openBlock(), createElementBlock("li", {
45
45
  key: item.key,
46
46
  class: "rk-accordion-item"
@@ -51,10 +51,10 @@ var BaseAccordion_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
51
51
  "aria-expanded": isOpen(item.key),
52
52
  "aria-controls": `${unref(uid)}-${item.key}`,
53
53
  onClick: ($event) => toggle(item.key)
54
- }, [createElementVNode("span", _hoisted_3$11, [renderSlot(_ctx.$slots, "title", {
54
+ }, [createElementVNode("span", _hoisted_3$12, [renderSlot(_ctx.$slots, "title", {
55
55
  item,
56
56
  open: isOpen(item.key)
57
- }, () => [createTextVNode(toDisplayString(item.title), 1)], true)]), createElementVNode("span", _hoisted_4$9, [_cache[0] || (_cache[0] = createElementVNode("span", { class: "rk-accordion-bar" }, null, -1)), createElementVNode("span", { class: normalizeClass(["rk-accordion-bar rk-accordion-bar-turn", { "is-open": isOpen(item.key) }]) }, null, 2)])], 8, _hoisted_2$12)]),
57
+ }, () => [createTextVNode(toDisplayString(item.title), 1)], true)]), createElementVNode("span", _hoisted_4$10, [_cache[0] || (_cache[0] = createElementVNode("span", { class: "rk-accordion-bar" }, null, -1)), createElementVNode("span", { class: normalizeClass(["rk-accordion-bar rk-accordion-bar-turn", { "is-open": isOpen(item.key) }]) }, null, 2)])], 8, _hoisted_2$13)]),
58
58
  _: 2
59
59
  }, 1024)), createElementVNode("div", {
60
60
  id: `${unref(uid)}-${item.key}`,
@@ -62,21 +62,21 @@ var BaseAccordion_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
62
62
  }, [createElementVNode("div", _hoisted_6$6, [createElementVNode("div", { class: normalizeClass(["rk-accordion-body", { "is-open": isOpen(item.key) }]) }, [renderSlot(_ctx.$slots, "default", {
63
63
  item,
64
64
  open: isOpen(item.key)
65
- }, void 0, true)], 2)])], 10, _hoisted_5$7)]);
65
+ }, void 0, true)], 2)])], 10, _hoisted_5$8)]);
66
66
  }), 128))]);
67
67
  };
68
68
  }
69
69
  }), [["__scopeId", "data-v-03e2e1d0"]]);
70
70
  //#endregion
71
71
  //#region src/web/BaseBreadcrumb.vue?vue&type=script&setup=true&lang.ts
72
- var _hoisted_1$14 = ["aria-label"];
73
- var _hoisted_2$11 = { class: "rk-crumbs" };
74
- var _hoisted_3$10 = {
72
+ var _hoisted_1$17 = ["aria-label"];
73
+ var _hoisted_2$12 = { class: "rk-crumbs" };
74
+ var _hoisted_3$11 = {
75
75
  key: 1,
76
76
  class: "rk-crumb-current",
77
77
  "aria-current": "page"
78
78
  };
79
- var _hoisted_4$8 = {
79
+ var _hoisted_4$9 = {
80
80
  key: 2,
81
81
  class: "rk-crumb-sep",
82
82
  "aria-hidden": "true"
@@ -91,7 +91,7 @@ var BaseBreadcrumb_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
91
91
  },
92
92
  setup(__props) {
93
93
  return (_ctx, _cache) => {
94
- return openBlock(), createElementBlock("nav", { "aria-label": __props.label || void 0 }, [createElementVNode("ol", _hoisted_2$11, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item, index) => {
94
+ return openBlock(), createElementBlock("nav", { "aria-label": __props.label || void 0 }, [createElementVNode("ol", _hoisted_2$12, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item, index) => {
95
95
  return openBlock(), createElementBlock("li", {
96
96
  key: item.label,
97
97
  class: "rk-crumb"
@@ -102,21 +102,162 @@ var BaseBreadcrumb_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
102
102
  }, {
103
103
  default: withCtx(() => [createTextVNode(toDisplayString(item.label), 1)]),
104
104
  _: 2
105
- }, 1032, ["to"])) : (openBlock(), createElementBlock("span", _hoisted_3$10, toDisplayString(item.label), 1)), index < __props.items.length - 1 ? (openBlock(), createElementBlock("span", _hoisted_4$8, "/")) : createCommentVNode("", true)]);
106
- }), 128))])], 8, _hoisted_1$14);
105
+ }, 1032, ["to"])) : (openBlock(), createElementBlock("span", _hoisted_3$11, toDisplayString(item.label), 1)), index < __props.items.length - 1 ? (openBlock(), createElementBlock("span", _hoisted_4$9, "/")) : createCommentVNode("", true)]);
106
+ }), 128))])], 8, _hoisted_1$17);
107
107
  };
108
108
  }
109
109
  }), [["__scopeId", "data-v-dcc01b03"]]);
110
110
  //#endregion
111
+ //#region src/web/BaseContextMenu.vue?vue&type=script&setup=true&lang.ts
112
+ var _hoisted_1$16 = ["id", "aria-label"];
113
+ //#endregion
114
+ //#region src/web/BaseContextMenu.vue
115
+ var BaseContextMenu_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
116
+ __name: "BaseContextMenu",
117
+ props: {
118
+ label: {},
119
+ disabled: {
120
+ type: Boolean,
121
+ default: false
122
+ }
123
+ },
124
+ setup(__props, { expose: __expose }) {
125
+ const id = useId();
126
+ const open = ref(false);
127
+ const at = ref({
128
+ x: 0,
129
+ y: 0
130
+ });
131
+ const area = ref(null);
132
+ const panel = ref(null);
133
+ let restoreTo = null;
134
+ function close() {
135
+ open.value = false;
136
+ }
137
+ const triggerProps = computed(() => __props.disabled ? {} : {
138
+ "aria-haspopup": "menu",
139
+ "aria-expanded": open.value,
140
+ ...open.value ? { "aria-controls": id } : {}
141
+ });
142
+ const { items, onKeydown: onMenuKeydown } = useMenuKeys({
143
+ panel,
144
+ onClose: close
145
+ });
146
+ /**
147
+ * Keeps the panel on screen.
148
+ *
149
+ * A menu opened near the right or bottom edge would otherwise run off it,
150
+ * and the items past the edge cannot be reached with a pointer at all. It
151
+ * flips rather than clamps, because a menu that slides back over the point
152
+ * you clicked hides what you were acting on.
153
+ */
154
+ function place(x, y) {
155
+ const width = panel.value?.offsetWidth ?? 0;
156
+ const height = panel.value?.offsetHeight ?? 0;
157
+ const room = {
158
+ w: window.innerWidth,
159
+ h: window.innerHeight
160
+ };
161
+ at.value = {
162
+ x: x + width > room.w ? Math.max(0, x - width) : x,
163
+ y: y + height > room.h ? Math.max(0, y - height) : y
164
+ };
165
+ }
166
+ async function openAt(x, y) {
167
+ if (__props.disabled) return;
168
+ restoreTo = document.activeElement instanceof HTMLElement ? document.activeElement : null;
169
+ open.value = true;
170
+ await nextTick();
171
+ place(x, y);
172
+ items()[0]?.focus();
173
+ }
174
+ function onContextMenu(event) {
175
+ if (__props.disabled) return;
176
+ event.preventDefault();
177
+ openAt(event.clientX, event.clientY);
178
+ }
179
+ /**
180
+ * Shift+F10 and the Menu key, which is how this is opened without a mouse.
181
+ *
182
+ * Anchored to the focused element rather than to coordinates, because there
183
+ * is no pointer to take them from.
184
+ */
185
+ function onAreaKeydown(event) {
186
+ if (!(event.key === "ContextMenu" || event.key === "F10" && event.shiftKey) || __props.disabled) return;
187
+ event.preventDefault();
188
+ const box = (event.target instanceof HTMLElement ? event.target : area.value)?.getBoundingClientRect();
189
+ openAt(box?.left ?? 0, box ? box.bottom : 0);
190
+ }
191
+ function onPanelKeydown(event) {
192
+ onMenuKeydown(event);
193
+ }
194
+ function onDocumentPointer(event) {
195
+ if (panel.value && !panel.value.contains(event.target)) close();
196
+ }
197
+ function onDocumentContextMenu(event) {
198
+ const target = event.target;
199
+ if (panel.value?.contains(target) || area.value?.contains(target)) return;
200
+ close();
201
+ }
202
+ watch(open, async (isOpen) => {
203
+ if (typeof document === "undefined") return;
204
+ if (isOpen) {
205
+ document.addEventListener("pointerdown", onDocumentPointer);
206
+ document.addEventListener("contextmenu", onDocumentContextMenu);
207
+ window.addEventListener("resize", close);
208
+ window.addEventListener("scroll", close, true);
209
+ await nextTick();
210
+ } else {
211
+ document.removeEventListener("pointerdown", onDocumentPointer);
212
+ document.removeEventListener("contextmenu", onDocumentContextMenu);
213
+ window.removeEventListener("resize", close);
214
+ window.removeEventListener("scroll", close, true);
215
+ if (panel.value?.contains(document.activeElement)) restoreTo?.focus();
216
+ restoreTo = null;
217
+ }
218
+ });
219
+ onBeforeUnmount(() => {
220
+ if (typeof document === "undefined") return;
221
+ document.removeEventListener("pointerdown", onDocumentPointer);
222
+ document.removeEventListener("contextmenu", onDocumentContextMenu);
223
+ window.removeEventListener("resize", close);
224
+ window.removeEventListener("scroll", close, true);
225
+ });
226
+ __expose({ close });
227
+ return (_ctx, _cache) => {
228
+ return openBlock(), createElementBlock("div", {
229
+ ref_key: "area",
230
+ ref: area,
231
+ class: "rk-ctx-area",
232
+ onContextmenu: onContextMenu,
233
+ onKeydown: onAreaKeydown
234
+ }, [renderSlot(_ctx.$slots, "default", { props: triggerProps.value }, void 0, true), (openBlock(), createBlock(Teleport, { to: "body" }, [open.value ? (openBlock(), createElementBlock("div", {
235
+ key: 0,
236
+ id: unref(id),
237
+ ref_key: "panel",
238
+ ref: panel,
239
+ class: "rk-ctx-panel surface-overlay",
240
+ role: "menu",
241
+ "aria-label": __props.label,
242
+ style: normalizeStyle({
243
+ left: `${at.value.x}px`,
244
+ top: `${at.value.y}px`
245
+ }),
246
+ onKeydown: onPanelKeydown
247
+ }, [renderSlot(_ctx.$slots, "items", { close }, void 0, true)], 44, _hoisted_1$16)) : createCommentVNode("", true)]))], 544);
248
+ };
249
+ }
250
+ }), [["__scopeId", "data-v-4888e5a2"]]);
251
+ //#endregion
111
252
  //#region src/web/BaseDisclosure.vue?vue&type=script&setup=true&lang.ts
112
- var _hoisted_1$13 = { class: "rk-disclosure" };
113
- var _hoisted_2$10 = ["aria-expanded", "aria-controls"];
114
- var _hoisted_3$9 = { class: "rk-disclosure-title" };
115
- var _hoisted_4$7 = {
253
+ var _hoisted_1$15 = { class: "rk-disclosure" };
254
+ var _hoisted_2$11 = ["aria-expanded", "aria-controls"];
255
+ var _hoisted_3$10 = { class: "rk-disclosure-title" };
256
+ var _hoisted_4$8 = {
116
257
  class: "rk-disclosure-mark",
117
258
  "aria-hidden": "true"
118
259
  };
119
- var _hoisted_5$6 = ["id"];
260
+ var _hoisted_5$7 = ["id"];
120
261
  var _hoisted_6$5 = { class: "rk-disclosure-clip" };
121
262
  //#endregion
122
263
  //#region src/web/BaseDisclosure.vue
@@ -137,23 +278,245 @@ var BaseDisclosure_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
137
278
  const open = useModel(__props, "modelValue");
138
279
  const id = useId();
139
280
  return (_ctx, _cache) => {
140
- return openBlock(), createElementBlock("div", _hoisted_1$13, [(openBlock(), createBlock(resolveDynamicComponent(`h${__props.headingLevel}`), null, {
281
+ return openBlock(), createElementBlock("div", _hoisted_1$15, [(openBlock(), createBlock(resolveDynamicComponent(`h${__props.headingLevel}`), null, {
141
282
  default: withCtx(() => [createElementVNode("button", {
142
283
  type: "button",
143
284
  class: "rk-disclosure-control",
144
285
  "aria-expanded": open.value,
145
286
  "aria-controls": unref(id),
146
287
  onClick: _cache[0] || (_cache[0] = ($event) => open.value = !open.value)
147
- }, [createElementVNode("span", _hoisted_3$9, [renderSlot(_ctx.$slots, "title", {}, () => [createTextVNode(toDisplayString(__props.title), 1)], true)]), createElementVNode("span", _hoisted_4$7, [_cache[1] || (_cache[1] = createElementVNode("span", { class: "rk-disclosure-bar" }, null, -1)), createElementVNode("span", { class: normalizeClass(["rk-disclosure-bar rk-disclosure-turn", { "is-open": open.value }]) }, null, 2)])], 8, _hoisted_2$10)]),
288
+ }, [createElementVNode("span", _hoisted_3$10, [renderSlot(_ctx.$slots, "title", {}, () => [createTextVNode(toDisplayString(__props.title), 1)], true)]), createElementVNode("span", _hoisted_4$8, [_cache[1] || (_cache[1] = createElementVNode("span", { class: "rk-disclosure-bar" }, null, -1)), createElementVNode("span", { class: normalizeClass(["rk-disclosure-bar rk-disclosure-turn", { "is-open": open.value }]) }, null, 2)])], 8, _hoisted_2$11)]),
148
289
  _: 3
149
290
  })), createElementVNode("div", {
150
291
  id: unref(id),
151
292
  class: normalizeClass(["rk-disclosure-panel", { "is-open": open.value }])
152
- }, [createElementVNode("div", _hoisted_6$5, [createElementVNode("div", { class: normalizeClass(["rk-disclosure-body", { "is-open": open.value }]) }, [renderSlot(_ctx.$slots, "default", {}, void 0, true)], 2)])], 10, _hoisted_5$6)]);
293
+ }, [createElementVNode("div", _hoisted_6$5, [createElementVNode("div", { class: normalizeClass(["rk-disclosure-body", { "is-open": open.value }]) }, [renderSlot(_ctx.$slots, "default", {}, void 0, true)], 2)])], 10, _hoisted_5$7)]);
153
294
  };
154
295
  }
155
296
  }), [["__scopeId", "data-v-ad5c09f5"]]);
156
297
  //#endregion
298
+ //#region src/web/BaseHoverCard.vue?vue&type=script&setup=true&lang.ts
299
+ var _hoisted_1$14 = ["id", "aria-label"];
300
+ //#endregion
301
+ //#region src/web/BaseHoverCard.vue
302
+ var BaseHoverCard_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
303
+ __name: "BaseHoverCard",
304
+ props: {
305
+ label: {},
306
+ openDelay: { default: 300 },
307
+ closeDelay: { default: 200 },
308
+ placement: { default: "bottom" }
309
+ },
310
+ setup(__props) {
311
+ const id = useId();
312
+ const open = ref(false);
313
+ let timer;
314
+ function clear() {
315
+ if (timer !== void 0) clearTimeout(timer);
316
+ timer = void 0;
317
+ }
318
+ function schedule(next, delay) {
319
+ clear();
320
+ if (open.value === next) return;
321
+ timer = setTimeout(() => {
322
+ open.value = next;
323
+ timer = void 0;
324
+ }, delay);
325
+ }
326
+ const show = () => schedule(true, __props.openDelay);
327
+ const hide = () => schedule(false, __props.closeDelay);
328
+ /** Focus is deliberate, so it skips the wait a sweeping pointer needs. */
329
+ function showNow() {
330
+ clear();
331
+ open.value = true;
332
+ }
333
+ function onKeydown(event) {
334
+ if (event.key !== "Escape" || !open.value) return;
335
+ event.stopPropagation();
336
+ clear();
337
+ open.value = false;
338
+ }
339
+ function onFocusOut(event) {
340
+ const next = event.relatedTarget;
341
+ if (next instanceof Node && event.currentTarget.contains(next)) return;
342
+ clear();
343
+ open.value = false;
344
+ }
345
+ const triggerProps = computed(() => ({
346
+ "aria-expanded": open.value,
347
+ "aria-controls": open.value ? id : void 0
348
+ }));
349
+ onBeforeUnmount(clear);
350
+ return (_ctx, _cache) => {
351
+ return openBlock(), createElementBlock("div", {
352
+ class: "rk-hovercard",
353
+ onPointerenter: show,
354
+ onPointerleave: hide,
355
+ onFocusin: showNow,
356
+ onFocusout: onFocusOut,
357
+ onKeydown
358
+ }, [renderSlot(_ctx.$slots, "default", { props: triggerProps.value }, void 0, true), open.value ? (openBlock(), createElementBlock("div", {
359
+ key: 0,
360
+ id: unref(id),
361
+ class: normalizeClass(["rk-hovercard-panel surface-raised", `is-${__props.placement}`]),
362
+ role: "group",
363
+ "aria-label": __props.label
364
+ }, [renderSlot(_ctx.$slots, "card", {}, void 0, true)], 10, _hoisted_1$14)) : createCommentVNode("", true)], 32);
365
+ };
366
+ }
367
+ }), [["__scopeId", "data-v-70c09916"]]);
368
+ //#endregion
369
+ //#region src/composables/use-dialog-shell.ts
370
+ /**
371
+ * What every modal surface has to do, in one place.
372
+ *
373
+ * A dialog, a drawer and anything else that takes the whole page share a
374
+ * list that is easy to get nearly right: trap Tab, stop Escape, make the
375
+ * rest of the page inert, stop it scrolling underneath, and hand focus back
376
+ * to whatever opened it. Each of those has an order that matters, and the
377
+ * orders are not obvious — releasing `inert` *after* restoring focus drops
378
+ * it on the body, because an inert element cannot take focus. That was
379
+ * written once, correctly, in `BaseModal`; a drawer that copied it would be
380
+ * a second copy to keep correct.
381
+ *
382
+ * The Tab wrap has to be done by hand: the browser's own Tab order is the
383
+ * whole document, and a dialog is only part of it. `inert` is what also
384
+ * stops a screen reader's virtual cursor, which walks straight past a
385
+ * keydown handler.
386
+ */
387
+ var FOCUSABLE$1 = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
388
+ function useDialogShell(open, panel, { dismissible = () => true, onClose }) {
389
+ let releaseInert = null;
390
+ let restoreTo = null;
391
+ const focusable = () => panel.value ? Array.from(panel.value.querySelectorAll(FOCUSABLE$1)) : [];
392
+ function onKeydown(event) {
393
+ if (event.key === "Escape" && dismissible()) {
394
+ event.stopPropagation();
395
+ onClose();
396
+ return;
397
+ }
398
+ if (event.key !== "Tab") return;
399
+ const items = focusable();
400
+ if (items.length === 0) return event.preventDefault();
401
+ const first = items[0];
402
+ const last = items[items.length - 1];
403
+ const active = document.activeElement;
404
+ if (event.shiftKey && (active === first || !panel.value?.contains(active))) {
405
+ event.preventDefault();
406
+ last.focus();
407
+ } else if (!event.shiftKey && active === last) {
408
+ event.preventDefault();
409
+ first.focus();
410
+ }
411
+ }
412
+ watch(open, async (isOpen) => {
413
+ if (isOpen) {
414
+ restoreTo = document.activeElement;
415
+ document.body.style.overflow = "hidden";
416
+ await nextTick();
417
+ if (panel.value) releaseInert = inertOutside(panel.value);
418
+ (focusable()[0] ?? panel.value)?.focus();
419
+ } else {
420
+ document.body.style.overflow = "";
421
+ releaseInert?.();
422
+ releaseInert = null;
423
+ restoreTo?.focus();
424
+ restoreTo = null;
425
+ }
426
+ });
427
+ onBeforeUnmount(() => {
428
+ if (open.value) document.body.style.overflow = "";
429
+ releaseInert?.();
430
+ });
431
+ return {
432
+ onKeydown,
433
+ focusable
434
+ };
435
+ }
436
+ //#endregion
437
+ //#region src/web/BaseDrawer.vue?vue&type=script&setup=true&lang.ts
438
+ var _hoisted_1$13 = ["aria-label"];
439
+ var _hoisted_2$10 = { class: "rk-drawer-head" };
440
+ var _hoisted_3$9 = { class: "rk-drawer-title" };
441
+ var _hoisted_4$7 = { class: "rk-drawer-body" };
442
+ var _hoisted_5$6 = {
443
+ key: 0,
444
+ class: "rk-drawer-actions"
445
+ };
446
+ //#endregion
447
+ //#region src/web/BaseDrawer.vue
448
+ var BaseDrawer_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
449
+ __name: "BaseDrawer",
450
+ props: /*@__PURE__*/ mergeModels({
451
+ title: {},
452
+ closeLabel: {},
453
+ side: { default: "end" },
454
+ size: { default: "22rem" },
455
+ dismissible: {
456
+ type: Boolean,
457
+ default: true
458
+ }
459
+ }, {
460
+ "modelValue": {
461
+ type: Boolean,
462
+ required: true
463
+ },
464
+ "modelModifiers": {}
465
+ }),
466
+ emits: ["update:modelValue"],
467
+ setup(__props) {
468
+ const open = useModel(__props, "modelValue");
469
+ const panel = ref(null);
470
+ function close() {
471
+ open.value = false;
472
+ }
473
+ const { onKeydown } = useDialogShell(open, panel, {
474
+ dismissible: () => __props.dismissible,
475
+ onClose: close
476
+ });
477
+ const extent = (horizontal) => horizontal ? { width: __props.size } : { height: __props.size };
478
+ return (_ctx, _cache) => {
479
+ return openBlock(), createBlock(Teleport, { to: "body" }, [createVNode(Transition, { name: `rk-drawer-${__props.side}` }, {
480
+ default: withCtx(() => [open.value ? (openBlock(), createElementBlock("div", {
481
+ key: 0,
482
+ class: "rk-drawer-scrim",
483
+ onKeydown: _cache[1] || (_cache[1] = (...args) => unref(onKeydown) && unref(onKeydown)(...args))
484
+ }, [createElementVNode("div", {
485
+ class: "rk-drawer-veil",
486
+ onClick: _cache[0] || (_cache[0] = ($event) => __props.dismissible && close())
487
+ }), createElementVNode("section", {
488
+ ref_key: "panel",
489
+ ref: panel,
490
+ class: normalizeClass(["rk-drawer-panel surface-overlay", `is-${__props.side}`]),
491
+ style: normalizeStyle(extent(__props.side === "start" || __props.side === "end")),
492
+ role: "dialog",
493
+ "aria-modal": "true",
494
+ "aria-label": __props.title,
495
+ tabindex: "-1"
496
+ }, [
497
+ createElementVNode("header", _hoisted_2$10, [createElementVNode("h2", _hoisted_3$9, toDisplayString(__props.title), 1), __props.dismissible ? (openBlock(), createBlock(BaseButton_default, {
498
+ key: 0,
499
+ variant: "ghost",
500
+ size: "sm",
501
+ icon: "",
502
+ "aria-label": __props.closeLabel,
503
+ onClick: close
504
+ }, {
505
+ default: withCtx(() => [createVNode(unref(X), {
506
+ class: "size-4",
507
+ "aria-hidden": "true"
508
+ })]),
509
+ _: 1
510
+ }, 8, ["aria-label"])) : createCommentVNode("", true)]),
511
+ createElementVNode("div", _hoisted_4$7, [renderSlot(_ctx.$slots, "default", {}, void 0, true)]),
512
+ _ctx.$slots.actions ? (openBlock(), createElementBlock("footer", _hoisted_5$6, [renderSlot(_ctx.$slots, "actions", {}, void 0, true)])) : createCommentVNode("", true)
513
+ ], 14, _hoisted_1$13)], 32)) : createCommentVNode("", true)]),
514
+ _: 3
515
+ }, 8, ["name"])]);
516
+ };
517
+ }
518
+ }), [["__scopeId", "data-v-de2cccb9"]]);
519
+ //#endregion
157
520
  //#region src/web/BaseModal.vue?vue&type=script&setup=true&lang.ts
158
521
  var _hoisted_1$12 = ["role", "aria-label"];
159
522
  var _hoisted_2$9 = { class: "rk-modal-head" };
@@ -164,35 +527,6 @@ var _hoisted_6$4 = {
164
527
  key: 0,
165
528
  class: "rk-modal-actions"
166
529
  };
167
- /**
168
- * A dialog that arrives from nowhere.
169
- *
170
- * Not `BaseSheet` with different padding. A sheet slides up from the bottom
171
- * edge, is dismissed by dragging it back down, and belongs to a thumb; a modal
172
- * appears in the middle of what you were reading and is dismissed by leaving
173
- * it. They are two answers to two questions and merging them would give a
174
- * component that is wrong on a phone and wrong on a desktop.
175
- *
176
- * ## The parts that are easy to get wrong
177
- *
178
- * This is why it exists rather than being written per dialog, which is what the
179
- * one wide consumer was doing in two places. None of the following is visible
180
- * on screen when it is missing:
181
- *
182
- * - **Focus moves in and comes back.** Opening without moving focus leaves a
183
- * keyboard user behind the dialog, operating a page they cannot see. Closing
184
- * without restoring it drops them at the top of the document.
185
- * - **Tab does not leave.** A dialog you can Tab out of is a dialog that is
186
- * modal only to somebody using a mouse.
187
- * - **Escape closes.** Every dialog in every application does this.
188
- * - **The page underneath does not scroll.** Otherwise dismissing the dialog
189
- * returns you somewhere else.
190
- * - **The backdrop closes it, the panel does not.** A click that starts inside
191
- * the panel and ends on the backdrop is not a click on the backdrop, which is
192
- * why this listens for a press on the backdrop itself rather than any click
193
- * that reaches it.
194
- */
195
- var FOCUSABLE$1 = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
196
530
  //#endregion
197
531
  //#region src/web/BaseModal.vue
198
532
  var BaseModal_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -216,60 +550,17 @@ var BaseModal_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
216
550
  setup(__props) {
217
551
  const open = useModel(__props, "modelValue");
218
552
  const panel = ref(null);
219
- /** Who had focus before this opened, so it can be given back. */
220
- let restoreTo = null;
221
- /** Gives the page behind back; set while open. */
222
- let releaseInert = null;
223
- function focusable() {
224
- if (!panel.value) return [];
225
- return Array.from(panel.value.querySelectorAll(FOCUSABLE$1));
226
- }
227
- function onKeydown(event) {
228
- if (event.key === "Escape" && __props.dismissible) {
229
- event.stopPropagation();
230
- open.value = false;
231
- return;
232
- }
233
- if (event.key !== "Tab") return;
234
- const items = focusable();
235
- if (items.length === 0) return event.preventDefault();
236
- const first = items[0];
237
- const last = items[items.length - 1];
238
- const active = document.activeElement;
239
- if (event.shiftKey && (active === first || !panel.value?.contains(active))) {
240
- event.preventDefault();
241
- last.focus();
242
- } else if (!event.shiftKey && active === last) {
243
- event.preventDefault();
244
- first.focus();
245
- }
246
- }
247
- watch(open, async (isOpen) => {
248
- if (isOpen) {
249
- restoreTo = document.activeElement;
250
- document.body.style.overflow = "hidden";
251
- await nextTick();
252
- if (panel.value) releaseInert = inertOutside(panel.value);
253
- (focusable()[0] ?? panel.value)?.focus();
254
- } else {
255
- document.body.style.overflow = "";
256
- releaseInert?.();
257
- releaseInert = null;
258
- restoreTo?.focus();
259
- restoreTo = null;
260
- }
261
- });
262
- onBeforeUnmount(() => {
263
- if (open.value) document.body.style.overflow = "";
264
- releaseInert?.();
553
+ const { onKeydown } = useDialogShell(open, panel, {
554
+ dismissible: () => __props.dismissible,
555
+ onClose: () => open.value = false
265
556
  });
266
557
  return (_ctx, _cache) => {
267
558
  return openBlock(), createBlock(Teleport, { to: "body" }, [createVNode(Transition, { name: "rk-modal" }, {
268
559
  default: withCtx(() => [open.value ? (openBlock(), createElementBlock("div", {
269
560
  key: 0,
270
561
  class: "rk-modal-scrim",
271
- onKeydown,
272
- onMousedown: _cache[1] || (_cache[1] = withModifiers(($event) => __props.dismissible && (open.value = false), ["self"]))
562
+ onKeydown: _cache[1] || (_cache[1] = (...args) => unref(onKeydown) && unref(onKeydown)(...args)),
563
+ onMousedown: _cache[2] || (_cache[2] = withModifiers(($event) => __props.dismissible && (open.value = false), ["self"]))
273
564
  }, [createElementVNode("div", {
274
565
  ref_key: "panel",
275
566
  ref: panel,
@@ -285,7 +576,7 @@ var BaseModal_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
285
576
  class: "rk-modal-close",
286
577
  "aria-label": __props.closeLabel,
287
578
  onClick: _cache[0] || (_cache[0] = ($event) => open.value = false)
288
- }, [..._cache[2] || (_cache[2] = [createElementVNode("svg", {
579
+ }, [..._cache[3] || (_cache[3] = [createElementVNode("svg", {
289
580
  viewBox: "0 0 24 24",
290
581
  fill: "none",
291
582
  stroke: "currentColor",
@@ -301,7 +592,7 @@ var BaseModal_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
301
592
  })]);
302
593
  };
303
594
  }
304
- }), [["__scopeId", "data-v-61956691"]]);
595
+ }), [["__scopeId", "data-v-92ea084c"]]);
305
596
  //#endregion
306
597
  //#region src/web/BasePagination.vue?vue&type=script&setup=true&lang.ts
307
598
  var _hoisted_1$11 = ["aria-label"];
@@ -1689,6 +1980,6 @@ var NavLinks_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PUR
1689
1980
  }
1690
1981
  }), [["__scopeId", "data-v-52e5d553"]]);
1691
1982
  //#endregion
1692
- export { BaseAccordion_default as BaseAccordion, BaseBreadcrumb_default as BaseBreadcrumb, BaseDisclosure_default as BaseDisclosure, BaseModal_default as BaseModal, BasePagination_default as BasePagination, BaseSplitter_default as BaseSplitter, BaseTabs_default as BaseTabs, BaseToolbar_default as BaseToolbar, BaseTooltip_default as BaseTooltip, BaseTree_default as BaseTree, CommandMenu_default as CommandMenu, DataTable_default as DataTable, MegaMenu_default as MegaMenu, NavLinks_default as NavLinks, ResponsiveDialog_default as ResponsiveDialog, TransferList_default as TransferList };
1983
+ export { BaseAccordion_default as BaseAccordion, BaseBreadcrumb_default as BaseBreadcrumb, BaseContextMenu_default as BaseContextMenu, BaseDisclosure_default as BaseDisclosure, BaseDrawer_default as BaseDrawer, BaseHoverCard_default as BaseHoverCard, BaseModal_default as BaseModal, BasePagination_default as BasePagination, BaseSplitter_default as BaseSplitter, BaseTabs_default as BaseTabs, BaseToolbar_default as BaseToolbar, BaseTooltip_default as BaseTooltip, BaseTree_default as BaseTree, CommandMenu_default as CommandMenu, DataTable_default as DataTable, MegaMenu_default as MegaMenu, NavLinks_default as NavLinks, ResponsiveDialog_default as ResponsiveDialog, TransferList_default as TransferList };
1693
1984
 
1694
1985
  //# sourceMappingURL=web.js.map