ui-thing 0.0.9 → 0.0.11
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/CHANGELOG.md +45 -0
- package/README.md +8 -0
- package/dist/index.js +326 -8491
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
- package/src/commands/add.ts +6 -2
- package/src/commands/init.ts +1 -1
- package/src/commands/shortcuts.ts +42 -0
- package/src/index.ts +2 -0
- package/src/templates/shortcuts.ts +217 -0
- package/src/types.ts +1 -0
- package/src/utils/addShortcutFiles.ts +12 -0
- package/src/utils/constants.ts +0 -2
- package/src/utils/fetchComponents.ts +8 -0
- package/src/utils/promptForComponents.ts +8 -2
- package/src/comp.ts +0 -2287
package/package.json
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ui-thing",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"description": "CLI used to add Nuxt 3 components to a project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"repository": {
|
|
9
|
-
"url": "https://github.com/BayBreezy/ui-thing-cli"
|
|
9
|
+
"url": "git+https://github.com/BayBreezy/ui-thing-cli.git"
|
|
10
10
|
},
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
14
|
-
"bin":
|
|
14
|
+
"bin": {
|
|
15
|
+
"ui-thing": "dist/index.js"
|
|
16
|
+
},
|
|
15
17
|
"scripts": {
|
|
16
18
|
"build": "tsup",
|
|
17
19
|
"dev": "tsup --watch",
|
|
@@ -38,6 +40,7 @@
|
|
|
38
40
|
},
|
|
39
41
|
"license": "MIT",
|
|
40
42
|
"dependencies": {
|
|
43
|
+
"axios": "^1.6.2",
|
|
41
44
|
"boxen": "^7.1.1",
|
|
42
45
|
"build": "^0.1.4",
|
|
43
46
|
"c12": "^1.5.1",
|
package/src/commands/add.ts
CHANGED
|
@@ -5,15 +5,17 @@ import kleur from "kleur";
|
|
|
5
5
|
import _ from "lodash";
|
|
6
6
|
import prompts from "prompts";
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import { Component } from "../types";
|
|
9
9
|
import { compareUIConfig } from "../utils/compareUIConfig";
|
|
10
10
|
import { addModuleToConfig, getNuxtConfig, getUIConfig, updateConfig } from "../utils/config";
|
|
11
|
+
import { fetchComponents } from "../utils/fetchComponents";
|
|
11
12
|
import { fileExists } from "../utils/fileExists";
|
|
12
13
|
import { installPackages } from "../utils/installPackages";
|
|
13
14
|
import { printFancyBoxMessage } from "../utils/printFancyBoxMessage";
|
|
14
15
|
import { promptUserForComponents } from "../utils/promptForComponents";
|
|
15
16
|
import { writeFile } from "../utils/writeFile";
|
|
16
17
|
|
|
18
|
+
let allComponents: Component[] = [];
|
|
17
19
|
const currentDirectory = process.cwd();
|
|
18
20
|
|
|
19
21
|
const findComponent = (name: string) => {
|
|
@@ -41,6 +43,8 @@ export const add = new Command()
|
|
|
41
43
|
consola.info("Config file not set. Exiting...");
|
|
42
44
|
process.exit(0);
|
|
43
45
|
}
|
|
46
|
+
// get components from API
|
|
47
|
+
allComponents = await fetchComponents();
|
|
44
48
|
|
|
45
49
|
let componentNames = components;
|
|
46
50
|
// if no components are passed, prompt the user to select components
|
|
@@ -65,7 +69,7 @@ export const add = new Command()
|
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
// store the components that are found
|
|
68
|
-
let found:
|
|
72
|
+
let found: Component[] = [];
|
|
69
73
|
componentNames.forEach((c) => {
|
|
70
74
|
if (findComponent(c)) {
|
|
71
75
|
found.push(findComponent(c)!);
|
package/src/commands/init.ts
CHANGED
|
@@ -57,7 +57,7 @@ export const init = new Command()
|
|
|
57
57
|
type: true,
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
|
-
//
|
|
60
|
+
// Write changes to nuxt config
|
|
61
61
|
await updateConfig(cfg.nuxtConfig, "nuxt.config.ts");
|
|
62
62
|
// instal deps
|
|
63
63
|
await installPackages(uiConfig.packageManager, INIT_DEPS, INIT_DEV_DEPS);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import prompts from "prompts";
|
|
3
|
+
|
|
4
|
+
import { addShortcutFiles } from "../utils/addShortcutFiles";
|
|
5
|
+
import { addModuleToConfig, getNuxtConfig, updateConfig } from "../utils/config";
|
|
6
|
+
import { installPackages } from "../utils/installPackages";
|
|
7
|
+
import { printFancyBoxMessage } from "../utils/printFancyBoxMessage";
|
|
8
|
+
|
|
9
|
+
export const addShortcuts = new Command()
|
|
10
|
+
.command("shortcuts")
|
|
11
|
+
.name("shortcuts")
|
|
12
|
+
.description("Add the defineShortcuts & useShortcuts composables to your project.")
|
|
13
|
+
.action(async () => {
|
|
14
|
+
await addShortcutFiles();
|
|
15
|
+
|
|
16
|
+
// Get nuxt config
|
|
17
|
+
const cfg = await getNuxtConfig();
|
|
18
|
+
addModuleToConfig(cfg.nuxtConfig, ["@vueuse/nuxt"]);
|
|
19
|
+
// Write changes to nuxt config
|
|
20
|
+
await updateConfig(cfg.nuxtConfig, "nuxt.config.ts");
|
|
21
|
+
|
|
22
|
+
const { pkgManager } = await prompts({
|
|
23
|
+
name: "pkgManager",
|
|
24
|
+
type: "select",
|
|
25
|
+
message: "Which package manager are you using?",
|
|
26
|
+
choices: [
|
|
27
|
+
{ title: "npm", value: "npm" },
|
|
28
|
+
{ title: "yarn", value: "yarn" },
|
|
29
|
+
{ title: "pnpm", value: "pnpm" },
|
|
30
|
+
{ title: "bun", value: "bun" },
|
|
31
|
+
],
|
|
32
|
+
});
|
|
33
|
+
if (!pkgManager) return process.exit(0);
|
|
34
|
+
|
|
35
|
+
// install prettier dep
|
|
36
|
+
await installPackages(pkgManager, undefined, ["@vueuse/math", "@vueuse/nuxt"]);
|
|
37
|
+
printFancyBoxMessage(
|
|
38
|
+
"All Done!",
|
|
39
|
+
{ title: "Shortcuts Added" },
|
|
40
|
+
`Check the composables folder for the defineShortcuts & useShortcuts composables.`
|
|
41
|
+
);
|
|
42
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { Command } from "commander";
|
|
|
4
4
|
import { add } from "./commands/add";
|
|
5
5
|
import { init } from "./commands/init";
|
|
6
6
|
import { addPrettier } from "./commands/prettier";
|
|
7
|
+
import { addShortcuts } from "./commands/shortcuts";
|
|
7
8
|
import { theme } from "./commands/theme";
|
|
8
9
|
import { printFancyBoxMessage } from "./utils/printFancyBoxMessage";
|
|
9
10
|
|
|
@@ -25,6 +26,7 @@ program
|
|
|
25
26
|
.addCommand(init)
|
|
26
27
|
.addCommand(add)
|
|
27
28
|
.addCommand(theme)
|
|
29
|
+
.addCommand(addShortcuts)
|
|
28
30
|
.addCommand(addPrettier);
|
|
29
31
|
|
|
30
32
|
program.parse(process.argv);
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
export const DEFINE_SHORTCUT = `import { logicAnd, logicNot } from "@vueuse/math";
|
|
2
|
+
import { computed, ref } from "vue";
|
|
3
|
+
import type { ComputedRef, WatchSource } from "vue";
|
|
4
|
+
|
|
5
|
+
export interface ShortcutConfig {
|
|
6
|
+
handler: Function;
|
|
7
|
+
usingInput?: string | boolean;
|
|
8
|
+
whenever?: WatchSource<Boolean>[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ShortcutsConfig {
|
|
12
|
+
[key: string]: ShortcutConfig | Function;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ShortcutsOptions {
|
|
16
|
+
chainDelay?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface Shortcut {
|
|
20
|
+
handler: Function;
|
|
21
|
+
condition: ComputedRef<Boolean>;
|
|
22
|
+
chained: boolean;
|
|
23
|
+
// KeyboardEvent attributes
|
|
24
|
+
key: string;
|
|
25
|
+
ctrlKey: boolean;
|
|
26
|
+
metaKey: boolean;
|
|
27
|
+
shiftKey: boolean;
|
|
28
|
+
altKey: boolean;
|
|
29
|
+
// code?: string
|
|
30
|
+
// keyCode?: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const defineShortcuts = (config: ShortcutsConfig, options: ShortcutsOptions = {}) => {
|
|
34
|
+
const { macOS, usingInput } = useShortcuts();
|
|
35
|
+
|
|
36
|
+
let shortcuts: Shortcut[] = [];
|
|
37
|
+
|
|
38
|
+
const chainedInputs = ref<any[]>([]);
|
|
39
|
+
const clearChainedInput = () => {
|
|
40
|
+
chainedInputs.value.splice(0, chainedInputs.value.length);
|
|
41
|
+
};
|
|
42
|
+
const debouncedClearChainedInput = useDebounceFn(clearChainedInput, options.chainDelay ?? 800);
|
|
43
|
+
|
|
44
|
+
const onKeyDown = (e: KeyboardEvent) => {
|
|
45
|
+
// Input autocomplete triggers a keydown event
|
|
46
|
+
if (!e.key) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const alphabeticalKey = /^[a-z]{1}$/i.test(e.key);
|
|
51
|
+
|
|
52
|
+
let chainedKey;
|
|
53
|
+
chainedInputs.value.push(e.key);
|
|
54
|
+
// try matching a chained shortcut
|
|
55
|
+
if (chainedInputs.value.length >= 2) {
|
|
56
|
+
chainedKey = chainedInputs.value.slice(-2).join("-");
|
|
57
|
+
|
|
58
|
+
for (const shortcut of shortcuts.filter((s) => s.chained)) {
|
|
59
|
+
if (shortcut.key !== chainedKey) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (shortcut.condition.value) {
|
|
64
|
+
e.preventDefault();
|
|
65
|
+
shortcut.handler();
|
|
66
|
+
}
|
|
67
|
+
clearChainedInput();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// try matching a standard shortcut
|
|
73
|
+
for (const shortcut of shortcuts.filter((s) => !s.chained)) {
|
|
74
|
+
if (e.key.toLowerCase() !== shortcut.key) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (e.metaKey !== shortcut.metaKey) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (e.ctrlKey !== shortcut.ctrlKey) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
// shift modifier is only checked in combination with alphabetical keys
|
|
84
|
+
// (shift with non-alphabetical keys would change the key)
|
|
85
|
+
if (alphabeticalKey && e.shiftKey !== shortcut.shiftKey) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
// alt modifier changes the combined key anyways
|
|
89
|
+
// if (e.altKey !== shortcut.altKey) { continue }
|
|
90
|
+
|
|
91
|
+
if (shortcut.condition.value) {
|
|
92
|
+
e.preventDefault();
|
|
93
|
+
shortcut.handler();
|
|
94
|
+
}
|
|
95
|
+
clearChainedInput();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
debouncedClearChainedInput();
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Map config to full detailled shortcuts
|
|
103
|
+
shortcuts = Object.entries(config)
|
|
104
|
+
.map(([key, shortcutConfig]) => {
|
|
105
|
+
if (!shortcutConfig) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Parse key and modifiers
|
|
110
|
+
let shortcut: Partial<Shortcut>;
|
|
111
|
+
|
|
112
|
+
if (key.includes("-") && key.includes("_")) {
|
|
113
|
+
console.trace("[Shortcut] Invalid key");
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const chained = key.includes("-");
|
|
118
|
+
if (chained) {
|
|
119
|
+
shortcut = {
|
|
120
|
+
key: key.toLowerCase(),
|
|
121
|
+
metaKey: false,
|
|
122
|
+
ctrlKey: false,
|
|
123
|
+
shiftKey: false,
|
|
124
|
+
altKey: false,
|
|
125
|
+
};
|
|
126
|
+
} else {
|
|
127
|
+
const keySplit = key
|
|
128
|
+
.toLowerCase()
|
|
129
|
+
.split("_")
|
|
130
|
+
.map((k) => k);
|
|
131
|
+
shortcut = {
|
|
132
|
+
key: keySplit.filter((k) => !["meta", "ctrl", "shift", "alt"].includes(k)).join("_"),
|
|
133
|
+
metaKey: keySplit.includes("meta"),
|
|
134
|
+
ctrlKey: keySplit.includes("ctrl"),
|
|
135
|
+
shiftKey: keySplit.includes("shift"),
|
|
136
|
+
altKey: keySplit.includes("alt"),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
shortcut.chained = chained;
|
|
140
|
+
|
|
141
|
+
// Convert Meta to Ctrl for non-MacOS
|
|
142
|
+
if (!macOS.value && shortcut.metaKey && !shortcut.ctrlKey) {
|
|
143
|
+
shortcut.metaKey = false;
|
|
144
|
+
shortcut.ctrlKey = true;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Retrieve handler function
|
|
148
|
+
if (typeof shortcutConfig === "function") {
|
|
149
|
+
shortcut.handler = shortcutConfig;
|
|
150
|
+
} else if (typeof shortcutConfig === "object") {
|
|
151
|
+
shortcut = { ...shortcut, handler: shortcutConfig.handler };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!shortcut.handler) {
|
|
155
|
+
console.trace("[Shortcut] Invalid value");
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Create shortcut computed
|
|
160
|
+
const conditions: ComputedRef<Boolean>[] = [];
|
|
161
|
+
if (!(shortcutConfig as ShortcutConfig).usingInput) {
|
|
162
|
+
conditions.push(logicNot(usingInput));
|
|
163
|
+
} else if (typeof (shortcutConfig as ShortcutConfig).usingInput === "string") {
|
|
164
|
+
conditions.push(
|
|
165
|
+
computed(() => usingInput.value === (shortcutConfig as ShortcutConfig).usingInput)
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
shortcut.condition = logicAnd(
|
|
169
|
+
...conditions,
|
|
170
|
+
...((shortcutConfig as ShortcutConfig).whenever || [])
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
return shortcut as Shortcut;
|
|
174
|
+
})
|
|
175
|
+
.filter(Boolean) as Shortcut[];
|
|
176
|
+
|
|
177
|
+
useEventListener("keydown", onKeyDown);
|
|
178
|
+
};
|
|
179
|
+
`;
|
|
180
|
+
|
|
181
|
+
export const USE_SHORTCUTS = `export const _useShortcuts = () => {
|
|
182
|
+
const macOS = computed(
|
|
183
|
+
() =>
|
|
184
|
+
process.client && navigator && navigator.userAgent && navigator.userAgent.match(/Macintosh;/)
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
const metaSymbol = ref(" ");
|
|
188
|
+
|
|
189
|
+
const activeElement = useActiveElement();
|
|
190
|
+
const usingInput = computed(() => {
|
|
191
|
+
const usingInput = !!(
|
|
192
|
+
activeElement.value?.tagName === "INPUT" ||
|
|
193
|
+
activeElement.value?.tagName === "TEXTAREA" ||
|
|
194
|
+
activeElement.value?.contentEditable === "true"
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
if (usingInput) {
|
|
198
|
+
return ((activeElement.value as any)?.name as string) || true;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return false;
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
onMounted(() => {
|
|
205
|
+
metaSymbol.value = macOS.value ? "⌘" : "Ctrl";
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
macOS,
|
|
210
|
+
metaSymbol,
|
|
211
|
+
activeElement,
|
|
212
|
+
usingInput,
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export const useShortcuts = createSharedComposable(_useShortcuts);
|
|
217
|
+
`;
|
package/src/types.ts
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import fse from "fs-extra";
|
|
2
|
+
|
|
3
|
+
import { DEFINE_SHORTCUT, USE_SHORTCUTS } from "../templates/shortcuts";
|
|
4
|
+
|
|
5
|
+
export const addShortcutFiles = async (cwd = process.cwd()) => {
|
|
6
|
+
// ensure that the composable folder exists
|
|
7
|
+
await fse.ensureDir(`${cwd}/composables`);
|
|
8
|
+
// write the defineShortcuts composable
|
|
9
|
+
await fse.writeFile(`${cwd}/composables/defineShortcuts.ts`, DEFINE_SHORTCUT, "utf-8");
|
|
10
|
+
// write the useShortcuts composable
|
|
11
|
+
await fse.writeFile(`${cwd}/composables/useShortcuts.ts`, USE_SHORTCUTS, "utf-8");
|
|
12
|
+
};
|
package/src/utils/constants.ts
CHANGED
|
@@ -3,7 +3,6 @@ export const INIT_DEV_DEPS = [
|
|
|
3
3
|
"typescript",
|
|
4
4
|
"tailwindcss-animate",
|
|
5
5
|
"nuxt-icon",
|
|
6
|
-
"nuxt-lodash",
|
|
7
6
|
"prettier-plugin-tailwindcss",
|
|
8
7
|
"prettier",
|
|
9
8
|
"@nuxtjs/tailwindcss",
|
|
@@ -16,7 +15,6 @@ export const INIT_MODULES = [
|
|
|
16
15
|
"@nuxtjs/tailwindcss",
|
|
17
16
|
"@nuxtjs/color-mode",
|
|
18
17
|
"@vueuse/nuxt",
|
|
19
|
-
"nuxt-lodash",
|
|
20
18
|
"nuxt-icon",
|
|
21
19
|
];
|
|
22
20
|
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
+
import ora from "ora";
|
|
1
2
|
import prompts from "prompts";
|
|
2
3
|
|
|
3
|
-
import
|
|
4
|
+
import { Component } from "../types";
|
|
5
|
+
import { fetchComponents } from "./fetchComponents";
|
|
4
6
|
|
|
5
7
|
export const promptUserForComponents = async (): Promise<string[]> => {
|
|
8
|
+
// get comps from API
|
|
9
|
+
const compsSpinner = ora("Fetching components...").start();
|
|
10
|
+
const allComponents = await fetchComponents();
|
|
11
|
+
compsSpinner.succeed("Fetched components");
|
|
6
12
|
const { components } = await prompts({
|
|
7
13
|
type: "autocompleteMultiselect",
|
|
8
14
|
name: "components",
|
|
9
15
|
message: "Select the components you want to add",
|
|
10
|
-
choices: allComponents.map((c) => ({ title: c.name, value: c.value })),
|
|
16
|
+
choices: allComponents.map((c: Component) => ({ title: c.name, value: c.value })),
|
|
11
17
|
onRender(kleur) {
|
|
12
18
|
// @ts-ignore
|
|
13
19
|
this.msg = kleur.bgCyan(" Choose components ") + " Select the components you want to add";
|