mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-16 12:21:35 +00:00
Compare commits
52 Commits
shadcn@4.8
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ec117715f | ||
|
|
e583c773fe | ||
|
|
0f154171a7 | ||
|
|
9197676b3d | ||
|
|
82dce7e945 | ||
|
|
35bc9934bf | ||
|
|
1fd75c9d7e | ||
|
|
2ea31d8070 | ||
|
|
ea9d371a2d | ||
|
|
d15f17d717 | ||
|
|
46ca8c5d4b | ||
|
|
a5eb279650 | ||
|
|
1994caba0b | ||
|
|
1450bea8d6 | ||
|
|
ced2a5beb5 | ||
|
|
10f1717a3e | ||
|
|
deba036d50 | ||
|
|
5bd81beebf | ||
|
|
3f2ff18157 | ||
|
|
05eb2b968b | ||
|
|
a721cc08e5 | ||
|
|
8da4592308 | ||
|
|
f47d48f316 | ||
|
|
e6d9d6023b | ||
|
|
7dfd933102 | ||
|
|
9c6a5ee1b1 | ||
|
|
c87897b2a5 | ||
|
|
c61197f627 | ||
|
|
a1fb619cef | ||
|
|
d84c4a8ca5 | ||
|
|
cd54e0927f | ||
|
|
adac7cae1f | ||
|
|
7c63c46736 | ||
|
|
916c012132 | ||
|
|
460ad60d84 | ||
|
|
8e2d2d1439 | ||
|
|
67cef8fcb9 | ||
|
|
4ff43ba694 | ||
|
|
efdec3ca45 | ||
|
|
5c849297d0 | ||
|
|
2baa86081d | ||
|
|
980f288149 | ||
|
|
07900769d9 | ||
|
|
360e8a19c3 | ||
|
|
e2fa0101e3 | ||
|
|
55ea86f252 | ||
|
|
f584f05489 | ||
|
|
a06ba18dcc | ||
|
|
f3e16e7db7 | ||
|
|
64afddefd9 | ||
|
|
c873713992 | ||
|
|
3751fdfa4c |
5
.changeset/lazy-buttons-fetch.md
Normal file
5
.changeset/lazy-buttons-fetch.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
replace node-fetch with native fetch
|
||||
21
.github/version-script-beta.js
vendored
21
.github/version-script-beta.js
vendored
@@ -1,21 +0,0 @@
|
||||
// ORIGINALLY FROM CLOUDFLARE WRANGLER:
|
||||
// https://github.com/cloudflare/wrangler2/blob/main/.github/version-script.js
|
||||
|
||||
import { exec } from "child_process"
|
||||
import fs from "fs"
|
||||
|
||||
const pkgJsonPath = "packages/shadcn/package.json"
|
||||
try {
|
||||
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath))
|
||||
exec("git rev-parse --short HEAD", (err, stdout) => {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
process.exit(1)
|
||||
}
|
||||
pkg.version = "0.0.0-beta." + stdout.trim()
|
||||
fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, "\t") + "\n")
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
}
|
||||
37
.github/version-script-prerelease.js
vendored
Normal file
37
.github/version-script-prerelease.js
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import fs from "fs"
|
||||
|
||||
const pkgJsonPath = "packages/shadcn/package.json"
|
||||
const channel = process.argv[2]
|
||||
const headSha = process.argv[3]
|
||||
|
||||
if (!["beta", "rc"].includes(channel)) {
|
||||
console.error(
|
||||
`Expected prerelease channel to be "beta" or "rc", got "${channel}".`
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!headSha) {
|
||||
console.error("Expected pull request head SHA.")
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
try {
|
||||
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"))
|
||||
const shortSha = headSha.trim().slice(0, 7)
|
||||
const baseVersion = channel === "beta" ? "0.0.0" : pkg.version
|
||||
|
||||
if (channel === "rc" && baseVersion.includes("-")) {
|
||||
console.error(
|
||||
`Expected a stable planned version for rc, got "${baseVersion}".`
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
pkg.version = `${baseVersion}-${channel}.${shortSha}`
|
||||
fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, "\t") + "\n")
|
||||
console.log(`Prepared shadcn@${pkg.version}`)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
}
|
||||
36
.github/workflows/prerelease-comment.yml
vendored
36
.github/workflows/prerelease-comment.yml
vendored
@@ -1,5 +1,5 @@
|
||||
# Adapted from create-t3-app.
|
||||
name: Write Beta Release comment
|
||||
name: Write Prerelease comment
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
@@ -32,9 +32,13 @@ jobs:
|
||||
const match = /^npm-package-shadcn@(.*?)-pr-(\d+)/.exec(artifact.name);
|
||||
|
||||
if (match) {
|
||||
const version = match[1];
|
||||
const channel = version.includes("-rc.") ? "rc" : "beta";
|
||||
require("fs").appendFileSync(
|
||||
process.env.GITHUB_ENV,
|
||||
`\nBETA_PACKAGE_VERSION=${match[1]}` +
|
||||
`\nPRERELEASE_PACKAGE_VERSION=${version}` +
|
||||
`\nPRERELEASE_CHANNEL=${channel}` +
|
||||
`\nPRERELEASE_LABEL=release: ${channel}` +
|
||||
`\nWORKFLOW_RUN_PR=${match[2]}` +
|
||||
`\nWORKFLOW_RUN_ID=${context.payload.workflow_run.id}`
|
||||
);
|
||||
@@ -47,20 +51,30 @@ jobs:
|
||||
with:
|
||||
number: ${{ env.WORKFLOW_RUN_PR }}
|
||||
message: |
|
||||
A new prerelease is available for testing:
|
||||
A new ${{ env.PRERELEASE_CHANNEL }} prerelease is available for testing:
|
||||
|
||||
```sh
|
||||
pnpm dlx shadcn@${{ env.BETA_PACKAGE_VERSION }}
|
||||
pnpm dlx shadcn@${{ env.PRERELEASE_PACKAGE_VERSION }}
|
||||
```
|
||||
|
||||
- name: "Remove the autorelease label once published"
|
||||
View on npm: https://www.npmjs.com/package/shadcn/v/${{ env.PRERELEASE_PACKAGE_VERSION }}
|
||||
|
||||
- name: "Remove the prerelease label once published"
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: '${{ env.WORKFLOW_RUN_PR }}',
|
||||
name: '🚀 autorelease',
|
||||
});
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: '${{ env.WORKFLOW_RUN_PR }}',
|
||||
name: '${{ env.PRERELEASE_LABEL }}',
|
||||
});
|
||||
} catch (error) {
|
||||
if (error.status !== 404) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
core.info("The prerelease label was already removed.");
|
||||
}
|
||||
|
||||
67
.github/workflows/release.yml
vendored
67
.github/workflows/release.yml
vendored
@@ -2,7 +2,7 @@
|
||||
|
||||
name: Release
|
||||
|
||||
run-name: ${{ github.event_name == 'pull_request' && format('Release Beta - PR {0}', github.event.number) || 'Release Stable' }}
|
||||
run-name: ${{ github.event_name == 'pull_request' && format('Release Prerelease - PR {0}', github.event.number) || 'Release Stable' }}
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -15,8 +15,8 @@ on:
|
||||
|
||||
jobs:
|
||||
prerelease:
|
||||
if: ${{ github.event_name == 'pull_request' && github.repository_owner == 'shadcn-ui' && contains(github.event.pull_request.labels.*.name, '🚀 autorelease') }}
|
||||
name: Publish Beta to NPM
|
||||
if: "${{ github.event_name == 'pull_request' && github.repository_owner == 'shadcn-ui' && (contains(github.event.pull_request.labels.*.name, 'release: beta') || contains(github.event.pull_request.labels.*.name, 'release: rc')) }}"
|
||||
name: Publish Prerelease to NPM
|
||||
runs-on: ubuntu-latest
|
||||
environment: Preview
|
||||
permissions:
|
||||
@@ -24,10 +24,49 @@ jobs:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Select prerelease channel
|
||||
id: prerelease
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const prereleaseLabels = [
|
||||
{ name: "release: beta", channel: "beta" },
|
||||
{ name: "release: rc", channel: "rc" },
|
||||
];
|
||||
const labels = context.payload.pull_request.labels.map((label) => label.name);
|
||||
const selectedLabels = prereleaseLabels.filter((label) =>
|
||||
labels.includes(label.name)
|
||||
);
|
||||
|
||||
if (selectedLabels.length !== 1) {
|
||||
throw new Error(
|
||||
`Expected exactly one prerelease label, found: ${
|
||||
selectedLabels.map((label) => label.name).join(", ") || "none"
|
||||
}.`
|
||||
);
|
||||
}
|
||||
|
||||
const selected = selectedLabels[0];
|
||||
const pullRequest = context.payload.pull_request;
|
||||
|
||||
if (
|
||||
selected.channel === "rc" &&
|
||||
(pullRequest.head.ref !== "changeset-release/main" ||
|
||||
pullRequest.title !== "chore(release): version packages")
|
||||
) {
|
||||
throw new Error(
|
||||
"The release: rc label can only be used on the Changesets version PR from changeset-release/main."
|
||||
);
|
||||
}
|
||||
|
||||
core.setOutput("channel", selected.channel);
|
||||
core.setOutput("label", selected.name);
|
||||
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: Use PNPM
|
||||
uses: pnpm/action-setup@v4
|
||||
@@ -48,10 +87,7 @@ jobs:
|
||||
run: pnpm install
|
||||
|
||||
- name: Modify package.json version
|
||||
run: node .github/version-script-beta.js
|
||||
|
||||
- name: Publish Beta to NPM
|
||||
run: pnpm pub:beta
|
||||
run: node .github/version-script-prerelease.js ${{ steps.prerelease.outputs.channel }} ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: get-npm-version
|
||||
id: package-version
|
||||
@@ -59,6 +95,23 @@ jobs:
|
||||
with:
|
||||
path: packages/shadcn
|
||||
|
||||
- name: Check package version on NPM
|
||||
id: package-exists
|
||||
run: |
|
||||
if npm view "shadcn@${{ steps.package-version.outputs.current-version }}" version >/dev/null 2>&1; then
|
||||
echo "exists=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "exists=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Publish Prerelease to NPM
|
||||
if: ${{ steps.package-exists.outputs.exists == 'false' }}
|
||||
run: pnpm pub:${{ steps.prerelease.outputs.channel }}
|
||||
|
||||
- name: Build packaged artifact
|
||||
if: ${{ steps.package-exists.outputs.exists == 'true' }}
|
||||
run: pnpm shadcn:build
|
||||
|
||||
- name: Upload packaged artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
||||
314
.github/workflows/templates.yml
vendored
Normal file
314
.github/workflows/templates.yml
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
name: Templates
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: ["*"]
|
||||
paths:
|
||||
- ".github/workflows/templates.yml"
|
||||
- "apps/v4/registry/**"
|
||||
- "package.json"
|
||||
- "packages/shadcn/src/commands/add.ts"
|
||||
- "packages/shadcn/src/commands/init.ts"
|
||||
- "packages/shadcn/src/templates/**"
|
||||
- "packages/shadcn/src/utils/create-project.ts"
|
||||
- "packages/shadcn/src/utils/get-monorepo-info.ts"
|
||||
- "packages/shadcn/src/utils/get-package-manager.ts"
|
||||
- "pnpm-lock.yaml"
|
||||
- "templates/**"
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
name: ${{ matrix.package-manager == 'pnpm' && format('pnpm {0}', matrix.pnpm-version) || matrix.package-manager }} ${{ matrix.template }}
|
||||
permissions:
|
||||
contents: read
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
template: [next, vite, astro, start, react-router]
|
||||
package-manager: [pnpm, bun, npm, yarn]
|
||||
pnpm-version: [10.33.4, 11]
|
||||
exclude:
|
||||
- package-manager: bun
|
||||
pnpm-version: 11
|
||||
- package-manager: npm
|
||||
pnpm-version: 11
|
||||
- package-manager: yarn
|
||||
pnpm-version: 11
|
||||
env:
|
||||
NEXT_PUBLIC_APP_URL: http://localhost:4000
|
||||
NEXT_PUBLIC_V0_URL: https://v0.dev
|
||||
REGISTRY_URL: http://localhost:4000/r
|
||||
ROOT_PNPM_VERSION: 10.33.4
|
||||
TEMPLATE_PNPM_VERSION: ${{ matrix.pnpm-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
version: ${{ env.ROOT_PNPM_VERSION }}
|
||||
run_install: false
|
||||
|
||||
- name: Install Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: Install Yarn
|
||||
if: matrix.package-manager == 'yarn'
|
||||
run: |
|
||||
corepack enable
|
||||
COREPACK_ENABLE_PROJECT_SPEC=0 corepack prepare yarn@4.12.0 --activate
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
run: |
|
||||
echo "pnpm_cache_dir=$(pnpm store path)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- uses: actions/cache@v4
|
||||
name: Setup pnpm cache
|
||||
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
|
||||
run: pnpm install
|
||||
|
||||
- name: Build packages
|
||||
run: |
|
||||
pnpm --filter=shadcn build
|
||||
pnpm --filter=v4 registry:build
|
||||
|
||||
- name: Validate templates
|
||||
env:
|
||||
TEMPLATE: ${{ matrix.template }}
|
||||
TEMPLATE_PACKAGE_MANAGER: ${{ matrix.package-manager }}
|
||||
SHADCN_TEMPLATE_DIR: ${{ github.workspace }}/templates
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
root_pnpm="$(command -v pnpm)"
|
||||
validation_script="$RUNNER_TEMP/validate-templates.sh"
|
||||
|
||||
cat > "$validation_script" <<'BASH'
|
||||
set -euo pipefail
|
||||
|
||||
bin_dir="$RUNNER_TEMP/template-pnpm-bin"
|
||||
mkdir -p "$bin_dir"
|
||||
|
||||
cat > "$bin_dir/pnpm" <<'PNPM'
|
||||
#!/usr/bin/env bash
|
||||
exec npx -y "pnpm@${TEMPLATE_PNPM_VERSION}" "$@"
|
||||
PNPM
|
||||
chmod +x "$bin_dir/pnpm"
|
||||
export PATH="$bin_dir:$PATH"
|
||||
|
||||
echo "Using template pnpm $(pnpm --version)"
|
||||
|
||||
cli="$GITHUB_WORKSPACE/packages/shadcn/dist/index.js"
|
||||
template_root="$RUNNER_TEMP/generated-template-${TEMPLATE_PACKAGE_MANAGER}-${TEMPLATE}"
|
||||
rm -rf "$template_root"
|
||||
mkdir -p "$template_root"
|
||||
|
||||
modes=(app monorepo)
|
||||
|
||||
has_script() {
|
||||
node -e "const pkg = require('./package.json'); process.exit(pkg.scripts && pkg.scripts[process.argv[1]] ? 0 : 1)" "$1"
|
||||
}
|
||||
|
||||
run_script_if_present() {
|
||||
local script="$1"
|
||||
if has_script "$script"; then
|
||||
pnpm run "$script"
|
||||
else
|
||||
echo "No $script script found; skipping."
|
||||
fi
|
||||
}
|
||||
|
||||
validate_non_pnpm_project() {
|
||||
local package_manager="$1"
|
||||
local project_path="$2"
|
||||
local check_workspace_protocol="$3"
|
||||
local is_monorepo="$4"
|
||||
|
||||
cd "$project_path"
|
||||
test ! -f pnpm-workspace.yaml
|
||||
test ! -f pnpm-lock.yaml
|
||||
|
||||
EXPECTED_PACKAGE_MANAGER="$package_manager" \
|
||||
CHECK_WORKSPACE_PROTOCOL="$check_workspace_protocol" \
|
||||
IS_MONOREPO="$is_monorepo" \
|
||||
node <<'NODE'
|
||||
const fs = require("node:fs")
|
||||
const path = require("node:path")
|
||||
|
||||
const expectedPackageManager = process.env.EXPECTED_PACKAGE_MANAGER
|
||||
const checkWorkspaceProtocol =
|
||||
process.env.CHECK_WORKSPACE_PROTOCOL === "true"
|
||||
const isMonorepo = process.env.IS_MONOREPO === "true"
|
||||
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"))
|
||||
|
||||
if (isMonorepo) {
|
||||
const workspaces = pkg.workspaces ?? []
|
||||
|
||||
if (!Array.isArray(workspaces)) {
|
||||
throw new Error("Expected package.json workspaces to be an array.")
|
||||
}
|
||||
|
||||
if (workspaces.length === 0) {
|
||||
throw new Error("Expected package.json workspaces to have entries.")
|
||||
}
|
||||
|
||||
for (const workspace of ["sharp", "unrs-resolver", "esbuild"]) {
|
||||
if (workspaces.includes(workspace)) {
|
||||
throw new Error(`Unexpected workspace entry: ${workspace}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (!pkg.packageManager?.startsWith(`${expectedPackageManager}@`)) {
|
||||
throw new Error(
|
||||
`Expected packageManager to use ${expectedPackageManager}, got ${pkg.packageManager}`
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (pkg.workspaces !== undefined) {
|
||||
throw new Error("Did not expect package.json workspaces for app template.")
|
||||
}
|
||||
|
||||
if (pkg.packageManager !== undefined) {
|
||||
throw new Error(
|
||||
`Did not expect packageManager for app template, got ${pkg.packageManager}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (checkWorkspaceProtocol) {
|
||||
const packageJsonFiles = []
|
||||
function collectPackageJsonFiles(dir) {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
if (entry.name === "node_modules") {
|
||||
continue
|
||||
}
|
||||
|
||||
const fullPath = path.join(dir, entry.name)
|
||||
if (entry.isDirectory()) {
|
||||
collectPackageJsonFiles(fullPath)
|
||||
} else if (entry.name === "package.json") {
|
||||
packageJsonFiles.push(fullPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectPackageJsonFiles(process.cwd())
|
||||
|
||||
for (const file of packageJsonFiles) {
|
||||
const json = fs.readFileSync(file, "utf8")
|
||||
if (json.includes("workspace:")) {
|
||||
throw new Error(`Unexpected workspace: protocol in ${file}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
NODE
|
||||
}
|
||||
|
||||
for mode in "${modes[@]}"; do
|
||||
project="test-${TEMPLATE}-${mode}-${TEMPLATE_PACKAGE_MANAGER}"
|
||||
project_path="$template_root/$project"
|
||||
|
||||
echo "::group::${TEMPLATE} ${mode} ${TEMPLATE_PACKAGE_MANAGER}"
|
||||
args=(
|
||||
init
|
||||
--defaults
|
||||
--name "$project"
|
||||
--template "$TEMPLATE"
|
||||
--cwd "$template_root"
|
||||
--silent
|
||||
)
|
||||
|
||||
if [ "$mode" = "monorepo" ]; then
|
||||
args+=(--monorepo)
|
||||
is_monorepo="true"
|
||||
else
|
||||
args+=(--no-monorepo)
|
||||
is_monorepo="false"
|
||||
fi
|
||||
|
||||
case "$TEMPLATE_PACKAGE_MANAGER" in
|
||||
pnpm)
|
||||
SHADCN_TEMPLATE_DIR="$SHADCN_TEMPLATE_DIR" \
|
||||
REGISTRY_URL="$REGISTRY_URL" \
|
||||
npm_config_user_agent="pnpm/${TEMPLATE_PNPM_VERSION}" \
|
||||
node "$cli" "${args[@]}"
|
||||
|
||||
cd "$project_path"
|
||||
pnpm install --frozen-lockfile
|
||||
run_script_if_present typecheck
|
||||
run_script_if_present build
|
||||
;;
|
||||
bun)
|
||||
(
|
||||
cd "$template_root"
|
||||
SHADCN_TEMPLATE_DIR="$SHADCN_TEMPLATE_DIR" \
|
||||
REGISTRY_URL="$REGISTRY_URL" \
|
||||
npm_config_user_agent="bun/$(bun --version)" \
|
||||
bunx --bun --package "$GITHUB_WORKSPACE/packages/shadcn" \
|
||||
shadcn "${args[@]}"
|
||||
)
|
||||
validate_non_pnpm_project \
|
||||
"bun" \
|
||||
"$project_path" \
|
||||
"false" \
|
||||
"$is_monorepo"
|
||||
;;
|
||||
npm)
|
||||
(
|
||||
cd "$template_root"
|
||||
SHADCN_TEMPLATE_DIR="$SHADCN_TEMPLATE_DIR" \
|
||||
REGISTRY_URL="$REGISTRY_URL" \
|
||||
npm_config_user_agent="npm/$(npm --version)" \
|
||||
npx --yes --package "$GITHUB_WORKSPACE/packages/shadcn" \
|
||||
shadcn "${args[@]}"
|
||||
)
|
||||
validate_non_pnpm_project \
|
||||
"npm" \
|
||||
"$project_path" \
|
||||
"true" \
|
||||
"$is_monorepo"
|
||||
;;
|
||||
yarn)
|
||||
(
|
||||
cd "$template_root"
|
||||
SHADCN_TEMPLATE_DIR="$SHADCN_TEMPLATE_DIR" \
|
||||
REGISTRY_URL="$REGISTRY_URL" \
|
||||
COREPACK_ENABLE_PROJECT_SPEC=0 \
|
||||
npm_config_user_agent="yarn/$(COREPACK_ENABLE_PROJECT_SPEC=0 yarn --version)" \
|
||||
yarn dlx --package "$GITHUB_WORKSPACE/packages/shadcn" \
|
||||
shadcn "${args[@]}"
|
||||
)
|
||||
validate_non_pnpm_project \
|
||||
"yarn" \
|
||||
"$project_path" \
|
||||
"false" \
|
||||
"$is_monorepo"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "::endgroup::"
|
||||
done
|
||||
BASH
|
||||
|
||||
"$root_pnpm" exec start-server-and-test \
|
||||
"$root_pnpm v4:dev" \
|
||||
http://localhost:4000 \
|
||||
"bash $validation_script"
|
||||
57
.github/workflows/validate-registries.yml
vendored
57
.github/workflows/validate-registries.yml
vendored
@@ -3,54 +3,14 @@ name: Validate Registries
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "apps/v4/public/r/registries.json"
|
||||
- "apps/v4/registry/directory.json"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "apps/v4/public/r/registries.json"
|
||||
- "apps/v4/registry/directory.json"
|
||||
|
||||
jobs:
|
||||
check-registry-sync:
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
name: check-registry-sync
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Check changed files
|
||||
id: changed
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
CHANGED_FILES=$(gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --name-only)
|
||||
|
||||
DIRECTORY_CHANGED=false
|
||||
REGISTRIES_CHANGED=false
|
||||
|
||||
if echo "$CHANGED_FILES" | grep -q "^apps/v4/registry/directory.json$"; then
|
||||
DIRECTORY_CHANGED=true
|
||||
fi
|
||||
|
||||
if echo "$CHANGED_FILES" | grep -q "^apps/v4/public/r/registries.json$"; then
|
||||
REGISTRIES_CHANGED=true
|
||||
fi
|
||||
|
||||
echo "directory_changed=$DIRECTORY_CHANGED" >> $GITHUB_OUTPUT
|
||||
echo "registries_changed=$REGISTRIES_CHANGED" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Flag missing registries.json update
|
||||
if: steps.changed.outputs.directory_changed == 'true' && steps.changed.outputs.registries_changed == 'false'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh pr edit ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --add-label "registries: invalid"
|
||||
gh pr comment ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --body "can you run \`pnpm registry:build\` and commit the json files please?"
|
||||
exit 1
|
||||
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
name: pnpm validate:registries
|
||||
@@ -73,25 +33,20 @@ jobs:
|
||||
node <<'EOF'
|
||||
const fs = require("node:fs")
|
||||
|
||||
const files = [
|
||||
"apps/v4/public/r/registries.json",
|
||||
"apps/v4/registry/directory.json",
|
||||
]
|
||||
const file = "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(
|
||||
function readNames() {
|
||||
return JSON.parse(fs.readFileSync(file, "utf8")).map(
|
||||
(entry) => entry.name
|
||||
)
|
||||
}
|
||||
|
||||
const violations = files.flatMap((filePath) => {
|
||||
return readNames(filePath)
|
||||
.filter((name) => reservedNamespaces.has(name))
|
||||
.map((name) => `${filePath}: ${name}`)
|
||||
})
|
||||
const violations = readNames()
|
||||
.filter((name) => reservedNamespaces.has(name))
|
||||
.map((name) => `${file}: ${name}`)
|
||||
|
||||
if (violations.length > 0) {
|
||||
console.error("Reserved registry namespaces are not allowed:")
|
||||
|
||||
@@ -141,6 +141,11 @@ When adding or modifying components, please ensure that:
|
||||
2. You update the documentation.
|
||||
3. You run `pnpm registry:build` to update the registry.
|
||||
|
||||
See [`apps/v4/registry/README.md`](apps/v4/registry/README.md) for how the
|
||||
registry pipeline is structured and for the faster targeted build modes
|
||||
(`--style`, `--registry`, `--examples`, `--indexes`) you can use while
|
||||
iterating locally. Always run the full `pnpm registry:build` before committing.
|
||||
|
||||
## Commit Convention
|
||||
|
||||
Before you create a Pull Request, please check whether your commits comply with
|
||||
|
||||
@@ -79,7 +79,7 @@ export function CardsDemo() {
|
||||
return (
|
||||
<div
|
||||
data-slot="demo"
|
||||
className="theme-neutral relative flex w-full max-w-none flex-col gap-(--gap) overflow-hidden bg-muted p-12 pb-0! [--gap:--spacing(8)] 3xl:[--gap:--spacing(8)] min-[1900px]:[--gap:--spacing(10)]! lg:p-8 lg:[--gap:--spacing(6)] xl:p-12 dark:bg-background"
|
||||
className="theme-neutral relative flex w-full max-w-none flex-col gap-(--gap) overflow-hidden bg-muted p-12 pb-0! [--gap:--spacing(8)] 3xl:[--gap:--spacing(8)] min-[1900px]:p-12 min-[1900px]:[--gap:--spacing(10)]! lg:p-6 lg:[--gap:--spacing(6)] dark:bg-background"
|
||||
>
|
||||
<CardsSkeletonRails />
|
||||
<div className="relative z-10 mx-auto grid gap-(--gap) **:data-[slot=card]:w-full min-[1400px]:grid-cols-4! min-[1900px]:grid-cols-5! md:max-w-3xl md:grid-cols-2 lg:max-w-none lg:grid-cols-3 xl:max-w-[1600px] 2xl:max-w-[1900px]">
|
||||
|
||||
@@ -144,7 +144,7 @@ export function SidebarNav() {
|
||||
|
||||
<SidebarSection
|
||||
label="Support"
|
||||
className="hidden xl:col-start-2 xl:row-start-1 xl:flex"
|
||||
className="flex xl:col-start-2 xl:row-start-1"
|
||||
>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton>
|
||||
@@ -180,7 +180,7 @@ export function SidebarNav() {
|
||||
|
||||
<SidebarSection
|
||||
label="Account"
|
||||
className="hidden xl:col-start-2 xl:row-start-2 xl:flex"
|
||||
className="flex xl:col-start-2 xl:row-start-2"
|
||||
>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton>
|
||||
|
||||
@@ -60,23 +60,23 @@ export default function IndexPage() {
|
||||
</Button>
|
||||
</PageActions>
|
||||
</PageHeader>
|
||||
<div className="container-wrapper flex-1 pb-6 md:px-0">
|
||||
<div className="container-wrapper flex-1 p-0">
|
||||
<div className="container overflow-hidden md:px-0 lg:max-w-none">
|
||||
<section className="-mx-4 w-[160vw] overflow-hidden rounded-lg border border-border/50 md:hidden md:w-[150vw]">
|
||||
<section className="-mx-4 w-[140vw] overflow-hidden md:hidden">
|
||||
<Image
|
||||
src="/r/styles/new-york-v4/dashboard-01-light.png"
|
||||
width={1400}
|
||||
height={875}
|
||||
src="/images/full-light.png"
|
||||
width={2560}
|
||||
height={2764}
|
||||
alt="Dashboard"
|
||||
className="block dark:hidden"
|
||||
className="block h-auto w-full dark:hidden"
|
||||
priority
|
||||
/>
|
||||
<Image
|
||||
src="/r/styles/new-york-v4/dashboard-01-dark.png"
|
||||
width={1400}
|
||||
height={875}
|
||||
src="/images/full-dark.png"
|
||||
width={2560}
|
||||
height={2764}
|
||||
alt="Dashboard"
|
||||
className="hidden dark:block"
|
||||
className="hidden h-auto w-full dark:block"
|
||||
priority
|
||||
/>
|
||||
</section>
|
||||
|
||||
@@ -24,15 +24,10 @@ const LocksContext = React.createContext<LocksContextValue | null>(null)
|
||||
|
||||
export function LocksProvider({ children }: { children: React.ReactNode }) {
|
||||
const [locks, setLocks] = React.useState<Set<LockableParam>>(new Set())
|
||||
const locksRef = React.useRef(locks)
|
||||
React.useEffect(() => {
|
||||
locksRef.current = locks
|
||||
}, [locks])
|
||||
|
||||
// Stable callback — reads from ref so it doesn't change on every lock toggle.
|
||||
const isLocked = React.useCallback(
|
||||
(param: LockableParam) => locksRef.current.has(param),
|
||||
[]
|
||||
(param: LockableParam) => locks.has(param),
|
||||
[locks]
|
||||
)
|
||||
|
||||
const toggleLock = React.useCallback((param: LockableParam) => {
|
||||
|
||||
@@ -42,7 +42,8 @@ export async function getBaseComponent(name: string, base: BaseName) {
|
||||
return null
|
||||
}
|
||||
|
||||
return index[name].component
|
||||
const { Components } = await import("@/registry/bases/__components__")
|
||||
return Components[base]?.[name] ?? null
|
||||
}
|
||||
|
||||
export async function getAllItems() {
|
||||
|
||||
@@ -284,6 +284,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-figure] code,
|
||||
[data-rehype-pretty-code-figure] code span {
|
||||
font-variant-ligatures: none;
|
||||
font-feature-settings:
|
||||
"liga" 0,
|
||||
"calt" 0;
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-title] {
|
||||
border-bottom: color-mix(in oklab, var(--border) 30%, transparent);
|
||||
border-bottom-width: 1px;
|
||||
|
||||
16
apps/v4/app/r/registries.json/route.ts
Normal file
16
apps/v4/app/r/registries.json/route.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { NextResponse } from "next/server"
|
||||
|
||||
import directory from "@/registry/directory.json"
|
||||
|
||||
export const dynamic = "force-static"
|
||||
|
||||
export async function GET() {
|
||||
const registries = directory.map(({ name, homepage, url, description }) => ({
|
||||
name,
|
||||
homepage,
|
||||
url,
|
||||
description,
|
||||
}))
|
||||
|
||||
return NextResponse.json(registries)
|
||||
}
|
||||
@@ -6,8 +6,8 @@ import { Badge } from "@/registry/new-york-v4/ui/badge"
|
||||
export function Announcement() {
|
||||
return (
|
||||
<Badge asChild variant="secondary" className="bg-muted">
|
||||
<Link href="/docs/changelog">
|
||||
Introducing Rhea <ArrowRightIcon />
|
||||
<Link href="/docs/registry/github">
|
||||
Introducing GitHub Registries <ArrowRightIcon />
|
||||
</Link>
|
||||
</Badge>
|
||||
)
|
||||
|
||||
@@ -3,6 +3,8 @@ title: shadcn
|
||||
description: Use the shadcn CLI to add components to your project.
|
||||
---
|
||||
|
||||
import { TriangleAlertIcon } from "lucide-react"
|
||||
|
||||
## init
|
||||
|
||||
Use the `init` command to initialize configuration and dependencies for an existing project, or create a new project with `--name`.
|
||||
@@ -503,3 +505,87 @@ npx shadcn@latest migrate radix "src/components/ui/**"
|
||||
If no path is provided, the migration will transform all files in your `ui` directory (from `components.json`).
|
||||
|
||||
Once complete, you can remove any unused `@radix-ui/react-*` packages from your `package.json`.
|
||||
|
||||
---
|
||||
|
||||
## eject
|
||||
|
||||
When you run `init`, shadcn adds `@import "shadcn/tailwind.css"` to your global CSS file. This import provides shared Tailwind v4 utilities such as custom variants (`data-open:`, `data-closed:`, etc.) and accordion animations.
|
||||
|
||||
Use the `eject` command to inline `shadcn/tailwind.css` into your global CSS file and remove the `shadcn` dependency from your project.
|
||||
|
||||
<Callout icon={<TriangleAlertIcon />}>
|
||||
**Note: This action is irreversible.** After ejecting, future shadcn CLI
|
||||
updates to `shadcn/tailwind.css` will not apply automatically.
|
||||
</Callout>
|
||||
|
||||
```bash
|
||||
npx shadcn@latest eject
|
||||
```
|
||||
|
||||
**Before**
|
||||
|
||||
```css
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
@import "shadcn/tailwind.css";
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```css
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
/* ejected from shadcn@4.8.3 */
|
||||
@theme inline {
|
||||
@keyframes accordion-down {
|
||||
from {
|
||||
height: 0;
|
||||
}
|
||||
to {
|
||||
height: var(
|
||||
--radix-accordion-content-height,
|
||||
var(--accordion-panel-height, auto)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@custom-variant data-open {
|
||||
&:where([data-state="open"]),
|
||||
&:where([data-open]:not([data-open="false"])) {
|
||||
@slot;
|
||||
}
|
||||
}
|
||||
|
||||
@utility no-scrollbar {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Monorepo**
|
||||
|
||||
In a monorepo, run the command from the workspace that contains your `components.json` and global CSS file:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest eject -c packages/ui
|
||||
```
|
||||
|
||||
**Options**
|
||||
|
||||
```bash
|
||||
Usage: shadcn eject [options]
|
||||
|
||||
inline shadcn/tailwind.css and remove the shadcn dependency
|
||||
|
||||
Options:
|
||||
-c, --cwd <cwd> the working directory. defaults to the current directory.
|
||||
-y, --yes skip confirmation prompt. (default: false)
|
||||
-s, --silent mute output. (default: false)
|
||||
-h, --help display help for command
|
||||
```
|
||||
|
||||
61
apps/v4/content/docs/changelog/2026-05-shadcn-eject.mdx
Normal file
61
apps/v4/content/docs/changelog/2026-05-shadcn-eject.mdx
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: May 2026 - shadcn eject
|
||||
description: Inline shadcn/tailwind.css and remove the shadcn dependency.
|
||||
date: 2026-05-31
|
||||
---
|
||||
|
||||
When we added support for both Radix and Base UI, we needed a place for shared Tailwind utilities that both libraries depend on, e.g. custom variants like `data-open:` and `data-closed:` and utilities like `no-scrollbar`.
|
||||
|
||||
We also ran into a few bugs while working on RTL support that were easier to fix in one shared place rather than duplicating across every component.
|
||||
|
||||
So we created `shadcn/tailwind.css`. When you run `init`, it adds `@import "shadcn/tailwind.css"` to your global CSS file. It works just like other CSS imports such as `tw-animate-css`: a small dependency that is tree-shaken in production and resolved at build time.
|
||||
|
||||
If you prefer not to depend on the `shadcn` package for that CSS, we've added the `shadcn eject` command. It inlines `shadcn/tailwind.css` into your global CSS file and removes the `shadcn` dependency from your project.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest eject
|
||||
```
|
||||
|
||||
**Before**
|
||||
|
||||
```css
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
@import "shadcn/tailwind.css";
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```css
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
/* ejected from shadcn@4.8.3 */
|
||||
@theme inline {
|
||||
@keyframes accordion-down {
|
||||
from {
|
||||
height: 0;
|
||||
}
|
||||
to {
|
||||
height: var(
|
||||
--radix-accordion-content-height,
|
||||
var(--accordion-panel-height, auto)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@custom-variant data-open {
|
||||
&:where([data-state="open"]),
|
||||
&:where([data-open]:not([data-open="false"])) {
|
||||
@slot;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In a monorepo, run the command from the workspace that contains your `components.json` and global CSS file:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest eject -c packages/ui
|
||||
```
|
||||
|
||||
See the [CLI documentation](/docs/cli#eject) for more details.
|
||||
98
apps/v4/content/docs/changelog/2026-06-github-registries.mdx
Normal file
98
apps/v4/content/docs/changelog/2026-06-github-registries.mdx
Normal file
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: June 2026 - GitHub Registries
|
||||
description: Turn any public GitHub repository into a shadcn registry.
|
||||
date: 2026-06-01
|
||||
---
|
||||
|
||||
**You can now turn any public GitHub repository into a registry.**
|
||||
|
||||
Add a `registry.json` file at the root of the repository, define the items you
|
||||
want to distribute, and users can install them directly from GitHub with the
|
||||
`shadcn` CLI.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add <username>/<repo>/<item>
|
||||
```
|
||||
|
||||
For example, to install the `project-conventions` item from the `acme/toolkit` repository:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/project-conventions
|
||||
```
|
||||
|
||||
GitHub registries are source registries. You do not need to run `shadcn build`,
|
||||
publish generated item JSON files or set up a registry server. The CLI reads the
|
||||
root `registry.json`, resolves `include` entries, finds the requested item and
|
||||
installs the files declared by that item.
|
||||
|
||||
## Distribute anything
|
||||
|
||||
Registry items are not limited to components. A GitHub registry can distribute
|
||||
components, hooks, utilities, design tokens, feature kits, project conventions,
|
||||
agent instructions, testing setup, CI workflows, release workflows, templates,
|
||||
codemods, migration kits and other project files.
|
||||
|
||||
For example, a repository can expose a `project-conventions` item that installs
|
||||
shared docs, editor settings and agent instructions:
|
||||
|
||||
```json title="registry.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||
"name": "acme-toolkit",
|
||||
"homepage": "https://github.com/acme/toolkit",
|
||||
"items": [
|
||||
{
|
||||
"name": "project-conventions",
|
||||
"type": "registry:item",
|
||||
"files": [
|
||||
{
|
||||
"path": "AGENTS.md",
|
||||
"type": "registry:file",
|
||||
"target": "~/AGENTS.md"
|
||||
},
|
||||
{
|
||||
"path": ".editorconfig",
|
||||
"type": "registry:file",
|
||||
"target": "~/.editorconfig"
|
||||
},
|
||||
{
|
||||
"path": "docs/conventions.md",
|
||||
"type": "registry:file",
|
||||
"target": "~/docs/conventions.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
GitHub registry addresses work with the same commands as other registry
|
||||
addresses.
|
||||
|
||||
List items from a GitHub registry:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest list acme/toolkit
|
||||
```
|
||||
|
||||
Search items:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest search acme/toolkit --query conventions
|
||||
```
|
||||
|
||||
View an item:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest view acme/toolkit/project-conventions
|
||||
```
|
||||
|
||||
Install an item:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/project-conventions
|
||||
```
|
||||
|
||||
See the [GitHub Registries](/docs/registry/github) docs for the full guide.
|
||||
@@ -103,6 +103,24 @@ Use the `size="sm"` prop to set the size of the card to small. The small size va
|
||||
previewClassName="h-96"
|
||||
/>
|
||||
|
||||
### Spacing
|
||||
|
||||
In addition to the `size` prop, you can use the `--card-spacing` CSS variable to control the spacing between sections and the inset of card parts.
|
||||
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="card-spacing"
|
||||
previewClassName="h-[34rem]"
|
||||
/>
|
||||
|
||||
Use negative margins with `-mx-(--card-spacing)` to make content go edge to edge while keeping it aligned with the card inset. When the edge-to-edge content sits above a footer, use `-mb-(--card-spacing)` on `CardContent` to remove the section gap.
|
||||
|
||||
<ComponentPreview
|
||||
styleName="base-nova"
|
||||
name="card-edge-to-edge"
|
||||
previewClassName="h-[24rem]"
|
||||
/>
|
||||
|
||||
### Image
|
||||
|
||||
Add an image before the card header to create a card with an image.
|
||||
@@ -182,3 +200,70 @@ The `CardFooter` component is used for actions and secondary content at the bott
|
||||
| Prop | Type | Default |
|
||||
| ----------- | -------- | ------- |
|
||||
| `className` | `string` | - |
|
||||
|
||||
## Changelog
|
||||
|
||||
### Spacing Variable
|
||||
|
||||
If you're upgrading from a previous version of the `Card` component, you'll need to apply the following updates to use the `--card-spacing` variable:
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step>Update the Card root spacing classes.</Step>
|
||||
|
||||
Replace the hard-coded gap and vertical padding with `--card-spacing`, and set the default and small size values on the root:
|
||||
|
||||
```diff
|
||||
className={cn(
|
||||
- "group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
|
||||
+ "group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
|
||||
className
|
||||
)}
|
||||
```
|
||||
|
||||
<Step>Update CardHeader spacing classes.</Step>
|
||||
|
||||
Replace the horizontal padding and border spacing with the shared variable:
|
||||
|
||||
```diff
|
||||
className={cn(
|
||||
- "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
|
||||
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
|
||||
className
|
||||
)}
|
||||
```
|
||||
|
||||
<Step>Update CardContent and CardFooter spacing classes.</Step>
|
||||
|
||||
Use `--card-spacing` for the content inset and footer padding:
|
||||
|
||||
```diff
|
||||
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-content"
|
||||
- className={cn("px-4 group-data-[size=sm]/card:px-3", className)}
|
||||
+ className={cn("px-(--card-spacing)", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```diff
|
||||
className={cn(
|
||||
- "flex items-center rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/card:p-3",
|
||||
+ "flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)",
|
||||
className
|
||||
)}
|
||||
```
|
||||
|
||||
</Steps>
|
||||
|
||||
After applying these changes, you can customize card spacing by setting `--card-spacing` on the `Card` with an arbitrary property class:
|
||||
|
||||
```tsx
|
||||
function Example() {
|
||||
return <Card className="[--card-spacing:--spacing(6)]">...</Card>
|
||||
}
|
||||
```
|
||||
|
||||
@@ -103,6 +103,24 @@ Use the `size="sm"` prop to set the size of the card to small. The small size va
|
||||
previewClassName="h-96"
|
||||
/>
|
||||
|
||||
### Spacing
|
||||
|
||||
In addition to the `size` prop, you can use the `--card-spacing` CSS variable to control the spacing between sections and the inset of card parts.
|
||||
|
||||
<ComponentPreview
|
||||
styleName="radix-nova"
|
||||
name="card-spacing"
|
||||
previewClassName="h-[34rem]"
|
||||
/>
|
||||
|
||||
Use negative margins with `-mx-(--card-spacing)` to make content go edge to edge while keeping it aligned with the card inset. When the edge-to-edge content sits above a footer, use `-mb-(--card-spacing)` on `CardContent` to remove the section gap.
|
||||
|
||||
<ComponentPreview
|
||||
styleName="radix-nova"
|
||||
name="card-edge-to-edge"
|
||||
previewClassName="h-[24rem]"
|
||||
/>
|
||||
|
||||
### Image
|
||||
|
||||
Add an image before the card header to create a card with an image.
|
||||
@@ -182,3 +200,70 @@ The `CardFooter` component is used for actions and secondary content at the bott
|
||||
| Prop | Type | Default |
|
||||
| ----------- | -------- | ------- |
|
||||
| `className` | `string` | - |
|
||||
|
||||
## Changelog
|
||||
|
||||
### Spacing Variable
|
||||
|
||||
If you're upgrading from a previous version of the `Card` component, you'll need to apply the following updates to use the `--card-spacing` variable:
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step>Update the Card root spacing classes.</Step>
|
||||
|
||||
Replace the hard-coded gap and vertical padding with `--card-spacing`, and set the default and small size values on the root:
|
||||
|
||||
```diff
|
||||
className={cn(
|
||||
- "group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
|
||||
+ "group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
|
||||
className
|
||||
)}
|
||||
```
|
||||
|
||||
<Step>Update CardHeader spacing classes.</Step>
|
||||
|
||||
Replace the horizontal padding and border spacing with the shared variable:
|
||||
|
||||
```diff
|
||||
className={cn(
|
||||
- "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
|
||||
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
|
||||
className
|
||||
)}
|
||||
```
|
||||
|
||||
<Step>Update CardContent and CardFooter spacing classes.</Step>
|
||||
|
||||
Use `--card-spacing` for the content inset and footer padding:
|
||||
|
||||
```diff
|
||||
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-content"
|
||||
- className={cn("px-4 group-data-[size=sm]/card:px-3", className)}
|
||||
+ className={cn("px-(--card-spacing)", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```diff
|
||||
className={cn(
|
||||
- "flex items-center rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/card:p-3",
|
||||
+ "flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)",
|
||||
className
|
||||
)}
|
||||
```
|
||||
|
||||
</Steps>
|
||||
|
||||
After applying these changes, you can customize card spacing by setting `--card-spacing` on the `Card` with an arbitrary property class:
|
||||
|
||||
```tsx
|
||||
function Example() {
|
||||
return <Card className="[--card-spacing:--spacing(6)]">...</Card>
|
||||
}
|
||||
```
|
||||
|
||||
422
apps/v4/content/docs/registry/api-reference.mdx
Normal file
422
apps/v4/content/docs/registry/api-reference.mdx
Normal file
@@ -0,0 +1,422 @@
|
||||
---
|
||||
title: API Reference
|
||||
description: Programmatic API for working with registries, schemas and presets.
|
||||
---
|
||||
|
||||
The `shadcn` package exposes a set of programmatic APIs in addition to the CLI.
|
||||
You can use these to fetch and resolve registry items, validate registry JSON,
|
||||
and build custom tooling on top of the registry.
|
||||
|
||||
Each API is available under a dedicated subpath import.
|
||||
|
||||
```ts
|
||||
import { getRegistryItems } from "shadcn/registry"
|
||||
import { registryItemSchema } from "shadcn/schema"
|
||||
```
|
||||
|
||||
<Callout className="mt-6">
|
||||
The CLI commands themselves are not part of the public API. Only the imports
|
||||
documented below are considered stable.
|
||||
</Callout>
|
||||
|
||||
## shadcn/registry
|
||||
|
||||
Fetch and resolve items from configured registries.
|
||||
|
||||
Most functions accept an options object. The two options below are common to all
|
||||
of them. In the examples that follow, `config` refers to this optional value —
|
||||
omit it to use the built-in registries.
|
||||
|
||||
### config
|
||||
|
||||
- **Type:** `Partial<Config>`
|
||||
- **Default:** built-in registries only
|
||||
|
||||
The resolved contents of your `components.json` file. Its `registries` field
|
||||
maps a namespace (e.g. `@acme`) to a URL and any authentication headers or
|
||||
environment variables required to reach it.
|
||||
|
||||
```ts showLineNumbers
|
||||
import { getRegistryItems } from "shadcn/registry"
|
||||
|
||||
const items = await getRegistryItems(["@acme/login-form"], {
|
||||
config: {
|
||||
registries: {
|
||||
"@acme": "https://acme.com/r/{name}.json",
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### useCache
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `true`
|
||||
|
||||
Registry responses are cached **in memory for the lifetime of the process**,
|
||||
keyed by the resolved URL. Because the in-flight promise is cached, concurrent
|
||||
requests for the same URL are de-duplicated into a single fetch.
|
||||
|
||||
Leave this enabled for one-off scripts and CLI runs. Set it to `false` in
|
||||
long-running processes (servers, watchers, the MCP server) where the registry
|
||||
can change between requests and you need fresh data each time.
|
||||
|
||||
```ts
|
||||
const fresh = await getRegistry("@shadcn", { useCache: false })
|
||||
```
|
||||
|
||||
### getRegistry
|
||||
|
||||
Fetch a single registry by name.
|
||||
|
||||
```ts showLineNumbers
|
||||
import { getRegistry } from "shadcn/registry"
|
||||
|
||||
const registry = await getRegistry("@acme", {
|
||||
config, // optional Partial<Config>
|
||||
useCache: true,
|
||||
})
|
||||
```
|
||||
|
||||
### getRegistryItems
|
||||
|
||||
Fetch one or more registry items by their qualified names.
|
||||
|
||||
```ts showLineNumbers
|
||||
import { getRegistryItems } from "shadcn/registry"
|
||||
|
||||
const items = await getRegistryItems(["@acme/button", "@acme/card"], {
|
||||
config,
|
||||
useCache: true,
|
||||
})
|
||||
```
|
||||
|
||||
Returns an array of registry items:
|
||||
|
||||
```json showLineNumbers
|
||||
[
|
||||
{
|
||||
"name": "button",
|
||||
"type": "registry:ui",
|
||||
"dependencies": ["@radix-ui/react-slot"],
|
||||
"files": [
|
||||
{
|
||||
"path": "ui/button.tsx",
|
||||
"type": "registry:ui",
|
||||
"content": "..."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### resolveRegistryItems
|
||||
|
||||
Resolve multiple items together with their registry dependencies, merged into a
|
||||
single tree. Unlike [`getRegistryItems`](#getregistryitems), which returns the
|
||||
items as a list, this walks each item's `registryDependencies` and flattens
|
||||
everything — files, dependencies, CSS variables — into one installable object.
|
||||
|
||||
```ts showLineNumbers
|
||||
import { resolveRegistryItems } from "shadcn/registry"
|
||||
|
||||
const tree = await resolveRegistryItems(
|
||||
["@acme/button", "@acme/card", "@acme/dialog"],
|
||||
{ config }
|
||||
)
|
||||
```
|
||||
|
||||
Returns a single merged tree:
|
||||
|
||||
```json showLineNumbers
|
||||
{
|
||||
"dependencies": ["@radix-ui/react-slot", "@radix-ui/react-dialog"],
|
||||
"files": [
|
||||
{ "path": "ui/button.tsx", "type": "registry:ui", "content": "..." },
|
||||
{ "path": "ui/card.tsx", "type": "registry:ui", "content": "..." },
|
||||
{ "path": "ui/dialog.tsx", "type": "registry:ui", "content": "..." }
|
||||
],
|
||||
"cssVars": {
|
||||
"theme": {
|
||||
"font-heading": "Poppins, sans-serif"
|
||||
},
|
||||
"light": {
|
||||
"brand": "oklch(0.205 0.015 18)"
|
||||
},
|
||||
"dark": {
|
||||
"brand": "oklch(0.205 0.015 18)"
|
||||
}
|
||||
},
|
||||
"docs": ""
|
||||
}
|
||||
```
|
||||
|
||||
### getRegistries
|
||||
|
||||
Fetch the registry directory.
|
||||
|
||||
```ts showLineNumbers
|
||||
import { getRegistries } from "shadcn/registry"
|
||||
|
||||
const registries = await getRegistries({ useCache: true })
|
||||
```
|
||||
|
||||
Returns an array of registry entries:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"name": "@shadcn",
|
||||
"url": "https://ui.shadcn.com/r/{name}.json",
|
||||
"homepage": "https://ui.shadcn.com"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### searchRegistries
|
||||
|
||||
Search across one or more registries with fuzzy matching.
|
||||
|
||||
```ts showLineNumbers
|
||||
import { searchRegistries } from "shadcn/registry"
|
||||
|
||||
const results = await searchRegistries(["@shadcn"], {
|
||||
query: "button",
|
||||
types: ["registry:component"],
|
||||
limit: 100,
|
||||
offset: 0,
|
||||
config,
|
||||
continueOnError: true, // skip (don't throw on) registries that fail to load
|
||||
})
|
||||
```
|
||||
|
||||
Returns matching items wrapped in pagination metadata:
|
||||
|
||||
```json
|
||||
{
|
||||
"pagination": { "total": 1, "offset": 0, "limit": 100, "hasMore": false },
|
||||
"items": [
|
||||
{
|
||||
"name": "button",
|
||||
"type": "registry:ui",
|
||||
"description": "A button component.",
|
||||
"registry": "@shadcn",
|
||||
"addCommandArgument": "@shadcn/button"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### loadRegistry
|
||||
|
||||
Read and resolve a local `registry.json` file from disk, following any
|
||||
`include` references, and return the registry catalog.
|
||||
|
||||
```ts showLineNumbers
|
||||
import { loadRegistry } from "shadcn/registry"
|
||||
|
||||
const catalog = await loadRegistry({
|
||||
cwd: process.cwd(), // defaults to process.cwd()
|
||||
registryFile: "registry.json", // defaults to "registry.json"
|
||||
})
|
||||
```
|
||||
|
||||
The returned catalog lists every item but **omits file contents** — like a
|
||||
built `registry.json` index.
|
||||
|
||||
<Callout className="mt-6" title="How is this different from getRegistry?">
|
||||
[`getRegistry`](#getregistry) fetches a **remote** registry over the network
|
||||
(by namespace, URL or GitHub address) and expects the served catalog to
|
||||
already be flattened — it rejects catalogs that still use `include`.
|
||||
`loadRegistry` reads a **local** `registry.json` from disk and resolves
|
||||
`include` references itself.
|
||||
</Callout>
|
||||
|
||||
### loadRegistryItem
|
||||
|
||||
Read a single item from a local `registry.json` by name, with its file contents
|
||||
read from disk and inlined.
|
||||
|
||||
```ts showLineNumbers
|
||||
import { loadRegistryItem } from "shadcn/registry"
|
||||
|
||||
const item = await loadRegistryItem("login-form", { cwd: process.cwd() })
|
||||
```
|
||||
|
||||
Returns a fully resolved registry item with file contents:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "login-form",
|
||||
"type": "registry:component",
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york/login-form.tsx",
|
||||
"type": "registry:component",
|
||||
"content": "..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
<Callout className="mt-6" title="How is this different from getRegistryItems?">
|
||||
[`getRegistryItems`](#getregistryitems) resolves items from a **remote**
|
||||
registry over the network. `loadRegistryItem` builds a single item on demand
|
||||
from your **local** source files, reading each file from disk. Use it in a
|
||||
dynamic route that serves `registry-item.json` responses.
|
||||
</Callout>
|
||||
|
||||
### Errors
|
||||
|
||||
All registry functions throw typed errors that extend `RegistryError`. Use the
|
||||
`RegistryErrorCode` enum or `instanceof` checks to handle them.
|
||||
|
||||
```ts showLineNumbers
|
||||
import { RegistryError, RegistryNotFoundError } from "shadcn/registry"
|
||||
|
||||
try {
|
||||
await getRegistry("@unknown")
|
||||
} catch (error) {
|
||||
if (error instanceof RegistryNotFoundError) {
|
||||
// handle missing registry
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Available error classes:
|
||||
|
||||
- `RegistryError`
|
||||
- `RegistryNotFoundError`
|
||||
- `RegistryUnauthorizedError`
|
||||
- `RegistryForbiddenError`
|
||||
- `RegistryFetchError`
|
||||
- `RegistryNotConfiguredError`
|
||||
- `RegistryLocalFileError`
|
||||
- `RegistryParseError`
|
||||
- `RegistryValidationError`
|
||||
- `RegistryItemNotFoundError`
|
||||
- `RegistriesIndexParseError`
|
||||
- `RegistryMissingEnvironmentVariablesError`
|
||||
- `RegistryInvalidNamespaceError`
|
||||
|
||||
## shadcn/schema
|
||||
|
||||
The Zod schemas used to validate `registry.json`, `registry-item.json` and
|
||||
`components.json`. Useful for validating registry data in your own tooling.
|
||||
|
||||
```ts
|
||||
import { registryItemSchema, registrySchema } from "shadcn/schema"
|
||||
|
||||
const result = registryItemSchema.safeParse(json)
|
||||
if (!result.success) {
|
||||
console.error(result.error)
|
||||
}
|
||||
```
|
||||
|
||||
Key schemas:
|
||||
|
||||
- `registrySchema`
|
||||
- `registryItemSchema`
|
||||
- `registryItemFileSchema`
|
||||
- `registryItemTypeSchema`
|
||||
- `registryItemCssVarsSchema`
|
||||
- `registryItemTailwindSchema`
|
||||
- `registryBaseColorSchema`
|
||||
- `configSchema`
|
||||
- `presetSchema`
|
||||
|
||||
Inferred types are exported alongside them:
|
||||
|
||||
- `Registry`
|
||||
- `RegistryItem`
|
||||
- `RegistryBaseItem`
|
||||
- `RegistryFontItem`
|
||||
- `Preset`
|
||||
- `ConfigJson`
|
||||
|
||||
## shadcn/preset
|
||||
|
||||
Encode, decode and validate theme presets, plus the preset option constants used
|
||||
by the theme editor.
|
||||
|
||||
### encodePreset
|
||||
|
||||
Encode a `Partial<PresetConfig>` into a short, URL-safe preset code. Any fields
|
||||
you omit fall back to `DEFAULT_PRESET_CONFIG`.
|
||||
|
||||
```ts showLineNumbers
|
||||
import { encodePreset } from "shadcn/preset"
|
||||
|
||||
const code = encodePreset({
|
||||
style: "vega",
|
||||
baseColor: "stone",
|
||||
theme: "blue",
|
||||
radius: "large",
|
||||
font: "geist",
|
||||
})
|
||||
```
|
||||
|
||||
Returns a version-prefixed string:
|
||||
|
||||
```ts showLineNumbers
|
||||
"bJ4FLU0"
|
||||
```
|
||||
|
||||
### decodePreset
|
||||
|
||||
Decode a preset code back into a full `PresetConfig`. Returns `null` if the code
|
||||
is missing or invalid.
|
||||
|
||||
```ts showLineNumbers
|
||||
import { decodePreset } from "shadcn/preset"
|
||||
|
||||
const config = decodePreset("bJ4FLU0")
|
||||
```
|
||||
|
||||
Returns the resolved config (omitted fields are filled with their defaults):
|
||||
|
||||
```json
|
||||
{
|
||||
"style": "vega",
|
||||
"baseColor": "stone",
|
||||
"theme": "blue",
|
||||
"chartColor": "neutral",
|
||||
"iconLibrary": "lucide",
|
||||
"font": "geist",
|
||||
"fontHeading": "inherit",
|
||||
"radius": "large",
|
||||
"menuAccent": "subtle",
|
||||
"menuColor": "default"
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
decodePreset("not-a-code") // null
|
||||
```
|
||||
|
||||
### Other exports
|
||||
|
||||
Additional functions for validating codes and generating random presets:
|
||||
|
||||
- `isPresetCode`
|
||||
- `isValidPreset`
|
||||
- `generateRandomConfig`
|
||||
- `generateRandomPreset`
|
||||
- `toBase62`
|
||||
- `fromBase62`
|
||||
|
||||
Constants:
|
||||
|
||||
- `PRESET_BASES`
|
||||
- `PRESET_STYLES`
|
||||
- `PRESET_BASE_COLORS`
|
||||
- `PRESET_THEMES`
|
||||
- `PRESET_ICON_LIBRARIES`
|
||||
- `PRESET_FONTS`
|
||||
- `PRESET_FONT_HEADINGS`
|
||||
- `PRESET_RADII`
|
||||
- `PRESET_MENU_ACCENTS`
|
||||
- `PRESET_MENU_COLORS`
|
||||
- `PRESET_CHART_COLORS`
|
||||
- `DEFAULT_PRESET_CONFIG`
|
||||
@@ -76,6 +76,35 @@ To add a new color you need to add it to `cssVars` under `light` and `dark` keys
|
||||
|
||||
The CLI will update the project CSS file. Once updated, the new colors will be available to be used as utility classes: `bg-brand` and `text-brand-accent`.
|
||||
|
||||
### Why does `button` in `registryDependencies` not resolve to my GitHub repository?
|
||||
|
||||
Bare registry dependency names keep the existing shadcn behavior. `button`
|
||||
means the built-in shadcn `button` item.
|
||||
|
||||
For a dependency from a GitHub repository, use the full GitHub item address.
|
||||
|
||||
```json title="registry-item.json" showLineNumbers
|
||||
{
|
||||
"registryDependencies": ["acme/ui/button"]
|
||||
}
|
||||
```
|
||||
|
||||
### How do I pin a GitHub registry item?
|
||||
|
||||
Add `#ref` to the GitHub item address. The ref can be a branch, tag or full
|
||||
commit SHA.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/ui/button#v1.2.0
|
||||
```
|
||||
|
||||
For published registries, prefer tags or full commit SHAs.
|
||||
|
||||
### Can GitHub registry addresses use private repositories?
|
||||
|
||||
Not currently. GitHub registry addresses support public `github.com`
|
||||
repositories. For private registries, use a namespace with authenticated URLs.
|
||||
|
||||
### How do I add or override a Tailwind theme variable?
|
||||
|
||||
To add or override a theme variable you add it to `cssVars.theme` under the key you want to add or override.
|
||||
|
||||
@@ -3,15 +3,19 @@ title: Getting Started
|
||||
description: Learn how to get setup and run your own component registry.
|
||||
---
|
||||
|
||||
This guide will walk you through the process of setting up your own component registry. It assumes you already have a project with components and would like to turn it into a registry.
|
||||
This guide will walk you through the process of setting up your own registry. It assumes you already have a project with components, hooks, utilities or other files you would like to distribute.
|
||||
|
||||
**If you have an existing public GitHub repository, you can turn it into a
|
||||
registry by adding a `registry.json` file at the root.** See
|
||||
[GitHub Registries](/docs/registry/github) for details.
|
||||
|
||||
If you're starting a new registry project, you can use the [registry template](https://github.com/shadcn-ui/registry-template) as a starting point. We have already configured it for you.
|
||||
|
||||
## Requirements
|
||||
|
||||
You are free to design and host your custom registry as you see fit. The only requirement is that your registry catalog and registry items must be valid JSON files that conform to the [registry schema specification](/docs/registry/registry-json) and [registry-item schema specification](/docs/registry/registry-item-json).
|
||||
You are free to design and publish your custom registry as you see fit. The only requirement is that your registry catalog and registry items must conform to the [registry schema specification](/docs/registry/registry-json) and [registry-item schema specification](/docs/registry/registry-item-json).
|
||||
|
||||
Your registry can be a Next.js, Vite, Vue, Svelte, PHP or any other framework as long as it supports serving JSON over HTTP.
|
||||
Your registry can be a Next.js, Vite, Vue, Svelte, PHP or any other framework as long as it supports serving JSON over HTTP. It can also be a public GitHub repository with a `registry.json` file at the root.
|
||||
|
||||
If you'd like to see an example of a registry, we have a [template project](https://github.com/shadcn-ui/registry-template) for you to use as a starting point.
|
||||
|
||||
@@ -638,7 +642,7 @@ Here are some guidelines to follow when building components for a registry.
|
||||
- Place your registry item in the `registry/[STYLE]/[NAME]` directory. I'm using `default` as an example. It can be anything you want as long as it's nested under the `registry` directory.
|
||||
- For blocks, the following properties are required: `name`, `description`, `type` and `files`.
|
||||
- It is recommended to add a proper name and description to your registry item. This helps LLMs understand the component and its purpose.
|
||||
- Make sure to list all registry dependencies in `registryDependencies`. A registry dependency is the name of the component in the registry eg. `input`, `button`, `card`, etc or a URL to a registry item eg. `http://localhost:3000/r/editor.json`.
|
||||
- Make sure to list all registry dependencies in `registryDependencies`. A registry dependency is an item address such as `button`, `@acme/input-form`, `acme/ui/button` or `http://localhost:3000/r/editor.json`.
|
||||
- Make sure to list all dependencies in `dependencies`. A dependency is the name of the package in the registry eg. `zod`, `sonner`, etc. To set a version, you can use the `name@version` format eg. `zod@^3.20.0`.
|
||||
- **Imports should always use the `@/registry` path.** eg. `import { HelloWorld } from "@/registry/default/hello-world/hello-world"`
|
||||
- Ideally, place your files within a registry item in `components`, `hooks`, `lib` directories.
|
||||
|
||||
619
apps/v4/content/docs/registry/github.mdx
Normal file
619
apps/v4/content/docs/registry/github.mdx
Normal file
@@ -0,0 +1,619 @@
|
||||
---
|
||||
title: GitHub Registries
|
||||
description: Use a public GitHub repository as a registry.
|
||||
---
|
||||
|
||||
You can now turn **any public GitHub repository into a registry.**
|
||||
|
||||
Add a `registry.json` file to the root of the repo, describe the files you want
|
||||
to share, and users can install them with the `shadcn` CLI.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add <username>/<repo>/<item>
|
||||
```
|
||||
|
||||
You do not need to set up a registry server or publish generated JSON files. **The GitHub repository becomes the source registry.**
|
||||
|
||||
## Distribute Anything
|
||||
|
||||
Registry items are **not limited to components or React code.** They can include
|
||||
any files from your repository: source files, configuration, docs, templates,
|
||||
workflows, rules or project conventions.
|
||||
|
||||
<div className="not-prose my-6 overflow-hidden rounded-lg border text-sm">
|
||||
<div className="hidden grid-cols-[220px_1fr] border-b bg-muted/50 px-4 py-3 font-medium md:grid">
|
||||
<div>Use case</div>
|
||||
<div>Example files</div>
|
||||
</div>
|
||||
{[
|
||||
["Components", "components/date-picker.tsx", "components/data-table.tsx"],
|
||||
[
|
||||
"Helpers and utilities",
|
||||
"lib/format-date.ts",
|
||||
"lib/cn.ts",
|
||||
"hooks/use-copy.ts",
|
||||
],
|
||||
[
|
||||
"Design system packages",
|
||||
"tokens/colors.json",
|
||||
"styles/theme.css",
|
||||
"components/*",
|
||||
],
|
||||
[
|
||||
"Feature kits",
|
||||
"app/(auth)/*",
|
||||
"lib/auth.ts",
|
||||
"components/login-form.tsx",
|
||||
],
|
||||
["Agent workflows", "AGENTS.md", ".cursor/rules/*", ".claude/commands/*"],
|
||||
[
|
||||
"Project conventions",
|
||||
".editorconfig",
|
||||
"biome.json",
|
||||
"docs/conventions.md",
|
||||
],
|
||||
[
|
||||
"Codemods and migration kits",
|
||||
"codemods/*",
|
||||
"scripts/migrate.ts",
|
||||
"docs/migration.md",
|
||||
],
|
||||
["Testing setup", "vitest.config.ts", "test/setup.ts", "docs/testing.md"],
|
||||
[
|
||||
"CI and release workflows",
|
||||
".github/workflows/ci.yml",
|
||||
".github/workflows/release.yml",
|
||||
],
|
||||
[
|
||||
"Project automation",
|
||||
"scripts/release.ts",
|
||||
"scripts/checks.ts",
|
||||
"docs/automation.md",
|
||||
],
|
||||
[
|
||||
"Issue and pull request templates",
|
||||
".github/ISSUE_TEMPLATE/*",
|
||||
".github/pull_request_template.md",
|
||||
],
|
||||
["MCP configuration", ".mcp.json", ".cursor/mcp.json"],
|
||||
].map(([label, ...files]) => (
|
||||
<div
|
||||
className="grid gap-2 border-b px-4 py-3 last:border-b-0 md:grid-cols-[220px_1fr]"
|
||||
key={label}
|
||||
>
|
||||
<div className="font-medium">{label}</div>
|
||||
<div className="flex min-w-0 flex-wrap gap-1.5">
|
||||
{files.map((file) => (
|
||||
<code key={file}>{file}</code>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
## When to use GitHub
|
||||
|
||||
Use a GitHub registry when:
|
||||
|
||||
- You already have reusable code in a public GitHub repository.
|
||||
- You want users to install directly from `owner/repo/item`.
|
||||
- You want to distribute config files, rules, docs, templates, utilities or
|
||||
any other files from the same repository.
|
||||
- You do not need private repo access or custom request authentication.
|
||||
|
||||
## Requirements
|
||||
|
||||
A GitHub registry must:
|
||||
|
||||
- Be a public `github.com` repository.
|
||||
- Have a `registry.json` file at the repository root.
|
||||
- Use valid `registry.json` and `registry-item.json` schemas.
|
||||
- Reference source files that exist in the repository.
|
||||
|
||||
Private repositories and GitHub Enterprise hosts are not currently supported by
|
||||
GitHub addresses. For private or authenticated registries, use a
|
||||
[namespace](/docs/registry/namespace) with
|
||||
[authentication](/docs/registry/authentication).
|
||||
|
||||
## Step 1: Add registry.json
|
||||
|
||||
Given an existing public repository:
|
||||
|
||||
```txt
|
||||
.
|
||||
├── ...
|
||||
├── .editorconfig
|
||||
├── AGENTS.md
|
||||
└── docs
|
||||
└── conventions.md
|
||||
```
|
||||
|
||||
Add `registry.json` at the root of the repository.
|
||||
|
||||
```txt
|
||||
.
|
||||
├── ...
|
||||
├── registry.json
|
||||
├── .editorconfig
|
||||
├── AGENTS.md
|
||||
└── docs
|
||||
└── conventions.md
|
||||
```
|
||||
|
||||
Define the item you want to distribute.
|
||||
|
||||
```json title="registry.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||
"name": "acme-toolkit",
|
||||
"homepage": "https://github.com/acme/toolkit",
|
||||
"items": [
|
||||
{
|
||||
"name": "project-conventions",
|
||||
"type": "registry:item",
|
||||
"title": "Project Conventions",
|
||||
"description": "Shared project conventions, editor settings and agent instructions.",
|
||||
"files": [
|
||||
{
|
||||
"path": "AGENTS.md",
|
||||
"type": "registry:file",
|
||||
"target": "~/AGENTS.md"
|
||||
},
|
||||
{
|
||||
"path": ".editorconfig",
|
||||
"type": "registry:file",
|
||||
"target": "~/.editorconfig"
|
||||
},
|
||||
{
|
||||
"path": "docs/conventions.md",
|
||||
"type": "registry:file",
|
||||
"target": "~/docs/conventions.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Commit and push the file.
|
||||
|
||||
```bash
|
||||
git add registry.json
|
||||
```
|
||||
|
||||
```bash
|
||||
git commit -m "add registry"
|
||||
```
|
||||
|
||||
```bash
|
||||
git push
|
||||
```
|
||||
|
||||
Users can now install the item from GitHub.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/project-conventions
|
||||
```
|
||||
|
||||
## Step 2: Distribute any file
|
||||
|
||||
A registry item can install one file or many files. Use the `files` array to
|
||||
declare the files that belong together.
|
||||
|
||||
For example, a testing setup can install a Vitest config, a setup file and a
|
||||
short team guide.
|
||||
|
||||
```txt
|
||||
registry.json
|
||||
config
|
||||
└── vitest.config.ts
|
||||
docs
|
||||
└── testing.md
|
||||
test
|
||||
└── setup.ts
|
||||
```
|
||||
|
||||
```json title="registry.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||
"name": "acme-toolkit",
|
||||
"homepage": "https://github.com/acme/toolkit",
|
||||
"items": [
|
||||
{
|
||||
"name": "vitest-setup",
|
||||
"type": "registry:item",
|
||||
"title": "Vitest Setup",
|
||||
"description": "A Vitest setup with project defaults and docs.",
|
||||
"files": [
|
||||
{
|
||||
"path": "config/vitest.config.ts",
|
||||
"type": "registry:file",
|
||||
"target": "~/vitest.config.ts"
|
||||
},
|
||||
{
|
||||
"path": "test/setup.ts",
|
||||
"type": "registry:file",
|
||||
"target": "~/test/setup.ts"
|
||||
},
|
||||
{
|
||||
"path": "docs/testing.md",
|
||||
"type": "registry:file",
|
||||
"target": "~/docs/testing.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Users install it the same way.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/vitest-setup
|
||||
```
|
||||
|
||||
Use `target` when a file should be written to a specific destination in the
|
||||
user's project.
|
||||
|
||||
```json title="registry.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||
"name": "acme-toolkit",
|
||||
"homepage": "https://github.com/acme/toolkit",
|
||||
"items": [
|
||||
{
|
||||
"name": "editorconfig",
|
||||
"type": "registry:file",
|
||||
"files": [
|
||||
{
|
||||
"path": "config/.editorconfig",
|
||||
"type": "registry:file",
|
||||
"target": "~/.editorconfig"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/editorconfig
|
||||
```
|
||||
|
||||
## Step 3: Validate the registry
|
||||
|
||||
Before sharing the registry, validate it from the CLI.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest registry validate acme/toolkit
|
||||
```
|
||||
|
||||
The command reads the root `registry.json`, resolves includes, validates the
|
||||
registry items, and checks that referenced files exist.
|
||||
|
||||
You can also validate a branch, tag or commit SHA.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest registry validate acme/toolkit#v1.0.0
|
||||
```
|
||||
|
||||
## Step 4: List and search items
|
||||
|
||||
Use `list` to see every item in the repository registry.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest list acme/toolkit
|
||||
```
|
||||
|
||||
Use `search` to filter the catalog.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest search acme/toolkit --query conventions
|
||||
```
|
||||
|
||||
Use `view` to inspect one item payload.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest view acme/toolkit/project-conventions
|
||||
```
|
||||
|
||||
## Organize with include
|
||||
|
||||
For larger repositories, keep item definitions close to the source files they
|
||||
describe.
|
||||
|
||||
```txt
|
||||
registry.json
|
||||
config
|
||||
├── prettier.config.mjs
|
||||
└── registry.json
|
||||
rules
|
||||
├── agent.md
|
||||
└── registry.json
|
||||
```
|
||||
|
||||
The root `registry.json` can include the nested registry files.
|
||||
|
||||
```json title="registry.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||
"name": "acme-toolkit",
|
||||
"homepage": "https://github.com/acme/toolkit",
|
||||
"include": ["config/registry.json", "rules/registry.json"]
|
||||
}
|
||||
```
|
||||
|
||||
The included registry file declares items for that directory.
|
||||
|
||||
```json title="rules/registry.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||
"items": [
|
||||
{
|
||||
"name": "agent-rules",
|
||||
"type": "registry:file",
|
||||
"files": [
|
||||
{
|
||||
"path": "agent.md",
|
||||
"type": "registry:file",
|
||||
"target": "~/AGENTS.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
When using `include`, file paths are relative to the `registry.json` file that
|
||||
declares the item.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/project-conventions
|
||||
```
|
||||
|
||||
## Registry dependencies
|
||||
|
||||
Use `registryDependencies` when one registry item depends on another registry
|
||||
item.
|
||||
|
||||
### Same repository dependencies
|
||||
|
||||
For dependencies in the same GitHub repository, use the full GitHub item
|
||||
address.
|
||||
|
||||
```json title="registry.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||
"name": "acme-toolkit",
|
||||
"homepage": "https://github.com/acme/toolkit",
|
||||
"items": [
|
||||
{
|
||||
"name": "project-setup",
|
||||
"type": "registry:item",
|
||||
"registryDependencies": [
|
||||
"acme/toolkit/agent-rules",
|
||||
"acme/toolkit/prettier-config",
|
||||
"acme/toolkit/tsconfig"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "docs/project-setup.md",
|
||||
"type": "registry:file",
|
||||
"target": "~/docs/project-setup.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
A docs item can depend on a template item from the same repository.
|
||||
|
||||
```json title="registry.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||
"name": "acme-toolkit",
|
||||
"homepage": "https://github.com/acme/toolkit",
|
||||
"items": [
|
||||
{
|
||||
"name": "contributing-guide",
|
||||
"type": "registry:item",
|
||||
"registryDependencies": ["acme/toolkit/readme-template"],
|
||||
"files": [
|
||||
{
|
||||
"path": "docs/contributing.md",
|
||||
"type": "registry:file",
|
||||
"target": "~/docs/contributing.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
A CI setup can depend on the same formatting and testing defaults that users can
|
||||
install separately.
|
||||
|
||||
```json title="registry.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||
"name": "acme-toolkit",
|
||||
"homepage": "https://github.com/acme/toolkit",
|
||||
"items": [
|
||||
{
|
||||
"name": "ci-setup",
|
||||
"type": "registry:item",
|
||||
"registryDependencies": [
|
||||
"acme/toolkit/prettier-config",
|
||||
"acme/toolkit/vitest-setup"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": ".github/workflows/ci.yml",
|
||||
"type": "registry:file",
|
||||
"target": "~/.github/workflows/ci.yml"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### External registry dependencies
|
||||
|
||||
Items can also depend on external registries. Use the full item address for the
|
||||
registry that owns the dependency.
|
||||
|
||||
```json title="registry.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||
"name": "acme-toolkit",
|
||||
"homepage": "https://github.com/acme/toolkit",
|
||||
"items": [
|
||||
{
|
||||
"name": "workspace-setup",
|
||||
"type": "registry:item",
|
||||
"registryDependencies": [
|
||||
"@acme/tsconfig",
|
||||
"contoso/devtools/prettier-config"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "docs/workspace.md",
|
||||
"type": "registry:file",
|
||||
"target": "~/docs/workspace.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Dependency refs
|
||||
|
||||
Refs are not inherited across dependencies. If a dependency should be pinned,
|
||||
include its own ref.
|
||||
|
||||
```json title="registry.json" showLineNumbers
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||
"name": "acme-toolkit",
|
||||
"homepage": "https://github.com/acme/toolkit",
|
||||
"items": [
|
||||
{
|
||||
"name": "project-setup",
|
||||
"type": "registry:item",
|
||||
"registryDependencies": [
|
||||
"acme/toolkit/agent-rules#v1.0.0",
|
||||
"acme/toolkit/tsconfig#c0ffee254729296a45d6691db565cf707a3fef5d"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "docs/project-setup.md",
|
||||
"type": "registry:file",
|
||||
"target": "~/docs/project-setup.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Useful commands
|
||||
|
||||
List every item in a GitHub registry.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest list acme/toolkit
|
||||
```
|
||||
|
||||
Search a GitHub registry.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest search acme/toolkit -q conventions
|
||||
```
|
||||
|
||||
Validate a GitHub registry.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest registry validate acme/toolkit
|
||||
```
|
||||
|
||||
Install an item from a GitHub registry.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/project-conventions
|
||||
```
|
||||
|
||||
View an item from a GitHub registry.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest view acme/toolkit/project-conventions
|
||||
```
|
||||
|
||||
Install an item whose registry item name contains `/`.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/rules/agent
|
||||
```
|
||||
|
||||
<Callout>
|
||||
For GitHub item addresses, the first two path segments are the GitHub owner
|
||||
and repository. Any remaining segments are the registry item name, not a file
|
||||
path. An address ending in `.json` is treated as a file path.
|
||||
</Callout>
|
||||
|
||||
Install from a tag.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/project-conventions#v1.0.0
|
||||
```
|
||||
|
||||
Install from a full commit SHA.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/project-conventions#c0ffee254729296a45d6691db565cf707a3fef5d
|
||||
```
|
||||
|
||||
## Refs
|
||||
|
||||
Use `#ref` to install from a branch, tag or commit SHA.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/project-conventions#main
|
||||
```
|
||||
|
||||
Refs may contain slashes.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/toolkit/project-conventions#feature/conventions
|
||||
```
|
||||
|
||||
If no ref is provided, the CLI uses the repository default branch.
|
||||
|
||||
The CLI uses Git to resolve branches, tags and short refs into a commit SHA
|
||||
before reading files. Full 40-character commit SHAs are used directly and do not
|
||||
require Git.
|
||||
|
||||
## Review before installing
|
||||
|
||||
GitHub registry items install code and project files from public repositories.
|
||||
Treat a GitHub item address like any other third-party code dependency.
|
||||
|
||||
Before installing from a source you do not control:
|
||||
|
||||
- Review the repository and the root `registry.json`.
|
||||
- Review the item definition, especially `files`, `target`, `dependencies`,
|
||||
`devDependencies`, `registryDependencies` and `envVars`.
|
||||
- Check any external registry dependencies. They can install files from other
|
||||
registries.
|
||||
- Prefer pinned refs for published install commands. A full 40-character commit
|
||||
SHA is the most reproducible option.
|
||||
- Use `shadcn view acme/toolkit/project-conventions` to inspect the resolved
|
||||
item payload before installing.
|
||||
- Pipe `shadcn view` output to your agent or review tool if you want help
|
||||
checking the item.
|
||||
- Use `shadcn add acme/toolkit/project-conventions --dry-run` to preview an
|
||||
install without writing files.
|
||||
- Use `--diff` or `--view` with `shadcn add` to inspect file changes or file
|
||||
contents before applying them.
|
||||
@@ -33,12 +33,32 @@ You can use the `shadcn` CLI to run your own code registry. Running your own reg
|
||||
Ready to create your own registry? In the next section, we'll walk you through setting up your own custom registry step-by-step, from creating your first component to publishing it for others to use.
|
||||
|
||||
<div className="mt-6 grid gap-4 sm:grid-cols-2">
|
||||
<LinkedCard href="/docs/registry/getting-started" className="items-start text-sm md:p-6">
|
||||
<div className="font-medium">Getting Started</div>
|
||||
<div className="text-muted-foreground">
|
||||
Set up and build your own registry
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="/docs/registry/getting-started"
|
||||
className="items-start text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Getting Started</div>
|
||||
<div className="text-muted-foreground">
|
||||
Set up and build your own registry
|
||||
</div>
|
||||
</LinkedCard>
|
||||
|
||||
<LinkedCard href="/docs/registry/github" className="items-start text-sm md:p-6">
|
||||
<div className="font-medium">GitHub</div>
|
||||
<div className="text-muted-foreground">
|
||||
Turn a GitHub repository into a registry
|
||||
</div>
|
||||
</LinkedCard>
|
||||
|
||||
<LinkedCard
|
||||
href="/docs/registry/namespace"
|
||||
className="items-start text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Namespaces</div>
|
||||
<div className="text-muted-foreground">
|
||||
Configure registries with namespaces
|
||||
</div>
|
||||
</LinkedCard>
|
||||
|
||||
<LinkedCard
|
||||
href="/docs/registry/authentication"
|
||||
@@ -49,31 +69,22 @@ Ready to create your own registry? In the next section, we'll walk you through s
|
||||
Secure your registry with authentication
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="/docs/registry/namespace"
|
||||
className="items-start text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Namespaces</div>
|
||||
<div className="text-muted-foreground">
|
||||
Configure registries with namespaces
|
||||
</div>
|
||||
</LinkedCard>
|
||||
|
||||
<LinkedCard
|
||||
href="/docs/registry/examples"
|
||||
className="items-start text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Examples</div>
|
||||
<div className="text-muted-foreground">Browse example registry items</div>
|
||||
</LinkedCard>
|
||||
|
||||
<LinkedCard
|
||||
href="/docs/registry/registry-json"
|
||||
className="items-start text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Schema</div>
|
||||
<div className="text-muted-foreground">
|
||||
Registry item examples and configurations
|
||||
Schema specification for registry.json
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="/docs/registry/registry-json"
|
||||
className="items-start text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Schema</div>
|
||||
<div className="text-muted-foreground">
|
||||
Schema specification for registry.json
|
||||
</div>
|
||||
</LinkedCard>
|
||||
</div>
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
"pages": [
|
||||
"index",
|
||||
"getting-started",
|
||||
"github",
|
||||
"registry-index",
|
||||
"examples",
|
||||
"namespace",
|
||||
"authentication",
|
||||
"mcp",
|
||||
"open-in-v0",
|
||||
"api-reference",
|
||||
"registry-json",
|
||||
"registry-item-json"
|
||||
]
|
||||
|
||||
@@ -156,6 +156,28 @@ The pattern for referencing resources is: `@namespace/resource-name`
|
||||
|
||||
---
|
||||
|
||||
## GitHub and Namespaces
|
||||
|
||||
GitHub registry addresses and namespaces solve different problems.
|
||||
|
||||
Use a GitHub address when the registry is a public GitHub repository and you
|
||||
want users to install without configuring `components.json`.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add acme/ui/button
|
||||
```
|
||||
|
||||
Use a namespace when you want a stable alias, custom hosting, authentication,
|
||||
request headers, query parameters or private registry support.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add @acme/button
|
||||
```
|
||||
|
||||
See the [GitHub registry](/docs/registry/github) docs for more information.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
Namespaced registries are configured in your `components.json` file under the `registries` field.
|
||||
|
||||
@@ -9,10 +9,14 @@ When you run `shadcn add` or `shadcn search`, the CLI will automatically check t
|
||||
|
||||
You can see the full list at [https://ui.shadcn.com/r/registries.json](https://ui.shadcn.com/r/registries.json).
|
||||
|
||||
You do not need to submit a public GitHub registry to the registry directory to
|
||||
use it with `owner/repo/item` addresses. The registry directory is for
|
||||
namespaces such as `@acme`.
|
||||
|
||||
## Adding a Registry
|
||||
|
||||
1. Add your registry to [`apps/v4/registry/directory.json`](https://github.com/shadcn-ui/ui/blob/main/apps/v4/registry/directory.json)
|
||||
2. Run `pnpm registry:build` to update `registries.json` file.
|
||||
2. Run `pnpm validate:registries` to validate the registry directory.
|
||||
3. Create a pull request to https://github.com/shadcn-ui/ui
|
||||
|
||||
Once you have submitted your request, it will be validated and reviewed by the team.
|
||||
|
||||
@@ -161,23 +161,34 @@ Use `@version` to specify the version of the package.
|
||||
|
||||
### registryDependencies
|
||||
|
||||
Used for registry dependencies. Can be names, namespaced or URLs.
|
||||
Used for registry dependencies. Each entry is an item address.
|
||||
|
||||
- For `shadcn/ui` registry items such as `button`, `input`, `select`, etc use the name eg. `['button', 'input', 'select']`.
|
||||
- For namespaced registry items such as `@acme` use the name eg. `['@acme/input-form']`.
|
||||
- For namespaced registry items, use `@namespace/item-name` eg. `['@acme/input-form']`.
|
||||
- For GitHub registry items, use `owner/repo/item-name` eg. `['acme/ui/button']`. For published registries, prefer a tag or full commit SHA eg. `['acme/ui/button#v1.2.0']`.
|
||||
- For custom registry items use the URL of the registry item eg. `['https://example.com/r/hello-world.json']`.
|
||||
- For local registry item files use a file path eg. `['./hello-world.json']`.
|
||||
|
||||
```json title="registry-item.json" showLineNumbers
|
||||
{
|
||||
"registryDependencies": [
|
||||
"button",
|
||||
"@acme/input-form",
|
||||
"https://example.com/r/editor.json"
|
||||
"acme/ui/button#v1.2.0",
|
||||
"https://example.com/r/editor.json",
|
||||
"./editor.json"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Note: The CLI will automatically resolve remote registry dependencies.
|
||||
Note: Bare names keep their existing behavior. `button` means the built-in
|
||||
shadcn `button` item, not an item from the same GitHub repository. For
|
||||
same-repository GitHub dependencies, use the full GitHub item address.
|
||||
|
||||
Refs are not inherited across dependencies. If a GitHub dependency should be
|
||||
reproducible, pin that dependency to its own tag or full commit SHA.
|
||||
|
||||
See the [GitHub registry](/docs/registry/github) docs for more information.
|
||||
|
||||
### files
|
||||
|
||||
|
||||
@@ -49,6 +49,11 @@ using `include`.
|
||||
}
|
||||
```
|
||||
|
||||
Public GitHub repositories use the same source registry format. The CLI reads
|
||||
the root `registry.json`, resolves `include`, and installs files from the
|
||||
repository. See the [GitHub registry](/docs/registry/github) docs for more
|
||||
information.
|
||||
|
||||
## Definitions
|
||||
|
||||
You can see the JSON Schema for `registry.json` [here](https://ui.shadcn.com/schema/registry.json).
|
||||
|
||||
@@ -19,6 +19,7 @@ const eslintConfig = tseslint.config(
|
||||
"next-env.d.ts",
|
||||
".source/**",
|
||||
"**/__index__.tsx",
|
||||
"**/__components__.tsx",
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
7843
apps/v4/examples/__components__.tsx
Normal file
7843
apps/v4/examples/__components__.tsx
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
47
apps/v4/examples/base/card-edge-to-edge.tsx
Normal file
47
apps/v4/examples/base/card-edge-to-edge.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/styles/base-nova/ui/card"
|
||||
|
||||
export function CardEdgeToEdge() {
|
||||
return (
|
||||
<Card className="mx-auto w-full max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Terms of Service</CardTitle>
|
||||
<CardDescription>
|
||||
Review the terms before accepting the agreement.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="-mb-(--card-spacing)">
|
||||
<div className="-mx-(--card-spacing) max-h-48 space-y-4 overflow-y-scroll border-t bg-muted/50 px-(--card-spacing) py-4 text-sm leading-relaxed">
|
||||
<p>
|
||||
These terms govern your use of the workspace, including access to
|
||||
shared documents, project files, and collaboration tools.
|
||||
</p>
|
||||
<p>
|
||||
You are responsible for the content you upload and for ensuring that
|
||||
your team has the appropriate permissions to view or edit it.
|
||||
</p>
|
||||
<p>
|
||||
We may update features or limits as the service evolves. When those
|
||||
changes materially affect your workflow, we will notify your
|
||||
workspace administrators.
|
||||
</p>
|
||||
<p>
|
||||
By continuing, you agree to keep your account credentials secure and
|
||||
to follow your organization's acceptable use policies.
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="justify-end gap-2">
|
||||
<Button variant="outline">Decline</Button>
|
||||
<Button>Accept</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
118
apps/v4/examples/base/card-spacing.tsx
Normal file
118
apps/v4/examples/base/card-spacing.tsx
Normal file
@@ -0,0 +1,118 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/styles/base-nova/ui/card"
|
||||
import { Input } from "@/styles/base-nova/ui/input"
|
||||
import { Label } from "@/styles/base-nova/ui/label"
|
||||
import {
|
||||
ToggleGroup,
|
||||
ToggleGroupItem,
|
||||
} from "@/styles/base-nova/ui/toggle-group"
|
||||
|
||||
const spacingOptions = [
|
||||
{
|
||||
className: "[--card-spacing:--spacing(4)]",
|
||||
label: "16px",
|
||||
value: "4",
|
||||
},
|
||||
{
|
||||
className: "[--card-spacing:--spacing(5)]",
|
||||
label: "20px",
|
||||
value: "5",
|
||||
},
|
||||
{
|
||||
className: "[--card-spacing:--spacing(6)]",
|
||||
label: "24px",
|
||||
value: "6",
|
||||
},
|
||||
{
|
||||
className: "[--card-spacing:--spacing(8)]",
|
||||
label: "32px",
|
||||
value: "8",
|
||||
},
|
||||
]
|
||||
|
||||
export function CardSpacing() {
|
||||
const [spacing, setSpacing] = React.useState("4")
|
||||
const selectedSpacing = spacingOptions.find(
|
||||
(option) => option.value === spacing
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="mx-auto grid w-full max-w-sm gap-4">
|
||||
<ToggleGroup
|
||||
value={[spacing]}
|
||||
onValueChange={(value) => {
|
||||
if (value[0]) {
|
||||
setSpacing(value[0])
|
||||
}
|
||||
}}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="justify-center"
|
||||
>
|
||||
{spacingOptions.map((option) => (
|
||||
<ToggleGroupItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</ToggleGroupItem>
|
||||
))}
|
||||
</ToggleGroup>
|
||||
<Card className={selectedSpacing?.className}>
|
||||
<CardHeader>
|
||||
<CardTitle>Login to your account</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your email below to login to your account
|
||||
</CardDescription>
|
||||
<CardAction>
|
||||
<Button variant="link">Sign Up</Button>
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form>
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="email-spacing">Email</Label>
|
||||
<Input
|
||||
id="email-spacing"
|
||||
type="email"
|
||||
placeholder="m@example.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="password-spacing">Password</Label>
|
||||
<a
|
||||
href="#"
|
||||
className="ml-auto inline-block text-sm underline-offset-4 hover:underline"
|
||||
>
|
||||
Forgot your password?
|
||||
</a>
|
||||
</div>
|
||||
<Input id="password-spacing" type="password" required />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardFooter className="flex-col gap-2">
|
||||
<Button type="submit" className="w-full">
|
||||
Login
|
||||
</Button>
|
||||
<Button variant="outline" className="w-full">
|
||||
Login with Google
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
47
apps/v4/examples/radix/card-edge-to-edge.tsx
Normal file
47
apps/v4/examples/radix/card-edge-to-edge.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/styles/radix-nova/ui/card"
|
||||
|
||||
export function CardEdgeToEdge() {
|
||||
return (
|
||||
<Card className="mx-auto w-full max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Terms of Service</CardTitle>
|
||||
<CardDescription>
|
||||
Review the terms before accepting the agreement.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="-mb-(--card-spacing)">
|
||||
<div className="-mx-(--card-spacing) max-h-48 space-y-4 overflow-y-scroll border-t bg-muted/50 px-(--card-spacing) py-4 text-sm leading-relaxed">
|
||||
<p>
|
||||
These terms govern your use of the workspace, including access to
|
||||
shared documents, project files, and collaboration tools.
|
||||
</p>
|
||||
<p>
|
||||
You are responsible for the content you upload and for ensuring that
|
||||
your team has the appropriate permissions to view or edit it.
|
||||
</p>
|
||||
<p>
|
||||
We may update features or limits as the service evolves. When those
|
||||
changes materially affect your workflow, we will notify your
|
||||
workspace administrators.
|
||||
</p>
|
||||
<p>
|
||||
By continuing, you agree to keep your account credentials secure and
|
||||
to follow your organization's acceptable use policies.
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="justify-end gap-2">
|
||||
<Button variant="outline">Decline</Button>
|
||||
<Button>Accept</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
119
apps/v4/examples/radix/card-spacing.tsx
Normal file
119
apps/v4/examples/radix/card-spacing.tsx
Normal file
@@ -0,0 +1,119 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/styles/radix-nova/ui/card"
|
||||
import { Input } from "@/styles/radix-nova/ui/input"
|
||||
import { Label } from "@/styles/radix-nova/ui/label"
|
||||
import {
|
||||
ToggleGroup,
|
||||
ToggleGroupItem,
|
||||
} from "@/styles/radix-nova/ui/toggle-group"
|
||||
|
||||
const spacingOptions = [
|
||||
{
|
||||
className: "[--card-spacing:--spacing(4)]",
|
||||
label: "16px",
|
||||
value: "4",
|
||||
},
|
||||
{
|
||||
className: "[--card-spacing:--spacing(5)]",
|
||||
label: "20px",
|
||||
value: "5",
|
||||
},
|
||||
{
|
||||
className: "[--card-spacing:--spacing(6)]",
|
||||
label: "24px",
|
||||
value: "6",
|
||||
},
|
||||
{
|
||||
className: "[--card-spacing:--spacing(8)]",
|
||||
label: "32px",
|
||||
value: "8",
|
||||
},
|
||||
]
|
||||
|
||||
export function CardSpacing() {
|
||||
const [spacing, setSpacing] = React.useState("4")
|
||||
const selectedSpacing = spacingOptions.find(
|
||||
(option) => option.value === spacing
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="mx-auto grid w-full max-w-sm gap-4">
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
value={spacing}
|
||||
onValueChange={(value) => {
|
||||
if (value) {
|
||||
setSpacing(value)
|
||||
}
|
||||
}}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="justify-center"
|
||||
>
|
||||
{spacingOptions.map((option) => (
|
||||
<ToggleGroupItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</ToggleGroupItem>
|
||||
))}
|
||||
</ToggleGroup>
|
||||
<Card className={selectedSpacing?.className}>
|
||||
<CardHeader>
|
||||
<CardTitle>Login to your account</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your email below to login to your account
|
||||
</CardDescription>
|
||||
<CardAction>
|
||||
<Button variant="link">Sign Up</Button>
|
||||
</CardAction>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form>
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="email-spacing">Email</Label>
|
||||
<Input
|
||||
id="email-spacing"
|
||||
type="email"
|
||||
placeholder="m@example.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<div className="flex items-center">
|
||||
<Label htmlFor="password-spacing">Password</Label>
|
||||
<a
|
||||
href="#"
|
||||
className="ml-auto inline-block text-sm underline-offset-4 hover:underline"
|
||||
>
|
||||
Forgot your password?
|
||||
</a>
|
||||
</div>
|
||||
<Input id="password-spacing" type="password" required />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardFooter className="flex-col gap-2">
|
||||
<Button type="submit" className="w-full">
|
||||
Login
|
||||
</Button>
|
||||
<Button variant="outline" className="w-full">
|
||||
Login with Google
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
export const PAGES_NEW = [
|
||||
"/create",
|
||||
"/docs/registry",
|
||||
"/docs/registry/getting-started",
|
||||
"/docs/changelog",
|
||||
]
|
||||
export const PAGES_NEW = ["/create", "/docs/registry/github", "/docs/changelog"]
|
||||
|
||||
export const PAGES_UPDATED = ["/docs/components/button"]
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { promises as fs } from "fs"
|
||||
import path from "path"
|
||||
import { ExamplesComponents } from "@/examples/__components__"
|
||||
import { ExamplesIndex } from "@/examples/__index__"
|
||||
import { LRUCache } from "lru-cache"
|
||||
import { registryItemSchema, type registryItemFileSchema } from "shadcn/schema"
|
||||
import { type z } from "zod"
|
||||
|
||||
import { readFileFromRoot } from "@/lib/read-file"
|
||||
import { Components as StylesComponents } from "@/registry/__components__"
|
||||
import { Index as StylesIndex } from "@/registry/__index__"
|
||||
import { BASES } from "@/registry/bases"
|
||||
import { Components as BasesComponents } from "@/registry/bases/__components__"
|
||||
import { Index as BasesIndex } from "@/registry/bases/__index__"
|
||||
|
||||
// LRU cache for cross-request caching of registry items.
|
||||
@@ -64,9 +67,20 @@ function getRegistryEntry(name: string, styleName: string) {
|
||||
return getStyleIndex(styleName)?.[name] ?? getBaseIndex(styleName)?.[name]
|
||||
}
|
||||
|
||||
// Lazy components live in dedicated __components__ maps (separate from the
|
||||
// metadata indexes) so metadata-only consumers don't pull every component's
|
||||
// dynamic import into their module graph. Lookups mirror getRegistryEntry.
|
||||
function getRegistryComponentEntry(name: string, styleName: string) {
|
||||
const base = getBaseForStyle(styleName)
|
||||
return (
|
||||
StylesComponents[styleName]?.[name] ??
|
||||
(base ? BasesComponents[base]?.[name] : undefined)
|
||||
)
|
||||
}
|
||||
|
||||
export function getDemoComponent(name: string, styleName: string) {
|
||||
const key = getDemoIndexKey(styleName)
|
||||
return ExamplesIndex[key]?.[name]?.component
|
||||
return ExamplesComponents[key]?.[name]
|
||||
}
|
||||
|
||||
export async function getDemoItem(name: string, styleName: string) {
|
||||
@@ -97,7 +111,7 @@ export function getRegistryComponent(name: string, styleName: string) {
|
||||
return demoComponent
|
||||
}
|
||||
|
||||
return getRegistryEntry(name, styleName)?.component
|
||||
return getRegistryComponentEntry(name, styleName)
|
||||
}
|
||||
|
||||
export async function getRegistryItems(
|
||||
|
||||
@@ -7,6 +7,18 @@ const nextConfig = {
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
experimental: {
|
||||
// Rewrite barrel imports to deep imports so a single icon doesn't pull the
|
||||
// whole package into the module graph. Next already optimizes lucide-react,
|
||||
// @tabler/icons-react, date-fns and lodash-es by default; these are the
|
||||
// heavy icon packages this app uses that are NOT on that default list.
|
||||
optimizePackageImports: [
|
||||
"@hugeicons/react",
|
||||
"@hugeicons/core-free-icons",
|
||||
"@phosphor-icons/react",
|
||||
"@remixicon/react",
|
||||
],
|
||||
},
|
||||
outputFileTracingIncludes: {
|
||||
"/*": ["./registry/**/*", "./styles/**/*"],
|
||||
},
|
||||
@@ -29,9 +41,6 @@ const nextConfig = {
|
||||
turbopack: {
|
||||
root: path.resolve(import.meta.dirname, "../.."),
|
||||
},
|
||||
experimental: {
|
||||
turbopackFileSystemCacheForDev: true,
|
||||
},
|
||||
redirects() {
|
||||
return [
|
||||
// Form redirects to /docs/forms.
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
"format:write": "prettier --write \"**/*.{ts,tsx,mdx}\" --cache",
|
||||
"format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache",
|
||||
"icons:dev": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/build-icons.ts --watch",
|
||||
"registry:build": "pnpm --filter=shadcn build && bun run ./scripts/build-registry.mts",
|
||||
"registry:capture": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/capture-registry.mts",
|
||||
"registry:build": "pnpm --filter=shadcn build && bun --conditions=react-server run ./scripts/build-registry.mts",
|
||||
"registry:capture": "tsx --conditions=react-server --tsconfig ./tsconfig.scripts.json ./scripts/capture-registry.mts",
|
||||
"explore:capture": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/capture-explore.mts",
|
||||
"validate:registries": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/validate-registries.mts",
|
||||
"test:apps": "bun run ./scripts/build-test-app.mts",
|
||||
"postinstall": "fumadocs-mdx"
|
||||
},
|
||||
"dependencies": {
|
||||
"@base-ui/react": "1.3.0",
|
||||
"@base-ui/react": "1.5.0",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/modifiers": "^9.0.0",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
@@ -61,7 +61,7 @@
|
||||
"lru-cache": "^11.2.4",
|
||||
"lucide-react": "0.474.0",
|
||||
"motion": "^12.12.1",
|
||||
"next": "16.1.6",
|
||||
"next": "16.2.7",
|
||||
"next-themes": "0.4.6",
|
||||
"nuqs": "^2.8.9",
|
||||
"postcss": "^8.5.1",
|
||||
@@ -77,7 +77,7 @@
|
||||
"rehype-pretty-code": "^0.14.1",
|
||||
"rimraf": "^6.0.1",
|
||||
"server-only": "^0.0.1",
|
||||
"shadcn": "4.8.1",
|
||||
"shadcn": "4.11.0",
|
||||
"shiki": "^1.10.1",
|
||||
"sonner": "^2.0.0",
|
||||
"swr": "^2.3.6",
|
||||
|
||||
BIN
apps/v4/public/images/full-dark.png
Normal file
BIN
apps/v4/public/images/full-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 177 KiB |
BIN
apps/v4/public/images/full-light.png
Normal file
BIN
apps/v4/public/images/full-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 193 KiB |
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-luma/ui/button.tsx",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-luma/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:bg-transparent dark:hover:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5\",\n xs: \"h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n lg: \"h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-luma/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:bg-transparent dark:hover:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5\",\n xs: \"h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n lg: \"h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-luma/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-luma/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-6 overflow-hidden rounded-4xl bg-card py-6 text-sm text-card-foreground shadow-md ring-1 ring-foreground/5 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 dark:ring-foreground/10 *:[img:first-child]:rounded-t-4xl *:[img:last-child]:rounded-b-4xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-t-4xl px-6 group-data-[size=sm]/card:px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-6 group-data-[size=sm]/card:[.border-b]:pb-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6 group-data-[size=sm]/card:px-4\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-4xl px-6 group-data-[size=sm]/card:px-4 [.border-t]:pt-6 group-data-[size=sm]/card:[.border-t]:pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-luma/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-4xl bg-card py-(--card-spacing) text-sm text-card-foreground shadow-md ring-1 ring-foreground/5 [--card-spacing:--spacing(6)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] dark:ring-foreground/10 *:[img:first-child]:rounded-t-4xl *:[img:last-child]:rounded-b-4xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-t-4xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-4xl px-(--card-spacing) [.border-t]:pt-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-luma/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/base-luma/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/base-luma/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-lyra/ui/button.tsx",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-none border border-transparent bg-clip-padding text-xs font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-none px-2 text-xs has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-none px-2.5 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\": \"size-6 rounded-none [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-7 rounded-none\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-none border border-transparent bg-clip-padding text-xs font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-none px-2 text-xs has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-none px-2.5 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\": \"size-6 rounded-none [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-7 rounded-none\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-lyra/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-4 overflow-hidden rounded-none bg-card py-4 text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-2 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-none *:[img:last-child]:rounded-none\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-none px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-sm font-medium group-data-[size=sm]/card:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-xs/relaxed text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-4 group-data-[size=sm]/card:px-3\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-none border-t p-4 group-data-[size=sm]/card:p-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-lyra/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-none bg-card py-(--card-spacing) text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-none *:[img:last-child]:rounded-none\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-none px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-sm font-medium group-data-[size=sm]/card:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-xs/relaxed text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-none border-t p-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-lyra/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/base-lyra/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/base-lyra/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-maia/ui/button.tsx",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-maia/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5\",\n xs: \"h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n lg: \"h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-maia/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5\",\n xs: \"h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n lg: \"h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-maia/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-maia/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-6 overflow-hidden rounded-2xl bg-card py-6 text-sm text-card-foreground ring-1 ring-foreground/10 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-2 rounded-t-xl px-6 group-data-[size=sm]/card:px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-6 group-data-[size=sm]/card:[.border-b]:pb-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6 group-data-[size=sm]/card:px-4\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-xl px-6 group-data-[size=sm]/card:px-4 [.border-t]:pt-6 group-data-[size=sm]/card:[.border-t]:pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-maia/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-2xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(6)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-2 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-xl px-(--card-spacing) [.border-t]:pt-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-maia/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/base-maia/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/base-maia/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-mira/ui/button.tsx",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-mira/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-xs/relaxed font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-7 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n xs: \"h-5 gap-1 rounded-sm px-2 text-[0.625rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-2.5\",\n sm: \"h-6 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n lg: \"h-8 gap-1 px-2.5 text-xs/relaxed has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-4\",\n icon: \"size-7 [&_svg:not([class*='size-'])]:size-3.5\",\n \"icon-xs\": \"size-5 rounded-sm [&_svg:not([class*='size-'])]:size-2.5\",\n \"icon-sm\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-lg\": \"size-8 [&_svg:not([class*='size-'])]:size-4\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-mira/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-xs/relaxed font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-7 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n xs: \"h-5 gap-1 rounded-sm px-2 text-[0.625rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-2.5\",\n sm: \"h-6 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n lg: \"h-8 gap-1 px-2.5 text-xs/relaxed has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-4\",\n icon: \"size-7 [&_svg:not([class*='size-'])]:size-3.5\",\n \"icon-xs\": \"size-5 rounded-sm [&_svg:not([class*='size-'])]:size-2.5\",\n \"icon-sm\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-lg\": \"size-8 [&_svg:not([class*='size-'])]:size-4\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-mira/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-mira/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-4 overflow-hidden rounded-lg bg-card py-4 text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-lg px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-xs/relaxed text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-4 group-data-[size=sm]/card:px-3\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-lg px-4 group-data-[size=sm]/card:px-3 [.border-t]:pt-4 group-data-[size=sm]/card:[.border-t]:pt-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-mira/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-lg bg-card py-(--card-spacing) text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-lg px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-xs/relaxed text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-lg px-(--card-spacing) [.border-t]:pt-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-mira/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/base-mira/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/base-mira/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-nova/ui/button.tsx",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-nova/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-nova/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-nova/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-nova/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-4 group-data-[size=sm]/card:px-3\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/card:p-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-nova/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-nova/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/base-nova/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/base-nova/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-rhea/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-rhea/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-5 overflow-hidden rounded-[min(var(--radius-4xl),24px)] bg-card py-5 text-sm text-card-foreground shadow-sm ring-1 ring-foreground/5 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 dark:ring-foreground/10 *:[img:first-child]:rounded-t-[min(var(--radius-4xl),24px)] *:[img:last-child]:rounded-b-[min(var(--radius-4xl),24px)]\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-t-[min(var(--radius-4xl),24px)] px-5 group-data-[size=sm]/card:px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-5 group-data-[size=sm]/card:[.border-b]:pb-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-5 group-data-[size=sm]/card:px-4\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-[min(var(--radius-4xl),24px)] px-5 group-data-[size=sm]/card:px-4 [.border-t]:pt-5 group-data-[size=sm]/card:[.border-t]:pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-rhea/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-[min(var(--radius-4xl),24px)] bg-card py-(--card-spacing) text-sm text-card-foreground shadow-sm ring-1 ring-foreground/5 [--card-spacing:--spacing(5)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] dark:ring-foreground/10 *:[img:first-child]:rounded-t-[min(var(--radius-4xl),24px)] *:[img:last-child]:rounded-b-[min(var(--radius-4xl),24px)]\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-t-[min(var(--radius-4xl),24px)] px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-[min(var(--radius-4xl),24px)] px-(--card-spacing) [.border-t]:pt-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-rhea/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/base-rhea/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/base-rhea/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-sera/ui/button.tsx",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-sera/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-none border border-transparent bg-clip-padding text-xs font-semibold tracking-widest whitespace-nowrap uppercase transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-transparent hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-10 gap-1.5 px-6 has-data-[icon=inline-end]:pr-4 has-data-[icon=inline-start]:pl-4\",\n xs: \"h-7 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-9 gap-1 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n lg: \"h-11 gap-1.5 px-8 has-data-[icon=inline-end]:pr-5 has-data-[icon=inline-start]:pl-5\",\n icon: \"size-10\",\n \"icon-xs\": \"size-7 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-9\",\n \"icon-lg\": \"size-11\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-sera/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-none border border-transparent bg-clip-padding text-xs font-semibold tracking-widest whitespace-nowrap uppercase transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-transparent hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-10 gap-1.5 px-6 has-data-[icon=inline-end]:pr-4 has-data-[icon=inline-start]:pl-4\",\n xs: \"h-7 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-9 gap-1 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n lg: \"h-11 gap-1.5 px-8 has-data-[icon=inline-end]:pr-5 has-data-[icon=inline-start]:pl-5\",\n icon: \"size-10\",\n \"icon-xs\": \"size-7 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-9\",\n \"icon-lg\": \"size-11\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-sera/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-sera/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-8 overflow-hidden bg-card py-8 text-sm text-card-foreground shadow-sm ring-1 ring-foreground/5 has-[>img:first-child]:pt-0 data-[size=sm]:gap-5 data-[size=sm]:py-5 *:[img:first-child]:rounded-none *:[img:last-child]:rounded-none\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-none px-8 group-data-[size=sm]/card:px-5 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-8 group-data-[size=sm]/card:[.border-b]:pb-5\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-lg font-semibold tracking-wider uppercase\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm leading-relaxed text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-8 group-data-[size=sm]/card:px-5\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center px-8 group-data-[size=sm]/card:px-5 [.border-t]:pt-8 group-data-[size=sm]/card:[.border-t]:pt-5\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-sera/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden bg-card py-(--card-spacing) text-sm text-card-foreground shadow-sm ring-1 ring-foreground/5 [--card-spacing:--spacing(8)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(5)] *:[img:first-child]:rounded-none *:[img:last-child]:rounded-none\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-none px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-lg font-semibold tracking-wider uppercase\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm leading-relaxed text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center px-(--card-spacing) [.border-t]:pt-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-sera/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/base-sera/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/base-sera/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-vega/ui/button.tsx",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-vega/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5\",\n lg: \"h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-9\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/registry/base-vega/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5\",\n lg: \"h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-9\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-vega/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-vega/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-6 overflow-hidden rounded-xl bg-card py-6 text-sm text-card-foreground shadow-xs ring-1 ring-foreground/10 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-6 group-data-[size=sm]/card:px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-6 group-data-[size=sm]/card:[.border-b]:pb-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-base leading-normal font-medium group-data-[size=sm]/card:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6 group-data-[size=sm]/card:px-4\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-xl px-6 group-data-[size=sm]/card:px-4 [.border-t]:pt-6 group-data-[size=sm]/card:[.border-t]:pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/base-vega/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground shadow-xs ring-1 ring-foreground/10 [--card-spacing:--spacing(6)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-base leading-normal font-medium group-data-[size=sm]/card:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-xl px-(--card-spacing) [.border-t]:pt-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/base-vega/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/base-vega/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/base-vega/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-luma/ui/button.tsx",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-luma/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:bg-transparent dark:hover:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5\",\n xs: \"h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n lg: \"h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-luma/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:bg-transparent dark:hover:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5\",\n xs: \"h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n lg: \"h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-luma/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-luma/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-6 overflow-hidden rounded-4xl bg-card py-6 text-sm text-card-foreground shadow-md ring-1 ring-foreground/5 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 dark:ring-foreground/10 *:[img:first-child]:rounded-t-4xl *:[img:last-child]:rounded-b-4xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-t-4xl px-6 group-data-[size=sm]/card:px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-6 group-data-[size=sm]/card:[.border-b]:pb-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6 group-data-[size=sm]/card:px-4\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-4xl px-6 group-data-[size=sm]/card:px-4 [.border-t]:pt-6 group-data-[size=sm]/card:[.border-t]:pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-luma/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-4xl bg-card py-(--card-spacing) text-sm text-card-foreground shadow-md ring-1 ring-foreground/5 [--card-spacing:--spacing(6)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] dark:ring-foreground/10 *:[img:first-child]:rounded-t-4xl *:[img:last-child]:rounded-b-4xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-t-4xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-4xl px-(--card-spacing) [.border-t]:pt-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-luma/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/radix-luma/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/radix-luma/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-lyra/ui/button.tsx",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-lyra/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-none border border-transparent bg-clip-padding text-xs font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-none px-2 text-xs has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-none px-2.5 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\": \"size-6 rounded-none [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-7 rounded-none\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-lyra/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-none border border-transparent bg-clip-padding text-xs font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-none px-2 text-xs has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-none px-2.5 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\": \"size-6 rounded-none [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-7 rounded-none\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-lyra/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-lyra/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-4 overflow-hidden rounded-none bg-card py-4 text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-2 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-none *:[img:last-child]:rounded-none\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-none px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-sm font-medium group-data-[size=sm]/card:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-xs/relaxed text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-4 group-data-[size=sm]/card:px-3\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-none border-t p-4 group-data-[size=sm]/card:p-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-lyra/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-none bg-card py-(--card-spacing) text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-none *:[img:last-child]:rounded-none\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-none px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-sm font-medium group-data-[size=sm]/card:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-xs/relaxed text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-none border-t p-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-lyra/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/radix-lyra/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/radix-lyra/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-maia/ui/button.tsx",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-maia/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5\",\n xs: \"h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n lg: \"h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-maia/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5\",\n xs: \"h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n lg: \"h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-maia/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-maia/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-6 overflow-hidden rounded-2xl bg-card py-6 text-sm text-card-foreground ring-1 ring-foreground/10 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-2 rounded-t-xl px-6 group-data-[size=sm]/card:px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-6 group-data-[size=sm]/card:[.border-b]:pb-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6 group-data-[size=sm]/card:px-4\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-xl px-6 group-data-[size=sm]/card:px-4 [.border-t]:pt-6 group-data-[size=sm]/card:[.border-t]:pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-maia/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-2xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(6)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-2 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-xl px-(--card-spacing) [.border-t]:pt-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-maia/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/radix-maia/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/radix-maia/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-mira/ui/button.tsx",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-mira/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-xs/relaxed font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-7 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n xs: \"h-5 gap-1 rounded-sm px-2 text-[0.625rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-2.5\",\n sm: \"h-6 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n lg: \"h-8 gap-1 px-2.5 text-xs/relaxed has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-4\",\n icon: \"size-7 [&_svg:not([class*='size-'])]:size-3.5\",\n \"icon-xs\": \"size-5 rounded-sm [&_svg:not([class*='size-'])]:size-2.5\",\n \"icon-sm\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-lg\": \"size-8 [&_svg:not([class*='size-'])]:size-4\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-mira/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-xs/relaxed font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-7 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n xs: \"h-5 gap-1 rounded-sm px-2 text-[0.625rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-2.5\",\n sm: \"h-6 gap-1 px-2 text-xs/relaxed has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n lg: \"h-8 gap-1 px-2.5 text-xs/relaxed has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-4\",\n icon: \"size-7 [&_svg:not([class*='size-'])]:size-3.5\",\n \"icon-xs\": \"size-5 rounded-sm [&_svg:not([class*='size-'])]:size-2.5\",\n \"icon-sm\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-lg\": \"size-8 [&_svg:not([class*='size-'])]:size-4\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-mira/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-mira/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-4 overflow-hidden rounded-lg bg-card py-4 text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-lg px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-xs/relaxed text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-4 group-data-[size=sm]/card:px-3\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-lg px-4 group-data-[size=sm]/card:px-3 [.border-t]:pt-4 group-data-[size=sm]/card:[.border-t]:pt-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-mira/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-lg bg-card py-(--card-spacing) text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-lg px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-sm font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-xs/relaxed text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-lg px-(--card-spacing) [.border-t]:pt-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-mira/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/radix-mira/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/radix-mira/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-nova/ui/button.tsx",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-nova/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-nova/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-nova/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-nova/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-4 group-data-[size=sm]/card:px-3\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/card:p-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-nova/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"cn-font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-nova/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/radix-nova/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/radix-nova/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-rhea/ui/card.tsx",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-rhea/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-5 overflow-hidden rounded-[min(var(--radius-4xl),24px)] bg-card py-5 text-sm text-card-foreground shadow-sm ring-1 ring-foreground/5 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 dark:ring-foreground/10 *:[img:first-child]:rounded-t-[min(var(--radius-4xl),24px)] *:[img:last-child]:rounded-b-[min(var(--radius-4xl),24px)]\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-t-[min(var(--radius-4xl),24px)] px-5 group-data-[size=sm]/card:px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-5 group-data-[size=sm]/card:[.border-b]:pb-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-5 group-data-[size=sm]/card:px-4\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-[min(var(--radius-4xl),24px)] px-5 group-data-[size=sm]/card:px-4 [.border-t]:pt-5 group-data-[size=sm]/card:[.border-t]:pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"content": "import * as React from \"react\"\n\nimport { cn } from \"@/registry/radix-rhea/lib/utils\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-[min(var(--radius-4xl),24px)] bg-card py-(--card-spacing) text-sm text-card-foreground shadow-sm ring-1 ring-foreground/5 [--card-spacing:--spacing(5)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] dark:ring-foreground/10 *:[img:first-child]:rounded-t-[min(var(--radius-4xl),24px)] *:[img:last-child]:rounded-b-[min(var(--radius-4xl),24px)]\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-t-[min(var(--radius-4xl),24px)] px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"cn-font-heading text-base font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-(--card-spacing)\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-[min(var(--radius-4xl),24px)] px-(--card-spacing) [.border-t]:pt-(--card-spacing)\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-rhea/ui/spinner.tsx",
|
||||
"content": "import { cn } from \"@/registry/radix-rhea/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"content": "import { cn } from \"@/registry/radix-rhea/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <IconPlaceholder\n lucide=\"Loader2Icon\"\n tabler=\"IconLoader\"\n hugeicons=\"Loading03Icon\"\n phosphor=\"SpinnerIcon\"\n remixicon=\"RiLoaderLine\"\n data-slot=\"spinner\"\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/radix-sera/ui/button.tsx",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-sera/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-none border border-transparent bg-clip-padding text-xs font-semibold tracking-widest whitespace-nowrap uppercase transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-transparent hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-10 gap-1.5 px-6 has-data-[icon=inline-end]:pr-4 has-data-[icon=inline-start]:pl-4\",\n xs: \"h-7 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-9 gap-1 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n lg: \"h-11 gap-1.5 px-8 has-data-[icon=inline-end]:pr-5 has-data-[icon=inline-start]:pl-5\",\n icon: \"size-10\",\n \"icon-xs\": \"size-7 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-9\",\n \"icon-lg\": \"size-11\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/registry/radix-sera/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-none border border-transparent bg-clip-padding text-xs font-semibold tracking-widest whitespace-nowrap uppercase transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-transparent hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-input/30\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-10 gap-1.5 px-6 has-data-[icon=inline-end]:pr-4 has-data-[icon=inline-start]:pl-4\",\n xs: \"h-7 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-9 gap-1 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n lg: \"h-11 gap-1.5 px-8 has-data-[icon=inline-end]:pr-5 has-data-[icon=inline-start]:pl-5\",\n icon: \"size-10\",\n \"icon-xs\": \"size-7 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-9\",\n \"icon-lg\": \"size-11\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
],
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user