@leavepulse/ui 0.70.0 → 0.70.1

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 (135) hide show
  1. package/README.md +12 -0
  2. package/dist/assets/LpRepeater-C1Cw27hj.css +21 -0
  3. package/dist/assets/{LpRollingText-BGnE6q9j.css → LpRollingText-dyOXedGO.css} +7 -0
  4. package/dist/chunks/{ContextMenuItems-B5uE8Znw.js → ContextMenuItems-6kxEivBI.js} +10 -4
  5. package/dist/chunks/{LpAddressInput-CNnLTDZg.js → LpAddressInput-Chv_Xf8q.js} +1 -1
  6. package/dist/chunks/{LpAppShell-CEUAB8kK.js → LpAppShell-BiWByLmt.js} +1 -1
  7. package/dist/chunks/{LpBadge-HOEPBYmi.js → LpBadge-BBq1Er9T.js} +1 -1
  8. package/dist/chunks/{LpBreadcrumbs-DYoPc3P4.js → LpBreadcrumbs-JKEi_yFF.js} +1 -1
  9. package/dist/chunks/{LpCodeDisplay-CIKKT2iW.js → LpCodeDisplay-CbJMs-IK.js} +2 -2
  10. package/dist/chunks/{LpColorPicker-DFugXNUi.js → LpColorPicker-B7HSIFmn.js} +2 -2
  11. package/dist/chunks/{LpContextMenu-COwOwRgI.js → LpContextMenu-Cj96ENDC.js} +5 -4
  12. package/dist/chunks/{LpCountdown-Dtq1ihlJ.js → LpCountdown-BQnmB4gq.js} +1 -1
  13. package/dist/chunks/{LpDataList-B-5nHfNw.js → LpDataList-CHNYQw7h.js} +4 -3
  14. package/dist/chunks/{LpDatePicker-BUe1VUC0.js → LpDatePicker-ac1_6o5P.js} +4 -3
  15. package/dist/chunks/{LpDateRangePicker-C_k65vGR.js → LpDateRangePicker-B15gYrZJ.js} +4 -3
  16. package/dist/chunks/{LpDropdownMenu-CRgrhdAH.js → LpDropdownMenu-R4aYVtVV.js} +5 -2
  17. package/dist/chunks/{LpEditable-DTqLt2lT.js → LpEditable-Ws3DNQHn.js} +5 -3
  18. package/dist/chunks/{LpFileTree-DMISXVHC.js → LpFileTree-DDNg34tJ.js} +1 -1
  19. package/dist/chunks/{LpFileTreeNode-CPXB_Yy3.js → LpFileTreeNode-DmPuYNZ_.js} +2 -2
  20. package/dist/chunks/{LpGauge-Bk8TwJj0.js → LpGauge-C14Z9503.js} +1 -1
  21. package/dist/chunks/{LpHintLayer-p4hqzdyA.js → LpHintLayer-HvwUA5Ec.js} +1 -1
  22. package/dist/chunks/{LpHints-CCrhRfy9.js → LpHints-DxbPKOzQ.js} +2 -2
  23. package/dist/chunks/{LpInfraNode-CUC3t4na.js → LpInfraNode-D64hywJI.js} +2 -2
  24. package/dist/chunks/{LpLogViewer-elZHbj85.js → LpLogViewer-DKK4ySZl.js} +2 -2
  25. package/dist/chunks/{LpMediaGallery-D5swlmZ_.js → LpMediaGallery-rmI1DjKN.js} +1 -1
  26. package/dist/chunks/{LpModalNav-D4Z0wVHR.js → LpModalNav-DiyFCHiZ.js} +1 -1
  27. package/dist/chunks/{LpNotificationBell-DPZmP5dM.js → LpNotificationBell-D-WhE5m2.js} +5 -5
  28. package/dist/chunks/{LpPasswordInput-DTV18FIh.js → LpPasswordInput-GL2KOFK8.js} +10 -6
  29. package/dist/chunks/{LpPie-CFuV7pZv.js → LpPie-BgXZ3xmm.js} +2 -2
  30. package/dist/chunks/{LpPipeline-D81yh_NX.js → LpPipeline-B31h41Mu.js} +2 -2
  31. package/dist/chunks/{LpPopover-BEIcqb9p.js → LpPopover-DmZ3wUtP.js} +6 -5
  32. package/dist/chunks/{LpQuota-2Sw_gqcJ.js → LpQuota-DaL8TgNe.js} +1 -1
  33. package/dist/chunks/{LpRelativeTime-CKzVqAo9.js → LpRelativeTime-yin9uQP7.js} +1 -1
  34. package/dist/chunks/LpRepeater-D0S7jjwr.js +180 -0
  35. package/dist/chunks/{LpRollingText-DB7upf-5.js → LpRollingText-DiL717LK.js} +4 -3
  36. package/dist/chunks/{LpSecretField-DMfdJ1cQ.js → LpSecretField-CfWyHv9m.js} +19 -10
  37. package/dist/chunks/{LpSelect-B4f_yRi5.js → LpSelect-C_8cJtj6.js} +10 -15
  38. package/dist/chunks/{LpSidebar-D-M0Y_7U.js → LpSidebar-CZRXtvem.js} +1 -1
  39. package/dist/chunks/{LpSidebarNav-DF-TYxOV.js → LpSidebarNav-DBg1U1oW.js} +2 -2
  40. package/dist/chunks/{LpStat-B2ix1Q7t.js → LpStat-DFKlPJgy.js} +1 -1
  41. package/dist/chunks/{LpStatus-C7kx5PKE.js → LpStatus-BsGLrpor.js} +2 -2
  42. package/dist/chunks/{LpStepMark-DK-5BKAt.js → LpStepMark-TrzOioa9.js} +1 -1
  43. package/dist/chunks/{LpStepper-DRFfdJaq.js → LpStepper-BbnS5jUr.js} +1 -1
  44. package/dist/chunks/{LpTagsInput-DgpBFRV2.js → LpTagsInput-DZg80W-B.js} +1 -1
  45. package/dist/chunks/{LpThemeStudio-DguwHdGt.js → LpThemeStudio-DxVZMtzN.js} +1 -1
  46. package/dist/chunks/{LpThemeSwitcher-D5uz0MhK.js → LpThemeSwitcher-CadVBTBn.js} +3 -3
  47. package/dist/chunks/{LpTopologyCanvas-ZhKthfgz.js → LpTopologyCanvas-C17A1XCb.js} +1 -1
  48. package/dist/chunks/{LpTour-NfRJNEIP.js → LpTour-CY2bFXge.js} +1 -1
  49. package/dist/chunks/{LpUptimeBar-DWegV2p6.js → LpUptimeBar-Tew1Ykx4.js} +1 -1
  50. package/dist/chunks/{PickerField-CHRS1h7K.js → PickerField-DoHv0WMH.js} +25 -16
  51. package/dist/chunks/{TourCard-BXuVHsfn.js → TourCard-BJ8i7dk0.js} +1 -1
  52. package/dist/components/ContextMenuItems.vue.js +1 -1
  53. package/dist/components/LpAddressInput.vue.js +1 -1
  54. package/dist/components/LpAppShell.vue.js +1 -1
  55. package/dist/components/LpBadge.vue.js +1 -1
  56. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  57. package/dist/components/LpChart.vue.js +26 -24
  58. package/dist/components/LpCodeDisplay.vue.js +1 -1
  59. package/dist/components/LpColorPicker.vue.js +1 -1
  60. package/dist/components/LpContextMenu.vue.js +1 -1
  61. package/dist/components/LpCountdown.vue.js +1 -1
  62. package/dist/components/LpDataList.vue.js +1 -1
  63. package/dist/components/LpDatePicker.vue.d.ts +2 -0
  64. package/dist/components/LpDatePicker.vue.js +1 -1
  65. package/dist/components/LpDateRangePicker.vue.d.ts +2 -0
  66. package/dist/components/LpDateRangePicker.vue.js +1 -1
  67. package/dist/components/LpDropdownMenu.vue.js +1 -1
  68. package/dist/components/LpEditable.vue.js +1 -1
  69. package/dist/components/LpFileTree.vue.js +1 -1
  70. package/dist/components/LpFileTreeNode.vue.js +1 -1
  71. package/dist/components/LpGauge.vue.js +1 -1
  72. package/dist/components/LpHintLayer.vue.js +1 -1
  73. package/dist/components/LpHints.vue.js +1 -1
  74. package/dist/components/LpInfraNode.vue.js +1 -1
  75. package/dist/components/LpLogViewer.vue.js +1 -1
  76. package/dist/components/LpMediaGallery.vue.js +1 -1
  77. package/dist/components/LpModalNav.vue.js +1 -1
  78. package/dist/components/LpNotificationBell.vue.js +1 -1
  79. package/dist/components/LpPaletteFacts.vue.js +1 -1
  80. package/dist/components/LpPaletteStats.vue.js +1 -1
  81. package/dist/components/LpPasswordInput.vue.d.ts +7 -1
  82. package/dist/components/LpPasswordInput.vue.js +1 -1
  83. package/dist/components/LpPie.vue.js +1 -1
  84. package/dist/components/LpPipeline.vue.js +1 -1
  85. package/dist/components/LpPopover.vue.js +1 -1
  86. package/dist/components/LpQuota.vue.js +1 -1
  87. package/dist/components/LpRelativeTime.vue.js +1 -1
  88. package/dist/components/LpRepeater.vue.js +1 -1
  89. package/dist/components/LpRollingText.vue.d.ts +2 -0
  90. package/dist/components/LpRollingText.vue.js +1 -1
  91. package/dist/components/LpSecretField.vue.js +1 -1
  92. package/dist/components/LpSelect.vue.js +1 -1
  93. package/dist/components/LpSidebar.vue.js +1 -1
  94. package/dist/components/LpSidebarNav.vue.js +1 -1
  95. package/dist/components/LpStat.vue.js +1 -1
  96. package/dist/components/LpStatus.vue.js +1 -1
  97. package/dist/components/LpStepMark.vue.js +1 -1
  98. package/dist/components/LpStepper.vue.js +1 -1
  99. package/dist/components/LpTable.vue.js +4 -4
  100. package/dist/components/LpTabs.vue.js +3 -3
  101. package/dist/components/LpTagsInput.vue.js +1 -1
  102. package/dist/components/LpThemeStudio.vue.js +1 -1
  103. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  104. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  105. package/dist/components/LpTour.vue.js +1 -1
  106. package/dist/components/LpUptimeBar.vue.js +1 -1
  107. package/dist/components/PickerField.vue.d.ts +5 -3
  108. package/dist/components/PickerField.vue.js +1 -1
  109. package/dist/components/TourCard.vue.js +1 -1
  110. package/dist/components/menuWhen.js +1 -1
  111. package/dist/composables/useField.d.ts +5 -0
  112. package/dist/composables/useField.js +21 -1
  113. package/dist/composables/useForm.js +13 -4
  114. package/dist/composables/useView.js +4 -1
  115. package/dist/index.js +43 -43
  116. package/package.json +4 -1
  117. package/src/components/ContextMenuItems.vue +5 -2
  118. package/src/components/LpChart.vue +19 -17
  119. package/src/components/LpContextMenu.vue +4 -3
  120. package/src/components/LpDataList.vue +2 -2
  121. package/src/components/LpDatePicker.vue +2 -0
  122. package/src/components/LpDateRangePicker.vue +2 -0
  123. package/src/components/LpDropdownMenu.vue +1 -1
  124. package/src/components/LpEditable.vue +3 -1
  125. package/src/components/LpPasswordInput.vue +10 -5
  126. package/src/components/LpPopover.vue +4 -0
  127. package/src/components/LpRepeater.vue +64 -13
  128. package/src/components/LpRollingText.vue +12 -1
  129. package/src/components/LpSecretField.vue +15 -8
  130. package/src/components/LpSelect.vue +4 -9
  131. package/src/components/PickerField.vue +5 -4
  132. package/src/composables/useField.ts +26 -1
  133. package/src/composables/useForm.ts +14 -5
  134. package/src/composables/useView.ts +3 -0
  135. package/dist/chunks/LpRepeater-D0VjmD6y.js +0 -140
@@ -30,6 +30,7 @@ function useForm(options) {
30
30
  const submitting = ref(false);
31
31
  const submitCount = ref(0);
32
32
  const runs = /* @__PURE__ */ new Map();
33
+ let validationEpoch = 0;
33
34
  const fromForm = /* @__PURE__ */ new Map();
34
35
  const baseVersion = ref(0);
35
36
  const keys = () => Object.keys(plain());
@@ -51,7 +52,7 @@ function useForm(options) {
51
52
  return void 0;
52
53
  }
53
54
  async function runField(name) {
54
- const run = (runs.get(name) ?? 0) + 1;
55
+ const run = /* @__PURE__ */ Symbol();
55
56
  runs.set(name, run);
56
57
  const found = await checkField(name);
57
58
  if (runs.get(name) !== run) return !errors[name];
@@ -61,7 +62,7 @@ function useForm(options) {
61
62
  }
62
63
  async function runForm() {
63
64
  if (!options.validate) return true;
64
- const run = (runs.get("form") ?? 0) + 1;
65
+ const run = /* @__PURE__ */ Symbol();
65
66
  runs.set("form", run);
66
67
  const found = await options.validate(plain()) ?? {};
67
68
  if (runs.get("form") !== run) return true;
@@ -78,12 +79,17 @@ function useForm(options) {
78
79
  return ok;
79
80
  }
80
81
  async function validate(name) {
82
+ const epoch = validationEpoch;
81
83
  validating.value = true;
82
84
  try {
83
- if (name !== void 0) return await runField(name);
85
+ if (name !== void 0) {
86
+ const valid2 = await runField(name);
87
+ return epoch === validationEpoch && valid2;
88
+ }
84
89
  const fields = await Promise.all(keys().map(runField));
90
+ if (epoch !== validationEpoch) return false;
85
91
  const form = await runForm();
86
- return fields.every(Boolean) && form && !Object.values(external).some(Boolean);
92
+ return epoch === validationEpoch && fields.every(Boolean) && form && !Object.values(external).some(Boolean);
87
93
  } finally {
88
94
  validating.value = false;
89
95
  }
@@ -99,6 +105,7 @@ function useForm(options) {
99
105
  for (const [k, v] of Object.entries(next)) set(k, v);
100
106
  }
101
107
  function clearState() {
108
+ validationEpoch++;
102
109
  for (const k of Object.keys(errors)) delete errors[k];
103
110
  for (const k of Object.keys(external)) delete external[k];
104
111
  for (const k of Object.keys(touched)) delete touched[k];
@@ -131,7 +138,9 @@ function useForm(options) {
131
138
  { deep: true }
132
139
  );
133
140
  async function recheck(names) {
141
+ const epoch = validationEpoch;
134
142
  await Promise.all(names.map((name) => validate(name)));
143
+ if (epoch !== validationEpoch) return;
135
144
  if (fromForm.size || submitCount.value) await runForm();
136
145
  }
137
146
  let snapshot = clone(plain());
@@ -1,4 +1,4 @@
1
- import { computed, inject, provide } from "vue";
1
+ import { inject, computed, provide } from "vue";
2
2
  const LP_VIEW = /* @__PURE__ */ Symbol.for("lp-view");
3
3
  function provideView(view) {
4
4
  provide(LP_VIEW, view);
@@ -27,6 +27,9 @@ function forwardViewEvents(from, to) {
27
27
  const Copy = event.constructor;
28
28
  const copy = new Copy(event.type, event);
29
29
  copy[ORIGIN] = from;
30
+ const path = event.composedPath();
31
+ Object.defineProperty(copy, "target", { value: event.target });
32
+ copy.composedPath = () => path;
30
33
  to.dispatchEvent(copy);
31
34
  };
32
35
  for (const type of FORWARDED) from.addEventListener(type, forward);
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import { _ } from "./chunks/LayoutCanvas-BsJIzhdd.js";
2
- import { _ as _2 } from "./chunks/LpAddressInput-CNnLTDZg.js";
2
+ import { _ as _2 } from "./chunks/LpAddressInput-Chv_Xf8q.js";
3
3
  import { _ as _3 } from "./chunks/LpMapPicker-BtIl7NOM.js";
4
4
  import { OSM_TILES, createNominatimProvider, emptyAddress, formatAddress, project, tileUrl, unproject } from "./components/address.js";
5
5
  import { _ as _4 } from "./chunks/LpActionBar-CzOFar5t.js";
6
6
  import { _ as _5 } from "./chunks/LpAlert-C5igj802.js";
7
- import { _ as _6 } from "./chunks/LpAppShell-CEUAB8kK.js";
7
+ import { _ as _6 } from "./chunks/LpAppShell-BiWByLmt.js";
8
8
  import { _ as _7 } from "./chunks/LpAutocomplete-D92niDHE.js";
9
9
  import { _ as _8 } from "./chunks/LpAvatar-CLPl-qOF.js";
10
- import { _ as _9 } from "./chunks/LpBadge-HOEPBYmi.js";
11
- import { _ as _10 } from "./chunks/LpBreadcrumbs-DYoPc3P4.js";
10
+ import { _ as _9 } from "./chunks/LpBadge-BBq1Er9T.js";
11
+ import { _ as _10 } from "./chunks/LpBreadcrumbs-JKEi_yFF.js";
12
12
  import { _ as _11 } from "./chunks/LpButton-CVxBfGjd.js";
13
13
  import { _ as _12 } from "./chunks/LpCalendar-pVL91-Pl.js";
14
14
  import { _ as _13 } from "./chunks/LpCard-CqKLnEhl.js";
@@ -18,7 +18,7 @@ import { CHART_PALETTE, axisTicks, chartSummary, formatTick, markerIndex, niceSc
18
18
  import { _ as _14 } from "./chunks/LpCheckbox-DHc2bHDe.js";
19
19
  import { _ as _15 } from "./chunks/LpCodeBlock-BGsQhxw8.js";
20
20
  import { tokenizeLines } from "./components/codeHighlight.js";
21
- import { _ as _16 } from "./chunks/LpColorPicker-DFugXNUi.js";
21
+ import { _ as _16 } from "./chunks/LpColorPicker-B7HSIFmn.js";
22
22
  import { DEFAULT_SWATCHES, clampHsv, formatColor, hsvToHsl, hsvToRgb, isLight, normalizeHue, opaqueCss, parseColor, parseHex, rgbToHex, rgbToHsv } from "./components/color.js";
23
23
  import { default as default3 } from "./components/LpCommandPalette.vue.js";
24
24
  import { applyQueryFilters, highlightParts, parseCommandQuery, parsePaletteQuery, rankCommandItems } from "./components/commandSearch.js";
@@ -33,89 +33,89 @@ import { comboKeys, comboSteps } from "./components/keys.js";
33
33
  import { _ as _18 } from "./chunks/LpConfirmDialog-CfGCux8m.js";
34
34
  import { _ as _19 } from "./chunks/LpConfirmHost-exB7JmcO.js";
35
35
  import { confirm, useConfirm } from "./components/confirm.js";
36
- import { _ as _20 } from "./chunks/LpContextMenu-COwOwRgI.js";
37
- import { _ as _21 } from "./chunks/LpDatePicker-BUe1VUC0.js";
38
- import { _ as _22 } from "./chunks/LpDateRangePicker-C_k65vGR.js";
36
+ import { _ as _20 } from "./chunks/LpContextMenu-Cj96ENDC.js";
37
+ import { _ as _21 } from "./chunks/LpDatePicker-ac1_6o5P.js";
38
+ import { _ as _22 } from "./chunks/LpDateRangePicker-B15gYrZJ.js";
39
39
  import { _ as _23 } from "./chunks/LpRangeCalendar-c5qj7YcC.js";
40
40
  import { clampRange, dayAllowed, defaultDatePresets, defaultRangePresets, formatRange, normalizeRange, sameRange } from "./components/dateRange.js";
41
41
  import { _ as _24 } from "./chunks/LpDisclosure-DOarzlAG.js";
42
42
  import { _ as _25 } from "./chunks/LpDivider-CUX46KR0.js";
43
43
  import { _ as _26 } from "./chunks/LpDrawer-DGNKRsGq.js";
44
- import { _ as _27 } from "./chunks/LpDropdownMenu-CRgrhdAH.js";
44
+ import { _ as _27 } from "./chunks/LpDropdownMenu-R4aYVtVV.js";
45
45
  import { default as default9 } from "./components/LpDropzone.vue.js";
46
46
  import { _ as _28 } from "./chunks/LpEmptyState-KTKipws2.js";
47
- import { _ as _29 } from "./chunks/LpFileTree-DMISXVHC.js";
47
+ import { _ as _29 } from "./chunks/LpFileTree-DDNg34tJ.js";
48
48
  import { ancestorIds, checkStateOf, checkedCount, computeStats, fileIcon, formatModified, formatSize, sortNodes, subtreeIds, subtreeSize } from "./components/fileTree.js";
49
49
  import { _ as _30 } from "./chunks/LpFieldNotice-CurbNuXI.js";
50
50
  import { _ as _31 } from "./chunks/LpFormField-BWwgm1E4.js";
51
51
  import { _ as _32 } from "./chunks/LpIcon-HJP5xMz4.js";
52
52
  import { i, b, a, c } from "./chunks/icons-4IywzkHk.js";
53
53
  import { default as default10 } from "./components/LpImageEditor.vue.js";
54
- import { _ as _33 } from "./chunks/LpInfraNode-CUC3t4na.js";
54
+ import { _ as _33 } from "./chunks/LpInfraNode-D64hywJI.js";
55
55
  import { _ as _34 } from "./chunks/LpInput-CDuwODJG.js";
56
56
  import { _ as _35 } from "./chunks/LpLightbox-XJ0LpTcZ.js";
57
57
  import { fileNameOf } from "./components/lightbox.js";
58
58
  import { _ as _36 } from "./chunks/LpLink-Krkjhe_y.js";
59
- import { _ as _37 } from "./chunks/LpLogViewer-elZHbj85.js";
59
+ import { _ as _37 } from "./chunks/LpLogViewer-DKK4ySZl.js";
60
60
  import { countLevels, matchPositions, matchesTerm, ringWindow, stepMatch } from "./components/logSearch.js";
61
- import { _ as _38 } from "./chunks/LpMediaGallery-D5swlmZ_.js";
61
+ import { _ as _38 } from "./chunks/LpMediaGallery-rmI1DjKN.js";
62
62
  import { _ as _39 } from "./chunks/LpModal-eBMt2Fqn.js";
63
- import { _ as _40 } from "./chunks/LpModalNav-D4Z0wVHR.js";
64
- import { _ as _41 } from "./chunks/LpNotificationBell-DPZmP5dM.js";
63
+ import { _ as _40 } from "./chunks/LpModalNav-DiyFCHiZ.js";
64
+ import { _ as _41 } from "./chunks/LpNotificationBell-D-WhE5m2.js";
65
65
  import { _ as _42 } from "./chunks/LpNumberField-B9k-h2HE.js";
66
66
  import { _ as _43 } from "./chunks/LpTimeField-BFQVf_PW.js";
67
67
  import { _ as _44 } from "./chunks/LpNumberFlow-Cfyh033Q.js";
68
68
  import { _ as _45 } from "./chunks/LpOtpInput-CeBPsM7D.js";
69
69
  import { _ as _46 } from "./chunks/LpPagination-VNCX6pFC.js";
70
- import { _ as _47 } from "./chunks/LpPasswordInput-DTV18FIh.js";
71
- import { _ as _48 } from "./chunks/LpPie-CFuV7pZv.js";
70
+ import { _ as _47 } from "./chunks/LpPasswordInput-GL2KOFK8.js";
71
+ import { _ as _48 } from "./chunks/LpPie-BgXZ3xmm.js";
72
72
  import { _ as _49 } from "./chunks/LpPhoneInput-C60tx1tC.js";
73
73
  import { filterCountries, flagEmoji, loadCountries, matchCountryByValue } from "./components/countries.js";
74
- import { _ as _50 } from "./chunks/LpPopover-BEIcqb9p.js";
74
+ import { _ as _50 } from "./chunks/LpPopover-DmZ3wUtP.js";
75
75
  import { _ as _51 } from "./chunks/LpProgress-CE-m5OpD.js";
76
76
  import { _ as _52 } from "./chunks/LpRadio-CWA5Eb3M.js";
77
77
  import { _ as _53 } from "./chunks/LpRadioGroup-CGBr5nIp.js";
78
- import { _ as _54 } from "./chunks/LpRollingText-DB7upf-5.js";
78
+ import { _ as _54 } from "./chunks/LpRollingText-DiL717LK.js";
79
79
  import { _ as _55 } from "./chunks/LpScrollArea-Hz3-JWUG.js";
80
80
  import { _ as _56 } from "./chunks/LpSegmented-BO99Sr4m.js";
81
81
  import { _ as _57 } from "./chunks/LpSection-BW4xJ-Li.js";
82
- import { _ as _58 } from "./chunks/LpSelect-B4f_yRi5.js";
82
+ import { _ as _58 } from "./chunks/LpSelect-C_8cJtj6.js";
83
83
  import { fitChips, toggledValues } from "./components/select.js";
84
84
  import { _ as _59 } from "./chunks/LpServiceNode-D8uJ8sGk.js";
85
85
  import { _ as _60 } from "./chunks/LpShift-DXNsauQZ.js";
86
86
  import { _ as _61 } from "./chunks/LpSwap-DzE6M3Mg.js";
87
87
  import { _ as _62 } from "./chunks/LpHintExample-9Py0wc-L.js";
88
88
  import { default as default11 } from "./components/LpShortcutsDialog.vue.js";
89
- import { _ as _63 } from "./chunks/LpSidebar-D-M0Y_7U.js";
89
+ import { _ as _63 } from "./chunks/LpSidebar-CZRXtvem.js";
90
90
  import { _ as _64 } from "./chunks/LpSkeleton-BB6XIV-w.js";
91
91
  import { _ as _65 } from "./chunks/LpSlider-DuoRpOrH.js";
92
92
  import { _ as _66 } from "./chunks/LpRangeSlider-Dv6lNvHY.js";
93
93
  import { _ as _67 } from "./chunks/LpVideoBackdrop-DS1wGv-X.js";
94
94
  import { formatClipTime, isNativeLoop, planLoop, seamProgress, seamReached } from "./components/videoBackdrop.js";
95
95
  import { _ as _68 } from "./chunks/LpSparkline-CExIRDb3.js";
96
- import { _ as _69 } from "./chunks/LpStat-B2ix1Q7t.js";
97
- import { _ as _70 } from "./chunks/LpStepper-DRFfdJaq.js";
96
+ import { _ as _69 } from "./chunks/LpStat-DFKlPJgy.js";
97
+ import { _ as _70 } from "./chunks/LpStepper-BbnS5jUr.js";
98
98
  import { _ as _71 } from "./chunks/LpSwitch-DrzKrZZV.js";
99
99
  import { default as default12 } from "./components/LpTable.vue.js";
100
100
  import { compareValues } from "./components/tableSort.js";
101
101
  import { resolveRowMenu } from "./components/tableRowMenu.js";
102
102
  import { _ as _72 } from "./chunks/LpTableOfContents-rYvo8z5T.js";
103
103
  import { default as default13 } from "./components/LpTabs.vue.js";
104
- import { _ as _73 } from "./chunks/LpTagsInput-DgpBFRV2.js";
104
+ import { _ as _73 } from "./chunks/LpTagsInput-DZg80W-B.js";
105
105
  import { addTags, splitTags } from "./components/tags.js";
106
106
  import { _ as _74 } from "./chunks/LpTextarea-DiWjeVoJ.js";
107
- import { _ as _75 } from "./chunks/LpThemeSwitcher-D5uz0MhK.js";
107
+ import { _ as _75 } from "./chunks/LpThemeSwitcher-CadVBTBn.js";
108
108
  import { _ as _76 } from "./chunks/LpTilt-B7KHX1zH.js";
109
109
  import { _ as _77 } from "./chunks/LpToaster-Wv9ksj4q.js";
110
110
  import { _ as _78 } from "./chunks/LpTooltip-Cz8SQwRt.js";
111
- import { _ as _79 } from "./chunks/LpTour-NfRJNEIP.js";
111
+ import { _ as _79 } from "./chunks/LpTour-CY2bFXge.js";
112
112
  import { holeOf, openContextMenu, panelsAround } from "./components/tour.js";
113
- import { _ as _80 } from "./chunks/LpHintLayer-p4hqzdyA.js";
114
- import { _ as _81 } from "./chunks/LpHints-CCrhRfy9.js";
113
+ import { _ as _80 } from "./chunks/LpHintLayer-HvwUA5Ec.js";
114
+ import { _ as _81 } from "./chunks/LpHints-DxbPKOzQ.js";
115
115
  import { HINT_SIGNALS, contextMenuTip, createHintSystem, dropzoneTip, hintKey, hintSummary, hotkeyTip, localHintStorage, noteDropzone, noteHotkeyTarget, paletteTip, provideHintSystem, runningHintSystem, useHintSystem } from "./composables/useHintSystem.js";
116
116
  import { _ as _82 } from "./chunks/LpTooltipProvider-CftjV7Xc.js";
117
- import { _ as _83 } from "./chunks/LpTopologyCanvas-ZhKthfgz.js";
118
- import { _ as _84 } from "./chunks/LpUptimeBar-DWegV2p6.js";
117
+ import { _ as _83 } from "./chunks/LpTopologyCanvas-C17A1XCb.js";
118
+ import { _ as _84 } from "./chunks/LpUptimeBar-Tew1Ykx4.js";
119
119
  import { deserializeLayout, serializeLayout } from "./layout/tree.js";
120
120
  import { addLeaf, addTab, countBlocks, countLeaves, makeLayout, moveLeaf, removeBlock, removeLeaf, reorderTab, resizeAt, setActiveTab } from "./layout/tree.js";
121
121
  import { blockTitle, defineBlocks } from "./layout/registry.js";
@@ -123,7 +123,7 @@ import { layoutController, useLayout } from "./layout/useLayout.js";
123
123
  import { a as parseTheme, s as serializeTheme } from "./chunks/useTheme-BOV_-AiY.js";
124
124
  import { D, T, b as b2, c as c2, d, e, f, g, l, h, n, i as i2, j, p, r, k, t, m, o, q, u, v } from "./chunks/useTheme-BOV_-AiY.js";
125
125
  import { G, N, d as d2, i as i3, s } from "./chunks/backdrop-Dkf2vM81.js";
126
- import { _ as _85, a as a2, b as b3, c as c3, d as d3, e as e2, u as u2, w } from "./chunks/LpThemeStudio-DguwHdGt.js";
126
+ import { _ as _85, a as a2, b as b3, c as c3, d as d3, e as e2, u as u2, w } from "./chunks/LpThemeStudio-DxVZMtzN.js";
127
127
  import { useClipboard } from "./composables/useClipboard.js";
128
128
  import { activeShortcuts, appleModifierLabel, findHotkeyConflicts, hotkeyConflicts, hotkeySteps, isAppleKeyboard, matchesHotkey, mergeShortcutGroups, parseCombo, pendingHotkey, sequenceProgress, useAppleKeyboard, useHotkeys } from "./composables/useHotkeys.js";
129
129
  import { anyModalOpen, topModalElement, useModalLayer } from "./components/modalDepth.js";
@@ -163,11 +163,11 @@ import { _ as _86 } from "./chunks/LpThemeProvider-DcbfOxsU.js";
163
163
  import { _ as _87 } from "./chunks/LpFrame-BVQCQLDI.js";
164
164
  import { _ as _88 } from "./chunks/LpThemeStudioSection-BwhqYDLf.js";
165
165
  import { isInternalHref, resolveLink } from "./components/link.js";
166
- import { _ as _89 } from "./chunks/LpRepeater-D0VjmD6y.js";
167
- import { _ as _90 } from "./chunks/LpGauge-Bk8TwJj0.js";
168
- import { _ as _91 } from "./chunks/LpQuota-2Sw_gqcJ.js";
169
- import { _ as _92 } from "./chunks/LpStatus-C7kx5PKE.js";
170
- import { _ as _93 } from "./chunks/LpRelativeTime-CKzVqAo9.js";
166
+ import { _ as _89 } from "./chunks/LpRepeater-D0S7jjwr.js";
167
+ import { _ as _90 } from "./chunks/LpGauge-C14Z9503.js";
168
+ import { _ as _91 } from "./chunks/LpQuota-DaL8TgNe.js";
169
+ import { _ as _92 } from "./chunks/LpStatus-BsGLrpor.js";
170
+ import { _ as _93 } from "./chunks/LpRelativeTime-yin9uQP7.js";
171
171
  import { _ as _94 } from "./chunks/LpActivityLine-CJvzrNpj.js";
172
172
  import { TONE_COLOR, TONE_SOFT, arcPath, capacityThresholds, meterFraction, toneAt } from "./components/meter.js";
173
173
  import { TONES, TONE_ALIASES, toneLook, toneOf } from "./components/tone.js";
@@ -175,20 +175,20 @@ import { formatAmount, quotaSegments, quotaState } from "./components/quota.js";
175
175
  import { compactNumber, formatBytes } from "./components/format.js";
176
176
  import { STATUS_LABELS, STATUS_LOOK } from "./components/status.js";
177
177
  import { formatRelativeTime } from "./components/relativeTime.js";
178
- import { _ as _95 } from "./chunks/LpPipeline-D81yh_NX.js";
179
- import { _ as _96 } from "./chunks/LpStepMark-DK-5BKAt.js";
178
+ import { _ as _95 } from "./chunks/LpPipeline-B31h41Mu.js";
179
+ import { _ as _96 } from "./chunks/LpStepMark-TrzOioa9.js";
180
180
  import { childProgress, connectorFilled, currentStepIndex, isSettled, overallStatus, stepElapsed } from "./components/pipeline.js";
181
181
  import { _ as _97 } from "./chunks/LpLoader-DjJEX8hL.js";
182
182
  import { useLoadingGate } from "./composables/useLoadingGate.js";
183
183
  import { useNow } from "./composables/useNow.js";
184
- import { _ as _98 } from "./chunks/LpCountdown-Dtq1ihlJ.js";
184
+ import { _ as _98 } from "./chunks/LpCountdown-BQnmB4gq.js";
185
185
  import { DEFAULT_MILESTONES, DEFAULT_UNIT_LABELS, ceilToSecond, crossedMilestone, formatElapsed, formatTime, msToNextSecond, splitTime, timeParts } from "./components/timeSpan.js";
186
186
  import { _ as _99 } from "./chunks/LpCopyButton-DzHjnFs0.js";
187
- import { _ as _100 } from "./chunks/LpSecretField-DMfdJ1cQ.js";
188
- import { _ as _101 } from "./chunks/LpDataList-B-5nHfNw.js";
189
- import { _ as _102 } from "./chunks/LpEditable-DTqLt2lT.js";
187
+ import { _ as _100 } from "./chunks/LpSecretField-CfWyHv9m.js";
188
+ import { _ as _101 } from "./chunks/LpDataList-CHNYQw7h.js";
189
+ import { _ as _102 } from "./chunks/LpEditable-Ws3DNQHn.js";
190
190
  import { _ as _103 } from "./chunks/LpTruncate-D_5Pfv5B.js";
191
- import { _ as _104 } from "./chunks/LpCodeDisplay-CIKKT2iW.js";
191
+ import { _ as _104 } from "./chunks/LpCodeDisplay-CbJMs-IK.js";
192
192
  import { formatRemaining, groupCode, middleTruncate, normalizeCode } from "./components/fieldText.js";
193
193
  import { _ as _105 } from "./chunks/LpHoverCard-spGxyw7T.js";
194
194
  import { _ as _106 } from "./chunks/LpIdenticon-BzdC_qz9.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leavepulse/ui",
3
- "version": "0.70.0",
3
+ "version": "0.70.1",
4
4
  "type": "module",
5
5
  "description": "LeavePulse token-driven Vue component kit.",
6
6
  "repository": {
@@ -59,6 +59,7 @@
59
59
  "prepublishOnly": "npm run build",
60
60
  "typecheck": "vue-tsc --noEmit",
61
61
  "test": "bun test",
62
+ "test:browser": "playwright test",
62
63
  "release": "npm version patch -m \"chore: release v%s\" && git push --follow-tags",
63
64
  "release:minor": "npm version minor -m \"chore: release v%s\" && git push --follow-tags",
64
65
  "release:major": "npm version major -m \"chore: release v%s\" && git push --follow-tags",
@@ -85,6 +86,7 @@
85
86
  "devDependencies": {
86
87
  "@iconify-json/lucide": "^1.2.112",
87
88
  "@iconify/vue": "^5.0.1",
89
+ "@playwright/test": "^1.64.1",
88
90
  "@tailwindcss/vite": "^4.2.4",
89
91
  "@types/node": "^26.2.0",
90
92
  "@vitejs/plugin-vue": "^6.0.6",
@@ -107,6 +109,7 @@
107
109
  "@vue-flow/core": "^1.48.2",
108
110
  "@vue-flow/minimap": "^1.5.4",
109
111
  "libphonenumber-js": "^1.12.0",
112
+ "tailwind-merge": "^3.6.0",
110
113
  "vaul-vue": "^0.4.1"
111
114
  }
112
115
  }
@@ -28,6 +28,7 @@ import {
28
28
  DropdownMenuSubTrigger,
29
29
  } from "reka-ui"
30
30
  import { computed } from "vue"
31
+ import { useOutsideGuard, usePortalTarget } from "../composables/useView"
31
32
  import type { ContextMenuItemDef } from "./LpContextMenu.vue"
32
33
  import LpIcon from "./LpIcon.vue"
33
34
  import MenuShortcut from "./MenuShortcut.vue"
@@ -66,6 +67,8 @@ const PRIMITIVES = {
66
67
  } as const
67
68
 
68
69
  const P = computed(() => PRIMITIVES[props.kind])
70
+ const portalTo = usePortalTarget()
71
+ const guardOutside = useOutsideGuard()
69
72
 
70
73
  const ITEM =
71
74
  "group/item flex cursor-pointer select-none items-center gap-2 rounded-inner 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"
@@ -89,8 +92,8 @@ const ICON =
89
92
  </span>
90
93
  <LpIcon name="lucide:chevron-right" :size="14" class="text-muted" />
91
94
  </component>
92
- <component :is="P.Portal">
93
- <component :is="P.SubContent" :collision-padding="8" :class="panel" :side-offset="2" :align-offset="-4">
95
+ <component :is="P.Portal" :to="portalTo">
96
+ <component :is="P.SubContent" @interact-outside="guardOutside" @focus-outside="guardOutside" @escape-key-down="guardOutside" :collision-padding="8" :class="panel" :side-offset="2" :align-offset="-4">
94
97
  <ContextMenuItems :items="item.children" :panel="panel" :kind="kind" />
95
98
  </component>
96
99
  </component>
@@ -1556,23 +1556,25 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
1556
1556
  </div>
1557
1557
  </LpContextMenu>
1558
1558
 
1559
- <table v-if="dataTable && ready" class="sr-only">
1560
- <caption v-if="title">{{ title }}</caption>
1561
- <thead>
1562
- <tr>
1563
- <th scope="col"></th>
1564
- <th v-for="s in allSeries" :key="s.id" scope="col">{{ s.name }}</th>
1565
- </tr>
1566
- </thead>
1567
- <tbody>
1568
- <tr v-for="(label, i) in labels" :key="i">
1569
- <th scope="row">{{ label }}</th>
1570
- <td v-for="s in allSeries" :key="s.id">
1571
- {{ s.values[i] == null ? "—" : fmtSeries(s, s.values[i] as number) }}
1572
- </td>
1573
- </tr>
1574
- </tbody>
1575
- </table>
1559
+ <div v-if="dataTable && ready" class="sr-only">
1560
+ <table>
1561
+ <caption v-if="title">{{ title }}</caption>
1562
+ <thead>
1563
+ <tr>
1564
+ <th scope="col"></th>
1565
+ <th v-for="s in allSeries" :key="s.id" scope="col">{{ s.name }}</th>
1566
+ </tr>
1567
+ </thead>
1568
+ <tbody>
1569
+ <tr v-for="(label, i) in labels" :key="i">
1570
+ <th scope="row">{{ label }}</th>
1571
+ <td v-for="s in allSeries" :key="s.id">
1572
+ {{ s.values[i] == null ? "—" : fmtSeries(s, s.values[i] as number) }}
1573
+ </td>
1574
+ </tr>
1575
+ </tbody>
1576
+ </table>
1577
+ </div>
1576
1578
  </div>
1577
1579
  </template>
1578
1580
 
@@ -14,7 +14,7 @@ import { HINT_SIGNALS, noteContextTarget } from "../composables/useHintSystem"
14
14
  import ContextMenuItems from "./ContextMenuItems.vue"
15
15
  import MenuTitle from "./MenuTitle.vue"
16
16
  import { POPOVER_PANEL } from "./dropdown"
17
- import { useOutsideGuard, usePortalTarget } from "../composables/useView"
17
+ import { useOutsideGuard, usePortalTarget, useView, viewDocument } from "../composables/useView"
18
18
 
19
19
  export interface ContextMenuItemDef {
20
20
  label: string
@@ -81,12 +81,13 @@ const PANEL = `${POPOVER_PANEL} z-(--z-popover) min-w-48 p-1 outline-none`
81
81
  // selection if the menu action left the text as it was.
82
82
  type TextField = HTMLInputElement | HTMLTextAreaElement
83
83
  const SELECTABLE = new Set(["text", "search", "url", "tel", "password"])
84
+ const view = useView()
84
85
  let field: { el: TextField; value: string; start: number; end: number } | null = null
85
86
 
86
87
  function rememberField() {
87
- const el = document.activeElement
88
+ const el = viewDocument(view.value).activeElement
88
89
  const text =
89
- el instanceof HTMLTextAreaElement || (el instanceof HTMLInputElement && SELECTABLE.has(el.type))
90
+ el?.tagName === "TEXTAREA" || (el?.tagName === "INPUT" && SELECTABLE.has((el as HTMLInputElement).type))
90
91
  field = text
91
92
  ? { el: el as TextField, value: (el as TextField).value, start: (el as TextField).selectionStart ?? 0, end: (el as TextField).selectionEnd ?? 0 }
92
93
  : null
@@ -128,7 +128,7 @@ const pad = computed(() => (props.size === "sm" ? "py-1.5 text-xs" : "py-2.5 tex
128
128
  </LpTooltip>
129
129
  </dt>
130
130
  <dd class="flex min-w-0 items-center gap-1.5 text-ink" :class="item.mono ? 'font-mono' : ''">
131
- <span class="min-w-0 break-words">
131
+ <span class="min-w-0 flex-1 [overflow-wrap:anywhere]">
132
132
  <slot
133
133
  v-if="slots[`value-${keyOf(item)}`] || slots.value"
134
134
  :name="slots[`value-${keyOf(item)}`] ? `value-${keyOf(item)}` : 'value'"
@@ -136,7 +136,7 @@ const pad = computed(() => (props.size === "sm" ? "py-1.5 text-xs" : "py-2.5 tex
136
136
  :value="item.value"
137
137
  />
138
138
  <span v-else-if="isEmpty(item.value)" class="text-muted">{{ text.empty }}</span>
139
- <LpRollingText v-else-if="rolls(item.value)" :value="item.value!" align="start" />
139
+ <LpRollingText v-else-if="rolls(item.value)" :value="item.value!" align="start" wrap />
140
140
  <template v-else>{{ item.value }}</template>
141
141
  </span>
142
142
  <!-- Quiet until the row is hovered or focused; always there on touch,
@@ -87,6 +87,7 @@ const props = withDefaults(
87
87
 
88
88
  const emit = defineEmits<{
89
89
  (e: "update:modelValue", value: string | undefined): void
90
+ (e: "blur", event: FocusEvent): void
90
91
  }>()
91
92
 
92
93
  const open = ref(false)
@@ -197,6 +198,7 @@ const presetOptions = computed(() => presetList.value.map((preset) => ({
197
198
  :presets="presetOptions"
198
199
  presets-class="sm:w-36"
199
200
  @clear="clear"
201
+ @blur="emit('blur', $event)"
200
202
  >
201
203
  <div class="flex flex-col">
202
204
  <LpCalendar
@@ -69,6 +69,7 @@ const props = withDefaults(
69
69
 
70
70
  const emit = defineEmits<{
71
71
  (e: "update:modelValue", value: DateRange | undefined): void
72
+ (e: "blur", event: FocusEvent): void
72
73
  }>()
73
74
 
74
75
  const text = useLabels<DateRangePickerLabels>(
@@ -157,6 +158,7 @@ const presetOptions = computed(() => presetList.value.map((preset) => ({
157
158
  :presets="presetOptions"
158
159
  presets-class="sm:w-40"
159
160
  @clear="emit('update:modelValue', undefined)"
161
+ @blur="emit('blur', $event)"
160
162
  >
161
163
  <LpRangeCalendar
162
164
  :model-value="value"
@@ -45,7 +45,7 @@ const guardOutside = useOutsideGuard()
45
45
  </script>
46
46
 
47
47
  <template>
48
- <DropdownMenuRoot @update:open="opened">
48
+ <DropdownMenuRoot :modal="false" @update:open="opened">
49
49
  <DropdownMenuTrigger as-child>
50
50
  <slot name="trigger" />
51
51
  </DropdownMenuTrigger>
@@ -129,7 +129,7 @@ function cancel() {
129
129
 
130
130
  let committing = false
131
131
  async function commit(refocus: boolean) {
132
- if (!editing.value || committing) return
132
+ if (!editing.value || committing || !interactive.value) return
133
133
  const value = props.trim ? draft.value.trim() : draft.value
134
134
  if (value === props.modelValue) {
135
135
  notice.clear()
@@ -273,6 +273,8 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(() => "relative inline-
273
273
  :aria-invalid="(notice.tone.value === 'danger' && !!notice.message.value) || undefined"
274
274
  :placeholder="placeholder"
275
275
  :maxlength="maxlength"
276
+ :disabled="disabled"
277
+ :readonly="readonly"
276
278
  :rows="multiline ? 1 : undefined"
277
279
  class="col-start-1 row-start-1 w-full min-w-0 resize-none overflow-hidden bg-transparent text-ink outline-none placeholder:text-muted"
278
280
  :class="PAD[size]"
@@ -13,15 +13,18 @@ export interface PasswordInputLabels extends Record<string, string> {
13
13
  // LpSecretField's input form is this same field: it drives `visible` (to hide
14
14
  // again on a timer) and puts its copy button in `actions`.
15
15
  import { ref } from "vue"
16
+ import { useFieldControl } from "../composables/useField"
16
17
  import { useLabels } from "../composables/useLpConfig"
17
18
  import LpInput from "./LpInput.vue"
18
19
  import RevealToggle from "./RevealToggle.vue"
19
20
 
20
- const props = defineProps<{
21
+ const props = withDefaults(defineProps<{
21
22
  modelValue?: string
22
23
  placeholder?: string
23
24
  invalid?: boolean
24
25
  disabled?: boolean
26
+ /** Offer the show/hide button. When false, the field stays masked. */
27
+ revealable?: boolean
25
28
  // Field wrapping mirrors LpInput: passing any of these wraps the control in
26
29
  // LpFormField, so a password field labels itself like every other field.
27
30
  label?: string
@@ -31,10 +34,11 @@ const props = defineProps<{
31
34
  /** Control height, as on LpInput. */
32
35
  size?: "sm" | "md" | "lg"
33
36
  labels?: Partial<PasswordInputLabels>
34
- }>()
37
+ }>(), { revealable: true })
35
38
  defineEmits<{ (e: "update:modelValue", value: string): void }>()
36
39
  /** Whether the text shows; bind it to reveal or hide from outside. */
37
40
  const visible = defineModel<boolean>("visible", { default: false })
41
+ const field = useFieldControl(() => ({ wrapped: false, disabled: props.disabled }))
38
42
 
39
43
  const text = useLabels<PasswordInputLabels>(
40
44
  "passwordInput",
@@ -54,10 +58,10 @@ defineExpose({
54
58
  ref="inner"
55
59
  v-bind="$attrs"
56
60
  :model-value="modelValue"
57
- :type="visible ? 'text' : 'password'"
61
+ :type="revealable && visible ? 'text' : 'password'"
58
62
  :placeholder="placeholder"
59
63
  :invalid="invalid"
60
- :disabled="disabled"
64
+ :disabled="field.disabled"
61
65
  :label="label"
62
66
  :hint="hint"
63
67
  :error="error"
@@ -71,11 +75,12 @@ defineExpose({
71
75
  <!-- Sized to the icon with a hair of padding, as the field's other
72
76
  trailing controls are, rather than to a full square button. -->
73
77
  <RevealToggle
78
+ v-if="revealable"
74
79
  v-model="visible"
75
80
  :icon-size="size === 'sm' ? 14 : 16"
76
81
  :show-label="text.show"
77
82
  :hide-label="text.hide"
78
- :disabled="disabled"
83
+ :disabled="field.disabled"
79
84
  class="size-auto rounded-inner p-1 hover:bg-transparent"
80
85
  />
81
86
  </template>
@@ -10,6 +10,9 @@ import { mergeClass } from "../composables/useMergedClass"
10
10
  import { POPOVER_PANEL } from "./dropdown"
11
11
  import { useOutsideGuard, usePortalTarget } from "../composables/useView"
12
12
 
13
+ // The trigger owns its attributes through the slot; fallthrough tags the panel.
14
+ defineOptions({ inheritAttrs: false })
15
+
13
16
  const props = withDefaults(
14
17
  defineProps<{
15
18
  side?: "top" | "right" | "bottom" | "left"
@@ -47,6 +50,7 @@ const guardOutside = useOutsideGuard()
47
50
  </PopoverTrigger>
48
51
  <PopoverPortal :to="portalTo">
49
52
  <PopoverContent
53
+ v-bind="$attrs"
50
54
  @interact-outside="guardOutside"
51
55
  @escape-key-down="guardOutside"
52
56
  :collision-padding="8"