ui-thing 0.1.28 → 0.1.29
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 +38 -0
- package/dist/index.js +217 -122
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/commands/add.ts +6 -11
- package/src/commands/init.ts +6 -2
- package/src/commands/prettier.ts +2 -6
- package/src/commands/shortcuts.ts +2 -6
- package/src/comps.ts +4 -4
- package/src/index.ts +2 -1
- package/src/templates/css.ts +5 -7
- package/src/templates/shortcuts.ts +11 -6
- package/src/templates/tailwind.ts +31 -1
- package/src/types.ts +2 -1
- package/src/utils/addPrettierConfig.ts +4 -2
- package/src/utils/addShortcutFiles.ts +9 -3
- package/src/utils/compareUIConfig.ts +1 -0
- package/src/utils/config.ts +21 -3
- package/src/utils/constants.ts +14 -1
- package/src/utils/uiConfigPrompt.ts +32 -13
- package/tests/utils/compareUIConfig.test.ts +1 -0
- package/tsconfig.json +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ui-thing",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
4
4
|
"description": "CLI used to add Nuxt 3 components to a project",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"c12": "^2.0.1",
|
|
45
45
|
"commander": "^12.1.0",
|
|
46
46
|
"defu": "^6.1.4",
|
|
47
|
-
"execa": "^9.
|
|
47
|
+
"execa": "^9.5.1",
|
|
48
48
|
"figlet": "^1.8.0",
|
|
49
49
|
"fs-extra": "^11.2.0",
|
|
50
50
|
"kleur": "^4.1.5",
|
|
@@ -58,14 +58,14 @@
|
|
|
58
58
|
"@ianvs/prettier-plugin-sort-imports": "^4.3.1",
|
|
59
59
|
"@types/figlet": "^1.7.0",
|
|
60
60
|
"@types/fs-extra": "^11.0.4",
|
|
61
|
-
"@types/lodash": "^4.17.
|
|
62
|
-
"@types/node": "^22.
|
|
61
|
+
"@types/lodash": "^4.17.13",
|
|
62
|
+
"@types/node": "^22.8.6",
|
|
63
63
|
"@types/prompts": "^2.4.9",
|
|
64
|
-
"@vitest/coverage-v8": "^2.1.
|
|
64
|
+
"@vitest/coverage-v8": "^2.1.4",
|
|
65
65
|
"magicast": "^0.3.5",
|
|
66
|
-
"tsup": "^8.3.
|
|
66
|
+
"tsup": "^8.3.5",
|
|
67
67
|
"typescript": "^5.6.3",
|
|
68
|
-
"vitest": "^2.1.
|
|
68
|
+
"vitest": "^2.1.4"
|
|
69
69
|
},
|
|
70
70
|
"publishConfig": {
|
|
71
71
|
"access": "public"
|
package/src/commands/add.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { readFileSync } from "fs";
|
|
2
1
|
import path from "node:path";
|
|
3
2
|
import { Command } from "commander";
|
|
4
3
|
import { consola } from "consola";
|
|
5
|
-
import { defu } from "defu";
|
|
6
4
|
import kleur from "kleur";
|
|
7
5
|
import _ from "lodash";
|
|
8
6
|
import prompts from "prompts";
|
|
@@ -144,11 +142,8 @@ export const add = new Command()
|
|
|
144
142
|
(i: any) => i.from === "vue-sonner" && i.name === "toast"
|
|
145
143
|
);
|
|
146
144
|
if (!sonnerExists) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
name: "toast",
|
|
150
|
-
as: "useSonner",
|
|
151
|
-
});
|
|
145
|
+
// prettier-ignore
|
|
146
|
+
cfg.defaultExport.imports.imports.push({ from: "vue-sonner", name: "toast", as: "useSonner" });
|
|
152
147
|
}
|
|
153
148
|
const transpileExists = cfg.defaultExport.build.transpile.find((i: any) => "vue-sonner");
|
|
154
149
|
if (!transpileExists) {
|
|
@@ -162,21 +157,21 @@ export const add = new Command()
|
|
|
162
157
|
cfg.defaultExport.app.head.script ||= [];
|
|
163
158
|
const scriptOneExists = cfg.defaultExport.app.head.script.find(
|
|
164
159
|
(i: any) =>
|
|
165
|
-
i.src === "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.
|
|
160
|
+
i.src === "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.12/pdfmake.min.js"
|
|
166
161
|
);
|
|
167
162
|
if (!scriptOneExists) {
|
|
168
163
|
cfg.defaultExport.app.head.script.push({
|
|
169
|
-
src: "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.
|
|
164
|
+
src: "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.12/pdfmake.min.js",
|
|
170
165
|
defer: true,
|
|
171
166
|
});
|
|
172
167
|
}
|
|
173
168
|
const scriptTwoExists = cfg.defaultExport.app.head.script.find(
|
|
174
169
|
(i: any) =>
|
|
175
|
-
i.src === "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.
|
|
170
|
+
i.src === "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.12/vfs_fonts.min.js"
|
|
176
171
|
);
|
|
177
172
|
if (!scriptTwoExists) {
|
|
178
173
|
cfg.defaultExport.app.head.script.push({
|
|
179
|
-
src: "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.
|
|
174
|
+
src: "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.12/vfs_fonts.min.js",
|
|
180
175
|
defer: true,
|
|
181
176
|
});
|
|
182
177
|
}
|
package/src/commands/init.ts
CHANGED
|
@@ -16,10 +16,11 @@ export const init = new Command()
|
|
|
16
16
|
.command("init")
|
|
17
17
|
.name("init")
|
|
18
18
|
.description(
|
|
19
|
-
"Initialize UI Thing in your
|
|
19
|
+
"Initialize UI Thing in your Nuxt project. This will: 1. Create a tailwind.config.js file 2. Update your nuxt.config.ts file 3. Add the necessary dependencies 4. Create a ui-thing.config.ts file with the default configuration"
|
|
20
20
|
)
|
|
21
21
|
.option("-f --force", "Overwrite config file if it exists.", false)
|
|
22
22
|
.option("-y --yes", "Skip prompts and use default values.", false)
|
|
23
|
+
.option("-n --nuxtVersion <number>", "Specify the Nuxt version you are using.", "3")
|
|
23
24
|
.action(async (options: InitOptions) => {
|
|
24
25
|
// Get nuxt config
|
|
25
26
|
const cfg = await getNuxtConfig();
|
|
@@ -37,7 +38,10 @@ export const init = new Command()
|
|
|
37
38
|
// Add init modules ot nuxt cinfig
|
|
38
39
|
addModuleToConfig(cfg.nuxtConfig, INIT_MODULES);
|
|
39
40
|
// Configure modules in nuxt config
|
|
40
|
-
cfg.defaultExport.tailwindcss = defu(cfg.defaultExport.tailwindcss, {
|
|
41
|
+
cfg.defaultExport.tailwindcss = defu(cfg.defaultExport.tailwindcss, {
|
|
42
|
+
exposeConfig: true,
|
|
43
|
+
editorSupport: true,
|
|
44
|
+
});
|
|
41
45
|
cfg.defaultExport.colorMode = defu(cfg.defaultExport.colorMode, { classSuffix: "" });
|
|
42
46
|
cfg.defaultExport.imports ||= {};
|
|
43
47
|
cfg.defaultExport.imports.imports ||= [];
|
package/src/commands/prettier.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Command } from "commander";
|
|
|
2
2
|
import prompts from "prompts";
|
|
3
3
|
|
|
4
4
|
import { addPrettierConfig } from "../utils/addPrettierConfig";
|
|
5
|
+
import { PACKAGE_MANAGER_CHOICES } from "../utils/constants";
|
|
5
6
|
import { installPackages } from "../utils/installPackages";
|
|
6
7
|
import { printFancyBoxMessage } from "../utils/printFancyBoxMessage";
|
|
7
8
|
|
|
@@ -24,12 +25,7 @@ export const addPrettier = new Command()
|
|
|
24
25
|
name: "pkgManager",
|
|
25
26
|
type: "select",
|
|
26
27
|
message: "Which package manager are you using?",
|
|
27
|
-
choices:
|
|
28
|
-
{ title: "npm", value: "npm" },
|
|
29
|
-
{ title: "yarn", value: "yarn" },
|
|
30
|
-
{ title: "pnpm", value: "pnpm" },
|
|
31
|
-
{ title: "bun", value: "bun" },
|
|
32
|
-
],
|
|
28
|
+
choices: PACKAGE_MANAGER_CHOICES,
|
|
33
29
|
});
|
|
34
30
|
if (!pkgManager) return process.exit(0);
|
|
35
31
|
|
|
@@ -3,6 +3,7 @@ import prompts from "prompts";
|
|
|
3
3
|
|
|
4
4
|
import { addShortcutFiles } from "../utils/addShortcutFiles";
|
|
5
5
|
import { addModuleToConfig, getNuxtConfig, updateConfig } from "../utils/config";
|
|
6
|
+
import { PACKAGE_MANAGER_CHOICES } from "../utils/constants";
|
|
6
7
|
import { installPackages } from "../utils/installPackages";
|
|
7
8
|
import { printFancyBoxMessage } from "../utils/printFancyBoxMessage";
|
|
8
9
|
|
|
@@ -23,12 +24,7 @@ export const addShortcuts = new Command()
|
|
|
23
24
|
name: "pkgManager",
|
|
24
25
|
type: "select",
|
|
25
26
|
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
|
-
],
|
|
27
|
+
choices: PACKAGE_MANAGER_CHOICES,
|
|
32
28
|
});
|
|
33
29
|
if (!pkgManager) return process.exit(0);
|
|
34
30
|
|
package/src/comps.ts
CHANGED
|
@@ -76,7 +76,7 @@ export default [
|
|
|
76
76
|
fileName: "shared.styles.ts",
|
|
77
77
|
dirPath: "utils",
|
|
78
78
|
fileContent:
|
|
79
|
-
'// Add here because button styles are used in several components\nexport const buttonStyles = tv({\n base: "inline-flex items-center justify-center
|
|
79
|
+
'// Add here because button styles are used in several components\nexport const buttonStyles = tv({\n base: "group inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",\n variants: {\n variant: {\n default: "bg-primary text-primary-foreground hover:bg-primary/90",\n destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",\n outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",\n secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",\n ghost: "hover:bg-accent hover:text-accent-foreground",\n link: "text-primary underline-offset-4 hover:underline",\n expandIcon: "group relative bg-primary text-primary-foreground hover:bg-primary/90",\n ringHover:\n "bg-primary text-primary-foreground transition-all duration-300 hover:bg-primary/90 hover:ring-2 hover:ring-primary/90 hover:ring-offset-2",\n shine:\n "animate-shine bg-gradient-to-r from-primary via-primary/75 to-primary bg-[length:400%_100%] text-primary-foreground",\n gooeyRight:\n "relative z-0 overflow-hidden bg-primary from-primary-foreground/40 text-primary-foreground transition-all duration-500 before:absolute before:inset-0 before:-z-10 before:translate-x-[150%] before:translate-y-[150%] before:scale-[2.5] before:rounded-[100%] before:bg-gradient-to-r before:transition-transform before:duration-1000 hover:before:translate-x-[0%] hover:before:translate-y-[0%]",\n gooeyLeft:\n "relative z-0 overflow-hidden bg-primary from-primary-foreground/40 text-primary-foreground transition-all duration-500 after:absolute after:inset-0 after:-z-10 after:translate-x-[-150%] after:translate-y-[150%] after:scale-[2.5] after:rounded-[100%] after:bg-gradient-to-l after:transition-transform after:duration-1000 hover:after:translate-x-[0%] hover:after:translate-y-[0%]",\n linkHover1:\n "relative after:absolute after:bottom-2 after:h-[1px] after:w-2/3 after:origin-bottom-left after:scale-x-100 after:bg-primary after:transition-transform after:duration-300 after:ease-in-out hover:after:origin-bottom-right hover:after:scale-x-0",\n linkHover2:\n "relative after:absolute after:bottom-2 after:h-[1px] after:w-2/3 after:origin-bottom-right after:scale-x-0 after:bg-primary after:transition-transform after:duration-300 after:ease-in-out hover:after:origin-bottom-left hover:after:scale-x-100",\n },\n size: {\n xs: "h-8 px-2",\n sm: "h-9 px-3",\n default: "h-10 px-4 py-2",\n lg: "h-11 px-8",\n "icon-xs": "h-8 w-8",\n "icon-sm": "h-9 w-9",\n icon: "h-10 w-10",\n },\n disabled: {\n true: "pointer-events-none opacity-50",\n },\n hasIcon: {\n false: "gap-2",\n },\n },\n defaultVariants: {\n variant: "default",\n size: "default",\n },\n});\n',
|
|
80
80
|
},
|
|
81
81
|
],
|
|
82
82
|
files: [
|
|
@@ -330,7 +330,7 @@ export default [
|
|
|
330
330
|
fileName: "shared.styles.ts",
|
|
331
331
|
dirPath: "utils",
|
|
332
332
|
fileContent:
|
|
333
|
-
'// Add here because button styles are used in several components\nexport const buttonStyles = tv({\n base: "inline-flex items-center justify-center
|
|
333
|
+
'// Add here because button styles are used in several components\nexport const buttonStyles = tv({\n base: "group inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",\n variants: {\n variant: {\n default: "bg-primary text-primary-foreground hover:bg-primary/90",\n destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",\n outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",\n secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",\n ghost: "hover:bg-accent hover:text-accent-foreground",\n link: "text-primary underline-offset-4 hover:underline",\n expandIcon: "group relative bg-primary text-primary-foreground hover:bg-primary/90",\n ringHover:\n "bg-primary text-primary-foreground transition-all duration-300 hover:bg-primary/90 hover:ring-2 hover:ring-primary/90 hover:ring-offset-2",\n shine:\n "animate-shine bg-gradient-to-r from-primary via-primary/75 to-primary bg-[length:400%_100%] text-primary-foreground",\n gooeyRight:\n "relative z-0 overflow-hidden bg-primary from-primary-foreground/40 text-primary-foreground transition-all duration-500 before:absolute before:inset-0 before:-z-10 before:translate-x-[150%] before:translate-y-[150%] before:scale-[2.5] before:rounded-[100%] before:bg-gradient-to-r before:transition-transform before:duration-1000 hover:before:translate-x-[0%] hover:before:translate-y-[0%]",\n gooeyLeft:\n "relative z-0 overflow-hidden bg-primary from-primary-foreground/40 text-primary-foreground transition-all duration-500 after:absolute after:inset-0 after:-z-10 after:translate-x-[-150%] after:translate-y-[150%] after:scale-[2.5] after:rounded-[100%] after:bg-gradient-to-l after:transition-transform after:duration-1000 hover:after:translate-x-[0%] hover:after:translate-y-[0%]",\n linkHover1:\n "relative after:absolute after:bottom-2 after:h-[1px] after:w-2/3 after:origin-bottom-left after:scale-x-100 after:bg-primary after:transition-transform after:duration-300 after:ease-in-out hover:after:origin-bottom-right hover:after:scale-x-0",\n linkHover2:\n "relative after:absolute after:bottom-2 after:h-[1px] after:w-2/3 after:origin-bottom-right after:scale-x-0 after:bg-primary after:transition-transform after:duration-300 after:ease-in-out hover:after:origin-bottom-left hover:after:scale-x-100",\n },\n size: {\n xs: "h-8 px-2",\n sm: "h-9 px-3",\n default: "h-10 px-4 py-2",\n lg: "h-11 px-8",\n "icon-xs": "h-8 w-8",\n "icon-sm": "h-9 w-9",\n icon: "h-10 w-10",\n },\n disabled: {\n true: "pointer-events-none opacity-50",\n },\n hasIcon: {\n false: "gap-2",\n },\n },\n defaultVariants: {\n variant: "default",\n size: "default",\n },\n});\n',
|
|
334
334
|
},
|
|
335
335
|
],
|
|
336
336
|
files: [
|
|
@@ -338,7 +338,7 @@ export default [
|
|
|
338
338
|
fileName: "Button.vue",
|
|
339
339
|
dirPath: "components/UI",
|
|
340
340
|
fileContent:
|
|
341
|
-
'<template>\n <component\n :is="elementType"\n :class="\n buttonStyles({\n disabled: disabled || loading,\n variant: variant,\n size: size,\n class: props.class,\n })\n "\n :disabled="disabled || loading"\n
|
|
341
|
+
'<template>\n <component\n :is="elementType"\n :class="\n buttonStyles({\n hasIcon: !!icon,\n disabled: disabled || loading,\n variant: variant,\n size: size,\n class: props.class,\n })\n "\n :disabled="disabled || loading"\n v-bind="forwarded"\n >\n <slot name="iconLeft">\n <div\n v-if="icon && iconPlacement == \'left\'"\n className="w-0 flex items-center shrink-0 justify-center translate-x-[0%] pr-0 opacity-0 transition-all duration-200 group-hover:w-6 group-hover:translate-x-100 group-hover:pr-2 group-hover:opacity-100"\n >\n <Icon :name="icon" class="size-5" />\n </div>\n </slot>\n <slot>\n <span v-if="text">{{ text }}</span>\n </slot>\n <slot name="iconRight">\n <div\n v-if="icon && iconPlacement == \'right\'"\n className="w-0 flex items-center justify-center shrink-0 translate-x-[100%] pl-0 opacity-0 transition-all duration-200 group-hover:w-6 group-hover:translate-x-0 group-hover:pl-2 group-hover:opacity-100"\n >\n <Icon :name="icon" class="size-5" />\n </div>\n </slot>\n </component>\n</template>\n\n<script setup lang="ts">\n import { reactiveOmit } from "@vueuse/core";\n import { useForwardProps } from "radix-vue";\n import type { NuxtLinkProps } from "#app/components";\n\n type ButtonProps = VariantProps<typeof buttonStyles>;\n const props = withDefaults(\n defineProps<\n NuxtLinkProps & {\n /** The type fro the button */\n type?: "button" | "submit" | "reset";\n /** Whether the button is disabled */\n disabled?: boolean;\n /** Whether the button is loading */\n loading?: boolean;\n /** The action to perform when the button is clicked */\n onClick?: any;\n /** The element to render the button as */\n as?: string;\n /** Custom class(es) to add to parent element */\n class?: any;\n /** The variant of the button */\n variant?: ButtonProps["variant"];\n /** The size of the button */\n size?: ButtonProps["size"];\n /** The text to display in the button */\n text?: string;\n /** Should the icon be displayed on the `left` or the `right`? */\n iconPlacement?: "left" | "right";\n /** The icon to display in the button */\n icon?: string;\n }\n >(),\n {\n type: "button",\n }\n );\n\n const elementType = computed(() => {\n if (props.as) return props.as;\n if (props.href || props.to || props.target) return resolveComponent("NuxtLink");\n return "button";\n });\n\n const forwarded = useForwardProps(\n reactiveOmit(\n props,\n "class",\n "text",\n "icon",\n "iconPlacement",\n "size",\n "variant",\n "as",\n "loading",\n "disabled"\n )\n );\n</script>\n',
|
|
342
342
|
},
|
|
343
343
|
],
|
|
344
344
|
composables: [],
|
|
@@ -1539,7 +1539,7 @@ export default [
|
|
|
1539
1539
|
fileName: "Navbar.vue",
|
|
1540
1540
|
dirPath: "components/UI",
|
|
1541
1541
|
fileContent:
|
|
1542
|
-
'<template>\n <Primitive :class="styles({ sticky, class: props.class })" v-bind="forwarded">\n <slot />\n </Primitive>\n</template>\n\n<script lang="ts" setup>\n import { Primitive } from "radix-vue";\n import type { PrimitiveProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n PrimitiveProps & {\n /** Custom class(es) to add to the parent */\n class?: any;\n /** Whether the navbar should be sticky */\n sticky?: boolean;\n }\n >(),\n {\n as: "header",\n }\n );\n\n const forwarded = reactiveOmit(props, "class", "sticky");\n\n const styles = tv({\n base: "z-20 border-b bg-background/90 backdrop-blur",\n variants: {\n sticky: {\n true: "sticky top-0",\n },\n },\n });\n</script>\n',
|
|
1542
|
+
'<template>\n <Primitive :class="styles({ sticky, class: props.class })" v-bind="forwarded">\n <slot />\n </Primitive>\n</template>\n\n<script lang="ts" setup>\n import { reactiveOmit } from "@vueuse/core";\n import { Primitive, useForwardProps } from "radix-vue";\n import type { PrimitiveProps } from "radix-vue";\n\n const props = withDefaults(\n defineProps<\n PrimitiveProps & {\n /** Custom class(es) to add to the parent */\n class?: any;\n /** Whether the navbar should be sticky */\n sticky?: boolean;\n }\n >(),\n {\n as: "header",\n }\n );\n\n const forwarded = useForwardProps(reactiveOmit(props, "class", "sticky"));\n\n const styles = tv({\n base: "z-20 border-b bg-background/90 backdrop-blur",\n variants: {\n sticky: {\n true: "sticky top-0",\n },\n },\n });\n</script>\n',
|
|
1543
1543
|
},
|
|
1544
1544
|
],
|
|
1545
1545
|
utils: [],
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
|
|
4
|
+
import { version } from "../package.json";
|
|
4
5
|
import { add } from "./commands/add";
|
|
5
6
|
import { init } from "./commands/init";
|
|
6
7
|
import { addPrettier } from "./commands/prettier";
|
|
@@ -22,7 +23,7 @@ console.log();
|
|
|
22
23
|
program
|
|
23
24
|
.name("ui-thing")
|
|
24
25
|
.description("CLI for adding ui-thing components to your Nuxt 3 application")
|
|
25
|
-
.version(
|
|
26
|
+
.version(version)
|
|
26
27
|
.addCommand(init)
|
|
27
28
|
.addCommand(add)
|
|
28
29
|
.addCommand(theme)
|
package/src/templates/css.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
export const CSS_START = `@
|
|
2
|
-
|
|
3
|
-
@tailwind base;
|
|
1
|
+
export const CSS_START = `@tailwind base;
|
|
4
2
|
@tailwind components;
|
|
5
3
|
@tailwind utilities;
|
|
6
4
|
`;
|
|
@@ -9,14 +7,14 @@ export const CSS_END = `@layer base {
|
|
|
9
7
|
* {
|
|
10
8
|
@apply border-border;
|
|
11
9
|
}
|
|
10
|
+
html {
|
|
11
|
+
@apply antialiased;
|
|
12
|
+
}
|
|
12
13
|
body {
|
|
13
14
|
@apply bg-background text-foreground;
|
|
14
|
-
font-feature-settings:
|
|
15
|
-
"rlig" 1,
|
|
16
|
-
"calt" 1;
|
|
15
|
+
font-feature-settings: "cv02", "cv03", "cv04", "cv11";
|
|
17
16
|
}
|
|
18
17
|
}
|
|
19
|
-
|
|
20
18
|
`;
|
|
21
19
|
|
|
22
20
|
export const createCSS = (theme: keyof typeof themes) => {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export const DEFINE_SHORTCUT =
|
|
2
|
-
import {
|
|
1
|
+
export const DEFINE_SHORTCUT = `/* eslint-disable @typescript-eslint/no-unsafe-function-type */
|
|
2
|
+
import { logicAnd, logicNot } from "@vueuse/math";
|
|
3
3
|
import type { ComputedRef, WatchSource } from "vue";
|
|
4
4
|
|
|
5
5
|
export interface ShortcutConfig {
|
|
6
6
|
handler: Function;
|
|
7
7
|
usingInput?: string | boolean;
|
|
8
|
-
whenever?: WatchSource<
|
|
8
|
+
whenever?: WatchSource<boolean>[];
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export interface ShortcutsConfig {
|
|
@@ -18,7 +18,7 @@ export interface ShortcutsOptions {
|
|
|
18
18
|
|
|
19
19
|
interface Shortcut {
|
|
20
20
|
handler: Function;
|
|
21
|
-
condition: ComputedRef<
|
|
21
|
+
condition: ComputedRef<boolean>;
|
|
22
22
|
chained: boolean;
|
|
23
23
|
// KeyboardEvent attributes
|
|
24
24
|
key: string;
|
|
@@ -157,7 +157,7 @@ export const defineShortcuts = (config: ShortcutsConfig, options: ShortcutsOptio
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
// Create shortcut computed
|
|
160
|
-
const conditions: ComputedRef<
|
|
160
|
+
const conditions: ComputedRef<boolean>[] = [];
|
|
161
161
|
if (!(shortcutConfig as ShortcutConfig).usingInput) {
|
|
162
162
|
conditions.push(logicNot(usingInput));
|
|
163
163
|
} else if (typeof (shortcutConfig as ShortcutConfig).usingInput === "string") {
|
|
@@ -176,12 +176,16 @@ export const defineShortcuts = (config: ShortcutsConfig, options: ShortcutsOptio
|
|
|
176
176
|
|
|
177
177
|
useEventListener("keydown", onKeyDown);
|
|
178
178
|
};
|
|
179
|
+
|
|
179
180
|
`;
|
|
180
181
|
|
|
181
182
|
export const USE_SHORTCUTS = `export const _useShortcuts = () => {
|
|
182
183
|
const macOS = computed(
|
|
183
184
|
() =>
|
|
184
|
-
|
|
185
|
+
import.meta.client &&
|
|
186
|
+
navigator &&
|
|
187
|
+
navigator.userAgent &&
|
|
188
|
+
navigator.userAgent.match(/Macintosh;/)
|
|
185
189
|
);
|
|
186
190
|
|
|
187
191
|
const metaSymbol = ref(" ");
|
|
@@ -214,4 +218,5 @@ export const USE_SHORTCUTS = `export const _useShortcuts = () => {
|
|
|
214
218
|
};
|
|
215
219
|
|
|
216
220
|
export const useShortcuts = createSharedComposable(_useShortcuts);
|
|
221
|
+
|
|
217
222
|
`;
|
|
@@ -17,7 +17,13 @@ module.exports = {
|
|
|
17
17
|
},
|
|
18
18
|
},
|
|
19
19
|
fontFamily: {
|
|
20
|
-
sans: [
|
|
20
|
+
sans: [
|
|
21
|
+
\`Inter, \${fontFamily.sans.join(", ")}\`,
|
|
22
|
+
{
|
|
23
|
+
fontFeatureSettings: '"cv02","cv03","cv04","cv11"',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
mono: ["'Fira Code'", ...fontFamily.mono],
|
|
21
27
|
},
|
|
22
28
|
borderRadius: {
|
|
23
29
|
lg: "var(--radius)",
|
|
@@ -25,6 +31,27 @@ module.exports = {
|
|
|
25
31
|
sm: "calc(var(--radius) - 4px)",
|
|
26
32
|
},
|
|
27
33
|
keyframes: {
|
|
34
|
+
shine: {
|
|
35
|
+
from: { backgroundPosition: "200% 0" },
|
|
36
|
+
to: { backgroundPosition: "-200% 0" },
|
|
37
|
+
},
|
|
38
|
+
meteor: {
|
|
39
|
+
"0%": { transform: "rotate(215deg) translateX(0)", opacity: 1 },
|
|
40
|
+
"70%": { opacity: 1 },
|
|
41
|
+
"100%": {
|
|
42
|
+
transform: "rotate(215deg) translateX(-500px)",
|
|
43
|
+
opacity: 0,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
grid: {
|
|
47
|
+
"0%": { transform: "translateY(-50%)" },
|
|
48
|
+
"100%": { transform: "translateY(0)" },
|
|
49
|
+
},
|
|
50
|
+
"border-beam": {
|
|
51
|
+
"100%": {
|
|
52
|
+
"offset-distance": "100%",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
28
55
|
"accordion-down": {
|
|
29
56
|
from: { height: "0px" },
|
|
30
57
|
to: { height: "var(--radix-accordion-content-height)" },
|
|
@@ -51,6 +78,9 @@ module.exports = {
|
|
|
51
78
|
},
|
|
52
79
|
},
|
|
53
80
|
animation: {
|
|
81
|
+
shine: "shine 8s ease-in-out infinite",
|
|
82
|
+
meteor: "meteor 5s linear infinite",
|
|
83
|
+
grid: "grid 15s linear infinite",
|
|
54
84
|
"accordion-down": "accordion-down 0.2s ease-out",
|
|
55
85
|
"accordion-up": "accordion-up 0.2s ease-out",
|
|
56
86
|
fadeIn: "fadeIn 0.2s ease-out",
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type UIConfig = {
|
|
2
|
+
nuxtVersion?: number;
|
|
2
3
|
theme: string;
|
|
3
4
|
tailwindCSSLocation: string;
|
|
4
5
|
tailwindConfigLocation: string;
|
|
@@ -11,7 +12,7 @@ export type UIConfig = {
|
|
|
11
12
|
packageManager: string;
|
|
12
13
|
};
|
|
13
14
|
|
|
14
|
-
export type InitOptions = { force?: boolean; yes?: boolean };
|
|
15
|
+
export type InitOptions = { force?: boolean; yes?: boolean; nuxtVersion?: number };
|
|
15
16
|
|
|
16
17
|
export type Component = {
|
|
17
18
|
name: string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
1
2
|
import { $ } from "execa";
|
|
2
3
|
import fse from "fs-extra";
|
|
3
4
|
import ora from "ora";
|
|
@@ -6,7 +7,8 @@ import prompts from "prompts";
|
|
|
6
7
|
import { PRETTIER_CONFIG } from "../templates/prettier";
|
|
7
8
|
|
|
8
9
|
export const addPrettierConfig = async (cwd = process.cwd(), format: boolean = true) => {
|
|
9
|
-
|
|
10
|
+
const prettierLocation = join(cwd, ".prettierrc");
|
|
11
|
+
if (fse.existsSync(prettierLocation)) {
|
|
10
12
|
const res = await prompts({
|
|
11
13
|
name: "overwrite",
|
|
12
14
|
type: "confirm",
|
|
@@ -15,7 +17,7 @@ export const addPrettierConfig = async (cwd = process.cwd(), format: boolean = t
|
|
|
15
17
|
});
|
|
16
18
|
if (!res.overwrite) return false;
|
|
17
19
|
}
|
|
18
|
-
await fse.writeFile(
|
|
20
|
+
await fse.writeFile(prettierLocation, PRETTIER_CONFIG, "utf-8");
|
|
19
21
|
if (!format) return true;
|
|
20
22
|
const spinner = ora("Formatting files with prettier...").start();
|
|
21
23
|
await $`npx prettier --write .`;
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
1
2
|
import fse from "fs-extra";
|
|
2
3
|
|
|
3
4
|
import { DEFINE_SHORTCUT, USE_SHORTCUTS } from "../templates/shortcuts";
|
|
5
|
+
import { UIConfig } from "../types";
|
|
6
|
+
import { getUIConfig } from "./config";
|
|
4
7
|
|
|
5
8
|
export const addShortcutFiles = async (cwd = process.cwd()) => {
|
|
9
|
+
// get config
|
|
10
|
+
let userConfig: UIConfig = await getUIConfig();
|
|
11
|
+
const composablesLocation = join(cwd, userConfig.composablesLocation);
|
|
6
12
|
// ensure that the composable folder exists
|
|
7
|
-
await fse.ensureDir(
|
|
13
|
+
await fse.ensureDir(composablesLocation);
|
|
8
14
|
// write the defineShortcuts composable
|
|
9
|
-
await fse.writeFile(
|
|
15
|
+
await fse.writeFile(join(composablesLocation, "defineShortcuts.ts"), DEFINE_SHORTCUT, "utf-8");
|
|
10
16
|
// write the useShortcuts composable
|
|
11
|
-
await fse.writeFile(
|
|
17
|
+
await fse.writeFile(join(composablesLocation, "useShortcuts.ts"), USE_SHORTCUTS, "utf-8");
|
|
12
18
|
};
|
package/src/utils/config.ts
CHANGED
|
@@ -8,11 +8,12 @@ import { addNuxtModule, getDefaultExportOptions } from "magicast/helpers";
|
|
|
8
8
|
import prompts from "prompts";
|
|
9
9
|
|
|
10
10
|
import { InitOptions, UIConfig } from "../types";
|
|
11
|
-
import { initPrompts } from "./uiConfigPrompt";
|
|
11
|
+
import { initPrompts, promptForNuxtVersion } from "./uiConfigPrompt";
|
|
12
12
|
|
|
13
13
|
const currentDir = process.cwd();
|
|
14
14
|
const uiConfigFilename = "ui-thing.config.ts";
|
|
15
|
-
const defaultConfig = {
|
|
15
|
+
const defaultConfig: UIConfig = {
|
|
16
|
+
nuxtVersion: 3,
|
|
16
17
|
theme: "zinc",
|
|
17
18
|
tailwindCSSLocation: "assets/css/tailwind.css",
|
|
18
19
|
tailwindConfigLocation: "tailwind.config.js",
|
|
@@ -24,6 +25,19 @@ const defaultConfig = {
|
|
|
24
25
|
useDefaultFilename: true,
|
|
25
26
|
packageManager: "npm",
|
|
26
27
|
};
|
|
28
|
+
const defaultNuxt4Config: UIConfig = {
|
|
29
|
+
nuxtVersion: 4,
|
|
30
|
+
theme: "zinc",
|
|
31
|
+
tailwindCSSLocation: "app/assets/css/tailwind.css",
|
|
32
|
+
tailwindConfigLocation: "tailwind.config.js",
|
|
33
|
+
componentsLocation: "app/components/Ui",
|
|
34
|
+
composablesLocation: "app/composables",
|
|
35
|
+
pluginsLocation: "app/plugins",
|
|
36
|
+
utilsLocation: "app/utils",
|
|
37
|
+
force: true,
|
|
38
|
+
useDefaultFilename: true,
|
|
39
|
+
packageManager: "npm",
|
|
40
|
+
};
|
|
27
41
|
|
|
28
42
|
export const getNuxtConfig = async () => {
|
|
29
43
|
if (!fse.existsSync("nuxt.config.ts")) {
|
|
@@ -38,11 +52,15 @@ export const getNuxtConfig = async () => {
|
|
|
38
52
|
export const getUIConfig = async (options?: InitOptions) => {
|
|
39
53
|
const configFileExists = fse.existsSync(uiConfigFilename);
|
|
40
54
|
let uiConfig: UIConfig = {} as UIConfig;
|
|
55
|
+
let nuxtVersion = Number(options?.nuxtVersion);
|
|
41
56
|
|
|
42
57
|
if (!configFileExists || options?.force) {
|
|
58
|
+
if (!nuxtVersion) {
|
|
59
|
+
nuxtVersion = await promptForNuxtVersion();
|
|
60
|
+
}
|
|
43
61
|
// if option yes is passed, use default values
|
|
44
62
|
if (options?.yes) {
|
|
45
|
-
uiConfig = defaultConfig;
|
|
63
|
+
uiConfig = Number(nuxtVersion) === 4 ? defaultNuxt4Config : defaultConfig;
|
|
46
64
|
} else {
|
|
47
65
|
uiConfig = await initPrompts();
|
|
48
66
|
}
|
package/src/utils/constants.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const INIT_DEPS = ["radix-vue", "tailwind-variants"];
|
|
1
|
+
export const INIT_DEPS = ["radix-vue", "tailwind-variants", "@nuxt/fonts"];
|
|
2
2
|
export const INIT_DEV_DEPS = [
|
|
3
3
|
"typescript",
|
|
4
4
|
"tailwindcss-animate",
|
|
@@ -17,6 +17,19 @@ export const INIT_MODULES = [
|
|
|
17
17
|
"@nuxtjs/color-mode",
|
|
18
18
|
"@vueuse/nuxt",
|
|
19
19
|
"@nuxt/icon",
|
|
20
|
+
"@nuxt/fonts",
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
export const NUXT_VERSIONS = [
|
|
24
|
+
{ title: "Nuxt 3", value: 3 },
|
|
25
|
+
{ title: "Nuxt 4", value: 4 },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export const PACKAGE_MANAGER_CHOICES = [
|
|
29
|
+
{ title: "NPM", value: "npm" },
|
|
30
|
+
{ title: "YARN", value: "yarn" },
|
|
31
|
+
{ title: "PNPM", value: "pnpm" },
|
|
32
|
+
{ title: "BUN", value: "bun" },
|
|
20
33
|
];
|
|
21
34
|
|
|
22
35
|
export const CSS_THEME_OPTIONS = [
|
|
@@ -1,10 +1,32 @@
|
|
|
1
1
|
import kleur from "kleur";
|
|
2
2
|
import prompts from "prompts";
|
|
3
3
|
|
|
4
|
-
import { CSS_THEME_OPTIONS } from "./constants";
|
|
4
|
+
import { CSS_THEME_OPTIONS, NUXT_VERSIONS, PACKAGE_MANAGER_CHOICES } from "./constants";
|
|
5
|
+
|
|
6
|
+
export const promptForNuxtVersion = async () => {
|
|
7
|
+
const response = await prompts([
|
|
8
|
+
{
|
|
9
|
+
name: "nuxtVersion",
|
|
10
|
+
type: "select",
|
|
11
|
+
message: "Which Nuxt version are you using?",
|
|
12
|
+
choices: NUXT_VERSIONS,
|
|
13
|
+
},
|
|
14
|
+
]);
|
|
15
|
+
if (!response.nuxtVersion) {
|
|
16
|
+
console.log(kleur.red("No Nuxt version selected. Exiting..."));
|
|
17
|
+
return process.exit(0);
|
|
18
|
+
}
|
|
19
|
+
return response.nuxtVersion;
|
|
20
|
+
};
|
|
5
21
|
|
|
6
22
|
export const initPrompts = async () => {
|
|
7
23
|
const response = await prompts([
|
|
24
|
+
{
|
|
25
|
+
name: "nuxtVersion",
|
|
26
|
+
type: "select",
|
|
27
|
+
message: "Which Nuxt version are you using?",
|
|
28
|
+
choices: NUXT_VERSIONS,
|
|
29
|
+
},
|
|
8
30
|
{
|
|
9
31
|
name: "theme",
|
|
10
32
|
type: "autocomplete",
|
|
@@ -15,7 +37,8 @@ export const initPrompts = async () => {
|
|
|
15
37
|
name: "tailwindCSSLocation",
|
|
16
38
|
type: "text",
|
|
17
39
|
message: "Where is your tailwind.css file located?",
|
|
18
|
-
initial:
|
|
40
|
+
initial: (_, v) =>
|
|
41
|
+
v.nuxtVersion == 3 ? "assets/css/tailwind.css" : "app/assets/css/tailwind.css",
|
|
19
42
|
},
|
|
20
43
|
{
|
|
21
44
|
name: "tailwindConfigLocation",
|
|
@@ -27,25 +50,25 @@ export const initPrompts = async () => {
|
|
|
27
50
|
name: "componentsLocation",
|
|
28
51
|
type: "text",
|
|
29
52
|
message: "Where should your components be stored?",
|
|
30
|
-
initial: "components/Ui",
|
|
53
|
+
initial: (_, v) => (v.nuxtVersion == 3 ? "components/Ui" : "app/components/Ui"),
|
|
31
54
|
},
|
|
32
55
|
{
|
|
33
56
|
name: "composablesLocation",
|
|
34
57
|
type: "text",
|
|
35
58
|
message: "Where should your composables be stored?",
|
|
36
|
-
initial: "composables",
|
|
59
|
+
initial: (_, v) => (v.nuxtVersion == 3 ? "composables" : "app/composables"),
|
|
37
60
|
},
|
|
38
61
|
{
|
|
39
62
|
name: "pluginsLocation",
|
|
40
63
|
type: "text",
|
|
41
64
|
message: "Where should your plugins be stored?",
|
|
42
|
-
initial: "plugins",
|
|
65
|
+
initial: (_, v) => (v.nuxtVersion == 3 ? "plugins" : "app/plugins"),
|
|
43
66
|
},
|
|
44
67
|
{
|
|
45
68
|
name: "utilsLocation",
|
|
46
69
|
type: "text",
|
|
47
70
|
message: "Where should your utils be stored?",
|
|
48
|
-
initial: "utils",
|
|
71
|
+
initial: (_, v) => (v.nuxtVersion == 3 ? "utils" : "app/utils"),
|
|
49
72
|
},
|
|
50
73
|
{
|
|
51
74
|
name: "force",
|
|
@@ -63,15 +86,11 @@ export const initPrompts = async () => {
|
|
|
63
86
|
name: "packageManager",
|
|
64
87
|
type: "select",
|
|
65
88
|
message: "Which package manager do you use?",
|
|
66
|
-
choices:
|
|
67
|
-
{ title: "NPM", value: "npm" },
|
|
68
|
-
{ title: "Yarn", value: "yarn" },
|
|
69
|
-
{ title: "PNPM", value: "pnpm" },
|
|
70
|
-
{ title: "Bun", value: "bun" },
|
|
71
|
-
],
|
|
89
|
+
choices: PACKAGE_MANAGER_CHOICES,
|
|
72
90
|
},
|
|
73
91
|
]);
|
|
74
|
-
|
|
92
|
+
|
|
93
|
+
if (!response || Object.keys(response).length < 10) {
|
|
75
94
|
console.log(kleur.red("Incomplete configuration submitted. Exiting..."));
|
|
76
95
|
return process.exit(0);
|
|
77
96
|
}
|