@leavepulse/ui 0.37.4 → 0.37.6

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 (43) hide show
  1. package/dist/chunks/{LpAddressInput-C8NZWkH_.js → LpAddressInput-DOVpUONY.js} +1 -1
  2. package/dist/chunks/{LpAppShell-1rTB24lI.js → LpAppShell-CRDw1Du5.js} +1 -1
  3. package/dist/chunks/{LpAvatar-D3l4nabg.js → LpAvatar-B3-xAOH3.js} +1 -1
  4. package/dist/chunks/{LpCard-1SeUYPBT.js → LpCard-BhI1N_vL.js} +1 -1
  5. package/dist/chunks/{LpColorPicker-CFC6iaNK.js → LpColorPicker-BlXea7LM.js} +1 -1
  6. package/dist/chunks/{LpConfirmDialog-B6RAvDES.js → LpConfirmDialog-BH7az_E7.js} +1 -1
  7. package/dist/chunks/{LpContextMenu-B6WBLleS.js → LpContextMenu-CwW1QXe_.js} +21 -2
  8. package/dist/chunks/{LpFileTree-C-NFRT0H.js → LpFileTree-_5vFBgaK.js} +1 -1
  9. package/dist/chunks/{LpFileTreeNode-DNJUJiiB.js → LpFileTreeNode-BdcIYKIE.js} +1 -1
  10. package/dist/chunks/{LpLogViewer-y53ZqSVq.js → LpLogViewer-CaRy5MeS.js} +1 -1
  11. package/dist/chunks/{LpModal-D3QxgWaT.js → LpModal-Dq_qXN8-.js} +31 -32
  12. package/dist/chunks/{LpModalNav--a3i7c89.js → LpModalNav-CqxXbTkl.js} +2 -2
  13. package/dist/chunks/{LpNotificationBell-lHePf89W.js → LpNotificationBell-DyGGsMAM.js} +1 -1
  14. package/dist/chunks/{LpPie-c2-q4DJu.js → LpPie-D6OnzwlJ.js} +1 -1
  15. package/dist/chunks/{LpSidebar-DvxMte3k.js → LpSidebar-B1wLj-B2.js} +1 -1
  16. package/dist/chunks/{LpSidebarNav-CqwvT4H8.js → LpSidebarNav-llOcs_Fn.js} +1 -1
  17. package/dist/chunks/{LpThemeSwitcher-r1te9nB2.js → LpThemeSwitcher-Cue-myST.js} +1 -1
  18. package/dist/components/LpAddressInput.vue.js +1 -1
  19. package/dist/components/LpAppShell.vue.js +1 -1
  20. package/dist/components/LpAvatar.vue.js +1 -1
  21. package/dist/components/LpCard.vue.js +1 -1
  22. package/dist/components/LpChart.vue.js +1 -1
  23. package/dist/components/LpColorPicker.vue.js +1 -1
  24. package/dist/components/LpConfirmDialog.vue.js +1 -1
  25. package/dist/components/LpContextMenu.vue.d.ts +2 -2
  26. package/dist/components/LpContextMenu.vue.js +1 -1
  27. package/dist/components/LpFileTree.vue.js +1 -1
  28. package/dist/components/LpFileTreeNode.vue.js +1 -1
  29. package/dist/components/LpLogViewer.vue.js +1 -1
  30. package/dist/components/LpModal.vue.d.ts +7 -7
  31. package/dist/components/LpModal.vue.js +1 -1
  32. package/dist/components/LpModalNav.vue.js +1 -1
  33. package/dist/components/LpNotificationBell.vue.js +1 -1
  34. package/dist/components/LpPie.vue.js +1 -1
  35. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  36. package/dist/components/LpSidebar.vue.js +1 -1
  37. package/dist/components/LpSidebarNav.vue.js +1 -1
  38. package/dist/components/LpTable.vue.js +1 -1
  39. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  40. package/dist/index.js +16 -16
  41. package/package.json +1 -1
  42. package/src/components/LpContextMenu.vue +28 -2
  43. package/src/components/LpModal.vue +31 -46
@@ -6,7 +6,7 @@ import { _ as _sfc_main$3 } from "./LpButton-5VXXCjwF.js";
6
6
  import { _ as _sfc_main$1 } from "./LpFormField-CazBc2-a.js";
7
7
  import { _ as _sfc_main$4 } from "./LpIcon-CCnX5_2j.js";
8
8
  import { _ as _sfc_main$5 } from "./LpInput-9EXWUM9B.js";
9
- import { _ as _sfc_main$7 } from "./LpModal-D3QxgWaT.js";
9
+ import { _ as _sfc_main$7 } from "./LpModal-Dq_qXN8-.js";
10
10
  import { _ as _sfc_main$6 } from "./LpSelect-ANIVtrpM.js";
11
11
  import { useMergedAttrs } from "../composables/useMergedClass.js";
12
12
  const _hoisted_1 = { class: "flex items-stretch gap-2" };
@@ -3,7 +3,7 @@ import { _ as _sfc_main$2 } from "./LpButton-5VXXCjwF.js";
3
3
  import { _ as _sfc_main$3 } from "./LpIcon-CCnX5_2j.js";
4
4
  import { _ as _sfc_main$5 } from "./LpScrollArea-D8xyKXcF.js";
5
5
  import { _ as _sfc_main$4 } from "./LpShift-DXNsauQZ.js";
6
- import { _ as _sfc_main$1 } from "./LpSidebar-DvxMte3k.js";
6
+ import { _ as _sfc_main$1 } from "./LpSidebar-B1wLj-B2.js";
7
7
  import { useMergedAttrs } from "../composables/useMergedClass.js";
8
8
  const _hoisted_1 = { class: "flex min-w-0 flex-1 flex-col" };
9
9
  const _hoisted_2 = { class: "relative flex h-16 shrink-0 items-center gap-3 border-b border-line bg-surface px-4 md:px-6" };
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, computed, ref, onMounted, openBlock, createBlock, withCtx, createVNode, unref, mergeProps, createCommentVNode, createTextVNode, toDisplayString } from "vue";
2
2
  import { AvatarRoot, AvatarImage, AvatarFallback } from "reka-ui";
3
3
  import { tv } from "tailwind-variants";
4
- import { _ as _sfc_main$1 } from "./LpContextMenu-B6WBLleS.js";
4
+ import { _ as _sfc_main$1 } from "./LpContextMenu-CwW1QXe_.js";
5
5
  const __default__ = { inheritAttrs: false };
6
6
  const _sfc_main = /* @__PURE__ */ defineComponent({
7
7
  ...__default__,
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, computed, openBlock, createBlock, withCtx, resolveDynamicComponent, mergeProps, unref, renderSlot } from "vue";
2
2
  import { tv } from "tailwind-variants";
3
3
  import { useMergedAttrs } from "../composables/useMergedClass.js";
4
- import { _ as _sfc_main$1 } from "./LpContextMenu-B6WBLleS.js";
4
+ import { _ as _sfc_main$1 } from "./LpContextMenu-CwW1QXe_.js";
5
5
  const __default__ = { inheritAttrs: false };
6
6
  const _sfc_main = /* @__PURE__ */ defineComponent({
7
7
  ...__default__,
@@ -3,7 +3,7 @@ import { PopoverRoot, PopoverAnchor, PopoverTrigger, PopoverPortal, PopoverConte
3
3
  import { DEFAULT_SWATCHES, formatColor, opaqueCss, parseColor, rgbToHsv, isLight, clampHsv } from "../components/color.js";
4
4
  import { useClipboard } from "../composables/useClipboard.js";
5
5
  import { POPOVER_PANEL } from "../components/dropdown.js";
6
- import { _ as _sfc_main$1 } from "./LpContextMenu-B6WBLleS.js";
6
+ import { _ as _sfc_main$1 } from "./LpContextMenu-CwW1QXe_.js";
7
7
  import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
8
8
  const _hoisted_1 = ["disabled", "aria-label"];
9
9
  const _hoisted_2 = { class: "min-w-0 flex-1 truncate font-mono text-xs text-muted-strong" };
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, computed, openBlock, createBlock, createSlots, withCtx, renderSlot, createVNode, createTextVNode, toDisplayString, createElementVNode, normalizeClass } from "vue";
2
2
  import { _ as _sfc_main$2 } from "./LpButton-5VXXCjwF.js";
3
3
  import { _ as _sfc_main$3 } from "./LpIcon-CCnX5_2j.js";
4
- import { _ as _sfc_main$1 } from "./LpModal-D3QxgWaT.js";
4
+ import { _ as _sfc_main$1 } from "./LpModal-Dq_qXN8-.js";
5
5
  const _hoisted_1 = { class: "inline-flex items-center gap-2.5" };
6
6
  const _sfc_main = /* @__PURE__ */ defineComponent({
7
7
  __name: "LpConfirmDialog",
@@ -35,10 +35,28 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
35
35
  const props = __props;
36
36
  const enabled = computed(() => props.always || props.items.length > 0);
37
37
  const PANEL = `${POPOVER_PANEL} z-(--z-popover) min-w-48 p-1 outline-none`;
38
+ const SELECTABLE = /* @__PURE__ */ new Set(["text", "search", "url", "tel", "password"]);
39
+ let field = null;
40
+ function rememberField() {
41
+ const el = document.activeElement;
42
+ const text = el instanceof HTMLTextAreaElement || el instanceof HTMLInputElement && SELECTABLE.has(el.type);
43
+ field = text ? { el, value: el.value, start: el.selectionStart ?? 0, end: el.selectionEnd ?? 0 } : null;
44
+ }
45
+ function returnFocus(event) {
46
+ const saved = field;
47
+ field = null;
48
+ if (!saved || !saved.el.isConnected) return;
49
+ event.preventDefault();
50
+ saved.el.focus();
51
+ if (saved.el.value === saved.value) saved.el.setSelectionRange(saved.start, saved.end);
52
+ }
38
53
  return (_ctx, _cache) => {
39
54
  return !enabled.value ? renderSlot(_ctx.$slots, "default", { key: 0 }) : (openBlock(), createBlock(unref(ContextMenuRoot), { key: 1 }, {
40
55
  default: withCtx(() => [
41
- createVNode(unref(ContextMenuTrigger), { "as-child": "" }, {
56
+ createVNode(unref(ContextMenuTrigger), {
57
+ "as-child": "",
58
+ onContextmenuCapture: rememberField
59
+ }, {
42
60
  default: withCtx(() => [
43
61
  renderSlot(_ctx.$slots, "default")
44
62
  ]),
@@ -47,7 +65,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
47
65
  __props.items.length ? (openBlock(), createBlock(unref(ContextMenuPortal), { key: 0 }, {
48
66
  default: withCtx(() => [
49
67
  createVNode(unref(ContextMenuContent), {
50
- class: normalizeClass(PANEL)
68
+ class: normalizeClass(PANEL),
69
+ onCloseAutoFocus: returnFocus
51
70
  }, {
52
71
  default: withCtx(() => [
53
72
  (openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item, i) => {
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, ref, watch, computed, openBlock, createElementBlock, mergeProps, unref, Fragment, renderList, normalizeStyle, createBlock, createVNode, withCtx, createElementVNode, renderSlot, normalizeProps, guardReactiveProps, createTextVNode, toDisplayString, createCommentVNode } from "vue";
2
2
  import { computeStats, formatSize, sortNodes, subtreeIds, ancestorIds } from "../components/fileTree.js";
3
3
  import { _ as _sfc_main$1 } from "./LpEmptyState-Dsdqz1Wj.js";
4
- import { _ as _sfc_main$3 } from "./LpFileTreeNode-DNJUJiiB.js";
4
+ import { _ as _sfc_main$3 } from "./LpFileTreeNode-BdcIYKIE.js";
5
5
  import { _ as _sfc_main$2 } from "./LpScrollArea-D8xyKXcF.js";
6
6
  import { useMergedAttrs } from "../composables/useMergedClass.js";
7
7
  const _hoisted_1 = {
@@ -2,7 +2,7 @@ import { defineComponent, computed, resolveComponent, openBlock, createElementBl
2
2
  import { prefersReducedMotion, easingToken } from "../composables/easing.js";
3
3
  import { sortNodes, formatSize, formatModified, fileIcon } from "../components/fileTree.js";
4
4
  import { _ as _sfc_main$3 } from "./LpCheckbox-CVccKYaH.js";
5
- import { _ as _sfc_main$1 } from "./LpContextMenu-B6WBLleS.js";
5
+ import { _ as _sfc_main$1 } from "./LpContextMenu-CwW1QXe_.js";
6
6
  import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
7
7
  import { useMergedAttrs } from "../composables/useMergedClass.js";
8
8
  const _hoisted_1 = ["aria-level", "aria-selected", "aria-expanded", "aria-disabled"];
@@ -2,7 +2,7 @@ import { defineComponent, ref, shallowRef, computed, onMounted, onBeforeUnmount,
2
2
  import { prefersReducedMotion } from "../composables/easing.js";
3
3
  import { useClipboard } from "../composables/useClipboard.js";
4
4
  import { useHotkeys } from "../composables/useHotkeys.js";
5
- import { _ as _sfc_main$3 } from "./LpContextMenu-B6WBLleS.js";
5
+ import { _ as _sfc_main$3 } from "./LpContextMenu-CwW1QXe_.js";
6
6
  import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
7
7
  import { _ as _sfc_main$1 } from "./LpScrollArea-D8xyKXcF.js";
8
8
  import { useMergedAttrs } from "../composables/useMergedClass.js";
@@ -1,4 +1,4 @@
1
- import { defineComponent, computed, useSlots, watch, onBeforeUnmount, ref, openBlock, createBlock, unref, withCtx, createVNode, normalizeStyle, createElementVNode, createElementBlock, renderSlot, createCommentVNode, mergeProps, createTextVNode, toDisplayString, normalizeClass } from "vue";
1
+ import { defineComponent, computed, useSlots, watch, onBeforeUnmount, ref, openBlock, createBlock, unref, withCtx, createVNode, normalizeStyle, createElementVNode, mergeProps, createElementBlock, renderSlot, createCommentVNode, normalizeClass, createTextVNode, toDisplayString } from "vue";
2
2
  import { DialogRoot, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose } from "reka-ui";
3
3
  import { useShift } from "../composables/useShift.js";
4
4
  import { useModalLayer } from "../components/modalDepth.js";
@@ -8,7 +8,7 @@ import { _ as _sfc_main$2 } from "./LpScrollArea-D8xyKXcF.js";
8
8
  const _hoisted_1 = {
9
9
  key: 0,
10
10
  "data-lp-modal-aside": "",
11
- class: "pointer-events-auto flex min-h-0 flex-col"
11
+ class: "flex min-h-0 flex-col"
12
12
  };
13
13
  const _hoisted_2 = {
14
14
  key: 0,
@@ -22,7 +22,7 @@ const _hoisted_4 = {
22
22
  const _hoisted_5 = {
23
23
  key: 1,
24
24
  "data-lp-modal-aside": "",
25
- class: "pointer-events-auto flex min-h-0 flex-col"
25
+ class: "flex min-h-0 flex-col"
26
26
  };
27
27
  const _sfc_main = /* @__PURE__ */ defineComponent({
28
28
  __name: "LpModal",
@@ -83,8 +83,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
83
83
  ];
84
84
  function onOpenAutoFocus(event) {
85
85
  if (props.autoFocus === "none") return;
86
- const panel = panelRef.value?.$el;
87
- if (!(panel instanceof HTMLElement)) return;
86
+ const panel = panelRef.value;
87
+ if (!panel) return;
88
88
  const selectors = props.autoFocus === "auto" ? AUTO_FOCUS_ORDER : [props.autoFocus];
89
89
  for (const selector of selectors) {
90
90
  const target = panel.querySelector(selector);
@@ -110,8 +110,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
110
110
  watch(
111
111
  () => props.open ? panelRef.value : null,
112
112
  (panel) => {
113
- const el = panel?.$el;
114
- sizedEl.value = el instanceof HTMLElement ? el : null;
113
+ sizedEl.value = panel;
115
114
  },
116
115
  { flush: "post" }
117
116
  );
@@ -131,24 +130,24 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
131
130
  class: "fixed inset-0 flex items-center justify-center pointer-events-none",
132
131
  style: normalizeStyle({ zIndex: unref(layer).panel })
133
132
  }, [
134
- createElementVNode("div", {
135
- class: "flex items-start",
136
- style: normalizeStyle(hasAside.value ? { maxHeight: "min(90vh, calc(100dvh - 2rem))" } : void 0)
137
- }, [
138
- __props.open && _ctx.$slots.aside ? (openBlock(), createElementBlock("aside", _hoisted_1, [
139
- renderSlot(_ctx.$slots, "aside")
140
- ])) : createCommentVNode("", true),
141
- createVNode(unref(DialogContent), mergeProps({
142
- ref_key: "panelRef",
143
- ref: panelRef,
144
- class: ["pointer-events-auto flex max-h-[min(90vh,calc(100dvh-2rem))] min-h-0 flex-col overflow-hidden rounded-card border border-line bg-surface-raised shadow-panel outline-none data-[state=open]:animate-[rise-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[rise-out_120ms_cubic-bezier(0.4,0,1,1)]", [widthClass.value, unref(tweening) ? "transition-[height] duration-fast ease-[var(--ease-emphasized)] motion-reduce:transition-none" : ""]],
145
- style: { ...__props.width ? { width: __props.width } : {}, ...hasAside.value ? { alignSelf: "stretch" } : {} }
146
- }, describedByAttrs.value, {
147
- onOpenAutoFocus,
148
- onInteractOutside,
149
- onPointerDownOutside: onInteractOutside
150
- }), {
151
- default: withCtx(() => [
133
+ createVNode(unref(DialogContent), mergeProps({
134
+ class: "pointer-events-auto flex min-h-0 items-start outline-none data-[state=open]:animate-[rise-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[rise-out_120ms_cubic-bezier(0.4,0,1,1)]",
135
+ style: { maxHeight: "min(90vh, calc(100dvh - 2rem))" }
136
+ }, describedByAttrs.value, {
137
+ onOpenAutoFocus,
138
+ onInteractOutside,
139
+ onPointerDownOutside: onInteractOutside
140
+ }), {
141
+ default: withCtx(() => [
142
+ _ctx.$slots.aside ? (openBlock(), createElementBlock("aside", _hoisted_1, [
143
+ renderSlot(_ctx.$slots, "aside")
144
+ ])) : createCommentVNode("", true),
145
+ createElementVNode("div", {
146
+ ref_key: "panelRef",
147
+ ref: panelRef,
148
+ class: normalizeClass(["flex max-h-[min(90vh,calc(100dvh-2rem))] min-h-0 flex-col overflow-hidden rounded-card border border-line bg-surface-raised shadow-panel", [widthClass.value, unref(tweening) ? "transition-[height] duration-fast ease-[var(--ease-emphasized)] motion-reduce:transition-none" : ""]]),
149
+ style: normalizeStyle({ ...__props.width ? { width: __props.width } : {}, ...hasAside.value ? { alignSelf: "stretch" } : {} })
150
+ }, [
152
151
  __props.title || _ctx.$slots.title ? (openBlock(), createElementBlock("header", _hoisted_2, [
153
152
  createElementVNode("div", _hoisted_3, [
154
153
  createVNode(unref(DialogTitle), { class: "text-base font-semibold text-ink" }, {
@@ -202,13 +201,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
202
201
  _ctx.$slots.footer ? (openBlock(), createElementBlock("footer", _hoisted_4, [
203
202
  renderSlot(_ctx.$slots, "footer")
204
203
  ])) : createCommentVNode("", true)
205
- ]),
206
- _: 3
207
- }, 16, ["class", "style"]),
208
- __props.open && _ctx.$slots.asideEnd ? (openBlock(), createElementBlock("aside", _hoisted_5, [
209
- renderSlot(_ctx.$slots, "asideEnd")
210
- ])) : createCommentVNode("", true)
211
- ], 4)
204
+ ], 6),
205
+ _ctx.$slots.asideEnd ? (openBlock(), createElementBlock("aside", _hoisted_5, [
206
+ renderSlot(_ctx.$slots, "asideEnd")
207
+ ])) : createCommentVNode("", true)
208
+ ]),
209
+ _: 3
210
+ }, 16)
212
211
  ], 4)
213
212
  ]),
214
213
  _: 3
@@ -1,8 +1,8 @@
1
1
  import { defineComponent, ref, computed, openBlock, createBlock, createSlots, withCtx, renderSlot, createElementVNode, normalizeClass, createVNode, createCommentVNode, createTextVNode, toDisplayString } from "vue";
2
2
  import { _ as _sfc_main$2 } from "./LpButton-5VXXCjwF.js";
3
3
  import { _ as _sfc_main$3 } from "./LpIcon-CCnX5_2j.js";
4
- import { _ as _sfc_main$1 } from "./LpModal-D3QxgWaT.js";
5
- import { _ as _sfc_main$4 } from "./LpSidebar-DvxMte3k.js";
4
+ import { _ as _sfc_main$1 } from "./LpModal-Dq_qXN8-.js";
5
+ import { _ as _sfc_main$4 } from "./LpSidebar-B1wLj-B2.js";
6
6
  const _hoisted_1 = { class: "flex items-center gap-2" };
7
7
  const _sfc_main = /* @__PURE__ */ defineComponent({
8
8
  __name: "LpModalNav",
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, computed, useModel, getCurrentInstance, openBlock, createBlock, withCtx, createElementVNode, toDisplayString, createElementBlock, createCommentVNode, createVNode, Fragment, renderList, resolveDynamicComponent, normalizeClass, createTextVNode, mergeModels } from "vue";
2
2
  import { _ as _sfc_main$8 } from "./LpBadge-Fe0D1bYx.js";
3
3
  import { _ as _sfc_main$7 } from "./LpButton-5VXXCjwF.js";
4
- import { _ as _sfc_main$5 } from "./LpContextMenu-B6WBLleS.js";
4
+ import { _ as _sfc_main$5 } from "./LpContextMenu-CwW1QXe_.js";
5
5
  import { _ as _sfc_main$3 } from "./LpEmptyState-Dsdqz1Wj.js";
6
6
  import { _ as _sfc_main$6 } from "./LpIcon-CCnX5_2j.js";
7
7
  import { _ as _sfc_main$1 } from "./LpPopover-8268UmlC.js";
@@ -2,7 +2,7 @@ import { defineComponent, computed, ref, watch, onBeforeUnmount, openBlock, crea
2
2
  import { prefersReducedMotion, easeTravel } from "../composables/easing.js";
3
3
  import { useReveal } from "../composables/useReveal.js";
4
4
  import { resolveSlices, arcPath, calloutLabels, formatTick } from "../components/chart.js";
5
- import { _ as _sfc_main$2 } from "./LpContextMenu-B6WBLleS.js";
5
+ import { _ as _sfc_main$2 } from "./LpContextMenu-CwW1QXe_.js";
6
6
  import { _ as _sfc_main$1 } from "./LpIcon-CCnX5_2j.js";
7
7
  import { _ as _sfc_main$4 } from "./LpNumberFlow-amWYaeuA.js";
8
8
  import { _ as _sfc_main$5 } from "./LpRollingText-CM5gkSeF.js";
@@ -1,7 +1,7 @@
1
1
  import { defineComponent, computed, ref, useId, openBlock, createElementBlock, Fragment, createElementVNode, mergeProps, normalizeClass, renderSlot, createCommentVNode, createBlock, createVNode, createSlots, withCtx, normalizeProps, guardReactiveProps } from "vue";
2
2
  import { _ as _sfc_main$3 } from "./LpDrawer-E67O8fFP.js";
3
3
  import { _ as _sfc_main$1 } from "./LpInput-9EXWUM9B.js";
4
- import { _ as _sfc_main$2 } from "./LpSidebarNav-CqwvT4H8.js";
4
+ import { _ as _sfc_main$2 } from "./LpSidebarNav-llOcs_Fn.js";
5
5
  const _hoisted_1 = {
6
6
  key: 2,
7
7
  class: "mt-2 flex shrink-0 flex-col gap-2"
@@ -3,7 +3,7 @@ import { Motion } from "motion-v";
3
3
  import { CollapsibleRoot, CollapsibleTrigger, CollapsibleContent } from "reka-ui";
4
4
  import { usePillTransition } from "../composables/usePillTransition.js";
5
5
  import { _ as _sfc_main$3 } from "./LpBadge-Fe0D1bYx.js";
6
- import { _ as _sfc_main$4 } from "./LpContextMenu-B6WBLleS.js";
6
+ import { _ as _sfc_main$4 } from "./LpContextMenu-CwW1QXe_.js";
7
7
  import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
8
8
  import { _ as _sfc_main$1 } from "./LpScrollArea-D8xyKXcF.js";
9
9
  import { useMergedAttrs } from "../composables/useMergedClass.js";
@@ -1,6 +1,6 @@
1
1
  import { computed, readonly, shallowRef, defineComponent, onMounted, ref, openBlock, createBlock, withCtx, createElementVNode, normalizeClass, createElementBlock, normalizeStyle, createVNode, toDisplayString, createCommentVNode } from "vue";
2
2
  import { prefersReducedMotion, easingToken } from "../composables/easing.js";
3
- import { _ as _sfc_main$1 } from "./LpContextMenu-B6WBLleS.js";
3
+ import { _ as _sfc_main$1 } from "./LpContextMenu-CwW1QXe_.js";
4
4
  import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
5
5
  const sharedShape = { radiusControl: 8, radiusCard: 14, radiusPill: 9999 };
6
6
  const sharedDensity = { spacingUnit: 4, controlSm: 32, controlMd: 38, controlLg: 44 };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpAddressInput-C8NZWkH_.js";
1
+ import { _ as _sfc_main } from "../chunks/LpAddressInput-DOVpUONY.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpAppShell-1rTB24lI.js";
1
+ import { _ as _sfc_main } from "../chunks/LpAppShell-CRDw1Du5.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpAvatar-D3l4nabg.js";
1
+ import { _ as _sfc_main } from "../chunks/LpAvatar-B3-xAOH3.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpCard-1SeUYPBT.js";
1
+ import { _ as _sfc_main } from "../chunks/LpCard-BhI1N_vL.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -4,7 +4,7 @@ import { prefersReducedMotion, easeTravel } from "../composables/easing.js";
4
4
  import { usePillTransition } from "../composables/usePillTransition.js";
5
5
  import { useReveal } from "../composables/useReveal.js";
6
6
  import { normalise, pointCount, resolveLabels, extent, axisTicks, niceScale, plotHeight, plotWidth, xAt, yAt, areaPath, linePath, barPath, nearestIndex, formatTick } from "./chart.js";
7
- import { _ as _sfc_main$1 } from "../chunks/LpContextMenu-B6WBLleS.js";
7
+ import { _ as _sfc_main$1 } from "../chunks/LpContextMenu-CwW1QXe_.js";
8
8
  import { _ as _sfc_main$2 } from "../chunks/LpIcon-CCnX5_2j.js";
9
9
  import { _ as _sfc_main$3 } from "../chunks/LpShift-DXNsauQZ.js";
10
10
  import { useMergedAttrs } from "../composables/useMergedClass.js";
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpColorPicker-CFC6iaNK.js";
1
+ import { _ as _sfc_main } from "../chunks/LpColorPicker-BlXea7LM.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpConfirmDialog-B6RAvDES.js";
1
+ import { _ as _sfc_main } from "../chunks/LpConfirmDialog-BH7az_E7.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -27,11 +27,11 @@ type __VLS_Props = {
27
27
  */
28
28
  always?: boolean;
29
29
  };
30
- declare var __VLS_1: {}, __VLS_16: {};
30
+ declare var __VLS_1: {}, __VLS_18: {};
31
31
  type __VLS_Slots = {} & {
32
32
  default?: (props: typeof __VLS_1) => any;
33
33
  } & {
34
- default?: (props: typeof __VLS_16) => any;
34
+ default?: (props: typeof __VLS_18) => any;
35
35
  };
36
36
  declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
37
37
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpContextMenu-B6WBLleS.js";
1
+ import { _ as _sfc_main } from "../chunks/LpContextMenu-CwW1QXe_.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpFileTree-C-NFRT0H.js";
1
+ import { _ as _sfc_main } from "../chunks/LpFileTree-_5vFBgaK.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpFileTreeNode-DNJUJiiB.js";
1
+ import { _ as _sfc_main } from "../chunks/LpFileTreeNode-BdcIYKIE.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpLogViewer-y53ZqSVq.js";
1
+ import { _ as _sfc_main } from "../chunks/LpLogViewer-CaRy5MeS.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -26,19 +26,19 @@ type __VLS_Props = {
26
26
  */
27
27
  autoFocus?: "auto" | "none" | string;
28
28
  };
29
- declare var __VLS_21: {}, __VLS_41: {}, __VLS_60: {}, __VLS_68: {}, __VLS_70: {}, __VLS_72: {};
29
+ declare var __VLS_31: {}, __VLS_39: {}, __VLS_58: {}, __VLS_66: {}, __VLS_68: {}, __VLS_70: {};
30
30
  type __VLS_Slots = {} & {
31
- aside?: (props: typeof __VLS_21) => any;
31
+ aside?: (props: typeof __VLS_31) => any;
32
32
  } & {
33
- title?: (props: typeof __VLS_41) => any;
33
+ title?: (props: typeof __VLS_39) => any;
34
34
  } & {
35
- default?: (props: typeof __VLS_60) => any;
35
+ default?: (props: typeof __VLS_58) => any;
36
36
  } & {
37
- default?: (props: typeof __VLS_68) => any;
37
+ default?: (props: typeof __VLS_66) => any;
38
38
  } & {
39
- footer?: (props: typeof __VLS_70) => any;
39
+ footer?: (props: typeof __VLS_68) => any;
40
40
  } & {
41
- asideEnd?: (props: typeof __VLS_72) => any;
41
+ asideEnd?: (props: typeof __VLS_70) => any;
42
42
  };
43
43
  declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
44
44
  "update:open": (value: boolean) => any;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpModal-D3QxgWaT.js";
1
+ import { _ as _sfc_main } from "../chunks/LpModal-Dq_qXN8-.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpModalNav--a3i7c89.js";
1
+ import { _ as _sfc_main } from "../chunks/LpModalNav-CqxXbTkl.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpNotificationBell-lHePf89W.js";
1
+ import { _ as _sfc_main } from "../chunks/LpNotificationBell-DyGGsMAM.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpPie-c2-q4DJu.js";
1
+ import { _ as _sfc_main } from "../chunks/LpPie-D6OnzwlJ.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,5 +1,5 @@
1
1
  import { defineComponent, openBlock, createBlock, withCtx, createElementVNode, createElementBlock, Fragment, renderList, toDisplayString, unref } from "vue";
2
- import { _ as _sfc_main$1 } from "../chunks/LpModal-D3QxgWaT.js";
2
+ import { _ as _sfc_main$1 } from "../chunks/LpModal-Dq_qXN8-.js";
3
3
  import { appleModifierLabel } from "../composables/useHotkeys.js";
4
4
  import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper-1tPrXgE0.js";
5
5
  import '../assets/LpShortcutsDialog-B7H-RZLQ.css';const _hoisted_1 = { class: "shortcut-groups" };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpSidebar-DvxMte3k.js";
1
+ import { _ as _sfc_main } from "../chunks/LpSidebar-B1wLj-B2.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpSidebarNav-CqwvT4H8.js";
1
+ import { _ as _sfc_main } from "../chunks/LpSidebarNav-llOcs_Fn.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,6 +1,6 @@
1
1
  import { defineComponent, useAttrs, computed, ref, shallowRef, watch, onBeforeUnmount, openBlock, createElementBlock, normalizeClass, createVNode, mergeProps, withCtx, createElementVNode, createCommentVNode, Fragment, renderList, normalizeStyle, createBlock, createTextVNode, toDisplayString, TransitionGroup, unref, withModifiers, renderSlot, nextTick } from "vue";
2
2
  import { _ as _sfc_main$3 } from "../chunks/LpCheckbox-CVccKYaH.js";
3
- import { _ as _sfc_main$2 } from "../chunks/LpContextMenu-B6WBLleS.js";
3
+ import { _ as _sfc_main$2 } from "../chunks/LpContextMenu-CwW1QXe_.js";
4
4
  import { _ as _sfc_main$4 } from "../chunks/LpIcon-CCnX5_2j.js";
5
5
  import { _ as _sfc_main$5 } from "../chunks/LpPagination-5FxjmmB5.js";
6
6
  import { _ as _sfc_main$1 } from "../chunks/LpScrollArea-D8xyKXcF.js";
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpThemeSwitcher-r1te9nB2.js";
1
+ import { _ as _sfc_main } from "../chunks/LpThemeSwitcher-Cue-myST.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
package/dist/index.js CHANGED
@@ -1,26 +1,26 @@
1
1
  import { _ } from "./chunks/LayoutCanvas-Dd20boUG.js";
2
- import { _ as _2 } from "./chunks/LpAddressInput-C8NZWkH_.js";
2
+ import { _ as _2 } from "./chunks/LpAddressInput-DOVpUONY.js";
3
3
  import { _ as _3 } from "./chunks/LpMapPicker-ul4oYno6.js";
4
4
  import { OSM_TILES, createNominatimProvider, emptyAddress, formatAddress, project, tileUrl, unproject } from "./components/address.js";
5
5
  import { _ as _4 } from "./chunks/LpActionBar-BlvtGB2P.js";
6
6
  import { _ as _5 } from "./chunks/LpAlert-BAYHDSS1.js";
7
- import { _ as _6 } from "./chunks/LpAppShell-1rTB24lI.js";
7
+ import { _ as _6 } from "./chunks/LpAppShell-CRDw1Du5.js";
8
8
  import { _ as _7 } from "./chunks/LpAutocomplete-DExlIZe_.js";
9
- import { _ as _8 } from "./chunks/LpAvatar-D3l4nabg.js";
9
+ import { _ as _8 } from "./chunks/LpAvatar-B3-xAOH3.js";
10
10
  import { _ as _9 } from "./chunks/LpBadge-Fe0D1bYx.js";
11
11
  import { _ as _10 } from "./chunks/LpBreadcrumbs-p4jHe_V-.js";
12
12
  import { _ as _11 } from "./chunks/LpButton-5VXXCjwF.js";
13
13
  import { _ as _12 } from "./chunks/LpCalendar-B7Ko5RdR.js";
14
- import { _ as _13 } from "./chunks/LpCard-1SeUYPBT.js";
14
+ import { _ as _13 } from "./chunks/LpCard-BhI1N_vL.js";
15
15
  import { default as default2 } from "./components/LpChart.vue.js";
16
16
  import { CHART_PALETTE, axisTicks, formatTick, niceScale, resolveSlices } from "./components/chart.js";
17
17
  import { _ as _14 } from "./chunks/LpCheckbox-CVccKYaH.js";
18
18
  import { _ as _15 } from "./chunks/LpCodeBlock-Bo0B4TFR.js";
19
- import { _ as _16 } from "./chunks/LpColorPicker-CFC6iaNK.js";
19
+ import { _ as _16 } from "./chunks/LpColorPicker-BlXea7LM.js";
20
20
  import { DEFAULT_SWATCHES, clampHsv, formatColor, hsvToHsl, hsvToRgb, isLight, normalizeHue, opaqueCss, parseColor, parseHex, rgbToHex, rgbToHsv } from "./components/color.js";
21
21
  import { default as default3 } from "./components/LpCommandPalette.vue.js";
22
- import { _ as _17 } from "./chunks/LpConfirmDialog-B6RAvDES.js";
23
- import { _ as _18 } from "./chunks/LpContextMenu-B6WBLleS.js";
22
+ import { _ as _17 } from "./chunks/LpConfirmDialog-BH7az_E7.js";
23
+ import { _ as _18 } from "./chunks/LpContextMenu-CwW1QXe_.js";
24
24
  import { _ as _19 } from "./chunks/LpDatePicker-BPbvu3cZ.js";
25
25
  import { _ as _20 } from "./chunks/LpDisclosure-ChQYmjlR.js";
26
26
  import { _ as _21 } from "./chunks/LpDivider-CUX46KR0.js";
@@ -28,7 +28,7 @@ import { _ as _22 } from "./chunks/LpDrawer-E67O8fFP.js";
28
28
  import { _ as _23 } from "./chunks/LpDropdownMenu-DJpoqRCb.js";
29
29
  import { default as default4 } from "./components/LpDropzone.vue.js";
30
30
  import { _ as _24 } from "./chunks/LpEmptyState-Dsdqz1Wj.js";
31
- import { _ as _25 } from "./chunks/LpFileTree-C-NFRT0H.js";
31
+ import { _ as _25 } from "./chunks/LpFileTree-_5vFBgaK.js";
32
32
  import { ancestorIds, checkStateOf, checkedCount, computeStats, fileIcon, formatModified, formatSize, sortNodes, subtreeIds, subtreeSize } from "./components/fileTree.js";
33
33
  import { _ as _26 } from "./chunks/LpFormField-CazBc2-a.js";
34
34
  import { _ as _27 } from "./chunks/LpIcon-CCnX5_2j.js";
@@ -38,17 +38,17 @@ import { _ as _29 } from "./chunks/LpInput-9EXWUM9B.js";
38
38
  import { _ as _30 } from "./chunks/LpLightbox-oLqyjOln.js";
39
39
  import { fileNameOf } from "./components/lightbox.js";
40
40
  import { _ as _31 } from "./chunks/LpLink-DCND-zyu.js";
41
- import { _ as _32 } from "./chunks/LpLogViewer-y53ZqSVq.js";
41
+ import { _ as _32 } from "./chunks/LpLogViewer-CaRy5MeS.js";
42
42
  import { _ as _33 } from "./chunks/LpMediaGallery-Cid7PGYx.js";
43
- import { _ as _34 } from "./chunks/LpModal-D3QxgWaT.js";
44
- import { _ as _35 } from "./chunks/LpModalNav--a3i7c89.js";
45
- import { _ as _36 } from "./chunks/LpNotificationBell-lHePf89W.js";
43
+ import { _ as _34 } from "./chunks/LpModal-Dq_qXN8-.js";
44
+ import { _ as _35 } from "./chunks/LpModalNav-CqxXbTkl.js";
45
+ import { _ as _36 } from "./chunks/LpNotificationBell-DyGGsMAM.js";
46
46
  import { _ as _37 } from "./chunks/LpNumberField-CWuX08iX.js";
47
47
  import { _ as _38 } from "./chunks/LpNumberFlow-amWYaeuA.js";
48
48
  import { _ as _39 } from "./chunks/LpOtpInput-y2v-pmiN.js";
49
49
  import { _ as _40 } from "./chunks/LpPagination-5FxjmmB5.js";
50
50
  import { _ as _41 } from "./chunks/LpPasswordInput--sjYCkLS.js";
51
- import { _ as _42 } from "./chunks/LpPie-c2-q4DJu.js";
51
+ import { _ as _42 } from "./chunks/LpPie-D6OnzwlJ.js";
52
52
  import { _ as _43 } from "./chunks/LpPhoneInput-BDSKVl_z.js";
53
53
  import { flagEmoji, loadCountries, matchCountryByValue } from "./components/countries.js";
54
54
  import { _ as _44 } from "./chunks/LpPopover-8268UmlC.js";
@@ -63,7 +63,7 @@ import { _ as _52 } from "./chunks/LpSelect-ANIVtrpM.js";
63
63
  import { _ as _53 } from "./chunks/LpServiceNode-D8uJ8sGk.js";
64
64
  import { _ as _54 } from "./chunks/LpShift-DXNsauQZ.js";
65
65
  import { default as default6 } from "./components/LpShortcutsDialog.vue.js";
66
- import { _ as _55 } from "./chunks/LpSidebar-DvxMte3k.js";
66
+ import { _ as _55 } from "./chunks/LpSidebar-B1wLj-B2.js";
67
67
  import { _ as _56 } from "./chunks/LpSkeleton-CTI-vBgW.js";
68
68
  import { _ as _57 } from "./chunks/LpSlider-BwNIBkAK.js";
69
69
  import { _ as _58 } from "./chunks/LpSparkline-C6xQ2dwv.js";
@@ -74,8 +74,8 @@ import { default as default7 } from "./components/LpTable.vue.js";
74
74
  import { _ as _62 } from "./chunks/LpTableOfContents-CjvxPMpU.js";
75
75
  import { _ as _63 } from "./chunks/LpTabs-Cefe_lys.js";
76
76
  import { _ as _64 } from "./chunks/LpTextarea-t7F6gv8E.js";
77
- import { p as presets, a as parseTheme, s as serializeTheme } from "./chunks/LpThemeSwitcher-r1te9nB2.js";
78
- import { D, _ as _65, N, T, b, c, d, e, f, g, i, l, h, j, n, r, t, k, m, u, v } from "./chunks/LpThemeSwitcher-r1te9nB2.js";
77
+ import { p as presets, a as parseTheme, s as serializeTheme } from "./chunks/LpThemeSwitcher-Cue-myST.js";
78
+ import { D, _ as _65, N, T, b, c, d, e, f, g, i, l, h, j, n, r, t, k, m, u, v } from "./chunks/LpThemeSwitcher-Cue-myST.js";
79
79
  import { _ as _66 } from "./chunks/LpTilt-DuyKbpkA.js";
80
80
  import { _ as _67 } from "./chunks/LpToaster-gDB1EaU3.js";
81
81
  import { _ as _68 } from "./chunks/LpTooltip-hCLPAqMG.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leavepulse/ui",
3
- "version": "0.37.4",
3
+ "version": "0.37.6",
4
4
  "type": "module",
5
5
  "description": "LeavePulse token-driven Vue component kit.",
6
6
  "repository": {
@@ -63,17 +63,43 @@ const ITEM =
63
63
  "group/item flex cursor-pointer select-none items-center gap-2 rounded-md px-2.5 py-1.5 text-sm outline-none transition-[background-color,color] duration-[var(--duration-fast)] data-[disabled]:pointer-events-none data-[disabled]:opacity-45 data-[highlighted]:bg-brand-soft"
64
64
  const ICON =
65
65
  "transition-transform duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] group-data-[highlighted]/item:translate-x-0.5"
66
+
67
+ // A menu opened over a text field takes focus, and on close reka hands it to the
68
+ // trigger, so the caret and the selection the user right-clicked are gone — the
69
+ // next keystroke goes nowhere. Hand focus back to the field instead, with its
70
+ // selection if the menu action left the text as it was.
71
+ type TextField = HTMLInputElement | HTMLTextAreaElement
72
+ const SELECTABLE = new Set(["text", "search", "url", "tel", "password"])
73
+ let field: { el: TextField; value: string; start: number; end: number } | null = null
74
+
75
+ function rememberField() {
76
+ const el = document.activeElement
77
+ const text =
78
+ el instanceof HTMLTextAreaElement || (el instanceof HTMLInputElement && SELECTABLE.has(el.type))
79
+ field = text
80
+ ? { el: el as TextField, value: (el as TextField).value, start: (el as TextField).selectionStart ?? 0, end: (el as TextField).selectionEnd ?? 0 }
81
+ : null
82
+ }
83
+
84
+ function returnFocus(event: Event) {
85
+ const saved = field
86
+ field = null
87
+ if (!saved || !saved.el.isConnected) return
88
+ event.preventDefault()
89
+ saved.el.focus()
90
+ if (saved.el.value === saved.value) saved.el.setSelectionRange(saved.start, saved.end)
91
+ }
66
92
  </script>
67
93
 
68
94
  <template>
69
95
  <slot v-if="!enabled" />
70
96
 
71
97
  <ContextMenuRoot v-else>
72
- <ContextMenuTrigger as-child>
98
+ <ContextMenuTrigger as-child @contextmenu.capture="rememberField">
73
99
  <slot />
74
100
  </ContextMenuTrigger>
75
101
  <ContextMenuPortal v-if="items.length">
76
- <ContextMenuContent :class="PANEL">
102
+ <ContextMenuContent :class="PANEL" @close-auto-focus="returnFocus">
77
103
  <template v-for="(item, i) in items" :key="i">
78
104
  <ContextMenuSeparator v-if="item.separatorBefore" class="my-1 h-px bg-line" />
79
105
 
@@ -8,7 +8,6 @@ import {
8
8
  DialogRoot,
9
9
  DialogTitle,
10
10
  } from "reka-ui"
11
- import type { ComponentPublicInstance } from "vue"
12
11
  import { computed, onBeforeUnmount, ref, useSlots, watch } from "vue"
13
12
  import { useShift } from "../composables/useShift"
14
13
  import { useModalLayer } from "./modalDepth"
@@ -143,7 +142,7 @@ const bodyPad = computed(() =>
143
142
  * scroll area exactly as before. A panel whose size never moves is pinned once
144
143
  * and never transitions.
145
144
  */
146
- const panelRef = ref<ComponentPublicInstance | null>(null)
145
+ const panelRef = ref<HTMLElement | null>(null)
147
146
 
148
147
  /**
149
148
  * Controls that are worth landing on when the dialog opens, in order of
@@ -171,8 +170,8 @@ const AUTO_FOCUS_ORDER = [
171
170
  */
172
171
  function onOpenAutoFocus(event: Event) {
173
172
  if (props.autoFocus === "none") return
174
- const panel = panelRef.value?.$el
175
- if (!(panel instanceof HTMLElement)) return
173
+ const panel = panelRef.value
174
+ if (!panel) return
176
175
 
177
176
  const selectors =
178
177
  props.autoFocus === "auto" ? AUTO_FOCUS_ORDER : [props.autoFocus]
@@ -210,13 +209,10 @@ const {
210
209
  resizing,
211
210
  } = useShift({ axis: "height", enabled: () => props.open })
212
211
 
213
- // reka renders a real element but exposes it as a component instance, so the
214
- // sized element is handed over through $el once the panel has mounted.
215
212
  watch(
216
213
  () => (props.open ? panelRef.value : null),
217
214
  (panel) => {
218
- const el = panel?.$el
219
- sizedEl.value = el instanceof HTMLElement ? el : null
215
+ sizedEl.value = panel
220
216
  },
221
217
  { flush: "post" },
222
218
  )
@@ -265,48 +261,38 @@ watch(
265
261
  class="fixed inset-0 flex items-center justify-center pointer-events-none"
266
262
  :style="{ zIndex: layer.panel }"
267
263
  >
268
- <!-- The dialog and its aside stand in a row of their own, and that row is
269
- what the wrapper centres. Aligning them on the full-screen wrapper
270
- instead would pin them to the top of the WINDOW, and the dialog would
271
- be free to end up shorter than the aside beside it.
272
- `items-start` inside the row: the row collapses to the taller of the
273
- two, both hang from its top edge, and neither is stretched. -->
274
- <div
275
- class="flex items-start"
276
- :style="hasAside ? { maxHeight: 'min(90vh, calc(100dvh - 2rem))' } : undefined"
264
+ <!-- The dialog and its asides stand in one row, and that row IS the
265
+ DialogContent. An aside rendered as a sibling of DialogContent sat
266
+ outside the modal: reka marks everything outside aria-hidden and traps
267
+ focus inside, so a section list beside the dialog could be neither
268
+ tabbed to nor read by a screen reader. Inside DialogContent it belongs
269
+ to the dialog, while the visible card is the inner panel, so nothing
270
+ moves on screen.
271
+ `items-start`: the row collapses to the taller of the two, both hang
272
+ from its top edge, and neither is stretched. Without a description
273
+ reka-ui warns on every open, and the opt-out it checks for is an
274
+ ABSENT `aria-describedby`; a caller that passes a description keeps
275
+ the link to DialogDescription. -->
276
+ <DialogContent
277
+ class="pointer-events-auto flex min-h-0 items-start outline-none data-[state=open]:animate-[rise-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[rise-out_120ms_cubic-bezier(0.4,0,1,1)]"
278
+ :style="{ maxHeight: 'min(90vh, calc(100dvh - 2rem))' }"
279
+ v-bind="describedByAttrs"
280
+ @open-auto-focus="onOpenAutoFocus"
281
+ @interact-outside="onInteractOutside"
282
+ @pointer-down-outside="onInteractOutside"
277
283
  >
278
- <!-- Bound to `open`, not to the slot alone: DialogContent unmounts itself
279
- with the dialog, but an aside is an ordinary node in the portal and
280
- stayed on screen after the dialog closed — a section list floating
281
- over the page with nothing behind it.
282
-
283
- `pointer-events-auto` because the wrapper lets clicks through to the
284
- overlay, and the aside is not the overlay. `data-lp-modal-aside` is
285
- what tells `interact-outside` a click here is not a click on the
286
- scrim — without it the dialog closes under the pointer. -->
287
284
  <aside
288
- v-if="open && $slots.aside"
285
+ v-if="$slots.aside"
289
286
  data-lp-modal-aside
290
- class="pointer-events-auto flex min-h-0 flex-col"
287
+ class="flex min-h-0 flex-col"
291
288
  >
292
289
  <slot name="aside" />
293
290
  </aside>
294
- <!-- Without a description reka-ui warns on every open, and the opt-out it
295
- checks for is an ABSENT `aria-describedby` — despite the message
296
- naming the string "undefined" (a leftover from Radix, where
297
- `aria-describedby={undefined}` is how you drop the attribute).
298
- Dropping it here is what silences the warning; a caller that does
299
- pass a description keeps the generated id and the link to
300
- DialogDescription. -->
301
- <DialogContent
291
+ <div
302
292
  ref="panelRef"
303
- class="pointer-events-auto flex max-h-[min(90vh,calc(100dvh-2rem))] min-h-0 flex-col overflow-hidden rounded-card border border-line bg-surface-raised shadow-panel outline-none data-[state=open]:animate-[rise-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[rise-out_120ms_cubic-bezier(0.4,0,1,1)]"
293
+ class="flex max-h-[min(90vh,calc(100dvh-2rem))] min-h-0 flex-col overflow-hidden rounded-card border border-line bg-surface-raised shadow-panel"
304
294
  :class="[widthClass, tweening ? 'transition-[height] duration-fast ease-[var(--ease-emphasized)] motion-reduce:transition-none' : '']"
305
295
  :style="{ ...(width ? { width } : {}), ...(hasAside ? { alignSelf: 'stretch' } : {}) }"
306
- v-bind="describedByAttrs"
307
- @open-auto-focus="onOpenAutoFocus"
308
- @interact-outside="onInteractOutside"
309
- @pointer-down-outside="onInteractOutside"
310
296
  >
311
297
  <header v-if="title || $slots.title" class="flex shrink-0 items-start justify-between gap-4 p-5 pb-3">
312
298
  <div class="flex flex-col gap-1">
@@ -357,16 +343,15 @@ watch(
357
343
  <footer v-if="$slots.footer" class="flex shrink-0 justify-end gap-2 p-5 pt-4">
358
344
  <slot name="footer" />
359
345
  </footer>
360
- </DialogContent>
361
-
346
+ </div>
362
347
  <aside
363
- v-if="open && $slots.asideEnd"
348
+ v-if="$slots.asideEnd"
364
349
  data-lp-modal-aside
365
- class="pointer-events-auto flex min-h-0 flex-col"
350
+ class="flex min-h-0 flex-col"
366
351
  >
367
352
  <slot name="asideEnd" />
368
353
  </aside>
369
- </div>
354
+ </DialogContent>
370
355
  </div>
371
356
  </DialogPortal>
372
357
  </DialogRoot>