@happyvertical/smrt-svelte 0.55.7 → 0.55.8
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/AGENTS.md +7 -44
- package/README.md +112 -1
- package/agents/browser-ai.md +47 -0
- package/agents/command-palette.md +85 -0
- package/agents/import-export.md +62 -0
- package/agents/overview-surfaces.md +255 -0
- package/agents/screens.md +57 -0
- package/dist/browser-ai/adapters/tts/browser-synthesis.d.ts +5 -0
- package/dist/browser-ai/adapters/tts/browser-synthesis.d.ts.map +1 -1
- package/dist/browser-ai/adapters/tts/browser-synthesis.js +83 -55
- package/dist/components/command-palette/CommandPalette.svelte +75 -0
- package/dist/components/command-palette/CommandPalette.svelte.d.ts +22 -0
- package/dist/components/command-palette/CommandPalette.svelte.d.ts.map +1 -0
- package/dist/components/command-palette/CommandPaletteDialog.svelte +406 -0
- package/dist/components/command-palette/CommandPaletteDialog.svelte.d.ts +18 -0
- package/dist/components/command-palette/CommandPaletteDialog.svelte.d.ts.map +1 -0
- package/dist/components/command-palette/CommandPaletteTrigger.svelte +91 -0
- package/dist/components/command-palette/CommandPaletteTrigger.svelte.d.ts +17 -0
- package/dist/components/command-palette/CommandPaletteTrigger.svelte.d.ts.map +1 -0
- package/dist/components/command-palette/context.d.ts +18 -0
- package/dist/components/command-palette/context.d.ts.map +1 -0
- package/dist/components/command-palette/context.js +38 -0
- package/dist/components/command-palette/controller.svelte.d.ts +70 -0
- package/dist/components/command-palette/controller.svelte.d.ts.map +1 -0
- package/dist/components/command-palette/controller.svelte.js +379 -0
- package/dist/components/command-palette/hotkeys.d.ts +30 -0
- package/dist/components/command-palette/hotkeys.d.ts.map +1 -0
- package/dist/components/command-palette/hotkeys.js +161 -0
- package/dist/components/command-palette/index.d.ts +19 -0
- package/dist/components/command-palette/index.d.ts.map +1 -0
- package/dist/components/command-palette/index.js +17 -0
- package/dist/components/command-palette/match.d.ts +38 -0
- package/dist/components/command-palette/match.d.ts.map +1 -0
- package/dist/components/command-palette/match.js +172 -0
- package/dist/components/command-palette/providers.d.ts +159 -0
- package/dist/components/command-palette/providers.d.ts.map +1 -0
- package/dist/components/command-palette/providers.js +345 -0
- package/dist/components/command-palette/rank.d.ts +20 -0
- package/dist/components/command-palette/rank.d.ts.map +1 -0
- package/dist/components/command-palette/rank.js +74 -0
- package/dist/components/command-palette/types.d.ts +119 -0
- package/dist/components/command-palette/types.d.ts.map +1 -0
- package/dist/components/command-palette/types.js +10 -0
- package/dist/components/command-palette/use-provider.svelte.d.ts +14 -0
- package/dist/components/command-palette/use-provider.svelte.d.ts.map +1 -0
- package/dist/components/command-palette/use-provider.svelte.js +23 -0
- package/dist/components/import-export/ImportExport.svelte +678 -0
- package/dist/components/import-export/ImportExport.svelte.d.ts +5 -0
- package/dist/components/import-export/ImportExport.svelte.d.ts.map +1 -0
- package/dist/components/import-export/collection-adapter.d.ts +35 -0
- package/dist/components/import-export/collection-adapter.d.ts.map +1 -0
- package/dist/components/import-export/collection-adapter.js +42 -0
- package/dist/components/import-export/csv.d.ts +60 -0
- package/dist/components/import-export/csv.d.ts.map +1 -0
- package/dist/components/import-export/csv.js +192 -0
- package/dist/components/import-export/download.d.ts +4 -0
- package/dist/components/import-export/download.d.ts.map +1 -0
- package/dist/components/import-export/download.js +17 -0
- package/dist/components/import-export/export.d.ts +25 -0
- package/dist/components/import-export/export.d.ts.map +1 -0
- package/dist/components/import-export/export.js +68 -0
- package/dist/components/import-export/fields.d.ts +48 -0
- package/dist/components/import-export/fields.d.ts.map +1 -0
- package/dist/components/import-export/fields.js +103 -0
- package/dist/components/import-export/index.d.ts +12 -0
- package/dist/components/import-export/index.d.ts.map +1 -0
- package/dist/components/import-export/index.js +9 -0
- package/dist/components/import-export/mapping.d.ts +12 -0
- package/dist/components/import-export/mapping.d.ts.map +1 -0
- package/dist/components/import-export/mapping.js +38 -0
- package/dist/components/import-export/props.d.ts +34 -0
- package/dist/components/import-export/props.d.ts.map +1 -0
- package/dist/components/import-export/props.js +1 -0
- package/dist/components/import-export/report.d.ts +13 -0
- package/dist/components/import-export/report.d.ts.map +1 -0
- package/dist/components/import-export/report.js +50 -0
- package/dist/components/import-export/runner.d.ts +17 -0
- package/dist/components/import-export/runner.d.ts.map +1 -0
- package/dist/components/import-export/runner.js +39 -0
- package/dist/components/import-export/types.d.ts +100 -0
- package/dist/components/import-export/types.d.ts.map +1 -0
- package/dist/components/import-export/types.js +6 -0
- package/dist/components/import-export/validate.d.ts +39 -0
- package/dist/components/import-export/validate.d.ts.map +1 -0
- package/dist/components/import-export/validate.js +268 -0
- package/dist/components/overview/OverviewGrid.svelte +579 -0
- package/dist/components/overview/OverviewGrid.svelte.d.ts +5 -0
- package/dist/components/overview/OverviewGrid.svelte.d.ts.map +1 -0
- package/dist/components/overview/WidgetOptionsForm.svelte +193 -0
- package/dist/components/overview/WidgetOptionsForm.svelte.d.ts +5 -0
- package/dist/components/overview/WidgetOptionsForm.svelte.d.ts.map +1 -0
- package/dist/components/overview/controller.svelte.d.ts +92 -0
- package/dist/components/overview/controller.svelte.d.ts.map +1 -0
- package/dist/components/overview/controller.svelte.js +336 -0
- package/dist/components/overview/format.d.ts +13 -0
- package/dist/components/overview/format.d.ts.map +1 -0
- package/dist/components/overview/format.js +45 -0
- package/dist/components/overview/grid-types.d.ts +52 -0
- package/dist/components/overview/grid-types.d.ts.map +1 -0
- package/dist/components/overview/grid-types.js +1 -0
- package/dist/components/overview/index.d.ts +24 -0
- package/dist/components/overview/index.d.ts.map +1 -0
- package/dist/components/overview/index.js +22 -0
- package/dist/components/overview/load.d.ts +30 -0
- package/dist/components/overview/load.d.ts.map +1 -0
- package/dist/components/overview/load.js +92 -0
- package/dist/components/overview/markdown.d.ts +53 -0
- package/dist/components/overview/markdown.d.ts.map +1 -0
- package/dist/components/overview/markdown.js +203 -0
- package/dist/components/overview/model.d.ts +100 -0
- package/dist/components/overview/model.d.ts.map +1 -0
- package/dist/components/overview/model.js +460 -0
- package/dist/components/overview/recipe-widgets.d.ts +77 -0
- package/dist/components/overview/recipe-widgets.d.ts.map +1 -0
- package/dist/components/overview/recipe-widgets.js +151 -0
- package/dist/components/overview/registry.d.ts +45 -0
- package/dist/components/overview/registry.d.ts.map +1 -0
- package/dist/components/overview/registry.js +112 -0
- package/dist/components/overview/resize.d.ts +25 -0
- package/dist/components/overview/resize.d.ts.map +1 -0
- package/dist/components/overview/resize.js +41 -0
- package/dist/components/overview/schema.d.ts +34 -0
- package/dist/components/overview/schema.d.ts.map +1 -0
- package/dist/components/overview/schema.js +180 -0
- package/dist/components/overview/server.d.ts +14 -0
- package/dist/components/overview/server.d.ts.map +1 -0
- package/dist/components/overview/server.js +13 -0
- package/dist/components/overview/types.d.ts +235 -0
- package/dist/components/overview/types.d.ts.map +1 -0
- package/dist/components/overview/types.js +17 -0
- package/dist/components/overview/widgets/ChartWidget.svelte +111 -0
- package/dist/components/overview/widgets/ChartWidget.svelte.d.ts +6 -0
- package/dist/components/overview/widgets/ChartWidget.svelte.d.ts.map +1 -0
- package/dist/components/overview/widgets/MetricWidget.svelte +86 -0
- package/dist/components/overview/widgets/MetricWidget.svelte.d.ts +6 -0
- package/dist/components/overview/widgets/MetricWidget.svelte.d.ts.map +1 -0
- package/dist/components/overview/widgets/NoteWidget.svelte +61 -0
- package/dist/components/overview/widgets/NoteWidget.svelte.d.ts +5 -0
- package/dist/components/overview/widgets/NoteWidget.svelte.d.ts.map +1 -0
- package/dist/components/overview/widgets/RecordListWidget.svelte +91 -0
- package/dist/components/overview/widgets/RecordListWidget.svelte.d.ts +6 -0
- package/dist/components/overview/widgets/RecordListWidget.svelte.d.ts.map +1 -0
- package/dist/components/overview/widgets/ShortcutsWidget.svelte +80 -0
- package/dist/components/overview/widgets/ShortcutsWidget.svelte.d.ts +6 -0
- package/dist/components/overview/widgets/ShortcutsWidget.svelte.d.ts.map +1 -0
- package/dist/components/overview/widgets/core.d.ts +44 -0
- package/dist/components/overview/widgets/core.d.ts.map +1 -0
- package/dist/components/overview/widgets/core.js +222 -0
- package/dist/components/overview/widgets/data.d.ts +76 -0
- package/dist/components/overview/widgets/data.d.ts.map +1 -0
- package/dist/components/overview/widgets/data.js +40 -0
- package/dist/components/screens/DetailScreen.svelte +220 -0
- package/dist/components/screens/DetailScreen.svelte.d.ts +5 -0
- package/dist/components/screens/DetailScreen.svelte.d.ts.map +1 -0
- package/dist/components/screens/EditForm.svelte +313 -0
- package/dist/components/screens/EditForm.svelte.d.ts +5 -0
- package/dist/components/screens/EditForm.svelte.d.ts.map +1 -0
- package/dist/components/screens/ListScreen.svelte +191 -0
- package/dist/components/screens/ListScreen.svelte.d.ts +5 -0
- package/dist/components/screens/ListScreen.svelte.d.ts.map +1 -0
- package/dist/components/screens/RecipeScreens.svelte +237 -0
- package/dist/components/screens/RecipeScreens.svelte.d.ts +5 -0
- package/dist/components/screens/RecipeScreens.svelte.d.ts.map +1 -0
- package/dist/components/screens/fields.d.ts +54 -0
- package/dist/components/screens/fields.d.ts.map +1 -0
- package/dist/components/screens/fields.js +229 -0
- package/dist/components/screens/index.d.ts +8 -0
- package/dist/components/screens/index.d.ts.map +1 -0
- package/dist/components/screens/index.js +6 -0
- package/dist/components/screens/types.d.ts +215 -0
- package/dist/components/screens/types.d.ts.map +1 -0
- package/dist/components/screens/types.js +1 -0
- package/dist/components/screens/values.d.ts +62 -0
- package/dist/components/screens/values.d.ts.map +1 -0
- package/dist/components/screens/values.js +289 -0
- package/dist/components/sortable/controller.svelte.d.ts +10 -0
- package/dist/components/sortable/controller.svelte.d.ts.map +1 -1
- package/dist/components/sortable/controller.svelte.js +29 -7
- package/dist/components/workspace/manifest-nav.d.ts +20 -0
- package/dist/components/workspace/manifest-nav.d.ts.map +1 -1
- package/dist/components/workspace/manifest-nav.js +42 -13
- package/dist/i18n/server.d.ts +6 -0
- package/dist/i18n/server.d.ts.map +1 -1
- package/dist/i18n/server.js +6 -0
- package/dist/i18n/strings.import-export.d.ts +88 -0
- package/dist/i18n/strings.import-export.d.ts.map +1 -0
- package/dist/i18n/strings.import-export.js +88 -0
- package/dist/i18n/strings.overview.d.ts +100 -0
- package/dist/i18n/strings.overview.d.ts.map +1 -0
- package/dist/i18n/strings.overview.js +107 -0
- package/dist/i18n/strings.palette.d.ts +18 -0
- package/dist/i18n/strings.palette.d.ts.map +1 -0
- package/dist/i18n/strings.palette.js +18 -0
- package/dist/i18n/strings.screens.d.ts +31 -0
- package/dist/i18n/strings.screens.d.ts.map +1 -0
- package/dist/i18n/strings.screens.js +31 -0
- package/package.json +45 -16
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* CommandPaletteDialog - the palette itself: a modal with a search box and a
|
|
4
|
+
* grouped result list, driven by a {@link CommandPaletteController}.
|
|
5
|
+
*
|
|
6
|
+
* It follows the WAI-ARIA combobox pattern: focus stays in the search box,
|
|
7
|
+
* the highlighted row is `aria-activedescendant`, Up/Down move it, Enter
|
|
8
|
+
* chooses it and Escape closes. It also installs the global shortcut
|
|
9
|
+
* (`Mod+K` by default) that toggles the palette. The shortcut works in any
|
|
10
|
+
* field because it carries a modifier; a bare key such as `/` is ignored
|
|
11
|
+
* while the user is typing.
|
|
12
|
+
*
|
|
13
|
+
* The palette comes from the `palette` prop or the nearest
|
|
14
|
+
* `setCommandPalette()` context.
|
|
15
|
+
*/
|
|
16
|
+
import { Modal } from '@happyvertical/smrt-ui/feedback';
|
|
17
|
+
import { Input } from '@happyvertical/smrt-ui/forms';
|
|
18
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
19
|
+
import { onMount, tick } from 'svelte';
|
|
20
|
+
import { M } from '../../i18n/strings.palette.js';
|
|
21
|
+
import {
|
|
22
|
+
isShellIconName,
|
|
23
|
+
SHELL_ICON_PATHS,
|
|
24
|
+
} from '../workspace/admin-shell/shell-icons.js';
|
|
25
|
+
import { palettePicker } from './context.js';
|
|
26
|
+
import type { CommandPaletteController } from './controller.svelte.js';
|
|
27
|
+
import {
|
|
28
|
+
DEFAULT_PALETTE_HOTKEYS,
|
|
29
|
+
formatPaletteHotkey,
|
|
30
|
+
isApplePlatform,
|
|
31
|
+
isPaletteHotkeyEvent,
|
|
32
|
+
type PaletteHotkey,
|
|
33
|
+
parsePaletteHotkey,
|
|
34
|
+
} from './hotkeys.js';
|
|
35
|
+
import { highlightSegments } from './match.js';
|
|
36
|
+
import type { PaletteResult } from './types.js';
|
|
37
|
+
|
|
38
|
+
interface Props {
|
|
39
|
+
/** The palette to drive; default: the one on context. */
|
|
40
|
+
palette?: CommandPaletteController;
|
|
41
|
+
/**
|
|
42
|
+
* Shortcuts that toggle the palette, e.g. `['Mod+K', '/']`. `false` installs
|
|
43
|
+
* none (open it from your own control).
|
|
44
|
+
*/
|
|
45
|
+
hotkeys?: readonly string[] | false;
|
|
46
|
+
/** Accessible name of the dialog. */
|
|
47
|
+
label?: string;
|
|
48
|
+
/** Search box placeholder. */
|
|
49
|
+
placeholder?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let {
|
|
53
|
+
palette: paletteProp,
|
|
54
|
+
hotkeys = DEFAULT_PALETTE_HOTKEYS,
|
|
55
|
+
label,
|
|
56
|
+
placeholder,
|
|
57
|
+
}: Props = $props();
|
|
58
|
+
|
|
59
|
+
const { t } = useI18n();
|
|
60
|
+
const pick = palettePicker(() => paletteProp);
|
|
61
|
+
const palette = $derived(pick());
|
|
62
|
+
const uid = $props.id();
|
|
63
|
+
const listId = `smrt-palette-list-${uid}`;
|
|
64
|
+
const optionId = (result: PaletteResult) =>
|
|
65
|
+
`smrt-palette-opt-${uid}-${result.key.replace(/[^a-zA-Z0-9_-]/g, '_')}`;
|
|
66
|
+
|
|
67
|
+
const parsed: PaletteHotkey[] = $derived(
|
|
68
|
+
hotkeys === false
|
|
69
|
+
? []
|
|
70
|
+
: hotkeys.flatMap((spec) => {
|
|
71
|
+
const hotkey = parsePaletteHotkey(spec);
|
|
72
|
+
return hotkey ? [hotkey] : [];
|
|
73
|
+
}),
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
let apple = $state(false);
|
|
77
|
+
onMount(() => {
|
|
78
|
+
apple = isApplePlatform();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
let input: { focus(): void } | undefined = $state();
|
|
82
|
+
|
|
83
|
+
function onWindowKeydown(event: KeyboardEvent) {
|
|
84
|
+
if (!isPaletteHotkeyEvent(event, parsed)) return;
|
|
85
|
+
event.preventDefault();
|
|
86
|
+
palette.toggle();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
$effect(() => {
|
|
90
|
+
if (!palette.isOpen) return;
|
|
91
|
+
void tick().then(() => input?.focus());
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const active = $derived(palette.active);
|
|
95
|
+
const hasRows = $derived(palette.results.length > 0);
|
|
96
|
+
|
|
97
|
+
// Keep the highlighted row visible as the arrow keys move it.
|
|
98
|
+
$effect(() => {
|
|
99
|
+
if (!active || typeof document === 'undefined') return;
|
|
100
|
+
const row = document.getElementById(optionId(active));
|
|
101
|
+
if (row && typeof row.scrollIntoView === 'function') {
|
|
102
|
+
row.scrollIntoView({ block: 'nearest' });
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
function onInputKeydown(event: KeyboardEvent) {
|
|
107
|
+
if (event.isComposing) return;
|
|
108
|
+
switch (event.key) {
|
|
109
|
+
case 'ArrowDown':
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
palette.moveActive(1);
|
|
112
|
+
break;
|
|
113
|
+
case 'ArrowUp':
|
|
114
|
+
event.preventDefault();
|
|
115
|
+
palette.moveActive(-1);
|
|
116
|
+
break;
|
|
117
|
+
case 'Enter':
|
|
118
|
+
event.preventDefault();
|
|
119
|
+
void palette.activate();
|
|
120
|
+
break;
|
|
121
|
+
case 'PageDown':
|
|
122
|
+
event.preventDefault();
|
|
123
|
+
palette.moveActive(5);
|
|
124
|
+
break;
|
|
125
|
+
case 'PageUp':
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
palette.moveActive(-5);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const statusText = $derived.by(() => {
|
|
133
|
+
if (!palette.isOpen) return '';
|
|
134
|
+
const query = palette.query.trim();
|
|
135
|
+
if (palette.busy && !hasRows) return t(M['ui.command_palette.searching']);
|
|
136
|
+
if (!hasRows) {
|
|
137
|
+
return query
|
|
138
|
+
? t(M['ui.command_palette.empty'], { query })
|
|
139
|
+
: t(M['ui.command_palette.nothing']);
|
|
140
|
+
}
|
|
141
|
+
const count = palette.results.length;
|
|
142
|
+
const base =
|
|
143
|
+
count === 1
|
|
144
|
+
? t(M['ui.command_palette.status_one'])
|
|
145
|
+
: t(M['ui.command_palette.status_many'], { count });
|
|
146
|
+
return palette.failedProviders.size > 0
|
|
147
|
+
? `${base} ${t(M['ui.command_palette.partial'])}`
|
|
148
|
+
: base;
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
function iconPath(icon: string | undefined): string | null {
|
|
152
|
+
return icon && isShellIconName(icon) ? SHELL_ICON_PATHS[icon] : null;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const inputLabel = $derived(label ?? t(M['ui.command_palette.input_label']));
|
|
156
|
+
</script>
|
|
157
|
+
|
|
158
|
+
<svelte:window onkeydown={onWindowKeydown} />
|
|
159
|
+
|
|
160
|
+
<Modal
|
|
161
|
+
bind:open={() => palette.isOpen, (next) => { if (!next) palette.close(); }}
|
|
162
|
+
ariaLabel={label ?? t(M['ui.command_palette.title'])}
|
|
163
|
+
showClose={false}
|
|
164
|
+
size="md"
|
|
165
|
+
>
|
|
166
|
+
<div class="smrt-command-palette">
|
|
167
|
+
<div class="smrt-command-palette__field">
|
|
168
|
+
<svg class="smrt-command-palette__search-icon" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></svg>
|
|
169
|
+
<Input
|
|
170
|
+
bind:this={input}
|
|
171
|
+
type="text"
|
|
172
|
+
role="combobox"
|
|
173
|
+
aria-label={inputLabel}
|
|
174
|
+
aria-expanded={hasRows}
|
|
175
|
+
aria-controls={listId}
|
|
176
|
+
aria-autocomplete="list"
|
|
177
|
+
aria-activedescendant={active ? optionId(active) : undefined}
|
|
178
|
+
autocomplete="off"
|
|
179
|
+
autocapitalize="off"
|
|
180
|
+
spellcheck={false}
|
|
181
|
+
enterkeyhint="go"
|
|
182
|
+
placeholder={placeholder ?? t(M['ui.command_palette.placeholder'])}
|
|
183
|
+
interaction={false}
|
|
184
|
+
class="smrt-command-palette__input"
|
|
185
|
+
bind:value={() => palette.query, (next) => palette.setQuery(String(next))}
|
|
186
|
+
onkeydown={onInputKeydown}
|
|
187
|
+
/>
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
<div
|
|
191
|
+
class="smrt-command-palette__list"
|
|
192
|
+
id={listId}
|
|
193
|
+
role="listbox"
|
|
194
|
+
aria-label={t(M['ui.command_palette.results'])}
|
|
195
|
+
aria-busy={palette.busy}
|
|
196
|
+
>
|
|
197
|
+
{#each palette.sections as section, sectionIndex (section.id)}
|
|
198
|
+
<div class="smrt-command-palette__group" role="group" aria-labelledby={`${listId}-g${sectionIndex}`}>
|
|
199
|
+
<div class="smrt-command-palette__heading" id={`${listId}-g${sectionIndex}`}>{section.label}</div>
|
|
200
|
+
{#each section.results as result (result.key)}
|
|
201
|
+
{@const path = iconPath(result.item.icon)}
|
|
202
|
+
{@const shortcut = result.item.shortcut ? formatPaletteHotkey(result.item.shortcut, apple) : ''}
|
|
203
|
+
<!-- The combobox input owns the keyboard (aria-activedescendant); rows are pointer targets. -->
|
|
204
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
205
|
+
<div
|
|
206
|
+
class="smrt-command-palette__option"
|
|
207
|
+
id={optionId(result)}
|
|
208
|
+
role="option"
|
|
209
|
+
tabindex="-1"
|
|
210
|
+
aria-selected={active?.key === result.key}
|
|
211
|
+
aria-disabled={result.selectable ? undefined : true}
|
|
212
|
+
data-kind={result.item.kind}
|
|
213
|
+
data-active={active?.key === result.key ? '' : undefined}
|
|
214
|
+
title={typeof result.item.disabled === 'string' ? result.item.disabled : undefined}
|
|
215
|
+
onmousedown={(event) => event.preventDefault()}
|
|
216
|
+
onpointermove={() => palette.setActive(result.key)}
|
|
217
|
+
onclick={() => void palette.activate(result)}
|
|
218
|
+
>
|
|
219
|
+
<span class="smrt-command-palette__icon" aria-hidden="true">
|
|
220
|
+
{#if path}
|
|
221
|
+
<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor" focusable="false"><path d={path} /></svg>
|
|
222
|
+
{/if}
|
|
223
|
+
</span>
|
|
224
|
+
<span class="smrt-command-palette__text">
|
|
225
|
+
<span class="smrt-command-palette__title">
|
|
226
|
+
{#each highlightSegments(result.item.title, result.titleRanges) as segment}
|
|
227
|
+
{#if segment.match}<mark>{segment.text}</mark>{:else}{segment.text}{/if}
|
|
228
|
+
{/each}
|
|
229
|
+
</span>
|
|
230
|
+
{#if result.item.subtitle}
|
|
231
|
+
<span class="smrt-command-palette__subtitle">{result.item.subtitle}</span>
|
|
232
|
+
{/if}
|
|
233
|
+
</span>
|
|
234
|
+
{#if typeof result.item.disabled === 'string'}
|
|
235
|
+
<span class="smrt-command-palette__note">{t(M['ui.command_palette.unavailable'])}</span>
|
|
236
|
+
{:else if shortcut}
|
|
237
|
+
<kbd class="smrt-command-palette__shortcut">{shortcut}</kbd>
|
|
238
|
+
{/if}
|
|
239
|
+
</div>
|
|
240
|
+
{/each}
|
|
241
|
+
</div>
|
|
242
|
+
{/each}
|
|
243
|
+
</div>
|
|
244
|
+
{#if !hasRows}
|
|
245
|
+
<p class="smrt-command-palette__empty">{statusText}</p>
|
|
246
|
+
{/if}
|
|
247
|
+
|
|
248
|
+
<div class="smrt-command-palette__hints" aria-hidden="true">
|
|
249
|
+
<span><kbd>↑</kbd><kbd>↓</kbd> {t(M['ui.command_palette.hint_move'])}</span>
|
|
250
|
+
<span><kbd>↵</kbd> {t(M['ui.command_palette.hint_select'])}</span>
|
|
251
|
+
<span><kbd>Esc</kbd> {t(M['ui.command_palette.hint_close'])}</span>
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
<div class="smrt-command-palette__live" role="status" aria-live="polite">{statusText}</div>
|
|
255
|
+
</div>
|
|
256
|
+
</Modal>
|
|
257
|
+
|
|
258
|
+
<style>
|
|
259
|
+
.smrt-command-palette {
|
|
260
|
+
display: flex;
|
|
261
|
+
flex-direction: column;
|
|
262
|
+
gap: var(--smrt-spacing-2, 0.5rem);
|
|
263
|
+
min-block-size: 0;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.smrt-command-palette__field {
|
|
267
|
+
position: relative;
|
|
268
|
+
display: flex;
|
|
269
|
+
align-items: center;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.smrt-command-palette__search-icon {
|
|
273
|
+
position: absolute;
|
|
274
|
+
inset-inline-start: 0.75rem;
|
|
275
|
+
color: var(--smrt-color-on-surface-variant);
|
|
276
|
+
pointer-events: none;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.smrt-command-palette__field :global(.smrt-command-palette__input) {
|
|
280
|
+
padding-inline-start: 2.5rem;
|
|
281
|
+
/* 16px keeps iOS from zooming when the box takes focus. */
|
|
282
|
+
font-size: max(1rem, var(--smrt-typography-body-medium-size, 0.875rem));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.smrt-command-palette__list {
|
|
286
|
+
max-block-size: min(24rem, 55vh);
|
|
287
|
+
overflow-y: auto;
|
|
288
|
+
overscroll-behavior: contain;
|
|
289
|
+
display: flex;
|
|
290
|
+
flex-direction: column;
|
|
291
|
+
gap: var(--smrt-spacing-2, 0.5rem);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.smrt-command-palette__heading {
|
|
295
|
+
padding: 0.25rem 0.75rem;
|
|
296
|
+
font-size: var(--smrt-typography-label-small-size, 0.75rem);
|
|
297
|
+
font-weight: var(--smrt-typography-weight-semibold, 600);
|
|
298
|
+
letter-spacing: 0.04em;
|
|
299
|
+
text-transform: uppercase;
|
|
300
|
+
color: var(--smrt-color-on-surface-variant);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.smrt-command-palette__option {
|
|
304
|
+
display: flex;
|
|
305
|
+
align-items: center;
|
|
306
|
+
gap: 0.75rem;
|
|
307
|
+
min-block-size: max(2.5rem, var(--smrt-control-target-min, 0px));
|
|
308
|
+
padding: 0.375rem 0.75rem;
|
|
309
|
+
border-radius: var(--smrt-radius-medium, 0.5rem);
|
|
310
|
+
color: var(--smrt-color-on-surface);
|
|
311
|
+
cursor: pointer;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.smrt-command-palette__option[data-active] {
|
|
315
|
+
background: var(--smrt-color-surface-container-high);
|
|
316
|
+
box-shadow: inset 3px 0 0 var(--smrt-color-primary);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.smrt-command-palette__option[aria-disabled='true'] {
|
|
320
|
+
opacity: 0.55;
|
|
321
|
+
cursor: not-allowed;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.smrt-command-palette__icon {
|
|
325
|
+
flex: 0 0 1.125rem;
|
|
326
|
+
inline-size: 1.125rem;
|
|
327
|
+
color: var(--smrt-color-on-surface-variant);
|
|
328
|
+
display: inline-grid;
|
|
329
|
+
place-items: center;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.smrt-command-palette__text {
|
|
333
|
+
flex: 1 1 auto;
|
|
334
|
+
min-inline-size: 0;
|
|
335
|
+
display: flex;
|
|
336
|
+
flex-direction: column;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.smrt-command-palette__title,
|
|
340
|
+
.smrt-command-palette__subtitle {
|
|
341
|
+
overflow: hidden;
|
|
342
|
+
text-overflow: ellipsis;
|
|
343
|
+
white-space: nowrap;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.smrt-command-palette__subtitle {
|
|
347
|
+
font-size: var(--smrt-typography-body-small-size, 0.75rem);
|
|
348
|
+
color: var(--smrt-color-on-surface-variant);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.smrt-command-palette mark {
|
|
352
|
+
background: color-mix(in srgb, var(--smrt-color-primary) 18%, transparent);
|
|
353
|
+
color: inherit;
|
|
354
|
+
font-weight: var(--smrt-typography-weight-bold, 700);
|
|
355
|
+
border-radius: 0.125rem;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.smrt-command-palette__note {
|
|
359
|
+
font-size: var(--smrt-typography-label-small-size, 0.75rem);
|
|
360
|
+
color: var(--smrt-color-on-surface-variant);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.smrt-command-palette kbd {
|
|
364
|
+
font: inherit;
|
|
365
|
+
font-size: var(--smrt-typography-label-small-size, 0.75rem);
|
|
366
|
+
padding: 0.0625rem 0.375rem;
|
|
367
|
+
border: 1px solid var(--smrt-color-outline-variant, var(--smrt-color-outline));
|
|
368
|
+
border-radius: var(--smrt-radius-small, 0.375rem);
|
|
369
|
+
color: var(--smrt-color-on-surface-variant);
|
|
370
|
+
background: var(--smrt-color-surface-container);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.smrt-command-palette__empty {
|
|
374
|
+
margin: 0;
|
|
375
|
+
padding: 1.5rem 0.75rem;
|
|
376
|
+
text-align: center;
|
|
377
|
+
color: var(--smrt-color-on-surface-variant);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.smrt-command-palette__hints {
|
|
381
|
+
display: flex;
|
|
382
|
+
gap: 1rem;
|
|
383
|
+
padding: 0.25rem 0.75rem 0;
|
|
384
|
+
font-size: var(--smrt-typography-label-small-size, 0.75rem);
|
|
385
|
+
color: var(--smrt-color-on-surface-variant);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.smrt-command-palette__hints kbd + kbd {
|
|
389
|
+
margin-inline-start: 0.125rem;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
@media (max-width: 48rem) {
|
|
393
|
+
.smrt-command-palette__hints {
|
|
394
|
+
display: none;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.smrt-command-palette__live {
|
|
399
|
+
position: absolute;
|
|
400
|
+
inline-size: 1px;
|
|
401
|
+
block-size: 1px;
|
|
402
|
+
overflow: hidden;
|
|
403
|
+
clip-path: inset(50%);
|
|
404
|
+
white-space: nowrap;
|
|
405
|
+
}
|
|
406
|
+
</style>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CommandPaletteController } from './controller.svelte.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** The palette to drive; default: the one on context. */
|
|
4
|
+
palette?: CommandPaletteController;
|
|
5
|
+
/**
|
|
6
|
+
* Shortcuts that toggle the palette, e.g. `['Mod+K', '/']`. `false` installs
|
|
7
|
+
* none (open it from your own control).
|
|
8
|
+
*/
|
|
9
|
+
hotkeys?: readonly string[] | false;
|
|
10
|
+
/** Accessible name of the dialog. */
|
|
11
|
+
label?: string;
|
|
12
|
+
/** Search box placeholder. */
|
|
13
|
+
placeholder?: string;
|
|
14
|
+
}
|
|
15
|
+
declare const CommandPaletteDialog: import("svelte").Component<Props, {}, "">;
|
|
16
|
+
type CommandPaletteDialog = ReturnType<typeof CommandPaletteDialog>;
|
|
17
|
+
export default CommandPaletteDialog;
|
|
18
|
+
//# sourceMappingURL=CommandPaletteDialog.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPaletteDialog.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/command-palette/CommandPaletteDialog.svelte.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAavE,UAAU,KAAK;IACb,yDAAyD;IACzD,OAAO,CAAC,EAAE,wBAAwB,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAAC;IACpC,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAwLD,QAAA,MAAM,oBAAoB,2CAAwC,CAAC;AACnE,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACpE,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* CommandPaletteTrigger - the shell control that opens the palette: a search
|
|
4
|
+
* glyph, a label and the shortcut hint. Place it in a shell slot (the header
|
|
5
|
+
* center or end is the usual home) through `AppShell` `slotItems`. On narrow
|
|
6
|
+
* screens only the glyph shows; the accessible name stays the label.
|
|
7
|
+
*/
|
|
8
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
9
|
+
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
10
|
+
import { onMount } from 'svelte';
|
|
11
|
+
import { M } from '../../i18n/strings.palette.js';
|
|
12
|
+
import { palettePicker } from './context.js';
|
|
13
|
+
import type { CommandPaletteController } from './controller.svelte.js';
|
|
14
|
+
import {
|
|
15
|
+
ariaKeyShortcuts,
|
|
16
|
+
DEFAULT_PALETTE_HOTKEYS,
|
|
17
|
+
formatPaletteHotkey,
|
|
18
|
+
isApplePlatform,
|
|
19
|
+
} from './hotkeys.js';
|
|
20
|
+
|
|
21
|
+
interface Props {
|
|
22
|
+
/** The palette to open; default: the one on context. */
|
|
23
|
+
palette?: CommandPaletteController;
|
|
24
|
+
/** Button text and accessible name (default "Search"). */
|
|
25
|
+
label?: string;
|
|
26
|
+
/** Hint shown after the label: the first shortcut. Match `hotkeys` on the dialog. */
|
|
27
|
+
hotkeys?: readonly string[];
|
|
28
|
+
/** Glyph only, at every width. */
|
|
29
|
+
compact?: boolean;
|
|
30
|
+
/** Extra class on the button. */
|
|
31
|
+
class?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let {
|
|
35
|
+
palette: paletteProp,
|
|
36
|
+
label,
|
|
37
|
+
hotkeys = DEFAULT_PALETTE_HOTKEYS,
|
|
38
|
+
compact = false,
|
|
39
|
+
class: className = '',
|
|
40
|
+
}: Props = $props();
|
|
41
|
+
|
|
42
|
+
const { t } = useI18n();
|
|
43
|
+
const pick = palettePicker(() => paletteProp);
|
|
44
|
+
const palette = $derived(pick());
|
|
45
|
+
const text = $derived(label ?? t(M['ui.command_palette.trigger']));
|
|
46
|
+
|
|
47
|
+
let apple = $state(false);
|
|
48
|
+
onMount(() => {
|
|
49
|
+
apple = isApplePlatform();
|
|
50
|
+
});
|
|
51
|
+
const hint = $derived(hotkeys[0] ? formatPaletteHotkey(hotkeys[0], apple) : '');
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<Button
|
|
55
|
+
variant="ghost"
|
|
56
|
+
size="sm"
|
|
57
|
+
class={`smrt-command-palette-trigger ${className}`}
|
|
58
|
+
aria-label={text}
|
|
59
|
+
aria-haspopup="dialog"
|
|
60
|
+
aria-expanded={palette.isOpen}
|
|
61
|
+
aria-keyshortcuts={ariaKeyShortcuts(hotkeys)}
|
|
62
|
+
onclick={() => palette.open()}
|
|
63
|
+
>
|
|
64
|
+
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></svg>
|
|
65
|
+
{#if !compact}
|
|
66
|
+
<span class="smrt-command-palette-trigger__label">{text}</span>
|
|
67
|
+
{#if hint}<kbd class="smrt-command-palette-trigger__hint">{hint}</kbd>{/if}
|
|
68
|
+
{/if}
|
|
69
|
+
</Button>
|
|
70
|
+
|
|
71
|
+
<style>
|
|
72
|
+
:global(.smrt-command-palette-trigger) {
|
|
73
|
+
gap: 0.5rem;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.smrt-command-palette-trigger__hint {
|
|
77
|
+
font: inherit;
|
|
78
|
+
font-size: var(--smrt-typography-label-small-size, 0.75rem);
|
|
79
|
+
padding: 0.0625rem 0.375rem;
|
|
80
|
+
border: 1px solid var(--smrt-color-outline-variant, var(--smrt-color-outline));
|
|
81
|
+
border-radius: var(--smrt-radius-small, 0.375rem);
|
|
82
|
+
color: var(--smrt-color-on-surface-variant);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@media (max-width: 48rem) {
|
|
86
|
+
.smrt-command-palette-trigger__label,
|
|
87
|
+
.smrt-command-palette-trigger__hint {
|
|
88
|
+
display: none;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CommandPaletteController } from './controller.svelte.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** The palette to open; default: the one on context. */
|
|
4
|
+
palette?: CommandPaletteController;
|
|
5
|
+
/** Button text and accessible name (default "Search"). */
|
|
6
|
+
label?: string;
|
|
7
|
+
/** Hint shown after the label: the first shortcut. Match `hotkeys` on the dialog. */
|
|
8
|
+
hotkeys?: readonly string[];
|
|
9
|
+
/** Glyph only, at every width. */
|
|
10
|
+
compact?: boolean;
|
|
11
|
+
/** Extra class on the button. */
|
|
12
|
+
class?: string;
|
|
13
|
+
}
|
|
14
|
+
declare const CommandPaletteTrigger: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type CommandPaletteTrigger = ReturnType<typeof CommandPaletteTrigger>;
|
|
16
|
+
export default CommandPaletteTrigger;
|
|
17
|
+
//# sourceMappingURL=CommandPaletteTrigger.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPaletteTrigger.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/command-palette/CommandPaletteTrigger.svelte.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AASvE,UAAU,KAAK;IACb,wDAAwD;IACxD,OAAO,CAAC,EAAE,wBAAwB,CAAC;IACnC,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA4CD,QAAA,MAAM,qBAAqB,2CAAwC,CAAC;AACpE,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACtE,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CommandPaletteController } from './controller.svelte.js';
|
|
2
|
+
export declare const COMMAND_PALETTE_CONTEXT: unique symbol;
|
|
3
|
+
/**
|
|
4
|
+
* Put a palette on context so descendants (recipe components, pages) can
|
|
5
|
+
* register providers with {@link useCommandPaletteProvider}. Call it in the
|
|
6
|
+
* layout that owns the palette, above the `AppShell`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function setCommandPalette(controller: CommandPaletteController): CommandPaletteController;
|
|
9
|
+
/** The nearest palette; throws when there is none. */
|
|
10
|
+
export declare function useCommandPalette(): CommandPaletteController;
|
|
11
|
+
/** The nearest palette, or null. */
|
|
12
|
+
export declare function tryUseCommandPalette(): CommandPaletteController | null;
|
|
13
|
+
/**
|
|
14
|
+
* The palette a component should drive: the explicit one, else the nearest on
|
|
15
|
+
* context. Throws when there is neither. Call during component initialization.
|
|
16
|
+
*/
|
|
17
|
+
export declare function palettePicker(explicit: () => CommandPaletteController | undefined): () => CommandPaletteController;
|
|
18
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/components/command-palette/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAEvE,eAAO,MAAM,uBAAuB,eAAiC,CAAC;AAEtE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,wBAAwB,GACnC,wBAAwB,CAG1B;AAED,sDAAsD;AACtD,wBAAgB,iBAAiB,IAAI,wBAAwB,CAU5D;AAED,oCAAoC;AACpC,wBAAgB,oBAAoB,IAAI,wBAAwB,GAAG,IAAI,CAKtE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,wBAAwB,GAAG,SAAS,GACnD,MAAM,wBAAwB,CAWhC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { getContext, setContext } from 'svelte';
|
|
2
|
+
export const COMMAND_PALETTE_CONTEXT = Symbol('smrt-command-palette');
|
|
3
|
+
/**
|
|
4
|
+
* Put a palette on context so descendants (recipe components, pages) can
|
|
5
|
+
* register providers with {@link useCommandPaletteProvider}. Call it in the
|
|
6
|
+
* layout that owns the palette, above the `AppShell`.
|
|
7
|
+
*/
|
|
8
|
+
export function setCommandPalette(controller) {
|
|
9
|
+
setContext(COMMAND_PALETTE_CONTEXT, controller);
|
|
10
|
+
return controller;
|
|
11
|
+
}
|
|
12
|
+
/** The nearest palette; throws when there is none. */
|
|
13
|
+
export function useCommandPalette() {
|
|
14
|
+
const controller = getContext(COMMAND_PALETTE_CONTEXT);
|
|
15
|
+
if (!controller) {
|
|
16
|
+
throw new Error('[useCommandPalette] No command palette found on context. Call setCommandPalette() in a parent layout.');
|
|
17
|
+
}
|
|
18
|
+
return controller;
|
|
19
|
+
}
|
|
20
|
+
/** The nearest palette, or null. */
|
|
21
|
+
export function tryUseCommandPalette() {
|
|
22
|
+
return (getContext(COMMAND_PALETTE_CONTEXT) ??
|
|
23
|
+
null);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The palette a component should drive: the explicit one, else the nearest on
|
|
27
|
+
* context. Throws when there is neither. Call during component initialization.
|
|
28
|
+
*/
|
|
29
|
+
export function palettePicker(explicit) {
|
|
30
|
+
const fromContext = tryUseCommandPalette();
|
|
31
|
+
return () => {
|
|
32
|
+
const controller = explicit() ?? fromContext;
|
|
33
|
+
if (!controller) {
|
|
34
|
+
throw new Error('[command palette] Pass a `palette` prop or call setCommandPalette() in a parent layout.');
|
|
35
|
+
}
|
|
36
|
+
return controller;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { PaletteErrorContext, PaletteItem, PaletteProvider, PaletteResult, PaletteSection } from './types.js';
|
|
2
|
+
export interface CommandPaletteOptions {
|
|
3
|
+
/** Providers registered at construction (more can be registered later). */
|
|
4
|
+
providers?: readonly PaletteProvider[];
|
|
5
|
+
/**
|
|
6
|
+
* Opens `href` for an item that has one. SvelteKit apps pass `goto`.
|
|
7
|
+
* Default: `window.location.assign`.
|
|
8
|
+
*/
|
|
9
|
+
navigate?: (href: string, item?: PaletteItem) => void | Promise<void>;
|
|
10
|
+
/** Pause after the last keystroke before `search` providers run (ms). */
|
|
11
|
+
searchDebounceMs?: number;
|
|
12
|
+
/** Rows per group unless a provider sets `limit`. */
|
|
13
|
+
maxPerGroup?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Called when a provider fails to load or search, or an item's `run`
|
|
16
|
+
* throws. The palette keeps working; default logs a warning.
|
|
17
|
+
*/
|
|
18
|
+
onError?: (error: unknown, context: PaletteErrorContext) => void;
|
|
19
|
+
}
|
|
20
|
+
export declare class CommandPaletteController {
|
|
21
|
+
#private;
|
|
22
|
+
constructor(options?: CommandPaletteOptions);
|
|
23
|
+
/** Whether the palette is showing. */
|
|
24
|
+
get isOpen(): boolean;
|
|
25
|
+
/** The text in the search box. */
|
|
26
|
+
get query(): string;
|
|
27
|
+
/** Registered providers, in registration order. */
|
|
28
|
+
get providers(): readonly PaletteProvider[];
|
|
29
|
+
/** Whether any provider is still loading or searching. */
|
|
30
|
+
get busy(): boolean;
|
|
31
|
+
/** Ids of providers whose last load or search failed. */
|
|
32
|
+
get failedProviders(): ReadonlySet<string>;
|
|
33
|
+
/** Grouped, ranked rows for the current query. */
|
|
34
|
+
readonly sections: readonly PaletteSection[];
|
|
35
|
+
/** The rows in display order. */
|
|
36
|
+
readonly results: readonly PaletteResult[];
|
|
37
|
+
/** The highlighted row: the chosen one, else the first selectable row. */
|
|
38
|
+
readonly active: PaletteResult | null;
|
|
39
|
+
/**
|
|
40
|
+
* Register a provider; returns its disposer. Registering an id again
|
|
41
|
+
* replaces the earlier provider in place (so a re-rendering component does
|
|
42
|
+
* not stack duplicates); the disposer of a replaced registration is a no-op.
|
|
43
|
+
*/
|
|
44
|
+
registerProvider(provider: PaletteProvider): () => void;
|
|
45
|
+
/** Show the palette with an empty query. */
|
|
46
|
+
open(): void;
|
|
47
|
+
/** Hide the palette and cancel work in flight. */
|
|
48
|
+
close(): void;
|
|
49
|
+
toggle(): void;
|
|
50
|
+
/** Set the search text; local rows update at once, `search` providers after a pause. */
|
|
51
|
+
setQuery(query: string): void;
|
|
52
|
+
/** Move the highlight by `delta` rows among selectable ones, wrapping. */
|
|
53
|
+
moveActive(delta: number): void;
|
|
54
|
+
/** Move the highlight to the first or last selectable row. */
|
|
55
|
+
moveActiveTo(edge: 'first' | 'last'): void;
|
|
56
|
+
/** Highlight a specific row (pointer hover). */
|
|
57
|
+
setActive(key: string): void;
|
|
58
|
+
/**
|
|
59
|
+
* Choose a row (default: the highlighted one): closes the palette, then runs
|
|
60
|
+
* the item or navigates to its `href`. Resolves once that has finished.
|
|
61
|
+
*/
|
|
62
|
+
activate(result?: PaletteResult | null): Promise<void>;
|
|
63
|
+
/** Go to `href` with the host's `navigate` seam. */
|
|
64
|
+
navigate(href: string, item?: PaletteItem): void | Promise<void>;
|
|
65
|
+
/** Cancel timers and requests; call when the owner is destroyed. */
|
|
66
|
+
destroy(): void;
|
|
67
|
+
}
|
|
68
|
+
/** Create a palette controller. */
|
|
69
|
+
export declare function createCommandPalette(options?: CommandPaletteOptions): CommandPaletteController;
|
|
70
|
+
//# sourceMappingURL=controller.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/command-palette/controller.svelte.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,aAAa,EACb,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,qBAAqB;IACpC,2EAA2E;IAC3E,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;CAClE;AAUD,qBAAa,wBAAwB;;gBAkBvB,OAAO,GAAE,qBAA0B;IAK/C,sCAAsC;IACtC,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,kCAAkC;IAClC,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,mDAAmD;IACnD,IAAI,SAAS,IAAI,SAAS,eAAe,EAAE,CAE1C;IAED,0DAA0D;IAC1D,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,yDAAyD;IACzD,IAAI,eAAe,IAAI,WAAW,CAAC,MAAM,CAAC,CAEzC;IAED,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAQ1C;IAEF,iCAAiC;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAExC;IAEF,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAKlC;IAEH;;;;OAIG;IACH,gBAAgB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,IAAI;IA2BvD,4CAA4C;IAC5C,IAAI,IAAI,IAAI;IAeZ,kDAAkD;IAClD,KAAK,IAAI,IAAI;IAcb,MAAM,IAAI,IAAI;IAKd,wFAAwF;IACxF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAO7B,0EAA0E;IAC1E,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAgB/B,8DAA8D;IAC9D,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;IAQ1C,gDAAgD;IAChD,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK5B;;;OAGG;IACG,QAAQ,CAAC,MAAM,GAAE,aAAa,GAAG,IAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBzE,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhE,oEAAoE;IACpE,OAAO,IAAI,IAAI;CAkKhB;AAWD,mCAAmC;AACnC,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,qBAA0B,GAClC,wBAAwB,CAE1B"}
|