@leavepulse/ui 0.40.1 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/assets/{LpCommandPalette-DDGFwOom.css → LpCommandPalette-Esv0a-gS.css} +21 -21
  2. package/dist/assets/{LpShortcutsDialog-Cap_ALQM.css → LpShortcutsDialog-C6YoQ8_M.css} +7 -7
  3. package/dist/chunks/{LpAddressInput-H5NdhK6c.js → LpAddressInput-CMjaPQVw.js} +1 -1
  4. package/dist/chunks/{LpAppShell-BfqSA1ba.js → LpAppShell-Bcv6EhqU.js} +1 -1
  5. package/dist/chunks/{LpConfirmDialog-BBRnMkV4.js → LpConfirmDialog-BNAvOR24.js} +2 -2
  6. package/dist/chunks/{LpDrawer-B8vBnCWF.js → LpDrawer-DgaS2s2i.js} +6 -4
  7. package/dist/chunks/{LpModal-EyEdRuqF.js → LpModal-8bja5bWS.js} +5 -3
  8. package/dist/chunks/{LpModalNav-BrDtP7b_.js → LpModalNav-w9kfwHqO.js} +3 -3
  9. package/dist/chunks/{LpSidebar-DZ20iBxY.js → LpSidebar-DlTn5nXc.js} +1 -1
  10. package/dist/components/LpAddressInput.vue.js +1 -1
  11. package/dist/components/LpAppShell.vue.js +1 -1
  12. package/dist/components/LpCommandPalette.vue.d.ts +2 -1
  13. package/dist/components/LpCommandPalette.vue.js +140 -76
  14. package/dist/components/LpConfirmDialog.vue.d.ts +2 -1
  15. package/dist/components/LpConfirmDialog.vue.js +1 -1
  16. package/dist/components/LpDrawer.vue.d.ts +4 -2
  17. package/dist/components/LpDrawer.vue.js +1 -1
  18. package/dist/components/LpModal.vue.d.ts +2 -1
  19. package/dist/components/LpModal.vue.js +1 -1
  20. package/dist/components/LpModalNav.vue.d.ts +2 -1
  21. package/dist/components/LpModalNav.vue.js +1 -1
  22. package/dist/components/LpShortcutsDialog.vue.d.ts +8 -11
  23. package/dist/components/LpShortcutsDialog.vue.js +14 -9
  24. package/dist/components/LpSidebar.vue.js +1 -1
  25. package/dist/composables/useGlass.d.ts +9 -0
  26. package/dist/composables/useGlass.js +13 -0
  27. package/dist/composables/useHotkeys.d.ts +43 -2
  28. package/dist/composables/useHotkeys.js +89 -16
  29. package/dist/index.d.ts +3 -3
  30. package/dist/index.js +13 -8
  31. package/package.json +1 -1
  32. package/src/components/LpCommandPalette.vue +114 -36
  33. package/src/components/LpConfirmDialog.vue +2 -2
  34. package/src/components/LpDrawer.vue +9 -5
  35. package/src/components/LpModal.vue +8 -4
  36. package/src/components/LpModalNav.vue +2 -1
  37. package/src/components/LpShortcutsDialog.vue +32 -23
  38. package/src/composables/useGlass.ts +25 -0
  39. package/src/composables/useHotkeys.ts +146 -24
  40. package/src/index.ts +9 -3
@@ -3,67 +3,67 @@ import { DialogRoot, DialogPortal, DialogOverlay, DialogContent, DialogTitle, Di
3
3
  import { _ as _sfc_main$1 } from "../chunks/LpIcon-CCnX5_2j.js";
4
4
  import { _ as _sfc_main$2 } from "../chunks/LpScrollArea-D8xyKXcF.js";
5
5
  import { useAsyncTask } from "../composables/useAsyncTask.js";
6
+ import { useGlass } from "../composables/useGlass.js";
6
7
  import { useClipboard } from "../composables/useClipboard.js";
7
8
  import { useHotkeys } from "../composables/useHotkeys.js";
8
9
  import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper-1tPrXgE0.js";
9
- import '../assets/LpCommandPalette-DDGFwOom.css';const _hoisted_1 = { class: "flex shrink-0 items-center gap-2.5 border-b border-line px-4" };
10
+ import '../assets/LpCommandPalette-Esv0a-gS.css';const _hoisted_1 = { class: "flex shrink-0 items-center gap-2.5 border-b border-line px-4" };
10
11
  const _hoisted_2 = ["title", "onClick"];
11
12
  const _hoisted_3 = ["aria-activedescendant", "placeholder", "onKeydown"];
12
- const _hoisted_4 = { class: "flex min-h-0 flex-1" };
13
- const _hoisted_5 = {
13
+ const _hoisted_4 = {
14
14
  key: 0,
15
15
  class: "px-2 py-10 text-center text-sm text-muted"
16
16
  };
17
- const _hoisted_6 = ["aria-labelledby"];
18
- const _hoisted_7 = ["id"];
19
- const _hoisted_8 = { class: "min-w-0 flex-1" };
20
- const _hoisted_9 = { class: "block truncate font-medium" };
21
- const _hoisted_10 = {
17
+ const _hoisted_5 = ["aria-labelledby"];
18
+ const _hoisted_6 = ["id"];
19
+ const _hoisted_7 = { class: "min-w-0 flex-1" };
20
+ const _hoisted_8 = { class: "block truncate font-medium" };
21
+ const _hoisted_9 = {
22
22
  key: 0,
23
23
  class: "rounded-xs bg-brand/25 text-ink"
24
24
  };
25
- const _hoisted_11 = {
25
+ const _hoisted_10 = {
26
26
  key: 0,
27
27
  class: "mt-0.5 block truncate text-xs text-muted"
28
28
  };
29
- const _hoisted_12 = {
29
+ const _hoisted_11 = {
30
30
  key: 0,
31
31
  class: "rounded-xs bg-brand/20 text-ink"
32
32
  };
33
- const _hoisted_13 = {
33
+ const _hoisted_12 = {
34
34
  key: 0,
35
35
  class: "rounded-xs bg-brand/20 text-ink"
36
36
  };
37
- const _hoisted_14 = {
37
+ const _hoisted_13 = {
38
38
  key: 1,
39
39
  class: "shrink-0 text-xs text-muted"
40
40
  };
41
- const _hoisted_15 = {
41
+ const _hoisted_14 = {
42
42
  key: 0,
43
43
  class: "lp-cmd-pane hidden min-h-0 shrink-0 flex-col border-l border-line md:flex"
44
44
  };
45
- const _hoisted_16 = { class: "lp-cmd-para flex items-center gap-2 text-ink" };
46
- const _hoisted_17 = { class: "min-w-0 text-base font-semibold" };
47
- const _hoisted_18 = {
45
+ const _hoisted_15 = { class: "lp-cmd-para flex items-center gap-2 text-ink" };
46
+ const _hoisted_16 = { class: "min-w-0 text-base font-semibold" };
47
+ const _hoisted_17 = {
48
48
  key: 0,
49
49
  class: "lp-cmd-para mt-0.5 text-xs text-muted"
50
50
  };
51
- const _hoisted_19 = {
51
+ const _hoisted_18 = {
52
52
  key: 0,
53
53
  class: "rounded-xs bg-brand/25 text-ink"
54
54
  };
55
- const _hoisted_20 = { class: "flex shrink-0 items-center gap-4 border-t border-line px-4 py-2.5 text-[11px] text-muted" };
55
+ const _hoisted_19 = { class: "flex shrink-0 items-center gap-4 border-t border-line px-4 py-2.5 text-[11px] text-muted" };
56
+ const _hoisted_20 = { class: "flex items-center gap-1" };
56
57
  const _hoisted_21 = { class: "flex items-center gap-1" };
57
- const _hoisted_22 = { class: "flex items-center gap-1" };
58
- const _hoisted_23 = {
58
+ const _hoisted_22 = {
59
59
  key: 0,
60
60
  class: "flex items-center gap-1"
61
61
  };
62
- const _hoisted_24 = {
62
+ const _hoisted_23 = {
63
63
  key: 1,
64
64
  class: "flex items-center gap-1"
65
65
  };
66
- const _hoisted_25 = { class: "ml-auto flex items-center gap-1" };
66
+ const _hoisted_24 = { class: "ml-auto flex items-center gap-1" };
67
67
  const LATIN = "qwertyuiop[]asdfghjkl;'zxcvbnm,.`";
68
68
  const CYRILLIC = "йцукенгшщзхъфывапролджэячсмитьбюё";
69
69
  const TYPO_MIN = 5;
@@ -89,11 +89,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
89
89
  groupLimit: { default: 0 },
90
90
  layoutFallback: { type: Boolean, default: true },
91
91
  previewPane: { type: Boolean, default: false },
92
- glass: { type: Boolean, default: false }
92
+ glass: { type: Boolean, default: void 0 }
93
93
  },
94
94
  emits: ["update:open", "select", "run"],
95
95
  setup(__props, { emit: __emit }) {
96
96
  const props = __props;
97
+ const frosted = useGlass(() => props.glass);
97
98
  const DEFAULT_LABELS = {
98
99
  navigate: "navigate",
99
100
  select: "select",
@@ -118,9 +119,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
118
119
  }
119
120
  const activeId = computed(() => flat.value.length ? optionId(selectedIndex.value) : void 0);
120
121
  const selectedIndex = ref(0);
122
+ const selectedId = ref(null);
121
123
  const inputRef = ref(null);
122
124
  const scrollRef = ref(null);
123
125
  const trail = shallowRef([]);
126
+ const trailState = shallowRef([]);
124
127
  const mode = computed(() => trail.value[trail.value.length - 1] ?? null);
125
128
  const modeItems = shallowRef([]);
126
129
  const { copy } = useClipboard();
@@ -148,30 +151,37 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
148
151
  }
149
152
  const selectedActions = computed(() => actionsOf(flat.value[selectedIndex.value]));
150
153
  function onTab(event) {
154
+ event.preventDefault();
155
+ event.stopPropagation();
151
156
  if (event.shiftKey) return;
152
157
  const c = flat.value[selectedIndex.value];
153
158
  const actions = selectedActions.value;
154
159
  if (!c || !actions.length) return;
155
- event.preventDefault();
156
- event.stopPropagation();
157
160
  enter({ id: `${c.id}:actions`, label: c.label, icon: c.icon, children: actions });
158
161
  }
159
162
  function enter(c) {
163
+ trailState.value = [...trailState.value, { query: query.value, selectedId: selectedId.value }];
160
164
  trail.value = [...trail.value, c];
161
165
  query.value = "";
162
- selectedIndex.value = 0;
166
+ select(0);
163
167
  modeItems.value = Array.isArray(c.children) ? c.children : [];
164
168
  refresh();
165
169
  inputRef.value?.focus();
166
170
  }
167
171
  function popTo(depth) {
172
+ const state = trailState.value[depth] || { query: "", selectedId: null };
168
173
  const next = trail.value.slice(0, Math.max(0, depth));
174
+ trailState.value = trailState.value.slice(0, Math.max(0, depth));
169
175
  trail.value = next;
170
- query.value = "";
171
- selectedIndex.value = 0;
172
176
  const parent = next[next.length - 1];
173
177
  modeItems.value = parent && Array.isArray(parent.children) ? parent.children : [];
178
+ query.value = state.query;
179
+ select(0);
174
180
  refresh();
181
+ void nextTick(() => {
182
+ const index = state.selectedId ? flat.value.findIndex((c) => c.id === state.selectedId) : -1;
183
+ select(index >= 0 ? index : 0);
184
+ });
175
185
  inputRef.value?.focus();
176
186
  }
177
187
  function back() {
@@ -232,12 +242,30 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
232
242
  if (term.length < TYPO_MIN) return false;
233
243
  return label.split(/[^\p{L}\p{N}]+/u).some((word) => withinOne(term, word) || word.length > term.length && withinOne(term, word.slice(0, term.length)));
234
244
  }
245
+ const QUERY_TOKEN = /(-?)(?:(in):)?(?:"([^"]*)"|(\S+))/giu;
246
+ function searchTerms(value) {
247
+ const out = { include: [], exclude: [], groups: [] };
248
+ QUERY_TOKEN.lastIndex = 0;
249
+ for (let match; match = QUERY_TOKEN.exec(value); ) {
250
+ const text2 = (match[3] ?? match[4] ?? "").trim().toLowerCase();
251
+ if (!text2) continue;
252
+ if (match[2] && !match[1]) out.groups.push(text2);
253
+ else if (match[1]) out.exclude.push(text2);
254
+ else out.include.push(text2);
255
+ }
256
+ return out;
257
+ }
258
+ function matches(c, term) {
259
+ return c.label.toLowerCase().includes(term) || (c.keywords ?? []).some((keyword) => keyword.toLowerCase().includes(term)) || (c.description?.toLowerCase().includes(term) ?? false);
260
+ }
235
261
  function score(c, terms) {
236
262
  const label = c.label.toLowerCase();
237
263
  const keywords = (c.keywords ?? []).map((k) => k.toLowerCase());
238
264
  const description = c.description?.toLowerCase() ?? "";
239
- let total = 0;
240
- for (const term of terms) {
265
+ const group = c.group?.toLowerCase() ?? "";
266
+ if (terms.exclude.some((term) => matches(c, term)) || terms.groups.some((term) => !group.includes(term))) return 0;
267
+ let total = terms.include.length ? 0 : 1;
268
+ for (const term of terms.include) {
241
269
  let hit = (label.includes(term) ? 4 : 0) + (keywords.some((k) => k.includes(term)) ? 3 : 0) + (description.includes(term) ? 2 : 0);
242
270
  if (!hit && nearWord(term, label)) hit = 1;
243
271
  if (!hit) return 0;
@@ -248,15 +276,19 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
248
276
  function rank(items, terms) {
249
277
  return items.map((c) => ({ c, score: score(c, terms) })).filter((e) => e.score > 0).sort((a, b) => b.score - a.score || a.c.label.localeCompare(b.c.label)).map((e) => e.c);
250
278
  }
251
- const typedTerms = computed(() => query.value.trim().toLowerCase().split(/\s+/).filter(Boolean));
252
279
  const local = computed(() => {
253
- const terms = typedTerms.value;
254
- if (!terms.length) return { items: source.value.filter((c) => !c.hidden), terms };
255
- const items = rank(source.value, terms);
256
- if (items.length || !props.layoutFallback) return { items, terms };
257
- const swapped = terms.map(swapLayout);
258
- const other = rank(source.value, swapped);
259
- return other.length ? { items: other, terms: swapped } : { items, terms };
280
+ const terms = searchTerms(query.value);
281
+ const filtered = query.value.trim() ? source.value : source.value.filter((c) => !c.hidden);
282
+ if (!terms.include.length && !terms.exclude.length && !terms.groups.length) return { items: filtered, terms: [] };
283
+ const items = rank(filtered, terms);
284
+ if (items.length || !props.layoutFallback) return { items, terms: terms.include };
285
+ const swapped = {
286
+ include: terms.include.map(swapLayout),
287
+ exclude: terms.exclude.map(swapLayout),
288
+ groups: terms.groups.map(swapLayout)
289
+ };
290
+ const other = rank(filtered, swapped);
291
+ return other.length ? { items: other, terms: swapped.include } : { items, terms: terms.include };
260
292
  });
261
293
  const ranked = computed(() => local.value.items);
262
294
  const fetched = computed(() => {
@@ -362,16 +394,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
362
394
  return parts;
363
395
  }
364
396
  watch(query, () => {
365
- selectedIndex.value = 0;
397
+ select(0);
366
398
  refresh();
367
399
  });
368
400
  watch([query, trail, () => props.open], () => {
369
401
  expanded.value = /* @__PURE__ */ new Set();
370
402
  });
371
403
  watch(
372
- () => flat.value.length,
373
- (len) => {
374
- if (selectedIndex.value >= len) selectedIndex.value = Math.max(0, len - 1);
404
+ () => flat.value.map((c) => c.id).join("|"),
405
+ () => {
406
+ const index = selectedId.value ? flat.value.findIndex((c) => c.id === selectedId.value) : -1;
407
+ select(index >= 0 ? index : 0);
375
408
  }
376
409
  );
377
410
  watch([selectedIndex, () => flat.value.map((c) => c.id).join("|")], async () => {
@@ -384,13 +417,40 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
384
417
  );
385
418
  el?.scrollIntoView({ block: "nearest" });
386
419
  }
420
+ const keyboardSelection = ref(false);
421
+ function select(index, keyboard = false) {
422
+ const len = flat.value.length;
423
+ selectedIndex.value = len ? Math.max(0, Math.min(index, len - 1)) : 0;
424
+ selectedId.value = flat.value[selectedIndex.value]?.id ?? null;
425
+ if (keyboard) keyboardSelection.value = true;
426
+ }
387
427
  function moveDown() {
388
428
  const len = flat.value.length;
389
- if (len) selectedIndex.value = (selectedIndex.value + 1) % len;
429
+ if (len) select((selectedIndex.value + 1) % len, true);
390
430
  }
391
431
  function moveUp() {
392
432
  const len = flat.value.length;
393
- if (len) selectedIndex.value = (selectedIndex.value - 1 + len) % len;
433
+ if (len) select((selectedIndex.value - 1 + len) % len, true);
434
+ }
435
+ function movePage(direction) {
436
+ select(selectedIndex.value + direction * 8, true);
437
+ }
438
+ function onPaletteKeydown(event) {
439
+ if (event.isComposing) return;
440
+ if (!["ArrowDown", "ArrowUp", "Home", "End", "PageDown", "PageUp"].includes(event.key)) return;
441
+ event.preventDefault();
442
+ event.stopPropagation();
443
+ if (event.key === "ArrowDown") moveDown();
444
+ else if (event.key === "ArrowUp") moveUp();
445
+ else if (event.key === "Home") select(0, true);
446
+ else if (event.key === "End") select(flat.value.length - 1, true);
447
+ else movePage(event.key === "PageDown" ? 1 : -1);
448
+ }
449
+ function onPointerMove() {
450
+ keyboardSelection.value = false;
451
+ }
452
+ function onPointerEnter(c) {
453
+ if (!keyboardSelection.value) select(flatIndexOf(c));
394
454
  }
395
455
  function runSelected(event) {
396
456
  const c = flat.value[selectedIndex.value];
@@ -429,7 +489,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
429
489
  emit("run", c.id, c);
430
490
  if (c.keepOpen) {
431
491
  query.value = "";
432
- selectedIndex.value = 0;
492
+ select(0);
433
493
  inputRef.value?.focus();
434
494
  return;
435
495
  }
@@ -450,8 +510,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
450
510
  async (o) => {
451
511
  cancel();
452
512
  query.value = "";
453
- selectedIndex.value = 0;
513
+ select(0);
514
+ selectedId.value = null;
454
515
  trail.value = [];
516
+ trailState.value = [];
455
517
  modeItems.value = [];
456
518
  found.value = [];
457
519
  failed.value = false;
@@ -482,13 +544,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
482
544
  createVNode(unref(DialogPortal), null, {
483
545
  default: withCtx(() => [
484
546
  createVNode(unref(DialogOverlay), {
485
- class: normalizeClass([{ "lp-scrim--light": __props.glass }, "lp-scrim fixed inset-0 z-(--z-overlay) data-[state=open]:animate-[fade-in_150ms_ease] data-[state=closed]:animate-[fade-out_130ms_ease]"])
547
+ class: normalizeClass([{ "lp-scrim--light": unref(frosted) }, "lp-scrim fixed inset-0 z-(--z-overlay) data-[state=open]:animate-[fade-in_150ms_ease] data-[state=closed]:animate-[fade-out_130ms_ease]"])
486
548
  }, null, 8, ["class"]),
487
549
  createVNode(unref(DialogContent), {
488
- class: normalizeClass(["lp-cmd-dialog fixed left-1/2 top-[12vh] z-(--z-modal) flex max-h-[76vh] -translate-x-1/2 flex-col overflow-hidden rounded-card border border-line shadow-panel outline-none data-[state=open]:animate-[pop-in_160ms_var(--ease-emphasized)] data-[state=closed]:animate-[pop-out_130ms_ease]", [__props.glass ? "lp-glass-overlay" : "bg-surface-raised", __props.previewPane && "lp-cmd-split"]]),
550
+ class: normalizeClass(["lp-cmd-dialog fixed left-1/2 top-[12vh] z-(--z-modal) flex max-h-[76vh] -translate-x-1/2 flex-col overflow-hidden rounded-card border border-line shadow-panel outline-none data-[state=open]:animate-[pop-in_160ms_var(--ease-emphasized)] data-[state=closed]:animate-[pop-out_130ms_ease]", [unref(frosted) ? "lp-glass-overlay" : "bg-surface-raised", __props.previewPane && "lp-cmd-split"]]),
489
551
  "data-pane": paneOpen.value ? "open" : void 0,
490
552
  onOpenAutoFocus: _cache[2] || (_cache[2] = withModifiers(() => {
491
- }, ["prevent"]))
553
+ }, ["prevent"])),
554
+ onKeydownCapture: onPaletteKeydown
492
555
  }, {
493
556
  default: withCtx(() => [
494
557
  createVNode(unref(DialogTitle), { class: "sr-only" }, {
@@ -549,8 +612,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
549
612
  placeholder: mode.value?.childPlaceholder ?? __props.placeholder,
550
613
  class: "h-12 min-w-0 flex-1 bg-transparent text-sm text-ink outline-none placeholder:text-muted",
551
614
  onKeydown: [
552
- withKeys(withModifiers(moveDown, ["prevent"]), ["down"]),
553
- withKeys(withModifiers(moveUp, ["prevent"]), ["up"]),
554
615
  withKeys(withModifiers(runSelected, ["prevent"]), ["enter"]),
555
616
  withKeys(onBackspace, ["backspace"]),
556
617
  withKeys(onEscape, ["esc"]),
@@ -561,7 +622,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
561
622
  ]),
562
623
  _cache[6] || (_cache[6] = createElementVNode("kbd", { class: "shrink-0 rounded border border-line px-1.5 py-0.5 text-[10px] text-muted" }, "esc", -1))
563
624
  ]),
564
- createElementVNode("div", _hoisted_4, [
625
+ createElementVNode("div", {
626
+ class: "flex min-h-0 flex-1",
627
+ onPointermove: onPointerMove
628
+ }, [
565
629
  createVNode(_sfc_main$2, {
566
630
  ref_key: "scrollRef",
567
631
  ref: scrollRef,
@@ -569,7 +633,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
569
633
  "content-class": "p-2"
570
634
  }, {
571
635
  default: withCtx(() => [
572
- flat.value.length === 0 && !failed.value ? (openBlock(), createElementBlock("p", _hoisted_5, toDisplayString(unref(searching) ? text.value.searching : __props.emptyText), 1)) : createCommentVNode("", true),
636
+ flat.value.length === 0 && !failed.value ? (openBlock(), createElementBlock("p", _hoisted_4, toDisplayString(unref(searching) ? text.value.searching : __props.emptyText), 1)) : createCommentVNode("", true),
573
637
  createElementVNode("div", {
574
638
  id: listId,
575
639
  role: "listbox"
@@ -584,7 +648,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
584
648
  key: 0,
585
649
  id: `${listId}-g${gi}`,
586
650
  class: "px-2 pb-1 pt-3 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted"
587
- }, toDisplayString(group.name), 9, _hoisted_7)) : createCommentVNode("", true),
651
+ }, toDisplayString(group.name), 9, _hoisted_6)) : createCommentVNode("", true),
588
652
  (openBlock(true), createElementBlock(Fragment, null, renderList(group.items, (c) => {
589
653
  return openBlock(), createBlock(resolveDynamicComponent(c.href ? "a" : "button"), {
590
654
  id: optionId(flatIndexOf(c)),
@@ -602,7 +666,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
602
666
  flatIndexOf(c) === selectedIndex.value ? "bg-brand-soft text-brand" : unref(moreOf).has(c) ? "text-muted hover:bg-surface-soft/60" : "text-ink hover:bg-surface-soft/60"
603
667
  ]]),
604
668
  onClick: ($event) => onRowClick($event, c),
605
- onPointerenter: ($event) => selectedIndex.value = flatIndexOf(c)
669
+ onPointerenter: ($event) => onPointerEnter(c)
606
670
  }, {
607
671
  default: withCtx(() => [
608
672
  c.icon ? (openBlock(), createBlock(_sfc_main$1, {
@@ -611,24 +675,24 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
611
675
  size: 16,
612
676
  class: normalizeClass(["shrink-0", { "mt-0.5": c.excerpt }])
613
677
  }, null, 8, ["name", "class"])) : createCommentVNode("", true),
614
- createElementVNode("span", _hoisted_8, [
615
- createElementVNode("span", _hoisted_9, [
678
+ createElementVNode("span", _hoisted_7, [
679
+ createElementVNode("span", _hoisted_8, [
616
680
  (openBlock(true), createElementBlock(Fragment, null, renderList(highlight(c.label, c.highlight), (p, pi) => {
617
681
  return openBlock(), createElementBlock(Fragment, {
618
682
  key: `l${pi}`
619
683
  }, [
620
- p.hit ? (openBlock(), createElementBlock("mark", _hoisted_10, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
684
+ p.hit ? (openBlock(), createElementBlock("mark", _hoisted_9, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
621
685
  createTextVNode(toDisplayString(p.text), 1)
622
686
  ], 64))
623
687
  ], 64);
624
688
  }), 128))
625
689
  ]),
626
- c.description ? (openBlock(), createElementBlock("span", _hoisted_11, [
690
+ c.description ? (openBlock(), createElementBlock("span", _hoisted_10, [
627
691
  (openBlock(true), createElementBlock(Fragment, null, renderList(highlight(c.description, c.highlight), (p, pi) => {
628
692
  return openBlock(), createElementBlock(Fragment, {
629
693
  key: `d${pi}`
630
694
  }, [
631
- p.hit ? (openBlock(), createElementBlock("mark", _hoisted_12, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
695
+ p.hit ? (openBlock(), createElementBlock("mark", _hoisted_11, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
632
696
  createTextVNode(toDisplayString(p.text), 1)
633
697
  ], 64))
634
698
  ], 64);
@@ -643,14 +707,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
643
707
  return openBlock(), createElementBlock(Fragment, {
644
708
  key: `e${pi}`
645
709
  }, [
646
- p.hit ? (openBlock(), createElementBlock("mark", _hoisted_13, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
710
+ p.hit ? (openBlock(), createElementBlock("mark", _hoisted_12, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
647
711
  createTextVNode(toDisplayString(p.text), 1)
648
712
  ], 64))
649
713
  ], 64);
650
714
  }), 128))
651
715
  ], 4)) : createCommentVNode("", true)
652
716
  ]),
653
- c.shortcut ? (openBlock(), createElementBlock("kbd", _hoisted_14, toDisplayString(c.shortcut), 1)) : c.children ? (openBlock(), createBlock(_sfc_main$1, {
717
+ c.shortcut ? (openBlock(), createElementBlock("kbd", _hoisted_13, toDisplayString(c.shortcut), 1)) : c.children ? (openBlock(), createBlock(_sfc_main$1, {
654
718
  key: 2,
655
719
  name: "lucide:chevron-right",
656
720
  size: 14,
@@ -660,7 +724,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
660
724
  _: 2
661
725
  }, 1064, ["id", "href", "type", "aria-selected", "aria-disabled", "data-cmd-index", "disabled", "class", "onClick", "onPointerenter"]);
662
726
  }), 128))
663
- ], 8, _hoisted_6);
727
+ ], 8, _hoisted_5);
664
728
  }), 128))
665
729
  ]),
666
730
  failed.value ? (openBlock(), createElementBlock("div", {
@@ -688,7 +752,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
688
752
  }, 512),
689
753
  createVNode(Transition, { name: "lp-cmd-pane" }, {
690
754
  default: withCtx(() => [
691
- paneOpen.value ? (openBlock(), createElementBlock("aside", _hoisted_15, [
755
+ paneOpen.value ? (openBlock(), createElementBlock("aside", _hoisted_14, [
692
756
  createVNode(_sfc_main$2, {
693
757
  ref_key: "previewRef",
694
758
  ref: previewRef,
@@ -700,16 +764,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
700
764
  key: active.value.id
701
765
  }, [
702
766
  renderSlot(_ctx.$slots, "preview", { command: active.value }, () => [
703
- createElementVNode("div", _hoisted_16, [
767
+ createElementVNode("div", _hoisted_15, [
704
768
  active.value.icon ? (openBlock(), createBlock(_sfc_main$1, {
705
769
  key: 0,
706
770
  name: active.value.icon,
707
771
  size: 16,
708
772
  class: "shrink-0 text-muted"
709
773
  }, null, 8, ["name"])) : createCommentVNode("", true),
710
- createElementVNode("h3", _hoisted_17, toDisplayString(active.value.label), 1)
774
+ createElementVNode("h3", _hoisted_16, toDisplayString(active.value.label), 1)
711
775
  ]),
712
- active.value.description ? (openBlock(), createElementBlock("p", _hoisted_18, toDisplayString(active.value.description), 1)) : createCommentVNode("", true),
776
+ active.value.description ? (openBlock(), createElementBlock("p", _hoisted_17, toDisplayString(active.value.description), 1)) : createCommentVNode("", true),
713
777
  (openBlock(true), createElementBlock(Fragment, null, renderList(paragraphs.value, (para, i) => {
714
778
  return openBlock(), createElementBlock("p", {
715
779
  key: i,
@@ -720,7 +784,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
720
784
  return openBlock(), createElementBlock(Fragment, {
721
785
  key: `p${pi}`
722
786
  }, [
723
- p.hit ? (openBlock(), createElementBlock("mark", _hoisted_19, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
787
+ p.hit ? (openBlock(), createElementBlock("mark", _hoisted_18, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
724
788
  createTextVNode(toDisplayString(p.text), 1)
725
789
  ], 64))
726
790
  ], 64);
@@ -736,26 +800,26 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
736
800
  ]),
737
801
  _: 3
738
802
  })
739
- ]),
740
- createElementVNode("div", _hoisted_20, [
741
- createElementVNode("span", _hoisted_21, [
803
+ ], 32),
804
+ createElementVNode("div", _hoisted_19, [
805
+ createElementVNode("span", _hoisted_20, [
742
806
  _cache[7] || (_cache[7] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "↑", -1)),
743
807
  _cache[8] || (_cache[8] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "↓", -1)),
744
808
  createTextVNode(" " + toDisplayString(text.value.navigate), 1)
745
809
  ]),
746
- createElementVNode("span", _hoisted_22, [
810
+ createElementVNode("span", _hoisted_21, [
747
811
  _cache[9] || (_cache[9] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "↵", -1)),
748
812
  createTextVNode(" " + toDisplayString(text.value.select), 1)
749
813
  ]),
750
- selectedActions.value.length ? (openBlock(), createElementBlock("span", _hoisted_23, [
814
+ selectedActions.value.length ? (openBlock(), createElementBlock("span", _hoisted_22, [
751
815
  _cache[10] || (_cache[10] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "tab", -1)),
752
816
  createTextVNode(" " + toDisplayString(text.value.actions), 1)
753
817
  ])) : createCommentVNode("", true),
754
- trail.value.length ? (openBlock(), createElementBlock("span", _hoisted_24, [
818
+ trail.value.length ? (openBlock(), createElementBlock("span", _hoisted_23, [
755
819
  _cache[11] || (_cache[11] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "⌫", -1)),
756
820
  createTextVNode(" " + toDisplayString(text.value.back), 1)
757
821
  ])) : createCommentVNode("", true),
758
- createElementVNode("span", _hoisted_25, [
822
+ createElementVNode("span", _hoisted_24, [
759
823
  _cache[12] || (_cache[12] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "esc", -1)),
760
824
  createTextVNode(" " + toDisplayString(text.value.close), 1)
761
825
  ])
@@ -772,7 +836,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
772
836
  };
773
837
  }
774
838
  });
775
- const LpCommandPalette = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-27071a60"]]);
839
+ const LpCommandPalette = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-7bcd1140"]]);
776
840
  export {
777
841
  LpCommandPalette as default
778
842
  };
@@ -28,7 +28,7 @@ type __VLS_Props = {
28
28
  */
29
29
  loading?: boolean;
30
30
  loadingLabel?: string;
31
- /** Frosted glass panel, passed to LpModal. Off by default. */
31
+ /** Frosted glass panel, passed to LpModal. Follows `provideGlass` when unset. */
32
32
  glass?: boolean;
33
33
  };
34
34
  declare var __VLS_16: {};
@@ -44,6 +44,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
44
44
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
45
45
  onConfirm?: (() => any) | undefined;
46
46
  }>, {
47
+ glass: boolean;
47
48
  confirmLabel: string;
48
49
  cancelLabel: string;
49
50
  loadingLabel: string;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpConfirmDialog-BBRnMkV4.js";
1
+ import { _ as _sfc_main } from "../chunks/LpConfirmDialog-BNAvOR24.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -66,7 +66,8 @@ declare const __VLS_export: __VLS_WithSlots<import('vue').DefineComponent<{
66
66
  /**
67
67
  * Frosted glass instead of a solid panel: the page shows through,
68
68
  * blurred, under a lighter scrim (.lp-glass-overlay, .lp-scrim--light).
69
- * A look, not a behaviour, so it is the app's call and off by default.
69
+ * A look, not a behaviour, so it is the app's call: unset follows
70
+ * `provideGlass`, and without one it is off.
70
71
  */
71
72
  glass?: boolean;
72
73
  }, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
@@ -137,7 +138,8 @@ declare const __VLS_export: __VLS_WithSlots<import('vue').DefineComponent<{
137
138
  /**
138
139
  * Frosted glass instead of a solid panel: the page shows through,
139
140
  * blurred, under a lighter scrim (.lp-glass-overlay, .lp-scrim--light).
140
- * A look, not a behaviour, so it is the app's call and off by default.
141
+ * A look, not a behaviour, so it is the app's call: unset follows
142
+ * `provideGlass`, and without one it is off.
141
143
  */
142
144
  glass?: boolean;
143
145
  }> & Readonly<{
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpDrawer-B8vBnCWF.js";
1
+ import { _ as _sfc_main } from "../chunks/LpDrawer-DgaS2s2i.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -28,7 +28,8 @@ type __VLS_Props = {
28
28
  /**
29
29
  * Frosted glass instead of a solid panel: the page shows through,
30
30
  * blurred, under a lighter scrim (.lp-glass-overlay, .lp-scrim--light).
31
- * A look, not a behaviour, so it is the app's call and off by default.
31
+ * A look, not a behaviour, so it is the app's call: unset follows
32
+ * `provideGlass`, and without one it is off.
32
33
  */
33
34
  glass?: boolean;
34
35
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpModal-EyEdRuqF.js";
1
+ import { _ as _sfc_main } from "../chunks/LpModal-8bja5bWS.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -31,7 +31,7 @@ type __VLS_Props = {
31
31
  * column inside the body, and the rail is no longer in the body.
32
32
  */
33
33
  fillBody?: boolean;
34
- /** Frosted glass panel, passed to LpModal. Off by default. */
34
+ /** Frosted glass panel, passed to LpModal. Follows `provideGlass` when unset. */
35
35
  glass?: boolean;
36
36
  };
37
37
  declare var __VLS_36: {}, __VLS_38: {}, __VLS_41: {};
@@ -50,6 +50,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
50
50
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
51
51
  }>, {
52
52
  size: "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "full";
53
+ glass: boolean;
53
54
  mobileBreakpoint: Breakpoint;
54
55
  navWidth: string;
55
56
  navLabel: string;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpModalNav-BrDtP7b_.js";
1
+ import { _ as _sfc_main } from "../chunks/LpModalNav-w9kfwHqO.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,18 +1,12 @@
1
- export interface ShortcutEntry {
2
- /** Rendered one <kbd> per "+"-separated key, so write it the way it reads. */
3
- combo: string;
4
- label: string;
5
- }
6
- export interface ShortcutGroup {
7
- title: string;
8
- entries: ShortcutEntry[];
9
- }
1
+ import { ShortcutGroup } from '../composables/useHotkeys';
10
2
  type __VLS_Props = {
11
3
  open?: boolean;
12
- groups: ShortcutGroup[];
4
+ groups?: ShortcutGroup[];
5
+ /** Also list the bindings mounted right now (`useHotkeys` with `help`). */
6
+ live?: boolean;
13
7
  title?: string;
14
8
  description?: string;
15
- /** Frosted glass panel, passed to LpModal. Off by default. */
9
+ /** Frosted glass panel, passed to LpModal. Follows `provideGlass` when unset. */
16
10
  glass?: boolean;
17
11
  };
18
12
  declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
@@ -22,6 +16,9 @@ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {
22
16
  }>, {
23
17
  title: string;
24
18
  open: boolean;
19
+ glass: boolean;
20
+ groups: ShortcutGroup[];
21
+ live: boolean;
25
22
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
26
23
  declare const _default: typeof __VLS_export;
27
24
  export default _default;