@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.d.cts
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import * as _choice_ui_tabs from '@choice-ui/tabs';
|
|
2
|
-
import * as react from 'react';
|
|
3
|
-
import react__default, { HTMLProps, ReactNode } from 'react';
|
|
4
|
-
import { InputProps } from '@choice-ui/input';
|
|
5
|
-
import { KbdKey } from '@choice-ui/kbd';
|
|
6
|
-
import { ScrollAreaProps } from '@choice-ui/scroll-area';
|
|
7
|
-
|
|
8
|
-
interface CommandEmptyProps extends HTMLProps<HTMLDivElement> {
|
|
9
|
-
className?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface CommandGroupProps extends HTMLProps<HTMLDivElement> {
|
|
13
|
-
forceMount?: boolean;
|
|
14
|
-
heading?: react__default.ReactNode;
|
|
15
|
-
value?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface CommandInputProps extends Omit<InputProps, "value" | "onChange" | "type"> {
|
|
19
|
-
onChange?: (search: string) => void;
|
|
20
|
-
prefixElement?: ReactNode;
|
|
21
|
-
suffixElement?: ReactNode;
|
|
22
|
-
value?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface CommandItemProps extends Omit<HTMLProps<HTMLDivElement>, "onSelect"> {
|
|
26
|
-
disabled?: boolean;
|
|
27
|
-
forceMount?: boolean;
|
|
28
|
-
keywords?: string[];
|
|
29
|
-
onSelect?: (value: string) => void;
|
|
30
|
-
prefixElement?: ReactNode;
|
|
31
|
-
shortcut?: {
|
|
32
|
-
keys?: ReactNode;
|
|
33
|
-
modifier?: KbdKey | KbdKey[] | undefined;
|
|
34
|
-
};
|
|
35
|
-
suffixElement?: ReactNode;
|
|
36
|
-
value?: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
interface CommandListProps extends ScrollAreaProps {
|
|
40
|
-
children: React.ReactNode;
|
|
41
|
-
className?: string;
|
|
42
|
-
label?: string;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
interface CommandLoadingProps extends react__default.HTMLAttributes<HTMLDivElement> {
|
|
46
|
-
label?: string;
|
|
47
|
-
progress?: number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
interface CommandDividerProps extends HTMLProps<HTMLDivElement> {
|
|
51
|
-
/** 是否始终渲染此分隔符。当禁用自动过滤功能时特别有用。 */
|
|
52
|
-
alwaysRender?: boolean;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
type CommandFilter = (value: string, search: string, keywords?: string[]) => number;
|
|
56
|
-
interface CommandProps extends Omit<react__default.HTMLAttributes<HTMLDivElement>, "onChange"> {
|
|
57
|
-
/**
|
|
58
|
-
* Optional default item value when it is initially rendered.
|
|
59
|
-
*/
|
|
60
|
-
defaultValue?: string;
|
|
61
|
-
/**
|
|
62
|
-
* Optionally set to `true` to disable selection via pointer events.
|
|
63
|
-
*/
|
|
64
|
-
disablePointerSelection?: boolean;
|
|
65
|
-
/**
|
|
66
|
-
* Custom filter function for whether each command menu item should matches the given search query.
|
|
67
|
-
* It should return a number between 0 and 1, with 1 being the best match and 0 being hidden entirely.
|
|
68
|
-
* By default, uses the `command-score` library.
|
|
69
|
-
*/
|
|
70
|
-
filter?: CommandFilter;
|
|
71
|
-
/**
|
|
72
|
-
* Accessible label for this command menu. Not shown visibly.
|
|
73
|
-
*/
|
|
74
|
-
label?: string;
|
|
75
|
-
/**
|
|
76
|
-
* Optionally set to `true` to turn on looping around when using the arrow keys.
|
|
77
|
-
*/
|
|
78
|
-
loop?: boolean;
|
|
79
|
-
/**
|
|
80
|
-
* Event handler called when the selected item of the menu changes.
|
|
81
|
-
*/
|
|
82
|
-
onChange?: (value: string) => void;
|
|
83
|
-
/**
|
|
84
|
-
* Optionally set to `false` to turn off the automatic filtering and sorting.
|
|
85
|
-
* If `false`, you must conditionally render valid items based on the search query yourself.
|
|
86
|
-
*/
|
|
87
|
-
shouldFilter?: boolean;
|
|
88
|
-
size?: "default" | "large";
|
|
89
|
-
/**
|
|
90
|
-
* Optional controlled state of the selected command menu item.
|
|
91
|
-
*/
|
|
92
|
-
value?: string;
|
|
93
|
-
variant?: "default" | "dark";
|
|
94
|
-
/**
|
|
95
|
-
* Set to `false` to disable ctrl+n/j/p/k shortcuts. Defaults to `true`.
|
|
96
|
-
*/
|
|
97
|
-
vimBindings?: boolean;
|
|
98
|
-
}
|
|
99
|
-
type State = {
|
|
100
|
-
filtered: {
|
|
101
|
-
count: number;
|
|
102
|
-
groups: Set<string>;
|
|
103
|
-
items: Map<string, number>;
|
|
104
|
-
};
|
|
105
|
-
search: string;
|
|
106
|
-
selectedItemId?: string;
|
|
107
|
-
value: string;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
declare const defaultFilter: CommandFilter;
|
|
111
|
-
declare const Command$1: react__default.ForwardRefExoticComponent<CommandProps & react__default.RefAttributes<HTMLDivElement>>;
|
|
112
|
-
|
|
113
|
-
/** Run a selector against the store state. */
|
|
114
|
-
declare function useCommandState<T>(selector: (state: State) => T): T;
|
|
115
|
-
|
|
116
|
-
declare const Command: react.ForwardRefExoticComponent<CommandProps & react.RefAttributes<HTMLDivElement>> & {
|
|
117
|
-
Empty: react.ForwardRefExoticComponent<Omit<CommandEmptyProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
|
|
118
|
-
Footer: react.ForwardRefExoticComponent<Omit<react.HTMLProps<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
|
|
119
|
-
Group: react.ForwardRefExoticComponent<Omit<CommandGroupProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
|
|
120
|
-
Input: react.ForwardRefExoticComponent<Omit<CommandInputProps, "ref"> & react.RefAttributes<HTMLInputElement>>;
|
|
121
|
-
Item: react.ForwardRefExoticComponent<Omit<CommandItemProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
|
|
122
|
-
List: react.ForwardRefExoticComponent<CommandListProps & react.RefAttributes<HTMLDivElement>>;
|
|
123
|
-
Loading: react.ForwardRefExoticComponent<CommandLoadingProps & react.RefAttributes<HTMLDivElement>>;
|
|
124
|
-
Divider: react.ForwardRefExoticComponent<Omit<CommandDividerProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
|
|
125
|
-
Value: react.ForwardRefExoticComponent<Omit<react.HTMLProps<HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
|
|
126
|
-
Tabs: react.ForwardRefExoticComponent<Omit<_choice_ui_tabs.TabsProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
|
|
127
|
-
TabItem: react.MemoExoticComponent<react.ForwardRefExoticComponent<Omit<_choice_ui_tabs.TabItemProps, "ref"> & react.RefAttributes<HTMLElement>>>;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
export { Command, Command$1 as CommandRoot, defaultFilter, useCommandState };
|
package/src/command-score.ts
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
// The scores are arranged so that a continuous match of characters will
|
|
2
|
-
// result in a total score of 1.
|
|
3
|
-
//
|
|
4
|
-
// The best case, this character is a match, and either this is the start
|
|
5
|
-
// of the string, or the previous character was also a match.
|
|
6
|
-
const SCORE_CONTINUE_MATCH = 1,
|
|
7
|
-
// A new match at the start of a word scores better than a new match
|
|
8
|
-
// elsewhere as it's more likely that the user will type the starts
|
|
9
|
-
// of fragments.
|
|
10
|
-
// NOTE: We score word jumps between spaces slightly higher than slashes, brackets
|
|
11
|
-
// hyphens, etc.
|
|
12
|
-
SCORE_SPACE_WORD_JUMP = 0.9,
|
|
13
|
-
SCORE_NON_SPACE_WORD_JUMP = 0.8,
|
|
14
|
-
// Any other match isn't ideal, but we include it for completeness.
|
|
15
|
-
SCORE_CHARACTER_JUMP = 0.17,
|
|
16
|
-
// If the user transposed two letters, it should be significantly penalized.
|
|
17
|
-
//
|
|
18
|
-
// i.e. "ouch" is more likely than "curtain" when "uc" is typed.
|
|
19
|
-
SCORE_TRANSPOSITION = 0.1,
|
|
20
|
-
// The goodness of a match should decay slightly with each missing
|
|
21
|
-
// character.
|
|
22
|
-
//
|
|
23
|
-
// i.e. "bad" is more likely than "bard" when "bd" is typed.
|
|
24
|
-
//
|
|
25
|
-
// This will not change the order of suggestions based on SCORE_* until
|
|
26
|
-
// 100 characters are inserted between matches.
|
|
27
|
-
PENALTY_SKIPPED = 0.999,
|
|
28
|
-
// The goodness of an exact-case match should be higher than a
|
|
29
|
-
// case-insensitive match by a small amount.
|
|
30
|
-
//
|
|
31
|
-
// i.e. "HTML" is more likely than "haml" when "HM" is typed.
|
|
32
|
-
//
|
|
33
|
-
// This will not change the order of suggestions based on SCORE_* until
|
|
34
|
-
// 1000 characters are inserted between matches.
|
|
35
|
-
PENALTY_CASE_MISMATCH = 0.9999,
|
|
36
|
-
// Match higher for letters closer to the beginning of the word
|
|
37
|
-
PENALTY_DISTANCE_FROM_START = 0.9,
|
|
38
|
-
// If the word has more characters than the user typed, it should
|
|
39
|
-
// be penalised slightly.
|
|
40
|
-
//
|
|
41
|
-
// i.e. "html" is more likely than "html5" if I type "html".
|
|
42
|
-
//
|
|
43
|
-
// However, it may well be the case that there's a sensible secondary
|
|
44
|
-
// ordering (like alphabetical) that it makes sense to rely on when
|
|
45
|
-
// there are many prefix matches, so we don't make the penalty increase
|
|
46
|
-
// with the number of tokens.
|
|
47
|
-
PENALTY_NOT_COMPLETE = 0.99
|
|
48
|
-
|
|
49
|
-
const IS_GAP_REGEXP = /[\\/_+.#"@[({&]/,
|
|
50
|
-
COUNT_GAPS_REGEXP = /[\\/_+.#"@[({&]/g,
|
|
51
|
-
IS_SPACE_REGEXP = /[\s-]/,
|
|
52
|
-
COUNT_SPACE_REGEXP = /[\s-]/g
|
|
53
|
-
|
|
54
|
-
function commandScoreInner(
|
|
55
|
-
string: string,
|
|
56
|
-
abbreviation: string,
|
|
57
|
-
lowerString: string,
|
|
58
|
-
lowerAbbreviation: string,
|
|
59
|
-
stringIndex: number,
|
|
60
|
-
abbreviationIndex: number,
|
|
61
|
-
memoizedResults: Record<string, number>,
|
|
62
|
-
): number {
|
|
63
|
-
if (abbreviationIndex === abbreviation.length) {
|
|
64
|
-
if (stringIndex === string.length) {
|
|
65
|
-
return SCORE_CONTINUE_MATCH
|
|
66
|
-
}
|
|
67
|
-
return PENALTY_NOT_COMPLETE
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const memoizeKey = `${stringIndex},${abbreviationIndex}`
|
|
71
|
-
if (memoizedResults[memoizeKey] !== undefined) {
|
|
72
|
-
return memoizedResults[memoizeKey]
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const abbreviationChar = lowerAbbreviation.charAt(abbreviationIndex)
|
|
76
|
-
let index = lowerString.indexOf(abbreviationChar, stringIndex)
|
|
77
|
-
let highScore = 0
|
|
78
|
-
|
|
79
|
-
let score, transposedScore, wordBreaks, spaceBreaks
|
|
80
|
-
|
|
81
|
-
while (index >= 0) {
|
|
82
|
-
score = commandScoreInner(
|
|
83
|
-
string,
|
|
84
|
-
abbreviation,
|
|
85
|
-
lowerString,
|
|
86
|
-
lowerAbbreviation,
|
|
87
|
-
index + 1,
|
|
88
|
-
abbreviationIndex + 1,
|
|
89
|
-
memoizedResults,
|
|
90
|
-
)
|
|
91
|
-
if (score > highScore) {
|
|
92
|
-
if (index === stringIndex) {
|
|
93
|
-
score *= SCORE_CONTINUE_MATCH
|
|
94
|
-
} else if (IS_GAP_REGEXP.test(string.charAt(index - 1))) {
|
|
95
|
-
score *= SCORE_NON_SPACE_WORD_JUMP
|
|
96
|
-
wordBreaks = string.slice(stringIndex, index - 1).match(COUNT_GAPS_REGEXP)
|
|
97
|
-
if (wordBreaks && stringIndex > 0) {
|
|
98
|
-
score *= Math.pow(PENALTY_SKIPPED, wordBreaks.length)
|
|
99
|
-
}
|
|
100
|
-
} else if (IS_SPACE_REGEXP.test(string.charAt(index - 1))) {
|
|
101
|
-
score *= SCORE_SPACE_WORD_JUMP
|
|
102
|
-
spaceBreaks = string.slice(stringIndex, index - 1).match(COUNT_SPACE_REGEXP)
|
|
103
|
-
if (spaceBreaks && stringIndex > 0) {
|
|
104
|
-
score *= Math.pow(PENALTY_SKIPPED, spaceBreaks.length)
|
|
105
|
-
}
|
|
106
|
-
} else {
|
|
107
|
-
score *= SCORE_CHARACTER_JUMP
|
|
108
|
-
if (stringIndex > 0) {
|
|
109
|
-
score *= Math.pow(PENALTY_SKIPPED, index - stringIndex)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (string.charAt(index) !== abbreviation.charAt(abbreviationIndex)) {
|
|
114
|
-
score *= PENALTY_CASE_MISMATCH
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (
|
|
119
|
-
(score < SCORE_TRANSPOSITION &&
|
|
120
|
-
lowerString.charAt(index - 1) === lowerAbbreviation.charAt(abbreviationIndex + 1)) ||
|
|
121
|
-
(lowerAbbreviation.charAt(abbreviationIndex + 1) ===
|
|
122
|
-
lowerAbbreviation.charAt(abbreviationIndex) && // allow duplicate letters. Ref #7428
|
|
123
|
-
lowerString.charAt(index - 1) !== lowerAbbreviation.charAt(abbreviationIndex))
|
|
124
|
-
) {
|
|
125
|
-
transposedScore = commandScoreInner(
|
|
126
|
-
string,
|
|
127
|
-
abbreviation,
|
|
128
|
-
lowerString,
|
|
129
|
-
lowerAbbreviation,
|
|
130
|
-
index + 1,
|
|
131
|
-
abbreviationIndex + 2,
|
|
132
|
-
memoizedResults,
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
if (transposedScore * SCORE_TRANSPOSITION > score) {
|
|
136
|
-
score = transposedScore * SCORE_TRANSPOSITION
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (score > highScore) {
|
|
141
|
-
highScore = score
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
index = lowerString.indexOf(abbreviationChar, index + 1)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
memoizedResults[memoizeKey] = highScore
|
|
148
|
-
return highScore
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function formatInput(string: string): string {
|
|
152
|
-
// convert all valid space characters to space so they match each other
|
|
153
|
-
return string.toLowerCase().replace(COUNT_SPACE_REGEXP, " ")
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export function commandScore(string: string, abbreviation: string, aliases?: string[]): number {
|
|
157
|
-
/* NOTE:
|
|
158
|
-
* in the original, we used to do the lower-casing on each recursive call, but this meant that toLowerCase()
|
|
159
|
-
* was the dominating cost in the algorithm, passing both is a little ugly, but considerably faster.
|
|
160
|
-
*/
|
|
161
|
-
string = aliases && aliases.length > 0 ? `${string + " " + aliases.join(" ")}` : string
|
|
162
|
-
return commandScoreInner(
|
|
163
|
-
string,
|
|
164
|
-
abbreviation,
|
|
165
|
-
formatInput(string),
|
|
166
|
-
formatInput(abbreviation),
|
|
167
|
-
0,
|
|
168
|
-
0,
|
|
169
|
-
{},
|
|
170
|
-
)
|
|
171
|
-
}
|