commit 610fa90bec4db45a1409a722bee2aa523ff94cab Author: h Date: Tue Sep 22 02:24:49 2026 +0200 feat: init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6cf0b52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +static/r +.DS_Store diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..9573023 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "useTabs": true, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 100, + "plugins": ["prettier-plugin-svelte"], + "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4d8f24c --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +MIT License + +Copyright (c) 2026 h +Copyright (c) 2026 cladd-ui (design tokens, surface system and component styling +ported from https://github.com/cladd-ui/cladd) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1abe036 --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# claddcn-svelte + +The [cladd.io](https://cladd.io) skin for shadcn-svelte. + +## Install into a project + +```bash +# in the root of a shadcn-svelte project +npx git+https://git.kotikot.com/lib/claddcn-svelte.git init --strip-vars +# or +bunx git+https://git.kotikot.com/lib/claddcn-svelte.git init --strip-vars +``` + +`init`: + +1. copies `claddcn.css` next to your Tailwind entry and `@import`s it; +2. `--strip-vars` removes your old `:root` / `.dark` / `@theme inline` token blocks + (claddcn defines every shadcn token, and blocks after the import would win); +3. overwrites `$lib/components/ui/*` with the cladd versions and backs up the old + files to `.claddcn-backup//`; +4. extends `cn()` so tailwind-merge understands `text-cladd-xs`, `h-cladd-md`, etc.; +5. installs `@fontsource-variable/geist` and `geist-mono`, using bun, pnpm, yarn or npm. + +Flags: `--css ` (if components.json points at the wrong CSS), `--only button,card`, `--no-install`, `--dry`. + +As a shadcn-svelte registry: `npx shadcn-svelte registry build` → serve `static/r` +→ `npx shadcn-svelte add https://…/r/button.json`. + +## What you get + +| shadcn-svelte | cladd equivalent | +| ----------------------------- | -------------------------------------------------------- | +| `Button` `default` | brand-tinted gradient surface (the “Get started” button) | +| `outline` / `secondary` | neutral raised gradient, with or without outline | +| `ghost` | transparent, rises to the next surface level on hover | +| `destructive` | red-tinted surface | +| `fill` (new) | solid accent gradient fill | +| `color="green"` (new) | any of the 11 cladd accents on Button / Badge | +| `rounded` (new) | pill shape | +| `Input`, `Textarea` | recessed “cut” well, focus ring floating 4px off | +| `Checkbox` | round thumb, brand fill when checked | +| `Switch` | cladd switch with the × → ✓ indicator | +| `Tabs` | toolbar pill with raised active segment | +| `Select`, menus | 24px-radius popover, pill rows, spring scale-in | +| `Dialog`, `Sheet` | 24px panels, spring pop-in, floating sheet | +| `Tooltip` | small raised surface, no arrow | +| `Surface`, `SurfaceCut` (new) | the cladd primitives, auto-nesting depth | + +### Utility classes for hand-written markup + +`cladd-surface` (+ `cladd-gradient`, `cladd-fill`, `cladd-gradient-fill`, `cladd-outline`), +`cladd-cut`, `cladd-ghost`, `cladd-hoverable`, `cladd-clickable`, `cladd-focusable`, +`cladd-segment` (active via `aria-current="page"` / `data-state="active"`), +`cladd-section-title`, `cladd-color-{neutral,brand,red,pink,purple,blue,cyan,lime,green,yellow,orange}`, +`cladd-level-{1..5}`. + +Tailwind tokens: `bg-cladd-surface`, `bg-cladd-surface-next`, `text-cladd-fg-soft`, +`text-cladd-primary`, `h-cladd-md`, `rounded-cladd-md`, `rounded-cladd-panel`, +`shadow-cladd-outline`, `text-cladd-xs`, … + +Nested `.cladd-surface` elements step one level deeper automatically (1–5). cladd does +this with React context. Here it comes from selector depth, so it also works in plain markup. + +## Requirements + +Tailwind CSS v4, bits-ui v2, tailwind-merge v3, and browsers with relative color +syntax (`oklch(from …)`): Chrome 119+, Safari 18+, Firefox 128+. + +## License + +MIT. Design tokens, surface math and component styling are ported from +[cladd](https://github.com/cladd-ui/cladd) (MIT, © 2026 cladd-ui). diff --git a/bin/claddcn.mjs b/bin/claddcn.mjs new file mode 100755 index 0000000..ebf23ca --- /dev/null +++ b/bin/claddcn.mjs @@ -0,0 +1,211 @@ +#!/usr/bin/env node +// claddcn — puts the cladd.io look onto an existing shadcn-svelte project. +// +// npx claddcn init [--cwd ] [--css ] [--only button,card] [--strip-vars] [--no-install] [--dry] +// +// What `init` does, in order: +// 1. copies claddcn.css next to the Tailwind entry named in components.json +// and imports it right after the other top-level @imports; +// 2. with --strip-vars, removes the old :root / .dark / @theme inline token +// blocks from that file (claddcn ships its own, and later ones would win); +// 3. overwrites ui components with the cladd versions (same names, same API), +// backing up whatever it replaces into .claddcn-backup//; +// 4. teaches `cn()` the cladd scale so tailwind-merge doesn't drop classes; +// 5. adds the Geist / Geist Mono fonts with the project's package manager. + +import { execSync } from 'node:child_process'; +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const REGISTRY_UI = path.join(ROOT, 'registry', 'ui'); +const THEME_CSS = path.join(ROOT, 'src', 'claddcn.css'); +const UTILS_TS = path.join(ROOT, 'registry', 'lib', 'utils.ts'); + +const args = process.argv.slice(2); +const command = args[0]; +const flag = (name) => args.includes(`--${name}`); +const option = (name) => { + const i = args.indexOf(`--${name}`); + return i >= 0 ? args[i + 1] : undefined; +}; + +const cwd = path.resolve(option('cwd') ?? process.cwd()); +const dry = flag('dry'); +const log = (msg) => console.log(`claddcn ${msg}`); + +function write(file, content) { + if (dry) return log(`[dry] write ${path.relative(cwd, file)}`); + fs.mkdirSync(path.dirname(file), { recursive: true }); + fs.writeFileSync(file, content); +} + +function copyDir(src, dest) { + for (const entry of fs.readdirSync(src, { withFileTypes: true })) { + const from = path.join(src, entry.name); + const to = path.join(dest, entry.name); + if (entry.isDirectory()) copyDir(from, to); + else write(to, fs.readFileSync(from)); + } +} + +function resolveAlias(alias, config) { + const lib = config.aliases?.lib ?? '$lib'; + if (alias.startsWith('$lib')) return path.join(cwd, 'src', 'lib', alias.slice('$lib'.length)); + if (alias.startsWith(lib)) return path.join(cwd, 'src', 'lib', alias.slice(lib.length)); + return path.join(cwd, alias); +} + +// Removes a top-level block that starts with `selector {` by brace matching. +function stripBlock(css, selector) { + const re = new RegExp(`(^|\\n)${selector.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*\\{`); + const m = re.exec(css); + if (!m) return css; + let depth = 0; + let i = m.index + m[0].length - 1; + for (; i < css.length; i++) { + if (css[i] === '{') depth++; + else if (css[i] === '}' && --depth === 0) break; + } + return css.slice(0, m.index) + css.slice(i + 1); +} + +// Tailwind entries under src/, i.e. CSS files that `@import 'tailwindcss'`. +function findTailwindEntries(dir = path.join(cwd, 'src'), found = []) { + if (!fs.existsSync(dir)) return found; + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const file = path.join(dir, entry.name); + if (entry.isDirectory()) findTailwindEntries(file, found); + else if ( + entry.name.endsWith('.css') && + entry.name !== 'claddcn.css' && + /^@import ['"]tailwindcss['"]/m.test(fs.readFileSync(file, 'utf8')) + ) + found.push(file); + } + return found; +} + +// --css wins; then components.json; if that path is stale, the single Tailwind +// entry under src/ (or the one that already imports claddcn). +function resolveCss(config) { + if (option('css')) { + const file = path.join(cwd, option('css')); + if (fs.existsSync(file)) return file; + console.error(`claddcn ${option('css')} not found`); + process.exit(1); + } + const configured = path.join(cwd, config.tailwind.css); + if (fs.existsSync(configured)) return configured; + const entries = findTailwindEntries(); + const ours = entries.filter((f) => fs.readFileSync(f, 'utf8').includes('claddcn.css')); + const pick = entries.length === 1 ? entries[0] : ours.length === 1 ? ours[0] : null; + if (pick) { + log(`components.json points at ${config.tailwind.css}, using ${path.relative(cwd, pick)}`); + return pick; + } + console.error(`claddcn ${config.tailwind.css} not found. Pick the Tailwind entry with --css:`); + for (const f of entries) console.error(` --css "${path.relative(cwd, f)}"`); + process.exit(1); +} + +function patchCss(cssFile) { + let css = fs.readFileSync(cssFile, 'utf8'); + if (!css.includes('claddcn.css')) { + const imports = [...css.matchAll(/^@import[^;]+;\s*$/gm)]; + const at = imports.length ? imports.at(-1).index + imports.at(-1)[0].length : 0; + css = `${css.slice(0, at)}\n@import './claddcn.css';${css.slice(at)}`; + log(`import added to ${path.relative(cwd, cssFile)}`); + } + if (flag('strip-vars')) { + for (const selector of [':root', '.dark', '@theme inline']) css = stripBlock(css, selector); + log('old :root / .dark / @theme inline blocks removed'); + } else if (/(^|\n):root\s*\{[^}]*--background/.test(css)) { + log('warning: this file still defines shadcn tokens after the import and will override'); + log(' claddcn colors. Re-run with --strip-vars or delete those blocks by hand.'); + } + write(cssFile, css.replace(/\n{3,}/g, '\n\n')); +} + +function patchUtils(utilsFile) { + if (!fs.existsSync(utilsFile)) return write(utilsFile, fs.readFileSync(UTILS_TS)); + const src = fs.readFileSync(utilsFile, 'utf8'); + if (src.includes('extendTailwindMerge')) return log('cn() already extended, left as is'); + const ours = fs.readFileSync(UTILS_TS, 'utf8'); + const block = ours.slice(0, ours.indexOf('export function cn')); + const next = src.replace( + /import \{ clsx, type ClassValue \} from 'clsx';\s*\nimport \{ twMerge \} from 'tailwind-merge';\s*\n/, + block + ); + if (next === src) { + log( + `warning: couldn't patch ${path.relative(cwd, utilsFile)} — merge registry/lib/utils.ts by hand` + ); + return; + } + write(utilsFile, next); + log('cn() now knows the cladd scale'); +} + +function install() { + const has = (f) => fs.existsSync(path.join(cwd, f)); + const pkg = '@fontsource-variable/geist @fontsource-variable/geist-mono'; + const cmd = + has('bun.lock') || has('bun.lockb') + ? `bun add -d ${pkg}` + : has('pnpm-lock.yaml') + ? `pnpm add -D ${pkg}` + : has('yarn.lock') + ? `yarn add -D ${pkg}` + : `npm i -D ${pkg}`; + if (flag('no-install') || dry) return log(`skip install, run: ${cmd}`); + log(cmd); + execSync(cmd, { cwd, stdio: 'inherit' }); +} + +function init() { + const configFile = path.join(cwd, 'components.json'); + if (!fs.existsSync(configFile)) { + console.error(`claddcn no components.json in ${cwd} — is this a shadcn-svelte project?`); + process.exit(1); + } + const config = JSON.parse(fs.readFileSync(configFile, 'utf8')); + const cssFile = resolveCss(config); + const uiDir = resolveAlias(config.aliases?.ui ?? '$lib/components/ui', config); + const utilsFile = `${resolveAlias(config.aliases?.utils ?? '$lib/utils', config)}.ts`; + + const only = option('only')?.split(','); + const available = fs.readdirSync(REGISTRY_UI); + const components = only ?? available; + const missing = components.filter((c) => !available.includes(c)); + if (missing.length) log(`unknown components skipped: ${missing.join(', ')}`); + + write(path.join(path.dirname(cssFile), 'claddcn.css'), fs.readFileSync(THEME_CSS)); + patchCss(cssFile); + + const stamp = new Date().toISOString().replace(/[:.]/g, '-'); + const backup = path.join(cwd, '.claddcn-backup', stamp); + for (const name of components.filter((c) => available.includes(c))) { + const target = path.join(uiDir, name); + if (fs.existsSync(target) && !dry) { + fs.mkdirSync(backup, { recursive: true }); + fs.cpSync(target, path.join(backup, name), { recursive: true }); + } + copyDir(path.join(REGISTRY_UI, name), target); + } + log(`${components.length} components written to ${path.relative(cwd, uiDir)}`); + if (fs.existsSync(backup)) log(`previous versions saved in ${path.relative(cwd, backup)}`); + + patchUtils(utilsFile); + install(); + log('done — the cladd look is in. Dark mode follows the `.dark` class (mode-watcher).'); +} + +if (command === 'init') init(); +else { + console.log( + `usage: claddcn init [--cwd ] [--css ] [--only a,b] [--strip-vars] [--no-install] [--dry]` + ); + process.exit(command ? 1 : 0); +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..f5b6a60 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "claddcn-svelte", + "version": "0.1.0", + "description": "The cladd.io skin for shadcn-svelte", + "license": "MIT", + "type": "module", + "bin": { + "claddcn": "./bin/claddcn.mjs" + }, + "files": [ + "bin", + "src", + "registry", + "registry.json" + ], + "exports": { + "./css": "./src/claddcn.css" + }, + "scripts": { + "registry:build": "shadcn-svelte registry build" + }, + "peerDependencies": { + "@fontsource-variable/geist": "^5", + "@fontsource-variable/geist-mono": "^5", + "bits-ui": "^2", + "tailwind-merge": "^3", + "tailwindcss": "^4" + } +} diff --git a/registry.json b/registry.json new file mode 100644 index 0000000..1afe452 --- /dev/null +++ b/registry.json @@ -0,0 +1,801 @@ +{ + "$schema": "https://shadcn-svelte.com/schema/registry.json", + "name": "claddcn", + "homepage": "https://cladd.io", + "items": [ + { + "name": "claddcn-theme", + "type": "registry:style", + "title": "claddcn theme", + "description": "cladd.io tokens, surfaces and shadcn variable mapping", + "dependencies": ["@fontsource-variable/geist", "@fontsource-variable/geist-mono"], + "files": [ + { + "path": "src/claddcn.css", + "type": "registry:file", + "target": "src/routes/claddcn.css" + } + ] + }, + { + "name": "utils", + "type": "registry:lib", + "title": "cn() with cladd scale", + "dependencies": ["clsx", "tailwind-merge"], + "files": [ + { + "path": "registry/lib/utils.ts", + "type": "registry:lib" + } + ] + }, + { + "name": "avatar", + "type": "registry:ui", + "title": "avatar", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/avatar/avatar-fallback.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/avatar/avatar-image.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/avatar/avatar.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/avatar/index.ts", + "type": "registry:ui" + } + ] + }, + { + "name": "badge", + "type": "registry:ui", + "title": "badge", + "dependencies": [], + "registryDependencies": ["utils", "button"], + "files": [ + { + "path": "registry/ui/badge/badge.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/badge/index.ts", + "type": "registry:ui" + } + ] + }, + { + "name": "breadcrumb", + "type": "registry:ui", + "title": "breadcrumb", + "dependencies": [], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/breadcrumb/breadcrumb-ellipsis.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/breadcrumb/breadcrumb-item.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/breadcrumb/breadcrumb-link.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/breadcrumb/breadcrumb-list.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/breadcrumb/breadcrumb-page.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/breadcrumb/breadcrumb-separator.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/breadcrumb/breadcrumb.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/breadcrumb/index.ts", + "type": "registry:ui" + } + ] + }, + { + "name": "button", + "type": "registry:ui", + "title": "button", + "dependencies": [], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/button/button.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/button/index.ts", + "type": "registry:ui" + } + ] + }, + { + "name": "card", + "type": "registry:ui", + "title": "card", + "dependencies": [], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/card/card-action.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/card/card-content.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/card/card-description.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/card/card-footer.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/card/card-header.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/card/card-title.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/card/card.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/card/index.ts", + "type": "registry:ui" + } + ] + }, + { + "name": "checkbox", + "type": "registry:ui", + "title": "checkbox", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/checkbox/checkbox.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/checkbox/index.ts", + "type": "registry:ui" + } + ] + }, + { + "name": "collapsible", + "type": "registry:ui", + "title": "collapsible", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/collapsible/collapsible-content.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/collapsible/collapsible-trigger.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/collapsible/collapsible.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/collapsible/index.ts", + "type": "registry:ui" + } + ] + }, + { + "name": "context-menu", + "type": "registry:ui", + "title": "context-menu", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/context-menu/context-menu-checkbox-item.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-content.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-group-heading.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-group.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-item.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-label.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-portal.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-radio-group.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-radio-item.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-separator.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-shortcut.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-sub-content.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-sub-trigger.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-sub.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu-trigger.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/context-menu.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/context-menu/index.ts", + "type": "registry:ui" + } + ] + }, + { + "name": "dialog", + "type": "registry:ui", + "title": "dialog", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/dialog/dialog-close.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dialog/dialog-content.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dialog/dialog-description.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dialog/dialog-footer.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dialog/dialog-header.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dialog/dialog-overlay.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dialog/dialog-portal.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dialog/dialog-title.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dialog/dialog-trigger.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dialog/dialog.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dialog/index.ts", + "type": "registry:ui" + } + ] + }, + { + "name": "dropdown-menu", + "type": "registry:ui", + "title": "dropdown-menu", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-content.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-group-heading.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-group.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-item.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-label.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-portal.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-radio-group.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-radio-item.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-separator.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-shortcut.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-sub-content.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-sub.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu-trigger.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/dropdown-menu.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/dropdown-menu/index.ts", + "type": "registry:ui" + } + ] + }, + { + "name": "input", + "type": "registry:ui", + "title": "input", + "dependencies": [], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/input/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/input/input.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "label", + "type": "registry:ui", + "title": "label", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/label/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/label/label.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "progress", + "type": "registry:ui", + "title": "progress", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/progress/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/progress/progress.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "select", + "type": "registry:ui", + "title": "select", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/select/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/select/select-content.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/select/select-group-heading.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/select/select-group.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/select/select-item.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/select/select-label.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/select/select-portal.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/select/select-scroll-down-button.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/select/select-scroll-up-button.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/select/select-separator.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/select/select-trigger.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/select/select.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "separator", + "type": "registry:ui", + "title": "separator", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/separator/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/separator/separator.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "sheet", + "type": "registry:ui", + "title": "sheet", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/sheet/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/sheet/sheet-close.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/sheet/sheet-content.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/sheet/sheet-description.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/sheet/sheet-footer.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/sheet/sheet-header.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/sheet/sheet-overlay.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/sheet/sheet-portal.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/sheet/sheet-title.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/sheet/sheet-trigger.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/sheet/sheet.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "slider", + "type": "registry:ui", + "title": "slider", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/slider/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/slider/slider.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "sonner", + "type": "registry:ui", + "title": "sonner", + "dependencies": [], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/sonner/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/sonner/sonner.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "surface", + "type": "registry:ui", + "title": "surface", + "dependencies": [], + "registryDependencies": ["utils", "button"], + "files": [ + { + "path": "registry/ui/surface/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/surface/surface-cut.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/surface/surface.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "switch", + "type": "registry:ui", + "title": "switch", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/switch/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/switch/switch.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "table", + "type": "registry:ui", + "title": "table", + "dependencies": [], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/table/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/table/table-body.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/table/table-caption.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/table/table-cell.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/table/table-footer.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/table/table-head.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/table/table-header.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/table/table-row.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/table/table.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "tabs", + "type": "registry:ui", + "title": "tabs", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/tabs/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/tabs/tabs-content.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/tabs/tabs-list.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/tabs/tabs-trigger.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/tabs/tabs.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "textarea", + "type": "registry:ui", + "title": "textarea", + "dependencies": [], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/textarea/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/textarea/textarea.svelte", + "type": "registry:ui" + } + ] + }, + { + "name": "tooltip", + "type": "registry:ui", + "title": "tooltip", + "dependencies": ["bits-ui"], + "registryDependencies": ["utils"], + "files": [ + { + "path": "registry/ui/tooltip/index.ts", + "type": "registry:ui" + }, + { + "path": "registry/ui/tooltip/tooltip-content.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/tooltip/tooltip-portal.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/tooltip/tooltip-provider.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/tooltip/tooltip-trigger.svelte", + "type": "registry:ui" + }, + { + "path": "registry/ui/tooltip/tooltip.svelte", + "type": "registry:ui" + } + ] + } + ] +} diff --git a/registry/lib/utils.ts b/registry/lib/utils.ts new file mode 100644 index 0000000..2fba4f9 --- /dev/null +++ b/registry/lib/utils.ts @@ -0,0 +1,60 @@ +import { clsx, type ClassValue } from 'clsx'; +import { extendTailwindMerge } from 'tailwind-merge'; + +const cladd = (...names: string[]) => names.map((n) => `cladd-${n}`); + +// Teach tailwind-merge the cladd scale, otherwise `text-cladd-xs` (size) and +// `text-cladd-primary` (color) look like the same group and one gets dropped. +const twMerge = extendTailwindMerge({ + extend: { + theme: { + text: cladd('md', 'sm', 'xs', '2xs', '3xs'), + radius: cladd( + '3xs', + '2xs', + 'xs', + 'sm', + 'md', + 'lg', + 'xl', + '2xl', + 'wrap-md', + 'panel', + 'popover', + 'dialog', + 'toast', + 'tooltip' + ), + spacing: cladd( + '3xs', + '2xs', + 'xs', + 'sm', + 'md', + 'lg', + 'xl', + '2xl', + 'thumb-xs', + 'thumb-sm', + 'thumb-md', + 'nested-sm', + 'nested-md', + 'nested-lg' + ), + shadow: cladd('outline', 'outline-fill', 'cut-outline', 'popover') + } + } +}); + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type WithoutChild = T extends { child?: any } ? Omit : T; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type WithoutChildren = T extends { children?: any } ? Omit : T; +export type WithoutChildrenOrChild = WithoutChildren>; +export type WithElementRef = T & { + ref?: U | null; +}; diff --git a/registry/ui/avatar/avatar-fallback.svelte b/registry/ui/avatar/avatar-fallback.svelte new file mode 100644 index 0000000..0623288 --- /dev/null +++ b/registry/ui/avatar/avatar-fallback.svelte @@ -0,0 +1,20 @@ + + + diff --git a/registry/ui/avatar/avatar-image.svelte b/registry/ui/avatar/avatar-image.svelte new file mode 100644 index 0000000..7ccc3ce --- /dev/null +++ b/registry/ui/avatar/avatar-image.svelte @@ -0,0 +1,17 @@ + + + diff --git a/registry/ui/avatar/avatar.svelte b/registry/ui/avatar/avatar.svelte new file mode 100644 index 0000000..37ee335 --- /dev/null +++ b/registry/ui/avatar/avatar.svelte @@ -0,0 +1,22 @@ + + + diff --git a/registry/ui/avatar/index.ts b/registry/ui/avatar/index.ts new file mode 100644 index 0000000..9585f8a --- /dev/null +++ b/registry/ui/avatar/index.ts @@ -0,0 +1,13 @@ +import Root from './avatar.svelte'; +import Image from './avatar-image.svelte'; +import Fallback from './avatar-fallback.svelte'; + +export { + Root, + Image, + Fallback, + // + Root as Avatar, + Image as AvatarImage, + Fallback as AvatarFallback +}; diff --git a/registry/ui/badge/badge.svelte b/registry/ui/badge/badge.svelte new file mode 100644 index 0000000..3c9bff8 --- /dev/null +++ b/registry/ui/badge/badge.svelte @@ -0,0 +1,57 @@ + + + + + + {@render children?.()} + diff --git a/registry/ui/badge/index.ts b/registry/ui/badge/index.ts new file mode 100644 index 0000000..f05fb87 --- /dev/null +++ b/registry/ui/badge/index.ts @@ -0,0 +1,2 @@ +export { default as Badge } from './badge.svelte'; +export { badgeVariants, type BadgeVariant } from './badge.svelte'; diff --git a/registry/ui/breadcrumb/breadcrumb-ellipsis.svelte b/registry/ui/breadcrumb/breadcrumb-ellipsis.svelte new file mode 100644 index 0000000..030197f --- /dev/null +++ b/registry/ui/breadcrumb/breadcrumb-ellipsis.svelte @@ -0,0 +1,23 @@ + + + diff --git a/registry/ui/breadcrumb/breadcrumb-item.svelte b/registry/ui/breadcrumb/breadcrumb-item.svelte new file mode 100644 index 0000000..081b636 --- /dev/null +++ b/registry/ui/breadcrumb/breadcrumb-item.svelte @@ -0,0 +1,20 @@ + + +
  • + {@render children?.()} +
  • diff --git a/registry/ui/breadcrumb/breadcrumb-link.svelte b/registry/ui/breadcrumb/breadcrumb-link.svelte new file mode 100644 index 0000000..c56ab6d --- /dev/null +++ b/registry/ui/breadcrumb/breadcrumb-link.svelte @@ -0,0 +1,31 @@ + + +{#if child} + {@render child({ props: attrs })} +{:else} + + {@render children?.()} + +{/if} diff --git a/registry/ui/breadcrumb/breadcrumb-list.svelte b/registry/ui/breadcrumb/breadcrumb-list.svelte new file mode 100644 index 0000000..bbe948c --- /dev/null +++ b/registry/ui/breadcrumb/breadcrumb-list.svelte @@ -0,0 +1,23 @@ + + +
      + {@render children?.()} +
    diff --git a/registry/ui/breadcrumb/breadcrumb-page.svelte b/registry/ui/breadcrumb/breadcrumb-page.svelte new file mode 100644 index 0000000..a4313fe --- /dev/null +++ b/registry/ui/breadcrumb/breadcrumb-page.svelte @@ -0,0 +1,23 @@ + + + + {@render children?.()} + diff --git a/registry/ui/breadcrumb/breadcrumb-separator.svelte b/registry/ui/breadcrumb/breadcrumb-separator.svelte new file mode 100644 index 0000000..c3b70c6 --- /dev/null +++ b/registry/ui/breadcrumb/breadcrumb-separator.svelte @@ -0,0 +1,27 @@ + + + diff --git a/registry/ui/breadcrumb/breadcrumb.svelte b/registry/ui/breadcrumb/breadcrumb.svelte new file mode 100644 index 0000000..e2d0a3a --- /dev/null +++ b/registry/ui/breadcrumb/breadcrumb.svelte @@ -0,0 +1,21 @@ + + + diff --git a/registry/ui/breadcrumb/index.ts b/registry/ui/breadcrumb/index.ts new file mode 100644 index 0000000..773fd60 --- /dev/null +++ b/registry/ui/breadcrumb/index.ts @@ -0,0 +1,25 @@ +import Root from './breadcrumb.svelte'; +import Ellipsis from './breadcrumb-ellipsis.svelte'; +import Item from './breadcrumb-item.svelte'; +import Separator from './breadcrumb-separator.svelte'; +import Link from './breadcrumb-link.svelte'; +import List from './breadcrumb-list.svelte'; +import Page from './breadcrumb-page.svelte'; + +export { + Root, + Ellipsis, + Item, + Separator, + Link, + List, + Page, + // + Root as Breadcrumb, + Ellipsis as BreadcrumbEllipsis, + Item as BreadcrumbItem, + Separator as BreadcrumbSeparator, + Link as BreadcrumbLink, + List as BreadcrumbList, + Page as BreadcrumbPage +}; diff --git a/registry/ui/button/button.svelte b/registry/ui/button/button.svelte new file mode 100644 index 0000000..d178642 --- /dev/null +++ b/registry/ui/button/button.svelte @@ -0,0 +1,113 @@ + + + + + +{#if href} + + {@render children?.()} + +{:else} + +{/if} diff --git a/registry/ui/button/index.ts b/registry/ui/button/index.ts new file mode 100644 index 0000000..3456886 --- /dev/null +++ b/registry/ui/button/index.ts @@ -0,0 +1,21 @@ +import Root, { + type ButtonProps, + type ButtonSize, + type ButtonVariant, + type CladdColor, + buttonVariants, + withColor +} from './button.svelte'; + +export { + Root, + type ButtonProps as Props, + // + Root as Button, + buttonVariants, + withColor, + type CladdColor, + type ButtonProps, + type ButtonSize, + type ButtonVariant +}; diff --git a/registry/ui/card/card-action.svelte b/registry/ui/card/card-action.svelte new file mode 100644 index 0000000..bbaafd2 --- /dev/null +++ b/registry/ui/card/card-action.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/card/card-content.svelte b/registry/ui/card/card-content.svelte new file mode 100644 index 0000000..dc25f42 --- /dev/null +++ b/registry/ui/card/card-content.svelte @@ -0,0 +1,15 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/card/card-description.svelte b/registry/ui/card/card-description.svelte new file mode 100644 index 0000000..37a2110 --- /dev/null +++ b/registry/ui/card/card-description.svelte @@ -0,0 +1,20 @@ + + +

    + {@render children?.()} +

    diff --git a/registry/ui/card/card-footer.svelte b/registry/ui/card/card-footer.svelte new file mode 100644 index 0000000..1d2751f --- /dev/null +++ b/registry/ui/card/card-footer.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/card/card-header.svelte b/registry/ui/card/card-header.svelte new file mode 100644 index 0000000..3a824e7 --- /dev/null +++ b/registry/ui/card/card-header.svelte @@ -0,0 +1,23 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/card/card-title.svelte b/registry/ui/card/card-title.svelte new file mode 100644 index 0000000..140da83 --- /dev/null +++ b/registry/ui/card/card-title.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/card/card.svelte b/registry/ui/card/card.svelte new file mode 100644 index 0000000..fe98f5b --- /dev/null +++ b/registry/ui/card/card.svelte @@ -0,0 +1,23 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/card/index.ts b/registry/ui/card/index.ts new file mode 100644 index 0000000..77d3674 --- /dev/null +++ b/registry/ui/card/index.ts @@ -0,0 +1,25 @@ +import Root from './card.svelte'; +import Content from './card-content.svelte'; +import Description from './card-description.svelte'; +import Footer from './card-footer.svelte'; +import Header from './card-header.svelte'; +import Title from './card-title.svelte'; +import Action from './card-action.svelte'; + +export { + Root, + Content, + Description, + Footer, + Header, + Title, + Action, + // + Root as Card, + Content as CardContent, + Description as CardDescription, + Footer as CardFooter, + Header as CardHeader, + Title as CardTitle, + Action as CardAction +}; diff --git a/registry/ui/checkbox/checkbox.svelte b/registry/ui/checkbox/checkbox.svelte new file mode 100644 index 0000000..d4f9e72 --- /dev/null +++ b/registry/ui/checkbox/checkbox.svelte @@ -0,0 +1,46 @@ + + + + {#snippet children({ checked, indeterminate })} + + {#if indeterminate} + + {:else} + + {/if} + + {/snippet} + diff --git a/registry/ui/checkbox/index.ts b/registry/ui/checkbox/index.ts new file mode 100644 index 0000000..5c27671 --- /dev/null +++ b/registry/ui/checkbox/index.ts @@ -0,0 +1,6 @@ +import Root from './checkbox.svelte'; +export { + Root, + // + Root as Checkbox +}; diff --git a/registry/ui/collapsible/collapsible-content.svelte b/registry/ui/collapsible/collapsible-content.svelte new file mode 100644 index 0000000..59b068c --- /dev/null +++ b/registry/ui/collapsible/collapsible-content.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/collapsible/collapsible-trigger.svelte b/registry/ui/collapsible/collapsible-trigger.svelte new file mode 100644 index 0000000..c88ceba --- /dev/null +++ b/registry/ui/collapsible/collapsible-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/collapsible/collapsible.svelte b/registry/ui/collapsible/collapsible.svelte new file mode 100644 index 0000000..7a8c5da --- /dev/null +++ b/registry/ui/collapsible/collapsible.svelte @@ -0,0 +1,11 @@ + + + diff --git a/registry/ui/collapsible/index.ts b/registry/ui/collapsible/index.ts new file mode 100644 index 0000000..8181f64 --- /dev/null +++ b/registry/ui/collapsible/index.ts @@ -0,0 +1,13 @@ +import Root from './collapsible.svelte'; +import Trigger from './collapsible-trigger.svelte'; +import Content from './collapsible-content.svelte'; + +export { + Root, + Content, + Trigger, + // + Root as Collapsible, + Content as CollapsibleContent, + Trigger as CollapsibleTrigger +}; diff --git a/registry/ui/context-menu/context-menu-checkbox-item.svelte b/registry/ui/context-menu/context-menu-checkbox-item.svelte new file mode 100644 index 0000000..7d0d156 --- /dev/null +++ b/registry/ui/context-menu/context-menu-checkbox-item.svelte @@ -0,0 +1,38 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/registry/ui/context-menu/context-menu-content.svelte b/registry/ui/context-menu/context-menu-content.svelte new file mode 100644 index 0000000..18a95f2 --- /dev/null +++ b/registry/ui/context-menu/context-menu-content.svelte @@ -0,0 +1,28 @@ + + + + + diff --git a/registry/ui/context-menu/context-menu-group-heading.svelte b/registry/ui/context-menu/context-menu-group-heading.svelte new file mode 100644 index 0000000..c9d538f --- /dev/null +++ b/registry/ui/context-menu/context-menu-group-heading.svelte @@ -0,0 +1,21 @@ + + + diff --git a/registry/ui/context-menu/context-menu-group.svelte b/registry/ui/context-menu/context-menu-group.svelte new file mode 100644 index 0000000..0a5a142 --- /dev/null +++ b/registry/ui/context-menu/context-menu-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/context-menu/context-menu-item.svelte b/registry/ui/context-menu/context-menu-item.svelte new file mode 100644 index 0000000..6c8509d --- /dev/null +++ b/registry/ui/context-menu/context-menu-item.svelte @@ -0,0 +1,27 @@ + + + diff --git a/registry/ui/context-menu/context-menu-label.svelte b/registry/ui/context-menu/context-menu-label.svelte new file mode 100644 index 0000000..54d21b0 --- /dev/null +++ b/registry/ui/context-menu/context-menu-label.svelte @@ -0,0 +1,24 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/context-menu/context-menu-portal.svelte b/registry/ui/context-menu/context-menu-portal.svelte new file mode 100644 index 0000000..d03821a --- /dev/null +++ b/registry/ui/context-menu/context-menu-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/context-menu/context-menu-radio-group.svelte b/registry/ui/context-menu/context-menu-radio-group.svelte new file mode 100644 index 0000000..bd63b9f --- /dev/null +++ b/registry/ui/context-menu/context-menu-radio-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/registry/ui/context-menu/context-menu-radio-item.svelte b/registry/ui/context-menu/context-menu-radio-item.svelte new file mode 100644 index 0000000..70879c9 --- /dev/null +++ b/registry/ui/context-menu/context-menu-radio-item.svelte @@ -0,0 +1,31 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.({ checked })} + {/snippet} + diff --git a/registry/ui/context-menu/context-menu-separator.svelte b/registry/ui/context-menu/context-menu-separator.svelte new file mode 100644 index 0000000..1eaf52b --- /dev/null +++ b/registry/ui/context-menu/context-menu-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/registry/ui/context-menu/context-menu-shortcut.svelte b/registry/ui/context-menu/context-menu-shortcut.svelte new file mode 100644 index 0000000..7423979 --- /dev/null +++ b/registry/ui/context-menu/context-menu-shortcut.svelte @@ -0,0 +1,20 @@ + + + + {@render children?.()} + diff --git a/registry/ui/context-menu/context-menu-sub-content.svelte b/registry/ui/context-menu/context-menu-sub-content.svelte new file mode 100644 index 0000000..1b031a0 --- /dev/null +++ b/registry/ui/context-menu/context-menu-sub-content.svelte @@ -0,0 +1,20 @@ + + + diff --git a/registry/ui/context-menu/context-menu-sub-trigger.svelte b/registry/ui/context-menu/context-menu-sub-trigger.svelte new file mode 100644 index 0000000..2fa5b7b --- /dev/null +++ b/registry/ui/context-menu/context-menu-sub-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/registry/ui/context-menu/context-menu-sub.svelte b/registry/ui/context-menu/context-menu-sub.svelte new file mode 100644 index 0000000..c47f6f3 --- /dev/null +++ b/registry/ui/context-menu/context-menu-sub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/context-menu/context-menu-trigger.svelte b/registry/ui/context-menu/context-menu-trigger.svelte new file mode 100644 index 0000000..063cd50 --- /dev/null +++ b/registry/ui/context-menu/context-menu-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/context-menu/context-menu.svelte b/registry/ui/context-menu/context-menu.svelte new file mode 100644 index 0000000..486e3ad --- /dev/null +++ b/registry/ui/context-menu/context-menu.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/context-menu/index.ts b/registry/ui/context-menu/index.ts new file mode 100644 index 0000000..6c62da9 --- /dev/null +++ b/registry/ui/context-menu/index.ts @@ -0,0 +1,52 @@ +import Root from './context-menu.svelte'; +import Sub from './context-menu-sub.svelte'; +import Portal from './context-menu-portal.svelte'; +import Trigger from './context-menu-trigger.svelte'; +import Group from './context-menu-group.svelte'; +import RadioGroup from './context-menu-radio-group.svelte'; +import Item from './context-menu-item.svelte'; +import GroupHeading from './context-menu-group-heading.svelte'; +import Content from './context-menu-content.svelte'; +import Shortcut from './context-menu-shortcut.svelte'; +import RadioItem from './context-menu-radio-item.svelte'; +import Separator from './context-menu-separator.svelte'; +import SubContent from './context-menu-sub-content.svelte'; +import SubTrigger from './context-menu-sub-trigger.svelte'; +import CheckboxItem from './context-menu-checkbox-item.svelte'; +import Label from './context-menu-label.svelte'; + +export { + Root, + Sub, + Portal, + Item, + GroupHeading, + Label, + Group, + Trigger, + Content, + Shortcut, + Separator, + RadioItem, + SubContent, + SubTrigger, + RadioGroup, + CheckboxItem, + // + Root as ContextMenu, + Sub as ContextMenuSub, + Portal as ContextMenuPortal, + Item as ContextMenuItem, + GroupHeading as ContextMenuGroupHeading, + Group as ContextMenuGroup, + Content as ContextMenuContent, + Trigger as ContextMenuTrigger, + Shortcut as ContextMenuShortcut, + RadioItem as ContextMenuRadioItem, + Separator as ContextMenuSeparator, + RadioGroup as ContextMenuRadioGroup, + SubContent as ContextMenuSubContent, + SubTrigger as ContextMenuSubTrigger, + CheckboxItem as ContextMenuCheckboxItem, + Label as ContextMenuLabel +}; diff --git a/registry/ui/dialog/dialog-close.svelte b/registry/ui/dialog/dialog-close.svelte new file mode 100644 index 0000000..e8a96a7 --- /dev/null +++ b/registry/ui/dialog/dialog-close.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/dialog/dialog-content.svelte b/registry/ui/dialog/dialog-content.svelte new file mode 100644 index 0000000..c9eb98a --- /dev/null +++ b/registry/ui/dialog/dialog-content.svelte @@ -0,0 +1,45 @@ + + + + + + {@render children?.()} + {#if showCloseButton} + + + Close + + {/if} + + diff --git a/registry/ui/dialog/dialog-description.svelte b/registry/ui/dialog/dialog-description.svelte new file mode 100644 index 0000000..631b364 --- /dev/null +++ b/registry/ui/dialog/dialog-description.svelte @@ -0,0 +1,17 @@ + + + diff --git a/registry/ui/dialog/dialog-footer.svelte b/registry/ui/dialog/dialog-footer.svelte new file mode 100644 index 0000000..6ba487f --- /dev/null +++ b/registry/ui/dialog/dialog-footer.svelte @@ -0,0 +1,23 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/dialog/dialog-header.svelte b/registry/ui/dialog/dialog-header.svelte new file mode 100644 index 0000000..bb52355 --- /dev/null +++ b/registry/ui/dialog/dialog-header.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/dialog/dialog-overlay.svelte b/registry/ui/dialog/dialog-overlay.svelte new file mode 100644 index 0000000..f3549bd --- /dev/null +++ b/registry/ui/dialog/dialog-overlay.svelte @@ -0,0 +1,17 @@ + + + diff --git a/registry/ui/dialog/dialog-portal.svelte b/registry/ui/dialog/dialog-portal.svelte new file mode 100644 index 0000000..a60a85e --- /dev/null +++ b/registry/ui/dialog/dialog-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/dialog/dialog-title.svelte b/registry/ui/dialog/dialog-title.svelte new file mode 100644 index 0000000..0ce5977 --- /dev/null +++ b/registry/ui/dialog/dialog-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/registry/ui/dialog/dialog-trigger.svelte b/registry/ui/dialog/dialog-trigger.svelte new file mode 100644 index 0000000..ac04d9f --- /dev/null +++ b/registry/ui/dialog/dialog-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/dialog/dialog.svelte b/registry/ui/dialog/dialog.svelte new file mode 100644 index 0000000..c1444b2 --- /dev/null +++ b/registry/ui/dialog/dialog.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/dialog/index.ts b/registry/ui/dialog/index.ts new file mode 100644 index 0000000..9143f72 --- /dev/null +++ b/registry/ui/dialog/index.ts @@ -0,0 +1,34 @@ +import Root from './dialog.svelte'; +import Portal from './dialog-portal.svelte'; +import Title from './dialog-title.svelte'; +import Footer from './dialog-footer.svelte'; +import Header from './dialog-header.svelte'; +import Overlay from './dialog-overlay.svelte'; +import Content from './dialog-content.svelte'; +import Description from './dialog-description.svelte'; +import Trigger from './dialog-trigger.svelte'; +import Close from './dialog-close.svelte'; + +export { + Root, + Title, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + Close, + // + Root as Dialog, + Title as DialogTitle, + Portal as DialogPortal, + Footer as DialogFooter, + Header as DialogHeader, + Trigger as DialogTrigger, + Overlay as DialogOverlay, + Content as DialogContent, + Description as DialogDescription, + Close as DialogClose +}; diff --git a/registry/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte b/registry/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte new file mode 100644 index 0000000..c0bf94b --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/registry/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte b/registry/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte new file mode 100644 index 0000000..53b7809 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte @@ -0,0 +1,41 @@ + + + + {#snippet children({ checked, indeterminate })} + + {#if indeterminate} + + {:else} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/registry/ui/dropdown-menu/dropdown-menu-content.svelte b/registry/ui/dropdown-menu/dropdown-menu-content.svelte new file mode 100644 index 0000000..8bd0a4b --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-content.svelte @@ -0,0 +1,29 @@ + + + + + diff --git a/registry/ui/dropdown-menu/dropdown-menu-group-heading.svelte b/registry/ui/dropdown-menu/dropdown-menu-group-heading.svelte new file mode 100644 index 0000000..d43323b --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-group-heading.svelte @@ -0,0 +1,22 @@ + + + diff --git a/registry/ui/dropdown-menu/dropdown-menu-group.svelte b/registry/ui/dropdown-menu/dropdown-menu-group.svelte new file mode 100644 index 0000000..261ab7e --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/dropdown-menu/dropdown-menu-item.svelte b/registry/ui/dropdown-menu/dropdown-menu-item.svelte new file mode 100644 index 0000000..0bb8536 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-item.svelte @@ -0,0 +1,28 @@ + + + diff --git a/registry/ui/dropdown-menu/dropdown-menu-label.svelte b/registry/ui/dropdown-menu/dropdown-menu-label.svelte new file mode 100644 index 0000000..0ea90c5 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-label.svelte @@ -0,0 +1,24 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/dropdown-menu/dropdown-menu-portal.svelte b/registry/ui/dropdown-menu/dropdown-menu-portal.svelte new file mode 100644 index 0000000..089a25c --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/dropdown-menu/dropdown-menu-radio-group.svelte b/registry/ui/dropdown-menu/dropdown-menu-radio-group.svelte new file mode 100644 index 0000000..3e98749 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-radio-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/registry/ui/dropdown-menu/dropdown-menu-radio-item.svelte b/registry/ui/dropdown-menu/dropdown-menu-radio-item.svelte new file mode 100644 index 0000000..a2929e1 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-radio-item.svelte @@ -0,0 +1,31 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.({ checked })} + {/snippet} + diff --git a/registry/ui/dropdown-menu/dropdown-menu-separator.svelte b/registry/ui/dropdown-menu/dropdown-menu-separator.svelte new file mode 100644 index 0000000..bb4caf7 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/registry/ui/dropdown-menu/dropdown-menu-shortcut.svelte b/registry/ui/dropdown-menu/dropdown-menu-shortcut.svelte new file mode 100644 index 0000000..dab5255 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-shortcut.svelte @@ -0,0 +1,20 @@ + + + + {@render children?.()} + diff --git a/registry/ui/dropdown-menu/dropdown-menu-sub-content.svelte b/registry/ui/dropdown-menu/dropdown-menu-sub-content.svelte new file mode 100644 index 0000000..7ff9f87 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-sub-content.svelte @@ -0,0 +1,20 @@ + + + diff --git a/registry/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte b/registry/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte new file mode 100644 index 0000000..99d3d23 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/registry/ui/dropdown-menu/dropdown-menu-sub.svelte b/registry/ui/dropdown-menu/dropdown-menu-sub.svelte new file mode 100644 index 0000000..9cfa3b8 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-sub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/dropdown-menu/dropdown-menu-trigger.svelte b/registry/ui/dropdown-menu/dropdown-menu-trigger.svelte new file mode 100644 index 0000000..032b645 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/dropdown-menu/dropdown-menu.svelte b/registry/ui/dropdown-menu/dropdown-menu.svelte new file mode 100644 index 0000000..fbbb790 --- /dev/null +++ b/registry/ui/dropdown-menu/dropdown-menu.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/dropdown-menu/index.ts b/registry/ui/dropdown-menu/index.ts new file mode 100644 index 0000000..b097e3f --- /dev/null +++ b/registry/ui/dropdown-menu/index.ts @@ -0,0 +1,54 @@ +import Root from './dropdown-menu.svelte'; +import Sub from './dropdown-menu-sub.svelte'; +import CheckboxGroup from './dropdown-menu-checkbox-group.svelte'; +import CheckboxItem from './dropdown-menu-checkbox-item.svelte'; +import Content from './dropdown-menu-content.svelte'; +import Group from './dropdown-menu-group.svelte'; +import Item from './dropdown-menu-item.svelte'; +import Label from './dropdown-menu-label.svelte'; +import RadioGroup from './dropdown-menu-radio-group.svelte'; +import RadioItem from './dropdown-menu-radio-item.svelte'; +import Separator from './dropdown-menu-separator.svelte'; +import Shortcut from './dropdown-menu-shortcut.svelte'; +import Trigger from './dropdown-menu-trigger.svelte'; +import SubContent from './dropdown-menu-sub-content.svelte'; +import SubTrigger from './dropdown-menu-sub-trigger.svelte'; +import GroupHeading from './dropdown-menu-group-heading.svelte'; +import Portal from './dropdown-menu-portal.svelte'; + +export { + CheckboxGroup, + CheckboxItem, + Content, + Portal, + Root as DropdownMenu, + CheckboxGroup as DropdownMenuCheckboxGroup, + CheckboxItem as DropdownMenuCheckboxItem, + Content as DropdownMenuContent, + Portal as DropdownMenuPortal, + Group as DropdownMenuGroup, + Item as DropdownMenuItem, + Label as DropdownMenuLabel, + RadioGroup as DropdownMenuRadioGroup, + RadioItem as DropdownMenuRadioItem, + Separator as DropdownMenuSeparator, + Shortcut as DropdownMenuShortcut, + Sub as DropdownMenuSub, + SubContent as DropdownMenuSubContent, + SubTrigger as DropdownMenuSubTrigger, + Trigger as DropdownMenuTrigger, + GroupHeading as DropdownMenuGroupHeading, + Group, + GroupHeading, + Item, + Label, + RadioGroup, + RadioItem, + Root, + Separator, + Shortcut, + Sub, + SubContent, + SubTrigger, + Trigger +}; diff --git a/registry/ui/input/index.ts b/registry/ui/input/index.ts new file mode 100644 index 0000000..15c0933 --- /dev/null +++ b/registry/ui/input/index.ts @@ -0,0 +1,7 @@ +import Root from './input.svelte'; + +export { + Root, + // + Root as Input +}; diff --git a/registry/ui/input/input.svelte b/registry/ui/input/input.svelte new file mode 100644 index 0000000..04e279f --- /dev/null +++ b/registry/ui/input/input.svelte @@ -0,0 +1,48 @@ + + +{#if type === 'file'} + +{:else} + +{/if} diff --git a/registry/ui/label/index.ts b/registry/ui/label/index.ts new file mode 100644 index 0000000..41dd50d --- /dev/null +++ b/registry/ui/label/index.ts @@ -0,0 +1,3 @@ +import Label from './label.svelte'; + +export { Label }; diff --git a/registry/ui/label/label.svelte b/registry/ui/label/label.svelte new file mode 100644 index 0000000..fae6c80 --- /dev/null +++ b/registry/ui/label/label.svelte @@ -0,0 +1,22 @@ + + + + {@render children?.()} + diff --git a/registry/ui/progress/index.ts b/registry/ui/progress/index.ts new file mode 100644 index 0000000..97f57fc --- /dev/null +++ b/registry/ui/progress/index.ts @@ -0,0 +1,7 @@ +import Root from './progress.svelte'; + +export { + Root, + // + Root as Progress +}; diff --git a/registry/ui/progress/progress.svelte b/registry/ui/progress/progress.svelte new file mode 100644 index 0000000..71b561b --- /dev/null +++ b/registry/ui/progress/progress.svelte @@ -0,0 +1,27 @@ + + + +
    +
    diff --git a/registry/ui/select/index.ts b/registry/ui/select/index.ts new file mode 100644 index 0000000..305c47a --- /dev/null +++ b/registry/ui/select/index.ts @@ -0,0 +1,37 @@ +import Root from './select.svelte'; +import Group from './select-group.svelte'; +import Label from './select-label.svelte'; +import Item from './select-item.svelte'; +import Content from './select-content.svelte'; +import Trigger from './select-trigger.svelte'; +import Separator from './select-separator.svelte'; +import ScrollDownButton from './select-scroll-down-button.svelte'; +import ScrollUpButton from './select-scroll-up-button.svelte'; +import GroupHeading from './select-group-heading.svelte'; +import Portal from './select-portal.svelte'; + +export { + Root, + Group, + Label, + Item, + Content, + Trigger, + Separator, + ScrollDownButton, + ScrollUpButton, + GroupHeading, + Portal, + // + Root as Select, + Group as SelectGroup, + Label as SelectLabel, + Item as SelectItem, + Content as SelectContent, + Trigger as SelectTrigger, + Separator as SelectSeparator, + ScrollDownButton as SelectScrollDownButton, + ScrollUpButton as SelectScrollUpButton, + GroupHeading as SelectGroupHeading, + Portal as SelectPortal +}; diff --git a/registry/ui/select/select-content.svelte b/registry/ui/select/select-content.svelte new file mode 100644 index 0000000..65360fe --- /dev/null +++ b/registry/ui/select/select-content.svelte @@ -0,0 +1,45 @@ + + + + + + + {@render children?.()} + + + + diff --git a/registry/ui/select/select-group-heading.svelte b/registry/ui/select/select-group-heading.svelte new file mode 100644 index 0000000..aa6c41c --- /dev/null +++ b/registry/ui/select/select-group-heading.svelte @@ -0,0 +1,21 @@ + + + + {@render children?.()} + diff --git a/registry/ui/select/select-group.svelte b/registry/ui/select/select-group.svelte new file mode 100644 index 0000000..ed67413 --- /dev/null +++ b/registry/ui/select/select-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/select/select-item.svelte b/registry/ui/select/select-item.svelte new file mode 100644 index 0000000..63e3dfe --- /dev/null +++ b/registry/ui/select/select-item.svelte @@ -0,0 +1,38 @@ + + + + {#snippet children({ selected, highlighted })} + + {#if selected} + + {/if} + + {#if childrenProp} + {@render childrenProp({ selected, highlighted })} + {:else} + {label || value} + {/if} + {/snippet} + diff --git a/registry/ui/select/select-label.svelte b/registry/ui/select/select-label.svelte new file mode 100644 index 0000000..d9c910c --- /dev/null +++ b/registry/ui/select/select-label.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/select/select-portal.svelte b/registry/ui/select/select-portal.svelte new file mode 100644 index 0000000..59c4b78 --- /dev/null +++ b/registry/ui/select/select-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/select/select-scroll-down-button.svelte b/registry/ui/select/select-scroll-down-button.svelte new file mode 100644 index 0000000..478d9bd --- /dev/null +++ b/registry/ui/select/select-scroll-down-button.svelte @@ -0,0 +1,20 @@ + + + + + diff --git a/registry/ui/select/select-scroll-up-button.svelte b/registry/ui/select/select-scroll-up-button.svelte new file mode 100644 index 0000000..f17e44f --- /dev/null +++ b/registry/ui/select/select-scroll-up-button.svelte @@ -0,0 +1,20 @@ + + + + + diff --git a/registry/ui/select/select-separator.svelte b/registry/ui/select/select-separator.svelte new file mode 100644 index 0000000..ab5afd0 --- /dev/null +++ b/registry/ui/select/select-separator.svelte @@ -0,0 +1,18 @@ + + + diff --git a/registry/ui/select/select-trigger.svelte b/registry/ui/select/select-trigger.svelte new file mode 100644 index 0000000..76a70f4 --- /dev/null +++ b/registry/ui/select/select-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/registry/ui/select/select.svelte b/registry/ui/select/select.svelte new file mode 100644 index 0000000..b9bf9ba --- /dev/null +++ b/registry/ui/select/select.svelte @@ -0,0 +1,11 @@ + + + diff --git a/registry/ui/separator/index.ts b/registry/ui/separator/index.ts new file mode 100644 index 0000000..768efac --- /dev/null +++ b/registry/ui/separator/index.ts @@ -0,0 +1,7 @@ +import Root from './separator.svelte'; + +export { + Root, + // + Root as Separator +}; diff --git a/registry/ui/separator/separator.svelte b/registry/ui/separator/separator.svelte new file mode 100644 index 0000000..95d7f39 --- /dev/null +++ b/registry/ui/separator/separator.svelte @@ -0,0 +1,21 @@ + + + diff --git a/registry/ui/sheet/index.ts b/registry/ui/sheet/index.ts new file mode 100644 index 0000000..781bc48 --- /dev/null +++ b/registry/ui/sheet/index.ts @@ -0,0 +1,34 @@ +import Root from './sheet.svelte'; +import Portal from './sheet-portal.svelte'; +import Trigger from './sheet-trigger.svelte'; +import Close from './sheet-close.svelte'; +import Overlay from './sheet-overlay.svelte'; +import Content from './sheet-content.svelte'; +import Header from './sheet-header.svelte'; +import Footer from './sheet-footer.svelte'; +import Title from './sheet-title.svelte'; +import Description from './sheet-description.svelte'; + +export { + Root, + Close, + Trigger, + Portal, + Overlay, + Content, + Header, + Footer, + Title, + Description, + // + Root as Sheet, + Close as SheetClose, + Trigger as SheetTrigger, + Portal as SheetPortal, + Overlay as SheetOverlay, + Content as SheetContent, + Header as SheetHeader, + Footer as SheetFooter, + Title as SheetTitle, + Description as SheetDescription +}; diff --git a/registry/ui/sheet/sheet-close.svelte b/registry/ui/sheet/sheet-close.svelte new file mode 100644 index 0000000..b0180c0 --- /dev/null +++ b/registry/ui/sheet/sheet-close.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/sheet/sheet-content.svelte b/registry/ui/sheet/sheet-content.svelte new file mode 100644 index 0000000..0b41ef7 --- /dev/null +++ b/registry/ui/sheet/sheet-content.svelte @@ -0,0 +1,62 @@ + + + + + + + + {@render children?.()} + + + Закрыть + + + diff --git a/registry/ui/sheet/sheet-description.svelte b/registry/ui/sheet/sheet-description.svelte new file mode 100644 index 0000000..d560225 --- /dev/null +++ b/registry/ui/sheet/sheet-description.svelte @@ -0,0 +1,17 @@ + + + diff --git a/registry/ui/sheet/sheet-footer.svelte b/registry/ui/sheet/sheet-footer.svelte new file mode 100644 index 0000000..aea83f7 --- /dev/null +++ b/registry/ui/sheet/sheet-footer.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/sheet/sheet-header.svelte b/registry/ui/sheet/sheet-header.svelte new file mode 100644 index 0000000..00cd281 --- /dev/null +++ b/registry/ui/sheet/sheet-header.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/registry/ui/sheet/sheet-overlay.svelte b/registry/ui/sheet/sheet-overlay.svelte new file mode 100644 index 0000000..55eb7dd --- /dev/null +++ b/registry/ui/sheet/sheet-overlay.svelte @@ -0,0 +1,17 @@ + + + diff --git a/registry/ui/sheet/sheet-portal.svelte b/registry/ui/sheet/sheet-portal.svelte new file mode 100644 index 0000000..91e5178 --- /dev/null +++ b/registry/ui/sheet/sheet-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/sheet/sheet-title.svelte b/registry/ui/sheet/sheet-title.svelte new file mode 100644 index 0000000..aff3e79 --- /dev/null +++ b/registry/ui/sheet/sheet-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/registry/ui/sheet/sheet-trigger.svelte b/registry/ui/sheet/sheet-trigger.svelte new file mode 100644 index 0000000..d95719a --- /dev/null +++ b/registry/ui/sheet/sheet-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/sheet/sheet.svelte b/registry/ui/sheet/sheet.svelte new file mode 100644 index 0000000..d65b76b --- /dev/null +++ b/registry/ui/sheet/sheet.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/slider/index.ts b/registry/ui/slider/index.ts new file mode 100644 index 0000000..f1524fc --- /dev/null +++ b/registry/ui/slider/index.ts @@ -0,0 +1,7 @@ +import Root from './slider.svelte'; + +export { + Root, + // + Root as Slider +}; diff --git a/registry/ui/slider/slider.svelte b/registry/ui/slider/slider.svelte new file mode 100644 index 0000000..9db32fd --- /dev/null +++ b/registry/ui/slider/slider.svelte @@ -0,0 +1,52 @@ + + + + + {#snippet children({ thumbs })} + + + + {#each thumbs as thumb (thumb)} + + {/each} + {/snippet} + diff --git a/registry/ui/sonner/index.ts b/registry/ui/sonner/index.ts new file mode 100644 index 0000000..fcaf06b --- /dev/null +++ b/registry/ui/sonner/index.ts @@ -0,0 +1 @@ +export { default as Toaster } from './sonner.svelte'; diff --git a/registry/ui/sonner/sonner.svelte b/registry/ui/sonner/sonner.svelte new file mode 100644 index 0000000..5e46435 --- /dev/null +++ b/registry/ui/sonner/sonner.svelte @@ -0,0 +1,51 @@ + + +{#snippet loadingIcon()} + + {/snippet} + {#snippet successIcon()} + + {/snippet} + {#snippet errorIcon()} + + {/snippet} + {#snippet infoIcon()} + + {/snippet} + {#snippet warningIcon()} + + {/snippet} + diff --git a/registry/ui/surface/index.ts b/registry/ui/surface/index.ts new file mode 100644 index 0000000..2fca05a --- /dev/null +++ b/registry/ui/surface/index.ts @@ -0,0 +1,5 @@ +import Root from './surface.svelte'; +import Cut from './surface-cut.svelte'; + +export { Root, Cut, Root as Surface, Cut as SurfaceCut }; +export type { SurfaceProps, SurfaceVariant } from './surface.svelte'; diff --git a/registry/ui/surface/surface-cut.svelte b/registry/ui/surface/surface-cut.svelte new file mode 100644 index 0000000..68afae9 --- /dev/null +++ b/registry/ui/surface/surface-cut.svelte @@ -0,0 +1,38 @@ + + + + + {@render children?.()} + diff --git a/registry/ui/surface/surface.svelte b/registry/ui/surface/surface.svelte new file mode 100644 index 0000000..7338d83 --- /dev/null +++ b/registry/ui/surface/surface.svelte @@ -0,0 +1,66 @@ + + + + + + + {@render children?.()} + diff --git a/registry/ui/switch/index.ts b/registry/ui/switch/index.ts new file mode 100644 index 0000000..129f8f5 --- /dev/null +++ b/registry/ui/switch/index.ts @@ -0,0 +1,7 @@ +import Root from './switch.svelte'; + +export { + Root, + // + Root as Switch +}; diff --git a/registry/ui/switch/switch.svelte b/registry/ui/switch/switch.svelte new file mode 100644 index 0000000..916166b --- /dev/null +++ b/registry/ui/switch/switch.svelte @@ -0,0 +1,59 @@ + + + + + {#snippet child({ props })} + + + + + + + + {/snippet} + + diff --git a/registry/ui/table/index.ts b/registry/ui/table/index.ts new file mode 100644 index 0000000..99239ae --- /dev/null +++ b/registry/ui/table/index.ts @@ -0,0 +1,28 @@ +import Root from './table.svelte'; +import Body from './table-body.svelte'; +import Caption from './table-caption.svelte'; +import Cell from './table-cell.svelte'; +import Footer from './table-footer.svelte'; +import Head from './table-head.svelte'; +import Header from './table-header.svelte'; +import Row from './table-row.svelte'; + +export { + Root, + Body, + Caption, + Cell, + Footer, + Head, + Header, + Row, + // + Root as Table, + Body as TableBody, + Caption as TableCaption, + Cell as TableCell, + Footer as TableFooter, + Head as TableHead, + Header as TableHeader, + Row as TableRow +}; diff --git a/registry/ui/table/table-body.svelte b/registry/ui/table/table-body.svelte new file mode 100644 index 0000000..cf720f4 --- /dev/null +++ b/registry/ui/table/table-body.svelte @@ -0,0 +1,20 @@ + + + + {@render children?.()} + diff --git a/registry/ui/table/table-caption.svelte b/registry/ui/table/table-caption.svelte new file mode 100644 index 0000000..1c9c3ec --- /dev/null +++ b/registry/ui/table/table-caption.svelte @@ -0,0 +1,20 @@ + + + + {@render children?.()} + diff --git a/registry/ui/table/table-cell.svelte b/registry/ui/table/table-cell.svelte new file mode 100644 index 0000000..654f2f2 --- /dev/null +++ b/registry/ui/table/table-cell.svelte @@ -0,0 +1,23 @@ + + + + {@render children?.()} + diff --git a/registry/ui/table/table-footer.svelte b/registry/ui/table/table-footer.svelte new file mode 100644 index 0000000..51b7517 --- /dev/null +++ b/registry/ui/table/table-footer.svelte @@ -0,0 +1,23 @@ + + +tr]:last:border-b-0', + className + )} + {...restProps} +> + {@render children?.()} + diff --git a/registry/ui/table/table-head.svelte b/registry/ui/table/table-head.svelte new file mode 100644 index 0000000..5cf4ac7 --- /dev/null +++ b/registry/ui/table/table-head.svelte @@ -0,0 +1,23 @@ + + + + {@render children?.()} + diff --git a/registry/ui/table/table-header.svelte b/registry/ui/table/table-header.svelte new file mode 100644 index 0000000..2fbc6f8 --- /dev/null +++ b/registry/ui/table/table-header.svelte @@ -0,0 +1,23 @@ + + + + {@render children?.()} + diff --git a/registry/ui/table/table-row.svelte b/registry/ui/table/table-row.svelte new file mode 100644 index 0000000..62ac26b --- /dev/null +++ b/registry/ui/table/table-row.svelte @@ -0,0 +1,23 @@ + + +svelte-css-wrapper]:[&>th,td]:bg-cladd-surface-hover', + className + )} + {...restProps} +> + {@render children?.()} + diff --git a/registry/ui/table/table.svelte b/registry/ui/table/table.svelte new file mode 100644 index 0000000..a8d5347 --- /dev/null +++ b/registry/ui/table/table.svelte @@ -0,0 +1,22 @@ + + +
    + + {@render children?.()} +
    +
    diff --git a/registry/ui/tabs/index.ts b/registry/ui/tabs/index.ts new file mode 100644 index 0000000..d2a7939 --- /dev/null +++ b/registry/ui/tabs/index.ts @@ -0,0 +1,16 @@ +import Root from './tabs.svelte'; +import Content from './tabs-content.svelte'; +import List from './tabs-list.svelte'; +import Trigger from './tabs-trigger.svelte'; + +export { + Root, + Content, + List, + Trigger, + // + Root as Tabs, + Content as TabsContent, + List as TabsList, + Trigger as TabsTrigger +}; diff --git a/registry/ui/tabs/tabs-content.svelte b/registry/ui/tabs/tabs-content.svelte new file mode 100644 index 0000000..92044c8 --- /dev/null +++ b/registry/ui/tabs/tabs-content.svelte @@ -0,0 +1,17 @@ + + + diff --git a/registry/ui/tabs/tabs-list.svelte b/registry/ui/tabs/tabs-list.svelte new file mode 100644 index 0000000..aac8012 --- /dev/null +++ b/registry/ui/tabs/tabs-list.svelte @@ -0,0 +1,16 @@ + + + diff --git a/registry/ui/tabs/tabs-trigger.svelte b/registry/ui/tabs/tabs-trigger.svelte new file mode 100644 index 0000000..3463e87 --- /dev/null +++ b/registry/ui/tabs/tabs-trigger.svelte @@ -0,0 +1,20 @@ + + + diff --git a/registry/ui/tabs/tabs.svelte b/registry/ui/tabs/tabs.svelte new file mode 100644 index 0000000..b275bda --- /dev/null +++ b/registry/ui/tabs/tabs.svelte @@ -0,0 +1,19 @@ + + + diff --git a/registry/ui/textarea/index.ts b/registry/ui/textarea/index.ts new file mode 100644 index 0000000..9ccb3bf --- /dev/null +++ b/registry/ui/textarea/index.ts @@ -0,0 +1,7 @@ +import Root from './textarea.svelte'; + +export { + Root, + // + Root as Textarea +}; diff --git a/registry/ui/textarea/textarea.svelte b/registry/ui/textarea/textarea.svelte new file mode 100644 index 0000000..92373d5 --- /dev/null +++ b/registry/ui/textarea/textarea.svelte @@ -0,0 +1,23 @@ + + + diff --git a/registry/ui/tooltip/index.ts b/registry/ui/tooltip/index.ts new file mode 100644 index 0000000..809e219 --- /dev/null +++ b/registry/ui/tooltip/index.ts @@ -0,0 +1,19 @@ +import Root from './tooltip.svelte'; +import Trigger from './tooltip-trigger.svelte'; +import Content from './tooltip-content.svelte'; +import Provider from './tooltip-provider.svelte'; +import Portal from './tooltip-portal.svelte'; + +export { + Root, + Trigger, + Content, + Provider, + Portal, + // + Root as Tooltip, + Content as TooltipContent, + Trigger as TooltipTrigger, + Provider as TooltipProvider, + Portal as TooltipPortal +}; diff --git a/registry/ui/tooltip/tooltip-content.svelte b/registry/ui/tooltip/tooltip-content.svelte new file mode 100644 index 0000000..906acd7 --- /dev/null +++ b/registry/ui/tooltip/tooltip-content.svelte @@ -0,0 +1,35 @@ + + + + + {@render children?.()} + + diff --git a/registry/ui/tooltip/tooltip-portal.svelte b/registry/ui/tooltip/tooltip-portal.svelte new file mode 100644 index 0000000..7d328f0 --- /dev/null +++ b/registry/ui/tooltip/tooltip-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/tooltip/tooltip-provider.svelte b/registry/ui/tooltip/tooltip-provider.svelte new file mode 100644 index 0000000..b3bb5b7 --- /dev/null +++ b/registry/ui/tooltip/tooltip-provider.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/tooltip/tooltip-trigger.svelte b/registry/ui/tooltip/tooltip-trigger.svelte new file mode 100644 index 0000000..5631d1b --- /dev/null +++ b/registry/ui/tooltip/tooltip-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/registry/ui/tooltip/tooltip.svelte b/registry/ui/tooltip/tooltip.svelte new file mode 100644 index 0000000..7c9d712 --- /dev/null +++ b/registry/ui/tooltip/tooltip.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/claddcn.css b/src/claddcn.css new file mode 100644 index 0000000..a794a30 --- /dev/null +++ b/src/claddcn.css @@ -0,0 +1,796 @@ +/* +claddcn — the cladd.io visual system as a shadcn-svelte theme. +Tokens, surfaces and color math ported from cladd (MIT, © 2026 cladd-ui, +https://github.com/cladd-ui/cladd). Adapted to the shadcn convention: +light on :root, dark under `.dark`. + +Import after tailwindcss: + @import 'tailwindcss'; + @import 'tw-animate-css'; + @import './claddcn.css'; +*/ + +@import '@fontsource-variable/geist/index.css'; +@import '@fontsource-variable/geist-mono/index.css'; + +@property --cladd-overlay { + syntax: ''; + inherits: false; + initial-value: transparent; +} + +/* ───────────────────────── accents ───────────────────────── */ + +:root, +.cladd-color-neutral { + --cladd-theme: #fff; +} +.cladd-color-brand { + --cladd-theme: #388aff; +} +.cladd-color-red { + --cladd-theme: #ff0b0b; +} +.cladd-color-pink { + --cladd-theme: #ff0bac; +} +.cladd-color-purple { + --cladd-theme: #a20bff; +} +.cladd-color-blue { + --cladd-theme: #0047ff; +} +.cladd-color-cyan { + --cladd-theme: #00f9ff; +} +.cladd-color-lime { + --cladd-theme: #7dff0b; +} +.cladd-color-green { + --cladd-theme: #0bff23; +} +.cladd-color-yellow { + --cladd-theme: #fff800; +} +.cladd-color-orange { + --cladd-theme: #ff7a00; +} + +/* ───────────────────────── neutral light ───────────────────────── */ + +:root, +.cladd-color-neutral { + --cladd-bg: #fff; + --cladd-backdrop: oklch(0.91 0 0); + --cladd-primary: oklch(0.1 0 0); + --cladd-on-primary: oklch(0.96 0 0); + --cladd-surface: oklch(0.97 0 0); + --cladd-surface-cut: oklch(0.93 0 0); + --cladd-fg: oklch(0.32 0 0); + --cladd-fg-soft: oklch(0.5 0 0); + --cladd-fg-softer: oklch(0.65 0 0); + --cladd-fg-softest: oklch(0.75 0 0); + --cladd-surface-white: oklch(1 0 0); + --cladd-surface-black: oklch(0 0 0); + --cladd-bg-outline: oklch(0.89 0 0); + --cladd-outline: oklch(0.89 0 0); + --cladd-surface-hover: color-mix(in oklab, var(--cladd-surface-black) 3%, transparent); + --cladd-surface-pressed: color-mix(in oklab, var(--cladd-surface-white) 6%, transparent); + --cladd-surface-hover-fill: color-mix(in oklab, var(--cladd-surface-white) 20%, transparent); + --cladd-surface-mix-color: var(--cladd-surface-black); + --cladd-surface-mix-amount: 4%; + --cladd-highlight-mix: 50%; + --cladd-fill-fade: 20%; + + --shadow-cladd-cut-outline: + 0.5px 0.5px 0px 0px color-mix(in oklab, var(--cladd-surface-black) 10%, transparent) inset, + 0px 0px 0px 0.5px color-mix(in oklab, var(--cladd-surface-black) 5%, transparent) inset; + --shadow-cladd-outline-fill: + 0px 0px 0px 0.5px color-mix(in oklab, var(--cladd-surface-black) 20%, transparent) inset, + 1px 1px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 30%, transparent) inset; + --shadow-cladd-outline: + 0px 0px 0px 1px var(--color-cladd-outline) inset, + 1.5px 1.5px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 60%, transparent) inset; + --shadow-cladd-popover: 0 24px 64px -12px rgb(0 0 0 / 0.18); +} + +/* ───────────────────────── neutral dark ───────────────────────── */ + +.dark, +.dark .cladd-color-neutral { + --cladd-bg: #0f0f0f; + --cladd-backdrop: #000; + --cladd-primary: oklch(0.95 0 0); + --cladd-on-primary: oklch(0.2 0 0); + --cladd-surface: oklch(0.21 0 0); + --cladd-surface-cut: oklch(0.19 0 0); + --cladd-fg: oklch(0.9 0 0); + --cladd-fg-soft: oklch(0.65 0 0); + --cladd-fg-softer: oklch(0.5 0 0); + --cladd-fg-softest: oklch(0.4 0 0); + --cladd-surface-white: oklch(1 0 0); + --cladd-surface-black: oklch(0 0 0); + --cladd-bg-outline: oklch(0.23 0 0); + --cladd-outline: oklch(0.3 0 0); + --cladd-surface-hover: color-mix(in oklab, var(--cladd-surface-white) 5%, transparent); + --cladd-surface-pressed: color-mix(in oklab, var(--cladd-surface-white) 3%, transparent); + --cladd-surface-hover-fill: color-mix(in oklab, var(--cladd-surface-white) 20%, transparent); + --cladd-surface-mix-color: var(--cladd-surface-white); + --cladd-surface-mix-amount: 6%; + --cladd-highlight-mix: 3%; + --cladd-fill-fade: 15%; + + --shadow-cladd-cut-outline: + -1px -1px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 2%, transparent) inset, + 0px 0px 0px 1px color-mix(in oklab, var(--cladd-surface-white) 7%, transparent) inset; + --shadow-cladd-outline: + 1px 1px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 8%, transparent) inset, + -1px -1px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 7%, transparent) inset; + --shadow-cladd-outline-fill: + 1px 1px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 20%, transparent) inset, + -1px -1px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 20%, transparent) inset; + --shadow-cladd-popover: 0 24px 64px -12px rgb(0 0 0 / 0.5); +} + +/* ───────────────────────── colored light ───────────────────────── */ + +[class*='cladd-color-']:not(.cladd-color-neutral) { + --cladd-bg: oklch(from var(--cladd-theme) 1 0.015 h); + --cladd-backdrop: oklch(0.74 0.018 100); + --cladd-primary: oklch(from var(--cladd-theme) 0.5 0.18 h); + --cladd-on-primary: oklch(from var(--cladd-theme) 0.97 0.04 h); + --cladd-surface: oklch(from var(--cladd-theme) 0.97 0.015 h); + --cladd-surface-cut: oklch(from var(--cladd-theme) 0.93 0.02 h); + --cladd-fg: oklch(from var(--cladd-theme) 0.25 0.015 h); + --cladd-fg-soft: oklch(from var(--cladd-theme) 0.5 0.025 h); + --cladd-fg-softer: oklch(from var(--cladd-theme) 0.65 0.025 h); + --cladd-fg-softest: oklch(from var(--cladd-theme) 0.75 0.025 h); + --cladd-surface-white: oklch(from var(--cladd-theme) 0.98 0.04 h); + --cladd-surface-black: oklch(from var(--cladd-theme) 0.4 0.07 h); + --cladd-bg-outline: oklch(from var(--cladd-theme) 0.74 0.03 h); + --cladd-outline: oklch(from var(--cladd-theme) 0.88 0.025 h); + --cladd-surface-hover: color-mix(in oklab, var(--cladd-surface-black) 6%, transparent); + --cladd-surface-hover-fill: color-mix(in oklab, var(--cladd-surface-white) 10%, transparent); + --cladd-surface-pressed: color-mix(in oklab, var(--cladd-surface-white) 6%, transparent); + --cladd-surface-mix-amount: 5%; + --cladd-surface-mix-color: var(--cladd-surface-black); + + --shadow-cladd-cut-outline: + 0.5px 0.5px 0px 0px color-mix(in oklab, var(--cladd-surface-black) 10%, transparent) inset, + 0px 0px 0px 0.5px color-mix(in oklab, var(--cladd-surface-black) 5%, transparent) inset; + --shadow-cladd-outline-fill: + 0px 0px 0px 1px color-mix(in oklab, var(--cladd-surface-black) 40%, transparent) inset, + 1px 1px 0px 0.25px color-mix(in oklab, var(--cladd-surface-white) 30%, transparent) inset; + --shadow-cladd-outline: + 0px 0px 0px 1px var(--color-cladd-outline) inset, + 1.5px 1.5px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 80%, transparent) inset; +} + +/* ───────────────────────── colored dark ───────────────────────── */ + +.dark [class*='cladd-color-']:not(.cladd-color-neutral), +.dark[class*='cladd-color-']:not(.cladd-color-neutral) { + --cladd-bg: oklch(from var(--cladd-theme) 0.18 0.02 h); + --cladd-backdrop: #000; + --cladd-primary: oklch(from var(--cladd-theme) 0.95 0.18 h); + --cladd-on-primary: oklch(from var(--cladd-theme) 0.2 0.05 h); + --cladd-surface: oklch(from var(--cladd-theme) 0.23 0.027 h); + --cladd-surface-cut: oklch(from var(--cladd-theme) 0.19 0.027 h); + --cladd-fg: oklch(from var(--cladd-theme) 0.9 0.04 h); + --cladd-fg-soft: oklch(from var(--cladd-theme) 0.65 0.04 h); + --cladd-fg-softer: oklch(from var(--cladd-theme) 0.5 0.04 h); + --cladd-fg-softest: oklch(from var(--cladd-theme) 0.4 0.04 h); + --cladd-surface-white: oklch(from var(--cladd-theme) 0.92 0.05 h); + --cladd-surface-black: oklch(from var(--cladd-theme) 0.08 0.02 h); + --cladd-bg-outline: oklch(from var(--cladd-theme) 0.25 0.02 h); + --cladd-outline: oklch(from var(--cladd-theme) 0.28 0.025 h); + --cladd-surface-hover: color-mix(in oklab, var(--cladd-surface-white) 5%, transparent); + --cladd-surface-pressed: color-mix(in oklab, var(--cladd-surface-white) 3%, transparent); + --cladd-surface-hover-fill: color-mix(in oklab, var(--cladd-surface-white) 40%, transparent); + --cladd-surface-mix-color: var(--cladd-surface-white); + --cladd-surface-mix-amount: 6%; + + --shadow-cladd-cut-outline: + -1px -1px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 2%, transparent) inset, + 0px 0px 0px 1px color-mix(in oklab, var(--cladd-surface-white) 7%, transparent) inset; + --shadow-cladd-outline: + 1px 1px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 8%, transparent) inset, + -1px -1px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 7%, transparent) inset; + --shadow-cladd-outline-fill: + 1px 1px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 30%, transparent) inset, + -1px -1px 0px 0px color-mix(in oklab, var(--cladd-surface-white) 30%, transparent) inset; +} + +/* ───────────────────────── surface levels ───────────────────────── +Every .cladd-surface nested inside another bumps one level (up to 5), the same +auto-nesting cladd does with React context, done here with selector depth. */ + +.cladd-surface { + --cladd-surface-multiplier: 0; +} +.cladd-surface .cladd-surface { + --cladd-surface-multiplier: 1; +} +.cladd-surface .cladd-surface .cladd-surface { + --cladd-surface-multiplier: 2; +} +.cladd-surface .cladd-surface .cladd-surface .cladd-surface { + --cladd-surface-multiplier: 3; +} +.cladd-surface .cladd-surface .cladd-surface .cladd-surface .cladd-surface { + --cladd-surface-multiplier: 4; +} +.cladd-level-1.cladd-level-1.cladd-level-1.cladd-level-1.cladd-level-1.cladd-level-1 { + --cladd-surface-multiplier: 0; +} +.cladd-level-2.cladd-level-2.cladd-level-2.cladd-level-2.cladd-level-2.cladd-level-2 { + --cladd-surface-multiplier: 1; +} +.cladd-level-3.cladd-level-3.cladd-level-3.cladd-level-3.cladd-level-3.cladd-level-3 { + --cladd-surface-multiplier: 2; +} +.cladd-level-4.cladd-level-4.cladd-level-4.cladd-level-4.cladd-level-4.cladd-level-4 { + --cladd-surface-multiplier: 3; +} +.cladd-level-5.cladd-level-5.cladd-level-5.cladd-level-5.cladd-level-5.cladd-level-5 { + --cladd-surface-multiplier: 4; +} + +:root, +.dark, +.cladd-surface, +.cladd-cut, +[class*='cladd-level-'], +[class*='cladd-color-'] { + --cladd-step: calc(var(--cladd-surface-mix-amount) * var(--cladd-surface-multiplier, 0)); + --color-cladd-bg: var(--cladd-bg); + --color-cladd-backdrop: var(--cladd-backdrop); + --color-cladd-primary: var(--cladd-primary); + --color-cladd-on-primary: var(--cladd-on-primary); + --color-cladd-surface-white: var(--cladd-surface-white); + --color-cladd-surface-black: var(--cladd-surface-black); + --color-cladd-surface-hover: var(--cladd-surface-hover); + --color-cladd-surface-hover-fill: var(--cladd-surface-hover-fill); + --color-cladd-surface-pressed: var(--cladd-surface-pressed); + --color-cladd-bg-outline: var(--cladd-bg-outline); + --color-cladd-surface: color-mix( + in oklab, + var(--cladd-surface-mix-color) var(--cladd-step), + var(--cladd-surface) + ); + --color-cladd-surface-prev: color-mix( + in oklab, + var(--cladd-surface-mix-color) + calc(var(--cladd-surface-mix-amount) * (var(--cladd-surface-multiplier, 0) - 1)), + var(--cladd-surface) + ); + --color-cladd-surface-next: color-mix( + in oklab, + var(--cladd-surface-mix-color) + calc(var(--cladd-surface-mix-amount) * (var(--cladd-surface-multiplier, 0) + 1)), + var(--cladd-surface) + ); + --color-cladd-surface-cut: color-mix( + in oklab, + var(--cladd-surface-mix-color) var(--cladd-step), + var(--cladd-surface-cut) + ); + --color-cladd-outline: color-mix( + in oklab, + var(--cladd-surface-mix-color) var(--cladd-step), + var(--cladd-outline) + ); + --color-cladd-fg: var(--cladd-fg); + --color-cladd-fg-soft: color-mix( + in oklab, + var(--cladd-surface-mix-color) var(--cladd-step), + var(--cladd-fg-soft) + ); + --color-cladd-fg-softer: color-mix( + in oklab, + var(--cladd-surface-mix-color) var(--cladd-step), + var(--cladd-fg-softer) + ); + --color-cladd-fg-softest: color-mix( + in oklab, + var(--cladd-surface-mix-color) var(--cladd-step), + var(--cladd-fg-softest) + ); + --color-cladd-surface-highlight: color-mix( + in oklab, + var(--cladd-surface-white) var(--cladd-highlight-mix), + var(--color-cladd-surface) + ); +} + +/* ───────────────────────── tailwind tokens ───────────────────────── */ + +@theme { + --color-cladd-bg: var(--cladd-bg); + --color-cladd-backdrop: var(--cladd-backdrop); + --color-cladd-primary: var(--cladd-primary); + --color-cladd-on-primary: var(--cladd-on-primary); + --color-cladd-surface: var(--cladd-surface); + --color-cladd-surface-cut: var(--cladd-surface-cut); + --color-cladd-surface-prev: var(--cladd-surface); + --color-cladd-surface-next: var(--cladd-surface); + --color-cladd-surface-highlight: var(--cladd-surface); + --color-cladd-surface-white: var(--cladd-surface-white); + --color-cladd-surface-black: var(--cladd-surface-black); + --color-cladd-surface-hover: var(--cladd-surface-hover); + --color-cladd-surface-hover-fill: var(--cladd-surface-hover-fill); + --color-cladd-surface-pressed: var(--cladd-surface-pressed); + --color-cladd-fg: var(--cladd-fg); + --color-cladd-fg-soft: var(--cladd-fg-soft); + --color-cladd-fg-softer: var(--cladd-fg-softer); + --color-cladd-fg-softest: var(--cladd-fg-softest); + --color-cladd-bg-outline: var(--cladd-bg-outline); + --color-cladd-outline: var(--cladd-outline); + + --shadow-cladd-outline: var(--shadow-cladd-outline); + --shadow-cladd-outline-fill: var(--shadow-cladd-outline-fill); + --shadow-cladd-cut-outline: var(--shadow-cladd-cut-outline); + --shadow-cladd-popover: var(--shadow-cladd-popover); + + --spacing-cladd-3xs: 12px; + --spacing-cladd-2xs: 16px; + --spacing-cladd-xs: 20px; + --spacing-cladd-sm: 24px; + --spacing-cladd-md: 28px; + --spacing-cladd-lg: 32px; + --spacing-cladd-xl: 40px; + --spacing-cladd-2xl: 48px; + --spacing-cladd-thumb-xs: 16px; + --spacing-cladd-thumb-sm: 20px; + --spacing-cladd-thumb-md: 24px; + --spacing-cladd-nested-sm: 16px; + --spacing-cladd-nested-md: 20px; + --spacing-cladd-nested-lg: 24px; + + --cladd-radius: 8px; + --radius-cladd: var(--cladd-radius); + --radius-cladd-3xs: calc(var(--cladd-radius) * 12 / 28); + --radius-cladd-2xs: calc(var(--cladd-radius) * 16 / 28); + --radius-cladd-xs: calc(var(--cladd-radius) * 20 / 28); + --radius-cladd-sm: calc(var(--cladd-radius) * 24 / 28); + --radius-cladd-md: var(--cladd-radius); + --radius-cladd-lg: calc(var(--cladd-radius) * 32 / 28); + --radius-cladd-xl: calc(var(--cladd-radius) * 40 / 28); + --radius-cladd-2xl: calc(var(--cladd-radius) * 48 / 28); + --radius-cladd-wrap-md: calc(var(--cladd-radius) + 4px); + --radius-cladd-panel: 24px; + --radius-cladd-popover: 24px; + --radius-cladd-dialog: 24px; + --radius-cladd-toast: 24px; + --radius-cladd-tooltip: 12px; + + --text-cladd-md: 16px; + --text-cladd-sm: 14px; + --text-cladd-xs: 12px; + --text-cladd-2xs: 10px; + --text-cladd-3xs: 8px; + + --ease-cladd-spring: cubic-bezier(0, 1, 0.2, 1.1); + --ease-cladd-pop: cubic-bezier(0, 1, 0, 1.025); + --animate-cladd-spinner: cladd-spinner 1.5s infinite linear; + + @keyframes cladd-spinner { + to { + transform: rotate(360deg); + } + } +} + +/* ───────────────────────── shadcn mapping ───────────────────────── +Every shadcn-svelte token resolves to a cladd token, so plain shadcn markup +(bg-card, text-muted-foreground, border…) picks up the cladd palette too. */ + +:root { + --radius: 8px; + --background: var(--cladd-bg); + --foreground: var(--cladd-fg); + --card: var(--cladd-surface); + --card-foreground: var(--cladd-fg); + --popover: color-mix(in oklab, var(--cladd-surface-white) 50%, var(--cladd-surface)); + --popover-foreground: var(--cladd-fg); + --primary: var(--cladd-primary); + --primary-foreground: var(--cladd-on-primary); + --secondary: var(--cladd-surface); + --secondary-foreground: var(--cladd-fg); + --muted: var(--cladd-surface-cut); + --muted-foreground: var(--cladd-fg-soft); + --accent: color-mix( + in oklab, + var(--cladd-surface-mix-color) var(--cladd-surface-mix-amount), + var(--cladd-surface) + ); + --accent-foreground: var(--cladd-fg); + --border: var(--cladd-bg-outline); + --input: var(--cladd-outline); + + --brand: oklch(from #388aff 0.5 0.18 h); + --brand-foreground: oklch(from #388aff 0.97 0.04 h); + --brand-soft: oklch(from #388aff 0.95 0.03 h); + --destructive: oklch(from #ff0b0b 0.55 0.2 h); + --destructive-foreground: oklch(from #ff0b0b 0.97 0.04 h); + --success: oklch(from #0bff23 0.5 0.15 h); + --success-soft: oklch(from #0bff23 0.95 0.04 h); + --warning: oklch(from #ff7a00 0.58 0.15 h); + --warning-soft: oklch(from #fff800 0.96 0.05 h); + --ring: var(--brand); + + --chart-1: var(--brand); + --chart-2: var(--success); + --chart-3: var(--cladd-fg-soft); + --chart-4: oklch(from #00f9ff 0.6 0.12 h); + --chart-5: var(--destructive); + + --sidebar: var(--cladd-surface); + --sidebar-foreground: var(--cladd-fg); + --sidebar-primary: var(--brand); + --sidebar-primary-foreground: var(--brand-foreground); + --sidebar-accent: color-mix( + in oklab, + var(--cladd-surface-mix-color) var(--cladd-surface-mix-amount), + var(--cladd-surface) + ); + --sidebar-accent-foreground: var(--cladd-fg); + --sidebar-border: var(--cladd-bg-outline); + --sidebar-ring: var(--brand); +} + +.dark { + --popover: color-mix(in oklab, var(--cladd-surface-white) 12%, var(--cladd-surface)); + --brand: oklch(from #388aff 0.85 0.13 h); + --brand-foreground: oklch(from #388aff 0.2 0.05 h); + --brand-soft: oklch(from #388aff 0.23 0.027 h); + --destructive: oklch(from #ff0b0b 0.75 0.16 h); + --destructive-foreground: oklch(from #ff0b0b 0.2 0.05 h); + --success: oklch(from #0bff23 0.82 0.17 h); + --success-soft: oklch(from #0bff23 0.23 0.027 h); + --warning: oklch(from #fff800 0.88 0.16 h); + --warning-soft: oklch(from #fff800 0.23 0.027 h); +} + +@theme inline { + --font-sans: 'Geist Variable', 'Geist', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; + --font-mono: 'Geist Mono Variable', 'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace; + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-brand: var(--brand); + --color-brand-foreground: var(--brand-foreground); + --color-brand-soft: var(--brand-soft); + --color-success: var(--success); + --color-success-soft: var(--success-soft); + --color-warning: var(--warning); + --color-warning-soft: var(--warning-soft); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +/* ───────────────────────── surfaces ───────────────────────── +Background is two layers over a base color: the hover/press overlay on top and +the diagonal sheen below it. Base color stays a plain background-color, so a +`bg-*` utility on a component recolors it without losing the cladd finish. */ + +@layer components { + .cladd-surface, + .cladd-cut, + .cladd-ghost { + --cladd-sheen: linear-gradient(transparent, transparent); + background-color: var(--color-cladd-surface); + background-image: + linear-gradient(var(--cladd-overlay), var(--cladd-overlay)), var(--cladd-sheen); + transition-property: + --cladd-overlay, background-color, color, box-shadow, opacity, scale, outline-color, + outline-offset; + transition-duration: 200ms; + transition-timing-function: ease; + } + + .cladd-gradient { + --cladd-sheen: linear-gradient( + to bottom right, + color-mix(in oklab, var(--cladd-surface-white) var(--cladd-highlight-mix), transparent), + transparent + ); + } + + /* `cladd-fill-checked` turns into a gradient fill while bits-ui marks it checked/on. */ + .cladd-fill, + .cladd-gradient-fill, + .cladd-fill-checked:is([data-state='checked'], [data-state='indeterminate']) { + background-color: var(--color-cladd-primary); + color: var(--color-cladd-on-primary); + } + .cladd-gradient-fill, + .cladd-fill-checked:is([data-state='checked'], [data-state='indeterminate']) { + --cladd-sheen: linear-gradient( + to bottom right, + transparent, + color-mix(in oklab, var(--color-cladd-surface) var(--cladd-fill-fade), transparent) + ); + } + :root:not(.dark) + :is( + .cladd-gradient-fill, + .cladd-fill-checked:is([data-state='checked'], [data-state='indeterminate']) + ) { + --cladd-sheen: linear-gradient( + to bottom right, + color-mix(in oklab, var(--cladd-surface-white) var(--cladd-fill-fade), transparent), + transparent + ); + } + + .cladd-outline { + box-shadow: var(--shadow-cladd-outline); + } + .cladd-outline:is(.cladd-fill, .cladd-gradient-fill), + .cladd-outline.cladd-fill-checked:is([data-state='checked'], [data-state='indeterminate']) { + box-shadow: var(--shadow-cladd-outline-fill); + } + + .cladd-cut { + background-color: var(--color-cladd-surface-cut); + box-shadow: var(--shadow-cladd-cut-outline); + } + + .cladd-ghost { + background-color: transparent; + box-shadow: none; + } + + @media (hover: hover) { + .cladd-hoverable:hover { + --cladd-overlay: var(--color-cladd-surface-hover); + } + .cladd-hoverable:is(.cladd-fill, .cladd-gradient-fill):hover, + .cladd-hoverable.cladd-fill-checked:is( + [data-state='checked'], + [data-state='indeterminate'] + ):hover { + --cladd-overlay: var(--color-cladd-surface-hover-fill); + } + .cladd-ghost.cladd-hoverable:hover { + --cladd-overlay: transparent; + background-color: var(--color-cladd-surface); + } + } + + .cladd-clickable:active:not(:has(.cladd-clickable:active)), + .cladd-pressed { + --cladd-overlay: var(--color-cladd-surface-pressed); + } + .cladd-ghost.cladd-pressed, + .cladd-ghost.cladd-clickable:active { + background-color: var(--color-cladd-surface); + } + .cladd-clickable:active:not(:has(.cladd-clickable:active)) > *, + .cladd-press-content:active > * { + scale: 0.95; + opacity: 0.75; + } + .cladd-clickable > * { + transition: + scale 200ms ease, + opacity 200ms ease; + } + + /* Button content inherits the host's flex layout, so `justify-between`, `gap-*` + and friends on