@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.
- package/dist/assets/{LpCommandPalette-BM_IyzwB.css → LpCommandPalette-DA5pmuPi.css} +21 -21
- package/dist/assets/{LpTable-B_QCQCbB.css → LpTable-BZZf_rrt.css} +19 -19
- package/dist/chunks/{ContextMenuItems-CioDScj3.js → ContextMenuItems-qXReFtQW.js} +1 -1
- package/dist/chunks/{LayoutCanvas-BcGLJVBq.js → LayoutCanvas-t7LWFCEn.js} +1 -1
- package/dist/chunks/{LayoutNode-BkBn6dvM.js → LayoutNode-DHsE6GwM.js} +1 -1
- package/dist/chunks/{LpActionBar-DCN-_pZP.js → LpActionBar-BsSp66S_.js} +2 -2
- package/dist/chunks/{LpAddressInput-D-H94m4q.js → LpAddressInput-DD4zTN4P.js} +7 -7
- package/dist/chunks/{LpAlert-CXMn1GYE.js → LpAlert--KLL4NLk.js} +1 -1
- package/dist/chunks/{LpAppShell-BeMuKEjh.js → LpAppShell-Cv-Y9qNA.js} +3 -3
- package/dist/chunks/{LpAutocomplete-hJ_6CHlh.js → LpAutocomplete-PnL2ntKl.js} +1 -1
- package/dist/chunks/{LpAvatar-CeW4Z5CL.js → LpAvatar-CwGs1JCQ.js} +2 -2
- package/dist/chunks/{LpBreadcrumbs-BLzOEgAF.js → LpBreadcrumbs-CndzPYiG.js} +1 -1
- package/dist/chunks/{LpButton-vhlwmpBy.js → LpButton-CJSD7N0Z.js} +1 -1
- package/dist/chunks/{LpCalendar-BLoE8Qm7.js → LpCalendar-CXVDbb2M.js} +1 -1
- package/dist/chunks/{LpCard-Gbr8a1xK.js → LpCard-B2D0GIUU.js} +1 -1
- package/dist/chunks/{LpCheckbox-B_C8sOoT.js → LpCheckbox-DV9W6T3H.js} +1 -1
- package/dist/chunks/{LpCodeBlock-D6zhp30a.js → LpCodeBlock-t6MLA3fb.js} +1 -1
- package/dist/chunks/{LpColorPicker-CVXwjEtX.js → LpColorPicker-CvBF8TeL.js} +2 -2
- package/dist/chunks/{LpConfirmDialog-DkgIT-Xg.js → LpConfirmDialog-tkgyY3eu.js} +3 -3
- package/dist/chunks/{LpConfirmHost-CYzXWFOI.js → LpConfirmHost-CoYIcUdl.js} +1 -1
- package/dist/chunks/{LpContextMenu-DRFd-iyc.js → LpContextMenu-BnN1k7ga.js} +17 -5
- package/dist/chunks/{LpDatePicker-B-VMHMgy.js → LpDatePicker-DxdrVNCG.js} +3 -3
- package/dist/chunks/{LpDateRangePicker-B68KPKPl.js → LpDateRangePicker-DjeaqikC.js} +2 -2
- package/dist/chunks/{LpDisclosure-Ct-VBHxt.js → LpDisclosure-s8cQ7KQq.js} +1 -1
- package/dist/chunks/{LpDrawer-Rc6eAJrr.js → LpDrawer-C97yoWmh.js} +1 -1
- package/dist/chunks/{LpDropdownMenu-BoJQsjzt.js → LpDropdownMenu-CbyYu4Rw.js} +11 -4
- package/dist/chunks/{LpEmptyState-CBwwkkdA.js → LpEmptyState-CX8fdGSU.js} +1 -1
- package/dist/chunks/{LpFieldNotice-9hH4ITZa.js → LpFieldNotice-B--RzKfj.js} +1 -1
- package/dist/chunks/{LpFileTree-Bs57DhVa.js → LpFileTree-DEqh2ySW.js} +2 -2
- package/dist/chunks/{LpFileTreeNode-XgJW65v5.js → LpFileTreeNode-DCZA7sQ-.js} +3 -3
- package/dist/chunks/{LpFormField-BpQ6WJPe.js → LpFormField-DMPPL1jF.js} +1 -1
- package/dist/chunks/{LpHintLayer-B5-6FyEf.js → LpHintLayer-DsclGYcD.js} +1 -1
- package/dist/chunks/{LpHints-BqoZXHZk.js → LpHints-BTpvisgP.js} +10 -4
- package/dist/chunks/{LpIcon-B5guGKrW.js → LpIcon-CTuDVTYv.js} +1 -1
- package/dist/chunks/{LpInput-WvyP02ID.js → LpInput-C7FHxzj2.js} +2 -2
- package/dist/chunks/{LpLightbox-Dq-e36uT.js → LpLightbox-DiksFa4L.js} +1 -1
- package/dist/chunks/{LpLogViewer-B92bAftG.js → LpLogViewer-BuPe23sZ.js} +2 -2
- package/dist/chunks/{LpMapPicker-BH5csaBt.js → LpMapPicker-DybIlWnF.js} +1 -1
- package/dist/chunks/{LpMediaGallery-B1kDypJ-.js → LpMediaGallery-Cic9UHsa.js} +2 -2
- package/dist/chunks/{LpModal-DvGD6kEe.js → LpModal-QFfctZsj.js} +1 -1
- package/dist/chunks/{LpModalNav-B-_zRTS-.js → LpModalNav-Cw7m-eks.js} +4 -4
- package/dist/chunks/{LpNotificationBell-63pvatBj.js → LpNotificationBell-xH_JphpS.js} +4 -4
- package/dist/chunks/{LpNumberField-CJPjmoDz.js → LpNumberField-BFSRVGkJ.js} +1 -1
- package/dist/chunks/{LpPagination-DehAaJLY.js → LpPagination-BFl0I7tL.js} +1 -1
- package/dist/chunks/{LpPasswordInput-BK25_vNG.js → LpPasswordInput-C1G4k_r0.js} +2 -2
- package/dist/chunks/{LpPhoneInput-Bxg7a_qD.js → LpPhoneInput-CZrpVxla.js} +2 -2
- package/dist/chunks/{LpPie-Coa2GMHt.js → LpPie-BD5Lsh-2.js} +2 -2
- package/dist/chunks/{LpRangeCalendar-D5sDID9W.js → LpRangeCalendar-COeOYF52.js} +1 -1
- package/dist/chunks/{LpSection-B19VPYmr.js → LpSection-BAkbf0OK.js} +1 -1
- package/dist/chunks/{LpSegmented-DbrUjuSA.js → LpSegmented-DslFku0N.js} +1 -1
- package/dist/chunks/{LpSelect-DynjWK1A.js → LpSelect-C4OXN_q3.js} +1 -1
- package/dist/chunks/{LpSidebar-CKamWtPo.js → LpSidebar-B3E_iViL.js} +3 -3
- package/dist/chunks/{LpSidebarNav-Y4LV0ZEn.js → LpSidebarNav-32sAXNM-.js} +2 -2
- package/dist/chunks/{LpStat-BS2TEXYK.js → LpStat-oYk6V1LZ.js} +1 -1
- package/dist/chunks/{LpStepper-BSglWF45.js → LpStepper-YgHGzgfD.js} +1 -1
- package/dist/chunks/{LpTableFilter-CwHXVxJt.js → LpTableFilter-Ba-rS4H1.js} +2 -2
- package/dist/chunks/{LpTabs-D01b8jBI.js → LpTabs-00v3VQx4.js} +1 -1
- package/dist/chunks/{LpTagsInput-CHbQoAAA.js → LpTagsInput-Sc56iy_j.js} +3 -3
- package/dist/chunks/{LpTextarea-Bz2IWhTH.js → LpTextarea-CQZccQI3.js} +1 -1
- package/dist/chunks/{LpThemeSwitcher-CbzL6ipO.js → LpThemeSwitcher-CeBG0e_D.js} +2 -2
- package/dist/chunks/{LpTimeField-DvGXgdES.js → LpTimeField-BTEt0kvL.js} +1 -1
- package/dist/chunks/{LpToaster-C9EacEfR.js → LpToaster-BcKs7vX7.js} +1 -1
- package/dist/chunks/{LpTour-D7m9ZxNk.js → LpTour-C29-1wha.js} +4 -1
- package/dist/chunks/{MenuTitle-B9HdaBwE.js → MenuTitle-FeC6I24N.js} +1 -1
- package/dist/chunks/{TourCard-DCHOjr6e.js → TourCard-AjN0uhs1.js} +2 -2
- package/dist/chunks/{icons-QqBscG5I.js → icons-CuO3W46H.js} +1 -1
- package/dist/components/ContextMenuItems.vue.js +1 -1
- package/dist/components/LayoutCanvas.vue.js +1 -1
- package/dist/components/LayoutNode.vue.js +1 -1
- package/dist/components/LpActionBar.vue.js +1 -1
- package/dist/components/LpAddressInput.vue.js +1 -1
- package/dist/components/LpAlert.vue.js +1 -1
- package/dist/components/LpAppShell.vue.js +1 -1
- package/dist/components/LpAutocomplete.vue.js +1 -1
- package/dist/components/LpAvatar.vue.js +1 -1
- package/dist/components/LpBreadcrumbs.vue.js +1 -1
- package/dist/components/LpButton.vue.js +1 -1
- package/dist/components/LpCalendar.vue.js +1 -1
- package/dist/components/LpCard.vue.js +1 -1
- package/dist/components/LpChart.vue.js +2 -2
- package/dist/components/LpCheckbox.vue.js +1 -1
- package/dist/components/LpCodeBlock.vue.js +1 -1
- package/dist/components/LpColorPicker.vue.js +1 -1
- package/dist/components/LpCommandPalette.vue.js +30 -19
- package/dist/components/LpConfirmDialog.vue.js +1 -1
- package/dist/components/LpConfirmHost.vue.js +1 -1
- package/dist/components/LpContextMenu.vue.d.ts +7 -2
- package/dist/components/LpContextMenu.vue.js +1 -1
- package/dist/components/LpDatePicker.vue.js +1 -1
- package/dist/components/LpDateRangePicker.vue.js +1 -1
- package/dist/components/LpDisclosure.vue.js +1 -1
- package/dist/components/LpDrawer.vue.js +1 -1
- package/dist/components/LpDropdownMenu.vue.d.ts +7 -2
- package/dist/components/LpDropdownMenu.vue.js +1 -1
- package/dist/components/LpDropzone.vue.js +1 -1
- package/dist/components/LpEmptyState.vue.js +1 -1
- package/dist/components/LpFieldNotice.vue.js +1 -1
- package/dist/components/LpFileTree.vue.js +1 -1
- package/dist/components/LpFileTreeNode.vue.js +1 -1
- package/dist/components/LpFormField.vue.js +1 -1
- package/dist/components/LpHintLayer.vue.js +1 -1
- package/dist/components/LpHints.vue.js +1 -1
- package/dist/components/LpIcon.vue.js +1 -1
- package/dist/components/LpImageEditor.vue.js +4 -2
- package/dist/components/LpInput.vue.js +1 -1
- package/dist/components/LpLightbox.vue.js +1 -1
- package/dist/components/LpLogViewer.vue.js +1 -1
- package/dist/components/LpMapPicker.vue.js +1 -1
- package/dist/components/LpMediaGallery.vue.js +1 -1
- package/dist/components/LpModal.vue.js +1 -1
- package/dist/components/LpModalNav.vue.js +1 -1
- package/dist/components/LpNotificationBell.vue.js +1 -1
- package/dist/components/LpNumberField.vue.js +1 -1
- package/dist/components/LpPagination.vue.js +1 -1
- package/dist/components/LpPaletteFacts.vue.js +1 -1
- package/dist/components/LpPaletteHeader.vue.js +2 -2
- package/dist/components/LpPasswordInput.vue.js +1 -1
- package/dist/components/LpPhoneInput.vue.js +1 -1
- package/dist/components/LpPie.vue.js +1 -1
- package/dist/components/LpRangeCalendar.vue.js +1 -1
- package/dist/components/LpSection.vue.js +1 -1
- package/dist/components/LpSegmented.vue.js +1 -1
- package/dist/components/LpSelect.vue.js +1 -1
- package/dist/components/LpShortcutsDialog.vue.js +1 -1
- package/dist/components/LpSidebar.vue.js +1 -1
- package/dist/components/LpSidebarNav.vue.js +1 -1
- package/dist/components/LpStat.vue.js +1 -1
- package/dist/components/LpStepper.vue.js +1 -1
- package/dist/components/LpTable.vue.js +11 -10
- package/dist/components/LpTableFilter.vue.js +1 -1
- package/dist/components/LpTabs.vue.js +1 -1
- package/dist/components/LpTagsInput.vue.js +1 -1
- package/dist/components/LpTextarea.vue.js +1 -1
- package/dist/components/LpThemeSwitcher.vue.js +1 -1
- package/dist/components/LpTimeField.vue.js +1 -1
- package/dist/components/LpToaster.vue.js +1 -1
- package/dist/components/LpTour.vue.js +1 -1
- package/dist/components/MenuTitle.vue.js +1 -1
- package/dist/components/TourCard.vue.js +1 -1
- package/dist/composables/useHintSystem.d.ts +65 -0
- package/dist/composables/useHintSystem.js +98 -12
- package/dist/icons-all.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +62 -58
- package/package.json +1 -1
- package/src/components/LpCommandPalette.vue +26 -4
- package/src/components/LpContextMenu.vue +19 -1
- package/src/components/LpDropdownMenu.vue +13 -2
- package/src/components/LpHints.vue +7 -1
- package/src/components/LpTable.vue +1 -1
- package/src/components/LpTour.vue +3 -0
- package/src/composables/useHintSystem.ts +130 -12
- package/src/index.ts +2 -1
- 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-
|
|
3
|
-
import { _ as _sfc_main$6 } from "../chunks/LpContextMenu-
|
|
4
|
-
import { _ as _sfc_main$2 } from "../chunks/LpIcon-
|
|
5
|
-
import { _ as _sfc_main$a } from "../chunks/LpPagination-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
960
|
+
const LpTable = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-1d2375a8"]]);
|
|
960
961
|
export {
|
|
961
962
|
LpTable as default
|
|
962
963
|
};
|
|
@@ -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 (
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
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";
|