@leavepulse/ui 0.59.0 → 0.60.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 (154) hide show
  1. package/dist/assets/{LpCommandPalette-BM_IyzwB.css → LpCommandPalette-DA5pmuPi.css} +21 -21
  2. package/dist/assets/{LpTable-B_QCQCbB.css → LpTable-BZZf_rrt.css} +19 -19
  3. package/dist/chunks/{ContextMenuItems-CioDScj3.js → ContextMenuItems-qXReFtQW.js} +1 -1
  4. package/dist/chunks/{LayoutCanvas-BcGLJVBq.js → LayoutCanvas-t7LWFCEn.js} +1 -1
  5. package/dist/chunks/{LayoutNode-BkBn6dvM.js → LayoutNode-DHsE6GwM.js} +1 -1
  6. package/dist/chunks/{LpActionBar-DCN-_pZP.js → LpActionBar-BsSp66S_.js} +2 -2
  7. package/dist/chunks/{LpAddressInput-D-H94m4q.js → LpAddressInput-DD4zTN4P.js} +7 -7
  8. package/dist/chunks/{LpAlert-CXMn1GYE.js → LpAlert--KLL4NLk.js} +1 -1
  9. package/dist/chunks/{LpAppShell-BeMuKEjh.js → LpAppShell-Cv-Y9qNA.js} +3 -3
  10. package/dist/chunks/{LpAutocomplete-hJ_6CHlh.js → LpAutocomplete-PnL2ntKl.js} +1 -1
  11. package/dist/chunks/{LpAvatar-CeW4Z5CL.js → LpAvatar-CwGs1JCQ.js} +2 -2
  12. package/dist/chunks/{LpBreadcrumbs-BLzOEgAF.js → LpBreadcrumbs-CndzPYiG.js} +1 -1
  13. package/dist/chunks/{LpButton-vhlwmpBy.js → LpButton-CJSD7N0Z.js} +1 -1
  14. package/dist/chunks/{LpCalendar-BLoE8Qm7.js → LpCalendar-CXVDbb2M.js} +1 -1
  15. package/dist/chunks/{LpCard-Gbr8a1xK.js → LpCard-B2D0GIUU.js} +1 -1
  16. package/dist/chunks/{LpCheckbox-B_C8sOoT.js → LpCheckbox-DV9W6T3H.js} +1 -1
  17. package/dist/chunks/{LpCodeBlock-D6zhp30a.js → LpCodeBlock-t6MLA3fb.js} +1 -1
  18. package/dist/chunks/{LpColorPicker-CVXwjEtX.js → LpColorPicker-CvBF8TeL.js} +2 -2
  19. package/dist/chunks/{LpConfirmDialog-DkgIT-Xg.js → LpConfirmDialog-tkgyY3eu.js} +3 -3
  20. package/dist/chunks/{LpConfirmHost-CYzXWFOI.js → LpConfirmHost-CoYIcUdl.js} +1 -1
  21. package/dist/chunks/{LpContextMenu-DRFd-iyc.js → LpContextMenu-BnN1k7ga.js} +17 -5
  22. package/dist/chunks/{LpDatePicker-B-VMHMgy.js → LpDatePicker-DxdrVNCG.js} +3 -3
  23. package/dist/chunks/{LpDateRangePicker-B68KPKPl.js → LpDateRangePicker-DjeaqikC.js} +2 -2
  24. package/dist/chunks/{LpDisclosure-Ct-VBHxt.js → LpDisclosure-s8cQ7KQq.js} +1 -1
  25. package/dist/chunks/{LpDrawer-Rc6eAJrr.js → LpDrawer-C97yoWmh.js} +1 -1
  26. package/dist/chunks/{LpDropdownMenu-BoJQsjzt.js → LpDropdownMenu-CbyYu4Rw.js} +11 -4
  27. package/dist/chunks/{LpEmptyState-CBwwkkdA.js → LpEmptyState-CX8fdGSU.js} +1 -1
  28. package/dist/chunks/{LpFieldNotice-9hH4ITZa.js → LpFieldNotice-B--RzKfj.js} +1 -1
  29. package/dist/chunks/{LpFileTree-Bs57DhVa.js → LpFileTree-DEqh2ySW.js} +2 -2
  30. package/dist/chunks/{LpFileTreeNode-XgJW65v5.js → LpFileTreeNode-DCZA7sQ-.js} +3 -3
  31. package/dist/chunks/{LpFormField-BpQ6WJPe.js → LpFormField-DMPPL1jF.js} +1 -1
  32. package/dist/chunks/{LpHintLayer-B5-6FyEf.js → LpHintLayer-DsclGYcD.js} +1 -1
  33. package/dist/chunks/{LpHints-BqoZXHZk.js → LpHints-BTpvisgP.js} +10 -4
  34. package/dist/chunks/{LpIcon-B5guGKrW.js → LpIcon-CTuDVTYv.js} +1 -1
  35. package/dist/chunks/{LpInput-WvyP02ID.js → LpInput-C7FHxzj2.js} +2 -2
  36. package/dist/chunks/{LpLightbox-Dq-e36uT.js → LpLightbox-DiksFa4L.js} +1 -1
  37. package/dist/chunks/{LpLogViewer-B92bAftG.js → LpLogViewer-BuPe23sZ.js} +2 -2
  38. package/dist/chunks/{LpMapPicker-BH5csaBt.js → LpMapPicker-DybIlWnF.js} +1 -1
  39. package/dist/chunks/{LpMediaGallery-B1kDypJ-.js → LpMediaGallery-Cic9UHsa.js} +2 -2
  40. package/dist/chunks/{LpModal-DvGD6kEe.js → LpModal-QFfctZsj.js} +1 -1
  41. package/dist/chunks/{LpModalNav-B-_zRTS-.js → LpModalNav-Cw7m-eks.js} +4 -4
  42. package/dist/chunks/{LpNotificationBell-63pvatBj.js → LpNotificationBell-xH_JphpS.js} +4 -4
  43. package/dist/chunks/{LpNumberField-CJPjmoDz.js → LpNumberField-BFSRVGkJ.js} +1 -1
  44. package/dist/chunks/{LpPagination-DehAaJLY.js → LpPagination-BFl0I7tL.js} +1 -1
  45. package/dist/chunks/{LpPasswordInput-BK25_vNG.js → LpPasswordInput-C1G4k_r0.js} +2 -2
  46. package/dist/chunks/{LpPhoneInput-Bxg7a_qD.js → LpPhoneInput-CZrpVxla.js} +2 -2
  47. package/dist/chunks/{LpPie-Coa2GMHt.js → LpPie-BD5Lsh-2.js} +2 -2
  48. package/dist/chunks/{LpRangeCalendar-D5sDID9W.js → LpRangeCalendar-COeOYF52.js} +1 -1
  49. package/dist/chunks/{LpSection-B19VPYmr.js → LpSection-BAkbf0OK.js} +1 -1
  50. package/dist/chunks/{LpSegmented-DbrUjuSA.js → LpSegmented-DslFku0N.js} +1 -1
  51. package/dist/chunks/{LpSelect-DynjWK1A.js → LpSelect-C4OXN_q3.js} +1 -1
  52. package/dist/chunks/{LpSidebar-CKamWtPo.js → LpSidebar-B3E_iViL.js} +3 -3
  53. package/dist/chunks/{LpSidebarNav-Y4LV0ZEn.js → LpSidebarNav-32sAXNM-.js} +2 -2
  54. package/dist/chunks/{LpStat-BS2TEXYK.js → LpStat-oYk6V1LZ.js} +1 -1
  55. package/dist/chunks/{LpStepper-BSglWF45.js → LpStepper-YgHGzgfD.js} +1 -1
  56. package/dist/chunks/{LpTableFilter-CwHXVxJt.js → LpTableFilter-Ba-rS4H1.js} +2 -2
  57. package/dist/chunks/{LpTabs-D01b8jBI.js → LpTabs-00v3VQx4.js} +1 -1
  58. package/dist/chunks/{LpTagsInput-CHbQoAAA.js → LpTagsInput-Sc56iy_j.js} +3 -3
  59. package/dist/chunks/{LpTextarea-Bz2IWhTH.js → LpTextarea-CQZccQI3.js} +1 -1
  60. package/dist/chunks/{LpThemeSwitcher-CbzL6ipO.js → LpThemeSwitcher-CeBG0e_D.js} +2 -2
  61. package/dist/chunks/{LpTimeField-DvGXgdES.js → LpTimeField-BTEt0kvL.js} +1 -1
  62. package/dist/chunks/{LpToaster-C9EacEfR.js → LpToaster-BcKs7vX7.js} +1 -1
  63. package/dist/chunks/{LpTour-D7m9ZxNk.js → LpTour-C29-1wha.js} +4 -1
  64. package/dist/chunks/{MenuTitle-B9HdaBwE.js → MenuTitle-FeC6I24N.js} +1 -1
  65. package/dist/chunks/{TourCard-DCHOjr6e.js → TourCard-AjN0uhs1.js} +2 -2
  66. package/dist/chunks/{icons-QqBscG5I.js → icons-CuO3W46H.js} +1 -1
  67. package/dist/components/ContextMenuItems.vue.js +1 -1
  68. package/dist/components/LayoutCanvas.vue.js +1 -1
  69. package/dist/components/LayoutNode.vue.js +1 -1
  70. package/dist/components/LpActionBar.vue.js +1 -1
  71. package/dist/components/LpAddressInput.vue.js +1 -1
  72. package/dist/components/LpAlert.vue.js +1 -1
  73. package/dist/components/LpAppShell.vue.js +1 -1
  74. package/dist/components/LpAutocomplete.vue.js +1 -1
  75. package/dist/components/LpAvatar.vue.js +1 -1
  76. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  77. package/dist/components/LpButton.vue.js +1 -1
  78. package/dist/components/LpCalendar.vue.js +1 -1
  79. package/dist/components/LpCard.vue.js +1 -1
  80. package/dist/components/LpChart.vue.js +2 -2
  81. package/dist/components/LpCheckbox.vue.js +1 -1
  82. package/dist/components/LpCodeBlock.vue.js +1 -1
  83. package/dist/components/LpColorPicker.vue.js +1 -1
  84. package/dist/components/LpCommandPalette.vue.js +30 -19
  85. package/dist/components/LpConfirmDialog.vue.js +1 -1
  86. package/dist/components/LpConfirmHost.vue.js +1 -1
  87. package/dist/components/LpContextMenu.vue.d.ts +7 -2
  88. package/dist/components/LpContextMenu.vue.js +1 -1
  89. package/dist/components/LpDatePicker.vue.js +1 -1
  90. package/dist/components/LpDateRangePicker.vue.js +1 -1
  91. package/dist/components/LpDisclosure.vue.js +1 -1
  92. package/dist/components/LpDrawer.vue.js +1 -1
  93. package/dist/components/LpDropdownMenu.vue.d.ts +7 -2
  94. package/dist/components/LpDropdownMenu.vue.js +1 -1
  95. package/dist/components/LpDropzone.vue.js +1 -1
  96. package/dist/components/LpEmptyState.vue.js +1 -1
  97. package/dist/components/LpFieldNotice.vue.js +1 -1
  98. package/dist/components/LpFileTree.vue.js +1 -1
  99. package/dist/components/LpFileTreeNode.vue.js +1 -1
  100. package/dist/components/LpFormField.vue.js +1 -1
  101. package/dist/components/LpHintLayer.vue.js +1 -1
  102. package/dist/components/LpHints.vue.js +1 -1
  103. package/dist/components/LpIcon.vue.js +1 -1
  104. package/dist/components/LpImageEditor.vue.js +4 -2
  105. package/dist/components/LpInput.vue.js +1 -1
  106. package/dist/components/LpLightbox.vue.js +1 -1
  107. package/dist/components/LpLogViewer.vue.js +1 -1
  108. package/dist/components/LpMapPicker.vue.js +1 -1
  109. package/dist/components/LpMediaGallery.vue.js +1 -1
  110. package/dist/components/LpModal.vue.js +1 -1
  111. package/dist/components/LpModalNav.vue.js +1 -1
  112. package/dist/components/LpNotificationBell.vue.js +1 -1
  113. package/dist/components/LpNumberField.vue.js +1 -1
  114. package/dist/components/LpPagination.vue.js +1 -1
  115. package/dist/components/LpPaletteFacts.vue.js +1 -1
  116. package/dist/components/LpPaletteHeader.vue.js +2 -2
  117. package/dist/components/LpPasswordInput.vue.js +1 -1
  118. package/dist/components/LpPhoneInput.vue.js +1 -1
  119. package/dist/components/LpPie.vue.js +1 -1
  120. package/dist/components/LpRangeCalendar.vue.js +1 -1
  121. package/dist/components/LpSection.vue.js +1 -1
  122. package/dist/components/LpSegmented.vue.js +1 -1
  123. package/dist/components/LpSelect.vue.js +1 -1
  124. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  125. package/dist/components/LpSidebar.vue.js +1 -1
  126. package/dist/components/LpSidebarNav.vue.js +1 -1
  127. package/dist/components/LpStat.vue.js +1 -1
  128. package/dist/components/LpStepper.vue.js +1 -1
  129. package/dist/components/LpTable.vue.js +11 -10
  130. package/dist/components/LpTableFilter.vue.js +1 -1
  131. package/dist/components/LpTabs.vue.js +1 -1
  132. package/dist/components/LpTagsInput.vue.js +1 -1
  133. package/dist/components/LpTextarea.vue.js +1 -1
  134. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  135. package/dist/components/LpTimeField.vue.js +1 -1
  136. package/dist/components/LpToaster.vue.js +1 -1
  137. package/dist/components/LpTour.vue.js +1 -1
  138. package/dist/components/MenuTitle.vue.js +1 -1
  139. package/dist/components/TourCard.vue.js +1 -1
  140. package/dist/composables/useHintSystem.d.ts +65 -0
  141. package/dist/composables/useHintSystem.js +98 -12
  142. package/dist/icons-all.js +1 -1
  143. package/dist/index.d.ts +2 -2
  144. package/dist/index.js +62 -58
  145. package/package.json +1 -1
  146. package/src/components/LpCommandPalette.vue +26 -4
  147. package/src/components/LpContextMenu.vue +19 -1
  148. package/src/components/LpDropdownMenu.vue +13 -2
  149. package/src/components/LpHints.vue +7 -1
  150. package/src/components/LpTable.vue +1 -1
  151. package/src/components/LpTour.vue +3 -0
  152. package/src/composables/useHintSystem.ts +130 -12
  153. package/src/index.ts +2 -1
  154. package/src/kit-icons.ts +1 -1
@@ -1,24 +1,24 @@
1
1
  import { defineComponent, computed, useAttrs, ref, shallowRef, watch, onMounted, onBeforeUnmount, openBlock, createElementBlock, normalizeClass, createVNode, withCtx, createTextVNode, toDisplayString, createCommentVNode, Fragment, renderList, createElementVNode, Transition, renderSlot, mergeProps, normalizeStyle, createBlock, TransitionGroup, unref, withModifiers, nextTick } from "vue";
2
- import { _ as _sfc_main$7 } from "../chunks/LpCheckbox-B_C8sOoT.js";
3
- import { _ as _sfc_main$6 } from "../chunks/LpContextMenu-DRFd-iyc.js";
4
- import { _ as _sfc_main$2 } from "../chunks/LpIcon-B5guGKrW.js";
5
- import { _ as _sfc_main$a } from "../chunks/LpPagination-DehAaJLY.js";
2
+ import { _ as _sfc_main$7 } from "../chunks/LpCheckbox-DV9W6T3H.js";
3
+ import { _ as _sfc_main$6 } from "../chunks/LpContextMenu-BnN1k7ga.js";
4
+ import { _ as _sfc_main$2 } from "../chunks/LpIcon-CTuDVTYv.js";
5
+ import { _ as _sfc_main$a } from "../chunks/LpPagination-BFl0I7tL.js";
6
6
  import { _ as _sfc_main$8 } from "../chunks/LpPopover-DCKeqiVn.js";
7
7
  import { _ as _sfc_main$5 } from "../chunks/LpScrollArea-Hz3-JWUG.js";
8
8
  import { _ as _sfc_main$4 } from "../chunks/LpRollingText-DB7upf-5.js";
9
9
  import { _ as _sfc_main$3 } from "../chunks/LpShift-DXNsauQZ.js";
10
- import { _ as _sfc_main$9 } from "../chunks/LpTableFilter-CwHXVxJt.js";
10
+ import { _ as _sfc_main$9 } from "../chunks/LpTableFilter-Ba-rS4H1.js";
11
11
  import { useAsyncTask } from "../composables/useAsyncTask.js";
12
12
  import { useHotkeys } from "../composables/useHotkeys.js";
13
13
  import { usePaintSelect } from "../composables/usePaintSelect.js";
14
14
  import { useRovingFocus } from "../composables/useRovingFocus.js";
15
15
  import { useLabels } from "../composables/useLpConfig.js";
16
16
  import { compareValues } from "./tableSort.js";
17
- import { _ as _sfc_main$1 } from "../chunks/LpButton-vhlwmpBy.js";
17
+ import { _ as _sfc_main$1 } from "../chunks/LpButton-CJSD7N0Z.js";
18
18
  import { toCsv, downloadFile, fileStem } from "./exportData.js";
19
19
  import { summarizeShown, parseTableState, serializeTableState, countValues } from "./tableFilter.js";
20
20
  import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper-1tPrXgE0.js";
21
- import '../assets/LpTable-B_QCQCbB.css';const _hoisted_1 = {
21
+ import '../assets/LpTable-BZZf_rrt.css';const _hoisted_1 = {
22
22
  key: 0,
23
23
  class: "flex justify-end"
24
24
  };
@@ -760,7 +760,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
760
760
  default: withCtx(() => [
761
761
  createVNode(_sfc_main$6, {
762
762
  items: contextMenu.value,
763
- always: ""
763
+ always: "",
764
+ "no-hint": !__props.rowMenu
764
765
  }, {
765
766
  default: withCtx(() => [
766
767
  createElementVNode("table", {
@@ -940,7 +941,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
940
941
  ], 512)
941
942
  ]),
942
943
  _: 3
943
- }, 8, ["items"])
944
+ }, 8, ["items", "no-hint"])
944
945
  ]),
945
946
  _: 3
946
947
  }, 16, ["style", "bar-inset-top"]),
@@ -956,7 +957,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
956
957
  };
957
958
  }
958
959
  });
959
- const LpTable = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-344d1bc2"]]);
960
+ const LpTable = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-1d2375a8"]]);
960
961
  export {
961
962
  LpTable as default
962
963
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpTableFilter-CwHXVxJt.js";
1
+ import { _ as _sfc_main } from "../chunks/LpTableFilter-Ba-rS4H1.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpTabs-D01b8jBI.js";
1
+ import { _ as _sfc_main } from "../chunks/LpTabs-00v3VQx4.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpTagsInput-CHbQoAAA.js";
1
+ import { _ as _sfc_main } from "../chunks/LpTagsInput-Sc56iy_j.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpTextarea-Bz2IWhTH.js";
1
+ import { _ as _sfc_main } from "../chunks/LpTextarea-CQZccQI3.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpThemeSwitcher-CbzL6ipO.js";
1
+ import { _ as _sfc_main } from "../chunks/LpThemeSwitcher-CeBG0e_D.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpTimeField-DvGXgdES.js";
1
+ import { _ as _sfc_main } from "../chunks/LpTimeField-BTEt0kvL.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpToaster-C9EacEfR.js";
1
+ import { _ as _sfc_main } from "../chunks/LpToaster-BcKs7vX7.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpTour-D7m9ZxNk.js";
1
+ import { _ as _sfc_main } from "../chunks/LpTour-C29-1wha.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/MenuTitle-B9HdaBwE.js";
1
+ import { _ as _sfc_main } from "../chunks/MenuTitle-FeC6I24N.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/TourCard-DCHOjr6e.js";
1
+ import { _ as _sfc_main } from "../chunks/TourCard-AjN0uhs1.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -44,6 +44,43 @@ export interface HintNudge {
44
44
  feature: string;
45
45
  text: string;
46
46
  }
47
+ /**
48
+ * A better way to do something the user keeps doing the slow way: shown now
49
+ * and then (at most `max` times, `nudgeAgain` apart) and never again once the
50
+ * better way is used. `when` reads usage counters — kit components report
51
+ * their own (see HINT_SIGNALS), and `hints.use(name)` adds any of the app's.
52
+ */
53
+ export interface HintTip {
54
+ id: string;
55
+ title: string;
56
+ text: string;
57
+ keys?: string;
58
+ max?: number;
59
+ when: (count: (signal: string) => number) => boolean;
60
+ /** What "show me" lights up on the current screen; without it the tip only informs. */
61
+ step?: () => TourStep | null;
62
+ }
63
+ /** Usage the kit reports by itself. */
64
+ export declare const HINT_SIGNALS: {
65
+ /** A context menu was opened (right click or long press). */
66
+ readonly contextMenu: "lp.context-menu";
67
+ /** A "…" menu marked `rightClickToo` was opened: its items were one right click away. */
68
+ readonly menuButton: "lp.menu-button";
69
+ /** A left click on something that also has a context menu. */
70
+ readonly contextTarget: "lp.context-target";
71
+ /** The command palette was opened. */
72
+ readonly palette: "lp.palette";
73
+ /** The current hint page changed: a navigation. */
74
+ readonly navigate: "lp.navigate";
75
+ /** An item's actions were opened in the palette (Tab). */
76
+ readonly paletteActions: "lp.palette-actions";
77
+ };
78
+ /** Right click instead of the "…" button. */
79
+ export declare function contextMenuTip(text?: Partial<Pick<HintTip, "title" | "text"> & {
80
+ stepText: string;
81
+ }>): HintTip;
82
+ /** The palette instead of walking the menu. */
83
+ export declare function paletteTip(keys?: string, text?: Partial<Pick<HintTip, "title" | "text">>): HintTip;
47
84
  export type HintLevel = "seen" | "explained" | "used";
48
85
  export interface HintRecord {
49
86
  state: HintLevel;
@@ -76,6 +113,7 @@ export interface HintSystemOptions {
76
113
  features: Record<string, HintFeature>;
77
114
  pages?: Record<string, HintPage>;
78
115
  news?: HintNews[];
116
+ tips?: HintTip[];
79
117
  storage?: HintStorage;
80
118
  /** The current page id, read reactively (map your route to it). */
81
119
  page: () => string;
@@ -93,6 +131,10 @@ export type HintOffer = {
93
131
  kind: "nudge";
94
132
  page: string;
95
133
  nudge: HintNudge;
134
+ } | {
135
+ kind: "tip";
136
+ page: string;
137
+ tip: HintTip;
96
138
  };
97
139
  /** Records in localStorage: for anonymous sessions and apps without a server. */
98
140
  export declare function localHintStorage(key?: string): HintStorage;
@@ -124,6 +166,7 @@ export declare function createHintSystem(options: HintSystemOptions): {
124
166
  }> & Omit<Map<string, HintRecord>, keyof Map<any, any>>;
125
167
  loaded: boolean;
126
168
  page: string;
169
+ overlay: string | null;
127
170
  tour: {
128
171
  open: boolean;
129
172
  step: number;
@@ -161,6 +204,18 @@ export declare function createHintSystem(options: HintSystemOptions): {
161
204
  feature: string;
162
205
  text: string;
163
206
  };
207
+ } | {
208
+ kind: "tip";
209
+ page: string;
210
+ tip: {
211
+ id: string;
212
+ title: string;
213
+ text: string;
214
+ keys?: string | undefined;
215
+ max?: number | undefined;
216
+ when: (count: (signal: string) => number) => boolean;
217
+ step?: (() => TourStep | null) | undefined;
218
+ };
164
219
  } | null;
165
220
  candidate: {
166
221
  id: string;
@@ -180,6 +235,14 @@ export declare function createHintSystem(options: HintSystemOptions): {
180
235
  load(): Promise<void>;
181
236
  /** Ask for a nudge; it shows when the budget and the page allow. */
182
237
  nudge(n: HintNudge): void;
238
+ /**
239
+ * A dialog acts as its own page while open (its dots and tour), then hands
240
+ * back. Pass null on close, and on unmount: a dialog left open by a route
241
+ * change would otherwise keep the page.
242
+ */
243
+ overlay(page: string | null): void;
244
+ /** How many times a signal was reported (for an app's own tips or reports). */
245
+ count: (name: string) => number;
183
246
  /** The user navigated on purpose (palette, notification): do not interrupt this arrival. */
184
247
  markIntent(): void;
185
248
  unreadNews: (page?: string) => HintNews[];
@@ -193,3 +256,5 @@ export declare function createHintSystem(options: HintSystemOptions): {
193
256
  export type HintSystem = ReturnType<typeof createHintSystem>;
194
257
  export declare function provideHintSystem(system: HintSystem): void;
195
258
  export declare function useHintSystem(): HintSystem | null;
259
+ /** The mounted host's system, read reactively from anywhere. */
260
+ export declare function runningHintSystem(): HintSystem | null;
@@ -1,6 +1,44 @@
1
- import { provide, reactive, computed, inject, watch } from "vue";
1
+ import { shallowRef, provide, onBeforeUnmount, reactive, computed, inject, watch } from "vue";
2
2
  import { anyModalOpen } from "../components/modalDepth.js";
3
3
  import { hints } from "./useHints.js";
4
+ const HINT_SIGNALS = {
5
+ /** A context menu was opened (right click or long press). */
6
+ contextMenu: "lp.context-menu",
7
+ /** A "…" menu marked `rightClickToo` was opened: its items were one right click away. */
8
+ menuButton: "lp.menu-button",
9
+ /** A left click on something that also has a context menu. */
10
+ contextTarget: "lp.context-target",
11
+ /** The command palette was opened. */
12
+ palette: "lp.palette",
13
+ /** The current hint page changed: a navigation. */
14
+ navigate: "lp.navigate",
15
+ /** An item's actions were opened in the palette (Tab). */
16
+ paletteActions: "lp.palette-actions"
17
+ };
18
+ function contextMenuTip(text = {}) {
19
+ return {
20
+ id: "lp.tip.context-menu",
21
+ title: text.title ?? "Right-click works here",
22
+ text: text.text ?? "Rows and cards open their actions on right-click, even where no … button shows it.",
23
+ when: (count) => count(HINT_SIGNALS.contextMenu) === 0 && (count(HINT_SIGNALS.menuButton) >= 5 || count(HINT_SIGNALS.contextTarget) >= 25),
24
+ step: () => {
25
+ const target = [...document.querySelectorAll("[data-lp-context-menu]")].find((el) => {
26
+ const box = el.getBoundingClientRect();
27
+ return box.width > 0 && box.bottom > 0 && box.top < window.innerHeight;
28
+ });
29
+ return target ? { target, title: text.title ?? "Right-click works here", text: text.stepText ?? "Right-click this to see what it can do.", try: true } : null;
30
+ }
31
+ };
32
+ }
33
+ function paletteTip(keys = "Ctrl+K", text = {}) {
34
+ return {
35
+ id: "lp.tip.palette",
36
+ title: text.title ?? "Jump anywhere",
37
+ text: text.text ?? "Search pages, people and settings from anywhere instead of the menu.",
38
+ keys,
39
+ when: (count) => count(HINT_SIGNALS.navigate) >= 15 && count(HINT_SIGNALS.palette) === 0
40
+ };
41
+ }
4
42
  const RANK = { seen: 0, explained: 1, used: 2 };
5
43
  const DAY = 24 * 3600 * 1e3;
6
44
  const DEFAULT_TIMING = {
@@ -69,12 +107,15 @@ function createHintSystem(options) {
69
107
  const features = options.features;
70
108
  const pages = options.pages ?? {};
71
109
  const news = options.news ?? [];
110
+ const tips = options.tips ?? [];
111
+ const TIP_MAX = 3;
72
112
  const storage = options.storage ?? localHintStorage();
73
113
  const sessionKey = options.sessionKey ?? "lp-hints:interrupted";
74
114
  const state = reactive({
75
115
  records: /* @__PURE__ */ new Map(),
76
116
  loaded: false,
77
117
  page: "",
118
+ overlay: null,
78
119
  tour: { open: false, step: 0, steps: [], ids: [], page: "" },
79
120
  offer: null,
80
121
  candidate: null,
@@ -87,6 +128,9 @@ function createHintSystem(options) {
87
128
  const pageKey = hintKey.page;
88
129
  const newsKey = hintKey.news;
89
130
  const nudgeKey = hintKey.nudge;
131
+ const signalKey = (name) => `u:${name}`;
132
+ const tipKey = (id) => `p:${id}`;
133
+ const count = (name) => state.records.get(signalKey(name))?.count ?? 0;
90
134
  function interrupted() {
91
135
  try {
92
136
  return sessionStorage.getItem(sessionKey) === "1";
@@ -213,21 +257,35 @@ function createHintSystem(options) {
213
257
  return;
214
258
  }
215
259
  const n = state.candidate;
216
- if (!n || n.page !== page) return;
217
- const seen = state.records.get(nudgeKey(n.id));
218
- if (seen?.dismissed || state.records.get(featureKey(n.feature))?.state === "used" || !hints.present(n.feature)) return;
219
- if (seen && Date.now() - Date.parse(seen.updatedAt) < timing.nudgeAgain) return;
220
- state.candidate = null;
221
- spend();
222
- record(nudgeKey(n.id), { add: 1 });
223
- state.offer = { kind: "nudge", page, nudge: n };
260
+ if (n && n.page === page) {
261
+ const seen = state.records.get(nudgeKey(n.id));
262
+ const f = features[n.feature];
263
+ const visible = !!f && (!!f.target || !!f.enter || hints.present(n.feature));
264
+ if (!seen?.dismissed && state.records.get(featureKey(n.feature))?.state !== "used" && visible && !(seen && Date.now() - Date.parse(seen.updatedAt) < timing.nudgeAgain)) {
265
+ state.candidate = null;
266
+ spend();
267
+ record(nudgeKey(n.id), { add: 1 });
268
+ state.offer = { kind: "nudge", page, nudge: n };
269
+ return;
270
+ }
271
+ }
272
+ for (const tip of tips) {
273
+ const seen = state.records.get(tipKey(tip.id));
274
+ if (seen?.dismissed || (seen?.count ?? 0) >= (tip.max ?? TIP_MAX)) continue;
275
+ if (seen && Date.now() - Date.parse(seen.updatedAt) < timing.nudgeAgain) continue;
276
+ if (!tip.when(count)) continue;
277
+ spend();
278
+ state.offer = { kind: "tip", page, tip };
279
+ return;
280
+ }
224
281
  }
225
282
  let stops = [];
226
283
  function start() {
227
284
  if (stops.length) return;
228
285
  const stopPage = watch(
229
- options.page,
230
- (page) => {
286
+ () => state.overlay ?? options.page(),
287
+ (page, previous) => {
288
+ if (previous !== void 0 && page !== previous && !state.overlay) record(signalKey(HINT_SIGNALS.navigate), { add: 1 });
231
289
  state.page = page;
232
290
  state.settledAt = Date.now();
233
291
  if (state.offer && state.offer.page !== page) state.offer = null;
@@ -249,6 +307,7 @@ function createHintSystem(options) {
249
307
  stopPage,
250
308
  hints.on("used", (id) => {
251
309
  if (features[id]) record(featureKey(id), { state: "used", add: 1 });
310
+ if (id.startsWith("lp.") || !features[id]) record(signalKey(id), { add: 1 });
252
311
  }),
253
312
  () => clearInterval(poll),
254
313
  () => window.removeEventListener("pagehide", flushOnLeave)
@@ -279,6 +338,16 @@ function createHintSystem(options) {
279
338
  nudge(n) {
280
339
  state.candidate = { ...n, page: state.page };
281
340
  },
341
+ /**
342
+ * A dialog acts as its own page while open (its dots and tour), then hands
343
+ * back. Pass null on close, and on unmount: a dialog left open by a route
344
+ * change would otherwise keep the page.
345
+ */
346
+ overlay(page) {
347
+ state.overlay = page;
348
+ },
349
+ /** How many times a signal was reported (for an app's own tips or reports). */
350
+ count,
282
351
  /** The user navigated on purpose (palette, notification): do not interrupt this arrival. */
283
352
  markIntent() {
284
353
  state.intent = true;
@@ -294,6 +363,7 @@ function createHintSystem(options) {
294
363
  if (id) record(featureKey(id), { state: "explained" });
295
364
  },
296
365
  tourEnded(finished) {
366
+ if (!state.tour.ids.length) return;
297
367
  record(pageKey(state.tour.page), finished ? { state: "explained" } : { add: 1 });
298
368
  baseline(state.tour.page);
299
369
  },
@@ -305,6 +375,10 @@ function createHintSystem(options) {
305
375
  const ids = offer.items.map((n) => n.feature).filter((id) => !!id);
306
376
  readNews(offer.page);
307
377
  if (choice === "show" && ids.length) startTour(offer.page, ids);
378
+ } else if (offer.kind === "tip") {
379
+ record(tipKey(offer.tip.id), { add: 1, dismissed: choice === "never" });
380
+ const step = choice === "show" ? offer.tip.step?.() : null;
381
+ if (step) Object.assign(state.tour, { open: true, step: 0, page: offer.page, ids: [], steps: [step] });
308
382
  } else if (offer.kind === "nudge") {
309
383
  if (choice === "show") startTour(features[offer.nudge.feature].page, [offer.nudge.feature]);
310
384
  else record(nudgeKey(offer.nudge.id), { dismissed: true });
@@ -318,17 +392,29 @@ function createHintSystem(options) {
318
392
  };
319
393
  }
320
394
  const HINT_SYSTEM = /* @__PURE__ */ Symbol.for("lp-hint-system");
395
+ const running = shallowRef(null);
321
396
  function provideHintSystem(system) {
322
397
  provide(HINT_SYSTEM, system);
398
+ running.value = system;
399
+ onBeforeUnmount(() => {
400
+ if (running.value === system) running.value = null;
401
+ });
323
402
  }
324
403
  function useHintSystem() {
325
- return inject(HINT_SYSTEM, null);
404
+ return inject(HINT_SYSTEM, null) ?? running.value;
405
+ }
406
+ function runningHintSystem() {
407
+ return running.value;
326
408
  }
327
409
  export {
410
+ HINT_SIGNALS,
411
+ contextMenuTip,
328
412
  createHintSystem,
329
413
  hintKey,
330
414
  hintSummary,
331
415
  localHintStorage,
416
+ paletteTip,
332
417
  provideHintSystem,
418
+ runningHintSystem,
333
419
  useHintSystem
334
420
  };
package/dist/icons-all.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import lucide from "@iconify-json/lucide/icons.json";
2
- import { a as registerIconCollection } from "./chunks/icons-QqBscG5I.js";
2
+ import { a as registerIconCollection } from "./chunks/icons-CuO3W46H.js";
3
3
  registerIconCollection(lucide);
package/dist/index.d.ts CHANGED
@@ -162,8 +162,8 @@ export type { TourContext, TourStep } from "./components/LpTour.vue";
162
162
  export { holeOf, openContextMenu, panelsAround } from "./components/tour";
163
163
  export { default as LpHintLayer } from "./components/LpHintLayer.vue";
164
164
  export { default as LpHints } from "./components/LpHints.vue";
165
- export { createHintSystem, hintKey, hintSummary, localHintStorage, provideHintSystem, useHintSystem } from "./composables/useHintSystem";
166
- export type { HintDelta, HintFeature, HintLevel, HintNews, HintNudge, HintOffer, HintPage, HintRecord, HintStorage, HintSummary, HintSystem, HintSystemOptions, HintTiming, } from "./composables/useHintSystem";
165
+ export { HINT_SIGNALS, contextMenuTip, createHintSystem, hintKey, hintSummary, localHintStorage, paletteTip, provideHintSystem, runningHintSystem, useHintSystem } from "./composables/useHintSystem";
166
+ export type { HintDelta, HintFeature, HintLevel, HintNews, HintNudge, HintOffer, HintPage, HintRecord, HintStorage, HintSummary, HintSystem, HintTip, HintSystemOptions, HintTiming, } from "./composables/useHintSystem";
167
167
  export type { HintNote } from "./components/LpHintLayer.vue";
168
168
  export { default as LpTooltipProvider } from "./components/LpTooltipProvider.vue";
169
169
  export { default as LpTopologyCanvas } from "./components/LpTopologyCanvas.vue";