@leavepulse/ui 0.37.10 → 0.38.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-C0yStVNy.css +21 -0
- package/dist/chunks/LpSwitch-Blizvqyt.js +94 -0
- package/dist/components/LpCommandPalette.vue.d.ts +87 -1
- package/dist/components/LpCommandPalette.vue.js +410 -121
- package/dist/components/LpSwitch.vue.d.ts +31 -2
- package/dist/components/LpSwitch.vue.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/LpCommandPalette.vue +492 -76
- package/src/components/LpSwitch.vue +55 -10
- package/src/tokens/tokens.css +21 -0
- package/dist/assets/LpCommandPalette-B-g1fa8r.css +0 -16
- package/dist/chunks/LpSwitch-xgnRU2k0.js +0 -35
|
@@ -1,48 +1,80 @@
|
|
|
1
|
-
import { defineComponent, computed, ref, shallowRef, watch, nextTick, openBlock, createBlock, unref, withCtx, createVNode, withModifiers, createTextVNode, createElementVNode, createElementBlock, Fragment, renderList, createCommentVNode, toDisplayString, withDirectives, withKeys, vModelText,
|
|
1
|
+
import { defineComponent, computed, ref, useId, shallowRef, watch, nextTick, openBlock, createBlock, unref, withCtx, createVNode, withModifiers, normalizeClass, createTextVNode, createElementVNode, createElementBlock, Fragment, renderList, createCommentVNode, toDisplayString, withDirectives, withKeys, vModelText, resolveDynamicComponent, normalizeStyle, renderSlot } from "vue";
|
|
2
2
|
import { DialogRoot, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription } from "reka-ui";
|
|
3
3
|
import { _ as _sfc_main$1 } from "../chunks/LpIcon-CCnX5_2j.js";
|
|
4
4
|
import { _ as _sfc_main$2 } from "../chunks/LpScrollArea-D8xyKXcF.js";
|
|
5
5
|
import { useAsyncTask } from "../composables/useAsyncTask.js";
|
|
6
|
+
import { useClipboard } from "../composables/useClipboard.js";
|
|
6
7
|
import { useHotkeys } from "../composables/useHotkeys.js";
|
|
7
8
|
import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper-1tPrXgE0.js";
|
|
8
|
-
import '../assets/LpCommandPalette-
|
|
9
|
+
import '../assets/LpCommandPalette-C0yStVNy.css';const _hoisted_1 = { class: "flex shrink-0 items-center gap-2.5 border-b border-line px-4" };
|
|
9
10
|
const _hoisted_2 = ["title", "onClick"];
|
|
10
|
-
const _hoisted_3 = ["placeholder", "onKeydown"];
|
|
11
|
-
const _hoisted_4 = {
|
|
12
|
-
key: 0,
|
|
13
|
-
class: "px-2 py-10 text-center text-sm text-muted"
|
|
14
|
-
};
|
|
11
|
+
const _hoisted_3 = ["aria-activedescendant", "placeholder", "onKeydown"];
|
|
12
|
+
const _hoisted_4 = { class: "flex min-h-0 flex-1" };
|
|
15
13
|
const _hoisted_5 = {
|
|
16
14
|
key: 0,
|
|
17
|
-
class: "px-2
|
|
15
|
+
class: "px-2 py-10 text-center text-sm text-muted"
|
|
18
16
|
};
|
|
19
|
-
const _hoisted_6 = ["
|
|
20
|
-
const _hoisted_7 =
|
|
21
|
-
const _hoisted_8 = { class: "
|
|
22
|
-
const _hoisted_9 = {
|
|
17
|
+
const _hoisted_6 = ["aria-labelledby"];
|
|
18
|
+
const _hoisted_7 = ["id"];
|
|
19
|
+
const _hoisted_8 = { class: "min-w-0 flex-1" };
|
|
20
|
+
const _hoisted_9 = { class: "block truncate font-medium" };
|
|
21
|
+
const _hoisted_10 = {
|
|
23
22
|
key: 0,
|
|
24
23
|
class: "rounded-xs bg-brand/25 text-ink"
|
|
25
24
|
};
|
|
26
|
-
const
|
|
25
|
+
const _hoisted_11 = {
|
|
27
26
|
key: 0,
|
|
28
27
|
class: "mt-0.5 block truncate text-xs text-muted"
|
|
29
28
|
};
|
|
30
|
-
const
|
|
29
|
+
const _hoisted_12 = {
|
|
31
30
|
key: 0,
|
|
32
31
|
class: "rounded-xs bg-brand/20 text-ink"
|
|
33
32
|
};
|
|
34
|
-
const
|
|
33
|
+
const _hoisted_13 = {
|
|
34
|
+
key: 0,
|
|
35
|
+
class: "rounded-xs bg-brand/20 text-ink"
|
|
36
|
+
};
|
|
37
|
+
const _hoisted_14 = {
|
|
35
38
|
key: 1,
|
|
36
39
|
class: "shrink-0 text-xs text-muted"
|
|
37
40
|
};
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
const _hoisted_15 = {
|
|
42
|
+
key: 0,
|
|
43
|
+
class: "hidden min-h-0 w-[56%] shrink-0 flex-col border-l border-line md:flex"
|
|
44
|
+
};
|
|
45
|
+
const _hoisted_16 = { class: "flex items-center gap-2 text-ink" };
|
|
46
|
+
const _hoisted_17 = { class: "min-w-0 text-base font-semibold" };
|
|
47
|
+
const _hoisted_18 = {
|
|
48
|
+
key: 0,
|
|
49
|
+
class: "mt-0.5 text-xs text-muted"
|
|
50
|
+
};
|
|
51
|
+
const _hoisted_19 = {
|
|
52
|
+
key: 1,
|
|
53
|
+
class: "mt-3 whitespace-pre-line text-sm leading-relaxed text-ink/90"
|
|
54
|
+
};
|
|
55
|
+
const _hoisted_20 = {
|
|
56
|
+
key: 0,
|
|
57
|
+
class: "rounded-xs bg-brand/25 text-ink"
|
|
58
|
+
};
|
|
59
|
+
const _hoisted_21 = {
|
|
60
|
+
key: 2,
|
|
61
|
+
class: "mt-3 text-sm text-muted"
|
|
62
|
+
};
|
|
63
|
+
const _hoisted_22 = { class: "flex shrink-0 items-center gap-4 border-t border-line px-4 py-2.5 text-[11px] text-muted" };
|
|
64
|
+
const _hoisted_23 = { class: "flex items-center gap-1" };
|
|
65
|
+
const _hoisted_24 = { class: "flex items-center gap-1" };
|
|
66
|
+
const _hoisted_25 = {
|
|
42
67
|
key: 0,
|
|
43
68
|
class: "flex items-center gap-1"
|
|
44
69
|
};
|
|
45
|
-
const
|
|
70
|
+
const _hoisted_26 = {
|
|
71
|
+
key: 1,
|
|
72
|
+
class: "flex items-center gap-1"
|
|
73
|
+
};
|
|
74
|
+
const _hoisted_27 = { class: "ml-auto flex items-center gap-1" };
|
|
75
|
+
const LATIN = "qwertyuiop[]asdfghjkl;'zxcvbnm,.`";
|
|
76
|
+
const CYRILLIC = "йцукенгшщзхъфывапролджэячсмитьбюё";
|
|
77
|
+
const TYPO_MIN = 5;
|
|
46
78
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
47
79
|
__name: "LpCommandPalette",
|
|
48
80
|
props: {
|
|
@@ -58,7 +90,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
58
90
|
recentLimit: { default: 5 },
|
|
59
91
|
recentLabel: { default: "Recent" },
|
|
60
92
|
resultsLabel: { default: "Results" },
|
|
61
|
-
labels: {}
|
|
93
|
+
labels: {},
|
|
94
|
+
excerptLines: { default: 4 },
|
|
95
|
+
groupLimit: { default: 0 },
|
|
96
|
+
layoutFallback: { type: Boolean, default: true },
|
|
97
|
+
previewPane: { type: Boolean, default: false }
|
|
62
98
|
},
|
|
63
99
|
emits: ["update:open", "select", "run"],
|
|
64
100
|
setup(__props, { emit: __emit }) {
|
|
@@ -68,17 +104,63 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
68
104
|
select: "select",
|
|
69
105
|
close: "close",
|
|
70
106
|
back: "back",
|
|
71
|
-
searching: "Searching…"
|
|
107
|
+
searching: "Searching…",
|
|
108
|
+
searchFailed: "Search is unavailable right now.",
|
|
109
|
+
retry: "Retry",
|
|
110
|
+
showMore: "Show {count} more",
|
|
111
|
+
actions: "actions",
|
|
112
|
+
openInNewTab: "Open in new tab",
|
|
113
|
+
copyLink: "Copy link",
|
|
114
|
+
linkCopied: "Link copied",
|
|
115
|
+
noPreview: "No preview"
|
|
72
116
|
};
|
|
73
117
|
const text = computed(() => ({ ...DEFAULT_LABELS, ...props.labels }));
|
|
74
118
|
const emit = __emit;
|
|
75
119
|
const query = ref("");
|
|
120
|
+
const listId = `lp-cmd-${useId()}`;
|
|
121
|
+
function optionId(index) {
|
|
122
|
+
return `${listId}-${index}`;
|
|
123
|
+
}
|
|
124
|
+
const activeId = computed(() => flat.value.length ? optionId(selectedIndex.value) : void 0);
|
|
76
125
|
const selectedIndex = ref(0);
|
|
77
126
|
const inputRef = ref(null);
|
|
78
127
|
const scrollRef = ref(null);
|
|
79
128
|
const trail = shallowRef([]);
|
|
80
129
|
const mode = computed(() => trail.value[trail.value.length - 1] ?? null);
|
|
81
130
|
const modeItems = shallowRef([]);
|
|
131
|
+
const { copy } = useClipboard();
|
|
132
|
+
function actionsOf(c) {
|
|
133
|
+
if (!c || c.disabled || moreOf.has(c)) return [];
|
|
134
|
+
const own = c.actions ?? [];
|
|
135
|
+
const href = c.href;
|
|
136
|
+
if (!href) return own;
|
|
137
|
+
const link = new URL(href, window.location.href).href;
|
|
138
|
+
return [
|
|
139
|
+
...own,
|
|
140
|
+
{
|
|
141
|
+
id: `${c.id}:open-in-new-tab`,
|
|
142
|
+
label: text.value.openInNewTab,
|
|
143
|
+
icon: "lucide:external-link",
|
|
144
|
+
onSelect: () => window.open(href, "_blank", "noopener")
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
id: `${c.id}:copy-link`,
|
|
148
|
+
label: text.value.copyLink,
|
|
149
|
+
icon: "lucide:link",
|
|
150
|
+
onSelect: () => void copy(link, { toast: text.value.linkCopied || false })
|
|
151
|
+
}
|
|
152
|
+
];
|
|
153
|
+
}
|
|
154
|
+
const selectedActions = computed(() => actionsOf(flat.value[selectedIndex.value]));
|
|
155
|
+
function onTab(event) {
|
|
156
|
+
if (event.shiftKey) return;
|
|
157
|
+
const c = flat.value[selectedIndex.value];
|
|
158
|
+
const actions = selectedActions.value;
|
|
159
|
+
if (!c || !actions.length) return;
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
event.stopPropagation();
|
|
162
|
+
enter({ id: `${c.id}:actions`, label: c.label, icon: c.icon, children: actions });
|
|
163
|
+
}
|
|
82
164
|
function enter(c) {
|
|
83
165
|
trail.value = [...trail.value, c];
|
|
84
166
|
query.value = "";
|
|
@@ -115,9 +197,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
115
197
|
function cancel() {
|
|
116
198
|
task.cancel();
|
|
117
199
|
}
|
|
200
|
+
const failed = ref(false);
|
|
118
201
|
function refresh() {
|
|
119
202
|
cancel();
|
|
120
203
|
found.value = [];
|
|
204
|
+
failed.value = false;
|
|
121
205
|
const run2 = fetcher();
|
|
122
206
|
if (!run2) return;
|
|
123
207
|
const q = query.value.trim();
|
|
@@ -126,21 +210,60 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
126
210
|
task.run((signal) => run2(q, signal), {
|
|
127
211
|
delay: props.debounce,
|
|
128
212
|
apply: (hits) => found.value = hits,
|
|
129
|
-
fail: () =>
|
|
213
|
+
fail: () => {
|
|
214
|
+
found.value = [];
|
|
215
|
+
failed.value = true;
|
|
216
|
+
}
|
|
130
217
|
});
|
|
131
218
|
}
|
|
132
219
|
const source = computed(() => mode.value ? modeItems.value : props.commands);
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
220
|
+
const SWAP = /* @__PURE__ */ new Map();
|
|
221
|
+
for (let i = 0; i < LATIN.length; i++) {
|
|
222
|
+
SWAP.set(LATIN[i], CYRILLIC[i]);
|
|
223
|
+
SWAP.set(CYRILLIC[i], LATIN[i]);
|
|
224
|
+
}
|
|
225
|
+
function swapLayout(term) {
|
|
226
|
+
return [...term].map((ch) => SWAP.get(ch) ?? ch).join("");
|
|
227
|
+
}
|
|
228
|
+
function withinOne(a, b) {
|
|
229
|
+
if (Math.abs(a.length - b.length) > 1) return false;
|
|
230
|
+
let i = 0;
|
|
231
|
+
while (i < a.length && i < b.length && a[i] === b[i]) i++;
|
|
232
|
+
if (i === a.length || i === b.length) return true;
|
|
233
|
+
const rest = (x, y) => a.slice(i + x) === b.slice(i + y);
|
|
234
|
+
return rest(1, 1) || rest(1, 0) || rest(0, 1) || a[i] === b[i + 1] && a[i + 1] === b[i] && rest(2, 2);
|
|
235
|
+
}
|
|
236
|
+
function nearWord(term, label) {
|
|
237
|
+
if (term.length < TYPO_MIN) return false;
|
|
238
|
+
return label.split(/[^\p{L}\p{N}]+/u).some((word) => withinOne(term, word) || word.length > term.length && withinOne(term, word.slice(0, term.length)));
|
|
239
|
+
}
|
|
240
|
+
function score(c, terms) {
|
|
241
|
+
const label = c.label.toLowerCase();
|
|
242
|
+
const keywords = (c.keywords ?? []).map((k) => k.toLowerCase());
|
|
243
|
+
const description = c.description?.toLowerCase() ?? "";
|
|
244
|
+
let total = 0;
|
|
245
|
+
for (const term of terms) {
|
|
246
|
+
let hit = (label.includes(term) ? 4 : 0) + (keywords.some((k) => k.includes(term)) ? 3 : 0) + (description.includes(term) ? 2 : 0);
|
|
247
|
+
if (!hit && nearWord(term, label)) hit = 1;
|
|
248
|
+
if (!hit) return 0;
|
|
249
|
+
total += hit;
|
|
250
|
+
}
|
|
251
|
+
return total;
|
|
252
|
+
}
|
|
253
|
+
function rank(items, terms) {
|
|
254
|
+
return items.map((c) => ({ c, score: score(c, terms) })).filter((e) => e.score > 0).sort((a, b) => b.score - a.score || a.c.label.localeCompare(b.c.label)).map((e) => e.c);
|
|
255
|
+
}
|
|
256
|
+
const typedTerms = computed(() => query.value.trim().toLowerCase().split(/\s+/).filter(Boolean));
|
|
257
|
+
const local = computed(() => {
|
|
258
|
+
const terms = typedTerms.value;
|
|
259
|
+
if (!terms.length) return { items: source.value.filter((c) => !c.hidden), terms };
|
|
260
|
+
const items = rank(source.value, terms);
|
|
261
|
+
if (items.length || !props.layoutFallback) return { items, terms };
|
|
262
|
+
const swapped = terms.map(swapLayout);
|
|
263
|
+
const other = rank(source.value, swapped);
|
|
264
|
+
return other.length ? { items: other, terms: swapped } : { items, terms };
|
|
143
265
|
});
|
|
266
|
+
const ranked = computed(() => local.value.items);
|
|
144
267
|
const fetched = computed(() => {
|
|
145
268
|
if (!found.value.length) return [];
|
|
146
269
|
const seen = new Set(ranked.value.map((c) => c.id));
|
|
@@ -171,14 +294,45 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
171
294
|
for (const c of recent) push(c, props.recentLabel);
|
|
172
295
|
for (const c of ranked.value) if (!recent.includes(c)) push(c, c.group ?? "");
|
|
173
296
|
for (const c of fetched.value) push(c, c.group ?? "");
|
|
174
|
-
return order.map((name) => ({ name, items: map.get(name) }));
|
|
297
|
+
return order.map((name) => ({ name, items: folded(name, map.get(name)) }));
|
|
175
298
|
});
|
|
299
|
+
const expanded = ref(/* @__PURE__ */ new Set());
|
|
300
|
+
const moreOf = /* @__PURE__ */ new WeakMap();
|
|
301
|
+
function folded(name, items) {
|
|
302
|
+
const limit = props.groupLimit;
|
|
303
|
+
if (!limit || items.length <= limit + 1 || expanded.value.has(name)) return items;
|
|
304
|
+
const more = {
|
|
305
|
+
id: `lp-cmd-more:${name}`,
|
|
306
|
+
label: text.value.showMore.replace("{count}", String(items.length - limit)),
|
|
307
|
+
icon: "lucide:chevron-down",
|
|
308
|
+
keepOpen: true
|
|
309
|
+
};
|
|
310
|
+
moreOf.set(more, name);
|
|
311
|
+
return [...items.slice(0, limit), more];
|
|
312
|
+
}
|
|
176
313
|
const flat = computed(() => grouped.value.flatMap((g) => g.items));
|
|
314
|
+
const active = computed(() => {
|
|
315
|
+
const c = flat.value[selectedIndex.value];
|
|
316
|
+
return c && !moreOf.has(c) ? c : void 0;
|
|
317
|
+
});
|
|
318
|
+
const previewRef = ref(null);
|
|
319
|
+
watch(
|
|
320
|
+
() => active.value?.id,
|
|
321
|
+
async () => {
|
|
322
|
+
if (!props.previewPane) return;
|
|
323
|
+
await nextTick();
|
|
324
|
+
const viewport = previewRef.value?.viewportEl;
|
|
325
|
+
if (!viewport) return;
|
|
326
|
+
const mark = viewport.querySelector("mark");
|
|
327
|
+
if (mark) mark.scrollIntoView({ block: "center" });
|
|
328
|
+
else viewport.scrollTop = 0;
|
|
329
|
+
}
|
|
330
|
+
);
|
|
177
331
|
function flatIndexOf(c) {
|
|
178
332
|
return flat.value.indexOf(c);
|
|
179
333
|
}
|
|
180
|
-
function highlight(value) {
|
|
181
|
-
const terms = [...new Set(
|
|
334
|
+
function highlight(value, extra = []) {
|
|
335
|
+
const terms = [...new Set([...local.value.terms, ...extra.map((t) => t.toLowerCase())].filter((t) => t.length >= 2))].sort(
|
|
182
336
|
(a, b) => b.length - a.length
|
|
183
337
|
);
|
|
184
338
|
if (!value || terms.length === 0) return value ? [{ text: value, hit: false }] : [];
|
|
@@ -209,6 +363,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
209
363
|
selectedIndex.value = 0;
|
|
210
364
|
refresh();
|
|
211
365
|
});
|
|
366
|
+
watch([query, trail, () => props.open], () => {
|
|
367
|
+
expanded.value = /* @__PURE__ */ new Set();
|
|
368
|
+
});
|
|
212
369
|
watch(
|
|
213
370
|
() => flat.value.length,
|
|
214
371
|
(len) => {
|
|
@@ -233,13 +390,36 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
233
390
|
const len = flat.value.length;
|
|
234
391
|
if (len) selectedIndex.value = (selectedIndex.value - 1 + len) % len;
|
|
235
392
|
}
|
|
236
|
-
function runSelected() {
|
|
237
|
-
|
|
393
|
+
function runSelected(event) {
|
|
394
|
+
const c = flat.value[selectedIndex.value];
|
|
395
|
+
if (c?.href && !c.disabled && (event?.ctrlKey || event?.metaKey)) {
|
|
396
|
+
openInNewTab(c);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
run(c);
|
|
400
|
+
}
|
|
401
|
+
function openInNewTab(c) {
|
|
402
|
+
if (!c.href) return;
|
|
403
|
+
window.open(c.href, "_blank", "noopener");
|
|
404
|
+
emit("run", c.id, c);
|
|
405
|
+
emit("update:open", false);
|
|
406
|
+
}
|
|
407
|
+
function onRowClick(event, c) {
|
|
408
|
+
if (c.href && (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey || event.button !== 0)) return;
|
|
409
|
+
event.preventDefault();
|
|
410
|
+
run(c);
|
|
238
411
|
}
|
|
239
412
|
function run(c) {
|
|
240
413
|
if (!c || c.disabled) return;
|
|
414
|
+
const group = moreOf.get(c);
|
|
415
|
+
if (group !== void 0) {
|
|
416
|
+
expanded.value = /* @__PURE__ */ new Set([...expanded.value, group]);
|
|
417
|
+
inputRef.value?.focus();
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
241
420
|
emit("select", c);
|
|
242
421
|
c.onSelect?.();
|
|
422
|
+
if (!c.onSelect && c.href && !c.children) window.location.assign(c.href);
|
|
243
423
|
if (c.children) {
|
|
244
424
|
enter(c);
|
|
245
425
|
return;
|
|
@@ -272,6 +452,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
272
452
|
trail.value = [];
|
|
273
453
|
modeItems.value = [];
|
|
274
454
|
found.value = [];
|
|
455
|
+
failed.value = false;
|
|
275
456
|
if (o) {
|
|
276
457
|
await nextTick();
|
|
277
458
|
inputRef.value?.focus();
|
|
@@ -292,26 +473,26 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
292
473
|
return (_ctx, _cache) => {
|
|
293
474
|
return openBlock(), createBlock(unref(DialogRoot), {
|
|
294
475
|
open: __props.open,
|
|
295
|
-
"onUpdate:open": _cache[
|
|
476
|
+
"onUpdate:open": _cache[3] || (_cache[3] = (v) => emit("update:open", v))
|
|
296
477
|
}, {
|
|
297
478
|
default: withCtx(() => [
|
|
298
479
|
createVNode(unref(DialogPortal), null, {
|
|
299
480
|
default: withCtx(() => [
|
|
300
481
|
createVNode(unref(DialogOverlay), { class: "lp-scrim fixed inset-0 z-(--z-overlay) data-[state=open]:animate-[fade-in_150ms_ease] data-[state=closed]:animate-[fade-out_130ms_ease]" }),
|
|
301
482
|
createVNode(unref(DialogContent), {
|
|
302
|
-
class: "fixed left-1/2 top-[12vh] z-(--z-modal) flex max-h-[76vh] w-[min(92vw,40rem)] -translate-x-1/2 flex-col overflow-hidden rounded-card border border-line
|
|
303
|
-
onOpenAutoFocus: _cache[
|
|
483
|
+
class: normalizeClass(["fixed left-1/2 top-[12vh] z-(--z-modal) flex max-h-[76vh] w-[min(92vw,40rem)] -translate-x-1/2 flex-col overflow-hidden rounded-card border border-line lp-glass-overlay shadow-panel outline-none data-[state=open]:animate-[pop-in_160ms_var(--ease-emphasized)] data-[state=closed]:animate-[pop-out_130ms_ease]", __props.previewPane && "md:h-[min(76vh,36rem)] md:w-[min(92vw,64rem)]"]),
|
|
484
|
+
onOpenAutoFocus: _cache[2] || (_cache[2] = withModifiers(() => {
|
|
304
485
|
}, ["prevent"]))
|
|
305
486
|
}, {
|
|
306
487
|
default: withCtx(() => [
|
|
307
488
|
createVNode(unref(DialogTitle), { class: "sr-only" }, {
|
|
308
|
-
default: withCtx(() => [..._cache[
|
|
489
|
+
default: withCtx(() => [..._cache[4] || (_cache[4] = [
|
|
309
490
|
createTextVNode("Command palette", -1)
|
|
310
491
|
])]),
|
|
311
492
|
_: 1
|
|
312
493
|
}),
|
|
313
494
|
createVNode(unref(DialogDescription), { class: "sr-only" }, {
|
|
314
|
-
default: withCtx(() => [..._cache[
|
|
495
|
+
default: withCtx(() => [..._cache[5] || (_cache[5] = [
|
|
315
496
|
createTextVNode("Search and run a command.", -1)
|
|
316
497
|
])]),
|
|
317
498
|
_: 1
|
|
@@ -354,6 +535,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
354
535
|
ref: inputRef,
|
|
355
536
|
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => query.value = $event),
|
|
356
537
|
type: "text",
|
|
538
|
+
role: "combobox",
|
|
539
|
+
"aria-autocomplete": "list",
|
|
540
|
+
"aria-expanded": "true",
|
|
541
|
+
"aria-controls": listId,
|
|
542
|
+
"aria-activedescendant": activeId.value,
|
|
357
543
|
placeholder: mode.value?.childPlaceholder ?? __props.placeholder,
|
|
358
544
|
class: "h-12 min-w-0 flex-1 bg-transparent text-sm text-ink outline-none placeholder:text-muted",
|
|
359
545
|
onKeydown: [
|
|
@@ -361,111 +547,214 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
361
547
|
withKeys(withModifiers(moveUp, ["prevent"]), ["up"]),
|
|
362
548
|
withKeys(withModifiers(runSelected, ["prevent"]), ["enter"]),
|
|
363
549
|
withKeys(onBackspace, ["backspace"]),
|
|
364
|
-
withKeys(onEscape, ["esc"])
|
|
550
|
+
withKeys(onEscape, ["esc"]),
|
|
551
|
+
withKeys(onTab, ["tab"])
|
|
365
552
|
]
|
|
366
553
|
}, null, 40, _hoisted_3), [
|
|
367
554
|
[vModelText, query.value]
|
|
368
555
|
]),
|
|
369
|
-
_cache[
|
|
556
|
+
_cache[6] || (_cache[6] = createElementVNode("kbd", { class: "shrink-0 rounded border border-line px-1.5 py-0.5 text-[10px] text-muted" }, "esc", -1))
|
|
370
557
|
]),
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
558
|
+
createElementVNode("div", _hoisted_4, [
|
|
559
|
+
createVNode(_sfc_main$2, {
|
|
560
|
+
ref_key: "scrollRef",
|
|
561
|
+
ref: scrollRef,
|
|
562
|
+
class: "min-h-0 min-w-0 flex-1",
|
|
563
|
+
"content-class": "p-2"
|
|
564
|
+
}, {
|
|
565
|
+
default: withCtx(() => [
|
|
566
|
+
flat.value.length === 0 && !failed.value ? (openBlock(), createElementBlock("p", _hoisted_5, toDisplayString(unref(searching) ? text.value.searching : __props.emptyText), 1)) : createCommentVNode("", true),
|
|
567
|
+
createElementVNode("div", {
|
|
568
|
+
id: listId,
|
|
569
|
+
role: "listbox"
|
|
382
570
|
}, [
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
"data-cmd-index": flatIndexOf(c),
|
|
389
|
-
disabled: c.disabled,
|
|
390
|
-
class: normalizeClass(["lp-cmd-item flex w-full items-center gap-3 rounded-md px-2.5 py-2 text-left text-sm outline-none transition-colors duration-[var(--duration-fast)] disabled:pointer-events-none disabled:opacity-45", flatIndexOf(c) === selectedIndex.value ? "bg-brand-soft text-brand" : "text-ink hover:bg-surface-soft/60"]),
|
|
391
|
-
onClick: ($event) => run(c),
|
|
392
|
-
onPointerenter: ($event) => selectedIndex.value = flatIndexOf(c)
|
|
571
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(grouped.value, (group, gi) => {
|
|
572
|
+
return openBlock(), createElementBlock("div", {
|
|
573
|
+
key: group.name,
|
|
574
|
+
role: "group",
|
|
575
|
+
"aria-labelledby": group.name ? `${listId}-g${gi}` : void 0
|
|
393
576
|
}, [
|
|
394
|
-
|
|
577
|
+
group.name ? (openBlock(), createElementBlock("div", {
|
|
578
|
+
key: 0,
|
|
579
|
+
id: `${listId}-g${gi}`,
|
|
580
|
+
class: "px-2 pb-1 pt-3 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted"
|
|
581
|
+
}, toDisplayString(group.name), 9, _hoisted_7)) : createCommentVNode("", true),
|
|
582
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(group.items, (c) => {
|
|
583
|
+
return openBlock(), createBlock(resolveDynamicComponent(c.href ? "a" : "button"), {
|
|
584
|
+
id: optionId(flatIndexOf(c)),
|
|
585
|
+
key: c.id,
|
|
586
|
+
href: c.disabled ? void 0 : c.href,
|
|
587
|
+
type: c.href ? void 0 : "button",
|
|
588
|
+
role: "option",
|
|
589
|
+
tabindex: "-1",
|
|
590
|
+
"aria-selected": flatIndexOf(c) === selectedIndex.value,
|
|
591
|
+
"aria-disabled": c.disabled || void 0,
|
|
592
|
+
"data-cmd-index": flatIndexOf(c),
|
|
593
|
+
disabled: c.href ? void 0 : c.disabled,
|
|
594
|
+
class: normalizeClass(["lp-cmd-item flex w-full gap-3 rounded-md 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", [
|
|
595
|
+
c.excerpt ? "items-start" : "items-center",
|
|
596
|
+
flatIndexOf(c) === selectedIndex.value ? "bg-brand-soft text-brand" : unref(moreOf).has(c) ? "text-muted hover:bg-surface-soft/60" : "text-ink hover:bg-surface-soft/60"
|
|
597
|
+
]]),
|
|
598
|
+
onClick: ($event) => onRowClick($event, c),
|
|
599
|
+
onPointerenter: ($event) => selectedIndex.value = flatIndexOf(c)
|
|
600
|
+
}, {
|
|
601
|
+
default: withCtx(() => [
|
|
602
|
+
c.icon ? (openBlock(), createBlock(_sfc_main$1, {
|
|
603
|
+
key: 0,
|
|
604
|
+
name: c.icon,
|
|
605
|
+
size: 16,
|
|
606
|
+
class: normalizeClass(["shrink-0", { "mt-0.5": c.excerpt }])
|
|
607
|
+
}, null, 8, ["name", "class"])) : createCommentVNode("", true),
|
|
608
|
+
createElementVNode("span", _hoisted_8, [
|
|
609
|
+
createElementVNode("span", _hoisted_9, [
|
|
610
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(highlight(c.label, c.highlight), (p, pi) => {
|
|
611
|
+
return openBlock(), createElementBlock(Fragment, {
|
|
612
|
+
key: `l${pi}`
|
|
613
|
+
}, [
|
|
614
|
+
p.hit ? (openBlock(), createElementBlock("mark", _hoisted_10, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
615
|
+
createTextVNode(toDisplayString(p.text), 1)
|
|
616
|
+
], 64))
|
|
617
|
+
], 64);
|
|
618
|
+
}), 128))
|
|
619
|
+
]),
|
|
620
|
+
c.description ? (openBlock(), createElementBlock("span", _hoisted_11, [
|
|
621
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(highlight(c.description, c.highlight), (p, pi) => {
|
|
622
|
+
return openBlock(), createElementBlock(Fragment, {
|
|
623
|
+
key: `d${pi}`
|
|
624
|
+
}, [
|
|
625
|
+
p.hit ? (openBlock(), createElementBlock("mark", _hoisted_12, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
626
|
+
createTextVNode(toDisplayString(p.text), 1)
|
|
627
|
+
], 64))
|
|
628
|
+
], 64);
|
|
629
|
+
}), 128))
|
|
630
|
+
])) : createCommentVNode("", true),
|
|
631
|
+
c.excerpt ? (openBlock(), createElementBlock("span", {
|
|
632
|
+
key: 1,
|
|
633
|
+
class: "lp-cmd-excerpt mt-1 block text-[13px] leading-snug text-ink/80",
|
|
634
|
+
style: normalizeStyle({ "-webkit-line-clamp": __props.excerptLines })
|
|
635
|
+
}, [
|
|
636
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(highlight(c.excerpt, c.highlight), (p, pi) => {
|
|
637
|
+
return openBlock(), createElementBlock(Fragment, {
|
|
638
|
+
key: `e${pi}`
|
|
639
|
+
}, [
|
|
640
|
+
p.hit ? (openBlock(), createElementBlock("mark", _hoisted_13, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
641
|
+
createTextVNode(toDisplayString(p.text), 1)
|
|
642
|
+
], 64))
|
|
643
|
+
], 64);
|
|
644
|
+
}), 128))
|
|
645
|
+
], 4)) : createCommentVNode("", true)
|
|
646
|
+
]),
|
|
647
|
+
c.shortcut ? (openBlock(), createElementBlock("kbd", _hoisted_14, toDisplayString(c.shortcut), 1)) : c.children ? (openBlock(), createBlock(_sfc_main$1, {
|
|
648
|
+
key: 2,
|
|
649
|
+
name: "lucide:chevron-right",
|
|
650
|
+
size: 14,
|
|
651
|
+
class: "shrink-0 text-muted"
|
|
652
|
+
})) : createCommentVNode("", true)
|
|
653
|
+
]),
|
|
654
|
+
_: 2
|
|
655
|
+
}, 1064, ["id", "href", "type", "aria-selected", "aria-disabled", "data-cmd-index", "disabled", "class", "onClick", "onPointerenter"]);
|
|
656
|
+
}), 128))
|
|
657
|
+
], 8, _hoisted_6);
|
|
658
|
+
}), 128))
|
|
659
|
+
]),
|
|
660
|
+
failed.value ? (openBlock(), createElementBlock("div", {
|
|
661
|
+
key: 1,
|
|
662
|
+
role: "alert",
|
|
663
|
+
class: normalizeClass(["flex items-center justify-center gap-2 px-2 text-sm text-muted", flat.value.length ? "pb-1 pt-3" : "py-10"])
|
|
664
|
+
}, [
|
|
665
|
+
createVNode(_sfc_main$1, {
|
|
666
|
+
name: "lucide:circle-alert",
|
|
667
|
+
size: 15,
|
|
668
|
+
class: "shrink-0"
|
|
669
|
+
}),
|
|
670
|
+
createElementVNode("span", null, toDisplayString(text.value.searchFailed), 1),
|
|
671
|
+
createElementVNode("button", {
|
|
672
|
+
type: "button",
|
|
673
|
+
class: "rounded-md 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",
|
|
674
|
+
onClick: _cache[1] || (_cache[1] = ($event) => {
|
|
675
|
+
refresh();
|
|
676
|
+
inputRef.value?.focus();
|
|
677
|
+
})
|
|
678
|
+
}, toDisplayString(text.value.retry), 1)
|
|
679
|
+
], 2)) : createCommentVNode("", true)
|
|
680
|
+
]),
|
|
681
|
+
_: 1
|
|
682
|
+
}, 512),
|
|
683
|
+
__props.previewPane ? (openBlock(), createElementBlock("aside", _hoisted_15, [
|
|
684
|
+
createVNode(_sfc_main$2, {
|
|
685
|
+
ref_key: "previewRef",
|
|
686
|
+
ref: previewRef,
|
|
687
|
+
class: "min-h-0 flex-1",
|
|
688
|
+
"content-class": "px-5 py-4"
|
|
689
|
+
}, {
|
|
690
|
+
default: withCtx(() => [
|
|
691
|
+
active.value ? renderSlot(_ctx.$slots, "preview", {
|
|
692
|
+
key: 0,
|
|
693
|
+
command: active.value
|
|
694
|
+
}, () => [
|
|
695
|
+
createElementVNode("div", _hoisted_16, [
|
|
696
|
+
active.value.icon ? (openBlock(), createBlock(_sfc_main$1, {
|
|
395
697
|
key: 0,
|
|
396
|
-
name:
|
|
698
|
+
name: active.value.icon,
|
|
397
699
|
size: 16,
|
|
398
|
-
class: "shrink-0"
|
|
399
|
-
}, null, 8, ["name"])) : createCommentVNode("", true),
|
|
400
|
-
createElementVNode("span", _hoisted_7, [
|
|
401
|
-
createElementVNode("span", _hoisted_8, [
|
|
402
|
-
(openBlock(true), createElementBlock(Fragment, null, renderList(highlight(c.label), (p, pi) => {
|
|
403
|
-
return openBlock(), createElementBlock(Fragment, {
|
|
404
|
-
key: `l${pi}`
|
|
405
|
-
}, [
|
|
406
|
-
p.hit ? (openBlock(), createElementBlock("mark", _hoisted_9, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
407
|
-
createTextVNode(toDisplayString(p.text), 1)
|
|
408
|
-
], 64))
|
|
409
|
-
], 64);
|
|
410
|
-
}), 128))
|
|
411
|
-
]),
|
|
412
|
-
c.description ? (openBlock(), createElementBlock("span", _hoisted_10, [
|
|
413
|
-
(openBlock(true), createElementBlock(Fragment, null, renderList(highlight(c.description), (p, pi) => {
|
|
414
|
-
return openBlock(), createElementBlock(Fragment, {
|
|
415
|
-
key: `d${pi}`
|
|
416
|
-
}, [
|
|
417
|
-
p.hit ? (openBlock(), createElementBlock("mark", _hoisted_11, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
418
|
-
createTextVNode(toDisplayString(p.text), 1)
|
|
419
|
-
], 64))
|
|
420
|
-
], 64);
|
|
421
|
-
}), 128))
|
|
422
|
-
])) : createCommentVNode("", true)
|
|
423
|
-
]),
|
|
424
|
-
c.shortcut ? (openBlock(), createElementBlock("kbd", _hoisted_12, toDisplayString(c.shortcut), 1)) : c.children ? (openBlock(), createBlock(_sfc_main$1, {
|
|
425
|
-
key: 2,
|
|
426
|
-
name: "lucide:chevron-right",
|
|
427
|
-
size: 14,
|
|
428
700
|
class: "shrink-0 text-muted"
|
|
429
|
-
})) : createCommentVNode("", true)
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
701
|
+
}, null, 8, ["name"])) : createCommentVNode("", true),
|
|
702
|
+
createElementVNode("h3", _hoisted_17, toDisplayString(active.value.label), 1)
|
|
703
|
+
]),
|
|
704
|
+
active.value.description ? (openBlock(), createElementBlock("p", _hoisted_18, toDisplayString(active.value.description), 1)) : createCommentVNode("", true),
|
|
705
|
+
active.value.preview || active.value.excerpt ? (openBlock(), createElementBlock("p", _hoisted_19, [
|
|
706
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(highlight(active.value.preview ?? active.value.excerpt ?? "", active.value.highlight), (p, pi) => {
|
|
707
|
+
return openBlock(), createElementBlock(Fragment, {
|
|
708
|
+
key: `p${pi}`
|
|
709
|
+
}, [
|
|
710
|
+
p.hit ? (openBlock(), createElementBlock("mark", _hoisted_20, toDisplayString(p.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
711
|
+
createTextVNode(toDisplayString(p.text), 1)
|
|
712
|
+
], 64))
|
|
713
|
+
], 64);
|
|
714
|
+
}), 128))
|
|
715
|
+
])) : (openBlock(), createElementBlock("p", _hoisted_21, toDisplayString(text.value.noPreview), 1))
|
|
716
|
+
], true) : createCommentVNode("", true)
|
|
717
|
+
]),
|
|
718
|
+
_: 3
|
|
719
|
+
}, 512)
|
|
720
|
+
])) : createCommentVNode("", true)
|
|
721
|
+
]),
|
|
722
|
+
createElementVNode("div", _hoisted_22, [
|
|
723
|
+
createElementVNode("span", _hoisted_23, [
|
|
724
|
+
_cache[7] || (_cache[7] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "↑", -1)),
|
|
725
|
+
_cache[8] || (_cache[8] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "↓", -1)),
|
|
441
726
|
createTextVNode(" " + toDisplayString(text.value.navigate), 1)
|
|
442
727
|
]),
|
|
443
|
-
createElementVNode("span",
|
|
444
|
-
_cache[
|
|
728
|
+
createElementVNode("span", _hoisted_24, [
|
|
729
|
+
_cache[9] || (_cache[9] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "↵", -1)),
|
|
445
730
|
createTextVNode(" " + toDisplayString(text.value.select), 1)
|
|
446
731
|
]),
|
|
447
|
-
|
|
448
|
-
_cache[
|
|
732
|
+
selectedActions.value.length ? (openBlock(), createElementBlock("span", _hoisted_25, [
|
|
733
|
+
_cache[10] || (_cache[10] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "tab", -1)),
|
|
734
|
+
createTextVNode(" " + toDisplayString(text.value.actions), 1)
|
|
735
|
+
])) : createCommentVNode("", true),
|
|
736
|
+
trail.value.length ? (openBlock(), createElementBlock("span", _hoisted_26, [
|
|
737
|
+
_cache[11] || (_cache[11] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "⌫", -1)),
|
|
449
738
|
createTextVNode(" " + toDisplayString(text.value.back), 1)
|
|
450
739
|
])) : createCommentVNode("", true),
|
|
451
|
-
createElementVNode("span",
|
|
452
|
-
_cache[
|
|
740
|
+
createElementVNode("span", _hoisted_27, [
|
|
741
|
+
_cache[12] || (_cache[12] = createElementVNode("kbd", { class: "rounded border border-line px-1 text-[10px]" }, "esc", -1)),
|
|
453
742
|
createTextVNode(" " + toDisplayString(text.value.close), 1)
|
|
454
743
|
])
|
|
455
744
|
])
|
|
456
745
|
]),
|
|
457
|
-
_:
|
|
458
|
-
})
|
|
746
|
+
_: 3
|
|
747
|
+
}, 8, ["class"])
|
|
459
748
|
]),
|
|
460
|
-
_:
|
|
749
|
+
_: 3
|
|
461
750
|
})
|
|
462
751
|
]),
|
|
463
|
-
_:
|
|
752
|
+
_: 3
|
|
464
753
|
}, 8, ["open"]);
|
|
465
754
|
};
|
|
466
755
|
}
|
|
467
756
|
});
|
|
468
|
-
const LpCommandPalette = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
757
|
+
const LpCommandPalette = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-2a5d3558"]]);
|
|
469
758
|
export {
|
|
470
759
|
LpCommandPalette as default
|
|
471
760
|
};
|