@mantine-vue/spotlight 1.1.2

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/esm/index.mjs ADDED
@@ -0,0 +1,991 @@
1
+ import { createStore } from "@mantine-vue/store";
2
+ import { computed, defineComponent, h, inject, onBeforeUnmount, onMounted, provide, ref, watch } from "vue";
3
+ import { Box, Highlight, Input, Modal, ScrollAreaAutosize, UnstyledButton, getDefaultZIndex, rem, useProps, useStyles } from "@mantine-vue/core";
4
+ import { useHotkeys, useId } from "@mantine-vue/hooks";
5
+ //#region src/spotlight.store.ts
6
+ function clamp(value, min, max) {
7
+ return Math.min(max, Math.max(min, value));
8
+ }
9
+ var createSpotlightStore = () => createStore({
10
+ opened: false,
11
+ empty: false,
12
+ selected: -1,
13
+ listId: "",
14
+ query: "",
15
+ registeredActions: /* @__PURE__ */ new Set()
16
+ });
17
+ var useSpotlight = (store) => store.value;
18
+ function updateSpotlightStateAction(update, store) {
19
+ const state = store.getState();
20
+ store.setState({
21
+ ...state,
22
+ ...update(store.getState())
23
+ });
24
+ }
25
+ function openSpotlightAction(store) {
26
+ updateSpotlightStateAction(() => ({
27
+ opened: true,
28
+ selected: -1
29
+ }), store);
30
+ }
31
+ function closeSpotlightAction(store) {
32
+ updateSpotlightStateAction(() => ({ opened: false }), store);
33
+ }
34
+ function toggleSpotlightAction(store) {
35
+ updateSpotlightStateAction((state) => ({
36
+ opened: !state.opened,
37
+ selected: state.opened ? state.selected : -1
38
+ }), store);
39
+ }
40
+ function setSelectedAction(index, store) {
41
+ store.setState((state) => ({
42
+ ...state,
43
+ selected: index
44
+ }));
45
+ }
46
+ function setListId(id, store) {
47
+ store.setState((state) => ({
48
+ ...state,
49
+ listId: id
50
+ }));
51
+ }
52
+ function findElementByQuerySelector(selector, root = document) {
53
+ const element = root.querySelector(selector);
54
+ if (element) return element;
55
+ const children = root instanceof ShadowRoot ? root.host.children : root.children;
56
+ for (let i = 0; i < children.length; i += 1) {
57
+ const child = children[i];
58
+ if (child.shadowRoot) {
59
+ const shadowElement = findElementByQuerySelector(selector, child.shadowRoot);
60
+ if (shadowElement) return shadowElement;
61
+ }
62
+ const nestedElement = findElementByQuerySelector(selector, child);
63
+ if (nestedElement) return nestedElement;
64
+ }
65
+ return null;
66
+ }
67
+ function selectAction(index, store) {
68
+ const state = store.getState();
69
+ const actionsList = state.listId ? findElementByQuerySelector(`#${state.listId}`) : null;
70
+ const selected = actionsList?.querySelector("[data-selected]");
71
+ const actions = actionsList?.querySelectorAll("[data-action]") ?? [];
72
+ const selectedIndex = clamp(index === -1 ? actions.length - 1 : index === actions.length ? 0 : index, 0, actions.length - 1);
73
+ selected?.removeAttribute("data-selected");
74
+ actions[selectedIndex]?.scrollIntoView?.({ block: "nearest" });
75
+ actions[selectedIndex]?.setAttribute("data-selected", "true");
76
+ setSelectedAction(selectedIndex, store);
77
+ return selectedIndex;
78
+ }
79
+ function selectNextAction(store) {
80
+ return selectAction(store.getState().selected + 1, store);
81
+ }
82
+ function selectPreviousAction(store) {
83
+ return selectAction(store.getState().selected - 1, store);
84
+ }
85
+ function triggerSelectedAction(store) {
86
+ const state = store.getState();
87
+ (state.listId ? findElementByQuerySelector(`#${state.listId} [data-selected]`) : null)?.click();
88
+ }
89
+ function registerAction(id, store) {
90
+ const state = store.getState();
91
+ state.registeredActions.add(id);
92
+ return () => {
93
+ state.registeredActions.delete(id);
94
+ };
95
+ }
96
+ function setQuery(query, store) {
97
+ updateSpotlightStateAction(() => ({ query }), store);
98
+ Promise.resolve().then(() => {
99
+ selectAction(0, store);
100
+ updateSpotlightStateAction((state) => ({ empty: state.query.trim().length > 0 && state.registeredActions.size === 0 || false }), store);
101
+ });
102
+ }
103
+ function clearSpotlightState({ clearQuery }, store) {
104
+ store.setState((state) => ({
105
+ ...state,
106
+ selected: -1,
107
+ query: clearQuery ? "" : state.query,
108
+ empty: clearQuery ? false : state.empty
109
+ }));
110
+ }
111
+ var spotlightActions = {
112
+ open: openSpotlightAction,
113
+ close: closeSpotlightAction,
114
+ toggle: toggleSpotlightAction,
115
+ updateState: updateSpotlightStateAction,
116
+ setSelectedAction,
117
+ setListId,
118
+ selectAction,
119
+ selectNextAction,
120
+ selectPreviousAction,
121
+ triggerSelectedAction,
122
+ registerAction,
123
+ setQuery,
124
+ clearSpotlightState
125
+ };
126
+ function createSpotlight() {
127
+ const store = createSpotlightStore();
128
+ return [store, {
129
+ open: () => openSpotlightAction(store),
130
+ close: () => closeSpotlightAction(store),
131
+ toggle: () => toggleSpotlightAction(store)
132
+ }];
133
+ }
134
+ var [spotlightStore, spotlight] = createSpotlight();
135
+ var { open: openSpotlight, close: closeSpotlight, toggle: toggleSpotlight } = spotlight;
136
+ //#endregion
137
+ //#region src/is-actions-group.ts
138
+ function isActionsGroup(item) {
139
+ const group = item;
140
+ return group.group !== void 0 && Array.isArray(group.actions);
141
+ }
142
+ //#endregion
143
+ //#region src/default-spotlight-filter.ts
144
+ function getKeywords(keywords) {
145
+ if (Array.isArray(keywords)) return keywords.map((keyword) => keyword.trim()).join(",").toLowerCase().trim();
146
+ if (typeof keywords === "string") return keywords.toLowerCase().trim();
147
+ return "";
148
+ }
149
+ function getFlatActions(data) {
150
+ return data.reduce((acc, item) => {
151
+ if ("actions" in item) return [...acc, ...item.actions.map((action) => ({
152
+ ...action,
153
+ group: item.group
154
+ }))];
155
+ return [...acc, item];
156
+ }, []);
157
+ }
158
+ function flatActionsToGroups(data) {
159
+ const groups = {};
160
+ const result = [];
161
+ data.forEach((action) => {
162
+ if (action.group) {
163
+ if (!groups[action.group]) groups[action.group] = {
164
+ pushed: false,
165
+ data: {
166
+ group: action.group,
167
+ actions: []
168
+ }
169
+ };
170
+ groups[action.group].data.actions.push(action);
171
+ if (!groups[action.group].pushed) {
172
+ groups[action.group].pushed = true;
173
+ result.push(groups[action.group].data);
174
+ }
175
+ } else result.push(action);
176
+ });
177
+ return result;
178
+ }
179
+ var defaultSpotlightFilter = (_query, data) => {
180
+ const query = _query.trim().toLowerCase();
181
+ const priorityMatrix = [[], []];
182
+ getFlatActions(data).forEach((item) => {
183
+ if (item.label?.toLowerCase().includes(query)) priorityMatrix[0].push(item);
184
+ else if (item.description?.toLowerCase().includes(query) || getKeywords(item.keywords).includes(query)) priorityMatrix[1].push(item);
185
+ });
186
+ return flatActionsToGroups(priorityMatrix.flat());
187
+ };
188
+ //#endregion
189
+ //#region src/limit-actions.ts
190
+ function limitActions(actions, limit) {
191
+ if (!Array.isArray(actions)) return [];
192
+ let count = 0;
193
+ return actions.reduce((acc, item) => {
194
+ if (count >= limit) return acc;
195
+ if (isActionsGroup(item)) {
196
+ const groupActions = limitActions(item.actions, limit - count);
197
+ acc.push({
198
+ group: item.group,
199
+ actions: groupActions
200
+ });
201
+ count += groupActions.length;
202
+ } else {
203
+ acc.push(item);
204
+ count += 1;
205
+ }
206
+ return acc;
207
+ }, []);
208
+ }
209
+ //#endregion
210
+ //#region src/Spotlight.context.ts
211
+ var SpotlightContextKey = Symbol("SpotlightContext");
212
+ function provideSpotlightContext(value) {
213
+ provide(SpotlightContextKey, value);
214
+ }
215
+ function useSpotlightContext() {
216
+ const ctx = inject(SpotlightContextKey, null);
217
+ if (ctx === null) throw new Error("Spotlight component was not found in tree");
218
+ return ctx;
219
+ }
220
+ //#endregion
221
+ //#region src/style-api.ts
222
+ function mergeClassNames(...items) {
223
+ return items.reduce((acc, item) => {
224
+ if (!item || typeof item !== "object" || Array.isArray(item)) return acc;
225
+ Object.entries(item).forEach(([key, value]) => {
226
+ acc[key] = acc[key] ? [acc[key], value] : value;
227
+ });
228
+ return acc;
229
+ }, {});
230
+ }
231
+ function mergeStyles(...items) {
232
+ return items.reduce((acc, item) => {
233
+ if (!item || typeof item !== "object" || Array.isArray(item)) return acc;
234
+ Object.entries(item).forEach(([key, value]) => {
235
+ acc[key] = acc[key] ? [acc[key], value] : value;
236
+ });
237
+ return acc;
238
+ }, {});
239
+ }
240
+ function renderContent$1(value) {
241
+ return typeof value === "function" ? value() : value;
242
+ }
243
+ var Spotlight_module_default = {
244
+ root: "_root_87n7g_1",
245
+ content: "_content_87n7g_7",
246
+ body: "_body_87n7g_13",
247
+ search: "_search_87n7g_19",
248
+ actionsList: "_actionsList_87n7g_24",
249
+ action: "_action_87n7g_24",
250
+ actionBody: "_actionBody_87n7g_73",
251
+ actionSection: "_actionSection_87n7g_77",
252
+ actionLabel: "_actionLabel_87n7g_99",
253
+ actionDescription: "_actionDescription_87n7g_103",
254
+ empty: "_empty_87n7g_110",
255
+ footer: "_footer_87n7g_116",
256
+ actionsGroup: "_actionsGroup_87n7g_129"
257
+ };
258
+ //#endregion
259
+ //#region src/SpotlightAction.ts
260
+ var defaultProps$3 = {
261
+ dimmedSections: true,
262
+ highlightQuery: false
263
+ };
264
+ var SpotlightAction = defineComponent({
265
+ name: "SpotlightAction",
266
+ inheritAttrs: false,
267
+ props: {
268
+ label: {
269
+ type: String,
270
+ default: void 0
271
+ },
272
+ description: {
273
+ type: String,
274
+ default: void 0
275
+ },
276
+ leftSection: {
277
+ type: [
278
+ String,
279
+ Number,
280
+ Object,
281
+ Function
282
+ ],
283
+ default: void 0
284
+ },
285
+ rightSection: {
286
+ type: [
287
+ String,
288
+ Number,
289
+ Object,
290
+ Function
291
+ ],
292
+ default: void 0
293
+ },
294
+ dimmedSections: {
295
+ type: Boolean,
296
+ default: void 0
297
+ },
298
+ highlightQuery: {
299
+ type: Boolean,
300
+ default: void 0
301
+ },
302
+ highlightColor: {
303
+ type: String,
304
+ default: void 0
305
+ },
306
+ closeSpotlightOnTrigger: {
307
+ type: Boolean,
308
+ default: void 0
309
+ },
310
+ keywords: {
311
+ type: [String, Array],
312
+ default: void 0
313
+ },
314
+ classNames: {
315
+ type: [Object, Function],
316
+ default: void 0
317
+ },
318
+ styles: {
319
+ type: [Object, Function],
320
+ default: void 0
321
+ },
322
+ vars: {
323
+ type: [Object, Function],
324
+ default: void 0
325
+ }
326
+ },
327
+ setup(rawProps, { attrs, slots }) {
328
+ const props = useProps("SpotlightAction", defaultProps$3, rawProps);
329
+ const ctx = useSpotlightContext();
330
+ return () => {
331
+ const stylesApi = {
332
+ classNames: props.classNames,
333
+ styles: props.styles
334
+ };
335
+ const labelNode = props.highlightQuery && typeof props.label === "string" ? h(Highlight, {
336
+ component: "span",
337
+ highlight: ctx.query,
338
+ color: props.highlightColor,
339
+ ...ctx.getStyles("actionLabel", stylesApi)
340
+ }, () => props.label) : h("span", ctx.getStyles("actionLabel", stylesApi), props.label);
341
+ return h(UnstyledButton, {
342
+ ...attrs,
343
+ "data-action": true,
344
+ ...ctx.getStyles("action", {
345
+ className: attrs.class,
346
+ style: attrs.style,
347
+ ...stylesApi
348
+ }),
349
+ onMousedown: (event) => {
350
+ event.preventDefault();
351
+ attrs.onMousedown?.(event);
352
+ },
353
+ onClick: (event) => {
354
+ attrs.onClick?.(event);
355
+ if (props.closeSpotlightOnTrigger ?? ctx.closeOnActionTrigger) spotlightActions.close(ctx.store);
356
+ },
357
+ tabindex: -1
358
+ }, () => slots.default?.() ?? [
359
+ props.leftSection ? h(Box, {
360
+ component: "span",
361
+ mod: {
362
+ position: "left",
363
+ dimmed: props.dimmedSections
364
+ },
365
+ ...ctx.getStyles("actionSection", stylesApi)
366
+ }, () => renderContent$1(props.leftSection)) : null,
367
+ h("span", ctx.getStyles("actionBody", stylesApi), [labelNode, h("span", ctx.getStyles("actionDescription", stylesApi), props.description)]),
368
+ props.rightSection ? h(Box, {
369
+ component: "span",
370
+ mod: {
371
+ position: "right",
372
+ dimmed: props.dimmedSections
373
+ },
374
+ ...ctx.getStyles("actionSection", stylesApi)
375
+ }, () => renderContent$1(props.rightSection)) : null
376
+ ]);
377
+ };
378
+ }
379
+ });
380
+ Object.assign(SpotlightAction, { classes: Spotlight_module_default });
381
+ //#endregion
382
+ //#region src/SpotlightActionsGroup.ts
383
+ var SpotlightActionsGroup = defineComponent({
384
+ name: "SpotlightActionsGroup",
385
+ inheritAttrs: false,
386
+ props: {
387
+ label: {
388
+ type: String,
389
+ default: void 0
390
+ },
391
+ classNames: {
392
+ type: [Object, Function],
393
+ default: void 0
394
+ },
395
+ styles: {
396
+ type: [Object, Function],
397
+ default: void 0
398
+ },
399
+ vars: {
400
+ type: [Object, Function],
401
+ default: void 0
402
+ }
403
+ },
404
+ setup(rawProps, { attrs, slots }) {
405
+ const props = useProps("SpotlightActionsGroup", null, rawProps);
406
+ const ctx = useSpotlightContext();
407
+ return () => h(Box, {
408
+ ...attrs,
409
+ ...ctx.getStyles("actionsGroup", {
410
+ className: attrs.class,
411
+ style: attrs.style,
412
+ classNames: props.classNames,
413
+ styles: props.styles
414
+ }),
415
+ style: [
416
+ ctx.getStyles("actionsGroup", { styles: props.styles }).style,
417
+ attrs.style,
418
+ { "--spotlight-label": `'${props.label?.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'` }
419
+ ]
420
+ }, () => slots.default?.());
421
+ }
422
+ });
423
+ Object.assign(SpotlightActionsGroup, { classes: Spotlight_module_default });
424
+ //#endregion
425
+ //#region src/SpotlightActionsList.ts
426
+ var SpotlightActionsList = defineComponent({
427
+ name: "SpotlightActionsList",
428
+ inheritAttrs: false,
429
+ props: {
430
+ id: {
431
+ type: String,
432
+ default: void 0
433
+ },
434
+ classNames: {
435
+ type: [Object, Function],
436
+ default: void 0
437
+ },
438
+ styles: {
439
+ type: [Object, Function],
440
+ default: void 0
441
+ },
442
+ vars: {
443
+ type: [Object, Function],
444
+ default: void 0
445
+ }
446
+ },
447
+ setup(rawProps, { attrs, slots }) {
448
+ const props = useProps("SpotlightActionsList", null, rawProps);
449
+ const ctx = useSpotlightContext();
450
+ const generatedId = useId();
451
+ const listId = props.id || `mantine-${generatedId.value.replace(/:/g, "")}`;
452
+ onMounted(() => spotlightActions.setListId(listId, ctx.store));
453
+ onBeforeUnmount(() => spotlightActions.setListId("", ctx.store));
454
+ return () => h(ScrollAreaAutosize, {
455
+ ...attrs,
456
+ ...ctx.getStyles("actionsList", {
457
+ className: attrs.class,
458
+ style: attrs.style,
459
+ classNames: props.classNames,
460
+ styles: props.styles
461
+ }),
462
+ type: "scroll",
463
+ scrollbarSize: "var(--spotlight-actions-list-padding)",
464
+ offsetScrollbars: "y",
465
+ id: listId
466
+ }, () => slots.default?.());
467
+ }
468
+ });
469
+ Object.assign(SpotlightActionsList, { classes: Spotlight_module_default });
470
+ //#endregion
471
+ //#region src/SpotlightEmpty.ts
472
+ var SpotlightEmpty = defineComponent({
473
+ name: "SpotlightEmpty",
474
+ inheritAttrs: false,
475
+ props: {
476
+ classNames: {
477
+ type: [Object, Function],
478
+ default: void 0
479
+ },
480
+ styles: {
481
+ type: [Object, Function],
482
+ default: void 0
483
+ },
484
+ vars: {
485
+ type: [Object, Function],
486
+ default: void 0
487
+ }
488
+ },
489
+ setup(rawProps, { attrs, slots }) {
490
+ const props = useProps("SpotlightEmpty", null, rawProps);
491
+ const ctx = useSpotlightContext();
492
+ return () => h(Box, {
493
+ ...attrs,
494
+ ...ctx.getStyles("empty", {
495
+ className: attrs.class,
496
+ style: attrs.style,
497
+ classNames: props.classNames,
498
+ styles: props.styles
499
+ })
500
+ }, () => slots.default?.());
501
+ }
502
+ });
503
+ Object.assign(SpotlightEmpty, { classes: Spotlight_module_default });
504
+ //#endregion
505
+ //#region src/SpotlightFooter.ts
506
+ var SpotlightFooter = defineComponent({
507
+ name: "SpotlightFooter",
508
+ inheritAttrs: false,
509
+ props: {
510
+ classNames: {
511
+ type: [Object, Function],
512
+ default: void 0
513
+ },
514
+ styles: {
515
+ type: [Object, Function],
516
+ default: void 0
517
+ },
518
+ vars: {
519
+ type: [Object, Function],
520
+ default: void 0
521
+ }
522
+ },
523
+ setup(rawProps, { attrs, slots }) {
524
+ const props = useProps("SpotlightFooter", null, rawProps);
525
+ const ctx = useSpotlightContext();
526
+ return () => h(Box, {
527
+ ...attrs,
528
+ ...ctx.getStyles("footer", {
529
+ className: attrs.class,
530
+ style: attrs.style,
531
+ classNames: props.classNames,
532
+ styles: props.styles
533
+ })
534
+ }, () => slots.default?.());
535
+ }
536
+ });
537
+ Object.assign(SpotlightFooter, { classes: Spotlight_module_default });
538
+ //#endregion
539
+ //#region src/get-hotkeys.ts
540
+ function getHotkeys(hotkeys, store) {
541
+ if (!hotkeys) return [];
542
+ const open = () => spotlightActions.open(store);
543
+ if (Array.isArray(hotkeys)) return hotkeys.map((hotkey) => [hotkey, open]);
544
+ return [[hotkeys, open]];
545
+ }
546
+ //#endregion
547
+ //#region src/SpotlightRoot.ts
548
+ var defaultProps$2 = {
549
+ size: 600,
550
+ yOffset: 80,
551
+ zIndex: getDefaultZIndex("max"),
552
+ overlayProps: {
553
+ backgroundOpacity: .35,
554
+ blur: 7
555
+ },
556
+ transitionProps: {
557
+ duration: 200,
558
+ transition: "pop"
559
+ },
560
+ store: spotlightStore,
561
+ clearQueryOnClose: true,
562
+ closeOnActionTrigger: true,
563
+ shortcut: "mod + K",
564
+ maxHeight: 400
565
+ };
566
+ var SpotlightRoot = defineComponent({
567
+ name: "SpotlightRoot",
568
+ inheritAttrs: false,
569
+ props: {
570
+ store: {
571
+ type: Object,
572
+ default: void 0
573
+ },
574
+ query: {
575
+ type: String,
576
+ default: void 0
577
+ },
578
+ onQueryChange: {
579
+ type: Function,
580
+ default: void 0
581
+ },
582
+ clearQueryOnClose: {
583
+ type: Boolean,
584
+ default: void 0
585
+ },
586
+ shortcut: {
587
+ type: [
588
+ String,
589
+ Array,
590
+ null
591
+ ],
592
+ default: void 0
593
+ },
594
+ tagsToIgnore: {
595
+ type: Array,
596
+ default: void 0
597
+ },
598
+ triggerOnContentEditable: {
599
+ type: Boolean,
600
+ default: void 0
601
+ },
602
+ disabled: {
603
+ type: Boolean,
604
+ default: false
605
+ },
606
+ onSpotlightOpen: {
607
+ type: Function,
608
+ default: void 0
609
+ },
610
+ onSpotlightClose: {
611
+ type: Function,
612
+ default: void 0
613
+ },
614
+ forceOpened: {
615
+ type: Boolean,
616
+ default: false
617
+ },
618
+ closeOnActionTrigger: {
619
+ type: Boolean,
620
+ default: void 0
621
+ },
622
+ maxHeight: {
623
+ type: [String, Number],
624
+ default: void 0
625
+ },
626
+ scrollable: {
627
+ type: Boolean,
628
+ default: false
629
+ },
630
+ classNames: {
631
+ type: [Object, Function],
632
+ default: void 0
633
+ },
634
+ styles: {
635
+ type: [Object, Function],
636
+ default: void 0
637
+ },
638
+ vars: {
639
+ type: [Object, Function],
640
+ default: void 0
641
+ },
642
+ unstyled: {
643
+ type: Boolean,
644
+ default: false
645
+ }
646
+ },
647
+ setup(rawProps, { attrs, slots }) {
648
+ const props = useProps("SpotlightRoot", defaultProps$2, rawProps);
649
+ const state = useSpotlight(props.store);
650
+ const previousOpened = ref(state.value.opened);
651
+ const currentQuery = computed(() => typeof props.query === "string" ? props.query : state.value.query);
652
+ const setQuery = (query) => {
653
+ props.onQueryChange?.(query);
654
+ spotlightActions.setQuery(query, props.store);
655
+ };
656
+ const getStyles = useStyles({
657
+ name: "Spotlight",
658
+ classes: Spotlight_module_default,
659
+ props,
660
+ className: attrs.class,
661
+ style: attrs.style,
662
+ classNames: props.classNames,
663
+ styles: props.styles,
664
+ unstyled: props.unstyled,
665
+ vars: props.vars
666
+ });
667
+ provideSpotlightContext({
668
+ get query() {
669
+ return currentQuery.value;
670
+ },
671
+ setQuery,
672
+ getStyles,
673
+ store: props.store,
674
+ get closeOnActionTrigger() {
675
+ return props.closeOnActionTrigger;
676
+ }
677
+ });
678
+ useHotkeys(() => getHotkeys(props.shortcut, props.store), () => props.tagsToIgnore, () => props.triggerOnContentEditable);
679
+ watch(() => state.value.opened, (opened) => {
680
+ if (opened === previousOpened.value) return;
681
+ if (opened) props.onSpotlightOpen?.();
682
+ else props.onSpotlightClose?.();
683
+ previousOpened.value = opened;
684
+ });
685
+ return () => {
686
+ if (props.disabled) return null;
687
+ const rootStyles = getStyles("root", {
688
+ className: attrs.class,
689
+ style: attrs.style
690
+ });
691
+ const { classNames: _classNames, styles: _styles, vars: _vars, unstyled: _unstyled, store: _store, query: _query, onQueryChange: _onQueryChange, clearQueryOnClose: _clearQueryOnClose, shortcut: _shortcut, tagsToIgnore: _tagsToIgnore, triggerOnContentEditable: _triggerOnContentEditable, disabled: _disabled, onSpotlightOpen: _onSpotlightOpen, onSpotlightClose: _onSpotlightClose, forceOpened: _forceOpened, closeOnActionTrigger: _closeOnActionTrigger, maxHeight: _maxHeight, scrollable: _scrollable, ...modalAttrs } = {
692
+ ...attrs,
693
+ ...props
694
+ };
695
+ return h(Modal, {
696
+ ...modalAttrs,
697
+ withCloseButton: false,
698
+ opened: state.value.opened || !!props.forceOpened,
699
+ padding: 0,
700
+ onClose: () => spotlightActions.close(props.store),
701
+ class: rootStyles.class,
702
+ style: rootStyles.style,
703
+ classNames: mergeClassNames({
704
+ body: Spotlight_module_default.body,
705
+ content: Spotlight_module_default.content
706
+ }, props.classNames),
707
+ styles: mergeStyles(props.styles),
708
+ vars: mergeStyles({ root: { "--spotlight-max-height": props.scrollable ? rem(props.maxHeight) : void 0 } }, props.vars),
709
+ onExitTransitionEnd: () => {
710
+ if (props.clearQueryOnClose) setQuery("");
711
+ spotlightActions.clearSpotlightState({ clearQuery: props.clearQueryOnClose }, props.store);
712
+ props.transitionProps?.onExited?.();
713
+ props.onExitTransitionEnd?.();
714
+ },
715
+ "data-scrollable": props.scrollable || void 0
716
+ }, slots);
717
+ };
718
+ }
719
+ });
720
+ Object.assign(SpotlightRoot, { classes: Spotlight_module_default });
721
+ //#endregion
722
+ //#region src/SpotlightSearch.ts
723
+ var defaultProps$1 = { size: "lg" };
724
+ var SpotlightSearch = defineComponent({
725
+ name: "SpotlightSearch",
726
+ inheritAttrs: false,
727
+ props: {
728
+ size: {
729
+ type: [String, Number],
730
+ default: void 0
731
+ },
732
+ value: {
733
+ type: String,
734
+ default: void 0
735
+ },
736
+ onChange: {
737
+ type: Function,
738
+ default: void 0
739
+ },
740
+ onKeydown: {
741
+ type: Function,
742
+ default: void 0
743
+ },
744
+ classNames: {
745
+ type: [Object, Function],
746
+ default: void 0
747
+ },
748
+ styles: {
749
+ type: [Object, Function],
750
+ default: void 0
751
+ },
752
+ vars: {
753
+ type: [Object, Function],
754
+ default: void 0
755
+ }
756
+ },
757
+ setup(rawProps, { attrs }) {
758
+ const props = useProps("SpotlightSearch", defaultProps$1, rawProps);
759
+ const ctx = useSpotlightContext();
760
+ const isComposing = ref(false);
761
+ const handleKeydown = (event) => {
762
+ props.onKeydown?.(event);
763
+ if (isComposing.value) return;
764
+ if (event.code === "ArrowDown") {
765
+ event.preventDefault();
766
+ spotlightActions.selectNextAction(ctx.store);
767
+ }
768
+ if (event.code === "ArrowUp") {
769
+ event.preventDefault();
770
+ spotlightActions.selectPreviousAction(ctx.store);
771
+ }
772
+ if (event.code === "Enter" || event.code === "NumpadEnter") {
773
+ event.preventDefault();
774
+ spotlightActions.triggerSelectedAction(ctx.store);
775
+ }
776
+ };
777
+ return () => {
778
+ const inputStyles = ctx.getStyles("search");
779
+ return h(Input, {
780
+ ...attrs,
781
+ size: props.size,
782
+ value: props.value ?? ctx.query,
783
+ classNames: mergeClassNames({ input: inputStyles.class }, props.classNames),
784
+ styles: mergeStyles({ input: inputStyles.style }, props.styles),
785
+ vars: props.vars,
786
+ onInput: (event) => {
787
+ ctx.setQuery(event.currentTarget.value);
788
+ props.onChange?.(event);
789
+ },
790
+ onKeydown: handleKeydown,
791
+ onCompositionstart: () => {
792
+ isComposing.value = true;
793
+ },
794
+ onCompositionend: () => {
795
+ isComposing.value = false;
796
+ }
797
+ });
798
+ };
799
+ }
800
+ });
801
+ Object.assign(SpotlightSearch, { classes: Spotlight_module_default });
802
+ //#endregion
803
+ //#region src/Spotlight.ts
804
+ var defaultProps = {
805
+ size: 600,
806
+ yOffset: 80,
807
+ limit: Infinity,
808
+ zIndex: getDefaultZIndex("max"),
809
+ overlayProps: {
810
+ backgroundOpacity: .35,
811
+ blur: 7
812
+ },
813
+ transitionProps: {
814
+ duration: 200,
815
+ transition: "pop"
816
+ },
817
+ store: spotlightStore,
818
+ filter: defaultSpotlightFilter,
819
+ clearQueryOnClose: true,
820
+ closeOnActionTrigger: true,
821
+ shortcut: "mod + K"
822
+ };
823
+ function renderContent(value) {
824
+ return typeof value === "function" ? value() : value;
825
+ }
826
+ var SpotlightBase = defineComponent({
827
+ name: "Spotlight",
828
+ inheritAttrs: false,
829
+ props: {
830
+ searchProps: {
831
+ type: Object,
832
+ default: void 0
833
+ },
834
+ actions: {
835
+ type: Array,
836
+ required: true
837
+ },
838
+ filter: {
839
+ type: Function,
840
+ default: void 0
841
+ },
842
+ nothingFound: {
843
+ type: [
844
+ String,
845
+ Number,
846
+ Object,
847
+ Function
848
+ ],
849
+ default: void 0
850
+ },
851
+ highlightQuery: {
852
+ type: Boolean,
853
+ default: false
854
+ },
855
+ limit: {
856
+ type: Number,
857
+ default: void 0
858
+ },
859
+ scrollAreaProps: {
860
+ type: Object,
861
+ default: void 0
862
+ },
863
+ query: {
864
+ type: String,
865
+ default: void 0
866
+ },
867
+ onQueryChange: {
868
+ type: Function,
869
+ default: void 0
870
+ },
871
+ store: {
872
+ type: Object,
873
+ default: void 0
874
+ },
875
+ clearQueryOnClose: {
876
+ type: Boolean,
877
+ default: void 0
878
+ },
879
+ shortcut: {
880
+ type: [String, Array],
881
+ default: void 0
882
+ },
883
+ tagsToIgnore: {
884
+ type: Array,
885
+ default: void 0
886
+ },
887
+ triggerOnContentEditable: {
888
+ type: Boolean,
889
+ default: void 0
890
+ },
891
+ disabled: {
892
+ type: Boolean,
893
+ default: false
894
+ },
895
+ onSpotlightOpen: {
896
+ type: Function,
897
+ default: void 0
898
+ },
899
+ onSpotlightClose: {
900
+ type: Function,
901
+ default: void 0
902
+ },
903
+ forceOpened: {
904
+ type: Boolean,
905
+ default: false
906
+ },
907
+ closeOnActionTrigger: {
908
+ type: Boolean,
909
+ default: void 0
910
+ },
911
+ maxHeight: {
912
+ type: [String, Number],
913
+ default: void 0
914
+ },
915
+ scrollable: {
916
+ type: Boolean,
917
+ default: false
918
+ },
919
+ classNames: {
920
+ type: [Object, Function],
921
+ default: void 0
922
+ },
923
+ styles: {
924
+ type: [Object, Function],
925
+ default: void 0
926
+ },
927
+ vars: {
928
+ type: [Object, Function],
929
+ default: void 0
930
+ },
931
+ unstyled: {
932
+ type: Boolean,
933
+ default: false
934
+ }
935
+ },
936
+ setup(rawProps, { attrs }) {
937
+ const props = useProps("Spotlight", defaultProps, rawProps);
938
+ const uncontrolledQuery = ref("");
939
+ const currentQuery = computed(() => typeof props.query === "string" ? props.query : uncontrolledQuery.value);
940
+ const setQuery = (query) => {
941
+ if (typeof props.query !== "string") uncontrolledQuery.value = query;
942
+ props.onQueryChange?.(query);
943
+ };
944
+ return () => {
945
+ const renderedActions = limitActions(props.filter(currentQuery.value, props.actions), props.limit).map((item) => {
946
+ if (isActionsGroup(item)) return h(SpotlightActionsGroup, {
947
+ key: item.group,
948
+ label: item.group
949
+ }, () => item.actions.map(({ id, ...actionData }) => h(SpotlightAction, {
950
+ key: id,
951
+ highlightQuery: props.highlightQuery,
952
+ ...actionData
953
+ })));
954
+ const { id, ...actionData } = item;
955
+ return h(SpotlightAction, {
956
+ key: id,
957
+ highlightQuery: props.highlightQuery,
958
+ ...actionData
959
+ });
960
+ });
961
+ const { searchProps: _searchProps, actions: _actions, filter: _filter, nothingFound: _nothingFound, highlightQuery: _highlightQuery, limit: _limit, scrollAreaProps: _scrollAreaProps, query: _query, onQueryChange: _onQueryChange, ...rootProps } = props;
962
+ return h(SpotlightRoot, {
963
+ ...attrs,
964
+ ...rootProps,
965
+ query: currentQuery.value,
966
+ onQueryChange: setQuery
967
+ }, () => [
968
+ h(SpotlightSearch, props.searchProps),
969
+ renderedActions.length > 0 ? h(SpotlightActionsList, props.scrollAreaProps, () => renderedActions) : null,
970
+ renderedActions.length === 0 && props.nothingFound ? h(SpotlightEmpty, null, () => renderContent(props.nothingFound)) : null
971
+ ]);
972
+ };
973
+ }
974
+ });
975
+ var Spotlight = Object.assign(SpotlightBase, {
976
+ classes: Spotlight_module_default,
977
+ Search: SpotlightSearch,
978
+ ActionsList: SpotlightActionsList,
979
+ Action: SpotlightAction,
980
+ Empty: SpotlightEmpty,
981
+ Footer: SpotlightFooter,
982
+ ActionsGroup: SpotlightActionsGroup,
983
+ Root: SpotlightRoot,
984
+ open: spotlight.open,
985
+ close: spotlight.close,
986
+ toggle: spotlight.toggle
987
+ });
988
+ //#endregion
989
+ export { Spotlight, SpotlightAction, SpotlightActionsGroup, SpotlightActionsList, SpotlightEmpty, SpotlightFooter, SpotlightRoot, SpotlightSearch, closeSpotlight, createSpotlight, createSpotlightStore, isActionsGroup, openSpotlight, spotlight, toggleSpotlight, useSpotlight };
990
+
991
+ //# sourceMappingURL=index.mjs.map