@leavepulse/ui 0.58.1 → 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-DmQUsJqA.css → LpCommandPalette-DA5pmuPi.css} +21 -21
- package/dist/assets/{LpTable-BNzavdlv.css → LpTable-BZZf_rrt.css} +19 -19
- package/dist/chunks/{ContextMenuItems-BY5sTVQF.js → ContextMenuItems-qXReFtQW.js} +2 -2
- 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-Dio6Sqed.js → LpAddressInput-DD4zTN4P.js} +7 -7
- package/dist/chunks/{LpAlert-CXMn1GYE.js → LpAlert--KLL4NLk.js} +1 -1
- package/dist/chunks/{LpAppShell-Be6T96td.js → LpAppShell-Cv-Y9qNA.js} +3 -3
- package/dist/chunks/{LpAutocomplete-hJ_6CHlh.js → LpAutocomplete-PnL2ntKl.js} +1 -1
- package/dist/chunks/{LpAvatar-BxNs23Xu.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-DhR7u0d8.js → LpCard-B2D0GIUU.js} +1 -1
- package/dist/chunks/{LpCheckbox-B_C8sOoT.js → LpCheckbox-DV9W6T3H.js} +1 -1
- package/dist/chunks/{LpCodeBlock-CXsqJwDy.js → LpCodeBlock-t6MLA3fb.js} +5 -5
- package/dist/chunks/{LpColorPicker-DQ88niXq.js → LpColorPicker-CvBF8TeL.js} +6 -6
- package/dist/chunks/{LpConfirmDialog-DxlSdjmk.js → LpConfirmDialog-tkgyY3eu.js} +3 -3
- package/dist/chunks/{LpConfirmHost-BcrmTNu_.js → LpConfirmHost-CoYIcUdl.js} +1 -1
- package/dist/chunks/{LpContextMenu-B1NGfpp1.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-DSknigxH.js → LpDrawer-C97yoWmh.js} +2 -2
- package/dist/chunks/{LpDropdownMenu-C7oHVlKY.js → LpDropdownMenu-CbyYu4Rw.js} +12 -5
- 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-CMA0_rsB.js → LpFileTree-DEqh2ySW.js} +2 -2
- package/dist/chunks/{LpFileTreeNode-B4T258hF.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-DwiYE32z.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-BxYssnXg.js → LpModal-QFfctZsj.js} +2 -2
- package/dist/chunks/{LpModalNav-Bn2ws64b.js → LpModalNav-Cw7m-eks.js} +4 -4
- package/dist/chunks/{LpNotificationBell-DJfs4JjQ.js → LpNotificationBell-xH_JphpS.js} +6 -6
- 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-Bg5uTZbx.js → LpPasswordInput-C1G4k_r0.js} +3 -3
- package/dist/chunks/{LpPhoneInput-DStwcbnQ.js → LpPhoneInput-CZrpVxla.js} +3 -3
- package/dist/chunks/{LpPie-DeTkbbOK.js → LpPie-BD5Lsh-2.js} +3 -3
- 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-D3Eam8sa.js → LpSegmented-DslFku0N.js} +3 -3
- package/dist/chunks/{LpSelect-DynjWK1A.js → LpSelect-C4OXN_q3.js} +1 -1
- package/dist/chunks/{LpSidebar-CshW0fqC.js → LpSidebar-B3E_iViL.js} +3 -3
- package/dist/chunks/{LpSidebarNav-C9b3i9G2.js → LpSidebarNav-32sAXNM-.js} +4 -4
- 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-BBGRHY38.js → LpTabs-00v3VQx4.js} +7 -6
- 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-B_qhSl7q.js → LpThemeSwitcher-CeBG0e_D.js} +2 -2
- package/dist/chunks/{LpTimeField-DvGXgdES.js → LpTimeField-BTEt0kvL.js} +1 -1
- package/dist/chunks/{LpToaster-Bo9Q4QBP.js → LpToaster-BcKs7vX7.js} +3 -3
- package/dist/chunks/{LpTour-D7m9ZxNk.js → LpTour-C29-1wha.js} +4 -1
- package/dist/chunks/{MenuTitle-DQP6hc2N.js → MenuTitle-FeC6I24N.js} +3 -3
- 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 +4 -4
- 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 +38 -27
- 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 +13 -12
- package/dist/components/LpTableFilter.vue.js +1 -1
- package/dist/components/LpTabs.vue.d.ts +7 -0
- 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/components/dropdown.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/ContextMenuItems.vue +1 -1
- package/src/components/LpChart.vue +1 -1
- package/src/components/LpCodeBlock.vue +4 -4
- package/src/components/LpColorPicker.vue +4 -4
- package/src/components/LpCommandPalette.vue +36 -14
- package/src/components/LpContextMenu.vue +19 -1
- package/src/components/LpDrawer.vue +1 -1
- package/src/components/LpDropdownMenu.vue +14 -3
- package/src/components/LpHints.vue +7 -1
- package/src/components/LpModal.vue +1 -1
- package/src/components/LpNotificationBell.vue +2 -2
- package/src/components/LpPasswordInput.vue +1 -1
- package/src/components/LpPhoneInput.vue +1 -1
- package/src/components/LpPie.vue +1 -1
- package/src/components/LpSegmented.vue +2 -2
- package/src/components/LpSidebarNav.vue +2 -2
- package/src/components/LpTable.vue +3 -3
- package/src/components/LpTabs.vue +11 -5
- package/src/components/LpToaster.vue +2 -2
- package/src/components/LpTour.vue +3 -0
- package/src/components/MenuTitle.vue +2 -2
- package/src/components/dropdown.ts +1 -1
- package/src/composables/useHintSystem.ts +130 -12
- package/src/index.ts +2 -1
- package/src/kit-icons.ts +1 -1
- package/src/tokens/tokens.css +6 -0
|
@@ -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";
|
package/dist/index.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { _ } from "./chunks/LayoutCanvas-
|
|
2
|
-
import { _ as _2 } from "./chunks/LpAddressInput-
|
|
3
|
-
import { _ as _3 } from "./chunks/LpMapPicker-
|
|
1
|
+
import { _ } from "./chunks/LayoutCanvas-t7LWFCEn.js";
|
|
2
|
+
import { _ as _2 } from "./chunks/LpAddressInput-DD4zTN4P.js";
|
|
3
|
+
import { _ as _3 } from "./chunks/LpMapPicker-DybIlWnF.js";
|
|
4
4
|
import { OSM_TILES, createNominatimProvider, emptyAddress, formatAddress, project, tileUrl, unproject } from "./components/address.js";
|
|
5
|
-
import { _ as _4 } from "./chunks/LpActionBar-
|
|
6
|
-
import { _ as _5 } from "./chunks/LpAlert
|
|
7
|
-
import { _ as _6 } from "./chunks/LpAppShell-
|
|
8
|
-
import { _ as _7 } from "./chunks/LpAutocomplete-
|
|
9
|
-
import { _ as _8 } from "./chunks/LpAvatar-
|
|
5
|
+
import { _ as _4 } from "./chunks/LpActionBar-BsSp66S_.js";
|
|
6
|
+
import { _ as _5 } from "./chunks/LpAlert--KLL4NLk.js";
|
|
7
|
+
import { _ as _6 } from "./chunks/LpAppShell-Cv-Y9qNA.js";
|
|
8
|
+
import { _ as _7 } from "./chunks/LpAutocomplete-PnL2ntKl.js";
|
|
9
|
+
import { _ as _8 } from "./chunks/LpAvatar-CwGs1JCQ.js";
|
|
10
10
|
import { _ as _9 } from "./chunks/LpBadge-Fe0D1bYx.js";
|
|
11
|
-
import { _ as _10 } from "./chunks/LpBreadcrumbs-
|
|
12
|
-
import { _ as _11 } from "./chunks/LpButton-
|
|
13
|
-
import { _ as _12 } from "./chunks/LpCalendar-
|
|
14
|
-
import { _ as _13 } from "./chunks/LpCard-
|
|
11
|
+
import { _ as _10 } from "./chunks/LpBreadcrumbs-CndzPYiG.js";
|
|
12
|
+
import { _ as _11 } from "./chunks/LpButton-CJSD7N0Z.js";
|
|
13
|
+
import { _ as _12 } from "./chunks/LpCalendar-CXVDbb2M.js";
|
|
14
|
+
import { _ as _13 } from "./chunks/LpCard-B2D0GIUU.js";
|
|
15
15
|
import { default as default2 } from "./components/LpChart.vue.js";
|
|
16
16
|
import { backgroundOf, csvField, downloadFile, fileStem, inlineSvg, resolveCssColor, svgToPng, toCsv } from "./components/exportData.js";
|
|
17
17
|
import { CHART_PALETTE, axisTicks, chartSummary, formatTick, markerIndex, niceScale, resolveSlices } from "./components/chart.js";
|
|
18
|
-
import { _ as _14 } from "./chunks/LpCheckbox-
|
|
19
|
-
import { _ as _15 } from "./chunks/LpCodeBlock-
|
|
18
|
+
import { _ as _14 } from "./chunks/LpCheckbox-DV9W6T3H.js";
|
|
19
|
+
import { _ as _15 } from "./chunks/LpCodeBlock-t6MLA3fb.js";
|
|
20
20
|
import { tokenizeLines } from "./components/codeHighlight.js";
|
|
21
|
-
import { _ as _16 } from "./chunks/LpColorPicker-
|
|
21
|
+
import { _ as _16 } from "./chunks/LpColorPicker-CvBF8TeL.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";
|
|
@@ -30,46 +30,46 @@ import { default as default6 } from "./components/LpPaletteStats.vue.js";
|
|
|
30
30
|
import { default as default7 } from "./components/LpPaletteSwatches.vue.js";
|
|
31
31
|
import { default as default8 } from "./components/LpKeys.vue.js";
|
|
32
32
|
import { comboKeys, comboSteps } from "./components/keys.js";
|
|
33
|
-
import { _ as _18 } from "./chunks/LpConfirmDialog-
|
|
34
|
-
import { _ as _19 } from "./chunks/LpConfirmHost-
|
|
33
|
+
import { _ as _18 } from "./chunks/LpConfirmDialog-tkgyY3eu.js";
|
|
34
|
+
import { _ as _19 } from "./chunks/LpConfirmHost-CoYIcUdl.js";
|
|
35
35
|
import { confirm, useConfirm } from "./components/confirm.js";
|
|
36
|
-
import { _ as _20 } from "./chunks/LpContextMenu-
|
|
37
|
-
import { _ as _21 } from "./chunks/LpDatePicker-
|
|
38
|
-
import { _ as _22 } from "./chunks/LpDateRangePicker-
|
|
39
|
-
import { _ as _23 } from "./chunks/LpRangeCalendar-
|
|
36
|
+
import { _ as _20 } from "./chunks/LpContextMenu-BnN1k7ga.js";
|
|
37
|
+
import { _ as _21 } from "./chunks/LpDatePicker-DxdrVNCG.js";
|
|
38
|
+
import { _ as _22 } from "./chunks/LpDateRangePicker-DjeaqikC.js";
|
|
39
|
+
import { _ as _23 } from "./chunks/LpRangeCalendar-COeOYF52.js";
|
|
40
40
|
import { clampRange, defaultRangePresets, formatRange, normalizeRange, sameRange } from "./components/dateRange.js";
|
|
41
|
-
import { _ as _24 } from "./chunks/LpDisclosure-
|
|
41
|
+
import { _ as _24 } from "./chunks/LpDisclosure-s8cQ7KQq.js";
|
|
42
42
|
import { _ as _25 } from "./chunks/LpDivider-CUX46KR0.js";
|
|
43
|
-
import { _ as _26 } from "./chunks/LpDrawer-
|
|
44
|
-
import { _ as _27 } from "./chunks/LpDropdownMenu-
|
|
43
|
+
import { _ as _26 } from "./chunks/LpDrawer-C97yoWmh.js";
|
|
44
|
+
import { _ as _27 } from "./chunks/LpDropdownMenu-CbyYu4Rw.js";
|
|
45
45
|
import { default as default9 } from "./components/LpDropzone.vue.js";
|
|
46
|
-
import { _ as _28 } from "./chunks/LpEmptyState-
|
|
47
|
-
import { _ as _29 } from "./chunks/LpFileTree-
|
|
46
|
+
import { _ as _28 } from "./chunks/LpEmptyState-CX8fdGSU.js";
|
|
47
|
+
import { _ as _29 } from "./chunks/LpFileTree-DEqh2ySW.js";
|
|
48
48
|
import { ancestorIds, checkStateOf, checkedCount, computeStats, fileIcon, formatModified, formatSize, sortNodes, subtreeIds, subtreeSize } from "./components/fileTree.js";
|
|
49
|
-
import { _ as _30 } from "./chunks/LpFieldNotice-
|
|
50
|
-
import { _ as _31 } from "./chunks/LpFormField-
|
|
51
|
-
import { _ as _32 } from "./chunks/LpIcon-
|
|
52
|
-
import { i, b, a, c } from "./chunks/icons-
|
|
49
|
+
import { _ as _30 } from "./chunks/LpFieldNotice-B--RzKfj.js";
|
|
50
|
+
import { _ as _31 } from "./chunks/LpFormField-DMPPL1jF.js";
|
|
51
|
+
import { _ as _32 } from "./chunks/LpIcon-CTuDVTYv.js";
|
|
52
|
+
import { i, b, a, c } from "./chunks/icons-CuO3W46H.js";
|
|
53
53
|
import { default as default10 } from "./components/LpImageEditor.vue.js";
|
|
54
54
|
import { _ as _33 } from "./chunks/LpInfraNode-Ds_8SZgN.js";
|
|
55
|
-
import { _ as _34 } from "./chunks/LpInput-
|
|
56
|
-
import { _ as _35 } from "./chunks/LpLightbox-
|
|
55
|
+
import { _ as _34 } from "./chunks/LpInput-C7FHxzj2.js";
|
|
56
|
+
import { _ as _35 } from "./chunks/LpLightbox-DiksFa4L.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-
|
|
59
|
+
import { _ as _37 } from "./chunks/LpLogViewer-BuPe23sZ.js";
|
|
60
60
|
import { countLevels, matchPositions, matchesTerm, ringWindow, stepMatch } from "./components/logSearch.js";
|
|
61
|
-
import { _ as _38 } from "./chunks/LpMediaGallery-
|
|
62
|
-
import { _ as _39 } from "./chunks/LpModal-
|
|
63
|
-
import { _ as _40 } from "./chunks/LpModalNav-
|
|
64
|
-
import { _ as _41 } from "./chunks/LpNotificationBell-
|
|
65
|
-
import { _ as _42 } from "./chunks/LpNumberField-
|
|
66
|
-
import { _ as _43 } from "./chunks/LpTimeField-
|
|
61
|
+
import { _ as _38 } from "./chunks/LpMediaGallery-Cic9UHsa.js";
|
|
62
|
+
import { _ as _39 } from "./chunks/LpModal-QFfctZsj.js";
|
|
63
|
+
import { _ as _40 } from "./chunks/LpModalNav-Cw7m-eks.js";
|
|
64
|
+
import { _ as _41 } from "./chunks/LpNotificationBell-xH_JphpS.js";
|
|
65
|
+
import { _ as _42 } from "./chunks/LpNumberField-BFSRVGkJ.js";
|
|
66
|
+
import { _ as _43 } from "./chunks/LpTimeField-BTEt0kvL.js";
|
|
67
67
|
import { _ as _44 } from "./chunks/LpNumberFlow-z4WPZcZu.js";
|
|
68
68
|
import { _ as _45 } from "./chunks/LpOtpInput-PbeNJ5In.js";
|
|
69
|
-
import { _ as _46 } from "./chunks/LpPagination-
|
|
70
|
-
import { _ as _47 } from "./chunks/LpPasswordInput-
|
|
71
|
-
import { _ as _48 } from "./chunks/LpPie-
|
|
72
|
-
import { _ as _49 } from "./chunks/LpPhoneInput-
|
|
69
|
+
import { _ as _46 } from "./chunks/LpPagination-BFl0I7tL.js";
|
|
70
|
+
import { _ as _47 } from "./chunks/LpPasswordInput-C1G4k_r0.js";
|
|
71
|
+
import { _ as _48 } from "./chunks/LpPie-BD5Lsh-2.js";
|
|
72
|
+
import { _ as _49 } from "./chunks/LpPhoneInput-CZrpVxla.js";
|
|
73
73
|
import { filterCountries, flagEmoji, loadCountries, matchCountryByValue } from "./components/countries.js";
|
|
74
74
|
import { _ as _50 } from "./chunks/LpPopover-DCKeqiVn.js";
|
|
75
75
|
import { _ as _51 } from "./chunks/LpProgress-CBU1iI69.js";
|
|
@@ -77,38 +77,38 @@ import { _ as _52 } from "./chunks/LpRadio-CWA5Eb3M.js";
|
|
|
77
77
|
import { _ as _53 } from "./chunks/LpRadioGroup-CCn-Q2_c.js";
|
|
78
78
|
import { _ as _54 } from "./chunks/LpRollingText-DB7upf-5.js";
|
|
79
79
|
import { _ as _55 } from "./chunks/LpScrollArea-Hz3-JWUG.js";
|
|
80
|
-
import { _ as _56 } from "./chunks/LpSegmented-
|
|
81
|
-
import { _ as _57 } from "./chunks/LpSection-
|
|
82
|
-
import { _ as _58 } from "./chunks/LpSelect-
|
|
80
|
+
import { _ as _56 } from "./chunks/LpSegmented-DslFku0N.js";
|
|
81
|
+
import { _ as _57 } from "./chunks/LpSection-BAkbf0OK.js";
|
|
82
|
+
import { _ as _58 } from "./chunks/LpSelect-C4OXN_q3.js";
|
|
83
83
|
import { _ as _59 } from "./chunks/LpServiceNode-D8uJ8sGk.js";
|
|
84
84
|
import { _ as _60 } from "./chunks/LpShift-DXNsauQZ.js";
|
|
85
85
|
import { default as default11 } from "./components/LpShortcutsDialog.vue.js";
|
|
86
|
-
import { _ as _61 } from "./chunks/LpSidebar-
|
|
86
|
+
import { _ as _61 } from "./chunks/LpSidebar-B3E_iViL.js";
|
|
87
87
|
import { _ as _62 } from "./chunks/LpSkeleton-BB6XIV-w.js";
|
|
88
88
|
import { _ as _63 } from "./chunks/LpSlider-Cuzmrd7p.js";
|
|
89
89
|
import { _ as _64 } from "./chunks/LpRangeSlider-C1yF9-nP.js";
|
|
90
90
|
import { _ as _65 } from "./chunks/LpVideoBackdrop-qWRYBOTQ.js";
|
|
91
91
|
import { formatClipTime, isNativeLoop, planLoop, seamProgress, seamReached } from "./components/videoBackdrop.js";
|
|
92
92
|
import { _ as _66 } from "./chunks/LpSparkline-CB80N8SJ.js";
|
|
93
|
-
import { _ as _67 } from "./chunks/LpStat-
|
|
94
|
-
import { _ as _68 } from "./chunks/LpStepper-
|
|
93
|
+
import { _ as _67 } from "./chunks/LpStat-oYk6V1LZ.js";
|
|
94
|
+
import { _ as _68 } from "./chunks/LpStepper-YgHGzgfD.js";
|
|
95
95
|
import { _ as _69 } from "./chunks/LpSwitch-DG2AhXIL.js";
|
|
96
96
|
import { default as default12 } from "./components/LpTable.vue.js";
|
|
97
97
|
import { compareValues } from "./components/tableSort.js";
|
|
98
98
|
import { _ as _70 } from "./chunks/LpTableOfContents-DYuqkByy.js";
|
|
99
|
-
import { _ as _71 } from "./chunks/LpTabs-
|
|
100
|
-
import { _ as _72 } from "./chunks/LpTagsInput-
|
|
99
|
+
import { _ as _71 } from "./chunks/LpTabs-00v3VQx4.js";
|
|
100
|
+
import { _ as _72 } from "./chunks/LpTagsInput-Sc56iy_j.js";
|
|
101
101
|
import { addTags, splitTags } from "./components/tags.js";
|
|
102
|
-
import { _ as _73 } from "./chunks/LpTextarea-
|
|
103
|
-
import { _ as _74 } from "./chunks/LpThemeSwitcher-
|
|
102
|
+
import { _ as _73 } from "./chunks/LpTextarea-CQZccQI3.js";
|
|
103
|
+
import { _ as _74 } from "./chunks/LpThemeSwitcher-CeBG0e_D.js";
|
|
104
104
|
import { _ as _75 } from "./chunks/LpTilt-B7KHX1zH.js";
|
|
105
|
-
import { _ as _76 } from "./chunks/LpToaster-
|
|
105
|
+
import { _ as _76 } from "./chunks/LpToaster-BcKs7vX7.js";
|
|
106
106
|
import { _ as _77 } from "./chunks/LpTooltip-suFCM34F.js";
|
|
107
|
-
import { _ as _78 } from "./chunks/LpTour-
|
|
107
|
+
import { _ as _78 } from "./chunks/LpTour-C29-1wha.js";
|
|
108
108
|
import { holeOf, openContextMenu, panelsAround } from "./components/tour.js";
|
|
109
|
-
import { _ as _79 } from "./chunks/LpHintLayer-
|
|
110
|
-
import { _ as _80 } from "./chunks/LpHints-
|
|
111
|
-
import { createHintSystem, hintKey, hintSummary, localHintStorage, provideHintSystem, useHintSystem } from "./composables/useHintSystem.js";
|
|
109
|
+
import { _ as _79 } from "./chunks/LpHintLayer-DsclGYcD.js";
|
|
110
|
+
import { _ as _80 } from "./chunks/LpHints-BTpvisgP.js";
|
|
111
|
+
import { HINT_SIGNALS, contextMenuTip, createHintSystem, hintKey, hintSummary, localHintStorage, paletteTip, provideHintSystem, runningHintSystem, useHintSystem } from "./composables/useHintSystem.js";
|
|
112
112
|
import { _ as _81 } from "./chunks/LpTooltipProvider-CftjV7Xc.js";
|
|
113
113
|
import { _ as _82 } from "./chunks/LpTopologyCanvas-6ozNrQKh.js";
|
|
114
114
|
import { _ as _83 } from "./chunks/LpUptimeBar-B4ltCfno.js";
|
|
@@ -184,6 +184,7 @@ export {
|
|
|
184
184
|
DEFAULT_SWATCHES,
|
|
185
185
|
FIELD_NOTICE_MS,
|
|
186
186
|
G as GLASS_BACKDROP_ATTR,
|
|
187
|
+
HINT_SIGNALS,
|
|
187
188
|
LP_CONFIG,
|
|
188
189
|
LP_FIELD,
|
|
189
190
|
_ as LayoutCanvas,
|
|
@@ -314,6 +315,7 @@ export {
|
|
|
314
315
|
compareValues,
|
|
315
316
|
computeStats,
|
|
316
317
|
confirm,
|
|
318
|
+
contextMenuTip,
|
|
317
319
|
countBlocks,
|
|
318
320
|
countLeaves,
|
|
319
321
|
countLevels,
|
|
@@ -388,6 +390,7 @@ export {
|
|
|
388
390
|
k as normalizeTheme,
|
|
389
391
|
opaqueCss,
|
|
390
392
|
openContextMenu,
|
|
393
|
+
paletteTip,
|
|
391
394
|
panelsAround,
|
|
392
395
|
parseColor,
|
|
393
396
|
parseCommandQuery,
|
|
@@ -424,6 +427,7 @@ export {
|
|
|
424
427
|
rgbToHsv,
|
|
425
428
|
ringWindow,
|
|
426
429
|
o as rose,
|
|
430
|
+
runningHintSystem,
|
|
427
431
|
sameRange,
|
|
428
432
|
scrollParent,
|
|
429
433
|
scrollToElement,
|
package/package.json
CHANGED
|
@@ -23,7 +23,7 @@ defineProps<{
|
|
|
23
23
|
}>()
|
|
24
24
|
|
|
25
25
|
const ITEM =
|
|
26
|
-
"group/item flex cursor-pointer select-none items-center gap-2 rounded-
|
|
26
|
+
"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"
|
|
27
27
|
const ICON =
|
|
28
28
|
"transition-transform duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] group-data-[highlighted]/item:translate-x-0.5"
|
|
29
29
|
</script>
|
|
@@ -1116,7 +1116,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
1116
1116
|
v-for="s in allSeries"
|
|
1117
1117
|
:key="s.id"
|
|
1118
1118
|
type="button"
|
|
1119
|
-
class="group flex cursor-pointer items-center gap-1.5 rounded-
|
|
1119
|
+
class="group flex cursor-pointer items-center gap-1.5 rounded-inner text-xs outline-none transition-opacity duration-fast focus-visible:ring-2 focus-visible:ring-ring"
|
|
1120
1120
|
:class="hidden.has(s.id) ? 'opacity-40' : ''"
|
|
1121
1121
|
:aria-pressed="!hidden.has(s.id)"
|
|
1122
1122
|
@click="toggleSeries(s.id)"
|
|
@@ -236,14 +236,14 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
236
236
|
class="flex items-center gap-2 border-b border-line bg-surface-soft px-3 py-1.5 text-muted"
|
|
237
237
|
>
|
|
238
238
|
<span v-if="title" class="truncate text-ink">{{ title }}</span>
|
|
239
|
-
<span v-if="lang !== 'plain'" class="rounded bg-surface px-1.5 py-0.5 text-[10px] uppercase tracking-wide">
|
|
239
|
+
<span v-if="lang !== 'plain'" class="rounded-small bg-surface px-1.5 py-0.5 text-[10px] uppercase tracking-wide">
|
|
240
240
|
{{ lang }}
|
|
241
241
|
</span>
|
|
242
242
|
<div class="ml-auto flex items-center gap-1">
|
|
243
243
|
<button
|
|
244
244
|
v-if="lockToggle"
|
|
245
245
|
type="button"
|
|
246
|
-
class="group/lock flex items-center gap-1 rounded px-1.5 py-1 outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
|
|
246
|
+
class="group/lock flex items-center gap-1 rounded-small px-1.5 py-1 outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
|
|
247
247
|
:aria-label="locked ? text.unlock : text.lock"
|
|
248
248
|
@click="toggleLock"
|
|
249
249
|
>
|
|
@@ -256,7 +256,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
256
256
|
<button
|
|
257
257
|
v-if="copyable"
|
|
258
258
|
type="button"
|
|
259
|
-
class="group/copy flex items-center gap-1 rounded px-1.5 py-1 outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
|
|
259
|
+
class="group/copy flex items-center gap-1 rounded-small px-1.5 py-1 outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring"
|
|
260
260
|
:aria-label="copied ? text.copied : text.copy"
|
|
261
261
|
@click="copy"
|
|
262
262
|
>
|
|
@@ -314,7 +314,7 @@ const { class: rootClass, attrs: rest } = useMergedAttrs(
|
|
|
314
314
|
v-else
|
|
315
315
|
><button
|
|
316
316
|
type="button"
|
|
317
|
-
class="lp-fold-toggle flex w-full items-center gap-1.5 rounded px-1 py-0.5 text-left text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
|
|
317
|
+
class="lp-fold-toggle flex w-full items-center gap-1.5 rounded-small px-1 py-0.5 text-left text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
|
|
318
318
|
:aria-expanded="openState[seg.id]"
|
|
319
319
|
@click="toggleFold(seg.id)"
|
|
320
320
|
><LpIcon
|
|
@@ -654,11 +654,11 @@ defineExpose({ open })
|
|
|
654
654
|
would be painted over the checkerboard and, being translucent
|
|
655
655
|
white, would show it through as a see-through outline. -->
|
|
656
656
|
<span
|
|
657
|
-
class="relative size-5 shrink-0 overflow-hidden rounded-
|
|
657
|
+
class="relative size-5 shrink-0 overflow-hidden rounded-inner"
|
|
658
658
|
:style="{ background: CHECKERBOARD }"
|
|
659
659
|
>
|
|
660
660
|
<span class="block size-full" :style="{ backgroundColor: previewCss }" />
|
|
661
|
-
<span class="pointer-events-none absolute inset-0 rounded-
|
|
661
|
+
<span class="pointer-events-none absolute inset-0 rounded-inner ring-1 ring-inset ring-line" />
|
|
662
662
|
</span>
|
|
663
663
|
<span class="min-w-0 flex-1 truncate font-mono text-xs text-muted-strong">
|
|
664
664
|
{{ label ?? current }}
|
|
@@ -814,7 +814,7 @@ defineExpose({ open })
|
|
|
814
814
|
:disabled="disabled"
|
|
815
815
|
:aria-label="c"
|
|
816
816
|
:aria-pressed="isActiveSwatch(c)"
|
|
817
|
-
class="relative flex items-center justify-center overflow-hidden rounded-
|
|
817
|
+
class="relative flex items-center justify-center overflow-hidden rounded-inner outline-none transition-transform duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] hover:scale-110 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed motion-reduce:hover:scale-100 motion-reduce:active:scale-95"
|
|
818
818
|
:class="row.size"
|
|
819
819
|
:style="{ background: CHECKERBOARD }"
|
|
820
820
|
@click="pickSwatch(c)"
|
|
@@ -826,7 +826,7 @@ defineExpose({ open })
|
|
|
826
826
|
inset ring painted OVER the colour instead, so it reads
|
|
827
827
|
as one fixed hairline rather than a translucent gap. -->
|
|
828
828
|
<span class="absolute inset-0" :style="{ backgroundColor: c }" />
|
|
829
|
-
<span class="pointer-events-none absolute inset-0 rounded-
|
|
829
|
+
<span class="pointer-events-none absolute inset-0 rounded-inner ring-1 ring-inset ring-line" />
|
|
830
830
|
<LpIcon
|
|
831
831
|
v-if="isActiveSwatch(c)"
|
|
832
832
|
name="lucide:check"
|
|
@@ -44,6 +44,8 @@ import { useAsyncTask } from "../composables/useAsyncTask"
|
|
|
44
44
|
import { useGlass } from "../composables/useGlass"
|
|
45
45
|
import { useClipboard } from "../composables/useClipboard"
|
|
46
46
|
import { useHotkeys } from "../composables/useHotkeys"
|
|
47
|
+
import { hints } from "../composables/useHints"
|
|
48
|
+
import { HINT_SIGNALS, runningHintSystem } from "../composables/useHintSystem"
|
|
47
49
|
import { useModalLayer } from "./modalDepth"
|
|
48
50
|
import { useLabels } from "../composables/useLpConfig"
|
|
49
51
|
import {
|
|
@@ -516,9 +518,20 @@ function onTab(event: KeyboardEvent) {
|
|
|
516
518
|
event.stopPropagation()
|
|
517
519
|
const actionsMode: Command = { id: `${c.id}:actions`, label: c.label, icon: c.icon, children: actions }
|
|
518
520
|
syntheticModes.add(actionsMode)
|
|
521
|
+
hints.use(HINT_SIGNALS.paletteActions)
|
|
519
522
|
enter(actionsMode)
|
|
520
523
|
}
|
|
521
524
|
|
|
525
|
+
// A returning user who never pressed Tab gets the footer key lit up, nothing
|
|
526
|
+
// more: the palette is the one place they already came to on purpose.
|
|
527
|
+
const PALETTE_ACTIONS_AFTER = 3
|
|
528
|
+
const showActionsKey = computed(() => {
|
|
529
|
+
const system = runningHintSystem()
|
|
530
|
+
return !!system?.state.loaded
|
|
531
|
+
&& system.count(HINT_SIGNALS.palette) >= PALETTE_ACTIONS_AFTER
|
|
532
|
+
&& system.count(HINT_SIGNALS.paletteActions) === 0
|
|
533
|
+
})
|
|
534
|
+
|
|
522
535
|
/*
|
|
523
536
|
* A mode holds the command it was entered through, and a static `children`
|
|
524
537
|
* list is a snapshot of that moment. When the app rebuilds its commands (a
|
|
@@ -1162,8 +1175,10 @@ function onEscape(event: KeyboardEvent) {
|
|
|
1162
1175
|
watch(
|
|
1163
1176
|
() => props.open,
|
|
1164
1177
|
async (o) => {
|
|
1165
|
-
if (o)
|
|
1166
|
-
|
|
1178
|
+
if (o) {
|
|
1179
|
+
claim()
|
|
1180
|
+
hints.use(HINT_SIGNALS.palette)
|
|
1181
|
+
} else release()
|
|
1167
1182
|
cancel()
|
|
1168
1183
|
query.value = ""
|
|
1169
1184
|
select(0)
|
|
@@ -1239,7 +1254,7 @@ useHotkeys(() =>
|
|
|
1239
1254
|
v-for="(step, i) in trail"
|
|
1240
1255
|
:key="step.id"
|
|
1241
1256
|
type="button"
|
|
1242
|
-
class="flex shrink-0 items-center gap-1.5 rounded-
|
|
1257
|
+
class="flex shrink-0 items-center gap-1.5 rounded-inner bg-brand-soft px-2 py-1 text-xs font-medium text-brand transition-opacity hover:opacity-80"
|
|
1243
1258
|
:title="text.back"
|
|
1244
1259
|
@click="popTo(i)"
|
|
1245
1260
|
>
|
|
@@ -1264,7 +1279,7 @@ useHotkeys(() =>
|
|
|
1264
1279
|
@keydown.esc="onEscape"
|
|
1265
1280
|
@keydown.tab="onTab"
|
|
1266
1281
|
/>
|
|
1267
|
-
<kbd class="shrink-0 rounded border border-line px-1.5 py-0.5 text-[10px] text-muted">{{ text.esc }}</kbd>
|
|
1282
|
+
<kbd class="shrink-0 rounded-small border border-line px-1.5 py-0.5 text-[10px] text-muted">{{ text.esc }}</kbd>
|
|
1268
1283
|
</div>
|
|
1269
1284
|
|
|
1270
1285
|
<!-- Results -->
|
|
@@ -1305,7 +1320,7 @@ useHotkeys(() =>
|
|
|
1305
1320
|
:aria-disabled="c.disabled || undefined"
|
|
1306
1321
|
:data-cmd-index="flatIndexOf(c)"
|
|
1307
1322
|
:disabled="c.href ? undefined : c.disabled"
|
|
1308
|
-
class="lp-cmd-item flex w-full gap-3 rounded-
|
|
1323
|
+
class="lp-cmd-item flex w-full gap-3 rounded-inner px-2.5 py-2 text-left text-sm outline-none transition-colors duration-[var(--duration-fast)] disabled:pointer-events-none disabled:opacity-45 aria-disabled:pointer-events-none aria-disabled:opacity-45"
|
|
1309
1324
|
:class="[
|
|
1310
1325
|
c.excerpt ? 'items-start' : 'items-center',
|
|
1311
1326
|
flatIndexOf(c) === selectedIndex
|
|
@@ -1365,7 +1380,7 @@ useHotkeys(() =>
|
|
|
1365
1380
|
shortcut is learned by seeing it rather than reading docs. -->
|
|
1366
1381
|
<kbd
|
|
1367
1382
|
v-else-if="c.prefix && c.children"
|
|
1368
|
-
class="shrink-0 rounded border border-line px-1.5 font-mono text-[11px] whitespace-pre text-muted"
|
|
1383
|
+
class="shrink-0 rounded-small border border-line px-1.5 font-mono text-[11px] whitespace-pre text-muted"
|
|
1369
1384
|
>{{ c.prefix }}</kbd>
|
|
1370
1385
|
<!-- Drills in rather than runs: worth saying before the click,
|
|
1371
1386
|
since the two look identical otherwise. -->
|
|
@@ -1390,7 +1405,7 @@ useHotkeys(() =>
|
|
|
1390
1405
|
<span>{{ text.searchFailed }}</span>
|
|
1391
1406
|
<button
|
|
1392
1407
|
type="button"
|
|
1393
|
-
class="rounded-
|
|
1408
|
+
class="rounded-inner px-1.5 py-0.5 font-medium text-brand outline-none transition-colors hover:bg-brand-soft focus-visible:ring-2 focus-visible:ring-ring"
|
|
1394
1409
|
@click="refresh(); inputRef?.focus()"
|
|
1395
1410
|
>
|
|
1396
1411
|
{{ text.retry }}
|
|
@@ -1451,26 +1466,33 @@ useHotkeys(() =>
|
|
|
1451
1466
|
class="flex shrink-0 items-center gap-4 border-t border-line px-4 py-2.5 text-[11px] text-muted [@media(hover:none)_and_(pointer:coarse)]:hidden"
|
|
1452
1467
|
>
|
|
1453
1468
|
<span class="flex items-center gap-1">
|
|
1454
|
-
<kbd class="rounded border border-line px-1 text-[10px]">↑</kbd>
|
|
1455
|
-
<kbd class="rounded border border-line px-1 text-[10px]">↓</kbd>
|
|
1469
|
+
<kbd class="rounded-small border border-line px-1 text-[10px]">↑</kbd>
|
|
1470
|
+
<kbd class="rounded-small border border-line px-1 text-[10px]">↓</kbd>
|
|
1456
1471
|
{{ text.navigate }}
|
|
1457
1472
|
</span>
|
|
1458
1473
|
<span class="flex items-center gap-1">
|
|
1459
|
-
<kbd class="rounded border border-line px-1 text-[10px]">↵</kbd>
|
|
1474
|
+
<kbd class="rounded-small border border-line px-1 text-[10px]">↵</kbd>
|
|
1460
1475
|
{{ text.select }}
|
|
1461
1476
|
</span>
|
|
1462
1477
|
<!-- Only inside a mode: at the root Backspace just edits the query,
|
|
1463
1478
|
and advertising it there would be a lie. -->
|
|
1464
|
-
<span
|
|
1465
|
-
|
|
1479
|
+
<span
|
|
1480
|
+
v-if="selectedActions.length"
|
|
1481
|
+
class="flex items-center gap-1 transition-colors"
|
|
1482
|
+
:class="showActionsKey && 'font-medium text-brand'"
|
|
1483
|
+
>
|
|
1484
|
+
<kbd
|
|
1485
|
+
class="rounded-small border px-1 text-[10px] transition-colors"
|
|
1486
|
+
:class="showActionsKey ? 'border-brand' : 'border-line'"
|
|
1487
|
+
>tab</kbd>
|
|
1466
1488
|
{{ text.actions }}
|
|
1467
1489
|
</span>
|
|
1468
1490
|
<span v-if="trail.length" class="flex items-center gap-1">
|
|
1469
|
-
<kbd class="rounded border border-line px-1 text-[10px]">⌫</kbd>
|
|
1491
|
+
<kbd class="rounded-small border border-line px-1 text-[10px]">⌫</kbd>
|
|
1470
1492
|
{{ text.back }}
|
|
1471
1493
|
</span>
|
|
1472
1494
|
<span class="ml-auto flex items-center gap-1">
|
|
1473
|
-
<kbd class="rounded border border-line px-1 text-[10px]">{{ text.esc }}</kbd>
|
|
1495
|
+
<kbd class="rounded-small border border-line px-1 text-[10px]">{{ text.esc }}</kbd>
|
|
1474
1496
|
{{ text.close }}
|
|
1475
1497
|
</span>
|
|
1476
1498
|
</div>
|