mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-28 23:24:13 +00:00
fix
This commit is contained in:
@@ -9,7 +9,7 @@ import {
|
||||
resolveInitUrl,
|
||||
resolveRegistryBaseConfig,
|
||||
} from "@/src/preset/presets"
|
||||
import { getRegistryStyles } from "@/src/registry/api"
|
||||
import { getRegistryBaseColors, getRegistryStyles } from "@/src/registry/api"
|
||||
import { BUILTIN_REGISTRIES, SHADCN_URL } from "@/src/registry/constants"
|
||||
import { clearRegistryContext } from "@/src/registry/context"
|
||||
import { registryConfigSchema } from "@/src/registry/schema"
|
||||
@@ -31,7 +31,12 @@ import {
|
||||
restoreFileBackup,
|
||||
} from "@/src/utils/file-helper"
|
||||
import {
|
||||
DEFAULT_COMPONENTS,
|
||||
DEFAULT_TAILWIND_CONFIG,
|
||||
DEFAULT_TAILWIND_CSS,
|
||||
DEFAULT_UTILS,
|
||||
explorer,
|
||||
getConfig,
|
||||
getWorkspaceConfig,
|
||||
resolveConfigPaths,
|
||||
type Config,
|
||||
@@ -639,11 +644,9 @@ export async function runInit(
|
||||
}
|
||||
|
||||
// Standard init path for existing projects.
|
||||
if (!projectConfig) {
|
||||
throw new Error("Project config is required for standard init.")
|
||||
}
|
||||
|
||||
let config = await promptForMinimalConfig(projectConfig, options)
|
||||
let config = projectConfig
|
||||
? await promptForMinimalConfig(projectConfig, options)
|
||||
: await promptForConfig(await getConfig(options.cwd))
|
||||
|
||||
if (!options.yes) {
|
||||
const { proceed } = await prompts({
|
||||
@@ -778,6 +781,205 @@ export async function runInit(
|
||||
return fullConfig
|
||||
}
|
||||
|
||||
async function promptForConfig(defaultConfig: Config | null = null) {
|
||||
const [styles, baseColors] = await Promise.all([
|
||||
getRegistryStyles(),
|
||||
getRegistryBaseColors(),
|
||||
])
|
||||
|
||||
logger.info("")
|
||||
const options = await prompts([
|
||||
{
|
||||
type: "toggle",
|
||||
name: "typescript",
|
||||
message: `Would you like to use ${highlighter.info(
|
||||
"TypeScript"
|
||||
)} (recommended)?`,
|
||||
initial: defaultConfig?.tsx ?? true,
|
||||
active: "yes",
|
||||
inactive: "no",
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
name: "style",
|
||||
message: `Which ${highlighter.info("style")} would you like to use?`,
|
||||
choices: styles.map((style) => ({
|
||||
title: style.label,
|
||||
value: style.name,
|
||||
})),
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
name: "tailwindBaseColor",
|
||||
message: `Which color would you like to use as the ${highlighter.info(
|
||||
"base color"
|
||||
)}?`,
|
||||
choices: baseColors.map((color) => ({
|
||||
title: color.label,
|
||||
value: color.name,
|
||||
})),
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "tailwindCss",
|
||||
message: `Where is your ${highlighter.info("global CSS")} file?`,
|
||||
initial: defaultConfig?.tailwind.css ?? DEFAULT_TAILWIND_CSS,
|
||||
},
|
||||
{
|
||||
type: "toggle",
|
||||
name: "tailwindCssVariables",
|
||||
message: `Would you like to use ${highlighter.info(
|
||||
"CSS variables"
|
||||
)} for theming?`,
|
||||
initial: defaultConfig?.tailwind.cssVariables ?? true,
|
||||
active: "yes",
|
||||
inactive: "no",
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "tailwindPrefix",
|
||||
message: `Are you using a custom ${highlighter.info(
|
||||
"tailwind prefix eg. tw-"
|
||||
)}? (Leave blank if not)`,
|
||||
initial: "",
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "tailwindConfig",
|
||||
message: `Where is your ${highlighter.info(
|
||||
"tailwind.config.js"
|
||||
)} located?`,
|
||||
initial: defaultConfig?.tailwind.config ?? DEFAULT_TAILWIND_CONFIG,
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "components",
|
||||
message: `Configure the import alias for ${highlighter.info(
|
||||
"components"
|
||||
)}:`,
|
||||
initial: defaultConfig?.aliases["components"] ?? DEFAULT_COMPONENTS,
|
||||
},
|
||||
])
|
||||
|
||||
if (!options.style) {
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const existingAliases =
|
||||
defaultConfig && defaultConfig.aliases.components === options.components
|
||||
? defaultConfig.aliases
|
||||
: undefined
|
||||
|
||||
const aliasDefaults = getInitAliasDefaults(
|
||||
options.components,
|
||||
existingAliases
|
||||
)
|
||||
|
||||
const aliasOptions = await prompts([
|
||||
{
|
||||
type: "text",
|
||||
name: "ui",
|
||||
message: `Configure the import alias for ${highlighter.info("ui")}:`,
|
||||
initial: aliasDefaults.ui,
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "lib",
|
||||
message: `Configure the import alias for ${highlighter.info("lib")}:`,
|
||||
initial: aliasDefaults.lib,
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "hooks",
|
||||
message: `Configure the import alias for ${highlighter.info("hooks")}:`,
|
||||
initial: aliasDefaults.hooks,
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "utils",
|
||||
message: `Configure the import alias for ${highlighter.info("utils")}:`,
|
||||
initial: aliasDefaults.utils,
|
||||
},
|
||||
{
|
||||
type: "toggle",
|
||||
name: "rsc",
|
||||
message: `Are you using ${highlighter.info("React Server Components")}?`,
|
||||
initial: defaultConfig?.rsc ?? true,
|
||||
active: "yes",
|
||||
inactive: "no",
|
||||
},
|
||||
])
|
||||
|
||||
return rawConfigSchema.parse({
|
||||
$schema: "https://ui.shadcn.com/schema.json",
|
||||
style: options.style,
|
||||
tailwind: {
|
||||
config: options.tailwindConfig,
|
||||
css: options.tailwindCss,
|
||||
baseColor: options.tailwindBaseColor,
|
||||
cssVariables: options.tailwindCssVariables,
|
||||
prefix: options.tailwindPrefix,
|
||||
},
|
||||
rsc: aliasOptions.rsc,
|
||||
tsx: options.typescript,
|
||||
aliases: {
|
||||
components: options.components,
|
||||
ui: aliasOptions.ui,
|
||||
lib: aliasOptions.lib,
|
||||
hooks: aliasOptions.hooks,
|
||||
utils: aliasOptions.utils,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function getInitAliasDefaults(
|
||||
componentsAlias: string,
|
||||
existingAliases?: Config["aliases"]
|
||||
) {
|
||||
const derivedLib =
|
||||
existingAliases?.lib ?? deriveSiblingAlias(componentsAlias, "lib")
|
||||
|
||||
return {
|
||||
ui: existingAliases?.ui ?? deriveUiAlias(componentsAlias),
|
||||
lib: derivedLib,
|
||||
hooks:
|
||||
existingAliases?.hooks ?? deriveSiblingAlias(componentsAlias, "hooks"),
|
||||
utils:
|
||||
existingAliases?.utils ?? deriveUtilsAlias(componentsAlias, derivedLib),
|
||||
}
|
||||
}
|
||||
|
||||
function deriveUiAlias(componentsAlias: string) {
|
||||
return componentsAlias ? `${componentsAlias}/ui` : `${DEFAULT_COMPONENTS}/ui`
|
||||
}
|
||||
|
||||
function deriveUtilsAlias(componentsAlias: string, libAlias: string) {
|
||||
if (componentsAlias === "#components") {
|
||||
return "#utils"
|
||||
}
|
||||
|
||||
return libAlias ? `${libAlias}/utils` : DEFAULT_UTILS
|
||||
}
|
||||
|
||||
function deriveSiblingAlias(componentsAlias: string, segment: "lib" | "hooks") {
|
||||
if (componentsAlias === "components") {
|
||||
return segment
|
||||
}
|
||||
|
||||
if (componentsAlias.endsWith("/components")) {
|
||||
return `${componentsAlias.slice(0, -"/components".length)}/${segment}`
|
||||
}
|
||||
|
||||
if (
|
||||
componentsAlias.endsWith("components") &&
|
||||
!componentsAlias.includes("/")
|
||||
) {
|
||||
return `${componentsAlias.slice(0, -"components".length)}${segment}`
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
export function shouldRunTemplatePostInit(
|
||||
template:
|
||||
| { postInit?: (options: { projectPath: string }) => Promise<void> }
|
||||
|
||||
@@ -1,6 +1,55 @@
|
||||
import { describe, expect, test } from "vitest"
|
||||
|
||||
import { shouldRunTemplatePostInit } from "../../src/commands/init"
|
||||
import {
|
||||
getInitAliasDefaults,
|
||||
shouldRunTemplatePostInit,
|
||||
} from "../../src/commands/init"
|
||||
|
||||
describe("getInitAliasDefaults", () => {
|
||||
test("derives standard aliases from components", () => {
|
||||
expect(getInitAliasDefaults("@/components")).toEqual({
|
||||
ui: "@/components/ui",
|
||||
lib: "@/lib",
|
||||
hooks: "@/hooks",
|
||||
utils: "@/lib/utils",
|
||||
})
|
||||
})
|
||||
|
||||
test("derives package import aliases from #components", () => {
|
||||
expect(getInitAliasDefaults("#components")).toEqual({
|
||||
ui: "#components/ui",
|
||||
lib: "#lib",
|
||||
hooks: "#hooks",
|
||||
utils: "#utils",
|
||||
})
|
||||
})
|
||||
|
||||
test("derives sibling aliases for nested custom aliases", () => {
|
||||
expect(getInitAliasDefaults("#custom/components")).toEqual({
|
||||
ui: "#custom/components/ui",
|
||||
lib: "#custom/lib",
|
||||
hooks: "#custom/hooks",
|
||||
utils: "#custom/lib/utils",
|
||||
})
|
||||
})
|
||||
|
||||
test("preserves existing aliases when components alias is unchanged", () => {
|
||||
expect(
|
||||
getInitAliasDefaults("#components", {
|
||||
components: "#components",
|
||||
ui: "#components/ui",
|
||||
lib: "#lib",
|
||||
hooks: "#hooks",
|
||||
utils: "#utils",
|
||||
})
|
||||
).toEqual({
|
||||
ui: "#components/ui",
|
||||
lib: "#lib",
|
||||
hooks: "#hooks",
|
||||
utils: "#utils",
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("shouldRunTemplatePostInit", () => {
|
||||
test("does not run post-init for existing projects with an explicit template", () => {
|
||||
|
||||
Reference in New Issue
Block a user