ui-thing 0.1.56 → 0.2.1
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/.husky/pre-commit +1 -0
- package/CHANGELOG.md +76 -0
- package/README.md +4 -3
- package/dist/index.js +1175 -15776
- package/dist/index.js.map +1 -1
- package/package.json +34 -22
- package/src/commands/add.ts +218 -274
- package/src/commands/init.ts +107 -58
- package/src/commands/prettier.ts +6 -8
- package/src/commands/shortcuts.ts +13 -13
- package/src/commands/theme.ts +9 -6
- package/src/index.ts +2 -2
- package/src/templates/css.ts +958 -773
- package/src/templates/prettier.ts +14 -16
- package/src/templates/shortcuts.ts +225 -126
- package/src/templates/tw-helper.ts +8 -0
- package/src/templates/vs-code.ts +24 -0
- package/src/types.ts +74 -3
- package/src/utils/addPrettierConfig.ts +49 -6
- package/src/utils/addShortcutFiles.ts +5 -4
- package/src/utils/addTailwindVitePlugin.ts +35 -0
- package/src/utils/addVSCodeFiles.ts +13 -0
- package/src/utils/compareUIConfig.ts +1 -2
- package/src/utils/config.ts +59 -86
- package/src/utils/constants.ts +67 -13
- package/src/utils/detectNuxtVersion.ts +20 -0
- package/src/utils/fetchComponents.ts +14 -1
- package/src/utils/installPackages.ts +3 -27
- package/src/utils/mergeJsonFile.ts +28 -0
- package/src/utils/printFancyBoxMessage.ts +62 -16
- package/src/utils/promptForComponents.ts +8 -6
- package/src/utils/uiConfigPrompt.ts +12 -37
- package/tsconfig.json +2 -1
- package/dist/chunk-FW4363Y4.js +0 -2
- package/dist/chunk-FW4363Y4.js.map +0 -1
- package/dist/prompt-4NXDAQWE.js +0 -46
- package/dist/prompt-4NXDAQWE.js.map +0 -1
- package/src/comps.ts +0 -3237
- package/src/templates/tailwind.ts +0 -142
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
export const PRETTIER_CONFIG =
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
`;
|
|
1
|
+
export const PRETTIER_CONFIG = {
|
|
2
|
+
arrowParens: "always",
|
|
3
|
+
endOfLine: "lf",
|
|
4
|
+
plugins: ["@ianvs/prettier-plugin-sort-imports", "prettier-plugin-tailwindcss"],
|
|
5
|
+
printWidth: 100,
|
|
6
|
+
semi: true,
|
|
7
|
+
singleQuote: false,
|
|
8
|
+
tabWidth: 2,
|
|
9
|
+
trailingComma: "es5",
|
|
10
|
+
useTabs: false,
|
|
11
|
+
vueIndentScriptAndStyle: true,
|
|
12
|
+
tailwindFunctions: ["tv"],
|
|
13
|
+
importOrder: ["<BUILTIN_MODULES>", "<THIRD_PARTY_MODULES>", "<TYPES>", "", "^[.]"],
|
|
14
|
+
};
|
|
@@ -1,15 +1,95 @@
|
|
|
1
|
-
export const DEFINE_SHORTCUT =
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export const DEFINE_SHORTCUT = `import {
|
|
2
|
+
createSharedComposable,
|
|
3
|
+
useActiveElement,
|
|
4
|
+
useDebounceFn,
|
|
5
|
+
useEventListener,
|
|
6
|
+
} from "@vueuse/core";
|
|
7
|
+
import type { MaybeRef } from "vue";
|
|
8
|
+
|
|
9
|
+
type KbdKeysSpecificMap = {
|
|
10
|
+
meta: string;
|
|
11
|
+
alt: string;
|
|
12
|
+
ctrl: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const kbdKeysMap = {
|
|
16
|
+
meta: "",
|
|
17
|
+
ctrl: "",
|
|
18
|
+
alt: "",
|
|
19
|
+
win: "⊞",
|
|
20
|
+
command: "⌘",
|
|
21
|
+
shift: "⇧",
|
|
22
|
+
control: "⌃",
|
|
23
|
+
option: "⌥",
|
|
24
|
+
enter: "↵",
|
|
25
|
+
delete: "⌦",
|
|
26
|
+
backspace: "⌫",
|
|
27
|
+
escape: "⎋",
|
|
28
|
+
tab: "⇥",
|
|
29
|
+
capslock: "⇪",
|
|
30
|
+
arrowup: "↑",
|
|
31
|
+
arrowright: "→",
|
|
32
|
+
arrowdown: "↓",
|
|
33
|
+
arrowleft: "←",
|
|
34
|
+
pageup: "⇞",
|
|
35
|
+
pagedown: "⇟",
|
|
36
|
+
home: "↖",
|
|
37
|
+
end: "↘",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type KbdKey = keyof typeof kbdKeysMap;
|
|
41
|
+
export type KbdKeySpecific = keyof KbdKeysSpecificMap;
|
|
42
|
+
|
|
43
|
+
const _useKbd = () => {
|
|
44
|
+
const macOS = computed(
|
|
45
|
+
() =>
|
|
46
|
+
import.meta.client &&
|
|
47
|
+
navigator &&
|
|
48
|
+
navigator.userAgent &&
|
|
49
|
+
navigator.userAgent.match(/Macintosh;/)
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const kbdKeysSpecificMap = reactive({
|
|
53
|
+
meta: " ",
|
|
54
|
+
alt: " ",
|
|
55
|
+
ctrl: " ",
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
onMounted(() => {
|
|
59
|
+
kbdKeysSpecificMap.meta = macOS.value ? kbdKeysMap.command : "Ctrl";
|
|
60
|
+
kbdKeysSpecificMap.ctrl = macOS.value ? kbdKeysMap.control : "Ctrl";
|
|
61
|
+
kbdKeysSpecificMap.alt = macOS.value ? kbdKeysMap.option : "Alt";
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
function getKbdKey(value?: KbdKey | string) {
|
|
65
|
+
if (!value) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (["meta", "alt", "ctrl"].includes(value)) {
|
|
70
|
+
return kbdKeysSpecificMap[value as KbdKeySpecific];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return kbdKeysMap[value as KbdKey] || value.toUpperCase();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
macOS,
|
|
78
|
+
getKbdKey,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const useKbd = /* @__PURE__ */ createSharedComposable(_useKbd);
|
|
83
|
+
|
|
84
|
+
type Handler = (e?: any) => void;
|
|
4
85
|
|
|
5
86
|
export interface ShortcutConfig {
|
|
6
|
-
handler:
|
|
87
|
+
handler: Handler;
|
|
7
88
|
usingInput?: string | boolean;
|
|
8
|
-
whenever?: WatchSource<boolean>[];
|
|
9
89
|
}
|
|
10
90
|
|
|
11
91
|
export interface ShortcutsConfig {
|
|
12
|
-
[key: string]: ShortcutConfig |
|
|
92
|
+
[key: string]: ShortcutConfig | Handler | false | null | undefined;
|
|
13
93
|
}
|
|
14
94
|
|
|
15
95
|
export interface ShortcutsOptions {
|
|
@@ -17,8 +97,8 @@ export interface ShortcutsOptions {
|
|
|
17
97
|
}
|
|
18
98
|
|
|
19
99
|
interface Shortcut {
|
|
20
|
-
handler:
|
|
21
|
-
|
|
100
|
+
handler: Handler;
|
|
101
|
+
enabled: boolean;
|
|
22
102
|
chained: boolean;
|
|
23
103
|
// KeyboardEvent attributes
|
|
24
104
|
key: string;
|
|
@@ -30,24 +110,61 @@ interface Shortcut {
|
|
|
30
110
|
// keyCode?: number
|
|
31
111
|
}
|
|
32
112
|
|
|
33
|
-
|
|
34
|
-
|
|
113
|
+
const chainedShortcutRegex = /^[^-]+.*-.*[^-]+$/;
|
|
114
|
+
const combinedShortcutRegex = /^[^_]+.*_.*[^_]+$/;
|
|
115
|
+
// keyboard keys which can be combined with Shift modifier (in addition to alphabet keys)
|
|
116
|
+
const shiftableKeys = [
|
|
117
|
+
"arrowleft",
|
|
118
|
+
"arrowright",
|
|
119
|
+
"arrowup",
|
|
120
|
+
"arrowright",
|
|
121
|
+
"tab",
|
|
122
|
+
"escape",
|
|
123
|
+
"enter",
|
|
124
|
+
"backspace",
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
export function extractShortcuts(items: any[] | any[][]) {
|
|
128
|
+
const shortcuts: Record<string, Handler> = {};
|
|
129
|
+
|
|
130
|
+
function traverse(items: any[]) {
|
|
131
|
+
items.forEach((item) => {
|
|
132
|
+
if (item.kbds?.length && (item.onSelect || item.onClick)) {
|
|
133
|
+
const shortcutKey = item.kbds.join("_");
|
|
134
|
+
shortcuts[shortcutKey] = item.onSelect || item.onClick;
|
|
135
|
+
}
|
|
136
|
+
if (item.children) {
|
|
137
|
+
traverse(item.children.flat());
|
|
138
|
+
}
|
|
139
|
+
if (item.items) {
|
|
140
|
+
traverse(item.items.flat());
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
traverse(items.flat());
|
|
35
146
|
|
|
36
|
-
|
|
147
|
+
return shortcuts;
|
|
148
|
+
}
|
|
37
149
|
|
|
38
|
-
|
|
150
|
+
export function defineShortcuts(config: MaybeRef<ShortcutsConfig>, options: ShortcutsOptions = {}) {
|
|
151
|
+
const chainedInputs = ref<string[]>([]);
|
|
39
152
|
const clearChainedInput = () => {
|
|
40
153
|
chainedInputs.value.splice(0, chainedInputs.value.length);
|
|
41
154
|
};
|
|
42
155
|
const debouncedClearChainedInput = useDebounceFn(clearChainedInput, options.chainDelay ?? 800);
|
|
43
156
|
|
|
157
|
+
const { macOS } = useKbd();
|
|
158
|
+
const activeElement = useActiveElement();
|
|
159
|
+
|
|
44
160
|
const onKeyDown = (e: KeyboardEvent) => {
|
|
45
161
|
// Input autocomplete triggers a keydown event
|
|
46
162
|
if (!e.key) {
|
|
47
163
|
return;
|
|
48
164
|
}
|
|
49
165
|
|
|
50
|
-
const
|
|
166
|
+
const alphabetKey = /^[a-z]{1}$/i.test(e.key);
|
|
167
|
+
const shiftableKey = shiftableKeys.includes(e.key.toLowerCase());
|
|
51
168
|
|
|
52
169
|
let chainedKey;
|
|
53
170
|
chainedInputs.value.push(e.key);
|
|
@@ -55,14 +172,14 @@ export const defineShortcuts = (config: ShortcutsConfig, options: ShortcutsOptio
|
|
|
55
172
|
if (chainedInputs.value.length >= 2) {
|
|
56
173
|
chainedKey = chainedInputs.value.slice(-2).join("-");
|
|
57
174
|
|
|
58
|
-
for (const shortcut of shortcuts.filter((s) => s.chained)) {
|
|
175
|
+
for (const shortcut of shortcuts.value.filter((s) => s.chained)) {
|
|
59
176
|
if (shortcut.key !== chainedKey) {
|
|
60
177
|
continue;
|
|
61
178
|
}
|
|
62
179
|
|
|
63
|
-
if (shortcut.
|
|
180
|
+
if (shortcut.enabled) {
|
|
64
181
|
e.preventDefault();
|
|
65
|
-
shortcut.handler();
|
|
182
|
+
shortcut.handler(e);
|
|
66
183
|
}
|
|
67
184
|
clearChainedInput();
|
|
68
185
|
return;
|
|
@@ -70,7 +187,7 @@ export const defineShortcuts = (config: ShortcutsConfig, options: ShortcutsOptio
|
|
|
70
187
|
}
|
|
71
188
|
|
|
72
189
|
// try matching a standard shortcut
|
|
73
|
-
for (const shortcut of shortcuts.filter((s) => !s.chained)) {
|
|
190
|
+
for (const shortcut of shortcuts.value.filter((s) => !s.chained)) {
|
|
74
191
|
if (e.key.toLowerCase() !== shortcut.key) {
|
|
75
192
|
continue;
|
|
76
193
|
}
|
|
@@ -80,17 +197,17 @@ export const defineShortcuts = (config: ShortcutsConfig, options: ShortcutsOptio
|
|
|
80
197
|
if (e.ctrlKey !== shortcut.ctrlKey) {
|
|
81
198
|
continue;
|
|
82
199
|
}
|
|
83
|
-
// shift modifier is only checked in combination with
|
|
84
|
-
// (shift with
|
|
85
|
-
if (
|
|
200
|
+
// shift modifier is only checked in combination with alphabet keys and some extra keys
|
|
201
|
+
// (shift with special characters would change the key)
|
|
202
|
+
if ((alphabetKey || shiftableKey) && e.shiftKey !== shortcut.shiftKey) {
|
|
86
203
|
continue;
|
|
87
204
|
}
|
|
88
205
|
// alt modifier changes the combined key anyways
|
|
89
206
|
// if (e.altKey !== shortcut.altKey) { continue }
|
|
90
207
|
|
|
91
|
-
if (shortcut.
|
|
208
|
+
if (shortcut.enabled) {
|
|
92
209
|
e.preventDefault();
|
|
93
|
-
shortcut.handler();
|
|
210
|
+
shortcut.handler(e);
|
|
94
211
|
}
|
|
95
212
|
clearChainedInput();
|
|
96
213
|
return;
|
|
@@ -99,124 +216,106 @@ export const defineShortcuts = (config: ShortcutsConfig, options: ShortcutsOptio
|
|
|
99
216
|
debouncedClearChainedInput();
|
|
100
217
|
};
|
|
101
218
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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;
|
|
219
|
+
const usingInput = computed(() => {
|
|
220
|
+
const tagName = activeElement.value?.tagName;
|
|
221
|
+
const contentEditable = activeElement.value?.contentEditable;
|
|
140
222
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
223
|
+
const usingInput = !!(
|
|
224
|
+
tagName === "INPUT" ||
|
|
225
|
+
tagName === "TEXTAREA" ||
|
|
226
|
+
contentEditable === "true" ||
|
|
227
|
+
contentEditable === "plaintext-only"
|
|
228
|
+
);
|
|
146
229
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
} else if (typeof shortcutConfig === "object") {
|
|
151
|
-
shortcut = { ...shortcut, handler: shortcutConfig.handler };
|
|
152
|
-
}
|
|
230
|
+
if (usingInput) {
|
|
231
|
+
return ((activeElement.value as any)?.name as string) || true;
|
|
232
|
+
}
|
|
153
233
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
234
|
+
return false;
|
|
235
|
+
});
|
|
158
236
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
shortcut.condition = logicAnd(
|
|
169
|
-
...conditions,
|
|
170
|
-
...((shortcutConfig as ShortcutConfig).whenever || [])
|
|
171
|
-
);
|
|
237
|
+
// Map config to full detailed shortcuts
|
|
238
|
+
const shortcuts = computed<Shortcut[]>(() => {
|
|
239
|
+
return Object.entries(toValue(config))
|
|
240
|
+
.map(([key, shortcutConfig]) => {
|
|
241
|
+
if (!shortcutConfig) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
172
244
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
.filter(Boolean) as Shortcut[];
|
|
245
|
+
// Parse key and modifiers
|
|
246
|
+
let shortcut: Partial<Shortcut>;
|
|
176
247
|
|
|
177
|
-
|
|
178
|
-
|
|
248
|
+
if (
|
|
249
|
+
key.includes("-") &&
|
|
250
|
+
key !== "-" &&
|
|
251
|
+
!key.includes("_") &&
|
|
252
|
+
!key.match(chainedShortcutRegex)?.length
|
|
253
|
+
) {
|
|
254
|
+
console.trace(\`[Shortcut] Invalid key: "\${key}"\`);
|
|
255
|
+
}
|
|
179
256
|
|
|
180
|
-
|
|
257
|
+
if (key.includes("_") && key !== "_" && !key.match(combinedShortcutRegex)?.length) {
|
|
258
|
+
console.trace(\`[Shortcut] Invalid key: "\${key}"\`);
|
|
259
|
+
}
|
|
181
260
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
261
|
+
const chained = key.includes("-") && key !== "-" && !key.includes("_");
|
|
262
|
+
if (chained) {
|
|
263
|
+
shortcut = {
|
|
264
|
+
key: key.toLowerCase(),
|
|
265
|
+
metaKey: false,
|
|
266
|
+
ctrlKey: false,
|
|
267
|
+
shiftKey: false,
|
|
268
|
+
altKey: false,
|
|
269
|
+
};
|
|
270
|
+
} else {
|
|
271
|
+
const keySplit = key
|
|
272
|
+
.toLowerCase()
|
|
273
|
+
.split("_")
|
|
274
|
+
.map((k) => k);
|
|
275
|
+
shortcut = {
|
|
276
|
+
key: keySplit
|
|
277
|
+
.filter((k) => !["meta", "command", "ctrl", "shift", "alt", "option"].includes(k))
|
|
278
|
+
.join("_"),
|
|
279
|
+
metaKey: keySplit.includes("meta") || keySplit.includes("command"),
|
|
280
|
+
ctrlKey: keySplit.includes("ctrl"),
|
|
281
|
+
shiftKey: keySplit.includes("shift"),
|
|
282
|
+
altKey: keySplit.includes("alt") || keySplit.includes("option"),
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
shortcut.chained = chained;
|
|
190
286
|
|
|
191
|
-
|
|
287
|
+
// Convert Meta to Ctrl for non-MacOS
|
|
288
|
+
if (!macOS.value && shortcut.metaKey && !shortcut.ctrlKey) {
|
|
289
|
+
shortcut.metaKey = false;
|
|
290
|
+
shortcut.ctrlKey = true;
|
|
291
|
+
}
|
|
192
292
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
);
|
|
293
|
+
// Retrieve handler function
|
|
294
|
+
if (typeof shortcutConfig === "function") {
|
|
295
|
+
shortcut.handler = shortcutConfig;
|
|
296
|
+
} else if (typeof shortcutConfig === "object") {
|
|
297
|
+
shortcut = { ...shortcut, handler: shortcutConfig.handler };
|
|
298
|
+
}
|
|
200
299
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
300
|
+
if (!shortcut.handler) {
|
|
301
|
+
console.trace("[Shortcut] Invalid value");
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
204
304
|
|
|
205
|
-
|
|
206
|
-
|
|
305
|
+
let enabled = true;
|
|
306
|
+
if (!(shortcutConfig as ShortcutConfig).usingInput) {
|
|
307
|
+
enabled = !usingInput.value;
|
|
308
|
+
} else if (typeof (shortcutConfig as ShortcutConfig).usingInput === "string") {
|
|
309
|
+
enabled = usingInput.value === (shortcutConfig as ShortcutConfig).usingInput;
|
|
310
|
+
}
|
|
311
|
+
shortcut.enabled = enabled;
|
|
207
312
|
|
|
208
|
-
|
|
209
|
-
|
|
313
|
+
return shortcut;
|
|
314
|
+
})
|
|
315
|
+
.filter(Boolean) as Shortcut[];
|
|
210
316
|
});
|
|
211
317
|
|
|
212
|
-
return
|
|
213
|
-
|
|
214
|
-
metaSymbol,
|
|
215
|
-
activeElement,
|
|
216
|
-
usingInput,
|
|
217
|
-
};
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
export const useShortcuts = createSharedComposable(_useShortcuts);
|
|
318
|
+
return useEventListener("keydown", onKeyDown);
|
|
319
|
+
}
|
|
221
320
|
|
|
222
321
|
`;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper function used to get auto complete suggestions for Tailwind CSS classes.
|
|
3
|
+
*/
|
|
4
|
+
export const TW_HELPER = `/**
|
|
5
|
+
* Utility function to return Tailwind CSS classes.
|
|
6
|
+
*/
|
|
7
|
+
export const tw = <T extends TemplateStringsArray | string>(tailwindClasses: T) => tailwindClasses;
|
|
8
|
+
`;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VS Code extensions recommendations for Tailwind CSS development.
|
|
3
|
+
*/
|
|
4
|
+
export const VS_CODE_RECOMMENDATIONS = {
|
|
5
|
+
recommendations: [
|
|
6
|
+
"vue.volar",
|
|
7
|
+
"bradlc.vscode-tailwindcss",
|
|
8
|
+
"esbenp.prettier-vscode",
|
|
9
|
+
"antfu.iconify",
|
|
10
|
+
"formulahendry.auto-close-tag",
|
|
11
|
+
"formulahendry.auto-rename-tag",
|
|
12
|
+
],
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* VS Code settings for Tailwind CSS development.
|
|
17
|
+
*/
|
|
18
|
+
export const VS_CODE_SETTINGS = {
|
|
19
|
+
"editor.formatOnSave": true,
|
|
20
|
+
"editor.quickSuggestions": { strings: "on" },
|
|
21
|
+
"files.associations": { "*.css": "tailwindcss" },
|
|
22
|
+
"tailwindCSS.classFunctions": ["tw", "clsx", "tw\\.[a-z-]+"],
|
|
23
|
+
"tailwindCSS.experimental.classRegex": [["([\"'`][^\"'`]*.*?[\"'`])", "[\"'`]([^\"'`]*)[\"'`]"]],
|
|
24
|
+
};
|
package/src/types.ts
CHANGED
|
@@ -1,18 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the UI Thing configuration options.
|
|
3
|
+
*/
|
|
1
4
|
export type UIConfig = {
|
|
5
|
+
/**
|
|
6
|
+
* The Nuxt version being used
|
|
7
|
+
*
|
|
8
|
+
* @default 4
|
|
9
|
+
*
|
|
10
|
+
* @deprecated This is now auto detected based on package.json.
|
|
11
|
+
*/
|
|
2
12
|
nuxtVersion?: number;
|
|
13
|
+
/**
|
|
14
|
+
* The theme to use
|
|
15
|
+
*
|
|
16
|
+
* @default "zinc"
|
|
17
|
+
*/
|
|
3
18
|
theme: string;
|
|
19
|
+
/**
|
|
20
|
+
* Path to the Tailwind CSS file
|
|
21
|
+
*/
|
|
4
22
|
tailwindCSSLocation: string;
|
|
5
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Path to the components directory
|
|
25
|
+
*/
|
|
6
26
|
componentsLocation: string;
|
|
27
|
+
/**
|
|
28
|
+
* Path to the composables directory
|
|
29
|
+
*/
|
|
7
30
|
composablesLocation: string;
|
|
31
|
+
/**
|
|
32
|
+
* Path to the plugins directory
|
|
33
|
+
*/
|
|
8
34
|
pluginsLocation?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Path to the utils directory
|
|
37
|
+
*/
|
|
9
38
|
utilsLocation: string;
|
|
39
|
+
/**
|
|
40
|
+
* Whether to overwrite existing files
|
|
41
|
+
*/
|
|
10
42
|
force: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Whether to use the default filename when adding components.
|
|
45
|
+
*
|
|
46
|
+
* @default true
|
|
47
|
+
*/
|
|
11
48
|
useDefaultFilename: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* The default package manager to use for installing dependencies.
|
|
51
|
+
*/
|
|
12
52
|
packageManager: string;
|
|
13
53
|
};
|
|
14
54
|
|
|
15
|
-
|
|
55
|
+
/**
|
|
56
|
+
* CLI options passed to the `init` command.
|
|
57
|
+
*/
|
|
58
|
+
export type InitOptions = {
|
|
59
|
+
/**
|
|
60
|
+
* Whether to overwrite existing configuration files.
|
|
61
|
+
*
|
|
62
|
+
* @default false
|
|
63
|
+
*/
|
|
64
|
+
force?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Whether to skip prompts and use default values.
|
|
67
|
+
*
|
|
68
|
+
* @default false
|
|
69
|
+
*/
|
|
70
|
+
yes?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* The Nuxt version to use.
|
|
73
|
+
*
|
|
74
|
+
* @default 4
|
|
75
|
+
*/
|
|
76
|
+
nuxtVersion?: number;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type AddCommand = {
|
|
80
|
+
/**
|
|
81
|
+
* Whether to add all components.
|
|
82
|
+
*
|
|
83
|
+
* @default false
|
|
84
|
+
*/
|
|
85
|
+
all?: boolean;
|
|
86
|
+
};
|
|
16
87
|
|
|
17
88
|
export type Component = {
|
|
18
89
|
name: string;
|
|
@@ -30,7 +101,7 @@ export type Component = {
|
|
|
30
101
|
overrides?: Record<string, any>;
|
|
31
102
|
};
|
|
32
103
|
|
|
33
|
-
|
|
104
|
+
type Composable = {
|
|
34
105
|
fileName: string;
|
|
35
106
|
dirPath: string;
|
|
36
107
|
fileContent: string;
|
|
@@ -6,21 +6,64 @@ import prompts from "prompts";
|
|
|
6
6
|
|
|
7
7
|
import { PRETTIER_CONFIG } from "../templates/prettier";
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Adds or merges a Prettier configuration into the project.
|
|
11
|
+
*
|
|
12
|
+
* - If `.prettierrc` doesn't exist, creates it with `PRETTIER_CONFIG`.
|
|
13
|
+
* - If it exists, merges keys instead of overwriting, unless user chooses overwrite.
|
|
14
|
+
*
|
|
15
|
+
* @param cwd - The working directory of the project.
|
|
16
|
+
* @param format - Whether to run `prettier --write .` after adding/merging.
|
|
17
|
+
*/
|
|
9
18
|
export const addPrettierConfig = async (cwd = process.cwd(), format: boolean = true) => {
|
|
10
19
|
const prettierLocation = join(cwd, ".prettierrc");
|
|
20
|
+
let finalConfig = PRETTIER_CONFIG;
|
|
21
|
+
|
|
11
22
|
if (fse.existsSync(prettierLocation)) {
|
|
23
|
+
// Read existing config
|
|
24
|
+
const existingRaw = await fse.readFile(prettierLocation, "utf-8");
|
|
25
|
+
let existingConfig: Record<string, any> = {};
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
existingConfig = JSON.parse(existingRaw);
|
|
29
|
+
} catch {
|
|
30
|
+
console.warn("⚠️ Existing .prettierrc is not valid JSON — will prompt for overwrite.");
|
|
31
|
+
}
|
|
32
|
+
|
|
12
33
|
const res = await prompts({
|
|
13
|
-
name: "
|
|
14
|
-
type: "
|
|
15
|
-
message: "A prettier config file already exists.
|
|
16
|
-
|
|
34
|
+
name: "merge",
|
|
35
|
+
type: "select",
|
|
36
|
+
message: "A prettier config file already exists. What would you like to do?",
|
|
37
|
+
choices: [
|
|
38
|
+
{ title: "Merge configs", value: "merge" },
|
|
39
|
+
{ title: "Overwrite with new config", value: "overwrite" },
|
|
40
|
+
{ title: "Cancel", value: "cancel" },
|
|
41
|
+
],
|
|
42
|
+
initial: 0,
|
|
17
43
|
});
|
|
18
|
-
|
|
44
|
+
|
|
45
|
+
if (res.merge === "merge") {
|
|
46
|
+
// Merge existing config with PRETTIER_CONFIG
|
|
47
|
+
finalConfig = {
|
|
48
|
+
...existingConfig,
|
|
49
|
+
...PRETTIER_CONFIG,
|
|
50
|
+
};
|
|
51
|
+
} else if (res.merge === "overwrite") {
|
|
52
|
+
finalConfig = PRETTIER_CONFIG;
|
|
53
|
+
} else {
|
|
54
|
+
return false; // Cancelled
|
|
55
|
+
}
|
|
19
56
|
}
|
|
20
|
-
|
|
57
|
+
|
|
58
|
+
// Save merged or new config
|
|
59
|
+
await fse.writeFile(prettierLocation, JSON.stringify(finalConfig, null, 2), "utf-8");
|
|
60
|
+
|
|
21
61
|
if (!format) return true;
|
|
62
|
+
|
|
63
|
+
// Format project files
|
|
22
64
|
const spinner = ora("Formatting files with prettier...").start();
|
|
23
65
|
await $`npx prettier --write .`;
|
|
24
66
|
spinner.succeed("Files formatted with prettier");
|
|
67
|
+
|
|
25
68
|
return true;
|
|
26
69
|
};
|