@happyvertical/smrt-svelte 0.55.7 → 0.55.9
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,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command palette state: provider registry, open/query state, local and
|
|
3
|
+
* remote results, and keyboard selection. Components render this; assistants
|
|
4
|
+
* and tests can drive it directly.
|
|
5
|
+
*/
|
|
6
|
+
import { logger } from '../../internal/logger.js';
|
|
7
|
+
import { buildPaletteSections, flattenSections, orderProviders, } from './rank.js';
|
|
8
|
+
function isThenable(value) {
|
|
9
|
+
return (typeof value === 'object' &&
|
|
10
|
+
value !== null &&
|
|
11
|
+
typeof value.then === 'function');
|
|
12
|
+
}
|
|
13
|
+
export class CommandPaletteController {
|
|
14
|
+
#options;
|
|
15
|
+
#providers = $state.raw([]);
|
|
16
|
+
#local = $state.raw({});
|
|
17
|
+
#remote = $state.raw({});
|
|
18
|
+
#failed = $state.raw(new Set());
|
|
19
|
+
#itemsPending = $state(0);
|
|
20
|
+
#searchPending = $state(0);
|
|
21
|
+
#searchRun = 0;
|
|
22
|
+
#activeKey = $state(null);
|
|
23
|
+
#open = $state(false);
|
|
24
|
+
#query = $state('');
|
|
25
|
+
#itemsAbort = null;
|
|
26
|
+
#searchAbort = null;
|
|
27
|
+
#searchTimer = null;
|
|
28
|
+
#generation = 0;
|
|
29
|
+
constructor(options = {}) {
|
|
30
|
+
this.#options = options;
|
|
31
|
+
this.#providers = [...(options.providers ?? [])];
|
|
32
|
+
}
|
|
33
|
+
/** Whether the palette is showing. */
|
|
34
|
+
get isOpen() {
|
|
35
|
+
return this.#open;
|
|
36
|
+
}
|
|
37
|
+
/** The text in the search box. */
|
|
38
|
+
get query() {
|
|
39
|
+
return this.#query;
|
|
40
|
+
}
|
|
41
|
+
/** Registered providers, in registration order. */
|
|
42
|
+
get providers() {
|
|
43
|
+
return this.#providers;
|
|
44
|
+
}
|
|
45
|
+
/** Whether any provider is still loading or searching. */
|
|
46
|
+
get busy() {
|
|
47
|
+
return this.#itemsPending + this.#searchPending > 0;
|
|
48
|
+
}
|
|
49
|
+
/** Ids of providers whose last load or search failed. */
|
|
50
|
+
get failedProviders() {
|
|
51
|
+
return this.#failed;
|
|
52
|
+
}
|
|
53
|
+
/** Grouped, ranked rows for the current query. */
|
|
54
|
+
sections = $derived.by(() => buildPaletteSections({
|
|
55
|
+
providers: this.#providers,
|
|
56
|
+
local: this.#local,
|
|
57
|
+
remote: this.#remote,
|
|
58
|
+
query: this.#query,
|
|
59
|
+
maxPerGroup: this.#options.maxPerGroup,
|
|
60
|
+
}));
|
|
61
|
+
/** The rows in display order. */
|
|
62
|
+
results = $derived(flattenSections(this.sections));
|
|
63
|
+
/** The highlighted row: the chosen one, else the first selectable row. */
|
|
64
|
+
active = $derived.by(() => {
|
|
65
|
+
const chosen = this.results.find((result) => result.key === this.#activeKey && result.selectable);
|
|
66
|
+
return chosen ?? this.results.find((result) => result.selectable) ?? null;
|
|
67
|
+
});
|
|
68
|
+
/**
|
|
69
|
+
* Register a provider; returns its disposer. Registering an id again
|
|
70
|
+
* replaces the earlier provider in place (so a re-rendering component does
|
|
71
|
+
* not stack duplicates); the disposer of a replaced registration is a no-op.
|
|
72
|
+
*/
|
|
73
|
+
registerProvider(provider) {
|
|
74
|
+
const existing = this.#providers.findIndex((p) => p.id === provider.id);
|
|
75
|
+
if (existing === -1) {
|
|
76
|
+
this.#providers = [...this.#providers, provider];
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
const replaced = this.#providers[existing];
|
|
80
|
+
this.#providers = this.#providers.map((p, index) => index === existing ? provider : p);
|
|
81
|
+
// The replaced provider's rows (and any in-flight results, dropped by
|
|
82
|
+
// the registration check) must not outlive it.
|
|
83
|
+
this.#local = omit(this.#local, replaced.id);
|
|
84
|
+
this.#remote = omit(this.#remote, replaced.id);
|
|
85
|
+
this.#markFailed(replaced.id, false);
|
|
86
|
+
}
|
|
87
|
+
if (this.#open) {
|
|
88
|
+
void this.#loadProvider(provider, this.#itemsSignal());
|
|
89
|
+
if (this.#query.trim())
|
|
90
|
+
this.#scheduleSearch(0);
|
|
91
|
+
}
|
|
92
|
+
return () => {
|
|
93
|
+
if (!this.#providers.includes(provider))
|
|
94
|
+
return;
|
|
95
|
+
this.#providers = this.#providers.filter((p) => p !== provider);
|
|
96
|
+
this.#local = omit(this.#local, provider.id);
|
|
97
|
+
this.#remote = omit(this.#remote, provider.id);
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/** Show the palette with an empty query. */
|
|
101
|
+
open() {
|
|
102
|
+
if (this.#open)
|
|
103
|
+
return;
|
|
104
|
+
this.#open = true;
|
|
105
|
+
this.#query = '';
|
|
106
|
+
this.#activeKey = null;
|
|
107
|
+
this.#remote = {};
|
|
108
|
+
this.#failed = new Set();
|
|
109
|
+
this.#generation += 1;
|
|
110
|
+
this.#itemsAbort?.abort();
|
|
111
|
+
this.#itemsAbort = new AbortController();
|
|
112
|
+
for (const provider of orderProviders(this.#providers)) {
|
|
113
|
+
void this.#loadProvider(provider, this.#itemsAbort.signal);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/** Hide the palette and cancel work in flight. */
|
|
117
|
+
close() {
|
|
118
|
+
if (!this.#open)
|
|
119
|
+
return;
|
|
120
|
+
this.#open = false;
|
|
121
|
+
this.#query = '';
|
|
122
|
+
this.#activeKey = null;
|
|
123
|
+
this.#generation += 1;
|
|
124
|
+
this.#cancelSearch();
|
|
125
|
+
this.#itemsAbort?.abort();
|
|
126
|
+
this.#itemsAbort = null;
|
|
127
|
+
this.#itemsPending = 0;
|
|
128
|
+
this.#searchPending = 0;
|
|
129
|
+
this.#remote = {};
|
|
130
|
+
}
|
|
131
|
+
toggle() {
|
|
132
|
+
if (this.#open)
|
|
133
|
+
this.close();
|
|
134
|
+
else
|
|
135
|
+
this.open();
|
|
136
|
+
}
|
|
137
|
+
/** Set the search text; local rows update at once, `search` providers after a pause. */
|
|
138
|
+
setQuery(query) {
|
|
139
|
+
if (query === this.#query)
|
|
140
|
+
return;
|
|
141
|
+
this.#query = query;
|
|
142
|
+
this.#activeKey = null;
|
|
143
|
+
this.#scheduleSearch(this.#options.searchDebounceMs ?? 150);
|
|
144
|
+
}
|
|
145
|
+
/** Move the highlight by `delta` rows among selectable ones, wrapping. */
|
|
146
|
+
moveActive(delta) {
|
|
147
|
+
const selectable = this.results.filter((result) => result.selectable);
|
|
148
|
+
if (selectable.length === 0)
|
|
149
|
+
return;
|
|
150
|
+
const current = this.active
|
|
151
|
+
? selectable.findIndex((result) => result.key === this.active?.key)
|
|
152
|
+
: -1;
|
|
153
|
+
const next = current === -1
|
|
154
|
+
? delta > 0
|
|
155
|
+
? 0
|
|
156
|
+
: selectable.length - 1
|
|
157
|
+
: (((current + delta) % selectable.length) + selectable.length) %
|
|
158
|
+
selectable.length;
|
|
159
|
+
this.#activeKey = selectable[next].key;
|
|
160
|
+
}
|
|
161
|
+
/** Move the highlight to the first or last selectable row. */
|
|
162
|
+
moveActiveTo(edge) {
|
|
163
|
+
const selectable = this.results.filter((result) => result.selectable);
|
|
164
|
+
if (selectable.length === 0)
|
|
165
|
+
return;
|
|
166
|
+
this.#activeKey = (edge === 'first' ? selectable[0] : selectable[selectable.length - 1]).key;
|
|
167
|
+
}
|
|
168
|
+
/** Highlight a specific row (pointer hover). */
|
|
169
|
+
setActive(key) {
|
|
170
|
+
const result = this.results.find((candidate) => candidate.key === key);
|
|
171
|
+
if (result?.selectable)
|
|
172
|
+
this.#activeKey = key;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Choose a row (default: the highlighted one): closes the palette, then runs
|
|
176
|
+
* the item or navigates to its `href`. Resolves once that has finished.
|
|
177
|
+
*/
|
|
178
|
+
async activate(result = this.active) {
|
|
179
|
+
if (!result?.selectable)
|
|
180
|
+
return;
|
|
181
|
+
const { item, providerId } = result;
|
|
182
|
+
const query = this.#query;
|
|
183
|
+
this.close();
|
|
184
|
+
try {
|
|
185
|
+
if (item.run) {
|
|
186
|
+
await item.run({
|
|
187
|
+
query,
|
|
188
|
+
providerId,
|
|
189
|
+
navigate: (href) => this.navigate(href, item),
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
else if (item.href) {
|
|
193
|
+
await this.navigate(item.href, item);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
this.#report(error, { providerId, phase: 'run', item });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/** Go to `href` with the host's `navigate` seam. */
|
|
201
|
+
navigate(href, item) {
|
|
202
|
+
if (this.#options.navigate)
|
|
203
|
+
return this.#options.navigate(href, item);
|
|
204
|
+
if (typeof window !== 'undefined')
|
|
205
|
+
window.location.assign(href);
|
|
206
|
+
}
|
|
207
|
+
/** Cancel timers and requests; call when the owner is destroyed. */
|
|
208
|
+
destroy() {
|
|
209
|
+
this.#open = false;
|
|
210
|
+
this.#generation += 1;
|
|
211
|
+
this.#cancelSearch();
|
|
212
|
+
this.#itemsAbort?.abort();
|
|
213
|
+
this.#itemsAbort = null;
|
|
214
|
+
}
|
|
215
|
+
#itemsSignal() {
|
|
216
|
+
if (!this.#itemsAbort)
|
|
217
|
+
this.#itemsAbort = new AbortController();
|
|
218
|
+
return this.#itemsAbort.signal;
|
|
219
|
+
}
|
|
220
|
+
#report(error, context) {
|
|
221
|
+
if (this.#options.onError) {
|
|
222
|
+
this.#options.onError(error, context);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
logger.warn('[smrt-svelte] command palette provider failed', {
|
|
226
|
+
...context,
|
|
227
|
+
item: context.item?.id,
|
|
228
|
+
error: error instanceof Error ? error.message : String(error),
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
#markFailed(providerId, failed) {
|
|
232
|
+
if (this.#failed.has(providerId) === failed)
|
|
233
|
+
return;
|
|
234
|
+
const next = new Set(this.#failed);
|
|
235
|
+
if (failed)
|
|
236
|
+
next.add(providerId);
|
|
237
|
+
else
|
|
238
|
+
next.delete(providerId);
|
|
239
|
+
this.#failed = next;
|
|
240
|
+
}
|
|
241
|
+
/** Read a provider's `items`; sync results land immediately. */
|
|
242
|
+
#loadProvider(provider, signal) {
|
|
243
|
+
if (!provider.items)
|
|
244
|
+
return Promise.resolve();
|
|
245
|
+
const generation = this.#generation;
|
|
246
|
+
// A replaced or removed registration must not land late results.
|
|
247
|
+
const current = () => generation === this.#generation &&
|
|
248
|
+
!signal.aborted &&
|
|
249
|
+
this.#providers.includes(provider);
|
|
250
|
+
const accept = (items) => {
|
|
251
|
+
if (!current())
|
|
252
|
+
return;
|
|
253
|
+
this.#local = { ...this.#local, [provider.id]: items };
|
|
254
|
+
this.#markFailed(provider.id, false);
|
|
255
|
+
};
|
|
256
|
+
let outcome;
|
|
257
|
+
try {
|
|
258
|
+
outcome = provider.items({ signal });
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
this.#markFailed(provider.id, true);
|
|
262
|
+
this.#report(error, { providerId: provider.id, phase: 'items' });
|
|
263
|
+
return Promise.resolve();
|
|
264
|
+
}
|
|
265
|
+
if (!isThenable(outcome)) {
|
|
266
|
+
accept(outcome);
|
|
267
|
+
return Promise.resolve();
|
|
268
|
+
}
|
|
269
|
+
this.#itemsPending += 1;
|
|
270
|
+
const settle = () => {
|
|
271
|
+
// A close or reopen already reset the count for this generation.
|
|
272
|
+
if (generation === this.#generation) {
|
|
273
|
+
this.#itemsPending = Math.max(0, this.#itemsPending - 1);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
return Promise.resolve(outcome).then((items) => {
|
|
277
|
+
settle();
|
|
278
|
+
accept(items);
|
|
279
|
+
}, (error) => {
|
|
280
|
+
settle();
|
|
281
|
+
if (!current())
|
|
282
|
+
return;
|
|
283
|
+
this.#markFailed(provider.id, true);
|
|
284
|
+
this.#report(error, { providerId: provider.id, phase: 'items' });
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
#cancelSearch() {
|
|
288
|
+
if (this.#searchTimer)
|
|
289
|
+
clearTimeout(this.#searchTimer);
|
|
290
|
+
this.#searchTimer = null;
|
|
291
|
+
this.#searchAbort?.abort();
|
|
292
|
+
this.#searchAbort = null;
|
|
293
|
+
this.#searchRun += 1;
|
|
294
|
+
this.#searchPending = 0;
|
|
295
|
+
}
|
|
296
|
+
#scheduleSearch(delayMs) {
|
|
297
|
+
if (this.#searchTimer)
|
|
298
|
+
clearTimeout(this.#searchTimer);
|
|
299
|
+
this.#searchTimer = null;
|
|
300
|
+
this.#searchAbort?.abort();
|
|
301
|
+
this.#searchAbort = null;
|
|
302
|
+
this.#searchRun += 1;
|
|
303
|
+
this.#searchPending = 0;
|
|
304
|
+
const query = this.#query.trim();
|
|
305
|
+
if (query.length === 0) {
|
|
306
|
+
this.#remote = {};
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (!this.#open)
|
|
310
|
+
return;
|
|
311
|
+
this.#searchTimer = setTimeout(() => {
|
|
312
|
+
this.#searchTimer = null;
|
|
313
|
+
this.#runSearch(query);
|
|
314
|
+
}, delayMs);
|
|
315
|
+
}
|
|
316
|
+
#runSearch(query) {
|
|
317
|
+
const generation = this.#generation;
|
|
318
|
+
const controller = new AbortController();
|
|
319
|
+
this.#searchAbort = controller;
|
|
320
|
+
const run = ++this.#searchRun;
|
|
321
|
+
this.#searchPending = 0;
|
|
322
|
+
const stale = (provider) => generation !== this.#generation ||
|
|
323
|
+
controller.signal.aborted ||
|
|
324
|
+
!this.#providers.includes(provider);
|
|
325
|
+
const settle = () => {
|
|
326
|
+
if (run === this.#searchRun) {
|
|
327
|
+
this.#searchPending = Math.max(0, this.#searchPending - 1);
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
for (const provider of this.#providers) {
|
|
331
|
+
if (!provider.search)
|
|
332
|
+
continue;
|
|
333
|
+
if (query.length < (provider.minQueryLength ?? 2)) {
|
|
334
|
+
// Too short for this provider: drop what an earlier, longer query left.
|
|
335
|
+
if (this.#remote[provider.id]) {
|
|
336
|
+
this.#remote = omit(this.#remote, provider.id);
|
|
337
|
+
}
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
const limit = provider.limit ?? this.#options.maxPerGroup ?? 8;
|
|
341
|
+
let outcome;
|
|
342
|
+
try {
|
|
343
|
+
outcome = provider.search(query, { signal: controller.signal, limit });
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
this.#markFailed(provider.id, true);
|
|
347
|
+
this.#report(error, { providerId: provider.id, phase: 'search' });
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
// Earlier rows stay until these arrive, so a keystroke does not blank
|
|
351
|
+
// the list; they are replaced (or cleared on failure) below.
|
|
352
|
+
this.#searchPending += 1;
|
|
353
|
+
Promise.resolve(outcome).then((items) => {
|
|
354
|
+
settle();
|
|
355
|
+
if (stale(provider))
|
|
356
|
+
return;
|
|
357
|
+
this.#remote = { ...this.#remote, [provider.id]: items };
|
|
358
|
+
this.#markFailed(provider.id, false);
|
|
359
|
+
}, (error) => {
|
|
360
|
+
settle();
|
|
361
|
+
if (stale(provider))
|
|
362
|
+
return;
|
|
363
|
+
this.#remote = omit(this.#remote, provider.id);
|
|
364
|
+
this.#markFailed(provider.id, true);
|
|
365
|
+
this.#report(error, { providerId: provider.id, phase: 'search' });
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
function omit(record, key) {
|
|
371
|
+
if (!(key in record))
|
|
372
|
+
return record;
|
|
373
|
+
const { [key]: _removed, ...rest } = record;
|
|
374
|
+
return rest;
|
|
375
|
+
}
|
|
376
|
+
/** Create a palette controller. */
|
|
377
|
+
export function createCommandPalette(options = {}) {
|
|
378
|
+
return new CommandPaletteController(options);
|
|
379
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Parsed hotkey. */
|
|
2
|
+
export interface PaletteHotkey {
|
|
3
|
+
/** Lower-cased `KeyboardEvent.key`, e.g. `k` or `/`. */
|
|
4
|
+
key: string;
|
|
5
|
+
/** Control or Meta. */
|
|
6
|
+
mod: boolean;
|
|
7
|
+
ctrl: boolean;
|
|
8
|
+
meta: boolean;
|
|
9
|
+
alt: boolean;
|
|
10
|
+
shift: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** The palette's default shortcut. */
|
|
13
|
+
export declare const DEFAULT_PALETTE_HOTKEYS: readonly string[];
|
|
14
|
+
/** Parse `"Mod+K"`; null when the spec has no key. */
|
|
15
|
+
export declare function parsePaletteHotkey(spec: string): PaletteHotkey | null;
|
|
16
|
+
/** Whether `event` is the hotkey (modifiers must match exactly). */
|
|
17
|
+
export declare function matchesPaletteHotkey(hotkey: PaletteHotkey, event: KeyboardEvent): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Whether `event` should open the palette: it matches one of `hotkeys`, is
|
|
20
|
+
* not part of an IME composition, was not already handled, and (for a bare
|
|
21
|
+
* key) is not going to a text field.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isPaletteHotkeyEvent(event: KeyboardEvent, hotkeys: readonly PaletteHotkey[]): boolean;
|
|
24
|
+
/** Whether the platform shows the command key as a symbol (Apple devices). */
|
|
25
|
+
export declare function isApplePlatform(): boolean;
|
|
26
|
+
/** Display text for a hotkey: `⌘K` on Apple devices, `Ctrl+K` elsewhere. */
|
|
27
|
+
export declare function formatPaletteHotkey(spec: string | PaletteHotkey, apple?: boolean): string;
|
|
28
|
+
/** The `aria-keyshortcuts` value for specs: `Mod+K` -> `Control+K Meta+K`. */
|
|
29
|
+
export declare function ariaKeyShortcuts(specs: readonly string[]): string | undefined;
|
|
30
|
+
//# sourceMappingURL=hotkeys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotkeys.d.ts","sourceRoot":"","sources":["../../../src/components/command-palette/hotkeys.ts"],"names":[],"mappings":"AAWA,qBAAqB;AACrB,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAC;IACZ,uBAAuB;IACvB,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,sCAAsC;AACtC,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EAAc,CAAC;AAEpE,sDAAsD;AACtD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CA0CrE;AAWD,oEAAoE;AACpE,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,aAAa,GACnB,OAAO,CAaT;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,SAAS,aAAa,EAAE,GAChC,OAAO,CAST;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,IAAI,OAAO,CAOzC;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,GAAG,aAAa,EAC5B,KAAK,GAAE,OAA2B,GACjC,MAAM,CAqBR;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CA2B7E"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hotkey specs for the command palette: `"Mod+K"`, `"Ctrl+Shift+P"`, `"/"`.
|
|
3
|
+
*
|
|
4
|
+
* `Mod` is the platform command key: either Control or Meta matches, so
|
|
5
|
+
* Cmd+K on macOS and Ctrl+K elsewhere (and an external keyboard on either)
|
|
6
|
+
* all work. A spec with no modifier (`"/"`) never fires while the user is
|
|
7
|
+
* typing in a field; a spec with a modifier fires anywhere, because Ctrl/Cmd+K
|
|
8
|
+
* is not a character a field could be waiting for.
|
|
9
|
+
*/
|
|
10
|
+
import { isEditableTarget } from '../workspace/admin-shell/hotkeys.js';
|
|
11
|
+
/** The palette's default shortcut. */
|
|
12
|
+
export const DEFAULT_PALETTE_HOTKEYS = ['Mod+K'];
|
|
13
|
+
/** Parse `"Mod+K"`; null when the spec has no key. */
|
|
14
|
+
export function parsePaletteHotkey(spec) {
|
|
15
|
+
const parts = spec
|
|
16
|
+
.split('+')
|
|
17
|
+
.map((part) => part.trim())
|
|
18
|
+
.filter((part) => part.length > 0);
|
|
19
|
+
// "Mod++" would mean Mod and "+", which no palette needs: drop empties.
|
|
20
|
+
const key = parts.pop();
|
|
21
|
+
if (!key)
|
|
22
|
+
return null;
|
|
23
|
+
const hotkey = {
|
|
24
|
+
key: key.toLowerCase(),
|
|
25
|
+
mod: false,
|
|
26
|
+
ctrl: false,
|
|
27
|
+
meta: false,
|
|
28
|
+
alt: false,
|
|
29
|
+
shift: false,
|
|
30
|
+
};
|
|
31
|
+
for (const part of parts) {
|
|
32
|
+
switch (part.toLowerCase()) {
|
|
33
|
+
case 'mod':
|
|
34
|
+
hotkey.mod = true;
|
|
35
|
+
break;
|
|
36
|
+
case 'ctrl':
|
|
37
|
+
case 'control':
|
|
38
|
+
hotkey.ctrl = true;
|
|
39
|
+
break;
|
|
40
|
+
case 'meta':
|
|
41
|
+
case 'cmd':
|
|
42
|
+
case 'command':
|
|
43
|
+
hotkey.meta = true;
|
|
44
|
+
break;
|
|
45
|
+
case 'alt':
|
|
46
|
+
case 'option':
|
|
47
|
+
hotkey.alt = true;
|
|
48
|
+
break;
|
|
49
|
+
case 'shift':
|
|
50
|
+
hotkey.shift = true;
|
|
51
|
+
break;
|
|
52
|
+
default:
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return hotkey;
|
|
57
|
+
}
|
|
58
|
+
function keyMatches(hotkey, event) {
|
|
59
|
+
if (event.key.toLowerCase() === hotkey.key)
|
|
60
|
+
return true;
|
|
61
|
+
// A letter on a non-Latin layout or with Alt held still has its physical key.
|
|
62
|
+
return (/^[a-z]$/.test(hotkey.key) &&
|
|
63
|
+
event.code === `Key${hotkey.key.toUpperCase()}`);
|
|
64
|
+
}
|
|
65
|
+
/** Whether `event` is the hotkey (modifiers must match exactly). */
|
|
66
|
+
export function matchesPaletteHotkey(hotkey, event) {
|
|
67
|
+
if (!keyMatches(hotkey, event))
|
|
68
|
+
return false;
|
|
69
|
+
if (hotkey.mod) {
|
|
70
|
+
if (!(event.ctrlKey || event.metaKey))
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
else if (event.ctrlKey !== hotkey.ctrl || event.metaKey !== hotkey.meta) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
if (event.altKey !== hotkey.alt)
|
|
77
|
+
return false;
|
|
78
|
+
// A bare symbol such as "/" or "?" may need Shift on some layouts.
|
|
79
|
+
const symbol = !/^[a-z0-9]$/.test(hotkey.key);
|
|
80
|
+
const modified = hotkey.mod || hotkey.ctrl || hotkey.meta || hotkey.alt;
|
|
81
|
+
if (symbol && !modified && !hotkey.shift)
|
|
82
|
+
return true;
|
|
83
|
+
return event.shiftKey === hotkey.shift;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Whether `event` should open the palette: it matches one of `hotkeys`, is
|
|
87
|
+
* not part of an IME composition, was not already handled, and (for a bare
|
|
88
|
+
* key) is not going to a text field.
|
|
89
|
+
*/
|
|
90
|
+
export function isPaletteHotkeyEvent(event, hotkeys) {
|
|
91
|
+
if (event.isComposing || event.defaultPrevented || event.repeat)
|
|
92
|
+
return false;
|
|
93
|
+
for (const hotkey of hotkeys) {
|
|
94
|
+
if (!matchesPaletteHotkey(hotkey, event))
|
|
95
|
+
continue;
|
|
96
|
+
const modified = hotkey.mod || hotkey.ctrl || hotkey.meta || hotkey.alt;
|
|
97
|
+
if (!modified && isEditableTarget(event.target))
|
|
98
|
+
continue;
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
/** Whether the platform shows the command key as a symbol (Apple devices). */
|
|
104
|
+
export function isApplePlatform() {
|
|
105
|
+
if (typeof navigator === 'undefined')
|
|
106
|
+
return false;
|
|
107
|
+
const nav = navigator;
|
|
108
|
+
const platform = nav.userAgentData?.platform ?? nav.platform ?? '';
|
|
109
|
+
return /mac|iphone|ipad|ipod/i.test(platform);
|
|
110
|
+
}
|
|
111
|
+
/** Display text for a hotkey: `⌘K` on Apple devices, `Ctrl+K` elsewhere. */
|
|
112
|
+
export function formatPaletteHotkey(spec, apple = isApplePlatform()) {
|
|
113
|
+
const hotkey = typeof spec === 'string' ? parsePaletteHotkey(spec) : spec;
|
|
114
|
+
if (!hotkey)
|
|
115
|
+
return typeof spec === 'string' ? spec : '';
|
|
116
|
+
const key = hotkey.key.length === 1 ? hotkey.key.toUpperCase() : hotkey.key;
|
|
117
|
+
if (apple) {
|
|
118
|
+
return ((hotkey.ctrl ? '⌃' : '') +
|
|
119
|
+
(hotkey.alt ? '⌥' : '') +
|
|
120
|
+
(hotkey.shift ? '⇧' : '') +
|
|
121
|
+
(hotkey.mod || hotkey.meta ? '⌘' : '') +
|
|
122
|
+
key);
|
|
123
|
+
}
|
|
124
|
+
const parts = [
|
|
125
|
+
hotkey.mod || hotkey.ctrl ? 'Ctrl' : '',
|
|
126
|
+
hotkey.meta ? 'Meta' : '',
|
|
127
|
+
hotkey.alt ? 'Alt' : '',
|
|
128
|
+
hotkey.shift ? 'Shift' : '',
|
|
129
|
+
key,
|
|
130
|
+
].filter(Boolean);
|
|
131
|
+
return parts.join('+');
|
|
132
|
+
}
|
|
133
|
+
/** The `aria-keyshortcuts` value for specs: `Mod+K` -> `Control+K Meta+K`. */
|
|
134
|
+
export function ariaKeyShortcuts(specs) {
|
|
135
|
+
const out = [];
|
|
136
|
+
for (const spec of specs) {
|
|
137
|
+
const hotkey = parsePaletteHotkey(spec);
|
|
138
|
+
if (!hotkey)
|
|
139
|
+
continue;
|
|
140
|
+
const key = hotkey.key.length === 1 ? hotkey.key.toUpperCase() : hotkey.key;
|
|
141
|
+
const shared = [
|
|
142
|
+
hotkey.alt ? 'Alt' : '',
|
|
143
|
+
hotkey.shift ? 'Shift' : '',
|
|
144
|
+
].filter(Boolean);
|
|
145
|
+
if (hotkey.mod) {
|
|
146
|
+
out.push([...shared, 'Control', key].join('+'));
|
|
147
|
+
out.push([...shared, 'Meta', key].join('+'));
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
out.push([
|
|
151
|
+
hotkey.ctrl ? 'Control' : '',
|
|
152
|
+
hotkey.meta ? 'Meta' : '',
|
|
153
|
+
...shared,
|
|
154
|
+
key,
|
|
155
|
+
]
|
|
156
|
+
.filter(Boolean)
|
|
157
|
+
.join('+'));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return out.length > 0 ? out.join(' ') : undefined;
|
|
161
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @happyvertical/smrt-svelte/command-palette
|
|
3
|
+
*
|
|
4
|
+
* Global search and command palette (#3713): a shell-slot trigger, a modal
|
|
5
|
+
* palette, a provider contract, and providers derived from the shell nav and
|
|
6
|
+
* the SMRT manifest.
|
|
7
|
+
*/
|
|
8
|
+
export { default as CommandPalette } from './CommandPalette.svelte';
|
|
9
|
+
export { default as CommandPaletteDialog } from './CommandPaletteDialog.svelte';
|
|
10
|
+
export { default as CommandPaletteTrigger } from './CommandPaletteTrigger.svelte';
|
|
11
|
+
export { COMMAND_PALETTE_CONTEXT, setCommandPalette, tryUseCommandPalette, useCommandPalette, } from './context.js';
|
|
12
|
+
export { CommandPaletteController, type CommandPaletteOptions, createCommandPalette, } from './controller.svelte.js';
|
|
13
|
+
export { ariaKeyShortcuts, DEFAULT_PALETTE_HOTKEYS, formatPaletteHotkey, isApplePlatform, isPaletteHotkeyEvent, matchesPaletteHotkey, type PaletteHotkey, parsePaletteHotkey, } from './hotkeys.js';
|
|
14
|
+
export { highlightSegments, type ItemMatch, matchItem, matchText, type TextMatch, } from './match.js';
|
|
15
|
+
export { createModelProviders, createNavigationProvider, type ModelProvidersOptions, type NavigationProviderOptions, type PaletteManifestEntryLike, type PaletteManifestFieldLike, type PaletteManifestLike, type PaletteModel, type PaletteRecordRow, type PaletteRecordSearch, paletteModelsFromManifest, } from './providers.js';
|
|
16
|
+
export { buildPaletteSections, DEFAULT_MAX_PER_GROUP, flattenSections, orderProviders, type RankInput, } from './rank.js';
|
|
17
|
+
export type { MatchRange, PaletteErrorContext, PaletteItem, PaletteItemKind, PaletteItemsContext, PaletteProvider, PaletteResult, PaletteRunContext, PaletteSearchContext, PaletteSection, } from './types.js';
|
|
18
|
+
export { useCommandPaletteProvider } from './use-provider.svelte.js';
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/command-palette/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAClF,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,wBAAwB,EACxB,KAAK,qBAAqB,EAC1B,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,aAAa,EAClB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,iBAAiB,EACjB,KAAK,SAAS,EACd,SAAS,EACT,SAAS,EACT,KAAK,SAAS,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,KAAK,SAAS,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @happyvertical/smrt-svelte/command-palette
|
|
3
|
+
*
|
|
4
|
+
* Global search and command palette (#3713): a shell-slot trigger, a modal
|
|
5
|
+
* palette, a provider contract, and providers derived from the shell nav and
|
|
6
|
+
* the SMRT manifest.
|
|
7
|
+
*/
|
|
8
|
+
export { default as CommandPalette } from './CommandPalette.svelte';
|
|
9
|
+
export { default as CommandPaletteDialog } from './CommandPaletteDialog.svelte';
|
|
10
|
+
export { default as CommandPaletteTrigger } from './CommandPaletteTrigger.svelte';
|
|
11
|
+
export { COMMAND_PALETTE_CONTEXT, setCommandPalette, tryUseCommandPalette, useCommandPalette, } from './context.js';
|
|
12
|
+
export { CommandPaletteController, createCommandPalette, } from './controller.svelte.js';
|
|
13
|
+
export { ariaKeyShortcuts, DEFAULT_PALETTE_HOTKEYS, formatPaletteHotkey, isApplePlatform, isPaletteHotkeyEvent, matchesPaletteHotkey, parsePaletteHotkey, } from './hotkeys.js';
|
|
14
|
+
export { highlightSegments, matchItem, matchText, } from './match.js';
|
|
15
|
+
export { createModelProviders, createNavigationProvider, paletteModelsFromManifest, } from './providers.js';
|
|
16
|
+
export { buildPaletteSections, DEFAULT_MAX_PER_GROUP, flattenSections, orderProviders, } from './rank.js';
|
|
17
|
+
export { useCommandPaletteProvider } from './use-provider.svelte.js';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text matching for the command palette: accent- and case-insensitive,
|
|
3
|
+
* multi-term, with word-start and in-order (fuzzy) matches, and the matched
|
|
4
|
+
* ranges of the original text for highlighting. Pure; no DOM, no Svelte.
|
|
5
|
+
*/
|
|
6
|
+
import type { MatchRange, PaletteItem } from './types.js';
|
|
7
|
+
/** Lower-case and strip accents; the form both sides of a match are compared in. */
|
|
8
|
+
export declare function foldForMatch(source: string): string;
|
|
9
|
+
/** Split a query into its terms (whitespace separated, folded, de-duplicated). */
|
|
10
|
+
export declare function queryTerms(query: string): string[];
|
|
11
|
+
/** Result of matching a query against one text. */
|
|
12
|
+
export interface TextMatch {
|
|
13
|
+
score: number;
|
|
14
|
+
/** Ranges of the original text that matched. */
|
|
15
|
+
ranges: MatchRange[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Match every term of `query` against `text`. All terms must match somewhere
|
|
19
|
+
* (a missing term is no match). An empty query matches everything with score 0.
|
|
20
|
+
*/
|
|
21
|
+
export declare function matchText(query: string, text: string): TextMatch | null;
|
|
22
|
+
/** Result of matching a query against a palette item. */
|
|
23
|
+
export interface ItemMatch {
|
|
24
|
+
score: number;
|
|
25
|
+
/** Ranges of `item.title` that matched. */
|
|
26
|
+
titleRanges: MatchRange[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Match `query` against an item's title (full weight), and its subtitle and
|
|
30
|
+
* keywords (half weight). Each term may match any of them; all must match.
|
|
31
|
+
*/
|
|
32
|
+
export declare function matchItem(query: string, item: PaletteItem): ItemMatch | null;
|
|
33
|
+
/** Split `text` into alternating plain and matched segments for rendering. */
|
|
34
|
+
export declare function highlightSegments(text: string, ranges: readonly MatchRange[]): Array<{
|
|
35
|
+
text: string;
|
|
36
|
+
match: boolean;
|
|
37
|
+
}>;
|
|
38
|
+
//# sourceMappingURL=match.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match.d.ts","sourceRoot":"","sources":["../../../src/components/command-palette/match.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAmC1D,oFAAoF;AACpF,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAKlD;AA0ED,mDAAmD;AACnD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAkBvE;AAED,yDAAyD;AACzD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CA2B5E;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,UAAU,EAAE,GAC5B,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAgBzC"}
|