@leavepulse/ui 0.42.0 → 0.43.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 (155) hide show
  1. package/dist/assets/{LpCommandPalette-Esv0a-gS.css → LpCommandPalette-s_kKuCRf.css} +21 -21
  2. package/dist/chunks/{LpAddressInput-CMjaPQVw.js → LpAddressInput-B-Zvxsn7.js} +1 -1
  3. package/dist/chunks/{LpAppShell-Bcv6EhqU.js → LpAppShell-BGQVIY-3.js} +1 -1
  4. package/dist/chunks/{LpConfirmDialog-BNAvOR24.js → LpConfirmDialog-Q-bxff8z.js} +1 -1
  5. package/dist/chunks/{LpDrawer-DgaS2s2i.js → LpDrawer-BZ6k3hvo.js} +3 -3
  6. package/dist/chunks/{LpLightbox-oLqyjOln.js → LpLightbox-2sYVMY-S.js} +12 -4
  7. package/dist/chunks/{LpMediaGallery-Cid7PGYx.js → LpMediaGallery-FF-NquIo.js} +1 -1
  8. package/dist/chunks/{LpModal-8bja5bWS.js → LpModal-Bt0pQCI_.js} +2 -2
  9. package/dist/chunks/{LpModalNav-w9kfwHqO.js → LpModalNav-YaifHrXC.js} +2 -2
  10. package/dist/chunks/{LpSidebar-DlTn5nXc.js → LpSidebar-ClBUwoEz.js} +1 -1
  11. package/dist/components/LpAddressInput.vue.js +1 -1
  12. package/dist/components/LpAppShell.vue.js +1 -1
  13. package/dist/components/LpCommandPalette.vue.js +19 -72
  14. package/dist/components/LpConfirmDialog.vue.js +1 -1
  15. package/dist/components/LpDrawer.vue.js +1 -1
  16. package/dist/components/LpLightbox.vue.js +1 -1
  17. package/dist/components/LpMediaGallery.vue.js +1 -1
  18. package/dist/components/LpModal.vue.js +1 -1
  19. package/dist/components/LpModalNav.vue.js +1 -1
  20. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  21. package/dist/components/LpSidebar.vue.js +1 -1
  22. package/dist/components/commandSearch.js +66 -0
  23. package/dist/components/modalDepth.js +3 -2
  24. package/dist/index.js +13 -9
  25. package/package.json +3 -3
  26. package/src/components/LpCommandPalette.vue +18 -110
  27. package/src/components/LpDrawer.vue +3 -3
  28. package/src/components/LpLightbox.vue +11 -5
  29. package/src/components/LpModal.vue +2 -2
  30. package/src/components/commandSearch.ts +92 -0
  31. package/src/components/modalDepth.ts +4 -48
  32. package/src/index.ts +2 -0
  33. package/src/tokens/tokens.css +13 -19
  34. package/dist/component-names.d.ts +0 -1
  35. package/dist/components/LayoutCanvas.vue.d.ts +0 -28
  36. package/dist/components/LayoutNode.vue.d.ts +0 -40
  37. package/dist/components/LpActionBar.vue.d.ts +0 -84
  38. package/dist/components/LpAddressInput.vue.d.ts +0 -70
  39. package/dist/components/LpAlert.vue.d.ts +0 -44
  40. package/dist/components/LpAppShell.vue.d.ts +0 -123
  41. package/dist/components/LpAutocomplete.vue.d.ts +0 -50
  42. package/dist/components/LpAvatar.vue.d.ts +0 -34
  43. package/dist/components/LpBadge.vue.d.ts +0 -20
  44. package/dist/components/LpBreadcrumbs.vue.d.ts +0 -32
  45. package/dist/components/LpButton.vue.d.ts +0 -113
  46. package/dist/components/LpCalendar.vue.d.ts +0 -29
  47. package/dist/components/LpCard.vue.d.ts +0 -60
  48. package/dist/components/LpChart.vue.d.ts +0 -130
  49. package/dist/components/LpCheckbox.vue.d.ts +0 -32
  50. package/dist/components/LpCodeBlock.vue.d.ts +0 -58
  51. package/dist/components/LpColorPicker.vue.d.ts +0 -124
  52. package/dist/components/LpCommandPalette.vue.d.ts +0 -206
  53. package/dist/components/LpConfirmDialog.vue.d.ts +0 -59
  54. package/dist/components/LpContextMenu.vue.d.ts +0 -44
  55. package/dist/components/LpDatePicker.vue.d.ts +0 -33
  56. package/dist/components/LpDisclosure.vue.d.ts +0 -47
  57. package/dist/components/LpDivider.vue.d.ts +0 -17
  58. package/dist/components/LpDrawer.vue.d.ts +0 -170
  59. package/dist/components/LpDropdownMenu.vue.d.ts +0 -23
  60. package/dist/components/LpDropzone.vue.d.ts +0 -90
  61. package/dist/components/LpEmptyState.vue.d.ts +0 -28
  62. package/dist/components/LpFileTree.vue.d.ts +0 -126
  63. package/dist/components/LpFileTreeNode.vue.d.ts +0 -62
  64. package/dist/components/LpFormField.vue.d.ts +0 -24
  65. package/dist/components/LpIcon.vue.d.ts +0 -8
  66. package/dist/components/LpImageEditor.vue.d.ts +0 -106
  67. package/dist/components/LpInfraNode.vue.d.ts +0 -65
  68. package/dist/components/LpInput.vue.d.ts +0 -80
  69. package/dist/components/LpLaneNode.vue.d.ts +0 -24
  70. package/dist/components/LpLightbox.vue.d.ts +0 -62
  71. package/dist/components/LpLink.vue.d.ts +0 -93
  72. package/dist/components/LpLogViewer.vue.d.ts +0 -153
  73. package/dist/components/LpMapPicker.vue.d.ts +0 -59
  74. package/dist/components/LpMediaGallery.vue.d.ts +0 -80
  75. package/dist/components/LpModal.vue.d.ts +0 -66
  76. package/dist/components/LpModalNav.vue.d.ts +0 -66
  77. package/dist/components/LpNotificationBell.vue.d.ts +0 -85
  78. package/dist/components/LpNumberField.vue.d.ts +0 -21
  79. package/dist/components/LpNumberFlow.vue.d.ts +0 -35
  80. package/dist/components/LpOtpInput.vue.d.ts +0 -39
  81. package/dist/components/LpPagination.vue.d.ts +0 -35
  82. package/dist/components/LpPasswordInput.vue.d.ts +0 -36
  83. package/dist/components/LpPhoneInput.vue.d.ts +0 -49
  84. package/dist/components/LpPie.vue.d.ts +0 -196
  85. package/dist/components/LpPopover.vue.d.ts +0 -34
  86. package/dist/components/LpProgress.vue.d.ts +0 -66
  87. package/dist/components/LpRadio.vue.d.ts +0 -18
  88. package/dist/components/LpRadioGroup.vue.d.ts +0 -26
  89. package/dist/components/LpRollingText.vue.d.ts +0 -33
  90. package/dist/components/LpScrollArea.vue.d.ts +0 -28
  91. package/dist/components/LpSection.vue.d.ts +0 -120
  92. package/dist/components/LpSegmented.vue.d.ts +0 -30
  93. package/dist/components/LpSelect.vue.d.ts +0 -47
  94. package/dist/components/LpServiceNode.vue.d.ts +0 -14
  95. package/dist/components/LpShift.vue.d.ts +0 -36
  96. package/dist/components/LpShortcutsDialog.vue.d.ts +0 -24
  97. package/dist/components/LpSidebar.vue.d.ts +0 -146
  98. package/dist/components/LpSidebarNav.vue.d.ts +0 -54
  99. package/dist/components/LpSkeleton.vue.d.ts +0 -16
  100. package/dist/components/LpSlider.vue.d.ts +0 -30
  101. package/dist/components/LpSparkline.vue.d.ts +0 -48
  102. package/dist/components/LpStat.vue.d.ts +0 -69
  103. package/dist/components/LpStepper.vue.d.ts +0 -36
  104. package/dist/components/LpSwitch.vue.d.ts +0 -42
  105. package/dist/components/LpTable.vue.d.ts +0 -124
  106. package/dist/components/LpTableOfContents.vue.d.ts +0 -19
  107. package/dist/components/LpTabs.vue.d.ts +0 -47
  108. package/dist/components/LpTextarea.vue.d.ts +0 -22
  109. package/dist/components/LpThemeSwitcher.vue.d.ts +0 -47
  110. package/dist/components/LpTilt.vue.d.ts +0 -31
  111. package/dist/components/LpTimeField.vue.d.ts +0 -24
  112. package/dist/components/LpToaster.vue.d.ts +0 -3
  113. package/dist/components/LpTooltip.vue.d.ts +0 -58
  114. package/dist/components/LpTopologyCanvas.vue.d.ts +0 -205
  115. package/dist/components/LpUptimeBar.vue.d.ts +0 -46
  116. package/dist/components/LpWaypointEdge.vue.d.ts +0 -21
  117. package/dist/components/actionBar.d.ts +0 -19
  118. package/dist/components/address.d.ts +0 -107
  119. package/dist/components/chart.d.ts +0 -180
  120. package/dist/components/codeHighlight.d.ts +0 -8
  121. package/dist/components/color.d.ts +0 -65
  122. package/dist/components/countries-data.d.ts +0 -2
  123. package/dist/components/countries.d.ts +0 -20
  124. package/dist/components/dropdown.d.ts +0 -29
  125. package/dist/components/fileTree.d.ts +0 -79
  126. package/dist/components/lightbox.d.ts +0 -24
  127. package/dist/components/modalDepth.d.ts +0 -15
  128. package/dist/components/sidebar.d.ts +0 -42
  129. package/dist/composables/easing.d.ts +0 -46
  130. package/dist/composables/useAsyncTask.d.ts +0 -18
  131. package/dist/composables/useClipboard.d.ts +0 -46
  132. package/dist/composables/useFormDraft.d.ts +0 -67
  133. package/dist/composables/useGlass.d.ts +0 -9
  134. package/dist/composables/useHotkeys.d.ts +0 -101
  135. package/dist/composables/useInputFilter.d.ts +0 -14
  136. package/dist/composables/useMergedClass.d.ts +0 -42
  137. package/dist/composables/usePillTransition.d.ts +0 -21
  138. package/dist/composables/useReveal.d.ts +0 -26
  139. package/dist/composables/useRovingFocus.d.ts +0 -49
  140. package/dist/composables/useSettled.d.ts +0 -26
  141. package/dist/composables/useShift.d.ts +0 -35
  142. package/dist/composables/useTilt.d.ts +0 -23
  143. package/dist/composables/useToast.d.ts +0 -41
  144. package/dist/composables/useZoomPan.d.ts +0 -58
  145. package/dist/icons.d.ts +0 -1
  146. package/dist/index.d.ts +0 -160
  147. package/dist/layout/registry.d.ts +0 -26
  148. package/dist/layout/tree.d.ts +0 -75
  149. package/dist/layout/useLayout.d.ts +0 -39
  150. package/dist/theme/backdrop.d.ts +0 -9
  151. package/dist/theme/config.d.ts +0 -16
  152. package/dist/theme/define.d.ts +0 -12
  153. package/dist/theme/presets.d.ts +0 -20
  154. package/dist/theme/tokens.d.ts +0 -75
  155. package/dist/theme/useTheme.d.ts +0 -46
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { _ } from "./chunks/LayoutCanvas-Dd20boUG.js";
2
- import { _ as _2 } from "./chunks/LpAddressInput-CMjaPQVw.js";
2
+ import { _ as _2 } from "./chunks/LpAddressInput-B-Zvxsn7.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-Bcv6EhqU.js";
7
+ import { _ as _6 } from "./chunks/LpAppShell-BGQVIY-3.js";
8
8
  import { _ as _7 } from "./chunks/LpAutocomplete-DExlIZe_.js";
9
9
  import { _ as _8 } from "./chunks/LpAvatar-B3-xAOH3.js";
10
10
  import { _ as _9 } from "./chunks/LpBadge-Fe0D1bYx.js";
@@ -19,12 +19,13 @@ import { _ as _15 } from "./chunks/LpCodeBlock-Bo0B4TFR.js";
19
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-BNAvOR24.js";
22
+ import { parseCommandQuery, rankCommandItems, swapCommandTerms } from "./components/commandSearch.js";
23
+ import { _ as _17 } from "./chunks/LpConfirmDialog-Q-bxff8z.js";
23
24
  import { _ as _18 } from "./chunks/LpContextMenu-CwW1QXe_.js";
24
25
  import { _ as _19 } from "./chunks/LpDatePicker-CwOToxGq.js";
25
26
  import { _ as _20 } from "./chunks/LpDisclosure-ChQYmjlR.js";
26
27
  import { _ as _21 } from "./chunks/LpDivider-CUX46KR0.js";
27
- import { _ as _22 } from "./chunks/LpDrawer-DgaS2s2i.js";
28
+ import { _ as _22 } from "./chunks/LpDrawer-BZ6k3hvo.js";
28
29
  import { _ as _23 } from "./chunks/LpDropdownMenu-DJpoqRCb.js";
29
30
  import { default as default4 } from "./components/LpDropzone.vue.js";
30
31
  import { _ as _24 } from "./chunks/LpEmptyState-Dsdqz1Wj.js";
@@ -35,13 +36,13 @@ import { _ as _27 } from "./chunks/LpIcon-CCnX5_2j.js";
35
36
  import { default as default5 } from "./components/LpImageEditor.vue.js";
36
37
  import { _ as _28 } from "./chunks/LpInfraNode-Ds_8SZgN.js";
37
38
  import { _ as _29 } from "./chunks/LpInput-9EXWUM9B.js";
38
- import { _ as _30 } from "./chunks/LpLightbox-oLqyjOln.js";
39
+ import { _ as _30 } from "./chunks/LpLightbox-2sYVMY-S.js";
39
40
  import { fileNameOf } from "./components/lightbox.js";
40
41
  import { _ as _31 } from "./chunks/LpLink-DCND-zyu.js";
41
42
  import { _ as _32 } from "./chunks/LpLogViewer-CaRy5MeS.js";
42
- import { _ as _33 } from "./chunks/LpMediaGallery-Cid7PGYx.js";
43
- import { _ as _34 } from "./chunks/LpModal-8bja5bWS.js";
44
- import { _ as _35 } from "./chunks/LpModalNav-w9kfwHqO.js";
43
+ import { _ as _33 } from "./chunks/LpMediaGallery-FF-NquIo.js";
44
+ import { _ as _34 } from "./chunks/LpModal-Bt0pQCI_.js";
45
+ import { _ as _35 } from "./chunks/LpModalNav-YaifHrXC.js";
45
46
  import { _ as _36 } from "./chunks/LpNotificationBell-DyGGsMAM.js";
46
47
  import { _ as _37 } from "./chunks/LpNumberField-CWuX08iX.js";
47
48
  import { _ as _38 } from "./chunks/LpTimeField-K6nAGboX.js";
@@ -64,7 +65,7 @@ import { _ as _53 } from "./chunks/LpSelect-ANIVtrpM.js";
64
65
  import { _ as _54 } from "./chunks/LpServiceNode-D8uJ8sGk.js";
65
66
  import { _ as _55 } from "./chunks/LpShift-DXNsauQZ.js";
66
67
  import { default as default6 } from "./components/LpShortcutsDialog.vue.js";
67
- import { _ as _56 } from "./chunks/LpSidebar-DlTn5nXc.js";
68
+ import { _ as _56 } from "./chunks/LpSidebar-ClBUwoEz.js";
68
69
  import { _ as _57 } from "./chunks/LpSkeleton-CTI-vBgW.js";
69
70
  import { _ as _58 } from "./chunks/LpSlider-BwNIBkAK.js";
70
71
  import { _ as _59 } from "./chunks/LpSparkline-C6xQ2dwv.js";
@@ -270,6 +271,7 @@ export {
270
271
  normalizeHue,
271
272
  opaqueCss,
272
273
  parseColor,
274
+ parseCommandQuery,
273
275
  parseConfig,
274
276
  parseHex,
275
277
  parseTheme,
@@ -277,6 +279,7 @@ export {
277
279
  presets,
278
280
  project,
279
281
  provideGlass,
282
+ rankCommandItems,
280
283
  removeBlock,
281
284
  removeLeaf,
282
285
  reorderTab,
@@ -292,6 +295,7 @@ export {
292
295
  sortNodes,
293
296
  subtreeIds,
294
297
  subtreeSize,
298
+ swapCommandTerms,
295
299
  t as themeFromCookie,
296
300
  k as themeToCssRule,
297
301
  m as themeToCssVars,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leavepulse/ui",
3
- "version": "0.42.0",
3
+ "version": "0.43.0",
4
4
  "type": "module",
5
5
  "description": "LeavePulse token-driven Vue component kit.",
6
6
  "repository": {
@@ -45,10 +45,11 @@
45
45
  "scripts": {
46
46
  "dev": "vite",
47
47
  "gen:names": "node scripts/gen-component-names.mjs",
48
- "build": "node scripts/gen-component-names.mjs && vue-tsc --noEmit -p tsconfig.build.json && vite build --config vite.lib.config.ts",
48
+ "build": "node scripts/gen-component-names.mjs && vue-tsc --noEmit -p tsconfig.build.json && vite build --config vite.lib.config.ts && vue-tsc --declaration --emitDeclarationOnly --noEmit false -p tsconfig.build.json --outDir dist",
49
49
  "dev:dist": "vite build --watch --config vite.lib.config.ts",
50
50
  "prepublishOnly": "node scripts/gen-component-names.mjs && vue-tsc --noEmit -p tsconfig.build.json && vite build --config vite.lib.config.ts",
51
51
  "typecheck": "vue-tsc --noEmit",
52
+ "test": "bun test",
52
53
  "release": "npm version patch -m \"chore: release v%s\" && git push --follow-tags",
53
54
  "release:minor": "npm version minor -m \"chore: release v%s\" && git push --follow-tags",
54
55
  "release:major": "npm version major -m \"chore: release v%s\" && git push --follow-tags"
@@ -83,7 +84,6 @@
83
84
  "tailwindcss": "^4.2.4",
84
85
  "typescript": "^5.6.3",
85
86
  "vite": "^7.0.0",
86
- "vite-plugin-dts": "^5.0.2",
87
87
  "vite-plugin-lib-inject-css": "^2.2.2",
88
88
  "vue": "3.5.31",
89
89
  "vue-tsc": "^3.0.0"
@@ -36,13 +36,15 @@ import {
36
36
  DialogRoot,
37
37
  DialogTitle,
38
38
  } from "reka-ui"
39
- import { computed, nextTick, ref, shallowRef, useId, watch } from "vue"
39
+ import { computed, nextTick, onBeforeUnmount, ref, shallowRef, useId, watch } from "vue"
40
40
  import LpIcon from "./LpIcon.vue"
41
41
  import LpScrollArea from "./LpScrollArea.vue"
42
42
  import { useAsyncTask } from "../composables/useAsyncTask"
43
43
  import { useGlass } from "../composables/useGlass"
44
44
  import { useClipboard } from "../composables/useClipboard"
45
45
  import { useHotkeys } from "../composables/useHotkeys"
46
+ import { useModalLayer } from "./modalDepth"
47
+ import { parseCommandQuery, rankCommandItems, swapCommandTerms } from "./commandSearch"
46
48
 
47
49
  export interface Command {
48
50
  id: string
@@ -234,6 +236,7 @@ const props = withDefaults(
234
236
  )
235
237
 
236
238
  const frosted = useGlass(() => props.glass)
239
+ const { claim, release, layer } = useModalLayer()
237
240
 
238
241
  const DEFAULT_LABELS: PaletteLabels = {
239
242
  navigate: "navigate",
@@ -453,123 +456,22 @@ const source = computed<Command[]>(() => (mode.value ? modeItems.value : props.c
453
456
  * the one bilingual setup common enough to be worth a table — and it is a
454
457
  * fallback, tried only when the query as typed matches nothing.
455
458
  */
456
- const LATIN = "qwertyuiop[]asdfghjkl;'zxcvbnm,.`"
457
- const CYRILLIC = "йцукенгшщзхъфывапролджэячсмитьбюё"
458
- const SWAP = new Map<string, string>()
459
- for (let i = 0; i < LATIN.length; i++) {
460
- SWAP.set(LATIN[i]!, CYRILLIC[i]!)
461
- SWAP.set(CYRILLIC[i]!, LATIN[i]!)
462
- }
463
-
464
- function swapLayout(term: string): string {
465
- return [...term].map((ch) => SWAP.get(ch) ?? ch).join("")
466
- }
467
-
468
- /** Damerau-Levenshtein distance, giving up past 1: all a typo check needs. */
469
- function withinOne(a: string, b: string): boolean {
470
- if (Math.abs(a.length - b.length) > 1) return false
471
- let i = 0
472
- while (i < a.length && i < b.length && a[i] === b[i]) i++
473
- if (i === a.length || i === b.length) return true
474
- const rest = (x: number, y: number) => a.slice(i + x) === b.slice(i + y)
475
- return rest(1, 1) || rest(1, 0) || rest(0, 1) || (a[i] === b[i + 1] && a[i + 1] === b[i] && rest(2, 2))
476
- }
477
-
478
- /*
479
- * A typo in a word long enough to have one: a slip in a three-letter word
480
- * makes it a different word. Compared against the word and its start, so
481
- * "deplyo" finds "deploy" and "deployment" alike.
482
- */
483
- const TYPO_MIN = 5
484
- function nearWord(term: string, label: string): boolean {
485
- if (term.length < TYPO_MIN) return false
486
- return label
487
- .split(/[^\p{L}\p{N}]+/u)
488
- .some((word) => withinOne(term, word) || (word.length > term.length && withinOne(term, word.slice(0, term.length))))
489
- }
490
-
491
- /*
492
- * Every word of the query has to land somewhere, in any order: "branch deploy"
493
- * finds "Deploy current branch". Per word, label > keywords > description,
494
- * the same weights the palette always had; a typo match ranks below all of
495
- * them, so an exact hit is never outranked by a near one.
496
- */
497
- interface SearchTerms {
498
- include: string[]
499
- exclude: string[]
500
- groups: string[]
501
- }
502
-
503
- const QUERY_TOKEN = /(-?)(?:(in):)?(?:"([^"]*)"|(\S+))/giu
504
-
505
- function searchTerms(value: string): SearchTerms {
506
- const out: SearchTerms = { include: [], exclude: [], groups: [] }
507
- QUERY_TOKEN.lastIndex = 0
508
- for (let match; (match = QUERY_TOKEN.exec(value)); ) {
509
- const text = (match[3] ?? match[4] ?? "").trim().toLowerCase()
510
- if (!text) continue
511
- if (match[2] && !match[1]) out.groups.push(text)
512
- else if (match[1]) out.exclude.push(text)
513
- else out.include.push(text)
514
- }
515
- return out
516
- }
517
-
518
- function matches(c: Command, term: string): boolean {
519
- return (
520
- c.label.toLowerCase().includes(term) ||
521
- (c.keywords ?? []).some((keyword) => keyword.toLowerCase().includes(term)) ||
522
- (c.description?.toLowerCase().includes(term) ?? false)
523
- )
524
- }
525
-
526
- function score(c: Command, terms: SearchTerms): number {
527
- const label = c.label.toLowerCase()
528
- const keywords = (c.keywords ?? []).map((k) => k.toLowerCase())
529
- const description = c.description?.toLowerCase() ?? ""
530
- const group = c.group?.toLowerCase() ?? ""
531
- if (terms.exclude.some((term) => matches(c, term)) || terms.groups.some((term) => !group.includes(term))) return 0
532
- let total = terms.include.length ? 0 : 1
533
- for (const term of terms.include) {
534
- let hit =
535
- (label.includes(term) ? 4 : 0) +
536
- (keywords.some((k) => k.includes(term)) ? 3 : 0) +
537
- (description.includes(term) ? 2 : 0)
538
- if (!hit && nearWord(term, label)) hit = 1
539
- if (!hit) return 0
540
- total += hit
541
- }
542
- return total
543
- }
544
-
545
- function rank(items: Command[], terms: SearchTerms): Command[] {
546
- return items
547
- .map((c) => ({ c, score: score(c, terms) }))
548
- .filter((e) => e.score > 0)
549
- .sort((a, b) => b.score - a.score || a.c.label.localeCompare(b.c.label))
550
- .map((e) => e.c)
551
- }
552
-
553
459
  /*
554
460
  * The local match and the terms it matched with — the swapped ones when the
555
461
  * layout fallback is what found it, so the highlight marks what actually hit.
556
462
  */
557
463
  const local = computed<{ items: Command[]; terms: string[] }>(() => {
558
- const terms = searchTerms(query.value)
464
+ const terms = parseCommandQuery(query.value)
559
465
  const filtered = query.value.trim()
560
466
  ? source.value
561
467
  : source.value.filter((c) => !c.hidden)
562
468
  // Empty query: show everything EXCEPT hidden commands (they only surface once
563
469
  // typed). With a query, hidden commands rank like any other.
564
470
  if (!terms.include.length && !terms.exclude.length && !terms.groups.length) return { items: filtered, terms: [] }
565
- const items = rank(filtered, terms)
471
+ const items = rankCommandItems(filtered, terms)
566
472
  if (items.length || !props.layoutFallback) return { items, terms: terms.include }
567
- const swapped: SearchTerms = {
568
- include: terms.include.map(swapLayout),
569
- exclude: terms.exclude.map(swapLayout),
570
- groups: terms.groups.map(swapLayout),
571
- }
572
- const other = rank(filtered, swapped)
473
+ const swapped = swapCommandTerms(terms)
474
+ const other = rankCommandItems(filtered, swapped)
573
475
  return other.length ? { items: other, terms: swapped.include } : { items, terms: terms.include }
574
476
  })
575
477
 
@@ -904,6 +806,8 @@ function onEscape(event: KeyboardEvent) {
904
806
  watch(
905
807
  () => props.open,
906
808
  async (o) => {
809
+ if (o) claim()
810
+ else release()
907
811
  cancel()
908
812
  query.value = ""
909
813
  select(0)
@@ -921,6 +825,8 @@ watch(
921
825
  { immediate: true },
922
826
  )
923
827
 
828
+ onBeforeUnmount(release)
829
+
924
830
  // Through useHotkeys rather than a listener of its own: the palette is the one
925
831
  // shortcut that has to work from inside a text field, and `code` is what makes
926
832
  // it fire on a layout where Ctrl-K arrives as "л".
@@ -943,12 +849,14 @@ useHotkeys(() =>
943
849
  <DialogRoot :open="open" @update:open="(v) => emit('update:open', v)">
944
850
  <DialogPortal>
945
851
  <DialogOverlay
946
- :class="{ 'lp-scrim--light': frosted }"
947
- class="lp-scrim fixed inset-0 z-(--z-overlay) data-[state=open]:animate-[fade-in_150ms_ease] data-[state=closed]:animate-[fade-out_130ms_ease]"
852
+ :class="{ 'lp-scrim--light': frosted, 'lp-scrim--nested': layer.nested }"
853
+ class="lp-scrim fixed inset-0 data-[state=open]:animate-[fade-in_150ms_ease] data-[state=closed]:animate-[fade-out_130ms_ease]"
854
+ :style="{ zIndex: layer.scrim }"
948
855
  />
949
856
  <DialogContent
950
- class="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]"
951
- :class="[frosted ? 'lp-glass-overlay' : 'bg-surface-raised', previewPane && 'lp-cmd-split']"
857
+ class="lp-cmd-dialog fixed left-1/2 top-[12vh] 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]"
858
+ :class="[frosted ? (layer.nested ? 'lp-glass-overlay--nested' : 'lp-glass-overlay') : 'bg-surface-raised', previewPane && 'lp-cmd-split']"
859
+ :style="{ zIndex: layer.panel }"
952
860
  :data-pane="paneOpen ? 'open' : undefined"
953
861
  @open-auto-focus.prevent
954
862
  @keydown.capture="onPaletteKeydown"
@@ -153,7 +153,7 @@ watch(() => props.open, (open) => (open ? claim() : release()), { immediate: tru
153
153
  onBeforeUnmount(release)
154
154
 
155
155
  const contentClass = computed(() => {
156
- const surface = frosted.value ? "lp-glass-overlay" : "bg-surface-raised"
156
+ const surface = frosted.value ? (layer.value.nested ? "lp-glass-overlay--nested" : "lp-glass-overlay") : "bg-surface-raised"
157
157
  const base = `fixed z-(--z-modal) flex flex-col border-line ${surface} shadow-panel outline-none`
158
158
  const map: Record<Direction, string> = {
159
159
  left: "inset-y-0 left-0 border-r rounded-r-card",
@@ -443,7 +443,7 @@ const previewStyle = computed(() => {
443
443
  <div
444
444
  v-show="peeking || peek > 0"
445
445
  class="lp-scrim pointer-events-none fixed inset-0"
446
- :class="{ 'lp-scrim--light': frosted }"
446
+ :class="{ 'lp-scrim--light': frosted, 'lp-scrim--nested': layer.nested }"
447
447
  :style="{ zIndex: layer.scrim, opacity: peek, transition: peeking || reducedMotion() ? 'none' : 'opacity 0.18s ease-out' }"
448
448
  />
449
449
  <div
@@ -476,7 +476,7 @@ const previewStyle = computed(() => {
476
476
  <DrawerOverlay
477
477
  :style="{ zIndex: layer.scrim }"
478
478
  class="lp-scrim fixed inset-0 z-(--z-overlay) data-[state=open]:animate-[fade-in_150ms_ease] data-[state=closed]:animate-[fade-out_130ms_ease]"
479
- :class="{ 'lp-scrim--light': frosted }"
479
+ :class="{ 'lp-scrim--light': frosted, 'lp-scrim--nested': layer.nested }"
480
480
  />
481
481
  <DrawerContent
482
482
  :class="contentClass"
@@ -21,10 +21,11 @@ import {
21
21
  DialogRoot,
22
22
  DialogTitle,
23
23
  } from "reka-ui"
24
- import { computed, nextTick, ref, watch } from "vue"
24
+ import { computed, nextTick, onBeforeUnmount, ref, watch } from "vue"
25
25
  import { useZoomPan } from "../composables/useZoomPan"
26
26
  import { fileNameOf, type LightboxItem } from "./lightbox"
27
27
  import LpIcon from "./LpIcon.vue"
28
+ import { useModalLayer } from "./modalDepth"
28
29
 
29
30
  const props = withDefaults(
30
31
  defineProps<{
@@ -67,6 +68,10 @@ const emit = defineEmits<{
67
68
  (e: "copy", item: LightboxItem, ok: boolean): void
68
69
  }>()
69
70
 
71
+ const { claim, release, layer } = useModalLayer()
72
+ watch(() => props.open, (open) => (open ? claim() : release()), { immediate: true })
73
+ onBeforeUnmount(release)
74
+
70
75
  defineSlots<{
71
76
  /** Replace the caption block under the image. */
72
77
  caption(props: { item: LightboxItem; index: number; total: number }): unknown
@@ -335,13 +340,14 @@ const ARROW =
335
340
  <template>
336
341
  <DialogRoot :open="open" @update:open="(v) => emit('update:open', v)">
337
342
  <DialogPortal>
338
- <!-- Sits on the lightbox rung, not the shared modal one: opening this
339
- from inside a dialog must cover that dialog, not tie with it. -->
340
343
  <DialogOverlay
341
- class="lp-scrim lp-scrim--deep fixed inset-0 z-(--z-lightbox-overlay) data-[state=open]:animate-[fade-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[fade-out_120ms_ease]"
344
+ class="lp-scrim fixed inset-0 data-[state=open]:animate-[fade-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[fade-out_120ms_ease]"
345
+ :class="{ 'lp-scrim--nested': layer.nested }"
346
+ :style="{ zIndex: layer.scrim }"
342
347
  />
343
348
  <DialogContent
344
- class="fixed inset-0 z-(--z-lightbox) flex flex-col outline-none data-[state=open]:animate-[lightbox-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[lightbox-out_140ms_cubic-bezier(0.4,0,1,1)] motion-reduce:animate-none"
349
+ class="fixed inset-0 flex flex-col outline-none data-[state=open]:animate-[lightbox-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[lightbox-out_140ms_cubic-bezier(0.4,0,1,1)] motion-reduce:animate-none"
350
+ :style="{ zIndex: layer.panel }"
345
351
  @keydown="onKeydown"
346
352
  >
347
353
  <!-- reka wants both for a labelled dialog; the caption is the title. -->
@@ -232,7 +232,7 @@ watch(
232
232
  <DialogRoot :open="open" @update:open="(v) => $emit('update:open', v)">
233
233
  <DialogPortal>
234
234
  <DialogOverlay
235
- :class="{ 'lp-scrim--light': frosted }"
235
+ :class="{ 'lp-scrim--light': frosted, 'lp-scrim--nested': layer.nested }"
236
236
  class="lp-scrim fixed inset-0 data-[state=open]:animate-[fade-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[fade-out_120ms_ease]"
237
237
  :style="{ zIndex: layer.scrim }"
238
238
  />
@@ -302,7 +302,7 @@ watch(
302
302
  <div
303
303
  ref="panelRef"
304
304
  class="flex max-h-[min(90vh,calc(100dvh-2rem))] min-h-0 flex-col overflow-hidden rounded-card border border-line shadow-panel"
305
- :class="[frosted ? 'lp-glass-overlay' : 'bg-surface-raised', widthClass, tweening ? 'transition-[height] duration-fast ease-[var(--ease-emphasized)] motion-reduce:transition-none' : '']"
305
+ :class="[frosted ? (layer.nested ? 'lp-glass-overlay--nested' : 'lp-glass-overlay') : 'bg-surface-raised', widthClass, tweening ? 'transition-[height] duration-fast ease-[var(--ease-emphasized)] motion-reduce:transition-none' : '']"
306
306
  :style="{ ...(width ? { width } : {}), ...(hasAside ? { alignSelf: 'stretch' } : {}) }"
307
307
  >
308
308
  <header v-if="title || $slots.title" class="flex shrink-0 items-start justify-between gap-4 p-5 pb-3">
@@ -0,0 +1,92 @@
1
+ export interface SearchableCommand {
2
+ label: string
3
+ description?: string
4
+ keywords?: string[]
5
+ group?: string
6
+ }
7
+
8
+ export interface CommandSearchTerms {
9
+ include: string[]
10
+ exclude: string[]
11
+ groups: string[]
12
+ }
13
+
14
+ const QUERY_TOKEN = /(-?)(?:(in):)?(?:"([^"]*)"|(\S+))/giu
15
+ const LATIN = "qwertyuiop[]asdfghjkl;'zxcvbnm,.`"
16
+ const CYRILLIC = "йцукенгшщзхъфывапролджэячсмитьбюё"
17
+ const SWAP = new Map<string, string>()
18
+
19
+ for (let i = 0; i < LATIN.length; i++) {
20
+ SWAP.set(LATIN[i]!, CYRILLIC[i]!)
21
+ SWAP.set(CYRILLIC[i]!, LATIN[i]!)
22
+ }
23
+
24
+ export function parseCommandQuery(value: string): CommandSearchTerms {
25
+ const out: CommandSearchTerms = { include: [], exclude: [], groups: [] }
26
+ QUERY_TOKEN.lastIndex = 0
27
+ for (let match; (match = QUERY_TOKEN.exec(value)); ) {
28
+ const text = (match[3] ?? match[4] ?? "").trim().toLowerCase()
29
+ if (!text) continue
30
+ if (match[2] && !match[1]) out.groups.push(text)
31
+ else if (match[1]) out.exclude.push(text)
32
+ else out.include.push(text)
33
+ }
34
+ return out
35
+ }
36
+
37
+ export function swapCommandTerms(terms: CommandSearchTerms): CommandSearchTerms {
38
+ const swap = (term: string) => [...term].map((ch) => SWAP.get(ch) ?? ch).join("")
39
+ return {
40
+ include: terms.include.map(swap),
41
+ exclude: terms.exclude.map(swap),
42
+ groups: terms.groups.map(swap),
43
+ }
44
+ }
45
+
46
+ function matches(command: SearchableCommand, term: string): boolean {
47
+ return (
48
+ command.label.toLowerCase().includes(term)
49
+ || (command.keywords ?? []).some((keyword) => keyword.toLowerCase().includes(term))
50
+ || (command.description?.toLowerCase().includes(term) ?? false)
51
+ )
52
+ }
53
+
54
+ function withinOne(a: string, b: string): boolean {
55
+ if (Math.abs(a.length - b.length) > 1) return false
56
+ let i = 0
57
+ while (i < a.length && i < b.length && a[i] === b[i]) i++
58
+ if (i === a.length || i === b.length) return true
59
+ const rest = (x: number, y: number) => a.slice(i + x) === b.slice(i + y)
60
+ return rest(1, 1) || rest(1, 0) || rest(0, 1) || (a[i] === b[i + 1] && a[i + 1] === b[i] && rest(2, 2))
61
+ }
62
+
63
+ function nearWord(term: string, label: string): boolean {
64
+ if (term.length < 5) return false
65
+ return label
66
+ .split(/[^\p{L}\p{N}]+/u)
67
+ .some((word) => withinOne(term, word) || (word.length > term.length && withinOne(term, word.slice(0, term.length))))
68
+ }
69
+
70
+ function score(command: SearchableCommand, terms: CommandSearchTerms): number {
71
+ const label = command.label.toLowerCase()
72
+ const keywords = (command.keywords ?? []).map((keyword) => keyword.toLowerCase())
73
+ const description = command.description?.toLowerCase() ?? ""
74
+ const group = command.group?.toLowerCase() ?? ""
75
+ if (terms.exclude.some((term) => matches(command, term)) || terms.groups.some((term) => !group.includes(term))) return 0
76
+ let total = terms.include.length ? 0 : 1
77
+ for (const term of terms.include) {
78
+ let hit = (label.includes(term) ? 4 : 0) + (keywords.some((keyword) => keyword.includes(term)) ? 3 : 0) + (description.includes(term) ? 2 : 0)
79
+ if (!hit && nearWord(term, label)) hit = 1
80
+ if (!hit) return 0
81
+ total += hit
82
+ }
83
+ return total
84
+ }
85
+
86
+ export function rankCommandItems<T extends SearchableCommand>(items: T[], terms: CommandSearchTerms): T[] {
87
+ return items
88
+ .map((command) => ({ command, score: score(command, terms) }))
89
+ .filter((entry) => entry.score > 0)
90
+ .sort((a, b) => b.score - a.score || a.command.label.localeCompare(b.command.label))
91
+ .map((entry) => entry.command)
92
+ }
@@ -1,61 +1,17 @@
1
- /*
2
- * Stacking order for dialogs that are open at the same time.
3
- *
4
- * Not provide/inject, which was the first shape tried: it only works when the
5
- * second dialog is rendered INSIDE the first one's subtree, and the ordinary
6
- * way to write a dialog opened from a dialog is to put both at the top level of
7
- * the same component and toggle them with separate flags. Those two are
8
- * siblings, so the inner one injects nothing and lands on the same rungs as the
9
- * outer — which is the bug.
10
- *
11
- * What decides the order is the sequence of OPENING: a dialog opened while
12
- * another is up belongs above it, wherever it sits in the markup.
13
- *
14
- * The newest dialog keeps the scale's own --z-overlay/--z-modal and the ones
15
- * beneath are pushed DOWN, rather than each new dialog climbing higher. Climbing
16
- * runs out of room immediately: --z-popover is only 10 above --z-modal, so the
17
- * second nested dialog would tie with every popover and the third with every
18
- * tooltip — and a select inside a dialog is ordinary. Descending has no such
19
- * ceiling, and it keeps the frontmost dialog exactly where a single one has
20
- * always been.
21
- */
22
1
  import { computed, ref, type ComputedRef } from "vue"
23
2
 
24
- /*
25
- * Rungs per level. Has to clear a whole level, not just its scrim: --z-overlay
26
- * is 100 and --z-modal 110, so a gap of 2 left the upper scrim under the lower
27
- * PANEL — it darkened that panel and could not blur it, a backdrop-filter
28
- * having nothing of it underneath to work on.
29
- *
30
- * Clearing it means strictly more than the 10 between the two rungs. A step of
31
- * exactly 10 put the lower panel at 100, level with the upper scrim, and a tie
32
- * in z-index is settled by DOM order. Siblings in one component happened to
33
- * come out right, but a dialog mounted once at the app root — opened from a
34
- * page dialog that teleported in later — lost the tie, and its scrim darkened
35
- * the page behind the first dialog instead of the first dialog itself.
36
- */
37
3
  const STEP = 20
38
4
 
39
- /** Levels currently claimed, oldest first. */
40
5
  const stack = ref<number[]>([])
41
6
  let nextId = 0
42
7
 
43
- /**
44
- * Register a dialog as open and get back the z-indexes it should paint with.
45
- * The result is reactive: opening another dialog moves this one down a step.
46
- */
47
8
  export function useModalLayer(): {
48
9
  claim: () => void
49
10
  release: () => void
50
- layer: ComputedRef<{ scrim: string; panel: string }>
11
+ layer: ComputedRef<{ scrim: string; panel: string; nested: boolean }>
51
12
  } {
52
13
  const id = nextId++
53
14
 
54
- /*
55
- * How far from the TOP of the stack, so the newest dialog is 0 and keeps the
56
- * unmodified rungs. A dialog that is not in the stack reads 0 too: it is
57
- * either closed, or opening this very frame and about to claim.
58
- */
59
15
  const fromTop = computed(() => {
60
16
  const at = stack.value.indexOf(id)
61
17
  return at === -1 ? 0 : stack.value.length - 1 - at
@@ -71,14 +27,14 @@ export function useModalLayer(): {
71
27
  layer: computed(() => {
72
28
  const drop = fromTop.value * STEP
73
29
  return {
74
- scrim: `calc(var(--z-overlay) - ${drop})`,
75
- panel: `calc(var(--z-modal) - ${drop})`,
30
+ scrim: `calc(var(--z-toast) - 20 - ${drop})`,
31
+ panel: `calc(var(--z-toast) - 10 - ${drop})`,
32
+ nested: stack.value.indexOf(id) > 0,
76
33
  }
77
34
  }),
78
35
  }
79
36
  }
80
37
 
81
- /** True while any dialog or drawer holds a level — e.g. to keep a gesture from opening another one over it. */
82
38
  export function anyModalOpen(): boolean {
83
39
  return stack.value.length > 0
84
40
  }
package/src/index.ts CHANGED
@@ -65,6 +65,8 @@ export {
65
65
  export type { ColorFormat, Hsv, Rgb } from "./components/color"
66
66
  export { default as LpCommandPalette } from "./components/LpCommandPalette.vue"
67
67
  export type { Command, PaletteLabels } from "./components/LpCommandPalette.vue"
68
+ export { parseCommandQuery, rankCommandItems, swapCommandTerms } from "./components/commandSearch"
69
+ export type { CommandSearchTerms, SearchableCommand } from "./components/commandSearch"
68
70
  export { default as LpConfirmDialog } from "./components/LpConfirmDialog.vue"
69
71
  export { default as LpContextMenu } from "./components/LpContextMenu.vue"
70
72
  export type { ContextMenuItemDef } from "./components/LpContextMenu.vue"
@@ -171,14 +171,6 @@
171
171
  --z-tooltip: 130;
172
172
  --z-toast: 200;
173
173
 
174
- /* A lightbox is usually opened FROM a dialog — click a thumbnail in a modal
175
- and the full image comes up over it. Sharing --z-overlay/--z-modal left
176
- that order to DOM insertion alone, so the lightbox's own scrim landed on
177
- top of the modal panel and swallowed it while double-darkening the page
178
- behind. Its own rung above the modal (but below tooltip/toast, which must
179
- outrank everything) makes the stack explicit. */
180
- --z-lightbox-overlay: 140;
181
- --z-lightbox: 150;
182
174
  }
183
175
 
184
176
  /* ── overlay enter/exit animations ───────────────
@@ -511,17 +503,6 @@
511
503
  --scrim-opacity: 0.62;
512
504
  }
513
505
 
514
- /*
515
- * A lightbox is the one scrim that hides a whole page behind a photo, and it is
516
- * usually opened FROM a dialog — so it is the layer the mild shared tint serves
517
- * worst: without the blur, the content behind stayed readable around the image.
518
- * It gets its own value instead of raising the shared one, which would darken
519
- * every stacked pair.
520
- */
521
- :root[data-lp-no-backdrop] .lp-scrim--deep {
522
- --scrim-opacity: 0.78;
523
- }
524
-
525
506
  /*
526
507
  * Under a glass panel (.lp-glass-overlay) the usual tint leaves nothing but
527
508
  * grey to see through it, so the scrim dims less and the panel's own blur
@@ -532,6 +513,12 @@
532
513
  --scrim-opacity: 0.32;
533
514
  }
534
515
 
516
+ .lp-scrim--nested {
517
+ --scrim-opacity: 0.24;
518
+ -webkit-backdrop-filter: none;
519
+ backdrop-filter: none;
520
+ }
521
+
535
522
  /*
536
523
  * Frosted overlay: a floating panel that lets the page show through, softened.
537
524
  * For surfaces that float over everything and are read briefly (the command
@@ -550,6 +537,13 @@
550
537
  backdrop-filter: blur(var(--glass-overlay-blur, 28px)) saturate(170%);
551
538
  }
552
539
 
540
+ .lp-glass-overlay--nested {
541
+ background-color: color-mix(in srgb, var(--color-surface-raised) 88%, transparent);
542
+ background-image: none;
543
+ -webkit-backdrop-filter: none;
544
+ backdrop-filter: none;
545
+ }
546
+
553
547
  :root[data-lp-no-backdrop] .lp-glass-overlay {
554
548
  background-color: var(--color-surface-raised);
555
549
  background-image: none;
@@ -1 +0,0 @@
1
- export declare const COMPONENT_NAMES: readonly ["LayoutCanvas", "LayoutNode", "LpActionBar", "LpAddressInput", "LpAlert", "LpAppShell", "LpAutocomplete", "LpAvatar", "LpBadge", "LpBreadcrumbs", "LpButton", "LpCalendar", "LpCard", "LpChart", "LpCheckbox", "LpCodeBlock", "LpColorPicker", "LpCommandPalette", "LpConfirmDialog", "LpContextMenu", "LpDatePicker", "LpDisclosure", "LpDivider", "LpDrawer", "LpDropdownMenu", "LpDropzone", "LpEmptyState", "LpFileTree", "LpFileTreeNode", "LpFormField", "LpIcon", "LpImageEditor", "LpInfraNode", "LpInput", "LpLaneNode", "LpLightbox", "LpLink", "LpLogViewer", "LpMapPicker", "LpMediaGallery", "LpModal", "LpModalNav", "LpNotificationBell", "LpNumberField", "LpNumberFlow", "LpOtpInput", "LpPagination", "LpPasswordInput", "LpPhoneInput", "LpPie", "LpPopover", "LpProgress", "LpRadio", "LpRadioGroup", "LpRollingText", "LpScrollArea", "LpSection", "LpSegmented", "LpSelect", "LpServiceNode", "LpShift", "LpShortcutsDialog", "LpSidebar", "LpSidebarNav", "LpSkeleton", "LpSlider", "LpSparkline", "LpStat", "LpStepper", "LpSwitch", "LpTable", "LpTableOfContents", "LpTabs", "LpTextarea", "LpThemeSwitcher", "LpTilt", "LpTimeField", "LpToaster", "LpTooltip", "LpTopologyCanvas", "LpUptimeBar", "LpWaypointEdge"];
@@ -1,28 +0,0 @@
1
- import { Split } from '../layout/tree';
2
- import { BlockRegistry } from '../layout/registry';
3
- type __VLS_Props = {
4
- modelValue: Split;
5
- edit?: boolean;
6
- /** Catalogue mapping block ids to titles/icons for the tab bars. */
7
- registry?: BlockRegistry;
8
- };
9
- type __VLS_Slots = {
10
- block(props: {
11
- block: string;
12
- leafId: string;
13
- edit: boolean;
14
- }): unknown;
15
- };
16
- declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
17
- "update:modelValue": (value: Split) => any;
18
- }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
19
- "onUpdate:modelValue"?: ((value: Split) => any) | undefined;
20
- }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
21
- declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
22
- declare const _default: typeof __VLS_export;
23
- export default _default;
24
- type __VLS_WithSlots<T, S> = T & {
25
- new (): {
26
- $slots: S;
27
- };
28
- };