@teambit/command-bar 0.0.554 → 0.0.558
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/command-bar.ui.runtime.d.ts +20 -0
- package/dist/types.d.ts +2 -0
- package/package.json +20 -12
- package/tsconfig.json +1 -2
- package/command-bar.aspect.ts +0 -7
- package/command-bar.commands.ts +0 -3
- package/command-bar.preview.runtime.tsx +0 -40
- package/command-bar.ui.runtime.tsx +0 -177
- package/duplicate-command-error.ts +0 -8
- package/index.ts +0 -6
- package/keybinding.ts +0 -5
- package/model/key-event/index.ts +0 -1
- package/model/key-event/key-event.tsx +0 -9
- package/model/key-event/serialize-keyboard-event.ts +0 -16
- package/mousetrap-stub.ts +0 -20
- package/package-tar/teambit-command-bar-0.0.554.tgz +0 -0
- package/types/asset.d.ts +0 -29
- package/types/style.d.ts +0 -42
- package/types.tsx +0 -20
- package/ui/autocomplete-input/autocomplete-input.module.scss +0 -13
- package/ui/autocomplete-input/autocomplete-input.tsx +0 -62
- package/ui/autocomplete-input/index.ts +0 -1
- package/ui/command-bar/command-bar.module.scss +0 -44
- package/ui/command-bar/command-bar.tsx +0 -66
- package/ui/command-bar/index.ts +0 -1
- package/ui/command-bar-context/command-bar-context.tsx +0 -4
- package/ui/command-bar-context/index.ts +0 -1
- package/ui/command-bar-item/command-bar-item.module.scss +0 -38
- package/ui/command-bar-item/command-bar-item.tsx +0 -30
- package/ui/command-bar-item/index.ts +0 -1
- package/ui/command-searcher/command-searcher.ts +0 -31
- package/ui/command-searcher/index.ts +0 -1
- package/ui/component-searcher/component-searcher.ts +0 -44
- package/ui/component-searcher/index.ts +0 -1
|
@@ -10,23 +10,43 @@ export declare type CommandEntry = {
|
|
|
10
10
|
keybinding?: Keybinding;
|
|
11
11
|
displayName: string;
|
|
12
12
|
};
|
|
13
|
+
/** Quick launch actions. Use the `addSearcher` slot to extend the available actions */
|
|
13
14
|
export declare class CommandBarUI {
|
|
14
15
|
private searcherSlot;
|
|
15
16
|
private commandSlot;
|
|
16
17
|
private mousetrap;
|
|
17
18
|
private commandSearcher;
|
|
19
|
+
/** Opens the command bar */
|
|
18
20
|
open: () => boolean;
|
|
21
|
+
/** Closes the command bar */
|
|
19
22
|
close: () => void;
|
|
23
|
+
/** Add and autocomplete provider. To support keyboard navigation, each result should have a props `active: boolean`, and `exectue: () => any` */
|
|
20
24
|
addSearcher(commandSearcher: SearchProvider): this;
|
|
25
|
+
/**
|
|
26
|
+
* registers a command
|
|
27
|
+
*/
|
|
21
28
|
addCommand(...originalCommands: CommandEntry[]): ((next: CommandHandler) => void)[];
|
|
29
|
+
/**
|
|
30
|
+
* executes command by name, if exists.
|
|
31
|
+
* @param commandId
|
|
32
|
+
*/
|
|
22
33
|
run(commandId: CommandId): any;
|
|
34
|
+
/**
|
|
35
|
+
* executes a keyboard shortcut manually
|
|
36
|
+
*/
|
|
23
37
|
trigger: (key: string) => void;
|
|
24
38
|
private search;
|
|
25
39
|
private getCommand;
|
|
26
40
|
private updateCommandsSearcher;
|
|
27
41
|
private addKeybinding;
|
|
28
42
|
private renderContext;
|
|
43
|
+
/**
|
|
44
|
+
* internal. Opens and closes the command bar UI.
|
|
45
|
+
*/
|
|
29
46
|
setVisibility?: (visible: boolean) => void;
|
|
47
|
+
/**
|
|
48
|
+
* generate the ui for command bar
|
|
49
|
+
*/
|
|
30
50
|
getCommandBar: () => JSX.Element;
|
|
31
51
|
constructor(searcherSlot: SearcherSlot, commandSlot: CommandSlot, pubSub: PubsubUI);
|
|
32
52
|
static dependencies: import("@teambit/harmony").Aspect[];
|
package/dist/types.d.ts
CHANGED
|
@@ -9,7 +9,9 @@ export declare type CommanderSearchResult = {
|
|
|
9
9
|
keybinding?: Keybinding;
|
|
10
10
|
};
|
|
11
11
|
export interface SearchProvider {
|
|
12
|
+
/** provide completions for this search term */
|
|
12
13
|
search(term: string, limit: number): CommanderSearchResult[];
|
|
14
|
+
/** determines what terms are handled by this searcher. */
|
|
13
15
|
test(term: string): boolean;
|
|
14
16
|
}
|
|
15
17
|
export declare type Keybinding = string | string[];
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teambit/command-bar",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.558",
|
|
4
4
|
"homepage": "https://bit.dev/teambit/explorer/command-bar",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"componentId": {
|
|
7
7
|
"scope": "teambit.explorer",
|
|
8
8
|
"name": "command-bar",
|
|
9
|
-
"version": "0.0.
|
|
9
|
+
"version": "0.0.558"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@teambit/harmony": "0.2.11",
|
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
"core-js": "^3.0.0",
|
|
20
20
|
"@teambit/base-ui.surfaces.card": "1.0.1",
|
|
21
21
|
"@teambit/base-ui.text.muted-text": "1.0.1",
|
|
22
|
-
"@teambit/preview": "0.0.
|
|
23
|
-
"@teambit/pubsub": "0.0.
|
|
24
|
-
"@teambit/ui-foundation.ui.is-browser": "0.0.
|
|
25
|
-
"@teambit/ui": "0.0.
|
|
26
|
-
"@teambit/bit-error": "0.0.
|
|
27
|
-
"@teambit/ui-foundation.ui.constants.z-indexes": "0.0.
|
|
28
|
-
"@teambit/ui-foundation.ui.keycap": "0.0.
|
|
29
|
-
"@teambit/component": "0.0.
|
|
22
|
+
"@teambit/preview": "0.0.558",
|
|
23
|
+
"@teambit/pubsub": "0.0.558",
|
|
24
|
+
"@teambit/ui-foundation.ui.is-browser": "0.0.465",
|
|
25
|
+
"@teambit/ui": "0.0.558",
|
|
26
|
+
"@teambit/bit-error": "0.0.374",
|
|
27
|
+
"@teambit/ui-foundation.ui.constants.z-indexes": "0.0.465",
|
|
28
|
+
"@teambit/ui-foundation.ui.keycap": "0.0.465",
|
|
29
|
+
"@teambit/component": "0.0.558"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/mousetrap": "1.6.5",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@types/node": "12.20.4"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@teambit/legacy": "1.0.
|
|
42
|
+
"@teambit/legacy": "1.0.174",
|
|
43
43
|
"react-dom": "^16.8.0 || ^17.0.0",
|
|
44
44
|
"react": "^16.8.0 || ^17.0.0"
|
|
45
45
|
},
|
|
@@ -67,12 +67,20 @@
|
|
|
67
67
|
"react": "-"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
|
-
"@teambit/legacy": "1.0.
|
|
70
|
+
"@teambit/legacy": "1.0.174",
|
|
71
71
|
"react-dom": "^16.8.0 || ^17.0.0",
|
|
72
72
|
"react": "^16.8.0 || ^17.0.0"
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
|
+
"files": [
|
|
77
|
+
"dist",
|
|
78
|
+
"!dist/tsconfig.tsbuildinfo",
|
|
79
|
+
"README.md",
|
|
80
|
+
"README.mdx",
|
|
81
|
+
"*.js",
|
|
82
|
+
"*.json"
|
|
83
|
+
],
|
|
76
84
|
"private": false,
|
|
77
85
|
"engines": {
|
|
78
86
|
"node": ">=12.22.0"
|
package/tsconfig.json
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"skipLibCheck": true,
|
|
16
16
|
"moduleResolution": "node",
|
|
17
17
|
"esModuleInterop": true,
|
|
18
|
-
"outDir": "dist",
|
|
19
18
|
"composite": true,
|
|
20
19
|
"emitDeclarationOnly": true,
|
|
20
|
+
"outDir": "dist",
|
|
21
21
|
"experimentalDecorators": true,
|
|
22
22
|
"emitDecoratorMetadata": true,
|
|
23
23
|
"allowSyntheticDefaultImports": true,
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
"strict": true,
|
|
26
26
|
"noImplicitAny": false,
|
|
27
27
|
"rootDir": ".",
|
|
28
|
-
"removeComments": true,
|
|
29
28
|
"preserveConstEnums": true,
|
|
30
29
|
"resolveJsonModule": true
|
|
31
30
|
},
|
package/command-bar.aspect.ts
DELETED
package/command-bar.commands.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { PreviewRuntime } from '@teambit/preview';
|
|
2
|
-
import { PubsubAspect, PubsubPreview } from '@teambit/pubsub';
|
|
3
|
-
import { isOpenCommandBarKeybinding } from './keybinding';
|
|
4
|
-
import { CommandBarAspect } from './command-bar.aspect';
|
|
5
|
-
import { KeyEvent } from './model/key-event';
|
|
6
|
-
|
|
7
|
-
export class CommandBarPreview {
|
|
8
|
-
constructor(private pubSub: PubsubPreview) {
|
|
9
|
-
document.addEventListener('keydown', this.handleKeyEvent);
|
|
10
|
-
document.addEventListener('keypress', this.handleKeyEvent);
|
|
11
|
-
document.addEventListener('keyup', this.handleKeyEvent);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
handleKeyEvent = (e: KeyboardEvent) => {
|
|
15
|
-
const { target } = e;
|
|
16
|
-
if (!target || isEditable(target as HTMLElement)) return;
|
|
17
|
-
if (isDenyListed(e)) e.preventDefault();
|
|
18
|
-
|
|
19
|
-
this.pubSub.pub(CommandBarAspect.id, new KeyEvent(e));
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
static dependencies = [PubsubAspect];
|
|
23
|
-
static runtime = PreviewRuntime;
|
|
24
|
-
static async provider([pubSub]: [PubsubPreview]) {
|
|
25
|
-
const pubsubPreview = new CommandBarPreview(pubSub);
|
|
26
|
-
return pubsubPreview;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const editableTags = ['INPUT', 'SELECT', 'TEXTAREA'];
|
|
31
|
-
function isEditable(element: HTMLElement) {
|
|
32
|
-
return editableTags.includes(element.tagName) || element.isContentEditable;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
CommandBarAspect.addRuntime(CommandBarPreview);
|
|
36
|
-
|
|
37
|
-
// block default browser behavior that would override our keybinding.
|
|
38
|
-
function isDenyListed(e: KeyboardEvent) {
|
|
39
|
-
return isOpenCommandBarKeybinding(e);
|
|
40
|
-
}
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode } from 'react';
|
|
2
|
-
import { Slot, SlotRegistry } from '@teambit/harmony';
|
|
3
|
-
import Mousetrap from 'mousetrap';
|
|
4
|
-
|
|
5
|
-
import UIAspect, { UIRuntime, UiUI } from '@teambit/ui';
|
|
6
|
-
import { PubsubAspect, PubsubUI } from '@teambit/pubsub';
|
|
7
|
-
import { isBrowser } from '@teambit/ui-foundation.ui.is-browser';
|
|
8
|
-
import { CommandBar } from './ui/command-bar';
|
|
9
|
-
import { CommandSearcher } from './ui/command-searcher';
|
|
10
|
-
import { CommandBarAspect } from './command-bar.aspect';
|
|
11
|
-
import { commandBarCommands } from './command-bar.commands';
|
|
12
|
-
import { SearchProvider, Keybinding, CommandHandler, CommandId } from './types';
|
|
13
|
-
import { DuplicateCommandError } from './duplicate-command-error';
|
|
14
|
-
import { KeyEvent } from './model/key-event';
|
|
15
|
-
import { CommandBarContext } from './ui/command-bar-context';
|
|
16
|
-
import { MousetrapStub } from './mousetrap-stub';
|
|
17
|
-
import { openCommandBarKeybinding } from './keybinding';
|
|
18
|
-
|
|
19
|
-
const RESULT_LIMIT = 5;
|
|
20
|
-
type SearcherSlot = SlotRegistry<SearchProvider>;
|
|
21
|
-
type CommandSlot = SlotRegistry<CommandEntry[]>;
|
|
22
|
-
|
|
23
|
-
export type CommandEntry = {
|
|
24
|
-
id: CommandId;
|
|
25
|
-
handler: CommandHandler;
|
|
26
|
-
keybinding?: Keybinding;
|
|
27
|
-
displayName: string;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/** Quick launch actions. Use the `addSearcher` slot to extend the available actions */
|
|
31
|
-
export class CommandBarUI {
|
|
32
|
-
private mousetrap = isBrowser ? new Mousetrap() : new MousetrapStub();
|
|
33
|
-
private commandSearcher = new CommandSearcher([]);
|
|
34
|
-
|
|
35
|
-
/** Opens the command bar */
|
|
36
|
-
open = () => {
|
|
37
|
-
this.setVisibility?.(true);
|
|
38
|
-
return false; // aka prevent default
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/** Closes the command bar */
|
|
42
|
-
close = () => {
|
|
43
|
-
this.setVisibility?.(false);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
/** Add and autocomplete provider. To support keyboard navigation, each result should have a props `active: boolean`, and `exectue: () => any` */
|
|
47
|
-
addSearcher(commandSearcher: SearchProvider) {
|
|
48
|
-
this.searcherSlot.register(commandSearcher);
|
|
49
|
-
return this;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* registers a command
|
|
54
|
-
*/
|
|
55
|
-
addCommand(...originalCommands: CommandEntry[]) {
|
|
56
|
-
originalCommands.forEach(({ id: commandId }) => {
|
|
57
|
-
if (this.getCommand(commandId) !== undefined) throw new DuplicateCommandError(commandId);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// commands could mutate later on, clone to ensure immutability 👌
|
|
61
|
-
const commands = originalCommands.map((x) => ({
|
|
62
|
-
id: x.id,
|
|
63
|
-
displayName: x.displayName,
|
|
64
|
-
handler: x.handler,
|
|
65
|
-
keybinding: x.keybinding,
|
|
66
|
-
}));
|
|
67
|
-
|
|
68
|
-
this.commandSlot.register(commands);
|
|
69
|
-
|
|
70
|
-
commands.forEach((command) => {
|
|
71
|
-
if (command.keybinding) {
|
|
72
|
-
this.addKeybinding(command.keybinding, command.id);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
this.updateCommandsSearcher();
|
|
77
|
-
|
|
78
|
-
const updaters = commands.map((command) => (next: CommandHandler) => {
|
|
79
|
-
command.handler = next;
|
|
80
|
-
});
|
|
81
|
-
return updaters;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* executes command by name, if exists.
|
|
86
|
-
* @param commandId
|
|
87
|
-
*/
|
|
88
|
-
run(commandId: CommandId) {
|
|
89
|
-
const commandEntry = this.getCommand(commandId);
|
|
90
|
-
if (!commandEntry) return undefined;
|
|
91
|
-
|
|
92
|
-
return commandEntry.handler();
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* executes a keyboard shortcut manually
|
|
97
|
-
*/
|
|
98
|
-
trigger = (key: string) => {
|
|
99
|
-
this.mousetrap.trigger(key);
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
private search = (term: string, limit: number = RESULT_LIMIT) => {
|
|
103
|
-
const searchers = this.searcherSlot.values();
|
|
104
|
-
|
|
105
|
-
const searcher = searchers.find((x) => x.test(term));
|
|
106
|
-
return searcher?.search(term, limit) || [];
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
private getCommand(id: CommandId) {
|
|
110
|
-
const relevantCommands = this.commandSlot
|
|
111
|
-
.values()
|
|
112
|
-
.map((commands) => commands.find((command) => command.id === id))
|
|
113
|
-
.filter((x) => !!x);
|
|
114
|
-
|
|
115
|
-
return relevantCommands.pop();
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
private updateCommandsSearcher() {
|
|
119
|
-
const commands = this.commandSlot.values().flat();
|
|
120
|
-
this.commandSearcher.update(commands);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
private addKeybinding(key: Keybinding, command: CommandId) {
|
|
124
|
-
this.mousetrap.bind(key, this.run.bind(this, command));
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
private renderContext = ({ children }: { children: ReactNode }) => {
|
|
128
|
-
return <CommandBarContext.Provider value={this}>{children}</CommandBarContext.Provider>;
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* internal. Opens and closes the command bar UI.
|
|
133
|
-
*/
|
|
134
|
-
setVisibility?: (visible: boolean) => void;
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* generate the ui for command bar
|
|
138
|
-
*/
|
|
139
|
-
getCommandBar = () => {
|
|
140
|
-
return <CommandBar key="CommandBarUI" search={this.search} commander={this} />;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
constructor(private searcherSlot: SearcherSlot, private commandSlot: CommandSlot, pubSub: PubsubUI) {
|
|
144
|
-
this.addSearcher(this.commandSearcher);
|
|
145
|
-
pubSub.sub(CommandBarAspect.id, (e: KeyEvent) => {
|
|
146
|
-
const keyboardEvent = new KeyboardEvent(e.type, e.data);
|
|
147
|
-
document.dispatchEvent(keyboardEvent);
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
static dependencies = [UIAspect, PubsubAspect];
|
|
152
|
-
static slots = [Slot.withType<SearchProvider>(), Slot.withType<CommandEntry[]>()];
|
|
153
|
-
static runtime = UIRuntime;
|
|
154
|
-
static async provider(
|
|
155
|
-
[uiUi, pubsubUI]: [UiUI, PubsubUI],
|
|
156
|
-
config,
|
|
157
|
-
[searcherSlot, commandSlots]: [SearcherSlot, CommandSlot]
|
|
158
|
-
) {
|
|
159
|
-
const commandBar = new CommandBarUI(searcherSlot, commandSlots, pubsubUI);
|
|
160
|
-
|
|
161
|
-
commandBar.addCommand({
|
|
162
|
-
id: commandBarCommands.open,
|
|
163
|
-
handler: commandBar.open,
|
|
164
|
-
displayName: 'Open command bar',
|
|
165
|
-
keybinding: openCommandBarKeybinding,
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
uiUi.registerHudItem(commandBar.getCommandBar());
|
|
169
|
-
uiUi.registerRenderHooks({
|
|
170
|
-
reactContext: commandBar.renderContext,
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
return commandBar;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
CommandBarAspect.addRuntime(CommandBarUI);
|
package/index.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export { CommandBarAspect, CommandBarAspect as default } from './command-bar.aspect';
|
|
2
|
-
export { commandBarCommands } from './command-bar.commands';
|
|
3
|
-
export { ComponentSearcher } from './ui/component-searcher';
|
|
4
|
-
export { CommandBarContext } from './ui/command-bar-context';
|
|
5
|
-
export type { CommandBarUI, CommandEntry } from './command-bar.ui.runtime';
|
|
6
|
-
export type { CommandHandler, CommanderSearchResult, CommandId, Keybinding, SearchProvider } from './types';
|
package/keybinding.ts
DELETED
package/model/key-event/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { KeyEvent } from './key-event';
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { BitBaseEvent } from '@teambit/pubsub';
|
|
2
|
-
import { serializeKeyboardEvent } from './serialize-keyboard-event';
|
|
3
|
-
|
|
4
|
-
export class KeyEvent extends BitBaseEvent<KeyboardEventInit> {
|
|
5
|
-
constructor(event: KeyboardEvent, timestamp = Date.now()) {
|
|
6
|
-
const serialized = serializeKeyboardEvent(event);
|
|
7
|
-
super(event.type, '0.0.1', timestamp, serialized);
|
|
8
|
-
}
|
|
9
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import isPrimitive from 'is-primitive';
|
|
2
|
-
|
|
3
|
-
export function serializeKeyboardEvent(e: KeyboardEvent): KeyboardEventInit {
|
|
4
|
-
const serialized = {};
|
|
5
|
-
|
|
6
|
-
// 'for ... in' includes properties from prototype (which we want)
|
|
7
|
-
// eslint-disable-next-line no-restricted-syntax, guard-for-in
|
|
8
|
-
for (const key in e) {
|
|
9
|
-
const val = e[key];
|
|
10
|
-
if (isPrimitive(val)) {
|
|
11
|
-
serialized[key] = val;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return serialized;
|
|
16
|
-
}
|
package/mousetrap-stub.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { MousetrapInstance } from 'mousetrap';
|
|
2
|
-
|
|
3
|
-
export class MousetrapStub implements MousetrapInstance {
|
|
4
|
-
stopCallback() {
|
|
5
|
-
return false;
|
|
6
|
-
}
|
|
7
|
-
bind() {
|
|
8
|
-
return this;
|
|
9
|
-
}
|
|
10
|
-
unbind() {
|
|
11
|
-
return this;
|
|
12
|
-
}
|
|
13
|
-
trigger() {
|
|
14
|
-
return this;
|
|
15
|
-
}
|
|
16
|
-
handleKey() {}
|
|
17
|
-
reset() {
|
|
18
|
-
return this;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
Binary file
|
package/types/asset.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
declare module '*.png' {
|
|
2
|
-
const value: any;
|
|
3
|
-
export = value;
|
|
4
|
-
}
|
|
5
|
-
declare module '*.svg' {
|
|
6
|
-
import type { FunctionComponent, SVGProps } from 'react';
|
|
7
|
-
|
|
8
|
-
export const ReactComponent: FunctionComponent<SVGProps<SVGSVGElement> & { title?: string }>;
|
|
9
|
-
const src: string;
|
|
10
|
-
export default src;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// @TODO Gilad
|
|
14
|
-
declare module '*.jpg' {
|
|
15
|
-
const value: any;
|
|
16
|
-
export = value;
|
|
17
|
-
}
|
|
18
|
-
declare module '*.jpeg' {
|
|
19
|
-
const value: any;
|
|
20
|
-
export = value;
|
|
21
|
-
}
|
|
22
|
-
declare module '*.gif' {
|
|
23
|
-
const value: any;
|
|
24
|
-
export = value;
|
|
25
|
-
}
|
|
26
|
-
declare module '*.bmp' {
|
|
27
|
-
const value: any;
|
|
28
|
-
export = value;
|
|
29
|
-
}
|
package/types/style.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
declare module '*.module.css' {
|
|
2
|
-
const classes: { readonly [key: string]: string };
|
|
3
|
-
export default classes;
|
|
4
|
-
}
|
|
5
|
-
declare module '*.module.scss' {
|
|
6
|
-
const classes: { readonly [key: string]: string };
|
|
7
|
-
export default classes;
|
|
8
|
-
}
|
|
9
|
-
declare module '*.module.sass' {
|
|
10
|
-
const classes: { readonly [key: string]: string };
|
|
11
|
-
export default classes;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
declare module '*.module.less' {
|
|
15
|
-
const classes: { readonly [key: string]: string };
|
|
16
|
-
export default classes;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
declare module '*.less' {
|
|
20
|
-
const classes: { readonly [key: string]: string };
|
|
21
|
-
export default classes;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
declare module '*.css' {
|
|
25
|
-
const classes: { readonly [key: string]: string };
|
|
26
|
-
export default classes;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
declare module '*.sass' {
|
|
30
|
-
const classes: { readonly [key: string]: string };
|
|
31
|
-
export default classes;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
declare module '*.scss' {
|
|
35
|
-
const classes: { readonly [key: string]: string };
|
|
36
|
-
export default classes;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
declare module '*.mdx' {
|
|
40
|
-
const component: any;
|
|
41
|
-
export default component;
|
|
42
|
-
}
|
package/types.tsx
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export type CommandId = string;
|
|
2
|
-
export type CommandHandler = (...arg: any[]) => any;
|
|
3
|
-
|
|
4
|
-
export type CommanderSearchResult = {
|
|
5
|
-
id: string;
|
|
6
|
-
displayName: string;
|
|
7
|
-
handler: CommandHandler;
|
|
8
|
-
icon?: string;
|
|
9
|
-
iconAlt?: string;
|
|
10
|
-
keybinding?: Keybinding;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export interface SearchProvider {
|
|
14
|
-
/** provide completions for this search term */
|
|
15
|
-
search(term: string, limit: number): CommanderSearchResult[];
|
|
16
|
-
/** determines what terms are handled by this searcher. */
|
|
17
|
-
test(term: string): boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export type Keybinding = string | string[];
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
.input {
|
|
2
|
-
font-size: inherit;
|
|
3
|
-
font-family: inherit;
|
|
4
|
-
color: inherit;
|
|
5
|
-
border: none;
|
|
6
|
-
|
|
7
|
-
// command bar is open iff input is focused, so outline is not needed
|
|
8
|
-
outline: none;
|
|
9
|
-
|
|
10
|
-
&::placeholder {
|
|
11
|
-
color: var(--bit-text-inactive, #babec9);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, createRef, InputHTMLAttributes } from 'react';
|
|
2
|
-
import classNames from 'classnames';
|
|
3
|
-
import styles from './autocomplete-input.module.scss';
|
|
4
|
-
|
|
5
|
-
type AutoCompleteInputProps = InputHTMLAttributes<HTMLInputElement> & {
|
|
6
|
-
onEscape?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
7
|
-
onDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
8
|
-
onUp?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
9
|
-
onEnter?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
10
|
-
focus?: Truthy;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
type Truthy = boolean | number | string | null | undefined;
|
|
14
|
-
|
|
15
|
-
export function AutoCompleteInput({
|
|
16
|
-
className,
|
|
17
|
-
onEscape,
|
|
18
|
-
onDown,
|
|
19
|
-
onUp,
|
|
20
|
-
onEnter,
|
|
21
|
-
onKeyDown,
|
|
22
|
-
focus,
|
|
23
|
-
...rest
|
|
24
|
-
}: AutoCompleteInputProps) {
|
|
25
|
-
const inputRef = createRef<HTMLInputElement>();
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (focus) inputRef.current?.focus();
|
|
29
|
-
}, [focus]);
|
|
30
|
-
|
|
31
|
-
const handleKeyDown = useCallback(
|
|
32
|
-
(e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
33
|
-
onKeyDown?.(e);
|
|
34
|
-
if (e.defaultPrevented) return;
|
|
35
|
-
|
|
36
|
-
const handlers = {
|
|
37
|
-
Escape: () => {
|
|
38
|
-
e.preventDefault();
|
|
39
|
-
onEscape?.(e);
|
|
40
|
-
},
|
|
41
|
-
ArrowDown: () => {
|
|
42
|
-
e.preventDefault();
|
|
43
|
-
onDown?.(e);
|
|
44
|
-
},
|
|
45
|
-
ArrowUp: () => {
|
|
46
|
-
e.preventDefault();
|
|
47
|
-
onUp?.(e);
|
|
48
|
-
},
|
|
49
|
-
Enter: () => {
|
|
50
|
-
e.preventDefault();
|
|
51
|
-
onEnter?.(e);
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
if (e.key in handlers) handlers[e.key]();
|
|
56
|
-
},
|
|
57
|
-
[onEscape, onDown, onUp, onEnter]
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
// @ts-ignore (https://github.com/teambit/bit/issues/4908)
|
|
61
|
-
return <input {...rest} ref={inputRef} className={classNames(styles.input, className)} onKeyDown={handleKeyDown} />;
|
|
62
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './autocomplete-input';
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
@import '~@teambit/ui-foundation.ui.constants.z-indexes/z-indexes.module.scss';
|
|
2
|
-
|
|
3
|
-
.commandBar {
|
|
4
|
-
display: none;
|
|
5
|
-
flex-direction: column;
|
|
6
|
-
|
|
7
|
-
position: fixed;
|
|
8
|
-
top: 130px;
|
|
9
|
-
left: 50%;
|
|
10
|
-
transform: translate(-50%, 0);
|
|
11
|
-
width: 643px;
|
|
12
|
-
border: 1px solid var(--bit-border-color, #babec9);
|
|
13
|
-
max-width: 90%;
|
|
14
|
-
|
|
15
|
-
overflow: hidden; // enforce border-radius
|
|
16
|
-
|
|
17
|
-
color: var(--bit-text-color-heavy, #2b2b2b);
|
|
18
|
-
box-shadow: 0 40px 60px 0 rgba(0, 0, 0, 0.32);
|
|
19
|
-
|
|
20
|
-
&.visible {
|
|
21
|
-
display: flex;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.commandBar {
|
|
26
|
-
padding: 0px;
|
|
27
|
-
z-index: $modal-z-index;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.input {
|
|
31
|
-
padding: 0 24px;
|
|
32
|
-
font-size: 20px;
|
|
33
|
-
height: 56px;
|
|
34
|
-
line-height: 56px;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.results {
|
|
38
|
-
font-size: 14px;
|
|
39
|
-
|
|
40
|
-
&:not(:empty) {
|
|
41
|
-
margin-bottom: 8px;
|
|
42
|
-
border-top: solid 1px var(--bit-border-color, #babec9);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useState, useMemo } from 'react';
|
|
2
|
-
import classNames from 'classnames';
|
|
3
|
-
import { Card, CardProps } from '@teambit/base-ui.surfaces.card';
|
|
4
|
-
import type { CommandBarUI } from '../../command-bar.ui.runtime';
|
|
5
|
-
import { CommanderSearchResult } from '../../types';
|
|
6
|
-
import { AutoCompleteInput } from '../autocomplete-input';
|
|
7
|
-
import { CommandBarItem } from '../command-bar-item';
|
|
8
|
-
import styles from './command-bar.module.scss';
|
|
9
|
-
|
|
10
|
-
export type CommandBarProps = {
|
|
11
|
-
search: (term: string, limit?: number) => CommanderSearchResult[];
|
|
12
|
-
commander: CommandBarUI;
|
|
13
|
-
} & CardProps;
|
|
14
|
-
|
|
15
|
-
const MIN_IDX = 0;
|
|
16
|
-
|
|
17
|
-
export function CommandBar({ search, commander, elevation = 'high', className, ...rest }: CommandBarProps) {
|
|
18
|
-
const [term, setTerm] = useState('');
|
|
19
|
-
const options = useMemo(() => search(term), [term, search]);
|
|
20
|
-
const [activeIdx, setActive] = useState(MIN_IDX);
|
|
21
|
-
const increment = useCallback(() => setActive((x) => Math.min(x + 1, options.length - 1)), [options.length]);
|
|
22
|
-
const decrement = useCallback(() => setActive((x) => Math.max(x - 1, MIN_IDX)), []);
|
|
23
|
-
const [visible, setVisibility] = useState(false);
|
|
24
|
-
|
|
25
|
-
commander.setVisibility = setVisibility;
|
|
26
|
-
|
|
27
|
-
const handleEnter = useCallback(() => {
|
|
28
|
-
setVisibility(false);
|
|
29
|
-
options[activeIdx]?.handler();
|
|
30
|
-
}, [options, activeIdx]);
|
|
31
|
-
|
|
32
|
-
useEffect(() => setTerm(''), [visible]);
|
|
33
|
-
useEffect(() => setActive(MIN_IDX), [options]);
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<Card
|
|
37
|
-
{...rest}
|
|
38
|
-
elevation={elevation}
|
|
39
|
-
className={classNames(className, styles.commandBar, visible && styles.visible)}
|
|
40
|
-
>
|
|
41
|
-
<AutoCompleteInput
|
|
42
|
-
value={term}
|
|
43
|
-
focus={visible}
|
|
44
|
-
className={styles.input}
|
|
45
|
-
placeholder="Search anything or type > to only search commands"
|
|
46
|
-
onChange={(e) => setTerm(e.target.value)}
|
|
47
|
-
onDown={increment}
|
|
48
|
-
onUp={decrement}
|
|
49
|
-
onEnter={handleEnter}
|
|
50
|
-
onEscape={() => setVisibility(false)}
|
|
51
|
-
onBlur={() => setVisibility(false)}
|
|
52
|
-
/>
|
|
53
|
-
<div className={styles.results}>
|
|
54
|
-
{options.map((x, idx) => (
|
|
55
|
-
<CommandBarItem
|
|
56
|
-
key={idx} // use index instead of id to avoid duplicate keys
|
|
57
|
-
entry={x}
|
|
58
|
-
active={idx === activeIdx}
|
|
59
|
-
// mouseDown happens before blur, which closes the command bar
|
|
60
|
-
onMouseDown={x.handler}
|
|
61
|
-
/>
|
|
62
|
-
))}
|
|
63
|
-
</div>
|
|
64
|
-
</Card>
|
|
65
|
-
);
|
|
66
|
-
}
|
package/ui/command-bar/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { CommandBar, CommandBarProps } from './command-bar';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { CommandBarContext } from './command-bar-context';
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
.commandBarOption {
|
|
2
|
-
display: flex;
|
|
3
|
-
align-items: center;
|
|
4
|
-
|
|
5
|
-
height: 40px;
|
|
6
|
-
padding: 0 24px;
|
|
7
|
-
transition: all 180ms;
|
|
8
|
-
|
|
9
|
-
user-select: none;
|
|
10
|
-
cursor: pointer;
|
|
11
|
-
|
|
12
|
-
&:hover {
|
|
13
|
-
background-color: var(--bit-bg-heavy, #f6f6f6);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
&.active,
|
|
17
|
-
&.active:hover {
|
|
18
|
-
background-color: var(--bit-accent-bg, #eceaff);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.name {
|
|
23
|
-
flex: 1 1;
|
|
24
|
-
text-overflow: ellipsis;
|
|
25
|
-
overflow: hidden;
|
|
26
|
-
white-space: nowrap;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.commandKeys {
|
|
30
|
-
float: right;
|
|
31
|
-
font-size: 15px;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.icon {
|
|
35
|
-
width: 16px;
|
|
36
|
-
height: 16px;
|
|
37
|
-
margin-right: 8px;
|
|
38
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import classnames from 'classnames';
|
|
3
|
-
import { KeySequence } from '@teambit/ui-foundation.ui.keycap';
|
|
4
|
-
import { mutedText } from '@teambit/base-ui.text.muted-text';
|
|
5
|
-
import { CommanderSearchResult } from '../../types';
|
|
6
|
-
import styles from './command-bar-item.module.scss';
|
|
7
|
-
|
|
8
|
-
export type CommandItemProps = {
|
|
9
|
-
active?: boolean;
|
|
10
|
-
entry: CommanderSearchResult;
|
|
11
|
-
} & React.HTMLAttributes<HTMLDivElement>;
|
|
12
|
-
|
|
13
|
-
export function CommandBarItem({ entry, className, active, ...rest }: CommandItemProps) {
|
|
14
|
-
const { handler, displayName: name, icon, iconAlt, keybinding } = entry;
|
|
15
|
-
const firstKeybinding = Array.isArray(keybinding) ? keybinding[0] : keybinding;
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<div
|
|
19
|
-
{...rest}
|
|
20
|
-
className={classnames(className, styles.commandBarOption, active && styles.active)}
|
|
21
|
-
onMouseDown={handler}
|
|
22
|
-
>
|
|
23
|
-
{icon && <img src={icon} alt={iconAlt} className={styles.icon} />}
|
|
24
|
-
<div className={styles.name}>{name}</div>
|
|
25
|
-
{firstKeybinding && (
|
|
26
|
-
<KeySequence className={classnames(styles.commandKeys, mutedText)}>{firstKeybinding}</KeySequence>
|
|
27
|
-
)}
|
|
28
|
-
</div>
|
|
29
|
-
);
|
|
30
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { CommandBarItem, CommandItemProps } from './command-bar-item';
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import Fuse from 'fuse.js';
|
|
2
|
-
import { CommanderSearchResult, SearchProvider } from '../../types';
|
|
3
|
-
|
|
4
|
-
const searchedKeys: (keyof CommanderSearchResult)[] = ['displayName'];
|
|
5
|
-
|
|
6
|
-
export class CommandSearcher implements SearchProvider {
|
|
7
|
-
private fuseCommands = new Fuse<CommanderSearchResult>([], {
|
|
8
|
-
// weight can be included here.
|
|
9
|
-
// fields loses weight the longer they get, so it seems ok for now.
|
|
10
|
-
keys: searchedKeys,
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
constructor(commands: CommanderSearchResult[]) {
|
|
14
|
-
this.fuseCommands.setCollection(commands);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
update(commands: CommanderSearchResult[]) {
|
|
18
|
-
this.fuseCommands.setCollection(commands);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
search(term: string, limit: number): CommanderSearchResult[] {
|
|
22
|
-
const unprefixedPattern = term.replace(/^>/, '');
|
|
23
|
-
const searchResults = this.fuseCommands.search(unprefixedPattern, { limit });
|
|
24
|
-
// @ts-ignore this shows error on Circle for some weird reason
|
|
25
|
-
return searchResults.map((x) => x.item);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
test(term: string): boolean {
|
|
29
|
-
return term.startsWith('>');
|
|
30
|
-
}
|
|
31
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { CommandSearcher } from './command-searcher';
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import Fuse from 'fuse.js';
|
|
2
|
-
import memoizeOne from 'memoize-one';
|
|
3
|
-
import { ComponentModel } from '@teambit/component';
|
|
4
|
-
import { SearchProvider, CommanderSearchResult } from '../../types';
|
|
5
|
-
|
|
6
|
-
type ComponentSearchResult = CommanderSearchResult & { name: string };
|
|
7
|
-
|
|
8
|
-
const searchedKeys: (keyof ComponentSearchResult)[] = ['displayName', 'name'];
|
|
9
|
-
|
|
10
|
-
export class ComponentSearcher implements SearchProvider {
|
|
11
|
-
private fuseCommands = new Fuse<ComponentSearchResult>([], {
|
|
12
|
-
// weight can be included here.
|
|
13
|
-
// fields loses weight the longer they get, so it seems ok for now.
|
|
14
|
-
keys: searchedKeys,
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
constructor(private navigate: (path: string) => void) {}
|
|
18
|
-
|
|
19
|
-
// this method can be called on every render. memoize to prevent redundant calls
|
|
20
|
-
update = memoizeOne((components: ComponentModel[]) => {
|
|
21
|
-
const { navigate } = this;
|
|
22
|
-
|
|
23
|
-
const searchResults = components.map((c) => ({
|
|
24
|
-
id: c.id.fullName,
|
|
25
|
-
displayName: c.id.fullName,
|
|
26
|
-
name: c.id.name,
|
|
27
|
-
handler: () => navigate(`/${c.id.fullName}`),
|
|
28
|
-
icon: c.environment?.icon,
|
|
29
|
-
iconAlt: c.environment?.id,
|
|
30
|
-
}));
|
|
31
|
-
|
|
32
|
-
this.fuseCommands.setCollection(searchResults);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
search(term: string, limit: number): ComponentSearchResult[] {
|
|
36
|
-
const searchResults = this.fuseCommands.search(term, { limit });
|
|
37
|
-
// @ts-ignore this shows error on Circle for some weird reason
|
|
38
|
-
return searchResults.map((x) => x.item);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
test(term: string): boolean {
|
|
42
|
-
return !term.startsWith('>') && term.length > 0;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { ComponentSearcher } from './component-searcher';
|