Compare commits

...

8 Commits

Author SHA1 Message Date
shadcn
69a88f9579 Merge branch 'main' into shadcn/code-format 2026-03-15 12:48:37 +04:00
shadcn
4e8263d7a3 ci: add code-format action 2026-03-15 12:47:01 +04:00
Frank
e000e17856 fix(registry): register next form examples (#10021) 2026-03-15 11:50:47 +04:00
shadcn
1be8f98c46 feat: add namespace validation for registries (#10033) 2026-03-15 11:07:13 +04:00
Copilot
6e476e4756 Rename @hooks registry to @shadcnhooks (#10036)
* Initial plan

* Rename @hooks registry to @shadcnhooks

Co-authored-by: shadcn <124599+shadcn@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: shadcn <124599+shadcn@users.noreply.github.com>
2026-03-15 11:06:56 +04:00
github-actions[bot]
e2d36a3a7d chore(release): version packages (#10046)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-15 10:07:48 +04:00
shadcn
a97ebe54f1 fix: bundle @antfu/ni to resolve tinyexec missing module error (#10041)
* fix: bundle @antfu/ni to resolve tinyexec missing module error

Fixes #10028.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: changeset

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 10:01:15 +04:00
Ahmed Zougari
b2cc0dfe59 fix(docs): update tanstack commands (#10045) 2026-03-15 10:00:58 +04:00
13 changed files with 257 additions and 13 deletions

125
.github/workflows/code-format.yml vendored Normal file
View File

@@ -0,0 +1,125 @@
name: Code format
on:
workflow_run:
workflows: ["Code check"]
types:
- completed
permissions:
actions: read
contents: write
pull-requests: read
jobs:
format:
if: |
github.event.workflow_run.conclusion == 'failure' &&
github.event.workflow_run.event == 'pull_request'
runs-on: ubuntu-latest
name: Run pnpm format:write
steps:
- name: Inspect failed workflow run
id: meta
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.workflow_run.pull_requests[0]
if (!pr) {
core.notice("Skipping because the failed run is not attached to a pull request.")
core.setOutput("should_run", "false")
return
}
const { data: pullRequest } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
})
const { data: jobs } = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
per_page: 100,
})
const formatJob = jobs.jobs.find((job) => job.name === "pnpm format:check")
const sameRepo =
pullRequest.head.repo.full_name === `${context.repo.owner}/${context.repo.repo}`
const shouldRun = formatJob?.conclusion === "failure" && sameRepo
if (!formatJob) {
core.notice("Skipping because the format job could not be found in the failed run.")
} else if (formatJob.conclusion !== "failure") {
core.notice(
`Skipping because the format job concluded with "${formatJob.conclusion}".`
)
}
if (!sameRepo) {
core.notice(
`Skipping PR #${pullRequest.number} because its head branch lives in ${pullRequest.head.repo.full_name}.`
)
}
core.setOutput("head_ref", pullRequest.head.ref)
core.setOutput("should_run", shouldRun ? "true" : "false")
- name: Checkout pull request branch
if: steps.meta.outputs.should_run == 'true'
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ steps.meta.outputs.head_ref }}
- name: Install Node.js
if: steps.meta.outputs.should_run == 'true'
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install pnpm
if: steps.meta.outputs.should_run == 'true'
uses: pnpm/action-setup@v4
with:
version: 9.0.6
run_install: false
- name: Get pnpm store directory
if: steps.meta.outputs.should_run == 'true'
id: pnpm-cache
run: |
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- name: Setup pnpm cache
if: steps.meta.outputs.should_run == 'true'
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
if: steps.meta.outputs.should_run == 'true'
run: pnpm install
- name: Apply formatting
if: steps.meta.outputs.should_run == 'true'
run: pnpm format:write
- name: Commit formatting changes
if: steps.meta.outputs.should_run == 'true'
run: |
if git diff --quiet; then
echo "No formatting changes to commit."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A
git commit -m "style: apply automated formatting"
git push origin HEAD:${{ steps.meta.outputs.head_ref }}

View File

@@ -16,7 +16,7 @@ jobs:
check-registry-sync:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
name: Check registry sync
name: check-registry-sync
permissions:
contents: read
pull-requests: write
@@ -66,6 +66,44 @@ jobs:
with:
node-version: 20
- name: Block reserved registry namespaces
env:
RESERVED_NAMESPACES: "@shadcn,@ui,@blocks,@components,@block,@component,@util,@utils,@registry,@lib,@hook,@hooks,@theme,@themes,@chart,@charts"
run: |
node <<'EOF'
const fs = require("node:fs")
const files = [
"apps/v4/public/r/registries.json",
"apps/v4/registry/directory.json",
]
const reservedNamespaces = new Set(
process.env.RESERVED_NAMESPACES.split(",").filter(Boolean)
)
function readNames(filePath) {
return JSON.parse(fs.readFileSync(filePath, "utf8")).map(
(entry) => entry.name
)
}
const violations = files.flatMap((filePath) => {
return readNames(filePath)
.filter((name) => reservedNamespaces.has(name))
.map((name) => `${filePath}: ${name}`)
})
if (violations.length > 0) {
console.error("Reserved registry namespaces are not allowed:")
for (const violation of violations) {
console.error(`- ${violation}`)
}
process.exit(1)
}
EOF
- uses: pnpm/action-setup@v4
name: Install pnpm
id: pnpm-install

View File

@@ -16,13 +16,13 @@ description: Install and configure shadcn/ui for TanStack Start.
Run the following command to create a new TanStack Start project with shadcn/ui:
```bash
npx shadcn@latest init -t tanstack
npx shadcn@latest init -t start
```
**For a monorepo project, use `--monorepo` flag:**
```bash
npx shadcn@latest init -t tanstack --monorepo
npx shadcn@latest init -t start --monorepo
```
### Add Components

View File

@@ -76,7 +76,7 @@
"rehype-pretty-code": "^0.14.1",
"rimraf": "^6.0.1",
"server-only": "^0.0.1",
"shadcn": "4.0.7",
"shadcn": "4.0.8",
"shiki": "^1.10.1",
"sonner": "^2.0.0",
"swr": "^2.3.6",

View File

@@ -41,7 +41,7 @@
"@gaia": "https://ui.heygaia.io/r/{name}.json",
"@glass-ui": "https://glass-ui.crenspire.com/r/{name}.json",
"@heseui": "https://www.heseui.com/r/{name}.json",
"@hooks": "https://shadcn-hooks.com/r/{name}.json",
"@shadcnhooks": "https://shadcn-hooks.com/r/{name}.json",
"@intentui": "https://intentui.com/r/{name}",
"@kibo-ui": "https://www.kibo-ui.com/r/{name}.json",
"@kanpeki": "https://kanpeki.vercel.app/r/{name}.json",

View File

@@ -252,7 +252,7 @@
"description": "Ready-to-use foundation components/blocks built on top of shadcn/ui."
},
{
"name": "@hooks",
"name": "@shadcnhooks",
"homepage": "https://shadcn-hooks.com",
"url": "https://shadcn-hooks.com/r/{name}.json",
"description": "A comprehensive React Hooks Collection built with Shadcn."

View File

@@ -4888,6 +4888,44 @@ export const Index: Record<string, Record<string, any>> = {
categories: undefined,
meta: undefined,
},
"form-next-demo": {
name: "form-next-demo",
title: "undefined",
description: "",
type: "registry:example",
registryDependencies: ["field","input","textarea","button","card","spinner"],
files: [{
path: "registry/new-york-v4/examples/form-next-demo.tsx",
type: "registry:example",
target: ""
}],
component: React.lazy(async () => {
const mod = await import("@/registry/new-york-v4/examples/form-next-demo.tsx")
const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name
return { default: mod.default || mod[exportName] }
}),
categories: undefined,
meta: undefined,
},
"form-next-complex": {
name: "form-next-complex",
title: "undefined",
description: "",
type: "registry:example",
registryDependencies: ["field","input","textarea","button","card","spinner","checkbox","dialog","radio-group","select","switch"],
files: [{
path: "registry/new-york-v4/examples/form-next-complex.tsx",
type: "registry:example",
target: ""
}],
component: React.lazy(async () => {
const mod = await import("@/registry/new-york-v4/examples/form-next-complex.tsx")
const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name
return { default: mod.default || mod[exportName] }
}),
categories: undefined,
meta: undefined,
},
"form-rhf-demo": {
name: "form-rhf-demo",
title: "undefined",

File diff suppressed because one or more lines are too long

View File

@@ -950,6 +950,40 @@ export const examples: Registry["items"] = [
},
],
},
{
name: "form-next-demo",
type: "registry:example",
registryDependencies: ["field", "input", "textarea", "button", "card", "spinner"],
files: [
{
path: "examples/form-next-demo.tsx",
type: "registry:example",
},
],
},
{
name: "form-next-complex",
type: "registry:example",
registryDependencies: [
"field",
"input",
"textarea",
"button",
"card",
"spinner",
"checkbox",
"dialog",
"radio-group",
"select",
"switch",
],
files: [
{
path: "examples/form-next-complex.tsx",
type: "registry:example",
},
],
},
{
name: "form-rhf-demo",
type: "registry:example",

View File

@@ -1,5 +1,11 @@
# @shadcn/ui
## 4.0.8
### Patch Changes
- [#10041](https://github.com/shadcn-ui/ui/pull/10041) [`a97ebe54f1824032d8ad00d1d0c079e3dc6f52d7`](https://github.com/shadcn-ui/ui/commit/a97ebe54f1824032d8ad00d1d0c079e3dc6f52d7) Thanks [@shadcn](https://github.com/shadcn)! - Bundle @antfu/ni and tinyexec to fix missing module error with npx
## 4.0.7
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "shadcn",
"version": "4.0.7",
"version": "4.0.8",
"description": "Add components to your apps.",
"publishConfig": {
"access": "public"
@@ -79,7 +79,6 @@
"mcp:inspect": "pnpm dlx @modelcontextprotocol/inspector node dist/index.js mcp"
},
"dependencies": {
"@antfu/ni": "^25.0.0",
"@babel/core": "^7.28.0",
"@babel/parser": "^7.28.0",
"@babel/plugin-transform-typescript": "^7.28.0",
@@ -116,6 +115,7 @@
"zod-to-json-schema": "^3.24.6"
},
"devDependencies": {
"@antfu/ni": "^25.0.0",
"@types/babel__core": "^7.20.5",
"@types/fs-extra": "^11.0.4",
"@types/prompts": "^2.4.9",

View File

@@ -19,6 +19,9 @@ export default defineConfig({
target: "esnext",
outDir: "dist",
treeshake: true,
// Bundle @antfu/ni and its dependency tinyexec to avoid
// module resolution failures with npx temporary installs.
noExternal: ["@antfu/ni", "tinyexec"],
onSuccess: async () => {
copyFileSync("src/tailwind.css", "dist/tailwind.css")
},

8
pnpm-lock.yaml generated
View File

@@ -278,7 +278,7 @@ importers:
specifier: ^0.0.1
version: 0.0.1
shadcn:
specifier: 4.0.7
specifier: 4.0.8
version: link:../../packages/shadcn
shiki:
specifier: ^1.10.1
@@ -359,9 +359,6 @@ importers:
packages/shadcn:
dependencies:
'@antfu/ni':
specifier: ^25.0.0
version: 25.0.0
'@babel/core':
specifier: ^7.28.0
version: 7.28.0
@@ -465,6 +462,9 @@ importers:
specifier: ^3.24.6
version: 3.24.6(zod@3.25.76)
devDependencies:
'@antfu/ni':
specifier: ^25.0.0
version: 25.0.0
'@types/babel__core':
specifier: ^7.20.5
version: 7.20.5