@choice-ui/command 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +67 -6
- package/dist/index.js +278 -266
- package/package.json +13 -15
- package/dist/index.cjs +0 -1309
- package/dist/index.d.cts +0 -130
- package/src/command-score.ts +0 -171
- package/src/command.tsx +0 -482
- package/src/components/command-divider.tsx +0 -30
- package/src/components/command-empty.tsx +0 -30
- package/src/components/command-footer.tsx +0 -22
- package/src/components/command-group.tsx +0 -76
- package/src/components/command-input.tsx +0 -66
- package/src/components/command-item.tsx +0 -165
- package/src/components/command-list.tsx +0 -77
- package/src/components/command-loading.tsx +0 -30
- package/src/components/command-tabs.tsx +0 -20
- package/src/components/command-value.tsx +0 -23
- package/src/components/index.ts +0 -10
- package/src/context/command-context.ts +0 -5
- package/src/context/create-command-context.ts +0 -140
- package/src/context/index.ts +0 -2
- package/src/hooks/index.ts +0 -10
- package/src/hooks/use-as-ref.ts +0 -12
- package/src/hooks/use-command-state.ts +0 -18
- package/src/hooks/use-command.ts +0 -10
- package/src/hooks/use-schedule-layout-effect.ts +0 -19
- package/src/hooks/use-value.ts +0 -39
- package/src/index.ts +0 -31
- package/src/store/index.ts +0 -1
- package/src/tv.ts +0 -248
- package/src/types.ts +0 -84
- package/src/utils/constants.ts +0 -7
- package/src/utils/dom.ts +0 -19
- package/src/utils/helpers.ts +0 -45
- package/src/utils/index.ts +0 -3
package/dist/index.cjs
DELETED
|
@@ -1,1309 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var shared = require('@choice-ui/shared');
|
|
4
|
-
var React4 = require('react');
|
|
5
|
-
var usehooksTs = require('usehooks-ts');
|
|
6
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
-
var tabs = require('@choice-ui/tabs');
|
|
8
|
-
var input = require('@choice-ui/input');
|
|
9
|
-
var kbd = require('@choice-ui/kbd');
|
|
10
|
-
var scrollArea = require('@choice-ui/scroll-area');
|
|
11
|
-
|
|
12
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
-
|
|
14
|
-
var React4__default = /*#__PURE__*/_interopDefault(React4);
|
|
15
|
-
|
|
16
|
-
// src/command.tsx
|
|
17
|
-
|
|
18
|
-
// src/command-score.ts
|
|
19
|
-
var SCORE_CONTINUE_MATCH = 1;
|
|
20
|
-
var SCORE_SPACE_WORD_JUMP = 0.9;
|
|
21
|
-
var SCORE_NON_SPACE_WORD_JUMP = 0.8;
|
|
22
|
-
var SCORE_CHARACTER_JUMP = 0.17;
|
|
23
|
-
var SCORE_TRANSPOSITION = 0.1;
|
|
24
|
-
var PENALTY_SKIPPED = 0.999;
|
|
25
|
-
var PENALTY_CASE_MISMATCH = 0.9999;
|
|
26
|
-
var PENALTY_NOT_COMPLETE = 0.99;
|
|
27
|
-
var IS_GAP_REGEXP = /[\\/_+.#"@[({&]/;
|
|
28
|
-
var COUNT_GAPS_REGEXP = /[\\/_+.#"@[({&]/g;
|
|
29
|
-
var IS_SPACE_REGEXP = /[\s-]/;
|
|
30
|
-
var COUNT_SPACE_REGEXP = /[\s-]/g;
|
|
31
|
-
function commandScoreInner(string, abbreviation, lowerString, lowerAbbreviation, stringIndex, abbreviationIndex, memoizedResults) {
|
|
32
|
-
if (abbreviationIndex === abbreviation.length) {
|
|
33
|
-
if (stringIndex === string.length) {
|
|
34
|
-
return SCORE_CONTINUE_MATCH;
|
|
35
|
-
}
|
|
36
|
-
return PENALTY_NOT_COMPLETE;
|
|
37
|
-
}
|
|
38
|
-
const memoizeKey = `${stringIndex},${abbreviationIndex}`;
|
|
39
|
-
if (memoizedResults[memoizeKey] !== void 0) {
|
|
40
|
-
return memoizedResults[memoizeKey];
|
|
41
|
-
}
|
|
42
|
-
const abbreviationChar = lowerAbbreviation.charAt(abbreviationIndex);
|
|
43
|
-
let index = lowerString.indexOf(abbreviationChar, stringIndex);
|
|
44
|
-
let highScore = 0;
|
|
45
|
-
let score, transposedScore, wordBreaks, spaceBreaks;
|
|
46
|
-
while (index >= 0) {
|
|
47
|
-
score = commandScoreInner(
|
|
48
|
-
string,
|
|
49
|
-
abbreviation,
|
|
50
|
-
lowerString,
|
|
51
|
-
lowerAbbreviation,
|
|
52
|
-
index + 1,
|
|
53
|
-
abbreviationIndex + 1,
|
|
54
|
-
memoizedResults
|
|
55
|
-
);
|
|
56
|
-
if (score > highScore) {
|
|
57
|
-
if (index === stringIndex) {
|
|
58
|
-
score *= SCORE_CONTINUE_MATCH;
|
|
59
|
-
} else if (IS_GAP_REGEXP.test(string.charAt(index - 1))) {
|
|
60
|
-
score *= SCORE_NON_SPACE_WORD_JUMP;
|
|
61
|
-
wordBreaks = string.slice(stringIndex, index - 1).match(COUNT_GAPS_REGEXP);
|
|
62
|
-
if (wordBreaks && stringIndex > 0) {
|
|
63
|
-
score *= Math.pow(PENALTY_SKIPPED, wordBreaks.length);
|
|
64
|
-
}
|
|
65
|
-
} else if (IS_SPACE_REGEXP.test(string.charAt(index - 1))) {
|
|
66
|
-
score *= SCORE_SPACE_WORD_JUMP;
|
|
67
|
-
spaceBreaks = string.slice(stringIndex, index - 1).match(COUNT_SPACE_REGEXP);
|
|
68
|
-
if (spaceBreaks && stringIndex > 0) {
|
|
69
|
-
score *= Math.pow(PENALTY_SKIPPED, spaceBreaks.length);
|
|
70
|
-
}
|
|
71
|
-
} else {
|
|
72
|
-
score *= SCORE_CHARACTER_JUMP;
|
|
73
|
-
if (stringIndex > 0) {
|
|
74
|
-
score *= Math.pow(PENALTY_SKIPPED, index - stringIndex);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (string.charAt(index) !== abbreviation.charAt(abbreviationIndex)) {
|
|
78
|
-
score *= PENALTY_CASE_MISMATCH;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (score < SCORE_TRANSPOSITION && lowerString.charAt(index - 1) === lowerAbbreviation.charAt(abbreviationIndex + 1) || lowerAbbreviation.charAt(abbreviationIndex + 1) === lowerAbbreviation.charAt(abbreviationIndex) && // allow duplicate letters. Ref #7428
|
|
82
|
-
lowerString.charAt(index - 1) !== lowerAbbreviation.charAt(abbreviationIndex)) {
|
|
83
|
-
transposedScore = commandScoreInner(
|
|
84
|
-
string,
|
|
85
|
-
abbreviation,
|
|
86
|
-
lowerString,
|
|
87
|
-
lowerAbbreviation,
|
|
88
|
-
index + 1,
|
|
89
|
-
abbreviationIndex + 2,
|
|
90
|
-
memoizedResults
|
|
91
|
-
);
|
|
92
|
-
if (transposedScore * SCORE_TRANSPOSITION > score) {
|
|
93
|
-
score = transposedScore * SCORE_TRANSPOSITION;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (score > highScore) {
|
|
97
|
-
highScore = score;
|
|
98
|
-
}
|
|
99
|
-
index = lowerString.indexOf(abbreviationChar, index + 1);
|
|
100
|
-
}
|
|
101
|
-
memoizedResults[memoizeKey] = highScore;
|
|
102
|
-
return highScore;
|
|
103
|
-
}
|
|
104
|
-
function formatInput(string) {
|
|
105
|
-
return string.toLowerCase().replace(COUNT_SPACE_REGEXP, " ");
|
|
106
|
-
}
|
|
107
|
-
function commandScore(string, abbreviation, aliases) {
|
|
108
|
-
string = aliases && aliases.length > 0 ? `${string + " " + aliases.join(" ")}` : string;
|
|
109
|
-
return commandScoreInner(
|
|
110
|
-
string,
|
|
111
|
-
abbreviation,
|
|
112
|
-
formatInput(string),
|
|
113
|
-
formatInput(abbreviation),
|
|
114
|
-
0,
|
|
115
|
-
0,
|
|
116
|
-
{}
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
var CommandContext = React4.createContext(void 0);
|
|
120
|
-
var StoreContext = React4.createContext(void 0);
|
|
121
|
-
|
|
122
|
-
// src/context/create-command-context.ts
|
|
123
|
-
function createCommandContext(options) {
|
|
124
|
-
const {
|
|
125
|
-
allGroups,
|
|
126
|
-
allItems,
|
|
127
|
-
filterItems,
|
|
128
|
-
ids,
|
|
129
|
-
inputId,
|
|
130
|
-
label,
|
|
131
|
-
labelId,
|
|
132
|
-
listId,
|
|
133
|
-
listInnerRef,
|
|
134
|
-
propsRef,
|
|
135
|
-
schedule,
|
|
136
|
-
selectFirstItem,
|
|
137
|
-
size,
|
|
138
|
-
sort,
|
|
139
|
-
state,
|
|
140
|
-
store,
|
|
141
|
-
variant
|
|
142
|
-
} = options;
|
|
143
|
-
function score(value, keywords) {
|
|
144
|
-
const filter = propsRef.current?.filter ?? ((value2, search, keywords2) => commandScore(value2, search, keywords2));
|
|
145
|
-
return value ? filter(value, state.current.search, keywords) : 0;
|
|
146
|
-
}
|
|
147
|
-
return {
|
|
148
|
-
// Keep id → {value, keywords} mapping up-to-date
|
|
149
|
-
value: (id, value, keywords) => {
|
|
150
|
-
if (value !== ids.current.get(id)?.value) {
|
|
151
|
-
ids.current.set(id, { value: value || "", keywords });
|
|
152
|
-
state.current.filtered.items.set(id, score(value || "", keywords));
|
|
153
|
-
schedule(2, () => {
|
|
154
|
-
sort();
|
|
155
|
-
store.emit();
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
// Track item lifecycle (mount, unmount)
|
|
160
|
-
item: (id, groupId) => {
|
|
161
|
-
allItems.current.add(id);
|
|
162
|
-
if (groupId) {
|
|
163
|
-
if (!allGroups.current.has(groupId)) {
|
|
164
|
-
allGroups.current.set(groupId, /* @__PURE__ */ new Set([id]));
|
|
165
|
-
} else {
|
|
166
|
-
allGroups.current.get(groupId)?.add(id);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
schedule(3, () => {
|
|
170
|
-
filterItems();
|
|
171
|
-
sort();
|
|
172
|
-
if (!state.current.value) {
|
|
173
|
-
selectFirstItem();
|
|
174
|
-
}
|
|
175
|
-
store.emit();
|
|
176
|
-
});
|
|
177
|
-
return () => {
|
|
178
|
-
ids.current.delete(id);
|
|
179
|
-
allItems.current.delete(id);
|
|
180
|
-
state.current.filtered.items.delete(id);
|
|
181
|
-
schedule(4, () => {
|
|
182
|
-
filterItems();
|
|
183
|
-
const ITEM_SELECTOR2 = `[role="option"]`;
|
|
184
|
-
const selectedItem = listInnerRef.current?.querySelector(
|
|
185
|
-
`${ITEM_SELECTOR2}[aria-selected="true"]`
|
|
186
|
-
);
|
|
187
|
-
if (selectedItem?.getAttribute("id") === id) selectFirstItem();
|
|
188
|
-
store.emit();
|
|
189
|
-
});
|
|
190
|
-
};
|
|
191
|
-
},
|
|
192
|
-
// Track group lifecycle (mount, unmount)
|
|
193
|
-
group: (id) => {
|
|
194
|
-
if (!allGroups.current.has(id)) {
|
|
195
|
-
allGroups.current.set(id, /* @__PURE__ */ new Set());
|
|
196
|
-
}
|
|
197
|
-
return () => {
|
|
198
|
-
ids.current.delete(id);
|
|
199
|
-
allGroups.current.delete(id);
|
|
200
|
-
};
|
|
201
|
-
},
|
|
202
|
-
filter: () => {
|
|
203
|
-
return propsRef.current.shouldFilter !== false;
|
|
204
|
-
},
|
|
205
|
-
label: label || propsRef.current["aria-label"],
|
|
206
|
-
getDisablePointerSelection: () => {
|
|
207
|
-
return propsRef.current.disablePointerSelection ?? false;
|
|
208
|
-
},
|
|
209
|
-
listId,
|
|
210
|
-
inputId,
|
|
211
|
-
labelId,
|
|
212
|
-
listInnerRef,
|
|
213
|
-
store,
|
|
214
|
-
size,
|
|
215
|
-
variant
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
function useAsRef(data) {
|
|
219
|
-
const ref = React4.useRef(data);
|
|
220
|
-
usehooksTs.useIsomorphicLayoutEffect(() => {
|
|
221
|
-
ref.current = data;
|
|
222
|
-
});
|
|
223
|
-
return ref;
|
|
224
|
-
}
|
|
225
|
-
var useCommand = () => {
|
|
226
|
-
const context = React4__default.default.useContext(CommandContext);
|
|
227
|
-
if (!context) {
|
|
228
|
-
throw new Error("useCommand must be used within a Command component");
|
|
229
|
-
}
|
|
230
|
-
return context;
|
|
231
|
-
};
|
|
232
|
-
var useStore = () => {
|
|
233
|
-
const store = React4__default.default.useContext(StoreContext);
|
|
234
|
-
if (!store) {
|
|
235
|
-
throw new Error("useStore must be used within a Command component");
|
|
236
|
-
}
|
|
237
|
-
return store;
|
|
238
|
-
};
|
|
239
|
-
function useCommandState(selector) {
|
|
240
|
-
const store = useStore();
|
|
241
|
-
const cb = () => selector(store.snapshot());
|
|
242
|
-
return React4__default.default.useSyncExternalStore(store.subscribe, cb, cb);
|
|
243
|
-
}
|
|
244
|
-
var useScheduleLayoutEffect = () => {
|
|
245
|
-
const [updateCount, setUpdateCount] = React4.useState(0);
|
|
246
|
-
const fns = shared.useLazyRef(() => /* @__PURE__ */ new Map());
|
|
247
|
-
usehooksTs.useIsomorphicLayoutEffect(() => {
|
|
248
|
-
fns.current.forEach((f) => f());
|
|
249
|
-
fns.current = /* @__PURE__ */ new Map();
|
|
250
|
-
}, [updateCount]);
|
|
251
|
-
return React4.useCallback((id, cb) => {
|
|
252
|
-
fns.current.set(id, cb);
|
|
253
|
-
setUpdateCount((prev) => prev + 1);
|
|
254
|
-
}, []);
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
// src/utils/constants.ts
|
|
258
|
-
var GROUP_SELECTOR = `[role="presentation"]`;
|
|
259
|
-
var GROUP_ITEMS_SELECTOR = `[role="group"]`;
|
|
260
|
-
var GROUP_HEADING_SELECTOR = `[aria-hidden="true"]`;
|
|
261
|
-
var ITEM_SELECTOR = `[role="option"]`;
|
|
262
|
-
var VALID_ITEM_SELECTOR = `${ITEM_SELECTOR}:not([aria-disabled="true"])`;
|
|
263
|
-
var SELECT_EVENT = `cmdk-item-select`;
|
|
264
|
-
var VALUE_ATTR = `data-value`;
|
|
265
|
-
|
|
266
|
-
// src/utils/dom.ts
|
|
267
|
-
function findNextSibling(el, selector) {
|
|
268
|
-
let sibling = el.nextElementSibling;
|
|
269
|
-
while (sibling) {
|
|
270
|
-
if (sibling.matches(selector)) return sibling;
|
|
271
|
-
sibling = sibling.nextElementSibling;
|
|
272
|
-
}
|
|
273
|
-
return null;
|
|
274
|
-
}
|
|
275
|
-
function findPreviousSibling(el, selector) {
|
|
276
|
-
let sibling = el.previousElementSibling;
|
|
277
|
-
while (sibling) {
|
|
278
|
-
if (sibling.matches(selector)) return sibling;
|
|
279
|
-
sibling = sibling.previousElementSibling;
|
|
280
|
-
}
|
|
281
|
-
return null;
|
|
282
|
-
}
|
|
283
|
-
var useLayoutEffect = typeof window === "undefined" ? React4__default.default.useEffect : React4__default.default.useLayoutEffect;
|
|
284
|
-
function renderChildren(children) {
|
|
285
|
-
const childrenType = children.type;
|
|
286
|
-
if (typeof childrenType === "function") {
|
|
287
|
-
try {
|
|
288
|
-
return childrenType(children.props);
|
|
289
|
-
} catch {
|
|
290
|
-
return children;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
if (typeof childrenType === "object" && childrenType !== null && "render" in childrenType) {
|
|
294
|
-
const forwardRefComponent = childrenType;
|
|
295
|
-
return forwardRefComponent.render(children.props, null);
|
|
296
|
-
}
|
|
297
|
-
return children;
|
|
298
|
-
}
|
|
299
|
-
function SlottableWithNestedChildren({ asChild, children }, render) {
|
|
300
|
-
if (asChild && React4__default.default.isValidElement(children)) {
|
|
301
|
-
const renderedChild = renderChildren(children);
|
|
302
|
-
if (React4__default.default.isValidElement(renderedChild)) {
|
|
303
|
-
const childProps = children.props;
|
|
304
|
-
return React4__default.default.cloneElement(renderedChild, {}, render(childProps.children));
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
return render(children);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// src/hooks/use-value.ts
|
|
311
|
-
function useValue(id, ref, deps, aliases = []) {
|
|
312
|
-
const valueRef = React4.useRef();
|
|
313
|
-
const context = useCommand();
|
|
314
|
-
useLayoutEffect(() => {
|
|
315
|
-
const value = (() => {
|
|
316
|
-
for (const part of deps) {
|
|
317
|
-
if (typeof part === "string") {
|
|
318
|
-
return part.trim();
|
|
319
|
-
}
|
|
320
|
-
if (typeof part === "object" && part && "current" in part) {
|
|
321
|
-
if (part.current) {
|
|
322
|
-
return part.current.textContent?.trim();
|
|
323
|
-
}
|
|
324
|
-
return valueRef.current;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
return void 0;
|
|
328
|
-
})();
|
|
329
|
-
const keywords = aliases.map((alias) => alias.trim());
|
|
330
|
-
context.value(id, value || "", keywords);
|
|
331
|
-
ref.current?.setAttribute(VALUE_ATTR, value || "");
|
|
332
|
-
valueRef.current = value;
|
|
333
|
-
});
|
|
334
|
-
return valueRef;
|
|
335
|
-
}
|
|
336
|
-
var GroupContext = React4__default.default.createContext(void 0);
|
|
337
|
-
var commandTv = shared.tcv({
|
|
338
|
-
slots: {
|
|
339
|
-
root: "flex h-full w-full flex-col overflow-hidden",
|
|
340
|
-
divider: "my-2 h-px"
|
|
341
|
-
},
|
|
342
|
-
variants: {
|
|
343
|
-
variant: {
|
|
344
|
-
default: {
|
|
345
|
-
root: "bg-default-background text-default-foreground",
|
|
346
|
-
divider: "bg-default-boundary"
|
|
347
|
-
},
|
|
348
|
-
dark: {
|
|
349
|
-
root: "bg-menu-background text-white",
|
|
350
|
-
divider: "bg-menu-boundary"
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
var commandInputTv = shared.tcv({
|
|
356
|
-
slots: {
|
|
357
|
-
root: "m-2 flex items-center",
|
|
358
|
-
input: "w-full rounded-lg"
|
|
359
|
-
},
|
|
360
|
-
variants: {
|
|
361
|
-
size: {
|
|
362
|
-
default: {
|
|
363
|
-
input: "text-body-medium h-8 px-2"
|
|
364
|
-
},
|
|
365
|
-
large: {
|
|
366
|
-
input: "leading-lg tracking-lg h-10 px-4 text-body-large"
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
},
|
|
370
|
-
defaultVariants: {
|
|
371
|
-
size: "default"
|
|
372
|
-
}
|
|
373
|
-
});
|
|
374
|
-
var commandListTv = shared.tcv({
|
|
375
|
-
slots: {
|
|
376
|
-
root: "px-2 pb-2",
|
|
377
|
-
content: "flex flex-col"
|
|
378
|
-
}
|
|
379
|
-
});
|
|
380
|
-
var commandGroupTv = shared.tcv({
|
|
381
|
-
slots: {
|
|
382
|
-
root: "flex flex-col gap-1 not-first:mt-4",
|
|
383
|
-
heading: "text-body-medium px-2"
|
|
384
|
-
},
|
|
385
|
-
variants: {
|
|
386
|
-
variant: {
|
|
387
|
-
default: {
|
|
388
|
-
heading: "text-secondary-foreground"
|
|
389
|
-
},
|
|
390
|
-
dark: {
|
|
391
|
-
heading: "text-white/50"
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
var commandItemTv = shared.tcv({
|
|
397
|
-
slots: {
|
|
398
|
-
root: ["group/item relative flex items-center rounded-lg select-none", "focus:outline-none"],
|
|
399
|
-
icon: "flex flex-shrink-0 items-center justify-center rounded-md",
|
|
400
|
-
value: "flex-1 truncate",
|
|
401
|
-
shortcut: "text-secondary-foreground"
|
|
402
|
-
},
|
|
403
|
-
variants: {
|
|
404
|
-
variant: {
|
|
405
|
-
default: {},
|
|
406
|
-
dark: {
|
|
407
|
-
root: "text-white"
|
|
408
|
-
}
|
|
409
|
-
},
|
|
410
|
-
size: {
|
|
411
|
-
default: {
|
|
412
|
-
root: "text-body-medium min-h-8 p-1",
|
|
413
|
-
icon: "h-6 min-w-6"
|
|
414
|
-
},
|
|
415
|
-
large: {
|
|
416
|
-
root: "leading-lg tracking-lg min-h-10 p-2 text-body-large",
|
|
417
|
-
icon: "h-6 min-w-6"
|
|
418
|
-
}
|
|
419
|
-
},
|
|
420
|
-
hasPrefix: {
|
|
421
|
-
true: "",
|
|
422
|
-
false: ""
|
|
423
|
-
},
|
|
424
|
-
hasSuffix: {
|
|
425
|
-
true: "",
|
|
426
|
-
false: ""
|
|
427
|
-
},
|
|
428
|
-
selected: {
|
|
429
|
-
true: {},
|
|
430
|
-
false: {}
|
|
431
|
-
},
|
|
432
|
-
disabled: {
|
|
433
|
-
true: {
|
|
434
|
-
root: "pointer-events-none"
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
},
|
|
438
|
-
compoundVariants: [
|
|
439
|
-
{
|
|
440
|
-
hasPrefix: true,
|
|
441
|
-
size: "default",
|
|
442
|
-
class: {
|
|
443
|
-
root: "gap-1 pl-1"
|
|
444
|
-
}
|
|
445
|
-
},
|
|
446
|
-
{
|
|
447
|
-
hasPrefix: false,
|
|
448
|
-
size: "default",
|
|
449
|
-
class: {
|
|
450
|
-
root: "pl-2"
|
|
451
|
-
}
|
|
452
|
-
},
|
|
453
|
-
{
|
|
454
|
-
hasSuffix: true,
|
|
455
|
-
size: "default",
|
|
456
|
-
class: {
|
|
457
|
-
root: "gap-1 pr-1"
|
|
458
|
-
}
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
hasSuffix: false,
|
|
462
|
-
size: "default",
|
|
463
|
-
class: {
|
|
464
|
-
root: "pr-2"
|
|
465
|
-
}
|
|
466
|
-
},
|
|
467
|
-
// large
|
|
468
|
-
{
|
|
469
|
-
hasPrefix: true,
|
|
470
|
-
size: "large",
|
|
471
|
-
class: {
|
|
472
|
-
root: "gap-2 pl-2"
|
|
473
|
-
}
|
|
474
|
-
},
|
|
475
|
-
{
|
|
476
|
-
hasPrefix: false,
|
|
477
|
-
size: "large",
|
|
478
|
-
class: {
|
|
479
|
-
root: "pl-4"
|
|
480
|
-
}
|
|
481
|
-
},
|
|
482
|
-
{
|
|
483
|
-
hasSuffix: true,
|
|
484
|
-
size: "large",
|
|
485
|
-
class: {
|
|
486
|
-
root: "gap-2 pr-2"
|
|
487
|
-
}
|
|
488
|
-
},
|
|
489
|
-
{
|
|
490
|
-
hasSuffix: false,
|
|
491
|
-
size: "large",
|
|
492
|
-
class: {
|
|
493
|
-
root: "pr-4"
|
|
494
|
-
}
|
|
495
|
-
},
|
|
496
|
-
{
|
|
497
|
-
variant: "default",
|
|
498
|
-
selected: true,
|
|
499
|
-
class: {
|
|
500
|
-
root: "bg-secondary-background"
|
|
501
|
-
}
|
|
502
|
-
},
|
|
503
|
-
{
|
|
504
|
-
variant: "dark",
|
|
505
|
-
selected: true,
|
|
506
|
-
class: {
|
|
507
|
-
root: "bg-gray-700"
|
|
508
|
-
}
|
|
509
|
-
},
|
|
510
|
-
{
|
|
511
|
-
variant: "default",
|
|
512
|
-
disabled: true,
|
|
513
|
-
class: {
|
|
514
|
-
root: "text-secondary-foreground"
|
|
515
|
-
}
|
|
516
|
-
},
|
|
517
|
-
{
|
|
518
|
-
variant: "dark",
|
|
519
|
-
disabled: true,
|
|
520
|
-
class: {
|
|
521
|
-
root: "text-white/50"
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
],
|
|
525
|
-
defaultVariants: {
|
|
526
|
-
size: "default",
|
|
527
|
-
hasPrefix: false,
|
|
528
|
-
hasSuffix: false,
|
|
529
|
-
variant: "default"
|
|
530
|
-
}
|
|
531
|
-
});
|
|
532
|
-
var commandFooterTv = shared.tcv({
|
|
533
|
-
slots: {
|
|
534
|
-
root: "flex h-10 items-center justify-between border-t px-2"
|
|
535
|
-
},
|
|
536
|
-
variants: {
|
|
537
|
-
variant: {
|
|
538
|
-
default: {
|
|
539
|
-
root: "border-default-boundary"
|
|
540
|
-
},
|
|
541
|
-
dark: {
|
|
542
|
-
root: "border-menu-boundary"
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
},
|
|
546
|
-
defaultVariants: {
|
|
547
|
-
variant: "default"
|
|
548
|
-
}
|
|
549
|
-
});
|
|
550
|
-
var commandTabsTv = shared.tcv({
|
|
551
|
-
slots: {
|
|
552
|
-
tabs: "mx-2 mb-2"
|
|
553
|
-
}
|
|
554
|
-
});
|
|
555
|
-
var commandEmptyTv = shared.tcv({
|
|
556
|
-
slots: {
|
|
557
|
-
root: "py-6 text-center"
|
|
558
|
-
},
|
|
559
|
-
variants: {
|
|
560
|
-
variant: {
|
|
561
|
-
default: {
|
|
562
|
-
root: "text-secondary-foreground"
|
|
563
|
-
},
|
|
564
|
-
dark: {
|
|
565
|
-
root: "text-white/50"
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
});
|
|
570
|
-
var commandLoadingTv = shared.tcv({
|
|
571
|
-
slots: {
|
|
572
|
-
root: "flex items-center justify-center py-6 text-center"
|
|
573
|
-
}
|
|
574
|
-
});
|
|
575
|
-
var defaultFilter = (value, search, keywords) => commandScore(value, search, keywords);
|
|
576
|
-
var Command = React4.forwardRef((props, forwardedRef) => {
|
|
577
|
-
const state = shared.useLazyRef(() => ({
|
|
578
|
-
/** Value of the search query. */
|
|
579
|
-
search: "",
|
|
580
|
-
/** Currently selected item value. */
|
|
581
|
-
value: props.value ?? props.defaultValue ?? "",
|
|
582
|
-
/** Currently selected item id. */
|
|
583
|
-
selectedItemId: void 0,
|
|
584
|
-
filtered: {
|
|
585
|
-
/** The count of all visible items. */
|
|
586
|
-
count: 0,
|
|
587
|
-
/** Map from visible item id to its search score. */
|
|
588
|
-
items: /* @__PURE__ */ new Map(),
|
|
589
|
-
/** Set of groups with at least one visible item. */
|
|
590
|
-
groups: /* @__PURE__ */ new Set()
|
|
591
|
-
}
|
|
592
|
-
}));
|
|
593
|
-
const allItems = shared.useLazyRef(() => /* @__PURE__ */ new Set());
|
|
594
|
-
const allGroups = shared.useLazyRef(() => /* @__PURE__ */ new Map());
|
|
595
|
-
const ids = shared.useLazyRef(() => /* @__PURE__ */ new Map());
|
|
596
|
-
const listeners = shared.useLazyRef(() => /* @__PURE__ */ new Set());
|
|
597
|
-
const propsRef = useAsRef(props);
|
|
598
|
-
const {
|
|
599
|
-
label,
|
|
600
|
-
children,
|
|
601
|
-
value,
|
|
602
|
-
onChange: onValueChange,
|
|
603
|
-
filter,
|
|
604
|
-
shouldFilter,
|
|
605
|
-
loop,
|
|
606
|
-
size = "default",
|
|
607
|
-
variant = "default",
|
|
608
|
-
disablePointerSelection = false,
|
|
609
|
-
vimBindings = true,
|
|
610
|
-
className,
|
|
611
|
-
...etc
|
|
612
|
-
} = props;
|
|
613
|
-
const listId = React4.useId();
|
|
614
|
-
const labelId = React4.useId();
|
|
615
|
-
const inputId = React4.useId();
|
|
616
|
-
const listInnerRef = React4.useRef(null);
|
|
617
|
-
const schedule = useScheduleLayoutEffect();
|
|
618
|
-
const tv = commandTv({ variant });
|
|
619
|
-
const store = React4.useMemo(() => {
|
|
620
|
-
return {
|
|
621
|
-
subscribe: (cb) => {
|
|
622
|
-
listeners.current.add(cb);
|
|
623
|
-
return () => listeners.current.delete(cb);
|
|
624
|
-
},
|
|
625
|
-
snapshot: () => {
|
|
626
|
-
return state.current;
|
|
627
|
-
},
|
|
628
|
-
setState: (key, value2, opts) => {
|
|
629
|
-
if (Object.is(state.current[key], value2)) return;
|
|
630
|
-
state.current[key] = value2;
|
|
631
|
-
if (key === "search") {
|
|
632
|
-
filterItems();
|
|
633
|
-
sort();
|
|
634
|
-
schedule(1, selectFirstItem);
|
|
635
|
-
} else if (key === "value") {
|
|
636
|
-
const activeElement = document.activeElement;
|
|
637
|
-
if (activeElement?.hasAttribute("data-command-input") || activeElement?.hasAttribute("data-command-root")) {
|
|
638
|
-
const input = document.getElementById(inputId);
|
|
639
|
-
if (input) input.focus();
|
|
640
|
-
else document.getElementById(listId)?.focus();
|
|
641
|
-
}
|
|
642
|
-
schedule(7, () => {
|
|
643
|
-
state.current.selectedItemId = getSelectedItem()?.id;
|
|
644
|
-
store.emit();
|
|
645
|
-
});
|
|
646
|
-
if (!opts) {
|
|
647
|
-
schedule(5, scrollSelectedIntoView);
|
|
648
|
-
}
|
|
649
|
-
if (propsRef.current?.value !== void 0) {
|
|
650
|
-
const newValue = value2 ?? "";
|
|
651
|
-
propsRef.current.onChange?.(newValue);
|
|
652
|
-
return;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
store.emit();
|
|
656
|
-
},
|
|
657
|
-
emit: () => {
|
|
658
|
-
listeners.current.forEach((l) => l());
|
|
659
|
-
}
|
|
660
|
-
};
|
|
661
|
-
}, []);
|
|
662
|
-
usehooksTs.useIsomorphicLayoutEffect(() => {
|
|
663
|
-
if (value !== void 0) {
|
|
664
|
-
const v = value.trim();
|
|
665
|
-
state.current.value = v;
|
|
666
|
-
store.emit();
|
|
667
|
-
}
|
|
668
|
-
}, [value]);
|
|
669
|
-
usehooksTs.useIsomorphicLayoutEffect(() => {
|
|
670
|
-
schedule(6, scrollSelectedIntoView);
|
|
671
|
-
}, []);
|
|
672
|
-
const score = usehooksTs.useEventCallback((value2, keywords) => {
|
|
673
|
-
const filter2 = propsRef.current?.filter ?? defaultFilter;
|
|
674
|
-
return value2 ? filter2(value2, state.current.search, keywords) : 0;
|
|
675
|
-
});
|
|
676
|
-
const sort = React4.useCallback(() => {
|
|
677
|
-
if (!state.current.search || // Explicitly false, because true | undefined is the default
|
|
678
|
-
propsRef.current.shouldFilter === false) {
|
|
679
|
-
return;
|
|
680
|
-
}
|
|
681
|
-
const scores = state.current.filtered.items;
|
|
682
|
-
const groups = [];
|
|
683
|
-
state.current.filtered.groups.forEach((value2) => {
|
|
684
|
-
const items = allGroups.current.get(value2);
|
|
685
|
-
let max = 0;
|
|
686
|
-
items?.forEach((item) => {
|
|
687
|
-
const score2 = scores.get(item) ?? 0;
|
|
688
|
-
max = Math.max(score2, max);
|
|
689
|
-
});
|
|
690
|
-
groups.push([value2, max]);
|
|
691
|
-
});
|
|
692
|
-
const listInsertionElement = listInnerRef.current;
|
|
693
|
-
getValidItems().sort((a, b) => {
|
|
694
|
-
const valueA = a.getAttribute("id");
|
|
695
|
-
const valueB = b.getAttribute("id");
|
|
696
|
-
return (scores.get(valueB ?? "") ?? 0) - (scores.get(valueA ?? "") ?? 0);
|
|
697
|
-
}).forEach((item) => {
|
|
698
|
-
const group = item.closest(GROUP_ITEMS_SELECTOR);
|
|
699
|
-
if (group) {
|
|
700
|
-
const elementToMove = item.parentElement === group ? item : item.closest(`${GROUP_ITEMS_SELECTOR} > *`);
|
|
701
|
-
if (elementToMove) group.appendChild(elementToMove);
|
|
702
|
-
} else {
|
|
703
|
-
const elementToMove = item.parentElement === listInsertionElement ? item : item.closest(`${GROUP_ITEMS_SELECTOR} > *`);
|
|
704
|
-
if (elementToMove) listInsertionElement?.appendChild(elementToMove);
|
|
705
|
-
}
|
|
706
|
-
});
|
|
707
|
-
groups.sort((a, b) => b[1] - a[1]).forEach((group) => {
|
|
708
|
-
const element = listInnerRef.current?.querySelector(
|
|
709
|
-
`${GROUP_SELECTOR}[${VALUE_ATTR}="${encodeURIComponent(group[0])}"]`
|
|
710
|
-
);
|
|
711
|
-
if (element && element.parentElement) {
|
|
712
|
-
element.parentElement.appendChild(element);
|
|
713
|
-
}
|
|
714
|
-
});
|
|
715
|
-
}, []);
|
|
716
|
-
const selectFirstItem = React4.useCallback(() => {
|
|
717
|
-
const item = getValidItems().find((item2) => item2.getAttribute("aria-disabled") !== "true");
|
|
718
|
-
const value2 = item?.getAttribute(VALUE_ATTR);
|
|
719
|
-
store.setState("value", value2 || "");
|
|
720
|
-
}, []);
|
|
721
|
-
const filterItems = React4.useCallback(() => {
|
|
722
|
-
if (!state.current.search || // Explicitly false, because true | undefined is the default
|
|
723
|
-
propsRef.current.shouldFilter === false) {
|
|
724
|
-
state.current.filtered.count = allItems.current.size;
|
|
725
|
-
return;
|
|
726
|
-
}
|
|
727
|
-
state.current.filtered.groups = /* @__PURE__ */ new Set();
|
|
728
|
-
let itemCount = 0;
|
|
729
|
-
for (const id of allItems.current) {
|
|
730
|
-
const value2 = ids.current.get(id)?.value ?? "";
|
|
731
|
-
const keywords = ids.current.get(id)?.keywords ?? [];
|
|
732
|
-
const rank = score(value2, keywords);
|
|
733
|
-
state.current.filtered.items.set(id, rank);
|
|
734
|
-
if (rank > 0) itemCount++;
|
|
735
|
-
}
|
|
736
|
-
for (const [groupId, group] of allGroups.current) {
|
|
737
|
-
for (const itemId of group) {
|
|
738
|
-
if ((state.current.filtered.items.get(itemId) ?? 0) > 0) {
|
|
739
|
-
state.current.filtered.groups.add(groupId);
|
|
740
|
-
break;
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
state.current.filtered.count = itemCount;
|
|
745
|
-
}, []);
|
|
746
|
-
const scrollSelectedIntoView = React4.useCallback(() => {
|
|
747
|
-
const item = getSelectedItem();
|
|
748
|
-
if (item) {
|
|
749
|
-
if (item.parentElement?.firstChild === item) {
|
|
750
|
-
item.closest(GROUP_SELECTOR)?.querySelector(GROUP_HEADING_SELECTOR)?.scrollIntoView({ block: "nearest" });
|
|
751
|
-
}
|
|
752
|
-
item.scrollIntoView({ block: "nearest" });
|
|
753
|
-
}
|
|
754
|
-
}, []);
|
|
755
|
-
const getSelectedItem = React4.useCallback(() => {
|
|
756
|
-
return listInnerRef.current?.querySelector(`${ITEM_SELECTOR}[aria-selected="true"]`);
|
|
757
|
-
}, []);
|
|
758
|
-
function getValidItems() {
|
|
759
|
-
return Array.from(
|
|
760
|
-
listInnerRef.current?.querySelectorAll(VALID_ITEM_SELECTOR) || []
|
|
761
|
-
);
|
|
762
|
-
}
|
|
763
|
-
const updateSelectedToIndex = usehooksTs.useEventCallback((index) => {
|
|
764
|
-
const items = getValidItems();
|
|
765
|
-
const item = items[index];
|
|
766
|
-
if (item) store.setState("value", item.getAttribute(VALUE_ATTR) || "");
|
|
767
|
-
});
|
|
768
|
-
const updateSelectedByItem = usehooksTs.useEventCallback((change) => {
|
|
769
|
-
const selected = getSelectedItem();
|
|
770
|
-
const items = getValidItems();
|
|
771
|
-
const index = items.findIndex((item) => item === selected);
|
|
772
|
-
let newSelected = items[index + change];
|
|
773
|
-
if (propsRef.current?.loop) {
|
|
774
|
-
newSelected = index + change < 0 ? items[items.length - 1] : index + change === items.length ? items[0] : items[index + change];
|
|
775
|
-
}
|
|
776
|
-
if (newSelected) store.setState("value", newSelected.getAttribute(VALUE_ATTR) || "");
|
|
777
|
-
});
|
|
778
|
-
const updateSelectedByGroup = usehooksTs.useEventCallback((change) => {
|
|
779
|
-
const selected = getSelectedItem();
|
|
780
|
-
let group = selected?.closest(GROUP_SELECTOR);
|
|
781
|
-
let item = null;
|
|
782
|
-
while (group && !item) {
|
|
783
|
-
group = change > 0 ? findNextSibling(group, GROUP_SELECTOR) : findPreviousSibling(group, GROUP_SELECTOR);
|
|
784
|
-
item = group?.querySelector(VALID_ITEM_SELECTOR);
|
|
785
|
-
}
|
|
786
|
-
if (item) {
|
|
787
|
-
store.setState("value", item.getAttribute(VALUE_ATTR) || "");
|
|
788
|
-
} else {
|
|
789
|
-
updateSelectedByItem(change);
|
|
790
|
-
}
|
|
791
|
-
});
|
|
792
|
-
const context = React4.useMemo(
|
|
793
|
-
() => createCommandContext({
|
|
794
|
-
allGroups,
|
|
795
|
-
allItems,
|
|
796
|
-
filterItems,
|
|
797
|
-
ids,
|
|
798
|
-
inputId,
|
|
799
|
-
label,
|
|
800
|
-
labelId,
|
|
801
|
-
listId,
|
|
802
|
-
listInnerRef,
|
|
803
|
-
propsRef,
|
|
804
|
-
schedule,
|
|
805
|
-
selectFirstItem,
|
|
806
|
-
size,
|
|
807
|
-
sort,
|
|
808
|
-
state,
|
|
809
|
-
store,
|
|
810
|
-
variant
|
|
811
|
-
}),
|
|
812
|
-
[]
|
|
813
|
-
// ❌ 空依赖数组,和原始实现一致
|
|
814
|
-
);
|
|
815
|
-
const last = () => updateSelectedToIndex(getValidItems().length - 1);
|
|
816
|
-
const next = (e) => {
|
|
817
|
-
e.preventDefault();
|
|
818
|
-
if (e.metaKey) {
|
|
819
|
-
last();
|
|
820
|
-
} else if (e.altKey) {
|
|
821
|
-
updateSelectedByGroup(1);
|
|
822
|
-
} else {
|
|
823
|
-
updateSelectedByItem(1);
|
|
824
|
-
}
|
|
825
|
-
};
|
|
826
|
-
const prev = (e) => {
|
|
827
|
-
e.preventDefault();
|
|
828
|
-
if (e.metaKey) {
|
|
829
|
-
updateSelectedToIndex(0);
|
|
830
|
-
} else if (e.altKey) {
|
|
831
|
-
updateSelectedByGroup(-1);
|
|
832
|
-
} else {
|
|
833
|
-
updateSelectedByItem(-1);
|
|
834
|
-
}
|
|
835
|
-
};
|
|
836
|
-
const handleKeyDown = usehooksTs.useEventCallback((e) => {
|
|
837
|
-
etc.onKeyDown?.(e);
|
|
838
|
-
const isComposing = e.nativeEvent.isComposing || e.keyCode === 229;
|
|
839
|
-
if (e.defaultPrevented || isComposing) {
|
|
840
|
-
return;
|
|
841
|
-
}
|
|
842
|
-
switch (e.key) {
|
|
843
|
-
case "n":
|
|
844
|
-
case "j": {
|
|
845
|
-
if (vimBindings && e.ctrlKey) {
|
|
846
|
-
next(e);
|
|
847
|
-
}
|
|
848
|
-
break;
|
|
849
|
-
}
|
|
850
|
-
case "ArrowDown": {
|
|
851
|
-
next(e);
|
|
852
|
-
break;
|
|
853
|
-
}
|
|
854
|
-
case "p":
|
|
855
|
-
case "k": {
|
|
856
|
-
if (vimBindings && e.ctrlKey) {
|
|
857
|
-
prev(e);
|
|
858
|
-
}
|
|
859
|
-
break;
|
|
860
|
-
}
|
|
861
|
-
case "ArrowUp": {
|
|
862
|
-
prev(e);
|
|
863
|
-
break;
|
|
864
|
-
}
|
|
865
|
-
case "Home": {
|
|
866
|
-
e.preventDefault();
|
|
867
|
-
updateSelectedToIndex(0);
|
|
868
|
-
break;
|
|
869
|
-
}
|
|
870
|
-
case "End": {
|
|
871
|
-
e.preventDefault();
|
|
872
|
-
last();
|
|
873
|
-
break;
|
|
874
|
-
}
|
|
875
|
-
case "Enter": {
|
|
876
|
-
e.preventDefault();
|
|
877
|
-
const item = getSelectedItem();
|
|
878
|
-
if (item) {
|
|
879
|
-
const event = new Event(SELECT_EVENT);
|
|
880
|
-
item.dispatchEvent(event);
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
});
|
|
885
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
886
|
-
"div",
|
|
887
|
-
{
|
|
888
|
-
ref: forwardedRef,
|
|
889
|
-
tabIndex: -1,
|
|
890
|
-
...etc,
|
|
891
|
-
className: shared.tcx(tv.root({ className })),
|
|
892
|
-
"data-command-root": "",
|
|
893
|
-
onKeyDown: handleKeyDown,
|
|
894
|
-
children: [
|
|
895
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
896
|
-
"label",
|
|
897
|
-
{
|
|
898
|
-
htmlFor: context.inputId,
|
|
899
|
-
id: context.labelId,
|
|
900
|
-
className: "sr-only",
|
|
901
|
-
children: label
|
|
902
|
-
}
|
|
903
|
-
),
|
|
904
|
-
SlottableWithNestedChildren(props, (child) => /* @__PURE__ */ jsxRuntime.jsx(StoreContext.Provider, { value: store, children: /* @__PURE__ */ jsxRuntime.jsx(CommandContext.Provider, { value: context, children: child }) }))
|
|
905
|
-
]
|
|
906
|
-
}
|
|
907
|
-
);
|
|
908
|
-
});
|
|
909
|
-
Command.displayName = "Command";
|
|
910
|
-
var CommandEmpty = React4.forwardRef(
|
|
911
|
-
({ className, ...props }, forwardedRef) => {
|
|
912
|
-
const context = useCommand();
|
|
913
|
-
const render = useCommandState((state) => state.filtered.count === 0);
|
|
914
|
-
const tv = commandEmptyTv({ variant: context.variant });
|
|
915
|
-
if (!render) return null;
|
|
916
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
917
|
-
"div",
|
|
918
|
-
{
|
|
919
|
-
ref: forwardedRef,
|
|
920
|
-
...props,
|
|
921
|
-
className: shared.tcx(tv.root({ className })),
|
|
922
|
-
role: "presentation"
|
|
923
|
-
}
|
|
924
|
-
);
|
|
925
|
-
}
|
|
926
|
-
);
|
|
927
|
-
CommandEmpty.displayName = "CommandEmpty";
|
|
928
|
-
var CommandFooter = React4.forwardRef(
|
|
929
|
-
({ className, ...props }, ref) => {
|
|
930
|
-
const context = useCommand();
|
|
931
|
-
const tv = commandFooterTv({ variant: context.variant });
|
|
932
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
933
|
-
"div",
|
|
934
|
-
{
|
|
935
|
-
ref,
|
|
936
|
-
className: shared.tcx(tv.root({ className })),
|
|
937
|
-
...props
|
|
938
|
-
}
|
|
939
|
-
);
|
|
940
|
-
}
|
|
941
|
-
);
|
|
942
|
-
CommandFooter.displayName = "CommandFooter";
|
|
943
|
-
var CommandGroup = React4.forwardRef((props, forwardedRef) => {
|
|
944
|
-
const { className, heading, children, forceMount, value, ...rest } = props;
|
|
945
|
-
const id = React4.useId();
|
|
946
|
-
const ref = React4.useRef(null);
|
|
947
|
-
const headingRef = React4.useRef(null);
|
|
948
|
-
const headingId = React4__default.default.useId();
|
|
949
|
-
const context = useCommand();
|
|
950
|
-
const render = useCommandState(
|
|
951
|
-
(state) => forceMount ? true : context.filter() === false ? true : !state.search ? true : state.filtered.groups.has(id)
|
|
952
|
-
);
|
|
953
|
-
React4.useEffect(() => {
|
|
954
|
-
return context.group(id);
|
|
955
|
-
}, [context, id]);
|
|
956
|
-
const valueDeps = React4.useMemo(() => [value, heading, headingRef], [value, heading]);
|
|
957
|
-
useValue(id, ref, valueDeps);
|
|
958
|
-
const contextValue = React4.useMemo(() => ({ id, forceMount }), [id, forceMount]);
|
|
959
|
-
const tv = commandGroupTv({ variant: context.variant });
|
|
960
|
-
if (!render) return null;
|
|
961
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
962
|
-
"div",
|
|
963
|
-
{
|
|
964
|
-
ref: (el) => {
|
|
965
|
-
ref.current = el;
|
|
966
|
-
if (typeof forwardedRef === "function") forwardedRef(el);
|
|
967
|
-
else if (forwardedRef) forwardedRef.current = el;
|
|
968
|
-
},
|
|
969
|
-
...rest,
|
|
970
|
-
className: shared.tcx(tv.root({ className })),
|
|
971
|
-
role: "presentation",
|
|
972
|
-
"data-value": value,
|
|
973
|
-
children: [
|
|
974
|
-
heading && /* @__PURE__ */ jsxRuntime.jsx(
|
|
975
|
-
"div",
|
|
976
|
-
{
|
|
977
|
-
ref: headingRef,
|
|
978
|
-
className: shared.tcx(tv.heading()),
|
|
979
|
-
"aria-hidden": true,
|
|
980
|
-
id: headingId,
|
|
981
|
-
children: heading
|
|
982
|
-
}
|
|
983
|
-
),
|
|
984
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
985
|
-
"div",
|
|
986
|
-
{
|
|
987
|
-
role: "group",
|
|
988
|
-
"aria-labelledby": heading ? headingId : void 0,
|
|
989
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(GroupContext.Provider, { value: contextValue, children })
|
|
990
|
-
}
|
|
991
|
-
)
|
|
992
|
-
]
|
|
993
|
-
}
|
|
994
|
-
);
|
|
995
|
-
});
|
|
996
|
-
CommandGroup.displayName = "CommandGroup";
|
|
997
|
-
var CommandInput = React4.forwardRef((props, ref) => {
|
|
998
|
-
const { className, onChange, value, prefixElement, suffixElement, ...rest } = props;
|
|
999
|
-
const isControlled = value != null;
|
|
1000
|
-
const store = useCommand().store;
|
|
1001
|
-
const search = useCommandState((state) => state.search);
|
|
1002
|
-
const selectedItemId = useCommandState((state) => state.selectedItemId);
|
|
1003
|
-
const context = useCommand();
|
|
1004
|
-
React4.useEffect(() => {
|
|
1005
|
-
if (value != null) {
|
|
1006
|
-
store.setState("search", value);
|
|
1007
|
-
}
|
|
1008
|
-
}, [value, store]);
|
|
1009
|
-
const handleChange = usehooksTs.useEventCallback((value2) => {
|
|
1010
|
-
if (!isControlled) {
|
|
1011
|
-
store.setState("search", value2);
|
|
1012
|
-
}
|
|
1013
|
-
onChange?.(value2);
|
|
1014
|
-
});
|
|
1015
|
-
const tv = commandInputTv({ size: context.size });
|
|
1016
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: shared.tcx(tv.root({ className })), children: [
|
|
1017
|
-
prefixElement,
|
|
1018
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1019
|
-
input.Input,
|
|
1020
|
-
{
|
|
1021
|
-
ref,
|
|
1022
|
-
...rest,
|
|
1023
|
-
className: shared.tcx(tv.input({ className })),
|
|
1024
|
-
variant: props.variant || context.variant,
|
|
1025
|
-
"data-command-input": "",
|
|
1026
|
-
autoComplete: "off",
|
|
1027
|
-
autoCorrect: "off",
|
|
1028
|
-
spellCheck: false,
|
|
1029
|
-
"aria-autocomplete": "list",
|
|
1030
|
-
role: "combobox",
|
|
1031
|
-
"aria-expanded": true,
|
|
1032
|
-
"aria-controls": context.listId,
|
|
1033
|
-
"aria-labelledby": context.labelId,
|
|
1034
|
-
"aria-activedescendant": selectedItemId,
|
|
1035
|
-
id: context.inputId,
|
|
1036
|
-
type: "text",
|
|
1037
|
-
value: isControlled ? value : search,
|
|
1038
|
-
onChange: handleChange
|
|
1039
|
-
}
|
|
1040
|
-
),
|
|
1041
|
-
suffixElement
|
|
1042
|
-
] });
|
|
1043
|
-
});
|
|
1044
|
-
CommandInput.displayName = "CommandInput";
|
|
1045
|
-
var CommandItem = React4.forwardRef((props, forwardedRef) => {
|
|
1046
|
-
const {
|
|
1047
|
-
className,
|
|
1048
|
-
disabled,
|
|
1049
|
-
forceMount,
|
|
1050
|
-
keywords,
|
|
1051
|
-
onSelect,
|
|
1052
|
-
value,
|
|
1053
|
-
children,
|
|
1054
|
-
prefixElement,
|
|
1055
|
-
suffixElement,
|
|
1056
|
-
shortcut,
|
|
1057
|
-
...rest
|
|
1058
|
-
} = props;
|
|
1059
|
-
const ref = React4.useRef(null);
|
|
1060
|
-
const id = React4__default.default.useId();
|
|
1061
|
-
const context = useCommand();
|
|
1062
|
-
const groupContext = React4__default.default.useContext(GroupContext);
|
|
1063
|
-
const propsRef = React4.useRef({
|
|
1064
|
-
disabled,
|
|
1065
|
-
forceMount: forceMount ?? groupContext?.forceMount,
|
|
1066
|
-
keywords,
|
|
1067
|
-
onSelect,
|
|
1068
|
-
value
|
|
1069
|
-
});
|
|
1070
|
-
propsRef.current = {
|
|
1071
|
-
disabled,
|
|
1072
|
-
forceMount: forceMount ?? groupContext?.forceMount,
|
|
1073
|
-
keywords,
|
|
1074
|
-
onSelect,
|
|
1075
|
-
value
|
|
1076
|
-
};
|
|
1077
|
-
React4.useEffect(() => {
|
|
1078
|
-
if (!propsRef.current.forceMount) {
|
|
1079
|
-
return context.item(id, groupContext?.id);
|
|
1080
|
-
}
|
|
1081
|
-
}, [context, groupContext?.id, id]);
|
|
1082
|
-
const valueDeps = React4.useMemo(() => [value, children, ref], [value, children]);
|
|
1083
|
-
const stableKeywords = React4.useMemo(() => keywords || [], [keywords]);
|
|
1084
|
-
const valueRef = useValue(id, ref, valueDeps, stableKeywords);
|
|
1085
|
-
const store = context.store;
|
|
1086
|
-
const selected = useCommandState(
|
|
1087
|
-
(state) => Boolean(state.value && state.value === valueRef?.current)
|
|
1088
|
-
);
|
|
1089
|
-
const render = useCommandState(
|
|
1090
|
-
(state) => propsRef.current.forceMount ? true : context.filter() === false ? true : !state.search ? true : (state.filtered.items.get(id) ?? 0) > 0
|
|
1091
|
-
);
|
|
1092
|
-
React4.useEffect(() => {
|
|
1093
|
-
const element = ref.current;
|
|
1094
|
-
if (!element || disabled) return;
|
|
1095
|
-
const handleSelect = () => {
|
|
1096
|
-
select();
|
|
1097
|
-
propsRef.current.onSelect?.(valueRef.current || "");
|
|
1098
|
-
};
|
|
1099
|
-
element.addEventListener(SELECT_EVENT, handleSelect);
|
|
1100
|
-
return () => element.removeEventListener(SELECT_EVENT, handleSelect);
|
|
1101
|
-
}, [render, disabled, valueRef]);
|
|
1102
|
-
const select = () => {
|
|
1103
|
-
store.setState("value", valueRef.current || "", true);
|
|
1104
|
-
};
|
|
1105
|
-
const hasValidShortcut = shortcut && (shortcut.modifier || shortcut.keys);
|
|
1106
|
-
const handlePointerMove = usehooksTs.useEventCallback(() => {
|
|
1107
|
-
if (disabled || context.getDisablePointerSelection()) return;
|
|
1108
|
-
select();
|
|
1109
|
-
});
|
|
1110
|
-
const handleClick = usehooksTs.useEventCallback(() => {
|
|
1111
|
-
if (disabled) return;
|
|
1112
|
-
propsRef.current.onSelect?.(valueRef.current || "");
|
|
1113
|
-
});
|
|
1114
|
-
const tv = commandItemTv({
|
|
1115
|
-
selected,
|
|
1116
|
-
disabled,
|
|
1117
|
-
size: context.size,
|
|
1118
|
-
hasPrefix: !!prefixElement,
|
|
1119
|
-
hasSuffix: !!suffixElement,
|
|
1120
|
-
variant: context.variant
|
|
1121
|
-
});
|
|
1122
|
-
if (!render) return null;
|
|
1123
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1124
|
-
"div",
|
|
1125
|
-
{
|
|
1126
|
-
ref: (el) => {
|
|
1127
|
-
ref.current = el;
|
|
1128
|
-
if (typeof forwardedRef === "function") forwardedRef(el);
|
|
1129
|
-
else if (forwardedRef) forwardedRef.current = el;
|
|
1130
|
-
},
|
|
1131
|
-
...rest,
|
|
1132
|
-
id,
|
|
1133
|
-
className: shared.tcx(tv.root({ className })),
|
|
1134
|
-
role: "option",
|
|
1135
|
-
"aria-disabled": disabled,
|
|
1136
|
-
"aria-selected": selected || void 0,
|
|
1137
|
-
"data-disabled": disabled,
|
|
1138
|
-
"data-selected": selected,
|
|
1139
|
-
"data-value": valueRef.current,
|
|
1140
|
-
onPointerMove: handlePointerMove,
|
|
1141
|
-
onClick: handleClick,
|
|
1142
|
-
children: [
|
|
1143
|
-
prefixElement && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tv.icon(), children: prefixElement }),
|
|
1144
|
-
children,
|
|
1145
|
-
hasValidShortcut && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1146
|
-
kbd.Kbd,
|
|
1147
|
-
{
|
|
1148
|
-
className: tv.shortcut(),
|
|
1149
|
-
keys: shortcut.modifier,
|
|
1150
|
-
children: shortcut.keys
|
|
1151
|
-
}
|
|
1152
|
-
),
|
|
1153
|
-
suffixElement && /* @__PURE__ */ jsxRuntime.jsx("div", { className: tv.icon(), children: suffixElement })
|
|
1154
|
-
]
|
|
1155
|
-
}
|
|
1156
|
-
);
|
|
1157
|
-
});
|
|
1158
|
-
CommandItem.displayName = "CommandItem";
|
|
1159
|
-
var CommandList = React4.forwardRef((props, forwardedRef) => {
|
|
1160
|
-
const { children, className, label = "Suggestions", hoverBoundary = "none", ...rest } = props;
|
|
1161
|
-
const ref = React4.useRef(null);
|
|
1162
|
-
const height = React4.useRef(null);
|
|
1163
|
-
const selectedItemId = useCommandState((state) => state.selectedItemId);
|
|
1164
|
-
const context = useCommand();
|
|
1165
|
-
React4.useEffect(() => {
|
|
1166
|
-
if (height.current && ref.current) {
|
|
1167
|
-
const el = height.current;
|
|
1168
|
-
const wrapper = ref.current;
|
|
1169
|
-
let animationFrame;
|
|
1170
|
-
const observer = new ResizeObserver(() => {
|
|
1171
|
-
animationFrame = requestAnimationFrame(() => {
|
|
1172
|
-
const height2 = el.offsetHeight;
|
|
1173
|
-
wrapper.style.setProperty(`--cmdk-list-height`, height2.toFixed(1) + "px");
|
|
1174
|
-
});
|
|
1175
|
-
});
|
|
1176
|
-
observer.observe(el);
|
|
1177
|
-
return () => {
|
|
1178
|
-
cancelAnimationFrame(animationFrame);
|
|
1179
|
-
observer.unobserve(el);
|
|
1180
|
-
};
|
|
1181
|
-
}
|
|
1182
|
-
}, []);
|
|
1183
|
-
const tv = commandListTv();
|
|
1184
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1185
|
-
scrollArea.ScrollArea,
|
|
1186
|
-
{
|
|
1187
|
-
variant: context.variant,
|
|
1188
|
-
hoverBoundary,
|
|
1189
|
-
...rest,
|
|
1190
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1191
|
-
scrollArea.ScrollArea.Viewport,
|
|
1192
|
-
{
|
|
1193
|
-
ref: (el) => {
|
|
1194
|
-
ref.current = el;
|
|
1195
|
-
if (typeof forwardedRef === "function") forwardedRef(el);
|
|
1196
|
-
else if (forwardedRef) forwardedRef.current = el;
|
|
1197
|
-
},
|
|
1198
|
-
...rest,
|
|
1199
|
-
className: shared.tcx(tv.root({ className })),
|
|
1200
|
-
role: "listbox",
|
|
1201
|
-
tabIndex: -1,
|
|
1202
|
-
"aria-activedescendant": selectedItemId,
|
|
1203
|
-
"aria-label": label,
|
|
1204
|
-
id: context.listId,
|
|
1205
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1206
|
-
scrollArea.ScrollArea.Content,
|
|
1207
|
-
{
|
|
1208
|
-
className: shared.tcx(tv.content()),
|
|
1209
|
-
ref: (el) => {
|
|
1210
|
-
height.current = el;
|
|
1211
|
-
if (context.listInnerRef) {
|
|
1212
|
-
context.listInnerRef.current = el;
|
|
1213
|
-
}
|
|
1214
|
-
},
|
|
1215
|
-
children
|
|
1216
|
-
}
|
|
1217
|
-
)
|
|
1218
|
-
}
|
|
1219
|
-
)
|
|
1220
|
-
}
|
|
1221
|
-
);
|
|
1222
|
-
});
|
|
1223
|
-
CommandList.displayName = "CommandList";
|
|
1224
|
-
var CommandLoading = React4.forwardRef((props, ref) => {
|
|
1225
|
-
const { className, children, label = "Loading...", progress, ...rest } = props;
|
|
1226
|
-
const tv = commandLoadingTv();
|
|
1227
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1228
|
-
"div",
|
|
1229
|
-
{
|
|
1230
|
-
ref,
|
|
1231
|
-
...props,
|
|
1232
|
-
className: shared.tcx(tv.root({ className })),
|
|
1233
|
-
role: "progressbar",
|
|
1234
|
-
"aria-valuenow": progress,
|
|
1235
|
-
"aria-valuemin": 0,
|
|
1236
|
-
"aria-valuemax": 100,
|
|
1237
|
-
"aria-label": label,
|
|
1238
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, children })
|
|
1239
|
-
}
|
|
1240
|
-
);
|
|
1241
|
-
});
|
|
1242
|
-
CommandLoading.displayName = "CommandLoading";
|
|
1243
|
-
var CommandDivider = React4.forwardRef(
|
|
1244
|
-
({ className, alwaysRender, ...props }, forwardedRef) => {
|
|
1245
|
-
const context = useCommand();
|
|
1246
|
-
const render = useCommandState((state) => !state.search);
|
|
1247
|
-
const tv = commandTv({ variant: context.variant });
|
|
1248
|
-
if (!alwaysRender && !render) return null;
|
|
1249
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1250
|
-
"div",
|
|
1251
|
-
{
|
|
1252
|
-
ref: forwardedRef,
|
|
1253
|
-
...props,
|
|
1254
|
-
className: shared.tcx(tv.divider({ className })),
|
|
1255
|
-
role: "separator"
|
|
1256
|
-
}
|
|
1257
|
-
);
|
|
1258
|
-
}
|
|
1259
|
-
);
|
|
1260
|
-
CommandDivider.displayName = "CommandDivider";
|
|
1261
|
-
var CommandValue = React4.forwardRef((props, ref) => {
|
|
1262
|
-
const { className, children, ...rest } = props;
|
|
1263
|
-
const context = useCommand();
|
|
1264
|
-
const tv = commandItemTv({ size: context.size });
|
|
1265
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1266
|
-
"div",
|
|
1267
|
-
{
|
|
1268
|
-
ref,
|
|
1269
|
-
...rest,
|
|
1270
|
-
className: shared.tcx(tv.value({ className })),
|
|
1271
|
-
children
|
|
1272
|
-
}
|
|
1273
|
-
);
|
|
1274
|
-
});
|
|
1275
|
-
CommandValue.displayName = "CommandValue";
|
|
1276
|
-
var CommandTabs = React4.forwardRef((props, ref) => {
|
|
1277
|
-
const context = useCommand();
|
|
1278
|
-
const tv = commandTabsTv();
|
|
1279
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1280
|
-
tabs.Tabs,
|
|
1281
|
-
{
|
|
1282
|
-
ref,
|
|
1283
|
-
variant: props.variant || context.variant,
|
|
1284
|
-
className: tv.tabs(),
|
|
1285
|
-
...props
|
|
1286
|
-
}
|
|
1287
|
-
);
|
|
1288
|
-
});
|
|
1289
|
-
CommandTabs.displayName = "CommandTabs";
|
|
1290
|
-
|
|
1291
|
-
// src/index.ts
|
|
1292
|
-
var Command2 = Object.assign(Command, {
|
|
1293
|
-
Empty: CommandEmpty,
|
|
1294
|
-
Footer: CommandFooter,
|
|
1295
|
-
Group: CommandGroup,
|
|
1296
|
-
Input: CommandInput,
|
|
1297
|
-
Item: CommandItem,
|
|
1298
|
-
List: CommandList,
|
|
1299
|
-
Loading: CommandLoading,
|
|
1300
|
-
Divider: CommandDivider,
|
|
1301
|
-
Value: CommandValue,
|
|
1302
|
-
Tabs: CommandTabs,
|
|
1303
|
-
TabItem: tabs.TabItem
|
|
1304
|
-
});
|
|
1305
|
-
|
|
1306
|
-
exports.Command = Command2;
|
|
1307
|
-
exports.CommandRoot = Command;
|
|
1308
|
-
exports.defaultFilter = defaultFilter;
|
|
1309
|
-
exports.useCommandState = useCommandState;
|