feat: init
This commit is contained in:
commit
610fa90bec
147 files changed
+4979
No files matched your search
@@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
static/r
|
||||||
|
.DS_Store
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"useTabs": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"printWidth": 100,
|
||||||
|
"plugins": ["prettier-plugin-svelte"],
|
||||||
|
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
@@ -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/<timestamp>/`;
|
||||||
|
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 <file>` (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).
|
||||||
Executable
+211
@@ -0,0 +1,211 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
// claddcn — puts the cladd.io look onto an existing shadcn-svelte project.
|
||||||
|
//
|
||||||
|
// npx claddcn init [--cwd <dir>] [--css <file>] [--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/<timestamp>/;
|
||||||
|
// 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 <dir>] [--css <file>] [--only a,b] [--strip-vars] [--no-install] [--dry]`
|
||||||
|
);
|
||||||
|
process.exit(command ? 1 : 0);
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
+801
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -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> = T extends { child?: any } ? Omit<T, 'child'> : T;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, 'children'> : T;
|
||||||
|
export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
|
||||||
|
export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & {
|
||||||
|
ref?: U | null;
|
||||||
|
};
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Avatar as AvatarPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: AvatarPrimitive.FallbackProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AvatarPrimitive.Fallback
|
||||||
|
bind:ref
|
||||||
|
data-slot="avatar-fallback"
|
||||||
|
class={cn(
|
||||||
|
'flex size-full items-center justify-center rounded-full text-cladd-xs font-semibold text-cladd-fg-soft uppercase',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Avatar as AvatarPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: AvatarPrimitive.ImageProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AvatarPrimitive.Image
|
||||||
|
bind:ref
|
||||||
|
data-slot="avatar-image"
|
||||||
|
class={cn('aspect-square size-full', className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Avatar as AvatarPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
loadingStatus = $bindable('loading'),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: AvatarPrimitive.RootProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AvatarPrimitive.Root
|
||||||
|
bind:ref
|
||||||
|
bind:loadingStatus
|
||||||
|
data-slot="avatar"
|
||||||
|
class={cn(
|
||||||
|
'cladd-surface cladd-gradient cladd-outline relative flex size-cladd-lg shrink-0 overflow-hidden rounded-full',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -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
|
||||||
|
};
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<script lang="ts" module>
|
||||||
|
import { type VariantProps, tv } from 'tailwind-variants';
|
||||||
|
|
||||||
|
export const badgeVariants = tv({
|
||||||
|
base: 'cladd-surface inline-flex h-cladd-nested-md w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-cladd-sm px-2 text-cladd-xs leading-none font-semibold whitespace-nowrap select-none has-[>svg:first-child]:ps-1.5 has-[>svg:last-child]:pe-1.5 [&>svg]:pointer-events-none [&>svg]:size-3',
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: 'cladd-gradient cladd-outline cladd-color-brand text-cladd-primary',
|
||||||
|
secondary: 'cladd-gradient cladd-outline text-cladd-fg',
|
||||||
|
destructive: 'cladd-gradient cladd-outline cladd-color-red text-cladd-primary',
|
||||||
|
success: 'cladd-gradient cladd-outline cladd-color-green text-cladd-primary',
|
||||||
|
warning: 'cladd-gradient cladd-outline cladd-color-yellow text-cladd-primary',
|
||||||
|
outline: 'cladd-ghost shadow-cladd-outline text-cladd-fg',
|
||||||
|
fill: 'cladd-gradient-fill cladd-outline cladd-color-brand'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: 'default'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export type BadgeVariant = VariantProps<typeof badgeVariants>['variant'];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAnchorAttributes } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
import { withColor, type CladdColor } from '../button/button.svelte';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
href,
|
||||||
|
class: className,
|
||||||
|
variant = 'default',
|
||||||
|
color,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAnchorAttributes> & {
|
||||||
|
variant?: BadgeVariant;
|
||||||
|
color?: CladdColor;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:element
|
||||||
|
this={href ? 'a' : 'span'}
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="badge"
|
||||||
|
{href}
|
||||||
|
class={cn(
|
||||||
|
withColor(badgeVariants({ variant }), color),
|
||||||
|
href && 'cladd-hoverable cladd-focusable',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</svelte:element>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export { default as Badge } from './badge.svelte';
|
||||||
|
export { badgeVariants, type BadgeVariant } from './badge.svelte';
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import EllipsisIcon from '@lucide/svelte/icons/ellipsis';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef, type WithoutChildren } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChildren<WithElementRef<HTMLAttributes<HTMLSpanElement>>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="breadcrumb-ellipsis"
|
||||||
|
role="presentation"
|
||||||
|
aria-hidden="true"
|
||||||
|
class={cn('flex size-9 items-center justify-center', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
<EllipsisIcon class="size-4" />
|
||||||
|
<span class="sr-only">More</span>
|
||||||
|
</span>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLLiAttributes } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLLiAttributes> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<li
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="breadcrumb-item"
|
||||||
|
class={cn('inline-flex items-center gap-1.5', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</li>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAnchorAttributes } from 'svelte/elements';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
href = undefined,
|
||||||
|
child,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAnchorAttributes> & {
|
||||||
|
child?: Snippet<[{ props: HTMLAnchorAttributes }]>;
|
||||||
|
} = $props();
|
||||||
|
|
||||||
|
const attrs = $derived({
|
||||||
|
'data-slot': 'breadcrumb-link',
|
||||||
|
class: cn('hover:text-foreground transition-colors', className),
|
||||||
|
href,
|
||||||
|
...restProps
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if child}
|
||||||
|
{@render child({ props: attrs })}
|
||||||
|
{:else}
|
||||||
|
<a bind:this={ref} {...attrs}>
|
||||||
|
{@render children?.()}
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLOlAttributes } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLOlAttributes> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ol
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="breadcrumb-list"
|
||||||
|
class={cn(
|
||||||
|
'flex flex-wrap items-center gap-1.5 text-cladd-xs font-medium break-words text-cladd-fg-soft sm:gap-2.5',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</ol>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="breadcrumb-page"
|
||||||
|
role="link"
|
||||||
|
aria-disabled="true"
|
||||||
|
aria-current="page"
|
||||||
|
class={cn('font-medium text-cladd-fg', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</span>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import ChevronRightIcon from '@lucide/svelte/icons/chevron-right';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
import type { HTMLLiAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLLiAttributes> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<li
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="breadcrumb-separator"
|
||||||
|
role="presentation"
|
||||||
|
aria-hidden="true"
|
||||||
|
class={cn('[&>svg]:size-3.5', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{#if children}
|
||||||
|
{@render children?.()}
|
||||||
|
{:else}
|
||||||
|
<ChevronRightIcon />
|
||||||
|
{/if}
|
||||||
|
</li>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { WithElementRef } from '$lib/utils.js';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<nav
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="breadcrumb"
|
||||||
|
class={className}
|
||||||
|
aria-label="хлебные крошки"
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</nav>
|
||||||
@@ -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
|
||||||
|
};
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
<script lang="ts" module>
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
||||||
|
import { type VariantProps, tv } from 'tailwind-variants';
|
||||||
|
|
||||||
|
export type CladdColor =
|
||||||
|
| 'neutral'
|
||||||
|
| 'brand'
|
||||||
|
| 'red'
|
||||||
|
| 'pink'
|
||||||
|
| 'purple'
|
||||||
|
| 'blue'
|
||||||
|
| 'cyan'
|
||||||
|
| 'lime'
|
||||||
|
| 'green'
|
||||||
|
| 'yellow'
|
||||||
|
| 'orange';
|
||||||
|
|
||||||
|
export const buttonVariants = tv({
|
||||||
|
base: "cladd-clickable cladd-focusable relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 font-semibold whitespace-nowrap select-none disabled:pointer-events-none disabled:*:opacity-40 aria-disabled:pointer-events-none aria-disabled:*:opacity-40 aria-invalid:outline-destructive [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default:
|
||||||
|
'cladd-surface cladd-gradient cladd-outline cladd-hoverable cladd-color-brand text-cladd-primary',
|
||||||
|
destructive:
|
||||||
|
'cladd-surface cladd-gradient cladd-outline cladd-hoverable cladd-color-red text-cladd-primary',
|
||||||
|
outline: 'cladd-surface cladd-gradient cladd-outline cladd-hoverable text-cladd-fg',
|
||||||
|
secondary: 'cladd-surface cladd-gradient cladd-hoverable text-cladd-fg',
|
||||||
|
ghost: 'cladd-ghost cladd-hoverable text-cladd-fg',
|
||||||
|
fill: 'cladd-surface cladd-gradient-fill cladd-outline cladd-hoverable',
|
||||||
|
link: 'text-cladd-primary cladd-color-brand underline-offset-4 hover:underline'
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
default: 'h-cladd-md rounded-cladd-md px-2.5 text-cladd-xs',
|
||||||
|
xs: 'h-cladd-xs gap-1.5 rounded-cladd-xs px-2 text-cladd-xs [&_svg:not([class*=size-])]:size-3',
|
||||||
|
sm: 'h-cladd-sm gap-1.5 rounded-cladd-sm px-2.5 text-cladd-xs',
|
||||||
|
lg: 'h-cladd-lg rounded-cladd-lg px-3 text-cladd-xs',
|
||||||
|
xl: 'h-cladd-xl rounded-cladd-xl px-3.5 text-cladd-sm',
|
||||||
|
icon: 'size-cladd-md rounded-cladd-md',
|
||||||
|
'icon-xs': 'size-cladd-xs rounded-cladd-xs [&_svg:not([class*=size-])]:size-3',
|
||||||
|
'icon-sm': 'size-cladd-sm rounded-cladd-sm',
|
||||||
|
'icon-lg': 'size-cladd-lg rounded-cladd-lg'
|
||||||
|
},
|
||||||
|
rounded: {
|
||||||
|
true: 'rounded-full',
|
||||||
|
false: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
compoundVariants: [{ variant: 'link', class: 'h-auto px-0 rounded-none' }],
|
||||||
|
defaultVariants: {
|
||||||
|
variant: 'default',
|
||||||
|
size: 'default',
|
||||||
|
rounded: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Swaps the variant's accent for an explicit one: `<Button color="green">`. */
|
||||||
|
export function withColor(classes: string, color?: CladdColor) {
|
||||||
|
if (!color) return classes;
|
||||||
|
return `${classes.replace(/\bcladd-color-\w+/g, '')} cladd-color-${color}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ButtonVariant = VariantProps<typeof buttonVariants>['variant'];
|
||||||
|
export type ButtonSize = VariantProps<typeof buttonVariants>['size'];
|
||||||
|
|
||||||
|
export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
|
||||||
|
WithElementRef<HTMLAnchorAttributes> & {
|
||||||
|
variant?: ButtonVariant;
|
||||||
|
size?: ButtonSize;
|
||||||
|
rounded?: boolean;
|
||||||
|
color?: CladdColor;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
let {
|
||||||
|
class: className,
|
||||||
|
variant = 'default',
|
||||||
|
size = 'default',
|
||||||
|
rounded = false,
|
||||||
|
color,
|
||||||
|
ref = $bindable(null),
|
||||||
|
href = undefined,
|
||||||
|
type = 'button',
|
||||||
|
disabled,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: ButtonProps = $props();
|
||||||
|
|
||||||
|
const classes = $derived(
|
||||||
|
cn(withColor(buttonVariants({ variant, size, rounded }), color), className)
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Content sits in its own box so the press can shrink it while the surface stays put. -->
|
||||||
|
{#if href}
|
||||||
|
<a
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="button"
|
||||||
|
class={classes}
|
||||||
|
href={disabled ? undefined : href}
|
||||||
|
aria-disabled={disabled}
|
||||||
|
role={disabled ? 'link' : undefined}
|
||||||
|
tabindex={disabled ? -1 : undefined}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
<span data-slot="button-content" class="cladd-button-content">{@render children?.()}</span>
|
||||||
|
</a>
|
||||||
|
{:else}
|
||||||
|
<button bind:this={ref} data-slot="button" class={classes} {type} {disabled} {...restProps}>
|
||||||
|
<span data-slot="button-content" class="cladd-button-content">{@render children?.()}</span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
@@ -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
|
||||||
|
};
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="card-action"
|
||||||
|
class={cn('col-start-2 row-span-2 row-start-1 self-start justify-self-end', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div bind:this={ref} data-slot="card-content" class={cn('px-4', className)} {...restProps}>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLParagraphElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="card-description"
|
||||||
|
class={cn('text-cladd-xs leading-relaxed text-cladd-fg-soft', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</p>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="card-footer"
|
||||||
|
class={cn('flex items-center gap-2 px-4 [.border-t]:pt-4', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="card-header"
|
||||||
|
class={cn(
|
||||||
|
'@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1 px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-4',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="card-title"
|
||||||
|
class={cn('text-cladd-sm leading-tight font-semibold', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="card"
|
||||||
|
class={cn(
|
||||||
|
'cladd-surface cladd-outline flex flex-col gap-4 rounded-cladd-panel py-4 text-cladd-fg *:[form]:flex *:[form]:flex-col *:[form]:gap-4',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
@@ -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
|
||||||
|
};
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Checkbox as CheckboxPrimitive } from 'bits-ui';
|
||||||
|
import CheckIcon from '@lucide/svelte/icons/check';
|
||||||
|
import MinusIcon from '@lucide/svelte/icons/minus';
|
||||||
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
checked = $bindable(false),
|
||||||
|
indeterminate = $bindable(false),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChildrenOrChild<CheckboxPrimitive.RootProps> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CheckboxPrimitive.Root
|
||||||
|
bind:ref
|
||||||
|
data-slot="checkbox"
|
||||||
|
class={cn(
|
||||||
|
'peer group/checkbox cladd-surface cladd-gradient cladd-outline cladd-hoverable cladd-clickable cladd-focusable relative flex size-cladd-thumb-sm shrink-0 items-center justify-center rounded-full text-cladd-fg-soft disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:outline-destructive',
|
||||||
|
'cladd-fill-checked',
|
||||||
|
(checked || indeterminate) && 'cladd-color-brand',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
bind:checked
|
||||||
|
bind:indeterminate
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{#snippet children({ checked, indeterminate })}
|
||||||
|
<span
|
||||||
|
data-slot="checkbox-indicator"
|
||||||
|
class={cn(
|
||||||
|
'flex items-center justify-center transition-[scale,color] duration-200',
|
||||||
|
checked || indeterminate
|
||||||
|
? 'text-cladd-on-primary group-active/checkbox:scale-90'
|
||||||
|
: 'scale-75 group-active/checkbox:scale-65'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{#if indeterminate}
|
||||||
|
<MinusIcon class="size-3" strokeWidth={3} />
|
||||||
|
{:else}
|
||||||
|
<CheckIcon class="size-3" strokeWidth={3} />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{/snippet}
|
||||||
|
</CheckboxPrimitive.Root>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import Root from './checkbox.svelte';
|
||||||
|
export {
|
||||||
|
Root,
|
||||||
|
//
|
||||||
|
Root as Checkbox
|
||||||
|
};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Collapsible as CollapsiblePrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: CollapsiblePrimitive.ContentProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CollapsiblePrimitive.Content bind:ref data-slot="collapsible-content" {...restProps} />
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Collapsible as CollapsiblePrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: CollapsiblePrimitive.TriggerProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CollapsiblePrimitive.Trigger bind:ref data-slot="collapsible-trigger" {...restProps} />
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Collapsible as CollapsiblePrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
open = $bindable(false),
|
||||||
|
...restProps
|
||||||
|
}: CollapsiblePrimitive.RootProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CollapsiblePrimitive.Root bind:ref bind:open data-slot="collapsible" {...restProps} />
|
||||||
@@ -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
|
||||||
|
};
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
import CheckIcon from '@lucide/svelte/icons/check';
|
||||||
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
checked = $bindable(false),
|
||||||
|
indeterminate = $bindable(false),
|
||||||
|
class: className,
|
||||||
|
children: childrenProp,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChildrenOrChild<ContextMenuPrimitive.CheckboxItemProps> & {
|
||||||
|
children?: Snippet;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.CheckboxItem
|
||||||
|
bind:ref
|
||||||
|
bind:checked
|
||||||
|
bind:indeterminate
|
||||||
|
data-slot="context-menu-checkbox-item"
|
||||||
|
class={cn(
|
||||||
|
"relative flex min-h-cladd-lg cursor-default items-center gap-2 rounded-full py-1 ps-9 pe-3 text-cladd-xs font-medium outline-hidden transition-[background-color,box-shadow] duration-200 select-none data-highlighted:bg-cladd-surface-next data-[disabled]:pointer-events-none data-[disabled]:opacity-40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{#snippet children({ checked })}
|
||||||
|
<span class="pointer-events-none absolute start-3 flex size-4 items-center justify-center">
|
||||||
|
{#if checked}
|
||||||
|
<CheckIcon class="size-4" />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{@render childrenProp?.()}
|
||||||
|
{/snippet}
|
||||||
|
</ContextMenuPrimitive.CheckboxItem>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
import ContextMenuPortal from './context-menu-portal.svelte';
|
||||||
|
import type { ComponentProps } from 'svelte';
|
||||||
|
import type { WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
portalProps,
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: ContextMenuPrimitive.ContentProps & {
|
||||||
|
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof ContextMenuPortal>>;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPortal {...portalProps}>
|
||||||
|
<ContextMenuPrimitive.Content
|
||||||
|
bind:ref
|
||||||
|
data-slot="context-menu-content"
|
||||||
|
class={cn(
|
||||||
|
'cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-popover z-50 max-h-(--bits-context-menu-content-available-height) min-w-[10rem] origin-(--bits-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-cladd-popover p-2 text-cladd-fg shadow-cladd-popover outline-none',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
</ContextMenuPortal>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
...restProps
|
||||||
|
}: ContextMenuPrimitive.GroupHeadingProps & {
|
||||||
|
inset?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.GroupHeading
|
||||||
|
bind:ref
|
||||||
|
data-slot="context-menu-group-heading"
|
||||||
|
data-inset={inset}
|
||||||
|
class={cn('cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-8 data-[inset]:ps-9', className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: ContextMenuPrimitive.GroupProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.Group bind:ref data-slot="context-menu-group" {...restProps} />
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
variant = 'default',
|
||||||
|
...restProps
|
||||||
|
}: ContextMenuPrimitive.ItemProps & {
|
||||||
|
inset?: boolean;
|
||||||
|
variant?: 'default' | 'destructive';
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.Item
|
||||||
|
bind:ref
|
||||||
|
data-slot="context-menu-item"
|
||||||
|
data-inset={inset}
|
||||||
|
data-variant={variant}
|
||||||
|
class={cn(
|
||||||
|
"relative flex min-h-cladd-lg cursor-default items-center gap-2 rounded-full px-3 py-1 text-cladd-xs font-medium outline-hidden transition-[background-color,box-shadow] duration-200 select-none data-highlighted:bg-cladd-surface-next data-[disabled]:pointer-events-none data-[disabled]:opacity-40 data-[inset]:ps-8 data-[inset]:ps-9 data-[variant=destructive]:text-destructive data-[variant=destructive]:data-highlighted:bg-destructive/12 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft data-[variant=destructive]:*:[svg]:!text-destructive",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
||||||
|
inset?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="context-menu-label"
|
||||||
|
data-inset={inset}
|
||||||
|
class={cn('cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-8 data-[inset]:ps-9', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ...restProps }: ContextMenuPrimitive.PortalProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.Portal {...restProps} />
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
value = $bindable(''),
|
||||||
|
...restProps
|
||||||
|
}: ContextMenuPrimitive.RadioGroupProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.RadioGroup
|
||||||
|
bind:ref
|
||||||
|
bind:value
|
||||||
|
data-slot="context-menu-radio-group"
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
import CircleIcon from '@lucide/svelte/icons/circle';
|
||||||
|
import { cn, type WithoutChild } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children: childrenProp,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChild<ContextMenuPrimitive.RadioItemProps> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.RadioItem
|
||||||
|
bind:ref
|
||||||
|
data-slot="context-menu-radio-item"
|
||||||
|
class={cn(
|
||||||
|
"relative flex min-h-cladd-lg cursor-default items-center gap-2 rounded-full py-1 ps-9 pe-3 text-cladd-xs font-medium outline-hidden transition-[background-color,box-shadow] duration-200 select-none data-highlighted:bg-cladd-surface-next data-[disabled]:pointer-events-none data-[disabled]:opacity-40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{#snippet children({ checked })}
|
||||||
|
<span class="pointer-events-none absolute start-3 flex size-4 items-center justify-center">
|
||||||
|
{#if checked}
|
||||||
|
<CircleIcon class="size-2 fill-current" />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{@render childrenProp?.({ checked })}
|
||||||
|
{/snippet}
|
||||||
|
</ContextMenuPrimitive.RadioItem>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: ContextMenuPrimitive.SeparatorProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.Separator
|
||||||
|
bind:ref
|
||||||
|
data-slot="context-menu-separator"
|
||||||
|
class={cn('-mx-2 my-2 h-px bg-cladd-bg-outline', className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="context-menu-shortcut"
|
||||||
|
class={cn('ms-auto font-mono text-cladd-2xs tracking-widest text-cladd-fg-softer', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</span>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: ContextMenuPrimitive.SubContentProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.SubContent
|
||||||
|
bind:ref
|
||||||
|
data-slot="context-menu-sub-content"
|
||||||
|
class={cn(
|
||||||
|
'cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-popover z-50 min-w-[10rem] origin-(--bits-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-cladd-popover p-2 text-cladd-fg shadow-cladd-popover outline-none',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
import ChevronRightIcon from '@lucide/svelte/icons/chevron-right';
|
||||||
|
import { cn, type WithoutChild } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChild<ContextMenuPrimitive.SubTriggerProps> & {
|
||||||
|
inset?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.SubTrigger
|
||||||
|
bind:ref
|
||||||
|
data-slot="context-menu-sub-trigger"
|
||||||
|
data-inset={inset}
|
||||||
|
class={cn(
|
||||||
|
"relative flex min-h-cladd-lg cursor-default items-center gap-2 rounded-full px-3 py-1 text-cladd-xs font-medium outline-hidden transition-[background-color,box-shadow] duration-200 select-none data-highlighted:bg-cladd-surface-next data-[disabled]:pointer-events-none data-[disabled]:opacity-40 data-[inset]:ps-8 data-[inset]:ps-9 data-[state=open]:bg-cladd-surface-next [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
<ChevronRightIcon class="ms-auto" />
|
||||||
|
</ContextMenuPrimitive.SubTrigger>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { open = $bindable(false), ...restProps }: ContextMenuPrimitive.SubProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.Sub bind:open {...restProps} />
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: ContextMenuPrimitive.TriggerProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.Trigger bind:ref data-slot="context-menu-trigger" {...restProps} />
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { open = $bindable(false), ...restProps }: ContextMenuPrimitive.RootProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ContextMenuPrimitive.Root bind:open {...restProps} />
|
||||||
@@ -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
|
||||||
|
};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: DialogPrimitive.CloseProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Close bind:ref data-slot="dialog-close" {...restProps} />
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
import DialogPortal from './dialog-portal.svelte';
|
||||||
|
import XIcon from '@lucide/svelte/icons/x';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import * as Dialog from './index.js';
|
||||||
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
|
import type { ComponentProps } from 'svelte';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
portalProps,
|
||||||
|
children,
|
||||||
|
showCloseButton = true,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
|
||||||
|
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof DialogPortal>>;
|
||||||
|
children: Snippet;
|
||||||
|
showCloseButton?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPortal {...portalProps}>
|
||||||
|
<Dialog.Overlay />
|
||||||
|
<DialogPrimitive.Content
|
||||||
|
bind:ref
|
||||||
|
data-slot="dialog-content"
|
||||||
|
class={cn(
|
||||||
|
'cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-dialog fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-cladd-dialog p-4 text-cladd-fg shadow-cladd-popover outline-none sm:max-w-lg',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
{#if showCloseButton}
|
||||||
|
<DialogPrimitive.Close
|
||||||
|
class="cladd-ghost cladd-hoverable cladd-clickable cladd-focusable absolute end-3 top-3 flex size-cladd-md items-center justify-center rounded-full text-cladd-fg-soft disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
||||||
|
>
|
||||||
|
<XIcon />
|
||||||
|
<span class="sr-only">Close</span>
|
||||||
|
</DialogPrimitive.Close>
|
||||||
|
{/if}
|
||||||
|
</DialogPrimitive.Content>
|
||||||
|
</DialogPortal>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DialogPrimitive.DescriptionProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Description
|
||||||
|
bind:ref
|
||||||
|
data-slot="dialog-description"
|
||||||
|
class={cn('text-cladd-sm leading-relaxed text-cladd-fg-soft', className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="dialog-footer"
|
||||||
|
class={cn(
|
||||||
|
'mt-2 flex flex-col-reverse gap-2 sm:flex-row sm:flex-wrap sm:items-center sm:justify-end',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="dialog-header"
|
||||||
|
class={cn('flex flex-col gap-1.5 text-start', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DialogPrimitive.OverlayProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Overlay
|
||||||
|
bind:ref
|
||||||
|
data-slot="dialog-overlay"
|
||||||
|
class={cn('cladd-backdrop cladd-anim-fade fixed inset-0 z-50', className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ...restProps }: DialogPrimitive.PortalProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Portal {...restProps} />
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DialogPrimitive.TitleProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Title
|
||||||
|
bind:ref
|
||||||
|
data-slot="dialog-title"
|
||||||
|
class={cn('pe-8 text-cladd-md leading-tight font-semibold', className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: DialogPrimitive.TriggerProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Trigger bind:ref data-slot="dialog-trigger" {...restProps} />
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { open = $bindable(false), ...restProps }: DialogPrimitive.RootProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Root bind:open {...restProps} />
|
||||||
@@ -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
|
||||||
|
};
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
value = $bindable([]),
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.CheckboxGroupProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.CheckboxGroup
|
||||||
|
bind:ref
|
||||||
|
bind:value
|
||||||
|
data-slot="dropdown-menu-checkbox-group"
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
import CheckIcon from '@lucide/svelte/icons/check';
|
||||||
|
import MinusIcon from '@lucide/svelte/icons/minus';
|
||||||
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
checked = $bindable(false),
|
||||||
|
indeterminate = $bindable(false),
|
||||||
|
class: className,
|
||||||
|
children: childrenProp,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChildrenOrChild<DropdownMenuPrimitive.CheckboxItemProps> & {
|
||||||
|
children?: Snippet;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.CheckboxItem
|
||||||
|
bind:ref
|
||||||
|
bind:checked
|
||||||
|
bind:indeterminate
|
||||||
|
data-slot="dropdown-menu-checkbox-item"
|
||||||
|
class={cn(
|
||||||
|
"relative flex min-h-cladd-lg cursor-default items-center gap-2 rounded-full py-1 ps-9 pe-3 text-cladd-xs font-medium outline-hidden transition-[background-color,box-shadow] duration-200 select-none data-highlighted:bg-cladd-surface-next data-[disabled]:pointer-events-none data-[disabled]:opacity-40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{#snippet children({ checked, indeterminate })}
|
||||||
|
<span class="pointer-events-none absolute start-3 flex size-4 items-center justify-center">
|
||||||
|
{#if indeterminate}
|
||||||
|
<MinusIcon class="size-4" />
|
||||||
|
{:else}
|
||||||
|
<CheckIcon class={cn('size-4', !checked && 'text-transparent')} />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{@render childrenProp?.()}
|
||||||
|
{/snippet}
|
||||||
|
</DropdownMenuPrimitive.CheckboxItem>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
|
import DropdownMenuPortal from './dropdown-menu-portal.svelte';
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
import type { ComponentProps } from 'svelte';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
sideOffset = 4,
|
||||||
|
portalProps,
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.ContentProps & {
|
||||||
|
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof DropdownMenuPortal>>;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPortal {...portalProps}>
|
||||||
|
<DropdownMenuPrimitive.Content
|
||||||
|
bind:ref
|
||||||
|
data-slot="dropdown-menu-content"
|
||||||
|
{sideOffset}
|
||||||
|
class={cn(
|
||||||
|
'cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-popover z-50 max-h-(--bits-dropdown-menu-content-available-height) min-w-[10rem] origin-(--bits-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-cladd-popover p-2 text-cladd-fg shadow-cladd-popover outline-none',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
</DropdownMenuPortal>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
import type { ComponentProps } from 'svelte';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
...restProps
|
||||||
|
}: ComponentProps<typeof DropdownMenuPrimitive.GroupHeading> & {
|
||||||
|
inset?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.GroupHeading
|
||||||
|
bind:ref
|
||||||
|
data-slot="dropdown-menu-group-heading"
|
||||||
|
data-inset={inset}
|
||||||
|
class={cn('cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-8 data-[inset]:ps-9', className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: DropdownMenuPrimitive.GroupProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.Group bind:ref data-slot="dropdown-menu-group" {...restProps} />
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
variant = 'default',
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.ItemProps & {
|
||||||
|
inset?: boolean;
|
||||||
|
variant?: 'default' | 'destructive';
|
||||||
|
asChild?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.Item
|
||||||
|
bind:ref
|
||||||
|
data-slot="dropdown-menu-item"
|
||||||
|
data-inset={inset}
|
||||||
|
data-variant={variant}
|
||||||
|
class={cn(
|
||||||
|
"relative flex min-h-cladd-lg cursor-default items-center gap-2 rounded-full px-3 py-1 text-cladd-xs font-medium outline-hidden transition-[background-color,box-shadow] duration-200 select-none data-highlighted:bg-cladd-surface-next data-[disabled]:pointer-events-none data-[disabled]:opacity-40 data-[inset]:ps-8 data-[inset]:ps-9 data-[variant=destructive]:text-destructive data-[variant=destructive]:data-highlighted:bg-destructive/12 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft data-[variant=destructive]:*:[svg]:!text-destructive",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
||||||
|
inset?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="dropdown-menu-label"
|
||||||
|
data-inset={inset}
|
||||||
|
class={cn('cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-8 data-[inset]:ps-9', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ...restProps }: DropdownMenuPrimitive.PortalProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.Portal {...restProps} />
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
value = $bindable(),
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.RadioGroupProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.RadioGroup
|
||||||
|
bind:ref
|
||||||
|
bind:value
|
||||||
|
data-slot="dropdown-menu-radio-group"
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
import CircleIcon from '@lucide/svelte/icons/circle';
|
||||||
|
import { cn, type WithoutChild } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children: childrenProp,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChild<DropdownMenuPrimitive.RadioItemProps> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.RadioItem
|
||||||
|
bind:ref
|
||||||
|
data-slot="dropdown-menu-radio-item"
|
||||||
|
class={cn(
|
||||||
|
"relative flex min-h-cladd-lg cursor-default items-center gap-2 rounded-full py-1 ps-9 pe-3 text-cladd-xs font-medium outline-hidden transition-[background-color,box-shadow] duration-200 select-none data-highlighted:bg-cladd-surface-next data-[disabled]:pointer-events-none data-[disabled]:opacity-40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{#snippet children({ checked })}
|
||||||
|
<span class="pointer-events-none absolute start-3 flex size-4 items-center justify-center">
|
||||||
|
{#if checked}
|
||||||
|
<CircleIcon class="size-2 fill-current" />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{@render childrenProp?.({ checked })}
|
||||||
|
{/snippet}
|
||||||
|
</DropdownMenuPrimitive.RadioItem>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.SeparatorProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.Separator
|
||||||
|
bind:ref
|
||||||
|
data-slot="dropdown-menu-separator"
|
||||||
|
class={cn('-mx-2 my-2 h-px bg-cladd-bg-outline', className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="dropdown-menu-shortcut"
|
||||||
|
class={cn('ms-auto font-mono text-cladd-2xs tracking-widest text-cladd-fg-softer', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</span>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.SubContentProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.SubContent
|
||||||
|
bind:ref
|
||||||
|
data-slot="dropdown-menu-sub-content"
|
||||||
|
class={cn(
|
||||||
|
'cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-popover z-50 min-w-[10rem] origin-(--bits-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-cladd-popover p-2 text-cladd-fg shadow-cladd-popover outline-none',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
import ChevronRightIcon from '@lucide/svelte/icons/chevron-right';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
inset,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: DropdownMenuPrimitive.SubTriggerProps & {
|
||||||
|
inset?: boolean;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.SubTrigger
|
||||||
|
bind:ref
|
||||||
|
data-slot="dropdown-menu-sub-trigger"
|
||||||
|
data-inset={inset}
|
||||||
|
class={cn(
|
||||||
|
"relative flex min-h-cladd-lg cursor-default items-center gap-2 rounded-full px-3 py-1 text-cladd-xs font-medium outline-hidden transition-[background-color,box-shadow] duration-200 select-none data-highlighted:bg-cladd-surface-next data-[disabled]:pointer-events-none data-[disabled]:opacity-40 data-[inset]:ps-8 data-[inset]:ps-9 data-[state=open]:bg-cladd-surface-next [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
<ChevronRightIcon class="ms-auto size-4" />
|
||||||
|
</DropdownMenuPrimitive.SubTrigger>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { open = $bindable(false), ...restProps }: DropdownMenuPrimitive.SubProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.Sub bind:open {...restProps} />
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: DropdownMenuPrimitive.TriggerProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.Trigger bind:ref data-slot="dropdown-menu-trigger" {...restProps} />
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { open = $bindable(false), ...restProps }: DropdownMenuPrimitive.RootProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DropdownMenuPrimitive.Root bind:open {...restProps} />
|
||||||
@@ -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
|
||||||
|
};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import Root from './input.svelte';
|
||||||
|
|
||||||
|
export {
|
||||||
|
Root,
|
||||||
|
//
|
||||||
|
Root as Input
|
||||||
|
};
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { HTMLInputAttributes, HTMLInputTypeAttribute } from 'svelte/elements';
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
|
||||||
|
type InputType = Exclude<HTMLInputTypeAttribute, 'file'>;
|
||||||
|
|
||||||
|
type Props = WithElementRef<
|
||||||
|
Omit<HTMLInputAttributes, 'type'> &
|
||||||
|
({ type: 'file'; files?: FileList } | { type?: InputType; files?: undefined })
|
||||||
|
>;
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
value = $bindable(),
|
||||||
|
type,
|
||||||
|
files = $bindable(),
|
||||||
|
class: className,
|
||||||
|
'data-slot': dataSlot = 'input',
|
||||||
|
...restProps
|
||||||
|
}: Props = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if type === 'file'}
|
||||||
|
<input
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot={dataSlot}
|
||||||
|
class={cn(
|
||||||
|
'cladd-cut cladd-hoverable cladd-focusable-input flex h-cladd-md w-full min-w-0 rounded-cladd-md px-2.5 pt-1.5 text-cladd-xs font-medium text-cladd-fg selection:bg-brand/30 file:me-2 file:font-semibold file:text-cladd-fg placeholder:text-cladd-fg-softer disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
type="file"
|
||||||
|
bind:files
|
||||||
|
bind:value
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<input
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot={dataSlot}
|
||||||
|
class={cn(
|
||||||
|
'cladd-cut cladd-hoverable cladd-focusable-input flex h-cladd-md w-full min-w-0 rounded-cladd-md px-2.5 py-1 text-cladd-xs font-medium text-cladd-fg selection:bg-brand/30 placeholder:text-cladd-fg-softer disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{type}
|
||||||
|
bind:value
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import Label from './label.svelte';
|
||||||
|
|
||||||
|
export { Label };
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Label as LabelPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: { ref?: any; class?: string; children?: any; [key: string]: any } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<LabelPrimitive.Root
|
||||||
|
bind:ref
|
||||||
|
class={cn(
|
||||||
|
'text-cladd-xs leading-none font-medium text-cladd-fg-soft peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</LabelPrimitive.Root>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import Root from './progress.svelte';
|
||||||
|
|
||||||
|
export {
|
||||||
|
Root,
|
||||||
|
//
|
||||||
|
Root as Progress
|
||||||
|
};
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Progress as ProgressPrimitive } from 'bits-ui';
|
||||||
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
max = 100,
|
||||||
|
value,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChildrenOrChild<ProgressPrimitive.RootProps> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ProgressPrimitive.Root
|
||||||
|
bind:ref
|
||||||
|
data-slot="progress"
|
||||||
|
class={cn('cladd-cut relative h-2 w-full overflow-hidden rounded-full', className)}
|
||||||
|
{value}
|
||||||
|
{max}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-slot="progress-indicator"
|
||||||
|
class="cladd-surface cladd-gradient-fill cladd-color-brand h-full w-full flex-1 rounded-full transition-all duration-300 ease-out"
|
||||||
|
style="transform: translateX(-{100 - (100 * (value ?? 0)) / (max ?? 1)}%)"
|
||||||
|
></div>
|
||||||
|
</ProgressPrimitive.Root>
|
||||||
@@ -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
|
||||||
|
};
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Select as SelectPrimitive } from 'bits-ui';
|
||||||
|
import SelectPortal from './select-portal.svelte';
|
||||||
|
import SelectScrollUpButton from './select-scroll-up-button.svelte';
|
||||||
|
import SelectScrollDownButton from './select-scroll-down-button.svelte';
|
||||||
|
import { cn, type WithoutChild } from '$lib/utils.js';
|
||||||
|
import type { ComponentProps } from 'svelte';
|
||||||
|
import type { WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
sideOffset = 4,
|
||||||
|
portalProps,
|
||||||
|
children,
|
||||||
|
preventScroll = true,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChild<SelectPrimitive.ContentProps> & {
|
||||||
|
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof SelectPortal>>;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SelectPortal {...portalProps}>
|
||||||
|
<SelectPrimitive.Content
|
||||||
|
bind:ref
|
||||||
|
{sideOffset}
|
||||||
|
{preventScroll}
|
||||||
|
data-slot="select-content"
|
||||||
|
class={cn(
|
||||||
|
'cladd-surface cladd-gradient cladd-outline cladd-level-1 cladd-anim-popover z-50 max-h-(--bits-select-content-available-height) min-w-[10rem] origin-(--bits-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-cladd-popover text-cladd-fg shadow-cladd-popover outline-none',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
<SelectScrollUpButton />
|
||||||
|
<SelectPrimitive.Viewport
|
||||||
|
class={cn(
|
||||||
|
'h-(--bits-select-anchor-height) w-full min-w-(--bits-select-anchor-width) scroll-my-2 p-2'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</SelectPrimitive.Viewport>
|
||||||
|
<SelectScrollDownButton />
|
||||||
|
</SelectPrimitive.Content>
|
||||||
|
</SelectPortal>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Select as SelectPrimitive } from 'bits-ui';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
import type { ComponentProps } from 'svelte';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: ComponentProps<typeof SelectPrimitive.GroupHeading> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SelectPrimitive.GroupHeading
|
||||||
|
bind:ref
|
||||||
|
data-slot="select-group-heading"
|
||||||
|
class={cn('cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-9', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</SelectPrimitive.GroupHeading>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Select as SelectPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: SelectPrimitive.GroupProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SelectPrimitive.Group bind:ref data-slot="select-group" {...restProps} />
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import CheckIcon from '@lucide/svelte/icons/check';
|
||||||
|
import { Select as SelectPrimitive } from 'bits-ui';
|
||||||
|
import { cn, type WithoutChild } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
value,
|
||||||
|
label,
|
||||||
|
children: childrenProp,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChild<SelectPrimitive.ItemProps> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SelectPrimitive.Item
|
||||||
|
bind:ref
|
||||||
|
{value}
|
||||||
|
data-slot="select-item"
|
||||||
|
class={cn(
|
||||||
|
"relative flex min-h-cladd-lg cursor-default items-center gap-2 rounded-full py-1 ps-3 pe-9 text-cladd-xs font-medium outline-hidden transition-[background-color,box-shadow] duration-200 select-none data-highlighted:bg-cladd-surface-next data-[disabled]:pointer-events-none data-[disabled]:opacity-40 data-[selected]:bg-cladd-surface-next data-[selected]:shadow-cladd-outline [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-cladd-fg-soft *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{#snippet children({ selected, highlighted })}
|
||||||
|
<span class="absolute end-3 flex size-4 items-center justify-center">
|
||||||
|
{#if selected}
|
||||||
|
<CheckIcon class="size-4 text-cladd-fg" />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{#if childrenProp}
|
||||||
|
{@render childrenProp({ selected, highlighted })}
|
||||||
|
{:else}
|
||||||
|
{label || value}
|
||||||
|
{/if}
|
||||||
|
{/snippet}
|
||||||
|
</SelectPrimitive.Item>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn, type WithElementRef } from '$lib/utils.js';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="select-label"
|
||||||
|
class={cn('cladd-section-title px-3 pt-2 pb-1.5 data-[inset]:ps-9', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Select as SelectPrimitive } from 'bits-ui';
|
||||||
|
|
||||||
|
let { ...restProps }: SelectPrimitive.PortalProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SelectPrimitive.Portal {...restProps} />
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import ChevronDownIcon from '@lucide/svelte/icons/chevron-down';
|
||||||
|
import { Select as SelectPrimitive } from 'bits-ui';
|
||||||
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChildrenOrChild<SelectPrimitive.ScrollDownButtonProps> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SelectPrimitive.ScrollDownButton
|
||||||
|
bind:ref
|
||||||
|
data-slot="select-scroll-down-button"
|
||||||
|
class={cn('flex cursor-default items-center justify-center py-1 text-cladd-fg-softer', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
<ChevronDownIcon class="size-4" />
|
||||||
|
</SelectPrimitive.ScrollDownButton>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import ChevronUpIcon from '@lucide/svelte/icons/chevron-up';
|
||||||
|
import { Select as SelectPrimitive } from 'bits-ui';
|
||||||
|
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChildrenOrChild<SelectPrimitive.ScrollUpButtonProps> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SelectPrimitive.ScrollUpButton
|
||||||
|
bind:ref
|
||||||
|
data-slot="select-scroll-up-button"
|
||||||
|
class={cn('flex cursor-default items-center justify-center py-1 text-cladd-fg-softer', className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
<ChevronUpIcon class="size-4" />
|
||||||
|
</SelectPrimitive.ScrollUpButton>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { Separator as SeparatorPrimitive } from 'bits-ui';
|
||||||
|
import { Separator } from '$lib/components/ui/separator/index.js';
|
||||||
|
import { cn } from '$lib/utils.js';
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: SeparatorPrimitive.RootProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Separator
|
||||||
|
bind:ref
|
||||||
|
data-slot="select-separator"
|
||||||
|
class={cn('pointer-events-none -mx-2 my-2 h-px bg-cladd-bg-outline', className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
Loaded 100 of 147 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user