@hina-ui/vue 1.7.13 → 1.7.14

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 (68) hide show
  1. package/dist/index.js +1295 -283
  2. package/dist/index.js.map +1 -1
  3. package/dist/shared/lib/thumbhash.ts +12 -0
  4. package/dist/shared/lib/tour-engine.ts +721 -0
  5. package/dist/shared/lib/tour.ts +202 -24
  6. package/dist/shared/locale/en-US.ts +1 -0
  7. package/dist/shared/locale/ja-JP.ts +1 -0
  8. package/dist/shared/locale/types.ts +1 -0
  9. package/dist/shared/locale/zh-CN.ts +1 -0
  10. package/dist/shared/primitives/dialog/index.ts +2 -2
  11. package/dist/shared/primitives/dismissable-layer/index.ts +48 -1
  12. package/dist/shared/primitives/focus-scope/index.ts +5 -3
  13. package/dist/shared/styles/semantic.css +1 -0
  14. package/dist/shared/styles/tour.css +107 -2
  15. package/dist/shared/variants/image.ts +28 -0
  16. package/dist/shared/variants/tour.ts +22 -4
  17. package/dist/types/shared/src/lib/thumbhash.d.ts +2 -0
  18. package/dist/types/shared/src/lib/thumbhash.d.ts.map +1 -0
  19. package/dist/types/shared/src/lib/tour-engine.d.ts +47 -0
  20. package/dist/types/shared/src/lib/tour-engine.d.ts.map +1 -0
  21. package/dist/types/shared/src/lib/tour.d.ts +65 -9
  22. package/dist/types/shared/src/lib/tour.d.ts.map +1 -1
  23. package/dist/types/shared/src/locale/en-US.d.ts.map +1 -1
  24. package/dist/types/shared/src/locale/ja-JP.d.ts.map +1 -1
  25. package/dist/types/shared/src/locale/types.d.ts +1 -0
  26. package/dist/types/shared/src/locale/types.d.ts.map +1 -1
  27. package/dist/types/shared/src/locale/zh-CN.d.ts.map +1 -1
  28. package/dist/types/shared/src/primitives/dialog/index.d.ts +1 -1
  29. package/dist/types/shared/src/primitives/dialog/index.d.ts.map +1 -1
  30. package/dist/types/shared/src/primitives/dismissable-layer/index.d.ts +1 -0
  31. package/dist/types/shared/src/primitives/dismissable-layer/index.d.ts.map +1 -1
  32. package/dist/types/shared/src/primitives/focus-scope/index.d.ts.map +1 -1
  33. package/dist/types/shared/src/variants/image.d.ts +35 -0
  34. package/dist/types/shared/src/variants/image.d.ts.map +1 -1
  35. package/dist/types/shared/src/variants/tour.d.ts +9 -4
  36. package/dist/types/shared/src/variants/tour.d.ts.map +1 -1
  37. package/dist/types/vue/src/components/button/Button.vue.d.ts.map +1 -1
  38. package/dist/types/vue/src/components/dialog/Dialog.vue.d.ts +3 -0
  39. package/dist/types/vue/src/components/dialog/Dialog.vue.d.ts.map +1 -1
  40. package/dist/types/vue/src/components/drawer/Drawer.vue.d.ts +3 -0
  41. package/dist/types/vue/src/components/drawer/Drawer.vue.d.ts.map +1 -1
  42. package/dist/types/vue/src/components/image/Image.vue.d.ts +1 -0
  43. package/dist/types/vue/src/components/image/Image.vue.d.ts.map +1 -1
  44. package/dist/types/vue/src/components/image/composables/useImage.d.ts +2 -0
  45. package/dist/types/vue/src/components/image/composables/useImage.d.ts.map +1 -1
  46. package/dist/types/vue/src/components/overlay-branch/OverlayBranch.vue.d.ts +17 -0
  47. package/dist/types/vue/src/components/overlay-branch/OverlayBranch.vue.d.ts.map +1 -0
  48. package/dist/types/vue/src/components/sheet/Sheet.vue.d.ts +3 -0
  49. package/dist/types/vue/src/components/sheet/Sheet.vue.d.ts.map +1 -1
  50. package/dist/types/vue/src/components/tour/Tour.vue.d.ts +10 -1
  51. package/dist/types/vue/src/components/tour/Tour.vue.d.ts.map +1 -1
  52. package/dist/types/vue/src/components/tour/types.d.ts +9 -3
  53. package/dist/types/vue/src/components/tour/types.d.ts.map +1 -1
  54. package/dist/types/vue/src/index.d.ts +2 -1
  55. package/dist/types/vue/src/index.d.ts.map +1 -1
  56. package/dist/types/vue/src/primitives/dismissable-layer/DismissableLayerBranch.d.ts.map +1 -1
  57. package/package.json +2 -1
  58. package/src/components/button/Button.vue +1 -1
  59. package/src/components/dialog/Dialog.vue +14 -1
  60. package/src/components/drawer/Drawer.vue +14 -1
  61. package/src/components/image/Image.vue +58 -24
  62. package/src/components/image/composables/useImage.ts +46 -21
  63. package/src/components/overlay-branch/OverlayBranch.vue +14 -0
  64. package/src/components/sheet/Sheet.vue +14 -1
  65. package/src/components/tour/Tour.vue +302 -141
  66. package/src/components/tour/types.ts +33 -2
  67. package/src/index.ts +11 -0
  68. package/src/primitives/dismissable-layer/DismissableLayerBranch.ts +9 -18
package/dist/index.js CHANGED
@@ -5,9 +5,10 @@ import { Comment, Fragment, Teleport, Text, Transition, camelize, cloneVNode, co
5
5
  import { createEventHook, createSharedComposable, defaultDocument, isClient, onKeyStroke, reactiveOmit, refAutoReset, syncRef, tryOnBeforeUnmount, tryOnScopeDispose, unrefElement, useActiveElement, useDebounceFn, useDocumentVisibility, useElementBounding, useEventListener, useFocusWithin, useIntersectionObserver, useIntervalFn, useMediaQuery, useMounted, useMutationObserver, usePreferredReducedMotion, useRafFn, useResizeObserver, useTimeout, useTimeoutFn, useVModel, useWindowSize } from "@vueuse/core";
6
6
  import { arrow, autoUpdate, flip, hide, limitShift, offset, shift, size } from "@floating-ui/dom";
7
7
  import { autoUpdate as autoUpdate$1, useFloating } from "@floating-ui/vue";
8
- import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, CalendarClock, CalendarDays, CalendarRange, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ChevronsLeft, ChevronsRight, ChevronsUpDown, CircleAlert, CircleCheck, CircleX, Copy, Download, Eye, EyeOff, File, GripVertical, Inbox, Info, LayoutGrid, Lightbulb, List, Megaphone, Minus, MoreHorizontal, PanelLeft, Pause, Pencil, Play, QrCode, RefreshCw, RotateCw, Scan, Search, Shrink, Star, TrendingDown, TrendingUp, TriangleAlert, Upload, User, X, ZoomIn, ZoomOut } from "@lucide/vue";
9
8
  import { hideOthers } from "aria-hidden";
9
+ import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, CalendarClock, CalendarDays, CalendarRange, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ChevronsLeft, ChevronsRight, ChevronsUpDown, CircleAlert, CircleCheck, CircleX, Copy, Download, Eye, EyeOff, File, GripVertical, Inbox, Info, LayoutGrid, Lightbulb, List, Megaphone, Minus, MoreHorizontal, PanelLeft, Pause, Pencil, Play, QrCode, RefreshCw, RotateCcw, RotateCw, Scan, Search, Shrink, Star, TrendingDown, TrendingUp, TriangleAlert, Upload, User, X, ZoomIn, ZoomOut } from "@lucide/vue";
10
10
  import { Motion, animate, useMotionValue, useTransform } from "motion-v";
11
+ import { thumbHashToDataURL } from "thumbhash";
11
12
  import { defaultRangeExtractor, measureElement, observeElementRect, useVirtualizer } from "@tanstack/vue-virtual";
12
13
  import { NumberFormatter, NumberParser } from "@internationalized/number";
13
14
  import { CalendarDate, CalendarDateTime, DateFormatter, Time, ZonedDateTime, createCalendar, endOfMonth, endOfYear, getDayOfWeek, getLocalTimeZone, isEqualDay, isEqualMonth, isSameDay, isSameMonth, isToday, parseDate, parseDateTime, parseTime, startOfMonth, startOfYear, toCalendar, toCalendarDateTime, today } from "@internationalized/date";
@@ -175,6 +176,7 @@ var zhCN = {
175
176
  next: "下一步",
176
177
  finish: "完成",
177
178
  skip: "跳过引导",
179
+ replay: "重新演示",
178
180
  progress: (step, total) => `${step} / ${total}`,
179
181
  beacon: (step, title) => title ? `查看第 ${step} 步:${title}` : `查看第 ${step} 步`
180
182
  },
@@ -388,6 +390,7 @@ var enUS = {
388
390
  next: "Next",
389
391
  finish: "Done",
390
392
  skip: "Skip tour",
393
+ replay: "Replay",
391
394
  progress: (step, total) => `${step} / ${total}`,
392
395
  beacon: (step, title) => title ? `Open step ${step}: ${title}` : `Open step ${step}`
393
396
  },
@@ -601,6 +604,7 @@ var jaJP = {
601
604
  next: "次へ",
602
605
  finish: "完了",
603
606
  skip: "ガイドをスキップ",
607
+ replay: "もう一度再生",
604
608
  progress: (step, total) => `${step} / ${total}`,
605
609
  beacon: (step, title) => title ? `ステップ ${step} を開く:${title}` : `ステップ ${step} を開く`
606
610
  },
@@ -1166,7 +1170,7 @@ var spinner = tv({
1166
1170
  });
1167
1171
  //#endregion
1168
1172
  //#region src/components/spinner/Spinner.vue?vue&type=script&setup=true&lang.ts
1169
- var _hoisted_1$133 = ["aria-label"];
1173
+ var _hoisted_1$132 = ["aria-label"];
1170
1174
  //#endregion
1171
1175
  //#region src/components/spinner/Spinner.vue
1172
1176
  var Spinner_default = /* @__PURE__ */ defineComponent({
@@ -1186,13 +1190,13 @@ var Spinner_default = /* @__PURE__ */ defineComponent({
1186
1190
  "aria-label": props.label ?? unref(t).common.loading,
1187
1191
  class: unref(cn)(unref(spinner)({ size: props.size })),
1188
1192
  style: { animation: "hn-spin var(--hn-spin-duration) var(--hn-ease-linear) infinite" }
1189
- }), null, 16, _hoisted_1$133);
1193
+ }), null, 16, _hoisted_1$132);
1190
1194
  };
1191
1195
  }
1192
1196
  });
1193
1197
  //#endregion
1194
1198
  //#region src/components/button/IconSlot.vue?vue&type=script&setup=true&lang.ts
1195
- var _hoisted_1$132 = {
1199
+ var _hoisted_1$131 = {
1196
1200
  key: 0,
1197
1201
  "aria-hidden": "true",
1198
1202
  class: "absolute inset-0 inline-flex items-center justify-center"
@@ -1216,7 +1220,7 @@ var IconSlot_default$1 = /* @__PURE__ */ defineComponent({
1216
1220
  "leave-active-class": "hn-transition",
1217
1221
  "leave-to-class": "scale-90 opacity-0"
1218
1222
  }, {
1219
- default: withCtx(() => [props.swapped ? (openBlock(), createElementBlock("span", _hoisted_1$132, [createVNode(Spinner_default, { size: props.spinnerSize }, null, 8, ["size"])])) : createCommentVNode("", true)]),
1223
+ default: withCtx(() => [props.swapped ? (openBlock(), createElementBlock("span", _hoisted_1$131, [createVNode(Spinner_default, { size: props.spinnerSize }, null, 8, ["size"])])) : createCommentVNode("", true)]),
1220
1224
  _: 1
1221
1225
  })], 2);
1222
1226
  };
@@ -1440,7 +1444,7 @@ function useRipple(container, surface, isDisabled) {
1440
1444
  }
1441
1445
  //#endregion
1442
1446
  //#region src/components/ripple/Ripple.vue?vue&type=script&setup=true&lang.ts
1443
- var _hoisted_1$131 = ["data-pressed"];
1447
+ var _hoisted_1$130 = ["data-pressed"];
1444
1448
  //#endregion
1445
1449
  //#region src/components/ripple/Ripple.vue
1446
1450
  var Ripple_default = /* @__PURE__ */ defineComponent({
@@ -1463,7 +1467,7 @@ var Ripple_default = /* @__PURE__ */ defineComponent({
1463
1467
  ref: surface,
1464
1468
  class: "hn-ripple-surface",
1465
1469
  "data-pressed": unref(pressed) ? "" : void 0
1466
- }, null, 8, _hoisted_1$131)], 512);
1470
+ }, null, 8, _hoisted_1$130)], 512);
1467
1471
  };
1468
1472
  }
1469
1473
  });
@@ -1526,7 +1530,7 @@ var Primitive = defineComponent({
1526
1530
  });
1527
1531
  //#endregion
1528
1532
  //#region src/components/button/Button.vue?vue&type=script&setup=true&lang.ts
1529
- var _hoisted_1$130 = {
1533
+ var _hoisted_1$129 = {
1530
1534
  key: 0,
1531
1535
  "aria-hidden": "true",
1532
1536
  class: "absolute inset-0 flex items-center justify-center"
@@ -1616,7 +1620,7 @@ var Button_default = /* @__PURE__ */ defineComponent({
1616
1620
  ])) : createCommentVNode("", true),
1617
1621
  unref(slots).default ? (openBlock(), createElementBlock("span", {
1618
1622
  key: 2,
1619
- class: normalizeClass(["hn-transition inline-flex items-center gap-[var(--hn-control-gap)]", props.loading && spinnerAt.value === "center" ? "opacity-0" : "opacity-100"])
1623
+ class: normalizeClass(["hn-transition inline-flex min-w-0 items-center gap-[var(--hn-control-gap)]", props.loading && spinnerAt.value === "center" ? "opacity-0" : "opacity-100"])
1620
1624
  }, [renderSlot(_ctx.$slots, "default")], 2)) : createCommentVNode("", true),
1621
1625
  unref(slots).trailing ? (openBlock(), createBlock(IconSlot_default$1, {
1622
1626
  key: 3,
@@ -1637,7 +1641,7 @@ var Button_default = /* @__PURE__ */ defineComponent({
1637
1641
  "leave-active-class": "hn-transition",
1638
1642
  "leave-to-class": "opacity-0"
1639
1643
  }, {
1640
- default: withCtx(() => [props.loading && spinnerAt.value === "center" ? (openBlock(), createElementBlock("span", _hoisted_1$130, [createVNode(Spinner_default, { size: spinnerSize.value }, null, 8, ["size"])])) : createCommentVNode("", true)]),
1644
+ default: withCtx(() => [props.loading && spinnerAt.value === "center" ? (openBlock(), createElementBlock("span", _hoisted_1$129, [createVNode(Spinner_default, { size: spinnerSize.value }, null, 8, ["size"])])) : createCommentVNode("", true)]),
1641
1645
  _: 1
1642
1646
  })
1643
1647
  ], 64))]),
@@ -2542,11 +2546,28 @@ function addLayer(element) {
2542
2546
  if (layers.delete(element)) changed();
2543
2547
  };
2544
2548
  }
2549
+ var branchInline = /* @__PURE__ */ new Map();
2550
+ function syncBranchPointerEvents() {
2551
+ const list = [...branches];
2552
+ for (const branch of list) branch.style.pointerEvents = branchInline.get(branch) ?? "";
2553
+ if (blocking.size === 0 || list.length === 0) return;
2554
+ const body = list[0].ownerDocument.body;
2555
+ const blocked = body.style.pointerEvents;
2556
+ body.style.pointerEvents = originalBodyPointerEvents ?? "";
2557
+ const natural = list.map((branch) => getComputedStyle(branch).pointerEvents);
2558
+ body.style.pointerEvents = blocked;
2559
+ list.forEach((branch, index) => branch.style.pointerEvents = natural[index]);
2560
+ }
2545
2561
  function addBranch(element) {
2562
+ if (!branches.has(element)) branchInline.set(element, element.style.pointerEvents);
2546
2563
  branches.add(element);
2564
+ syncBranchPointerEvents();
2547
2565
  changed();
2548
2566
  return () => {
2549
- if (branches.delete(element)) changed();
2567
+ if (!branches.delete(element)) return;
2568
+ element.style.pointerEvents = branchInline.get(element) ?? "";
2569
+ branchInline.delete(element);
2570
+ changed();
2550
2571
  };
2551
2572
  }
2552
2573
  function blockOutsidePointerEvents(element) {
@@ -2556,16 +2577,19 @@ function blockOutsidePointerEvents(element) {
2556
2577
  body.style.pointerEvents = "none";
2557
2578
  }
2558
2579
  blocking.add(element);
2580
+ syncBranchPointerEvents();
2559
2581
  changed();
2560
2582
  return () => {
2561
2583
  if (!blocking.delete(element)) return;
2562
2584
  if (blocking.size === 0 && originalBodyPointerEvents != null) body.style.pointerEvents = originalBodyPointerEvents;
2585
+ syncBranchPointerEvents();
2563
2586
  changed();
2564
2587
  };
2565
2588
  }
2566
2589
  function releaseLayer(element) {
2567
2590
  const removed = layers.delete(element);
2568
2591
  const unblocked = blocking.delete(element);
2592
+ if (unblocked) syncBranchPointerEvents();
2569
2593
  if (removed || unblocked) changed();
2570
2594
  }
2571
2595
  function blockingLayerCount() {
@@ -2581,12 +2605,34 @@ function bodyPointerEventsDisabled() {
2581
2605
  return blocking.size > 0;
2582
2606
  }
2583
2607
  function pointerEventsEnabled(element) {
2608
+ if (inBranch(element ?? null)) return true;
2584
2609
  const highest = [...blocking].at(-1);
2585
2610
  return layerIndex(element) >= (highest ? [...layers].indexOf(highest) : -1);
2586
2611
  }
2587
2612
  function inBranch(target) {
2588
2613
  return [...branches].some((branch) => branch.contains(target));
2589
2614
  }
2615
+ function hideOutsideLayers(targets) {
2616
+ const connected = () => [...branches].filter((branch) => branch.isConnected);
2617
+ let kept = connected();
2618
+ const hide = () => {
2619
+ const visible = [...targets.filter((target) => target.isConnected), ...kept];
2620
+ return visible.length ? hideOthers(visible) : () => {};
2621
+ };
2622
+ let undo = hide();
2623
+ const stop = subscribeLayers(() => {
2624
+ const next = connected();
2625
+ if (next.length === kept.length && next.every((branch, index) => branch === kept[index])) return;
2626
+ kept = next;
2627
+ const previous = undo;
2628
+ undo = hide();
2629
+ previous();
2630
+ });
2631
+ return () => {
2632
+ stop();
2633
+ undo();
2634
+ };
2635
+ }
2590
2636
  function isLayerExist(layer, target) {
2591
2637
  if (!(target instanceof Element)) return false;
2592
2638
  const targetLayer = target.closest("[data-dismissable-layer]");
@@ -2882,19 +2928,19 @@ function trapFocus(container, scope) {
2882
2928
  if (scope.paused) return;
2883
2929
  const target = event.target;
2884
2930
  if (container.contains(target)) lastFocused = target;
2885
- else focus(lastFocused, { select: true });
2931
+ else if (!inBranch(target)) focus(lastFocused, { select: true });
2886
2932
  };
2887
2933
  const handleFocusOut = (event) => {
2888
2934
  if (scope.paused) return;
2889
2935
  const related = event.relatedTarget;
2890
2936
  if (related === null) return;
2891
- if (!container.contains(related)) focus(lastFocused, { select: true });
2937
+ if (!container.contains(related) && !inBranch(related)) focus(lastFocused, { select: true });
2892
2938
  };
2893
2939
  const handleMutations = (mutations) => {
2894
2940
  if (lastFocused === null) return;
2895
2941
  if (!mutations.some((mutation) => mutation.removedNodes.length > 0)) return;
2896
2942
  const active = getActiveElement$1();
2897
- if (active && container.contains(active)) return;
2943
+ if (active && (container.contains(active) || inBranch(active))) return;
2898
2944
  if (!container.contains(lastFocused)) focus(container);
2899
2945
  };
2900
2946
  document.addEventListener("focusin", handleFocusIn);
@@ -4349,7 +4395,7 @@ function useCopy(text, onCopied, resetAfter = () => COPIED_RESET_MS) {
4349
4395
  }
4350
4396
  //#endregion
4351
4397
  //#region src/components/copy-button/CopyButton.vue?vue&type=script&setup=true&lang.ts
4352
- var _hoisted_1$129 = { class: "relative inline-flex size-[1em]" };
4398
+ var _hoisted_1$128 = { class: "relative inline-flex size-[1em]" };
4353
4399
  //#endregion
4354
4400
  //#region src/components/copy-button/CopyButton.vue
4355
4401
  var CopyButton_default = /* @__PURE__ */ defineComponent({
@@ -4381,7 +4427,7 @@ var CopyButton_default = /* @__PURE__ */ defineComponent({
4381
4427
  class: props.class,
4382
4428
  onClick: unref(copy)
4383
4429
  }), {
4384
- default: withCtx(() => [createElementVNode("span", _hoisted_1$129, [createVNode(Transition, {
4430
+ default: withCtx(() => [createElementVNode("span", _hoisted_1$128, [createVNode(Transition, {
4385
4431
  "enter-active-class": "hn-transition-base",
4386
4432
  "enter-from-class": "scale-90 opacity-0",
4387
4433
  "leave-active-class": "hn-transition",
@@ -4456,7 +4502,7 @@ var buttonGroup = tv({
4456
4502
  });
4457
4503
  //#endregion
4458
4504
  //#region src/components/button-group/ButtonGroup.vue?vue&type=script&setup=true&lang.ts
4459
- var _hoisted_1$128 = ["aria-label", "aria-orientation"];
4505
+ var _hoisted_1$127 = ["aria-label", "aria-orientation"];
4460
4506
  //#endregion
4461
4507
  //#region src/components/button-group/ButtonGroup.vue
4462
4508
  var ButtonGroup_default = /* @__PURE__ */ defineComponent({
@@ -4487,7 +4533,7 @@ var ButtonGroup_default = /* @__PURE__ */ defineComponent({
4487
4533
  block: props.block,
4488
4534
  divider: props.divider
4489
4535
  }), props.class))
4490
- }, [renderSlot(_ctx.$slots, "default")], 10, _hoisted_1$128);
4536
+ }, [renderSlot(_ctx.$slots, "default")], 10, _hoisted_1$127);
4491
4537
  };
4492
4538
  }
4493
4539
  });
@@ -4714,7 +4760,7 @@ function floatButtonOffset(offset) {
4714
4760
  }
4715
4761
  //#endregion
4716
4762
  //#region src/components/float-button/FloatButton.vue?vue&type=script&setup=true&lang.ts
4717
- var _hoisted_1$127 = {
4763
+ var _hoisted_1$126 = {
4718
4764
  key: 0,
4719
4765
  class: "min-w-0 truncate"
4720
4766
  };
@@ -4818,7 +4864,7 @@ var FloatButton_default = /* @__PURE__ */ defineComponent({
4818
4864
  }), props.class),
4819
4865
  style: [offset.value, props.style]
4820
4866
  }), createSlots({
4821
- default: withCtx(() => [props.extended ? (openBlock(), createElementBlock("span", _hoisted_1$127, toDisplayString(props.label), 1)) : renderSlot(_ctx.$slots, "default", {}, void 0, void 0, 1)]),
4867
+ default: withCtx(() => [props.extended ? (openBlock(), createElementBlock("span", _hoisted_1$126, toDisplayString(props.label), 1)) : renderSlot(_ctx.$slots, "default", {}, void 0, void 0, 1)]),
4822
4868
  _: 2
4823
4869
  }, [props.extended ? {
4824
4870
  name: "icon",
@@ -6321,7 +6367,7 @@ function hideOutside(element) {
6321
6367
  try {
6322
6368
  insideClosedPopover = !!element.closest("[popover]:not(:popover-open)");
6323
6369
  } catch {}
6324
- return insideClosedPopover ? void 0 : hideOthers(element);
6370
+ return insideClosedPopover ? void 0 : hideOutsideLayers([element]);
6325
6371
  }
6326
6372
  function createNonModalOutsideTracker() {
6327
6373
  let interacted = false;
@@ -7192,7 +7238,7 @@ var splitButton = tv({
7192
7238
  var splitButtonAction = tv({ base: "min-w-0 flex-1 shrink [&>span]:min-w-0" });
7193
7239
  //#endregion
7194
7240
  //#region src/components/split-button/SplitButton.vue?vue&type=script&setup=true&lang.ts
7195
- var _hoisted_1$126 = { class: "min-w-0 truncate" };
7241
+ var _hoisted_1$125 = { class: "min-w-0 truncate" };
7196
7242
  //#endregion
7197
7243
  //#region src/components/split-button/SplitButton.vue
7198
7244
  var SplitButton_default = /* @__PURE__ */ defineComponent({
@@ -7317,7 +7363,7 @@ var SplitButton_default = /* @__PURE__ */ defineComponent({
7317
7363
  onClick: _cache[0] || (_cache[0] = ($event) => emit("click", $event)),
7318
7364
  onKeydown
7319
7365
  }), createSlots({
7320
- default: withCtx(() => [createElementVNode("span", _hoisted_1$126, [renderSlot(_ctx.$slots, "default")])]),
7366
+ default: withCtx(() => [createElementVNode("span", _hoisted_1$125, [renderSlot(_ctx.$slots, "default")])]),
7321
7367
  _: 2
7322
7368
  }, [_ctx.$slots.icon ? {
7323
7369
  name: "icon",
@@ -7631,7 +7677,7 @@ var chipRemove = tv({
7631
7677
  });
7632
7678
  //#endregion
7633
7679
  //#region src/components/chip/IconSlot.vue?vue&type=script&setup=true&lang.ts
7634
- var _hoisted_1$125 = { class: "hn-collapse-body" };
7680
+ var _hoisted_1$124 = { class: "hn-collapse-body" };
7635
7681
  var _hoisted_2$73 = {
7636
7682
  key: 0,
7637
7683
  "aria-hidden": "true",
@@ -7653,7 +7699,7 @@ var IconSlot_default = /* @__PURE__ */ defineComponent({
7653
7699
  return openBlock(), createElementBlock("span", {
7654
7700
  "data-hn-icon": "",
7655
7701
  class: normalizeClass(["hn-collapse-x", props.icon || props.checked ? "hn-collapse-open" : "hn-collapse-closed"])
7656
- }, [createElementVNode("span", _hoisted_1$125, [createElementVNode("span", { class: normalizeClass(unref(chipIcon)({ size: props.size })) }, [props.icon ? (openBlock(), createElementBlock("span", {
7702
+ }, [createElementVNode("span", _hoisted_1$124, [createElementVNode("span", { class: normalizeClass(unref(chipIcon)({ size: props.size })) }, [props.icon ? (openBlock(), createElementBlock("span", {
7657
7703
  key: 0,
7658
7704
  class: normalizeClass(["hn-transition inline-flex items-center justify-center", props.checked ? "scale-90 opacity-0" : "scale-100 opacity-100"])
7659
7705
  }, [renderSlot(_ctx.$slots, "default")], 2)) : createCommentVNode("", true), createVNode(Transition, {
@@ -8383,7 +8429,7 @@ var VisuallyHidden_default = /* @__PURE__ */ defineComponent({
8383
8429
  });
8384
8430
  //#endregion
8385
8431
  //#region src/components/lightbox/LightboxStrip.vue?vue&type=script&setup=true&lang.ts
8386
- var _hoisted_1$124 = [
8432
+ var _hoisted_1$123 = [
8387
8433
  "src",
8388
8434
  "alt",
8389
8435
  "onLoad"
@@ -8450,7 +8496,7 @@ var LightboxStrip_default = /* @__PURE__ */ defineComponent({
8450
8496
  draggable: "false",
8451
8497
  class: "block size-full object-contain",
8452
8498
  onLoad: ($event) => emit("learn", slide.item.id, $event.target)
8453
- }, null, 40, _hoisted_1$124), createVNode(Transition, {
8499
+ }, null, 40, _hoisted_1$123), createVNode(Transition, {
8454
8500
  "enter-active-class": "hn-transition-base",
8455
8501
  "enter-from-class": "opacity-0",
8456
8502
  "leave-active-class": "hn-transition",
@@ -11195,7 +11241,7 @@ function useScrollFocus(host, viewport, options) {
11195
11241
  }
11196
11242
  //#endregion
11197
11243
  //#region src/components/scroll-area/ScrollArea.vue?vue&type=script&setup=true&lang.ts
11198
- var _hoisted_1$123 = ["dir"];
11244
+ var _hoisted_1$122 = ["dir"];
11199
11245
  var _hoisted_2$71 = ["data-visible"];
11200
11246
  var _hoisted_3$39 = ["data-visible"];
11201
11247
  var _hoisted_4$32 = ["data-visible"];
@@ -11309,7 +11355,7 @@ var ScrollArea_default = /* @__PURE__ */ defineComponent({
11309
11355
  "data-visible": unref(showYEnd) ? "" : void 0,
11310
11356
  "aria-hidden": "true"
11311
11357
  }, null, 8, _hoisted_5$25)) : createCommentVNode("", true)
11312
- ], 64)) : createCommentVNode("", true)], 10, _hoisted_1$123);
11358
+ ], 64)) : createCommentVNode("", true)], 10, _hoisted_1$122);
11313
11359
  };
11314
11360
  }
11315
11361
  });
@@ -11367,7 +11413,7 @@ var Highlight_default = /* @__PURE__ */ defineComponent({
11367
11413
  });
11368
11414
  //#endregion
11369
11415
  //#region src/components/lightbox/LightboxThumbs.vue?vue&type=script&setup=true&lang.ts
11370
- var _hoisted_1$122 = {
11416
+ var _hoisted_1$121 = {
11371
11417
  "data-hn-thumbs": "",
11372
11418
  class: "relative isolate flex w-max gap-2 px-4 py-3"
11373
11419
  };
@@ -11412,7 +11458,7 @@ var LightboxThumbs_default = /* @__PURE__ */ defineComponent({
11412
11458
  scrollbar: false,
11413
11459
  class: "max-w-full"
11414
11460
  }, {
11415
- default: withCtx(() => [createElementVNode("div", _hoisted_1$122, [(openBlock(true), createElementBlock(Fragment, null, renderList(props.items, (item, at) => {
11461
+ default: withCtx(() => [createElementVNode("div", _hoisted_1$121, [(openBlock(true), createElementBlock(Fragment, null, renderList(props.items, (item, at) => {
11416
11462
  return openBlock(), createElementBlock("button", {
11417
11463
  key: item.id,
11418
11464
  ref_for: true,
@@ -11445,7 +11491,7 @@ var LightboxThumbs_default = /* @__PURE__ */ defineComponent({
11445
11491
  });
11446
11492
  //#endregion
11447
11493
  //#region src/components/lightbox/LightboxToolbar.vue?vue&type=script&setup=true&lang.ts
11448
- var _hoisted_1$121 = { class: "flex flex-col items-center gap-1 pb-[max(--spacing(3),env(safe-area-inset-bottom))]" };
11494
+ var _hoisted_1$120 = { class: "flex flex-col items-center gap-1 pb-[max(--spacing(3),env(safe-area-inset-bottom))]" };
11449
11495
  var _hoisted_2$69 = { class: "flex items-center gap-1" };
11450
11496
  //#endregion
11451
11497
  //#region src/components/lightbox/LightboxToolbar.vue
@@ -11473,7 +11519,7 @@ var LightboxToolbar_default = /* @__PURE__ */ defineComponent({
11473
11519
  const emit = __emit;
11474
11520
  const t = useUiLocale();
11475
11521
  return (_ctx, _cache) => {
11476
- return openBlock(), createElementBlock("div", _hoisted_1$121, [props.items.length > 1 ? (openBlock(), createBlock(LightboxThumbs_default, {
11522
+ return openBlock(), createElementBlock("div", _hoisted_1$120, [props.items.length > 1 ? (openBlock(), createBlock(LightboxThumbs_default, {
11477
11523
  key: 0,
11478
11524
  items: props.items,
11479
11525
  index: props.index,
@@ -13087,7 +13133,7 @@ async function saveImage(url) {
13087
13133
  }
13088
13134
  //#endregion
13089
13135
  //#region src/components/lightbox/Lightbox.vue?vue&type=script&setup=true&lang.ts
13090
- var _hoisted_1$120 = ["data-hn-phase"];
13136
+ var _hoisted_1$119 = ["data-hn-phase"];
13091
13137
  var _hoisted_2$68 = {
13092
13138
  "aria-hidden": "true",
13093
13139
  class: "pointer-events-none absolute inset-0 isolate"
@@ -13326,7 +13372,7 @@ var Lightbox_default = /* @__PURE__ */ defineComponent({
13326
13372
  "hint",
13327
13373
  "presence"
13328
13374
  ])
13329
- ], 42, _hoisted_1$120)]),
13375
+ ], 42, _hoisted_1$119)]),
13330
13376
  _: 1
13331
13377
  })]),
13332
13378
  _: 1
@@ -13346,6 +13392,7 @@ var image = tv({
13346
13392
  base: "relative z-10 block size-full",
13347
13393
  variants: {
13348
13394
  lazy: { true: "transition-opacity duration-(--hn-duration-base) ease-enter motion-reduce:transition-none" },
13395
+ placeholder: { true: "" },
13349
13396
  fit: {
13350
13397
  cover: "object-cover",
13351
13398
  contain: "object-contain",
@@ -13354,6 +13401,23 @@ var image = tv({
13354
13401
  "scale-down": "object-scale-down"
13355
13402
  }
13356
13403
  },
13404
+ compoundVariants: [{
13405
+ lazy: true,
13406
+ placeholder: true,
13407
+ class: "duration-(--hn-duration-slow) ease-move"
13408
+ }],
13409
+ defaultVariants: { fit: "cover" }
13410
+ });
13411
+ var imageFrame = tv({ base: "relative isolate block size-full" });
13412
+ var imagePlaceholder = tv({
13413
+ base: "bg-center bg-no-repeat",
13414
+ variants: { fit: {
13415
+ cover: "bg-cover",
13416
+ contain: "bg-contain",
13417
+ fill: "bg-size-[100%_100%]",
13418
+ none: "bg-cover",
13419
+ "scale-down": "bg-contain"
13420
+ } },
13357
13421
  defaultVariants: { fit: "cover" }
13358
13422
  });
13359
13423
  //#endregion
@@ -13365,6 +13429,18 @@ function cssTimeToMs(value) {
13365
13429
  return text.endsWith("s") && !text.endsWith("ms") ? amount * 1e3 : amount;
13366
13430
  }
13367
13431
  //#endregion
13432
+ //#region ../shared/src/lib/thumbhash.ts
13433
+ function thumbhashToDataUrl(hash) {
13434
+ let binary;
13435
+ try {
13436
+ binary = atob(hash.trim().replace(/-/g, "+").replace(/_/g, "/"));
13437
+ } catch {
13438
+ return null;
13439
+ }
13440
+ if (binary.length < 5) return null;
13441
+ return thumbHashToDataURL(Uint8Array.from(binary, (char) => char.charCodeAt(0)));
13442
+ }
13443
+ //#endregion
13368
13444
  //#region src/components/image/resolver.ts
13369
13445
  var KEY$2 = Symbol("hn-image-resolver");
13370
13446
  function provideImageResolver(resolver) {
@@ -13405,9 +13481,10 @@ function useImage(props, emit) {
13405
13481
  const primary = computed(() => props.src ? resolve(props.src, "image") : "");
13406
13482
  const fallback = computed(() => props.fallback ? resolve(props.fallback, "image") : "");
13407
13483
  const resolved = computed(() => usingFallback.value ? fallback.value : primary.value);
13484
+ const placeholder = computed(() => props.thumbhash ? thumbhashToDataUrl(props.thumbhash) : null);
13408
13485
  const src = computed(() => entered.value ? resolved.value || void 0 : void 0);
13409
13486
  const showImage = computed(() => Boolean(resolved.value) && !failed.value);
13410
- const showSkeleton = computed(() => props.skeleton && showImage.value && skeletonMounted.value);
13487
+ const showSkeleton = computed(() => (props.skeleton || !!placeholder.value) && showImage.value && skeletonMounted.value);
13411
13488
  watch(primary, () => {
13412
13489
  usingFallback.value = false;
13413
13490
  });
@@ -13418,12 +13495,12 @@ function useImage(props, emit) {
13418
13495
  skeletonMounted.value = true;
13419
13496
  failed.value = false;
13420
13497
  });
13421
- function play(el, frames) {
13498
+ function play(el, duration, easing) {
13422
13499
  const style = getComputedStyle(el);
13423
13500
  try {
13424
- return el.animate(frames, {
13425
- duration: cssTimeToMs(style.getPropertyValue("--hn-duration-fast")),
13426
- easing: style.getPropertyValue("--hn-ease-enter").trim() || "linear",
13501
+ return el.animate([{ opacity: 1 }, { opacity: 0 }], {
13502
+ duration: cssTimeToMs(style.getPropertyValue(duration)),
13503
+ easing: style.getPropertyValue(easing).trim() || "linear",
13427
13504
  fill: "forwards"
13428
13505
  });
13429
13506
  } catch {
@@ -13433,10 +13510,23 @@ function useImage(props, emit) {
13433
13510
  function afterPaint() {
13434
13511
  return new Promise((res) => requestAnimationFrame(() => requestAnimationFrame(() => res())));
13435
13512
  }
13513
+ function dropLayer() {
13514
+ const layer = skeletonEl.value;
13515
+ const anim = layer && (placeholder.value ? play(layer, "--hn-duration-slow", "--hn-ease-move") : play(layer, "--hn-duration-fast", "--hn-ease-enter"));
13516
+ if (!anim) {
13517
+ skeletonMounted.value = false;
13518
+ return;
13519
+ }
13520
+ fade = anim;
13521
+ anim.finished.then(() => {
13522
+ if (fade === anim) skeletonMounted.value = false;
13523
+ }, () => {});
13524
+ }
13436
13525
  async function reveal() {
13437
13526
  if (!props.lazy) {
13438
13527
  revealed.value = true;
13439
- skeletonMounted.value = false;
13528
+ if (placeholder.value) dropLayer();
13529
+ else skeletonMounted.value = false;
13440
13530
  return;
13441
13531
  }
13442
13532
  const img = imageEl.value;
@@ -13445,16 +13535,7 @@ function useImage(props, emit) {
13445
13535
  await afterPaint();
13446
13536
  if (imageEl.value !== img || src.value !== at) return;
13447
13537
  revealed.value = true;
13448
- const layer = skeletonEl.value;
13449
- const anim = layer && play(layer, [{ opacity: 1 }, { opacity: 0 }]);
13450
- if (!anim) {
13451
- skeletonMounted.value = false;
13452
- return;
13453
- }
13454
- fade = anim;
13455
- anim.finished.then(() => {
13456
- if (fade === anim) skeletonMounted.value = false;
13457
- }, () => {});
13538
+ dropLayer();
13458
13539
  }
13459
13540
  function fail() {
13460
13541
  if (!usingFallback.value && fallback.value) {
@@ -13489,6 +13570,7 @@ function useImage(props, emit) {
13489
13570
  imageEl,
13490
13571
  skeletonEl,
13491
13572
  src,
13573
+ placeholder,
13492
13574
  revealed,
13493
13575
  failed,
13494
13576
  showImage,
@@ -13505,15 +13587,6 @@ function useImageGroup() {
13505
13587
  return inject(KEY$1, null);
13506
13588
  }
13507
13589
  //#endregion
13508
- //#region src/components/image/Image.vue?vue&type=script&setup=true&lang.ts
13509
- var _hoisted_1$119 = [
13510
- "src",
13511
- "alt",
13512
- "decoding",
13513
- "fetchpriority",
13514
- "draggable"
13515
- ];
13516
- //#endregion
13517
13590
  //#region src/components/image/Image.vue
13518
13591
  var Image_default = /* @__PURE__ */ defineComponent({
13519
13592
  name: "HnImage",
@@ -13523,6 +13596,7 @@ var Image_default = /* @__PURE__ */ defineComponent({
13523
13596
  src: {},
13524
13597
  alt: { default: "" },
13525
13598
  fallback: {},
13599
+ thumbhash: {},
13526
13600
  fit: { default: "cover" },
13527
13601
  ratio: {},
13528
13602
  lazy: {
@@ -13564,7 +13638,21 @@ var Image_default = /* @__PURE__ */ defineComponent({
13564
13638
  emits: ["load", "error"],
13565
13639
  setup(__props, { emit: __emit }) {
13566
13640
  const props = __props;
13567
- const { rootEl, imageEl, skeletonEl, src, revealed, failed, showImage, showSkeleton } = useImage(props, __emit);
13641
+ const { rootEl, imageEl, skeletonEl, src, placeholder, revealed, failed, showImage, showSkeleton } = useImage(props, __emit);
13642
+ const framed = computed(() => !!placeholder.value && showImage.value);
13643
+ const imageProps = computed(() => ({
13644
+ style: props.imageStyle,
13645
+ src: src.value,
13646
+ alt: props.alt,
13647
+ decoding: props.eager ? "sync" : "async",
13648
+ fetchpriority: props.eager ? "high" : void 0,
13649
+ draggable: props.draggable,
13650
+ class: cn(image({
13651
+ fit: props.fit,
13652
+ lazy: props.lazy,
13653
+ placeholder: !!placeholder.value
13654
+ }), props.lazy && !revealed.value && "opacity-0", props.lazy && revealed.value && placeholder.value && showSkeleton.value && "mix-blend-plus-lighter", props.imageClass)
13655
+ }));
13568
13656
  const resolve = useImageResolver();
13569
13657
  const previewOpen = shallowRef(false);
13570
13658
  const previewId = useId();
@@ -13601,31 +13689,39 @@ var Image_default = /* @__PURE__ */ defineComponent({
13601
13689
  onClick: openPreview
13602
13690
  }, {
13603
13691
  default: withCtx(() => [
13604
- unref(showImage) ? (openBlock(), createElementBlock("img", mergeProps({
13692
+ framed.value ? (openBlock(), createElementBlock("span", {
13605
13693
  key: 0,
13694
+ class: normalizeClass(unref(imageFrame)())
13695
+ }, [createElementVNode("img", mergeProps({
13606
13696
  ref_key: "imageEl",
13607
13697
  ref: imageEl
13608
- }, _ctx.$attrs, {
13609
- style: props.imageStyle,
13610
- src: unref(src),
13611
- alt: props.alt,
13612
- decoding: props.eager ? "sync" : "async",
13613
- fetchpriority: props.eager ? "high" : void 0,
13614
- draggable: props.draggable,
13615
- class: unref(cn)(unref(image)({
13616
- fit: props.fit,
13617
- lazy: props.lazy
13618
- }), props.lazy && !unref(revealed) && "opacity-0", props.imageClass)
13619
- }), null, 16, _hoisted_1$119)) : unref(failed) ? renderSlot(_ctx.$slots, "error", {}, void 0, void 0, 1) : renderSlot(_ctx.$slots, "empty", {}, void 0, void 0, 2),
13620
- unref(showSkeleton) ? (openBlock(), createElementBlock("span", {
13621
- key: 3,
13698
+ }, {
13699
+ ..._ctx.$attrs,
13700
+ ...imageProps.value
13701
+ }), null, 16), unref(showSkeleton) ? (openBlock(), createElementBlock("span", {
13702
+ key: 0,
13703
+ ref_key: "skeletonEl",
13704
+ ref: skeletonEl,
13705
+ "aria-hidden": "true",
13706
+ class: normalizeClass(unref(cn)("pointer-events-none absolute inset-0", unref(imagePlaceholder)({ fit: props.fit }), unref(revealed) && "will-change-transform")),
13707
+ style: normalizeStyle({ backgroundImage: `url("${unref(placeholder)}")` })
13708
+ }, null, 6)) : createCommentVNode("", true)], 2)) : unref(showImage) ? (openBlock(), createElementBlock("img", mergeProps({
13709
+ key: 1,
13710
+ ref_key: "imageEl",
13711
+ ref: imageEl
13712
+ }, {
13713
+ ..._ctx.$attrs,
13714
+ ...imageProps.value
13715
+ }), null, 16)) : unref(failed) ? renderSlot(_ctx.$slots, "error", {}, void 0, void 0, 2) : renderSlot(_ctx.$slots, "empty", {}, void 0, void 0, 3),
13716
+ unref(showSkeleton) && !framed.value ? (openBlock(), createElementBlock("span", {
13717
+ key: 4,
13622
13718
  ref_key: "skeletonEl",
13623
13719
  ref: skeletonEl,
13624
13720
  "aria-hidden": "true",
13625
13721
  class: "pointer-events-none absolute inset-0"
13626
13722
  }, [renderSlot(_ctx.$slots, "skeleton", {}, () => [createVNode(Skeleton_default, { class: "size-full rounded-none" })])], 512)) : createCommentVNode("", true),
13627
13723
  props.preview && !unref(group) ? (openBlock(), createBlock(Lightbox_default, {
13628
- key: 4,
13724
+ key: 5,
13629
13725
  open: previewOpen.value,
13630
13726
  "onUpdate:open": _cache[0] || (_cache[0] = ($event) => previewOpen.value = $event),
13631
13727
  items: [previewItem.value]
@@ -18739,7 +18835,7 @@ var _hoisted_7$11 = {
18739
18835
  key: 0,
18740
18836
  class: "text-muted block truncate text-xs"
18741
18837
  };
18742
- var _hoisted_8$7 = { class: "flex size-4 shrink-0 items-center justify-center" };
18838
+ var _hoisted_8$8 = { class: "flex size-4 shrink-0 items-center justify-center" };
18743
18839
  var _hoisted_9$6 = { class: "min-w-0 flex-1" };
18744
18840
  var _hoisted_10$4 = { class: "block truncate" };
18745
18841
  var _hoisted_11$2 = {
@@ -18831,7 +18927,7 @@ var SelectList_default = /* @__PURE__ */ defineComponent({
18831
18927
  default: withCtx(() => [createVNode(unref(SelectItemText), { "as-child": "" }, {
18832
18928
  default: withCtx(() => [createElementVNode("span", _hoisted_5$22, [renderSlot(_ctx.$slots, "option", { option }, () => [createElementVNode("span", _hoisted_6$15, toDisplayString(option.label), 1), option.description ? (openBlock(), createElementBlock("span", _hoisted_7$11, toDisplayString(option.description), 1)) : createCommentVNode("", true)])])]),
18833
18929
  _: 2
18834
- }, 1024), createElementVNode("span", _hoisted_8$7, [createVNode(unref(SelectItemIndicator), null, {
18930
+ }, 1024), createElementVNode("span", _hoisted_8$8, [createVNode(unref(SelectItemIndicator), null, {
18835
18931
  default: withCtx(() => [createVNode(unref(Check))]),
18836
18932
  _: 1
18837
18933
  })])]),
@@ -21869,7 +21965,7 @@ var _hoisted_7$10 = {
21869
21965
  key: 0,
21870
21966
  class: "text-muted block truncate text-xs"
21871
21967
  };
21872
- var _hoisted_8$6 = { class: "flex size-4 shrink-0 items-center justify-center" };
21968
+ var _hoisted_8$7 = { class: "flex size-4 shrink-0 items-center justify-center" };
21873
21969
  var _hoisted_9$5 = { class: "min-w-0 flex-1" };
21874
21970
  var _hoisted_10$3 = { class: "block truncate" };
21875
21971
  var _hoisted_11$1 = {
@@ -21955,7 +22051,7 @@ var ComboboxList_default = /* @__PURE__ */ defineComponent({
21955
22051
  disabled: option.disabled,
21956
22052
  class: normalizeClass(unref(selectItem)())
21957
22053
  }, {
21958
- default: withCtx(() => [createElementVNode("span", _hoisted_5$20, [renderSlot(_ctx.$slots, "option", { option }, () => [createElementVNode("span", _hoisted_6$14, toDisplayString(option.label), 1), option.description ? (openBlock(), createElementBlock("span", _hoisted_7$10, toDisplayString(option.description), 1)) : createCommentVNode("", true)])]), createElementVNode("span", _hoisted_8$6, [createVNode(unref(ComboboxItemIndicator), null, {
22054
+ default: withCtx(() => [createElementVNode("span", _hoisted_5$20, [renderSlot(_ctx.$slots, "option", { option }, () => [createElementVNode("span", _hoisted_6$14, toDisplayString(option.label), 1), option.description ? (openBlock(), createElementBlock("span", _hoisted_7$10, toDisplayString(option.description), 1)) : createCommentVNode("", true)])]), createElementVNode("span", _hoisted_8$7, [createVNode(unref(ComboboxItemIndicator), null, {
21959
22055
  default: withCtx(() => [createVNode(unref(Check))]),
21960
22056
  _: 1
21961
22057
  })])]),
@@ -25022,7 +25118,7 @@ var _hoisted_7$8 = {
25022
25118
  key: 0,
25023
25119
  class: "text-muted block truncate text-xs"
25024
25120
  };
25025
- var _hoisted_8$5 = { class: "flex size-4 shrink-0 items-center justify-center" };
25121
+ var _hoisted_8$6 = { class: "flex size-4 shrink-0 items-center justify-center" };
25026
25122
  var _hoisted_9$4 = { role: "status" };
25027
25123
  //#endregion
25028
25124
  //#region src/components/tree-select/TreeSelect.vue
@@ -25175,7 +25271,7 @@ var TreeSelect_default = /* @__PURE__ */ defineComponent({
25175
25271
  open: isExpanded
25176
25272
  }, null, 8, ["open"])], 10, _hoisted_3$27)) : (openBlock(), createElementBlock("span", _hoisted_4$21)),
25177
25273
  createElementVNode("span", _hoisted_5$16, [renderSlot(_ctx.$slots, "node", { node: item.value }, () => [createElementVNode("span", _hoisted_6$11, toDisplayString(item.value.label), 1), item.value.description ? (openBlock(), createElementBlock("span", _hoisted_7$8, toDisplayString(item.value.description), 1)) : createCommentVNode("", true)])]),
25178
- createElementVNode("span", _hoisted_8$5, [isSelected ? (openBlock(), createBlock(unref(Check), { key: 0 })) : createCommentVNode("", true)])
25274
+ createElementVNode("span", _hoisted_8$6, [isSelected ? (openBlock(), createBlock(unref(Check), { key: 0 })) : createCommentVNode("", true)])
25179
25275
  ]),
25180
25276
  _: 2
25181
25277
  }, 1040, [
@@ -28133,13 +28229,11 @@ var DismissableLayerBranch = defineComponent({
28133
28229
  },
28134
28230
  setup(props, { slots }) {
28135
28231
  const { forwardRef, currentElement } = useForwardExpose();
28136
- let release;
28137
- onMounted(() => {
28138
- if (currentElement.value) release = addBranch(currentElement.value);
28139
- });
28140
- onUnmounted(() => {
28141
- release?.();
28142
- release = void 0;
28232
+ watch(currentElement, (element, _, onCleanup) => {
28233
+ if (isClient && element instanceof HTMLElement) onCleanup(addBranch(element));
28234
+ }, {
28235
+ immediate: true,
28236
+ flush: "post"
28143
28237
  });
28144
28238
  return () => h(Primitive, mergeProps({ ref: forwardRef }, props), { default: withCtx(() => [renderSlot(slots, "default")]) });
28145
28239
  }
@@ -38687,11 +38781,99 @@ function tourBeaconOnArrival(step, beacon, navigated) {
38687
38781
  function tourTargetBlocked(step, blockTarget) {
38688
38782
  return step.blockTarget ?? blockTarget;
38689
38783
  }
38784
+ function tourPageBlocked(step, blockPage) {
38785
+ return step.blockPage ?? blockPage;
38786
+ }
38787
+ function toRect(rect) {
38788
+ return {
38789
+ x: rect.left ?? rect.x ?? 0,
38790
+ y: rect.top ?? rect.y ?? 0,
38791
+ width: rect.width,
38792
+ height: rect.height
38793
+ };
38794
+ }
38795
+ function unionRect(rects) {
38796
+ const left = Math.min(...rects.map((rect) => rect.x));
38797
+ const top = Math.min(...rects.map((rect) => rect.y));
38798
+ const right = Math.max(...rects.map((rect) => rect.x + rect.width));
38799
+ const bottom = Math.max(...rects.map((rect) => rect.y + rect.height));
38800
+ return {
38801
+ x: left,
38802
+ y: top,
38803
+ width: right - left,
38804
+ height: bottom - top
38805
+ };
38806
+ }
38807
+ function readItem(item) {
38808
+ if (typeof item === "string") {
38809
+ if (typeof document === "undefined") return null;
38810
+ const element = document.querySelector(item);
38811
+ return element ? {
38812
+ element,
38813
+ read: () => toRect(element.getBoundingClientRect())
38814
+ } : null;
38815
+ }
38816
+ if (typeof Element !== "undefined" && item instanceof Element) return {
38817
+ element: item,
38818
+ read: () => toRect(item.getBoundingClientRect())
38819
+ };
38820
+ if (typeof item.getBoundingClientRect === "function") {
38821
+ const virtual = item;
38822
+ return {
38823
+ element: null,
38824
+ read: () => toRect(virtual.getBoundingClientRect())
38825
+ };
38826
+ }
38827
+ const rect = toRect(item);
38828
+ return {
38829
+ element: null,
38830
+ read: () => rect
38831
+ };
38832
+ }
38690
38833
  function resolveTourTarget(target) {
38691
38834
  if (!target) return null;
38692
- if (typeof target === "string") return typeof document === "undefined" ? null : document.querySelector(target);
38693
- if (typeof target === "function") return target() ?? null;
38694
- return target;
38835
+ const value = typeof target === "function" ? target() : target;
38836
+ if (!value) return null;
38837
+ const items = Array.isArray(value) ? value : [value];
38838
+ if (!items.length) return null;
38839
+ const readers = [];
38840
+ for (const item of items) {
38841
+ const reader = item ? readItem(item) : null;
38842
+ if (!reader) return null;
38843
+ readers.push(reader);
38844
+ }
38845
+ return {
38846
+ elements: readers.flatMap((reader) => reader.element ? [reader.element] : []),
38847
+ virtual: readers.some((reader) => !reader.element),
38848
+ rect: () => unionRect(readers.map((reader) => reader.read()))
38849
+ };
38850
+ }
38851
+ function waitForTourTarget(target, timeout, signal) {
38852
+ const found = resolveTourTarget(target);
38853
+ if (found || timeout <= 0 || signal?.aborted) return Promise.resolve(found);
38854
+ return new Promise((resolve) => {
38855
+ const check = () => {
38856
+ const resolved = resolveTourTarget(target);
38857
+ if (resolved) finish(resolved);
38858
+ };
38859
+ const observer = new MutationObserver(check);
38860
+ const interval = window.setInterval(check, 100);
38861
+ const timer = window.setTimeout(() => finish(null), timeout);
38862
+ const abort = () => finish(null);
38863
+ function finish(value) {
38864
+ observer.disconnect();
38865
+ window.clearInterval(interval);
38866
+ window.clearTimeout(timer);
38867
+ signal?.removeEventListener("abort", abort);
38868
+ resolve(value);
38869
+ }
38870
+ observer.observe(document.documentElement, {
38871
+ childList: true,
38872
+ subtree: true,
38873
+ attributes: true
38874
+ });
38875
+ signal?.addEventListener("abort", abort);
38876
+ });
38695
38877
  }
38696
38878
  function clampTourStep(step, count) {
38697
38879
  if (count <= 0) return 1;
@@ -38772,11 +38954,19 @@ async function runTourChange(beforeChange, step, previousStep, setBusy) {
38772
38954
  setBusy(false);
38773
38955
  }
38774
38956
  }
38775
- function tourReference(element, padding = 8) {
38957
+ function tourCardGap(element) {
38958
+ return cssTimeToMs(getComputedStyle(element ?? document.documentElement).getPropertyValue("--hn-duration-exit"));
38959
+ }
38960
+ function tourReference(read, contextElement) {
38776
38961
  return {
38777
- contextElement: element,
38962
+ contextElement: contextElement ?? void 0,
38778
38963
  getBoundingClientRect() {
38779
- const rect = spotlightRect(element.getBoundingClientRect(), padding);
38964
+ const rect = read() ?? {
38965
+ x: 0,
38966
+ y: 0,
38967
+ width: 0,
38968
+ height: 0
38969
+ };
38780
38970
  return {
38781
38971
  ...rect,
38782
38972
  left: rect.x,
@@ -38787,16 +38977,20 @@ function tourReference(element, padding = 8) {
38787
38977
  }
38788
38978
  };
38789
38979
  }
38790
- function watchTourTarget(element, onChange) {
38980
+ function watchTourTarget(resolved, onChange) {
38791
38981
  onChange();
38792
- return autoUpdate(element, document.documentElement, onChange);
38982
+ const stops = resolved.elements.map((element) => autoUpdate(element, document.documentElement, onChange));
38983
+ if (resolved.virtual) stops.push(autoUpdate({ getBoundingClientRect: () => DOMRect.fromRect(resolved.rect()) }, document.documentElement, onChange, { animationFrame: true }));
38984
+ return () => {
38985
+ for (const stop of stops) stop();
38986
+ };
38793
38987
  }
38794
- function isFullyVisible(element) {
38795
- const rect = element.getBoundingClientRect();
38796
- return rect.top >= 0 && rect.left >= 0 && rect.bottom <= window.innerHeight && rect.right <= window.innerWidth;
38988
+ function isFullyVisible(rect) {
38989
+ return rect.y >= 0 && rect.x >= 0 && rect.y + rect.height <= window.innerHeight && rect.x + rect.width <= window.innerWidth;
38797
38990
  }
38798
- function revealTourTarget(element) {
38799
- if (isFullyVisible(element)) return;
38991
+ function revealTourTarget(resolved) {
38992
+ const [element] = resolved.elements;
38993
+ if (!element || isFullyVisible(resolved.rect())) return;
38800
38994
  const reduce = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
38801
38995
  element.scrollIntoView({
38802
38996
  block: "center",
@@ -38806,11 +39000,13 @@ function revealTourTarget(element) {
38806
39000
  }
38807
39001
  function hideOutsideTour(elements) {
38808
39002
  const present = elements.filter((element) => !!element?.isConnected);
38809
- return present.length ? hideOthers(present) : () => {};
39003
+ return present.length ? hideOutsideLayers(present) : () => {};
38810
39004
  }
38811
- function trapTourFocus(getContainers, getLayer) {
39005
+ function tourOwnsInput(layer, scripted) {
39006
+ return scripted || isHighestLayer(layer);
39007
+ }
39008
+ function trapTourFocus(getContainers, enabled) {
38812
39009
  const containers = () => getContainers().filter((node) => !!node);
38813
- const enabled = () => isHighestLayer(getLayer());
38814
39010
  const inside = (node) => !!node && containers().some((c) => c.contains(node));
38815
39011
  function candidates() {
38816
39012
  return containers().flatMap((container) => [...container.tabIndex >= 0 ? [container] : [], ...getTabbableCandidates$1(container)]);
@@ -38838,26 +39034,672 @@ function trapTourFocus(getContainers, getLayer) {
38838
39034
  document.removeEventListener("keydown", onKeyDown, true);
38839
39035
  };
38840
39036
  }
39037
+ function listenTourKeys(onKeyDown) {
39038
+ window.addEventListener("keydown", onKeyDown, true);
39039
+ return () => window.removeEventListener("keydown", onKeyDown, true);
39040
+ }
39041
+ //#endregion
39042
+ //#region ../shared/src/lib/tour-engine.ts
39043
+ var INITIAL = {
39044
+ status: "idle",
39045
+ settled: false,
39046
+ hole: null,
39047
+ targetRect: null,
39048
+ radius: 8,
39049
+ elements: [],
39050
+ playing: false,
39051
+ viewport: {
39052
+ width: 0,
39053
+ height: 0
39054
+ }
39055
+ };
39056
+ var TOUR_SPRING = {
39057
+ stiffness: 260,
39058
+ damping: 30
39059
+ };
39060
+ var KEYS = [
39061
+ "x",
39062
+ "y",
39063
+ "width",
39064
+ "height"
39065
+ ];
39066
+ function stepSpring(position, velocity, goal, seconds, { stiffness, damping } = TOUR_SPRING) {
39067
+ const step = 1 / 240;
39068
+ let left = seconds;
39069
+ while (left > 0) {
39070
+ const dt = Math.min(step, left);
39071
+ for (const key of KEYS) {
39072
+ const force = -stiffness * (position[key] - goal[key]) - damping * velocity[key];
39073
+ velocity[key] += force * dt;
39074
+ position[key] += velocity[key] * dt;
39075
+ }
39076
+ left -= dt;
39077
+ }
39078
+ return KEYS.every((key) => Math.abs(position[key] - goal[key]) < .25 && Math.abs(velocity[key]) < 2);
39079
+ }
39080
+ function bezierEasing([x1, y1, x2, y2]) {
39081
+ const curve = (a, b, t) => 3 * a * t * (1 - t) ** 2 + 3 * b * t * t * (1 - t) + t ** 3;
39082
+ const slope = (a, b, t) => 3 * a * (1 - t) ** 2 + 6 * (b - a) * t * (1 - t) + 3 * (1 - b) * t * t;
39083
+ return (progress) => {
39084
+ if (progress <= 0) return 0;
39085
+ if (progress >= 1) return 1;
39086
+ let t = progress;
39087
+ for (let i = 0; i < 8; i++) {
39088
+ const error = curve(x1, x2, t) - progress;
39089
+ const derivative = slope(x1, x2, t);
39090
+ if (Math.abs(error) < 1e-5 || derivative === 0) break;
39091
+ t -= error / derivative;
39092
+ }
39093
+ return curve(y1, y2, Math.min(Math.max(t, 0), 1));
39094
+ };
39095
+ }
39096
+ var easeMove = bezierEasing(EASE.move);
39097
+ function reducedMotion() {
39098
+ return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
39099
+ }
39100
+ function abortError() {
39101
+ return new DOMException("The tour step was left", "AbortError");
39102
+ }
39103
+ function isAbortError(error) {
39104
+ return error instanceof DOMException && error.name === "AbortError";
39105
+ }
39106
+ function guard(signal) {
39107
+ if (signal.aborted) throw abortError();
39108
+ }
39109
+ function tourSleep(ms, signal) {
39110
+ return new Promise((resolve, reject) => {
39111
+ if (signal.aborted) return reject(abortError());
39112
+ const timer = window.setTimeout(done, ms);
39113
+ const abort = () => {
39114
+ window.clearTimeout(timer);
39115
+ reject(abortError());
39116
+ };
39117
+ function done() {
39118
+ signal.removeEventListener("abort", abort);
39119
+ resolve();
39120
+ }
39121
+ signal.addEventListener("abort", abort, { once: true });
39122
+ });
39123
+ }
39124
+ function tween(duration, onFrame, signal, easing = easeMove) {
39125
+ return new Promise((resolve, reject) => {
39126
+ if (signal.aborted) return reject(abortError());
39127
+ if (duration <= 0 || reducedMotion()) {
39128
+ onFrame(1);
39129
+ return resolve();
39130
+ }
39131
+ const start = performance.now();
39132
+ let frame = 0;
39133
+ const abort = () => {
39134
+ cancelAnimationFrame(frame);
39135
+ reject(abortError());
39136
+ };
39137
+ const tick = (now) => {
39138
+ const progress = Math.min((now - start) / duration, 1);
39139
+ onFrame(easing(progress));
39140
+ if (progress < 1) frame = requestAnimationFrame(tick);
39141
+ else {
39142
+ signal.removeEventListener("abort", abort);
39143
+ resolve();
39144
+ }
39145
+ };
39146
+ signal.addEventListener("abort", abort, { once: true });
39147
+ frame = requestAnimationFrame(tick);
39148
+ });
39149
+ }
39150
+ var nextFrame = () => new Promise((resolve) => requestAnimationFrame(() => resolve()));
39151
+ var delay = (ms) => new Promise((resolve) => window.setTimeout(resolve, ms));
39152
+ function finiteAnimations(affects = () => true) {
39153
+ if (typeof document.getAnimations !== "function") return [];
39154
+ return document.getAnimations().filter((animation) => {
39155
+ if (animation.playState !== "running" || animation.timeline !== document.timeline) return false;
39156
+ const end = animation.effect?.getComputedTiming().endTime;
39157
+ if (typeof end !== "number" || !Number.isFinite(end)) return false;
39158
+ const node = animation.effect?.target;
39159
+ return !!node && affects(node);
39160
+ });
39161
+ }
39162
+ function settle(animations, until) {
39163
+ if (!animations.length) return Promise.resolve();
39164
+ return Promise.race([Promise.allSettled(animations.map((animation) => animation.finished)), delay(Math.max(until - performance.now(), 0))]);
39165
+ }
39166
+ async function waitForStillTarget(target, limit = 1e3) {
39167
+ const until = performance.now() + limit;
39168
+ await nextFrame();
39169
+ await settle(finiteAnimations((node) => target.elements.some((element) => node === element || node.contains(element))), until);
39170
+ let previous = target.rect();
39171
+ let still = 0;
39172
+ while (still < 2 && performance.now() < until) {
39173
+ await nextFrame();
39174
+ const rect = target.rect();
39175
+ const moved = KEYS.some((key) => Math.abs(rect[key] - previous[key]) > .5);
39176
+ previous = rect;
39177
+ still = moved ? 0 : still + 1;
39178
+ }
39179
+ }
39180
+ async function waitForFiniteAnimations(limit = 1e3) {
39181
+ const until = performance.now() + limit;
39182
+ await nextFrame();
39183
+ await nextFrame();
39184
+ await settle(finiteAnimations(), until);
39185
+ }
39186
+ function isPoint(value) {
39187
+ return !!value && typeof value === "object" && typeof value.x === "number" && typeof value.y === "number" && !("width" in value);
39188
+ }
39189
+ function tourPointerPoint(target) {
39190
+ if (isPoint(target)) return {
39191
+ x: target.x,
39192
+ y: target.y
39193
+ };
39194
+ const resolved = resolveTourTarget(target);
39195
+ if (!resolved) return null;
39196
+ const rect = resolved.rect();
39197
+ return {
39198
+ x: rect.x + rect.width / 2,
39199
+ y: rect.y + rect.height / 2
39200
+ };
39201
+ }
39202
+ function createPointer(element, keyBadge, signal, memory, ready) {
39203
+ const place = (point) => {
39204
+ memory.point = point;
39205
+ const node = element();
39206
+ if (node) node.style.transform = `translate3d(${point.x}px, ${point.y}px, 0)`;
39207
+ };
39208
+ const setState = (name, value) => {
39209
+ const node = element();
39210
+ if (!node) return;
39211
+ if (value === null) node.removeAttribute(name);
39212
+ else node.setAttribute(name, value);
39213
+ };
39214
+ const ripple = () => {
39215
+ const node = element()?.querySelector("[data-hn-tour-pointer-ripples]");
39216
+ if (!node) return;
39217
+ const span = document.createElement("span");
39218
+ span.setAttribute("data-hn-tour-ripple", "");
39219
+ span.addEventListener("animationend", () => span.remove(), { once: true });
39220
+ window.setTimeout(() => span.remove(), 1e3);
39221
+ node.appendChild(span);
39222
+ };
39223
+ const resolvePoint = (target) => {
39224
+ const point = tourPointerPoint(target);
39225
+ if (!point) throw new Error("[Hina UI] Tour: the pointer target was not found");
39226
+ return point;
39227
+ };
39228
+ const travel = async (target, duration, onMove) => {
39229
+ guard(signal);
39230
+ let to = resolvePoint(target);
39231
+ const from = element()?.getAttribute("data-state") !== "shown" || !memory.point ? {
39232
+ x: to.x + 40,
39233
+ y: to.y + 40
39234
+ } : memory.point;
39235
+ place(from);
39236
+ setState("data-state", "shown");
39237
+ await tween(duration, (progress) => {
39238
+ to = tourPointerPoint(target) ?? to;
39239
+ const point = {
39240
+ x: from.x + (to.x - from.x) * progress,
39241
+ y: from.y + (to.y - from.y) * progress
39242
+ };
39243
+ place(point);
39244
+ onMove?.(point);
39245
+ }, signal);
39246
+ };
39247
+ return {
39248
+ async move(target, duration = 600) {
39249
+ await ready();
39250
+ await travel(target, duration);
39251
+ },
39252
+ async tap() {
39253
+ await ready();
39254
+ setState("data-pressed", "");
39255
+ ripple();
39256
+ await tourSleep(120, signal);
39257
+ setState("data-pressed", null);
39258
+ await tourSleep(180, signal);
39259
+ },
39260
+ async press(duration = 800) {
39261
+ await ready();
39262
+ element()?.style.setProperty("--hn-tour-press", `${duration}ms`);
39263
+ setState("data-pressed", "long");
39264
+ try {
39265
+ await tourSleep(duration, signal);
39266
+ } finally {
39267
+ setState("data-pressed", null);
39268
+ }
39269
+ },
39270
+ async drag(target, duration = 800, onMove) {
39271
+ await ready();
39272
+ setState("data-pressed", "");
39273
+ try {
39274
+ await tourSleep(80, signal);
39275
+ if (memory.point) onMove?.(memory.point);
39276
+ await travel(target, duration, onMove);
39277
+ await tourSleep(80, signal);
39278
+ } finally {
39279
+ setState("data-pressed", null);
39280
+ }
39281
+ },
39282
+ async key(key, duration = 700) {
39283
+ await ready();
39284
+ const badge = keyBadge();
39285
+ if (!badge) return;
39286
+ const label = badge.querySelector("[data-hn-tour-key-label]") ?? badge;
39287
+ label.textContent = key;
39288
+ const near = element()?.getAttribute("data-state") === "shown" && memory.point;
39289
+ const x = near ? memory.point.x + 20 : window.innerWidth / 2;
39290
+ const y = near ? memory.point.y + 28 : window.innerHeight - 72;
39291
+ badge.style.transform = `translate3d(${x}px, ${y}px, 0)`;
39292
+ badge.setAttribute("data-placement", near ? "pointer" : "screen");
39293
+ badge.setAttribute("data-state", "shown");
39294
+ try {
39295
+ await tourSleep(duration, signal);
39296
+ } finally {
39297
+ badge.setAttribute("data-state", "hidden");
39298
+ }
39299
+ },
39300
+ async hide() {
39301
+ setState("data-state", "hidden");
39302
+ }
39303
+ };
39304
+ }
39305
+ function createTourEngine(options) {
39306
+ let state = INITIAL;
39307
+ const listeners = /* @__PURE__ */ new Set();
39308
+ const set = (patch) => {
39309
+ state = {
39310
+ ...state,
39311
+ ...patch
39312
+ };
39313
+ for (const listener of [...listeners]) listener();
39314
+ };
39315
+ let step = {};
39316
+ let stepNumber = 0;
39317
+ let padding = 8;
39318
+ let resolved = null;
39319
+ let stopTracking = () => {};
39320
+ let token = 0;
39321
+ let epoch = 0;
39322
+ let revealAt = 0;
39323
+ let entering = false;
39324
+ let entry = Promise.resolve();
39325
+ let markEntered = () => {};
39326
+ let waiting = null;
39327
+ let position = null;
39328
+ let velocity = {
39329
+ x: 0,
39330
+ y: 0,
39331
+ width: 0,
39332
+ height: 0
39333
+ };
39334
+ let frame = 0;
39335
+ let last = 0;
39336
+ let settleWaiters = [];
39337
+ let run = null;
39338
+ const pointerMemory = { point: null };
39339
+ const viewport = () => ({
39340
+ width: window.innerWidth,
39341
+ height: window.innerHeight
39342
+ });
39343
+ const attached = (found) => found.elements.every((element) => element.isConnected);
39344
+ const goal = () => {
39345
+ if (!resolved) return null;
39346
+ if (!attached(resolved)) return position ? { ...position } : null;
39347
+ return spotlightRect(toBox(resolved.rect()), padding);
39348
+ };
39349
+ const toBox = (rect) => ({
39350
+ left: rect.x,
39351
+ top: rect.y,
39352
+ width: rect.width,
39353
+ height: rect.height
39354
+ });
39355
+ function flushSettled() {
39356
+ const waiters = settleWaiters;
39357
+ settleWaiters = [];
39358
+ for (const resolve of waiters) resolve();
39359
+ }
39360
+ function stopSpring() {
39361
+ if (frame) cancelAnimationFrame(frame);
39362
+ frame = 0;
39363
+ flushSettled();
39364
+ }
39365
+ function snap() {
39366
+ if (resolved && !attached(resolved)) {
39367
+ set({ viewport: viewport() });
39368
+ return;
39369
+ }
39370
+ const target = goal();
39371
+ position = target ? { ...target } : null;
39372
+ velocity = {
39373
+ x: 0,
39374
+ y: 0,
39375
+ width: 0,
39376
+ height: 0
39377
+ };
39378
+ set({
39379
+ hole: position ? { ...position } : null,
39380
+ targetRect: resolved ? resolved.rect() : null,
39381
+ viewport: viewport()
39382
+ });
39383
+ }
39384
+ function tick(now) {
39385
+ const target = goal();
39386
+ if (!target || !position) {
39387
+ frame = 0;
39388
+ snap();
39389
+ flushSettled();
39390
+ return;
39391
+ }
39392
+ const seconds = Math.min((now - last) / 1e3, 1 / 20);
39393
+ last = now;
39394
+ if (stepSpring(position, velocity, target, seconds)) {
39395
+ frame = 0;
39396
+ snap();
39397
+ flushSettled();
39398
+ return;
39399
+ }
39400
+ set({
39401
+ hole: { ...position },
39402
+ ...attached(resolved) ? { targetRect: resolved.rect() } : {},
39403
+ viewport: viewport()
39404
+ });
39405
+ frame = requestAnimationFrame(tick);
39406
+ }
39407
+ function springTo(animate) {
39408
+ if (!animate || !position || reducedMotion()) {
39409
+ stopSpring();
39410
+ snap();
39411
+ return Promise.resolve();
39412
+ }
39413
+ const settled = new Promise((resolve) => settleWaiters.push(resolve));
39414
+ if (!frame) {
39415
+ last = performance.now();
39416
+ frame = requestAnimationFrame(tick);
39417
+ }
39418
+ return settled;
39419
+ }
39420
+ function track() {
39421
+ if (frame) return;
39422
+ snap();
39423
+ }
39424
+ function follow(target, found) {
39425
+ let stopWatch = watchTourTarget(found, track);
39426
+ const observer = new MutationObserver(() => {
39427
+ if (!resolved || attached(resolved)) return;
39428
+ const again = resolveTourTarget(target);
39429
+ if (!again || !attached(again)) return;
39430
+ resolved = again;
39431
+ stopWatch();
39432
+ set({ elements: again.elements });
39433
+ springTo(!!position);
39434
+ stopWatch = watchTourTarget(again, track);
39435
+ });
39436
+ observer.observe(document.body, {
39437
+ childList: true,
39438
+ subtree: true
39439
+ });
39440
+ return () => {
39441
+ observer.disconnect();
39442
+ stopWatch();
39443
+ };
39444
+ }
39445
+ function onResize() {
39446
+ if (frame) return;
39447
+ if (resolved) snap();
39448
+ else set({ viewport: viewport() });
39449
+ }
39450
+ async function reveal(current) {
39451
+ if (revealAt > performance.now()) {
39452
+ await delay(revealAt - performance.now());
39453
+ if (current !== token) return false;
39454
+ }
39455
+ entering = false;
39456
+ set({ settled: true });
39457
+ markEntered();
39458
+ return true;
39459
+ }
39460
+ function untilEntered(signal) {
39461
+ return new Promise((resolve, reject) => {
39462
+ if (signal.aborted) return reject(abortError());
39463
+ const abort = () => reject(abortError());
39464
+ signal.addEventListener("abort", abort, { once: true });
39465
+ entry.then(() => {
39466
+ signal.removeEventListener("abort", abort);
39467
+ if (signal.aborted) reject(abortError());
39468
+ else resolve();
39469
+ });
39470
+ });
39471
+ }
39472
+ async function aim(target, { wait = 0, scroll = true, padding: nextPadding, radius }) {
39473
+ const current = ++token;
39474
+ waiting?.abort();
39475
+ const controller = new AbortController();
39476
+ waiting = controller;
39477
+ let found = resolveTourTarget(target);
39478
+ if (!found && target && wait > 0) {
39479
+ found = await waitForTourTarget(target, wait, controller.signal);
39480
+ if (current !== token) return "stale";
39481
+ }
39482
+ if (!found) {
39483
+ stopTracking();
39484
+ stopTracking = () => {};
39485
+ resolved = null;
39486
+ stopSpring();
39487
+ position = null;
39488
+ set({
39489
+ status: "missing",
39490
+ settled: !entering,
39491
+ hole: null,
39492
+ targetRect: null,
39493
+ elements: [],
39494
+ viewport: viewport()
39495
+ });
39496
+ if (entering && !await reveal(current)) return "stale";
39497
+ return target ? "missing" : "empty";
39498
+ }
39499
+ stopTracking();
39500
+ stopTracking = () => {};
39501
+ const animate = !!position;
39502
+ if (scroll) revealTourTarget(found);
39503
+ if (animate && !reducedMotion()) {
39504
+ stopSpring();
39505
+ for (let attempt = 0; attempt < 3; attempt++) {
39506
+ await waitForStillTarget(found);
39507
+ if (current !== token) return "stale";
39508
+ if (attached(found)) break;
39509
+ const again = resolveTourTarget(target);
39510
+ if (!again) break;
39511
+ found = again;
39512
+ }
39513
+ }
39514
+ resolved = found;
39515
+ padding = nextPadding ?? step.padding ?? 8;
39516
+ set({
39517
+ status: "ready",
39518
+ elements: found.elements,
39519
+ radius: radius ?? step.radius ?? 8,
39520
+ ...entering ? { settled: false } : {}
39521
+ });
39522
+ const settled = springTo(animate);
39523
+ stopTracking = follow(target, found);
39524
+ await settled;
39525
+ if (current !== token) return "stale";
39526
+ if (entering && !await reveal(current)) return "stale";
39527
+ return "ready";
39528
+ }
39529
+ function abortRun() {
39530
+ const current = run;
39531
+ if (!current) return;
39532
+ run = null;
39533
+ current.controller.abort();
39534
+ for (const cleanup of current.cleanups.reverse()) try {
39535
+ cleanup();
39536
+ } catch (error) {
39537
+ console.error(error);
39538
+ }
39539
+ options.pointer()?.setAttribute("data-state", "hidden");
39540
+ options.pointer()?.removeAttribute("data-pressed");
39541
+ options.keyBadge()?.setAttribute("data-state", "hidden");
39542
+ set({ playing: false });
39543
+ }
39544
+ function play() {
39545
+ abortRun();
39546
+ epoch += 1;
39547
+ const script = step.play;
39548
+ if (!script) return;
39549
+ const controller = new AbortController();
39550
+ const cleanups = [];
39551
+ const current = {
39552
+ controller,
39553
+ cleanups
39554
+ };
39555
+ run = current;
39556
+ const { signal } = controller;
39557
+ const context = {
39558
+ step: stepNumber,
39559
+ signal,
39560
+ defer(cleanup) {
39561
+ if (signal.aborted) cleanup();
39562
+ else cleanups.push(cleanup);
39563
+ },
39564
+ pointer: createPointer(options.pointer, options.keyBadge, signal, pointerMemory, () => untilEntered(signal)),
39565
+ async spotlight(target, spotlightOptions = {}) {
39566
+ guard(signal);
39567
+ await aim(target === void 0 ? step.target : target, {
39568
+ ...spotlightOptions,
39569
+ scroll: false
39570
+ });
39571
+ guard(signal);
39572
+ },
39573
+ async waitFor(target, timeout = 5e3) {
39574
+ guard(signal);
39575
+ const found = await waitForTourTarget(target, timeout, signal);
39576
+ guard(signal);
39577
+ return !!found;
39578
+ },
39579
+ sleep: (ms) => tourSleep(ms, signal)
39580
+ };
39581
+ set({ playing: true });
39582
+ Promise.resolve().then(() => script(context)).catch((error) => {
39583
+ if (!isAbortError(error)) console.error(error);
39584
+ }).finally(() => {
39585
+ if (run === current) set({ playing: false });
39586
+ });
39587
+ }
39588
+ return {
39589
+ subscribe(listener) {
39590
+ listeners.add(listener);
39591
+ return () => {
39592
+ listeners.delete(listener);
39593
+ };
39594
+ },
39595
+ getState: () => state,
39596
+ pointerKind: options.pointerKind,
39597
+ enter(next, number) {
39598
+ abortRun();
39599
+ epoch += 1;
39600
+ const fresh = state.status === "idle";
39601
+ if (fresh) {
39602
+ stopSpring();
39603
+ position = null;
39604
+ pointerMemory.point = null;
39605
+ window.addEventListener("resize", onResize);
39606
+ }
39607
+ revealAt = fresh ? 0 : performance.now() + (options.cardGap?.() ?? 0);
39608
+ markEntered();
39609
+ entering = true;
39610
+ entry = new Promise((resolve) => markEntered = resolve);
39611
+ step = next;
39612
+ stepNumber = number;
39613
+ set({
39614
+ status: "waiting",
39615
+ settled: false,
39616
+ viewport: viewport(),
39617
+ ...fresh ? {
39618
+ hole: null,
39619
+ targetRect: null,
39620
+ elements: []
39621
+ } : {}
39622
+ });
39623
+ return aim(next.target, {
39624
+ wait: next.wait ?? 0,
39625
+ scroll: next.scroll !== false
39626
+ });
39627
+ },
39628
+ play,
39629
+ replay() {
39630
+ if (!step.play) return;
39631
+ abortRun();
39632
+ const current = ++epoch;
39633
+ stopTracking();
39634
+ stopTracking = () => {};
39635
+ stopSpring();
39636
+ waitForFiniteAnimations().then(() => {
39637
+ if (current !== epoch) return;
39638
+ aim(step.target, {
39639
+ wait: step.wait ?? 0,
39640
+ scroll: false
39641
+ });
39642
+ play();
39643
+ });
39644
+ },
39645
+ leave() {
39646
+ abortRun();
39647
+ epoch += 1;
39648
+ token += 1;
39649
+ waiting?.abort();
39650
+ waiting = null;
39651
+ },
39652
+ close() {
39653
+ abortRun();
39654
+ epoch += 1;
39655
+ token += 1;
39656
+ waiting?.abort();
39657
+ waiting = null;
39658
+ stopTracking();
39659
+ stopTracking = () => {};
39660
+ stopSpring();
39661
+ window.removeEventListener("resize", onResize);
39662
+ entering = false;
39663
+ markEntered();
39664
+ set({
39665
+ status: "idle",
39666
+ settled: false,
39667
+ playing: false
39668
+ });
39669
+ }
39670
+ };
39671
+ }
38841
39672
  //#endregion
38842
39673
  //#region ../shared/src/variants/tour.ts
39674
+ var layer = "z-[calc(var(--hn-z-overlay)+1)]";
38843
39675
  var tourMask = tv({ base: "hn-scrim hn-tour-mask" });
38844
- var tourBlocker = tv({ base: "fixed z-(--hn-z-overlay)" });
38845
- var tourCard = tv({ base: "relative z-(--hn-z-overlay) flex w-80 max-w-[calc(100vw-2rem)] flex-col gap-3 overflow-visible p-4 shadow-lg outline-none" });
38846
- var tourCentered = tv({ base: "pointer-events-none fixed inset-0 z-(--hn-z-overlay) grid place-items-center p-4 [&>*]:pointer-events-auto" });
38847
- var tourBeacon = tv({ base: "hn-focus-ring fixed z-(--hn-z-overlay) size-4 -translate-x-1/2 -translate-y-1/2 cursor-pointer rounded-full" });
39676
+ var tourBlocker = tv({ base: `fixed ${layer}` });
39677
+ var tourCard = tv({ base: `relative ${layer} flex w-80 max-w-[calc(100vw-2rem)] flex-col gap-3 overflow-visible p-4 shadow-lg outline-none` });
39678
+ var tourCentered = tv({ base: `pointer-events-none fixed inset-0 ${layer} grid place-items-center p-4 [&>*]:pointer-events-auto` });
39679
+ var tourBeacon = tv({ base: `hn-focus-ring fixed ${layer} size-4 -translate-x-1/2 -translate-y-1/2 cursor-pointer rounded-full` });
38848
39680
  var tourBeaconPulse = tv({ base: "hn-ping bg-accent pointer-events-none absolute inset-0 rounded-full" });
38849
39681
  var tourBeaconDot = tv({ base: "bg-accent ring-surface pointer-events-none relative block size-full rounded-full ring-2" });
38850
39682
  var tourHeader = tv({ base: "flex items-start gap-2" });
38851
39683
  var tourFooter = tv({ base: "flex items-center gap-2" });
39684
+ var tourPointer = tv({ base: "hn-tour-pointer" });
39685
+ var tourPointerArrow = tv({ base: "fill-fg stroke-surface absolute top-0 size-6 -translate-x-1 -translate-y-0.5 drop-shadow-md" });
39686
+ var tourPointerTouch = tv({ base: "bg-fg/30 ring-surface absolute top-0 block size-9 -translate-x-1/2 -translate-y-1/2 rounded-full shadow-md ring-2" });
39687
+ var tourKey = tv({ base: "hn-tour-key" });
39688
+ var tourKeyCap = tv({ base: "border-line bg-surface text-fg block min-w-8 -translate-x-1/2 rounded-md border px-2 py-1 text-center text-sm font-medium whitespace-nowrap shadow-md" });
38852
39689
  //#endregion
38853
39690
  //#region src/components/tour/Tour.vue?vue&type=script&setup=true&lang.ts
38854
39691
  var _hoisted_1$68 = ["hidden"];
38855
- var _hoisted_2$43 = ["data-state", "data-hn-tour-hole"];
38856
- var _hoisted_3$24 = ["aria-label"];
38857
- var _hoisted_4$20 = ["id"];
38858
- var _hoisted_5$15 = ["d"];
39692
+ var _hoisted_2$43 = ["data-kind"];
39693
+ var _hoisted_3$24 = [
39694
+ "data-state",
39695
+ "data-mask",
39696
+ "data-hn-tour-hole"
39697
+ ];
39698
+ var _hoisted_4$20 = ["aria-label"];
39699
+ var _hoisted_5$15 = ["id"];
38859
39700
  var _hoisted_6$10 = ["d"];
38860
- var _hoisted_7$7 = { class: "ms-auto flex gap-2" };
39701
+ var _hoisted_7$7 = ["d"];
39702
+ var _hoisted_8$5 = { class: "ms-auto flex gap-2" };
38861
39703
  //#endregion
38862
39704
  //#region src/components/tour/Tour.vue
38863
39705
  var Tour_default = /* @__PURE__ */ defineComponent({
@@ -38866,7 +39708,7 @@ var Tour_default = /* @__PURE__ */ defineComponent({
38866
39708
  props: /*@__PURE__*/ mergeModels({
38867
39709
  steps: {},
38868
39710
  mask: {
38869
- type: Boolean,
39711
+ type: [Boolean, String],
38870
39712
  default: true
38871
39713
  },
38872
39714
  locked: { type: Boolean },
@@ -38875,10 +39717,16 @@ var Tour_default = /* @__PURE__ */ defineComponent({
38875
39717
  type: Boolean,
38876
39718
  default: false
38877
39719
  },
39720
+ blockPage: {
39721
+ type: Boolean,
39722
+ default: false
39723
+ },
39724
+ pointer: { default: "auto" },
38878
39725
  nextText: {},
38879
39726
  prevText: {},
38880
39727
  finishText: {},
38881
39728
  skipText: {},
39729
+ replayText: {},
38882
39730
  beforeChange: {},
38883
39731
  dir: {},
38884
39732
  class: {}
@@ -38891,7 +39739,13 @@ var Tour_default = /* @__PURE__ */ defineComponent({
38891
39739
  "step": { default: 1 },
38892
39740
  "stepModifiers": {}
38893
39741
  }),
38894
- emits: /*@__PURE__*/ mergeModels(["finish", "skip"], ["update:open", "update:step"]),
39742
+ emits: /*@__PURE__*/ mergeModels([
39743
+ "finish",
39744
+ "skip",
39745
+ "close",
39746
+ "stepEnter",
39747
+ "stepLeave"
39748
+ ], ["update:open", "update:step"]),
38895
39749
  setup(__props, { expose: __expose, emit: __emit }) {
38896
39750
  const props = __props;
38897
39751
  const emit = __emit;
@@ -38907,126 +39761,172 @@ var Tour_default = /* @__PURE__ */ defineComponent({
38907
39761
  const isLast = computed(() => current.value >= total.value);
38908
39762
  const busy = ref(false);
38909
39763
  const beaconPending = ref(false);
38910
- const resolvedFor = ref(null);
38911
- const target = shallowRef(null);
38912
- const hole = ref(null);
38913
- const targetRect = ref(null);
38914
- const viewport = ref({
38915
- width: 0,
38916
- height: 0
38917
- });
38918
- const padding = computed(() => currentStep.value.padding ?? 8);
39764
+ const entered = ref(null);
39765
+ const coarse = ref(false);
39766
+ const pointerKind = computed(() => props.pointer === "auto" ? coarse.value ? "touch" : "mouse" : props.pointer);
39767
+ const card = shallowRef(null);
39768
+ const layer = shallowRef(null);
39769
+ const beaconButton = shallowRef(null);
39770
+ const maskElement = shallowRef(null);
39771
+ const blockerElement = shallowRef(null);
39772
+ const pointerElement = shallowRef(null);
39773
+ const keyElement = shallowRef(null);
39774
+ const engine = createTourEngine({
39775
+ pointer: () => pointerElement.value,
39776
+ keyBadge: () => keyElement.value,
39777
+ pointerKind: () => pointerKind.value,
39778
+ cardGap: () => tourCardGap(card.value?.$el)
39779
+ });
39780
+ const tour = shallowRef(engine.getState());
39781
+ const unsubscribe = engine.subscribe(() => tour.value = engine.getState());
38919
39782
  const active = computed(() => open.value && total.value > 0);
38920
- const resolved = computed(() => active.value && resolvedFor.value !== null);
38921
- const beaconVisible = computed(() => resolved.value && !!target.value && beaconPending.value);
38922
- const cardVisible = computed(() => resolved.value && !beaconVisible.value);
38923
- const maskVisible = computed(() => cardVisible.value && props.mask);
38924
- const modal = computed(() => props.mask);
39783
+ const engaged = computed(() => active.value && entered.value !== null);
39784
+ const live = computed(() => engaged.value && entered.value === current.value);
39785
+ const status = computed(() => engaged.value ? tour.value.status : "idle");
39786
+ const beaconVisible = computed(() => live.value && status.value === "ready" && !!tour.value.hole && beaconPending.value);
39787
+ const cardVisible = computed(() => live.value && (status.value === "ready" || status.value === "missing") && tour.value.settled && !beaconVisible.value);
39788
+ let anchoredWhenShown = false;
39789
+ const anchored = computed(() => {
39790
+ if (!cardVisible.value) return anchoredWhenShown;
39791
+ anchoredWhenShown = status.value === "ready" && !!tour.value.hole;
39792
+ return anchoredWhenShown;
39793
+ });
39794
+ let stepWhenShown = current.value;
39795
+ const shown = computed(() => {
39796
+ if (cardVisible.value) stepWhenShown = current.value;
39797
+ return clampTourStep(stepWhenShown, total.value);
39798
+ });
39799
+ const shownStep = computed(() => props.steps[shown.value - 1] ?? {});
39800
+ const maskVisible = computed(() => !!props.mask && status.value !== "idle" && !beaconVisible.value && !(beaconPending.value && status.value === "waiting"));
39801
+ const modal = computed(() => !!props.mask);
39802
+ const scripted = computed(() => !!currentStep.value.play);
38925
39803
  const blocked = computed(() => tourTargetBlocked(currentStep.value, props.blockTarget));
38926
- const blocking = computed(() => cardVisible.value && !!hole.value && blocked.value);
38927
- const spotlight = computed(() => hole.value ? spotlightShape(viewport.value, hole.value, currentStep.value.radius ?? 8) : null);
39804
+ const pageBlocked = computed(() => engaged.value && tourPageBlocked(currentStep.value, props.blockPage));
39805
+ const blocking = computed(() => cardVisible.value && !!tour.value.hole && blocked.value);
39806
+ const targetElements = computed(() => tour.value.elements);
39807
+ const spotlight = computed(() => tour.value.hole ? spotlightShape(tour.value.viewport, tour.value.hole, tour.value.radius) : null);
38928
39808
  const lastSpotlight = shallowRef(null);
38929
39809
  const spotlightState = computed(() => spotlightMask(spotlight.value, lastSpotlight.value));
38930
- const holeStyle = computed(() => hole.value ? {
38931
- left: `${hole.value.x}px`,
38932
- top: `${hole.value.y}px`,
38933
- width: `${hole.value.width}px`,
38934
- height: `${hole.value.height}px`
38935
- } : void 0);
39810
+ const blockerStyle = computed(() => {
39811
+ if (pageBlocked.value) return {
39812
+ left: "0px",
39813
+ top: "0px",
39814
+ width: "100%",
39815
+ height: "100%"
39816
+ };
39817
+ const hole = tour.value.hole;
39818
+ if (!blocking.value || !hole) return void 0;
39819
+ return {
39820
+ left: `${hole.x}px`,
39821
+ top: `${hole.y}px`,
39822
+ width: `${hole.width}px`,
39823
+ height: `${hole.height}px`
39824
+ };
39825
+ });
38936
39826
  const beaconStyle = computed(() => {
38937
- if (!targetRect.value) return void 0;
38938
- const point = beaconPoint(targetRect.value, direction.value);
39827
+ if (!tour.value.targetRect) return void 0;
39828
+ const point = beaconPoint(tour.value.targetRect, direction.value);
38939
39829
  return {
38940
39830
  left: `${point.x}px`,
38941
39831
  top: `${point.y}px`
38942
39832
  };
38943
39833
  });
38944
- const reference = computed(() => target.value ? tourReference(target.value, padding.value) : void 0);
38945
- const card = shallowRef(null);
38946
- const layer = shallowRef(null);
38947
- const beaconButton = shallowRef(null);
39834
+ let holeWhenShown = null;
39835
+ const reference = tourReference(() => {
39836
+ if (cardVisible.value) holeWhenShown = engine.getState().hole;
39837
+ return holeWhenShown;
39838
+ });
38948
39839
  let returnFocus = null;
38949
- const mounted = ref(false);
39840
+ let closeReason = null;
38950
39841
  let navigated = false;
38951
- function resolveTarget() {
38952
- if (!mounted.value || !active.value) return;
38953
- const definition = currentStep.value.target;
38954
- const element = resolveTourTarget(definition);
38955
- if (definition && !element) `${current.value}`;
38956
- target.value = element;
38957
- root.value = element ?? document.documentElement;
38958
- resolvedFor.value = current.value;
38959
- if (element && currentStep.value.scroll !== false) revealTourTarget(element);
38960
- }
38961
- watch([
38962
- active,
38963
- current,
38964
- () => props.steps
38965
- ], resolveTarget, { flush: "post" });
39842
+ let refocusBeacon = false;
39843
+ const mounted = ref(false);
39844
+ function enterStep() {
39845
+ if (!mounted.value) return;
39846
+ if (!active.value) {
39847
+ if (entered.value !== null) exitTour();
39848
+ return;
39849
+ }
39850
+ if (entered.value === current.value) return;
39851
+ const previous = entered.value;
39852
+ refocusBeacon = !!card.value?.$el.contains(document.activeElement);
39853
+ if (previous !== null) {
39854
+ engine.leave();
39855
+ emit("stepLeave", previous);
39856
+ } else {
39857
+ returnFocus = document.activeElement;
39858
+ closeReason = null;
39859
+ }
39860
+ beaconPending.value = tourBeaconOnArrival(currentStep.value, !!props.beacon, previous !== null && navigated);
39861
+ navigated = false;
39862
+ const number = current.value;
39863
+ entered.value = number;
39864
+ emit("stepEnter", number);
39865
+ engine.enter(currentStep.value, number).then((result) => {
39866
+ if (result === "missing" && entered.value === number) `${number}`;
39867
+ });
39868
+ if (!beaconPending.value) engine.play();
39869
+ }
39870
+ function exitTour() {
39871
+ const previous = entered.value;
39872
+ entered.value = null;
39873
+ engine.close();
39874
+ lastSpotlight.value = null;
39875
+ if (previous !== null) emit("stepLeave", previous);
39876
+ emit("close", closeReason ?? "close");
39877
+ closeReason = null;
39878
+ nextTick(restoreFocus);
39879
+ }
39880
+ watch([active, current], enterStep, { flush: "post" });
38966
39881
  onMounted(() => {
38967
39882
  mounted.value = true;
38968
- beaconPending.value = tourBeaconOnArrival(currentStep.value, !!props.beacon, false);
38969
- resolveTarget();
38970
- if (!active.value) return;
38971
- returnFocus = document.activeElement;
38972
- nextTick(() => {
38973
- if (cardVisible.value) card.value?.$el.focus({ preventScroll: true });
38974
- });
39883
+ coarse.value = !!window.matchMedia?.("(pointer: coarse)").matches;
39884
+ enterStep();
38975
39885
  });
38976
- watch([active, current], ([isActive], [wasActive]) => {
38977
- const focusInCard = !!card.value?.$el.contains(document.activeElement);
38978
- beaconPending.value = tourBeaconOnArrival(currentStep.value, !!props.beacon, !!isActive && !!wasActive && navigated);
38979
- navigated = false;
38980
- if (!isActive) {
38981
- resolvedFor.value = null;
38982
- lastSpotlight.value = null;
38983
- }
38984
- if (isActive && !wasActive) returnFocus = document.activeElement;
38985
- if (!isActive && wasActive) nextTick(restoreFocus);
38986
- if (isActive && wasActive && focusInCard) nextTick(() => {
38987
- if (beaconVisible.value) beaconButton.value?.focus();
38988
- });
39886
+ onBeforeUnmount(() => {
39887
+ unsubscribe();
39888
+ engine.close();
38989
39889
  });
38990
39890
  watch([spotlight, maskVisible], ([value, visible]) => {
38991
39891
  if (value && visible) lastSpotlight.value = value;
38992
39892
  });
39893
+ watch(targetElements, (elements) => {
39894
+ root.value = elements[0] ?? document.documentElement;
39895
+ });
38993
39896
  watch(cardVisible, (visible) => {
38994
39897
  if (visible) nextTick(() => card.value?.$el.focus({ preventScroll: true }));
38995
39898
  });
38996
- watchEffect((onCleanup) => {
38997
- const element = target.value;
38998
- if (!mounted.value || !active.value) return;
38999
- const update = () => {
39000
- viewport.value = {
39001
- width: window.innerWidth,
39002
- height: window.innerHeight
39003
- };
39004
- if (!element) {
39005
- hole.value = null;
39006
- targetRect.value = null;
39007
- return;
39008
- }
39009
- const rect = element.getBoundingClientRect();
39010
- targetRect.value = spotlightRect(rect, 0);
39011
- hole.value = spotlightRect(rect, padding.value);
39012
- };
39013
- if (!element) {
39014
- update();
39015
- window.addEventListener("resize", update);
39016
- onCleanup(() => window.removeEventListener("resize", update));
39017
- return;
39018
- }
39019
- onCleanup(watchTourTarget(element, update));
39899
+ watch(beaconVisible, (visible) => {
39900
+ if (!visible || !refocusBeacon) return;
39901
+ refocusBeacon = false;
39902
+ nextTick(() => beaconButton.value?.focus());
39020
39903
  });
39904
+ function useBranch(element) {
39905
+ watch(element, (node, _, onCleanup) => {
39906
+ if (node) onCleanup(addBranch(node));
39907
+ }, {
39908
+ immediate: true,
39909
+ flush: "post"
39910
+ });
39911
+ }
39912
+ useBranch(() => layer.value?.$el);
39913
+ useBranch(() => maskElement.value);
39914
+ useBranch(() => blockerElement.value);
39915
+ useBranch(() => beaconButton.value);
39916
+ const owns = () => tourOwnsInput(layer.value?.$el, scripted.value || pageBlocked.value);
39021
39917
  watchEffect((onCleanup) => {
39022
39918
  if (!cardVisible.value || !modal.value) return;
39023
39919
  const layerElement = layer.value?.$el;
39024
39920
  if (!layerElement?.isConnected) return;
39025
- const reachable = !blocked.value;
39026
- const element = target.value;
39027
- onCleanup(hideOutsideTour([layerElement, element]));
39028
- onCleanup(trapTourFocus(() => [card.value?.$el, reachable ? element : null], () => layer.value?.$el));
39921
+ const reachable = !blocked.value && !pageBlocked.value;
39922
+ const elements = targetElements.value;
39923
+ onCleanup(hideOutsideTour([layerElement, ...elements]));
39924
+ onCleanup(trapTourFocus(() => [card.value?.$el, ...reachable ? elements : []], owns));
39029
39925
  }, { flush: "post" });
39926
+ watchEffect((onCleanup) => {
39927
+ if (!engaged.value || beaconVisible.value) return;
39928
+ onCleanup(listenTourKeys(onKeydown));
39929
+ });
39030
39930
  function restoreFocus() {
39031
39931
  const focus = returnFocus;
39032
39932
  returnFocus = null;
@@ -39055,23 +39955,37 @@ var Tour_default = /* @__PURE__ */ defineComponent({
39055
39955
  }
39056
39956
  function finish() {
39057
39957
  emit("finish");
39958
+ closeReason = "finish";
39058
39959
  open.value = false;
39059
39960
  }
39060
- function skip() {
39961
+ function skip(reason = "skip") {
39061
39962
  if (busy.value) return;
39062
39963
  emit("skip");
39964
+ closeReason = reason;
39063
39965
  open.value = false;
39064
39966
  }
39065
39967
  function close() {
39968
+ closeReason = "close";
39066
39969
  open.value = false;
39067
39970
  }
39068
- function onEscape(event) {
39069
- if (props.locked || busy.value) event.preventDefault();
39971
+ function replay() {
39972
+ if (live.value && !beaconPending.value) engine.replay();
39973
+ }
39974
+ function openBeacon() {
39975
+ beaconPending.value = false;
39976
+ engine.play();
39070
39977
  }
39071
39978
  function preventDismiss(event) {
39072
39979
  event.preventDefault();
39073
39980
  }
39074
39981
  function onKeydown(event) {
39982
+ if (event.defaultPrevented || !owns()) return;
39983
+ if (event.key === "Escape") {
39984
+ event.preventDefault();
39985
+ event.stopPropagation();
39986
+ if (!props.locked) skip("escape");
39987
+ return;
39988
+ }
39075
39989
  const action = tourKeyAction(event, direction.value);
39076
39990
  if (!action) return;
39077
39991
  event.preventDefault();
@@ -39080,22 +39994,27 @@ var Tour_default = /* @__PURE__ */ defineComponent({
39080
39994
  } else if (current.value > 1) prev();
39081
39995
  }
39082
39996
  const slotProps = computed(() => ({
39083
- step: currentStep.value,
39084
- current: current.value,
39997
+ step: shownStep.value,
39998
+ current: shown.value,
39085
39999
  total: total.value,
39086
40000
  busy: busy.value,
40001
+ playing: tour.value.playing,
39087
40002
  next: () => void next(),
39088
40003
  prev: () => void prev(),
39089
- skip
40004
+ skip: () => skip(),
40005
+ replay
39090
40006
  }));
39091
- const popperProps = computed(() => target.value ? {
40007
+ const popperProps = computed(() => anchored.value ? {
39092
40008
  asChild: true,
39093
- reference: reference.value,
39094
- side: currentStep.value.side ?? "bottom",
39095
- align: currentStep.value.align ?? "center",
40009
+ reference,
40010
+ side: shownStep.value.side ?? "bottom",
40011
+ align: shownStep.value.align ?? "center",
39096
40012
  sideOffset: 12,
39097
40013
  collisionPadding: 16,
39098
- arrowPadding: 12
40014
+ arrowPadding: 12,
40015
+ prioritizePosition: true,
40016
+ sticky: "always",
40017
+ updatePositionStrategy: "always"
39099
40018
  } : {
39100
40019
  class: cn(tourCentered(), "hn-anim-pop"),
39101
40020
  "data-state": cardVisible.value ? "open" : "closed"
@@ -39104,27 +40023,68 @@ var Tour_default = /* @__PURE__ */ defineComponent({
39104
40023
  next,
39105
40024
  prev,
39106
40025
  goTo,
39107
- close
40026
+ close,
40027
+ replay
39108
40028
  });
39109
40029
  return (_ctx, _cache) => {
39110
40030
  return total.value > 0 ? (openBlock(), createBlock(unref(Teleport$1), { key: 0 }, {
39111
40031
  default: withCtx(() => [
39112
40032
  createElementVNode("div", {
40033
+ ref_key: "blockerElement",
40034
+ ref: blockerElement,
39113
40035
  "data-hn-tour-blocker": "",
39114
40036
  "aria-hidden": "true",
39115
- hidden: !blocking.value,
40037
+ hidden: !blockerStyle.value,
39116
40038
  class: normalizeClass(unref(tourBlocker)()),
39117
- style: normalizeStyle(blocking.value ? holeStyle.value : void 0)
40039
+ style: normalizeStyle(blockerStyle.value)
39118
40040
  }, null, 14, _hoisted_1$68),
40041
+ createElementVNode("div", {
40042
+ ref_key: "pointerElement",
40043
+ ref: pointerElement,
40044
+ "data-hn-tour-pointer": "",
40045
+ "data-kind": pointerKind.value,
40046
+ "data-state": "hidden",
40047
+ "aria-hidden": "true",
40048
+ class: normalizeClass(unref(tourPointer)())
40049
+ }, [
40050
+ _cache[2] || (_cache[2] = createElementVNode("span", { "data-hn-tour-pointer-ring": "" }, null, -1)),
40051
+ _cache[3] || (_cache[3] = createElementVNode("span", { "data-hn-tour-pointer-ripples": "" }, null, -1)),
40052
+ pointerKind.value === "mouse" ? (openBlock(), createElementBlock("svg", {
40053
+ key: 0,
40054
+ "data-hn-tour-pointer-glyph": "",
40055
+ viewBox: "0 0 24 24",
40056
+ "stroke-width": "1.5",
40057
+ "stroke-linejoin": "round",
40058
+ class: normalizeClass(unref(tourPointerArrow)())
40059
+ }, [..._cache[1] || (_cache[1] = [createElementVNode("path", { d: "M4 2.5v16.2l4.1-3.9 2.8 6.6 2.9-1.2-2.8-6.5h5.8z" }, null, -1)])], 2)) : (openBlock(), createElementBlock("span", {
40060
+ key: 1,
40061
+ "data-hn-tour-pointer-glyph": "",
40062
+ class: normalizeClass(unref(tourPointerTouch)())
40063
+ }, null, 2))
40064
+ ], 10, _hoisted_2$43),
40065
+ createElementVNode("div", {
40066
+ ref_key: "keyElement",
40067
+ ref: keyElement,
40068
+ "data-hn-tour-key": "",
40069
+ "data-state": "hidden",
40070
+ "aria-hidden": "true",
40071
+ class: normalizeClass(unref(tourKey)())
40072
+ }, [createElementVNode("kbd", {
40073
+ "data-hn-tour-key-label": "",
40074
+ class: normalizeClass(unref(tourKeyCap)())
40075
+ }, null, 2)], 2),
39119
40076
  createVNode(unref(Presence), { present: maskVisible.value }, {
39120
40077
  default: withCtx(() => [createElementVNode("div", {
40078
+ ref_key: "maskElement",
40079
+ ref: maskElement,
39121
40080
  "data-hn-tour-mask": "",
39122
40081
  "aria-hidden": "true",
39123
40082
  "data-state": maskVisible.value ? "open" : "closed",
40083
+ "data-mask": props.mask === "dim" ? "dim" : void 0,
39124
40084
  "data-hn-tour-hole": spotlightState.value.hole,
39125
40085
  class: normalizeClass(unref(tourMask)()),
39126
40086
  style: normalizeStyle(spotlightState.value.style)
39127
- }, null, 14, _hoisted_2$43)]),
40087
+ }, null, 14, _hoisted_3$24)]),
39128
40088
  _: 1
39129
40089
  }, 8, ["present"]),
39130
40090
  beaconVisible.value ? (openBlock(), createElementBlock("button", {
@@ -39136,48 +40096,46 @@ var Tour_default = /* @__PURE__ */ defineComponent({
39136
40096
  "aria-label": unref(t).tour.beacon(current.value, currentStep.value.title ?? ""),
39137
40097
  class: normalizeClass(unref(tourBeacon)()),
39138
40098
  style: normalizeStyle(beaconStyle.value),
39139
- onClick: _cache[0] || (_cache[0] = ($event) => beaconPending.value = false)
39140
- }, [createElementVNode("span", { class: normalizeClass(unref(tourBeaconPulse)()) }, null, 2), createElementVNode("span", { class: normalizeClass(unref(tourBeaconDot)()) }, null, 2)], 14, _hoisted_3$24)) : createCommentVNode("", true),
40099
+ onClick: openBeacon
40100
+ }, [createElementVNode("span", { class: normalizeClass(unref(tourBeaconPulse)()) }, null, 2), createElementVNode("span", { class: normalizeClass(unref(tourBeaconDot)()) }, null, 2)], 14, _hoisted_4$20)) : createCommentVNode("", true),
39141
40101
  createVNode(unref(PopperRoot), null, {
39142
40102
  default: withCtx(() => [createVNode(unref(Presence), { present: cardVisible.value }, {
39143
40103
  default: withCtx(() => [createVNode(unref(DismissableLayer), {
39144
40104
  ref_key: "layer",
39145
40105
  ref: layer,
39146
40106
  "as-child": "",
39147
- onEscapeKeyDown: onEscape,
40107
+ onEscapeKeyDown: preventDismiss,
39148
40108
  onPointerDownOutside: preventDismiss,
39149
- onFocusOutside: preventDismiss,
39150
- onDismiss: skip
40109
+ onFocusOutside: preventDismiss
39151
40110
  }, {
39152
- default: withCtx(() => [(openBlock(), createBlock(resolveDynamicComponent(target.value ? unref(PopperContent) : "div"), normalizeProps(guardReactiveProps(popperProps.value)), {
40111
+ default: withCtx(() => [(openBlock(), createBlock(resolveDynamicComponent(anchored.value ? unref(PopperContent) : "div"), normalizeProps(guardReactiveProps(popperProps.value)), {
39153
40112
  default: withCtx(() => [createVNode(Card_default, {
39154
40113
  ref_key: "card",
39155
40114
  ref: card,
39156
40115
  "data-hn-tour": "",
39157
- "data-step": current.value,
40116
+ "data-step": shown.value,
39158
40117
  "data-state": cardVisible.value ? "open" : "closed",
39159
40118
  padded: false,
39160
40119
  role: "dialog",
39161
40120
  tabindex: "-1",
39162
40121
  dir: unref(direction),
39163
40122
  "aria-modal": modal.value ? "true" : void 0,
39164
- "aria-labelledby": currentStep.value.title ? unref(titleId) : void 0,
39165
- "aria-describedby": currentStep.value.description || _ctx.$slots.content ? unref(descriptionId) : void 0,
40123
+ "aria-labelledby": shownStep.value.title ? unref(titleId) : void 0,
40124
+ "aria-describedby": shownStep.value.description || _ctx.$slots.content ? unref(descriptionId) : void 0,
39166
40125
  "aria-busy": busy.value || void 0,
39167
- class: normalizeClass(unref(cn)(unref(tourCard)(), target.value && "hn-anim-pop", props.class)),
39168
- onKeydown
40126
+ class: normalizeClass(unref(cn)(unref(tourCard)(), anchored.value && "hn-anim-pop", props.class))
39169
40127
  }, {
39170
40128
  default: withCtx(() => [
39171
- currentStep.value.title || !props.locked ? (openBlock(), createElementBlock("div", {
40129
+ shownStep.value.title || !props.locked ? (openBlock(), createElementBlock("div", {
39172
40130
  key: 0,
39173
40131
  class: normalizeClass(unref(tourHeader)())
39174
- }, [currentStep.value.title ? (openBlock(), createBlock(Text_default, {
40132
+ }, [shownStep.value.title ? (openBlock(), createBlock(Text_default, {
39175
40133
  key: 0,
39176
40134
  id: unref(titleId),
39177
40135
  weight: "medium",
39178
40136
  class: "min-w-0 flex-1"
39179
40137
  }, {
39180
- default: withCtx(() => [createTextVNode(toDisplayString(currentStep.value.title), 1)]),
40138
+ default: withCtx(() => [createTextVNode(toDisplayString(shownStep.value.title), 1)]),
39181
40139
  _: 1
39182
40140
  }, 8, ["id"])) : createCommentVNode("", true), !props.locked ? (openBlock(), createBlock(CloseButton_default, {
39183
40141
  key: 1,
@@ -39185,19 +40143,19 @@ var Tour_default = /* @__PURE__ */ defineComponent({
39185
40143
  class: "ms-auto -me-1.5 -mt-1.5",
39186
40144
  label: props.skipText ?? unref(t).tour.skip,
39187
40145
  disabled: busy.value,
39188
- onClick: skip
40146
+ onClick: _cache[0] || (_cache[0] = ($event) => skip())
39189
40147
  }, null, 8, ["label", "disabled"])) : createCommentVNode("", true)], 2)) : createCommentVNode("", true),
39190
- currentStep.value.description || _ctx.$slots.content ? (openBlock(), createElementBlock("div", {
40148
+ shownStep.value.description || _ctx.$slots.content ? (openBlock(), createElementBlock("div", {
39191
40149
  key: 1,
39192
40150
  id: unref(descriptionId)
39193
40151
  }, [renderSlot(_ctx.$slots, "content", normalizeProps(guardReactiveProps(slotProps.value)), () => [createVNode(Text_default, {
39194
40152
  tone: "muted",
39195
40153
  size: "sm"
39196
40154
  }, {
39197
- default: withCtx(() => [createTextVNode(toDisplayString(currentStep.value.description), 1)]),
40155
+ default: withCtx(() => [createTextVNode(toDisplayString(shownStep.value.description), 1)]),
39198
40156
  _: 1
39199
- })])], 8, _hoisted_4$20)) : createCommentVNode("", true),
39200
- target.value ? (openBlock(), createBlock(unref(PopperArrow), {
40157
+ })])], 8, _hoisted_5$15)) : createCommentVNode("", true),
40158
+ anchored.value ? (openBlock(), createBlock(unref(PopperArrow), {
39201
40159
  key: 2,
39202
40160
  "data-hn-tour-arrow": "",
39203
40161
  width: unref(16),
@@ -39207,42 +40165,59 @@ var Tour_default = /* @__PURE__ */ defineComponent({
39207
40165
  default: withCtx(() => [createElementVNode("path", {
39208
40166
  d: `${unref(TOUR_ARROW_PATH)}Z`,
39209
40167
  class: "fill-surface"
39210
- }, null, 8, _hoisted_5$15), createElementVNode("path", {
40168
+ }, null, 8, _hoisted_6$10), createElementVNode("path", {
39211
40169
  d: unref(TOUR_ARROW_PATH),
39212
40170
  fill: "none",
39213
40171
  class: "stroke-line",
39214
40172
  "vector-effect": "non-scaling-stroke"
39215
- }, null, 8, _hoisted_6$10)]),
40173
+ }, null, 8, _hoisted_7$7)]),
39216
40174
  _: 1
39217
40175
  }, 8, ["width", "height"])) : createCommentVNode("", true),
39218
- renderSlot(_ctx.$slots, "footer", normalizeProps(guardReactiveProps(slotProps.value)), () => [createElementVNode("div", { class: normalizeClass(unref(tourFooter)()) }, [createVNode(Text_default, {
39219
- as: "span",
39220
- tone: "muted",
39221
- size: "sm",
39222
- class: "tabular-nums"
39223
- }, {
39224
- default: withCtx(() => [createTextVNode(toDisplayString(unref(t).tour.progress(current.value, total.value)), 1)]),
39225
- _: 1
39226
- }), createElementVNode("div", _hoisted_7$7, [current.value > 1 ? (openBlock(), createBlock(Button_default, {
39227
- key: 0,
39228
- "data-hn-tour-prev": "",
39229
- size: "sm",
39230
- variant: "soft",
39231
- tone: "neutral",
39232
- disabled: busy.value,
39233
- onClick: prev
39234
- }, {
39235
- default: withCtx(() => [createTextVNode(toDisplayString(props.prevText ?? unref(t).tour.prev), 1)]),
39236
- _: 1
39237
- }, 8, ["disabled"])) : createCommentVNode("", true), createVNode(Button_default, {
39238
- "data-hn-tour-next": "",
39239
- size: "sm",
39240
- loading: busy.value,
39241
- onClick: next
39242
- }, {
39243
- default: withCtx(() => [createTextVNode(toDisplayString(isLast.value ? props.finishText ?? unref(t).tour.finish : props.nextText ?? unref(t).tour.next), 1)]),
39244
- _: 1
39245
- }, 8, ["loading"])])], 2)])
40176
+ renderSlot(_ctx.$slots, "footer", normalizeProps(guardReactiveProps(slotProps.value)), () => [createElementVNode("div", { class: normalizeClass(unref(tourFooter)()) }, [
40177
+ createVNode(Text_default, {
40178
+ as: "span",
40179
+ tone: "muted",
40180
+ size: "sm",
40181
+ class: "tabular-nums"
40182
+ }, {
40183
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(t).tour.progress(shown.value, total.value)), 1)]),
40184
+ _: 1
40185
+ }),
40186
+ !!shownStep.value.play ? (openBlock(), createBlock(IconButton_default, {
40187
+ key: 0,
40188
+ "data-hn-tour-replay": "",
40189
+ label: props.replayText ?? unref(t).tour.replay,
40190
+ tooltip: false,
40191
+ size: "sm",
40192
+ variant: "ghost",
40193
+ tone: "neutral",
40194
+ pill: "",
40195
+ onClick: replay
40196
+ }, {
40197
+ default: withCtx(() => [createVNode(unref(RotateCcw))]),
40198
+ _: 1
40199
+ }, 8, ["label"])) : createCommentVNode("", true),
40200
+ createElementVNode("div", _hoisted_8$5, [shown.value > 1 ? (openBlock(), createBlock(Button_default, {
40201
+ key: 0,
40202
+ "data-hn-tour-prev": "",
40203
+ size: "sm",
40204
+ variant: "soft",
40205
+ tone: "neutral",
40206
+ disabled: busy.value,
40207
+ onClick: prev
40208
+ }, {
40209
+ default: withCtx(() => [createTextVNode(toDisplayString(props.prevText ?? unref(t).tour.prev), 1)]),
40210
+ _: 1
40211
+ }, 8, ["disabled"])) : createCommentVNode("", true), createVNode(Button_default, {
40212
+ "data-hn-tour-next": "",
40213
+ size: "sm",
40214
+ loading: busy.value,
40215
+ onClick: next
40216
+ }, {
40217
+ default: withCtx(() => [createTextVNode(toDisplayString(shown.value >= total.value ? props.finishText ?? unref(t).tour.finish : props.nextText ?? unref(t).tour.next), 1)]),
40218
+ _: 1
40219
+ }, 8, ["loading"])])
40220
+ ], 2)])
39246
40221
  ]),
39247
40222
  _: 3
39248
40223
  }, 8, [
@@ -40702,8 +41677,8 @@ var Sheet_default = /* @__PURE__ */ defineComponent({
40702
41677
  "open": { type: Boolean },
40703
41678
  "openModifiers": {}
40704
41679
  }),
40705
- emits: ["update:open"],
40706
- setup(__props, { expose: __expose }) {
41680
+ emits: /*@__PURE__*/ mergeModels(["interactOutside"], ["update:open"]),
41681
+ setup(__props, { expose: __expose, emit: __emit }) {
40707
41682
  const props = __props;
40708
41683
  const submitting = provideFormScope();
40709
41684
  const locked = computed(() => props.locked || submitting.value);
@@ -40724,6 +41699,11 @@ var Sheet_default = /* @__PURE__ */ defineComponent({
40724
41699
  function guard(event) {
40725
41700
  if (locked.value) event.preventDefault();
40726
41701
  }
41702
+ const emit = __emit;
41703
+ function onInteractOutside(event) {
41704
+ emit("interactOutside", event);
41705
+ guard(event);
41706
+ }
40727
41707
  function close() {
40728
41708
  open.value = false;
40729
41709
  }
@@ -40742,7 +41722,7 @@ var Sheet_default = /* @__PURE__ */ defineComponent({
40742
41722
  default: withCtx(() => [createVNode(unref(DialogOverlay), { class: "hn-scrim" }), createVNode(unref(DialogContent), {
40743
41723
  "as-child": "",
40744
41724
  onEscapeKeyDown: guard,
40745
- onInteractOutside: guard
41725
+ onInteractOutside
40746
41726
  }, {
40747
41727
  default: withCtx(() => [createVNode(Card_default, mergeProps({
40748
41728
  ref_key: "panel",
@@ -47909,8 +48889,8 @@ var Drawer_default = /* @__PURE__ */ defineComponent({
47909
48889
  "open": { type: Boolean },
47910
48890
  "openModifiers": {}
47911
48891
  }),
47912
- emits: ["update:open"],
47913
- setup(__props, { expose: __expose }) {
48892
+ emits: /*@__PURE__*/ mergeModels(["interactOutside"], ["update:open"]),
48893
+ setup(__props, { expose: __expose, emit: __emit }) {
47914
48894
  const props = __props;
47915
48895
  const slots = useSlots();
47916
48896
  const submitting = provideFormScope();
@@ -47918,6 +48898,11 @@ var Drawer_default = /* @__PURE__ */ defineComponent({
47918
48898
  function guard(e) {
47919
48899
  if (locked.value) e.preventDefault();
47920
48900
  }
48901
+ const emit = __emit;
48902
+ function onInteractOutside(event) {
48903
+ emit("interactOutside", event);
48904
+ guard(event);
48905
+ }
47921
48906
  const { scrollArea, viewport } = useScrollViewport();
47922
48907
  __expose({ viewport });
47923
48908
  const open = useModel(__props, "open");
@@ -47940,7 +48925,7 @@ var Drawer_default = /* @__PURE__ */ defineComponent({
47940
48925
  default: withCtx(() => [createVNode(unref(DialogOverlay), { class: "hn-scrim" }), createVNode(unref(DialogContent), {
47941
48926
  "as-child": "",
47942
48927
  onEscapeKeyDown: guard,
47943
- onInteractOutside: guard
48928
+ onInteractOutside
47944
48929
  }, {
47945
48930
  default: withCtx(() => [createVNode(Card_default, mergeProps({
47946
48931
  ref_key: "content",
@@ -49338,8 +50323,8 @@ var Dialog_default = /* @__PURE__ */ defineComponent({
49338
50323
  "open": { type: Boolean },
49339
50324
  "openModifiers": {}
49340
50325
  }),
49341
- emits: ["update:open"],
49342
- setup(__props, { expose: __expose }) {
50326
+ emits: /*@__PURE__*/ mergeModels(["interactOutside"], ["update:open"]),
50327
+ setup(__props, { expose: __expose, emit: __emit }) {
49343
50328
  const props = __props;
49344
50329
  const slots = useSlots();
49345
50330
  const submitting = provideFormScope();
@@ -49347,6 +50332,11 @@ var Dialog_default = /* @__PURE__ */ defineComponent({
49347
50332
  function guard(e) {
49348
50333
  if (locked.value) e.preventDefault();
49349
50334
  }
50335
+ const emit = __emit;
50336
+ function onInteractOutside(event) {
50337
+ emit("interactOutside", event);
50338
+ guard(event);
50339
+ }
49350
50340
  const { scrollArea, viewport } = useScrollViewport();
49351
50341
  __expose({ viewport });
49352
50342
  const open = useModel(__props, "open");
@@ -49369,7 +50359,7 @@ var Dialog_default = /* @__PURE__ */ defineComponent({
49369
50359
  default: withCtx(() => [createVNode(unref(DialogOverlay), { class: "hn-scrim" }), createElementVNode("div", { class: normalizeClass(unref(dialogWrapper)({ placement: props.placement ?? "auto" })) }, [createVNode(ModalContent_default, {
49370
50360
  "as-child": "",
49371
50361
  onEscapeKeyDown: guard,
49372
- onInteractOutside: guard
50362
+ onInteractOutside
49373
50363
  }, {
49374
50364
  default: withCtx(() => [createVNode(Card_default, mergeProps({
49375
50365
  ref_key: "content",
@@ -49460,6 +50450,28 @@ var Dialog_default = /* @__PURE__ */ defineComponent({
49460
50450
  }
49461
50451
  });
49462
50452
  //#endregion
50453
+ //#region src/components/overlay-branch/OverlayBranch.vue
50454
+ var OverlayBranch_default = /* @__PURE__ */ defineComponent({
50455
+ name: "HnOverlayBranch",
50456
+ __name: "OverlayBranch",
50457
+ props: {
50458
+ asChild: { type: Boolean },
50459
+ as: { default: "div" }
50460
+ },
50461
+ setup(__props) {
50462
+ const props = __props;
50463
+ return (_ctx, _cache) => {
50464
+ return openBlock(), createBlock(unref(DismissableLayerBranch), {
50465
+ as: props.as,
50466
+ "as-child": props.asChild
50467
+ }, {
50468
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
50469
+ _: 3
50470
+ }, 8, ["as", "as-child"]);
50471
+ };
50472
+ }
50473
+ });
50474
+ //#endregion
49463
50475
  //#region src/components/sidebar/SidebarTrigger.vue
49464
50476
  var SidebarTrigger_default = /* @__PURE__ */ defineComponent({
49465
50477
  name: "HnSidebarTrigger",
@@ -58454,6 +59466,6 @@ var Masonry_default = /* @__PURE__ */ defineComponent({
58454
59466
  }
58455
59467
  });
58456
59468
  //#endregion
58457
- export { Accordion_default as Accordion, AccordionContent_default as AccordionContent, AccordionItem_default as AccordionItem, AccordionTrigger_default as AccordionTrigger, Affix_default as Affix, Alert_default as Alert, AlertDialog_default as AlertDialog, Anchor_default as Anchor, AppShell_default as AppShell, AspectRatio_default as AspectRatio, Autocomplete_default as Autocomplete, Avatar_default as Avatar, AvatarGroup_default as AvatarGroup, Badge_default as Badge, Banner_default as Banner, Blockquote_default as Blockquote, Breadcrumb_default as Breadcrumb, BreadcrumbItem_default as BreadcrumbItem, BreadcrumbSeparator_default as BreadcrumbSeparator, Button_default as Button, ButtonGroup_default as ButtonGroup, Calendar_default as Calendar, Callout_default as Callout, Card_default as Card, Carousel_default as Carousel, Center_default as Center, Checkbox_default as Checkbox, CheckboxGroup_default as CheckboxGroup, Chip_default as Chip, CloseButton_default as CloseButton, Code_default as Code, CodeBlock_default as CodeBlock, Collapsible_default as Collapsible, CollapsibleContent_default as CollapsibleContent, CollapsibleTrigger_default as CollapsibleTrigger, Combobox_default as Combobox, CommandPalette_default as CommandPalette, CommandPaletteInput_default as CommandPaletteInput, ConfigProvider_default as ConfigProvider, Container_default as Container, ContextMenu_default as ContextMenu, ContextMenuCheckboxItem_default as ContextMenuCheckboxItem, ContextMenuGroup_default as ContextMenuGroup, ContextMenuItem_default as ContextMenuItem, ContextMenuLabel_default as ContextMenuLabel, ContextMenuRadioGroup_default as ContextMenuRadioGroup, ContextMenuRadioItem_default as ContextMenuRadioItem, ContextMenuSeparator_default as ContextMenuSeparator, ContextMenuSub_default as ContextMenuSub, CopyButton_default as CopyButton, DURATION, DataList_default as DataList, DataTable_default as DataTable, DateField_default as DateField, DatePicker_default as DatePicker, DateRangeField_default as DateRangeField, DateRangePicker_default as DateRangePicker, DateTimePicker_default as DateTimePicker, DescriptionDetails_default as DescriptionDetails, DescriptionList_default as DescriptionList, DescriptionTerm_default as DescriptionTerm, Dialog_default as Dialog, DisclosureIcon_default as DisclosureIcon, Divider_default as Divider, Drawer_default as Drawer, DropdownMenu_default as DropdownMenu, DropdownMenuCheckboxItem_default as DropdownMenuCheckboxItem, DropdownMenuGroup_default as DropdownMenuGroup, DropdownMenuItem_default as DropdownMenuItem, DropdownMenuLabel_default as DropdownMenuLabel, DropdownMenuRadioGroup_default as DropdownMenuRadioGroup, DropdownMenuRadioItem_default as DropdownMenuRadioItem, DropdownMenuSeparator_default as DropdownMenuSeparator, DropdownMenuSub_default as DropdownMenuSub, EASE, Editable_default as Editable, Empty_default as Empty, FileUpload_default as FileUpload, Flex_default as Flex, FloatButton_default as FloatButton, Form_default as Form, FormField_default as FormField, FormLayout_default as FormLayout, Grid_default as Grid, Heading_default as Heading, Highlight_default as Highlight, HoverCard_default as HoverCard, IconButton_default as IconButton, Image_default as Image, ImageGroup_default as ImageGroup, Indicator_default as Indicator, Inline_default as Inline, Input_default as Input, InputGroup_default as InputGroup, InputGroupAddon_default as InputGroupAddon, Kbd_default as Kbd, Lightbox_default as Lightbox, LineClamp_default as LineClamp, Link_default as Link, List_default as List, ListItem_default as ListItem, Listbox_default as Listbox, LoadingOverlay_default as LoadingOverlay, Mark_default as Mark, Masonry_default as Masonry, Menubar_default as Menubar, MenubarCheckboxItem_default as MenubarCheckboxItem, MenubarGroup_default as MenubarGroup, MenubarItem_default as MenubarItem, MenubarLabel_default as MenubarLabel, MenubarMenu_default as MenubarMenu, MenubarRadioGroup_default as MenubarRadioGroup, MenubarRadioItem_default as MenubarRadioItem, MenubarSeparator_default as MenubarSeparator, MenubarSub_default as MenubarSub, MeterGroup_default as MeterGroup, MonthGrid_default as MonthGrid, MultiCombobox_default as MultiCombobox, MultiSelect_default as MultiSelect, NavLink_default as NavLink, NavigationMenu_default as NavigationMenu, NavigationMenuContent_default as NavigationMenuContent, NavigationMenuItem_default as NavigationMenuItem, NavigationMenuLink_default as NavigationMenuLink, NavigationMenuTrigger_default as NavigationMenuTrigger, NumberFormat_default as NumberFormat, NumberInput_default as NumberInput, Page_default as Page, PageAside_default as PageAside, PageBody_default as PageBody, PageHeader_default as PageHeader, Pagination_default as Pagination, PaginationContent_default as PaginationContent, PaginationInfo_default as PaginationInfo, PaginationJump_default as PaginationJump, PaginationSize_default as PaginationSize, Panel_default as Panel, PasswordInput_default as PasswordInput, PinInput_default as PinInput, Popconfirm_default as Popconfirm, Popover_default as Popover, PrevNext_default as PrevNext, PrevNextLink_default as PrevNextLink, Progress_default as Progress, Prose_default as Prose, QRCode_default as QRCode, REQUIRED_SINGLETONS, RESTORE_DEADLINE_MS, RadioGroup_default as RadioGroup, RangeCalendar_default as RangeCalendar, RangeSlider_default as RangeSlider, Rating_default as Rating, Result_default as Result, RingProgress_default as RingProgress, Ripple_default as Ripple, SAVE_THROTTLE_MS, SCROLL_ATOP_ATTR, SCROLL_ATOP_HIDE_PX, SCROLL_AT_ATTR, SCROLL_RESTORE_ATTR, SCROLL_STATE_FIELD, STAGGER, ScrollArea_default as ScrollArea, ScrollTop_default as ScrollTop, SearchInput_default as SearchInput, Section_default as Section, SegmentedControl_default as SegmentedControl, Select_default as Select, Sheet_default as Sheet, Sidebar_default as Sidebar, SidebarGroup_default as SidebarGroup, SidebarLabel_default as SidebarLabel, SidebarTrigger_default as SidebarTrigger, SimpleGrid_default as SimpleGrid, Skeleton_default as Skeleton, Slider_default as Slider, Space_default as Space, Spinner_default as Spinner, SplitButton_default as SplitButton, Splitter_default as Splitter, SplitterHandle_default as SplitterHandle, SplitterPanel_default as SplitterPanel, Spoiler_default as Spoiler, Stack_default as Stack, Statistic_default as Statistic, Stepper_default as Stepper, Switch_default as Switch, TRANSITION, TRAVEL, Table_default as Table, TableBody_default as TableBody, TableCell_default as TableCell, TableHead_default as TableHead, TableHeader_default as TableHeader, TableRow_default as TableRow, Tabs_default as Tabs, TabsContent_default as TabsContent, TabsList_default as TabsList, TabsTrigger_default as TabsTrigger, Tag_default as Tag, TagsInput_default as TagsInput, Text_default as Text, Textarea_default as Textarea, Time_default as Time, TimeField_default as TimeField, Timeline_default as Timeline, Toaster_default as Toaster, Toggle_default as Toggle, Toolbar_default as Toolbar, ToolbarButton_default as ToolbarButton, ToolbarLink_default as ToolbarLink, ToolbarSeparator_default as ToolbarSeparator, ToolbarToggleGroup_default as ToolbarToggleGroup, ToolbarToggleItem_default as ToolbarToggleItem, Tooltip_default as Tooltip, TooltipProvider_default as TooltipProvider, Tour_default as Tour, Tree_default as Tree, TreeSelect_default as TreeSelect, VirtualList_default as VirtualList, VisuallyHidden_default as VisuallyHidden, atopOff, cn, createScrollRestoreSession, createScrollRestorer, cssEase, enUS, firstPaintRestoreScript, jaJP, keepScrollPosition, provideImageResolver, provideUiLocale, readScrollRecord, scrollRestoreScript, toast, tokenize, tokensToHtml, tv, useAvatarGroup, useConfig, useImageResolver, useUiLocale, vTooltip, writeScrollRecord, zhCN };
59469
+ export { Accordion_default as Accordion, AccordionContent_default as AccordionContent, AccordionItem_default as AccordionItem, AccordionTrigger_default as AccordionTrigger, Affix_default as Affix, Alert_default as Alert, AlertDialog_default as AlertDialog, Anchor_default as Anchor, AppShell_default as AppShell, AspectRatio_default as AspectRatio, Autocomplete_default as Autocomplete, Avatar_default as Avatar, AvatarGroup_default as AvatarGroup, Badge_default as Badge, Banner_default as Banner, Blockquote_default as Blockquote, Breadcrumb_default as Breadcrumb, BreadcrumbItem_default as BreadcrumbItem, BreadcrumbSeparator_default as BreadcrumbSeparator, Button_default as Button, ButtonGroup_default as ButtonGroup, Calendar_default as Calendar, Callout_default as Callout, Card_default as Card, Carousel_default as Carousel, Center_default as Center, Checkbox_default as Checkbox, CheckboxGroup_default as CheckboxGroup, Chip_default as Chip, CloseButton_default as CloseButton, Code_default as Code, CodeBlock_default as CodeBlock, Collapsible_default as Collapsible, CollapsibleContent_default as CollapsibleContent, CollapsibleTrigger_default as CollapsibleTrigger, Combobox_default as Combobox, CommandPalette_default as CommandPalette, CommandPaletteInput_default as CommandPaletteInput, ConfigProvider_default as ConfigProvider, Container_default as Container, ContextMenu_default as ContextMenu, ContextMenuCheckboxItem_default as ContextMenuCheckboxItem, ContextMenuGroup_default as ContextMenuGroup, ContextMenuItem_default as ContextMenuItem, ContextMenuLabel_default as ContextMenuLabel, ContextMenuRadioGroup_default as ContextMenuRadioGroup, ContextMenuRadioItem_default as ContextMenuRadioItem, ContextMenuSeparator_default as ContextMenuSeparator, ContextMenuSub_default as ContextMenuSub, CopyButton_default as CopyButton, DURATION, DataList_default as DataList, DataTable_default as DataTable, DateField_default as DateField, DatePicker_default as DatePicker, DateRangeField_default as DateRangeField, DateRangePicker_default as DateRangePicker, DateTimePicker_default as DateTimePicker, DescriptionDetails_default as DescriptionDetails, DescriptionList_default as DescriptionList, DescriptionTerm_default as DescriptionTerm, Dialog_default as Dialog, DisclosureIcon_default as DisclosureIcon, Divider_default as Divider, Drawer_default as Drawer, DropdownMenu_default as DropdownMenu, DropdownMenuCheckboxItem_default as DropdownMenuCheckboxItem, DropdownMenuGroup_default as DropdownMenuGroup, DropdownMenuItem_default as DropdownMenuItem, DropdownMenuLabel_default as DropdownMenuLabel, DropdownMenuRadioGroup_default as DropdownMenuRadioGroup, DropdownMenuRadioItem_default as DropdownMenuRadioItem, DropdownMenuSeparator_default as DropdownMenuSeparator, DropdownMenuSub_default as DropdownMenuSub, EASE, Editable_default as Editable, Empty_default as Empty, FileUpload_default as FileUpload, Flex_default as Flex, FloatButton_default as FloatButton, Form_default as Form, FormField_default as FormField, FormLayout_default as FormLayout, Grid_default as Grid, Heading_default as Heading, Highlight_default as Highlight, HoverCard_default as HoverCard, IconButton_default as IconButton, Image_default as Image, ImageGroup_default as ImageGroup, Indicator_default as Indicator, Inline_default as Inline, Input_default as Input, InputGroup_default as InputGroup, InputGroupAddon_default as InputGroupAddon, Kbd_default as Kbd, Lightbox_default as Lightbox, LineClamp_default as LineClamp, Link_default as Link, List_default as List, ListItem_default as ListItem, Listbox_default as Listbox, LoadingOverlay_default as LoadingOverlay, Mark_default as Mark, Masonry_default as Masonry, Menubar_default as Menubar, MenubarCheckboxItem_default as MenubarCheckboxItem, MenubarGroup_default as MenubarGroup, MenubarItem_default as MenubarItem, MenubarLabel_default as MenubarLabel, MenubarMenu_default as MenubarMenu, MenubarRadioGroup_default as MenubarRadioGroup, MenubarRadioItem_default as MenubarRadioItem, MenubarSeparator_default as MenubarSeparator, MenubarSub_default as MenubarSub, MeterGroup_default as MeterGroup, MonthGrid_default as MonthGrid, MultiCombobox_default as MultiCombobox, MultiSelect_default as MultiSelect, NavLink_default as NavLink, NavigationMenu_default as NavigationMenu, NavigationMenuContent_default as NavigationMenuContent, NavigationMenuItem_default as NavigationMenuItem, NavigationMenuLink_default as NavigationMenuLink, NavigationMenuTrigger_default as NavigationMenuTrigger, NumberFormat_default as NumberFormat, NumberInput_default as NumberInput, OverlayBranch_default as OverlayBranch, Page_default as Page, PageAside_default as PageAside, PageBody_default as PageBody, PageHeader_default as PageHeader, Pagination_default as Pagination, PaginationContent_default as PaginationContent, PaginationInfo_default as PaginationInfo, PaginationJump_default as PaginationJump, PaginationSize_default as PaginationSize, Panel_default as Panel, PasswordInput_default as PasswordInput, PinInput_default as PinInput, Popconfirm_default as Popconfirm, Popover_default as Popover, PrevNext_default as PrevNext, PrevNextLink_default as PrevNextLink, Progress_default as Progress, Prose_default as Prose, QRCode_default as QRCode, REQUIRED_SINGLETONS, RESTORE_DEADLINE_MS, RadioGroup_default as RadioGroup, RangeCalendar_default as RangeCalendar, RangeSlider_default as RangeSlider, Rating_default as Rating, Result_default as Result, RingProgress_default as RingProgress, Ripple_default as Ripple, SAVE_THROTTLE_MS, SCROLL_ATOP_ATTR, SCROLL_ATOP_HIDE_PX, SCROLL_AT_ATTR, SCROLL_RESTORE_ATTR, SCROLL_STATE_FIELD, STAGGER, ScrollArea_default as ScrollArea, ScrollTop_default as ScrollTop, SearchInput_default as SearchInput, Section_default as Section, SegmentedControl_default as SegmentedControl, Select_default as Select, Sheet_default as Sheet, Sidebar_default as Sidebar, SidebarGroup_default as SidebarGroup, SidebarLabel_default as SidebarLabel, SidebarTrigger_default as SidebarTrigger, SimpleGrid_default as SimpleGrid, Skeleton_default as Skeleton, Slider_default as Slider, Space_default as Space, Spinner_default as Spinner, SplitButton_default as SplitButton, Splitter_default as Splitter, SplitterHandle_default as SplitterHandle, SplitterPanel_default as SplitterPanel, Spoiler_default as Spoiler, Stack_default as Stack, Statistic_default as Statistic, Stepper_default as Stepper, Switch_default as Switch, TRANSITION, TRAVEL, Table_default as Table, TableBody_default as TableBody, TableCell_default as TableCell, TableHead_default as TableHead, TableHeader_default as TableHeader, TableRow_default as TableRow, Tabs_default as Tabs, TabsContent_default as TabsContent, TabsList_default as TabsList, TabsTrigger_default as TabsTrigger, Tag_default as Tag, TagsInput_default as TagsInput, Text_default as Text, Textarea_default as Textarea, Time_default as Time, TimeField_default as TimeField, Timeline_default as Timeline, Toaster_default as Toaster, Toggle_default as Toggle, Toolbar_default as Toolbar, ToolbarButton_default as ToolbarButton, ToolbarLink_default as ToolbarLink, ToolbarSeparator_default as ToolbarSeparator, ToolbarToggleGroup_default as ToolbarToggleGroup, ToolbarToggleItem_default as ToolbarToggleItem, Tooltip_default as Tooltip, TooltipProvider_default as TooltipProvider, Tour_default as Tour, Tree_default as Tree, TreeSelect_default as TreeSelect, VirtualList_default as VirtualList, VisuallyHidden_default as VisuallyHidden, atopOff, cn, createScrollRestoreSession, createScrollRestorer, cssEase, enUS, firstPaintRestoreScript, jaJP, keepScrollPosition, provideImageResolver, provideUiLocale, readScrollRecord, scrollRestoreScript, toast, tokenize, tokensToHtml, tv, useAvatarGroup, useConfig, useImageResolver, useUiLocale, vTooltip, writeScrollRecord, zhCN };
58458
59470
 
58459
59471
  //# sourceMappingURL=index.js.map