aetherx-dt-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/cli/index.mjs +440 -0
  2. package/package.json +56 -0
  3. package/src/registry/components/badge/DtBadge.vue +94 -0
  4. package/src/registry/components/badge/index.ts +2 -0
  5. package/src/registry/components/button/DtButton.vue +176 -0
  6. package/src/registry/components/button/index.ts +2 -0
  7. package/src/registry/components/card/DtCard.vue +46 -0
  8. package/src/registry/components/card/DtCardContent.vue +15 -0
  9. package/src/registry/components/card/DtCardFooter.vue +17 -0
  10. package/src/registry/components/card/DtCardHeader.vue +31 -0
  11. package/src/registry/components/card/index.ts +4 -0
  12. package/src/registry/components/dialog/DtDialog.vue +41 -0
  13. package/src/registry/components/dialog/DtDialogContent.vue +140 -0
  14. package/src/registry/components/dialog/DtDialogFooter.vue +18 -0
  15. package/src/registry/components/dialog/DtDialogHeader.vue +32 -0
  16. package/src/registry/components/dialog/DtDialogTrigger.vue +20 -0
  17. package/src/registry/components/dialog/index.ts +5 -0
  18. package/src/registry/components/input/DtInput.vue +140 -0
  19. package/src/registry/components/input/index.ts +2 -0
  20. package/src/registry/components/select/DtSelect.vue +102 -0
  21. package/src/registry/components/select/DtSelectContent.vue +103 -0
  22. package/src/registry/components/select/DtSelectItem.vue +123 -0
  23. package/src/registry/components/select/DtSelectTrigger.vue +128 -0
  24. package/src/registry/components/select/index.ts +4 -0
  25. package/src/registry/docs/badge.md +171 -0
  26. package/src/registry/docs/button.md +184 -0
  27. package/src/registry/docs/card.md +199 -0
  28. package/src/registry/docs/dialog.md +282 -0
  29. package/src/registry/docs/input.md +168 -0
  30. package/src/registry/docs/select.md +346 -0
  31. package/src/registry/lib/utils.ts +4 -0
  32. package/src/registry/registry.json +52 -0
  33. package/src/registry/styles/base.css +143 -0
@@ -0,0 +1,440 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import * as p from '@clack/prompts';
6
+ import pc from 'picocolors';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { execSync } from 'node:child_process';
9
+
10
+ const CONFIG_FILE = ".dtui.json";
11
+ function getConfigPath() {
12
+ return path.resolve(process.cwd(), CONFIG_FILE);
13
+ }
14
+ function configExists() {
15
+ return fs.existsSync(getConfigPath());
16
+ }
17
+ function readConfig() {
18
+ const configPath = getConfigPath();
19
+ if (!fs.existsSync(configPath)) {
20
+ throw new Error("No .dtui.json found. Run `npx dt-ui init` first.");
21
+ }
22
+ const raw = fs.readFileSync(configPath, "utf-8");
23
+ return JSON.parse(raw);
24
+ }
25
+ function writeConfig(config) {
26
+ const configPath = getConfigPath();
27
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
28
+ }
29
+ function detectFramework() {
30
+ const cwd = process.cwd();
31
+ if (fs.existsSync(path.join(cwd, "nuxt.config.ts")) || fs.existsSync(path.join(cwd, "nuxt.config.js"))) {
32
+ return "nuxt";
33
+ }
34
+ if (fs.existsSync(path.join(cwd, "vite.config.ts")) || fs.existsSync(path.join(cwd, "vite.config.js"))) {
35
+ return "vue-vite";
36
+ }
37
+ return "vue";
38
+ }
39
+ function detectPackageManager() {
40
+ const cwd = process.cwd();
41
+ if (fs.existsSync(path.join(cwd, "bun.lockb")) || fs.existsSync(path.join(cwd, "bun.lock"))) {
42
+ return "bun";
43
+ }
44
+ if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml"))) {
45
+ return "pnpm";
46
+ }
47
+ if (fs.existsSync(path.join(cwd, "yarn.lock"))) {
48
+ return "yarn";
49
+ }
50
+ return "npm";
51
+ }
52
+ function getInstallCommand(pm, deps) {
53
+ const depStr = deps.join(" ");
54
+ switch (pm) {
55
+ case "pnpm":
56
+ return `pnpm add ${depStr}`;
57
+ case "yarn":
58
+ return `yarn add ${depStr}`;
59
+ case "bun":
60
+ return `bun add ${depStr}`;
61
+ default:
62
+ return `npm install ${depStr}`;
63
+ }
64
+ }
65
+
66
+ function getRegistryDir() {
67
+ const thisFile = fileURLToPath(import.meta.url);
68
+ const cliDir = path.dirname(thisFile);
69
+ const candidates = [
70
+ // When running from built dist/
71
+ path.resolve(cliDir, "../../src/registry"),
72
+ // When running from src/cli/utils/
73
+ path.resolve(cliDir, "../../registry"),
74
+ // When running via unbuild stub
75
+ path.resolve(cliDir, "../../../src/registry")
76
+ ];
77
+ for (const candidate of candidates) {
78
+ if (fs.existsSync(path.join(candidate, "registry.json"))) {
79
+ return candidate;
80
+ }
81
+ }
82
+ throw new Error("Could not find registry directory. Make sure dt-ui is installed correctly.");
83
+ }
84
+ function loadRegistry() {
85
+ const registryDir = getRegistryDir();
86
+ const registryPath = path.join(registryDir, "registry.json");
87
+ const raw = fs.readFileSync(registryPath, "utf-8");
88
+ return JSON.parse(raw);
89
+ }
90
+ function getComponentFiles(componentName) {
91
+ const registryDir = getRegistryDir();
92
+ const registry = loadRegistry();
93
+ const component = registry.components[componentName];
94
+ if (!component) {
95
+ throw new Error(`Component "${componentName}" not found in registry.`);
96
+ }
97
+ return component.files.map((fileName) => {
98
+ const filePath = path.join(registryDir, "components", componentName, fileName);
99
+ return {
100
+ name: fileName,
101
+ content: fs.readFileSync(filePath, "utf-8")
102
+ };
103
+ });
104
+ }
105
+ function getStylesContent() {
106
+ const registryDir = getRegistryDir();
107
+ return fs.readFileSync(path.join(registryDir, "styles", "base.css"), "utf-8");
108
+ }
109
+ function getLibContent() {
110
+ const registryDir = getRegistryDir();
111
+ return fs.readFileSync(path.join(registryDir, "lib", "utils.ts"), "utf-8");
112
+ }
113
+ function getDocContent(docsPath) {
114
+ const registryDir = getRegistryDir();
115
+ const fullPath = path.join(registryDir, docsPath);
116
+ if (!fs.existsSync(fullPath)) {
117
+ return "";
118
+ }
119
+ return fs.readFileSync(fullPath, "utf-8");
120
+ }
121
+ function getAllComponentNames() {
122
+ const registry = loadRegistry();
123
+ return Object.keys(registry.components);
124
+ }
125
+
126
+ const AGENT_HEADER = `# DT UI \u2014 Component Reference
127
+
128
+ This project uses dt-ui components. Below is the complete API reference for all installed components. Components use pure CSS with CSS custom properties for theming. No Tailwind or CSS framework required.
129
+
130
+ ## Theming
131
+
132
+ All components use CSS custom properties prefixed with \`--dt-\` defined in \`base.css\`. Override them in your project's CSS to customize the look.
133
+
134
+ ### Available Tokens
135
+
136
+ | Token | Default (Light) | Description |
137
+ |-------|-----------------|-------------|
138
+ | \`--dt-primary\` | \`hsl(220 72% 50%)\` | Brand/primary color |
139
+ | \`--dt-primary-hover\` | \`hsl(220 72% 42%)\` | Primary hover state |
140
+ | \`--dt-primary-foreground\` | \`hsl(0 0% 100%)\` | Text on primary bg |
141
+ | \`--dt-secondary\` | \`hsl(220 14% 94%)\` | Secondary background |
142
+ | \`--dt-secondary-foreground\` | \`hsl(220 10% 20%)\` | Text on secondary bg |
143
+ | \`--dt-destructive\` | \`hsl(0 72% 51%)\` | Destructive/danger color |
144
+ | \`--dt-success\` | \`hsl(142 72% 40%)\` | Success color |
145
+ | \`--dt-warning\` | \`hsl(38 92% 50%)\` | Warning color |
146
+ | \`--dt-border\` | \`hsl(220 13% 88%)\` | Border color |
147
+ | \`--dt-ring\` | \`hsl(220 72% 50%)\` | Focus ring color |
148
+ | \`--dt-radius-sm\` | \`0.25rem\` | Small border radius |
149
+ | \`--dt-radius-md\` | \`0.375rem\` | Medium border radius |
150
+ | \`--dt-radius-lg\` | \`0.5rem\` | Large border radius |
151
+ | \`--dt-shadow-sm\` | \`0 1px 2px...\` | Small shadow |
152
+ | \`--dt-shadow-md\` | \`0 4px 6px...\` | Medium shadow |
153
+ | \`--dt-shadow-lg\` | \`0 10px 15px...\` | Large shadow |
154
+
155
+ ### Dark Mode
156
+
157
+ Add the \`dark\` class to your \`<html>\` or \`<body>\` element. All tokens automatically adjust.
158
+
159
+ ---
160
+
161
+ ## Components
162
+
163
+ `;
164
+ function getAgentMdPath() {
165
+ return path.resolve(process.cwd(), "AGENT.md");
166
+ }
167
+ function createAgentMd() {
168
+ fs.writeFileSync(getAgentMdPath(), AGENT_HEADER, "utf-8");
169
+ }
170
+ function appendComponentDoc(componentName) {
171
+ const registry = loadRegistry();
172
+ const component = registry.components[componentName];
173
+ if (!component) return;
174
+ const docContent = getDocContent(component.docs);
175
+ if (!docContent) return;
176
+ const agentPath = getAgentMdPath();
177
+ if (!fs.existsSync(agentPath)) {
178
+ createAgentMd();
179
+ }
180
+ const existing = fs.readFileSync(agentPath, "utf-8");
181
+ if (existing.includes(`### ${component.name}`)) return;
182
+ const separator = "\n---\n\n";
183
+ fs.appendFileSync(agentPath, docContent + separator, "utf-8");
184
+ }
185
+
186
+ async function initCommand() {
187
+ p.intro(pc.bold(pc.cyan("dt-ui init")));
188
+ if (configExists()) {
189
+ const overwrite = await p.confirm({
190
+ message: "A .dtui.json config already exists. Overwrite?",
191
+ initialValue: false
192
+ });
193
+ if (p.isCancel(overwrite) || !overwrite) {
194
+ p.cancel("Init cancelled.");
195
+ process.exit(0);
196
+ }
197
+ }
198
+ const detectedFramework = detectFramework();
199
+ const answers = await p.group(
200
+ {
201
+ framework: () => p.select({
202
+ message: "Which framework does your project use?",
203
+ initialValue: detectedFramework,
204
+ options: [
205
+ { value: "nuxt", label: "Nuxt", hint: detectedFramework === "nuxt" ? "detected" : void 0 },
206
+ { value: "vue-vite", label: "Vue + Vite", hint: detectedFramework === "vue-vite" ? "detected" : void 0 },
207
+ { value: "vue", label: "Vue (plain)", hint: detectedFramework === "vue" ? "detected" : void 0 }
208
+ ]
209
+ }),
210
+ componentsDir: () => p.text({
211
+ message: "Where should components be installed?",
212
+ initialValue: "src/components/ui",
213
+ placeholder: "src/components/ui"
214
+ }),
215
+ libDir: () => p.text({
216
+ message: "Where should lib utils go?",
217
+ initialValue: "src/lib",
218
+ placeholder: "src/lib"
219
+ }),
220
+ agent: () => p.confirm({
221
+ message: "Include AI agent documentation (AGENT.md)?",
222
+ initialValue: true
223
+ })
224
+ },
225
+ {
226
+ onCancel: () => {
227
+ p.cancel("Init cancelled.");
228
+ process.exit(0);
229
+ }
230
+ }
231
+ );
232
+ const stylesDir = "src/styles";
233
+ const config = {
234
+ framework: answers.framework,
235
+ componentsDir: answers.componentsDir,
236
+ libDir: answers.libDir,
237
+ stylesDir,
238
+ installedComponents: [],
239
+ agent: answers.agent
240
+ };
241
+ const s = p.spinner();
242
+ writeConfig(config);
243
+ s.start("Copying base.css...");
244
+ const stylesPath = path.resolve(process.cwd(), stylesDir);
245
+ fs.mkdirSync(stylesPath, { recursive: true });
246
+ fs.writeFileSync(
247
+ path.join(stylesPath, "base.css"),
248
+ getStylesContent(),
249
+ "utf-8"
250
+ );
251
+ s.stop("base.css copied");
252
+ s.start("Copying lib/utils.ts...");
253
+ const libPath = path.resolve(process.cwd(), answers.libDir);
254
+ fs.mkdirSync(libPath, { recursive: true });
255
+ fs.writeFileSync(
256
+ path.join(libPath, "utils.ts"),
257
+ getLibContent(),
258
+ "utf-8"
259
+ );
260
+ s.stop("lib/utils.ts copied");
261
+ if (answers.agent) {
262
+ s.start("Creating AGENT.md...");
263
+ createAgentMd();
264
+ s.stop("AGENT.md created");
265
+ }
266
+ p.note(
267
+ [
268
+ `${pc.bold("Next steps:")}`,
269
+ "",
270
+ `1. Import base.css in your main entry file:`,
271
+ ` ${pc.cyan("import './styles/base.css'")}`,
272
+ "",
273
+ `2. Add your first component:`,
274
+ ` ${pc.cyan("npx dt-ui add button")}`,
275
+ "",
276
+ `3. Use it in your Vue components:`,
277
+ ` ${pc.cyan('<DtButton variant="default">Click me</DtButton>')}`
278
+ ].join("\n"),
279
+ "Setup complete!"
280
+ );
281
+ p.outro(pc.green("dt-ui initialized successfully!"));
282
+ }
283
+
284
+ async function addCommand(componentNames) {
285
+ p.intro(pc.bold(pc.cyan("dt-ui add")));
286
+ if (!configExists()) {
287
+ p.cancel("No .dtui.json found. Run `npx dt-ui init` first.");
288
+ process.exit(1);
289
+ }
290
+ const config = readConfig();
291
+ const registry = loadRegistry();
292
+ const allNames = getAllComponentNames();
293
+ if (!componentNames || componentNames.length === 0) {
294
+ const selected = await p.multiselect({
295
+ message: "Which components would you like to add?",
296
+ options: allNames.map((name) => ({
297
+ value: name,
298
+ label: registry.components[name].name,
299
+ hint: config.installedComponents.includes(name) ? "installed" : void 0
300
+ })),
301
+ required: true
302
+ });
303
+ if (p.isCancel(selected)) {
304
+ p.cancel("Cancelled.");
305
+ process.exit(0);
306
+ }
307
+ componentNames = selected;
308
+ }
309
+ const invalid = componentNames.filter((n) => !registry.components[n]);
310
+ if (invalid.length > 0) {
311
+ p.cancel(
312
+ `Unknown component(s): ${invalid.map((n) => pc.red(n)).join(", ")}. Run ${pc.cyan("npx dt-ui list")} to see available components.`
313
+ );
314
+ process.exit(1);
315
+ }
316
+ const toInstall = /* @__PURE__ */ new Set();
317
+ const depQueue = [...componentNames];
318
+ while (depQueue.length > 0) {
319
+ const name = depQueue.pop();
320
+ if (toInstall.has(name)) continue;
321
+ toInstall.add(name);
322
+ const comp = registry.components[name];
323
+ for (const dep of comp.internalDeps) {
324
+ if (!toInstall.has(dep) && !config.installedComponents.includes(dep)) {
325
+ depQueue.push(dep);
326
+ }
327
+ }
328
+ }
329
+ const extraDeps = [...toInstall].filter((n) => !componentNames.includes(n));
330
+ if (extraDeps.length > 0) {
331
+ const confirmDeps = await p.confirm({
332
+ message: `The following dependencies are also required: ${extraDeps.map((n) => pc.cyan(n)).join(", ")}. Install them too?`,
333
+ initialValue: true
334
+ });
335
+ if (p.isCancel(confirmDeps)) {
336
+ p.cancel("Cancelled.");
337
+ process.exit(0);
338
+ }
339
+ if (!confirmDeps) {
340
+ for (const dep of extraDeps) {
341
+ toInstall.delete(dep);
342
+ }
343
+ }
344
+ }
345
+ const alreadyInstalled = [...toInstall].filter(
346
+ (n) => config.installedComponents.includes(n)
347
+ );
348
+ if (alreadyInstalled.length > 0) {
349
+ const overwrite = await p.confirm({
350
+ message: `${alreadyInstalled.map((n) => pc.yellow(n)).join(", ")} already installed. Overwrite?`,
351
+ initialValue: false
352
+ });
353
+ if (p.isCancel(overwrite) || !overwrite) {
354
+ for (const name of alreadyInstalled) {
355
+ toInstall.delete(name);
356
+ }
357
+ }
358
+ }
359
+ if (toInstall.size === 0) {
360
+ p.cancel("Nothing to install.");
361
+ process.exit(0);
362
+ }
363
+ const s = p.spinner();
364
+ const allPeerDeps = /* @__PURE__ */ new Set();
365
+ const installed = [];
366
+ for (const componentName of toInstall) {
367
+ const comp = registry.components[componentName];
368
+ s.start(`Installing ${pc.cyan(comp.name)}...`);
369
+ const files = getComponentFiles(componentName);
370
+ const targetDir = path.resolve(
371
+ process.cwd(),
372
+ config.componentsDir,
373
+ componentName
374
+ );
375
+ fs.mkdirSync(targetDir, { recursive: true });
376
+ for (const file of files) {
377
+ fs.writeFileSync(path.join(targetDir, file.name), file.content, "utf-8");
378
+ }
379
+ for (const dep of comp.peerDeps) {
380
+ allPeerDeps.add(dep);
381
+ }
382
+ if (!config.installedComponents.includes(componentName)) {
383
+ config.installedComponents.push(componentName);
384
+ }
385
+ if (config.agent) {
386
+ appendComponentDoc(componentName);
387
+ }
388
+ installed.push(componentName);
389
+ s.stop(`${pc.green("\u2713")} ${comp.name} installed`);
390
+ }
391
+ if (allPeerDeps.size > 0) {
392
+ const pm = detectPackageManager();
393
+ const cmd = getInstallCommand(pm, [...allPeerDeps]);
394
+ s.start(`Installing peer dependencies: ${[...allPeerDeps].join(", ")}...`);
395
+ try {
396
+ execSync(cmd, { cwd: process.cwd(), stdio: "pipe" });
397
+ s.stop("Peer dependencies installed");
398
+ } catch {
399
+ s.stop(pc.yellow("Failed to install peer dependencies. Please install manually:"));
400
+ p.log.warn(pc.dim(cmd));
401
+ }
402
+ }
403
+ writeConfig(config);
404
+ p.note(
405
+ installed.map((name) => {
406
+ const comp = registry.components[name];
407
+ return `${pc.green("\u2713")} ${comp.name} \u2192 ${config.componentsDir}/${name}/`;
408
+ }).join("\n"),
409
+ "Installed components"
410
+ );
411
+ p.outro(pc.green(`${installed.length} component(s) added successfully!`));
412
+ }
413
+
414
+ async function listCommand() {
415
+ p.intro(pc.bold(pc.cyan("dt-ui components")));
416
+ const registry = loadRegistry();
417
+ const installed = configExists() ? readConfig().installedComponents : [];
418
+ const components = Object.entries(registry.components);
419
+ const rows = components.map(([key, comp]) => {
420
+ const isInstalled = installed.includes(key);
421
+ const status = isInstalled ? pc.green("\u2713") : pc.dim("\u25CB");
422
+ const name = isInstalled ? pc.green(comp.name) : comp.name;
423
+ const deps = comp.internalDeps.length > 0 ? pc.dim(` (requires: ${comp.internalDeps.join(", ")})`) : "";
424
+ return ` ${status} ${name.padEnd(isInstalled ? 30 : 20)} ${pc.dim(comp.description)}${deps}`;
425
+ });
426
+ p.note(rows.join("\n"), `${components.length} components available`);
427
+ if (!configExists()) {
428
+ p.log.info(`Run ${pc.cyan("npx dt-ui init")} to get started.`);
429
+ } else {
430
+ p.log.info(`Run ${pc.cyan("npx dt-ui add <component>")} to install.`);
431
+ }
432
+ p.outro("");
433
+ }
434
+
435
+ const program = new Command();
436
+ program.name("dt-ui").description("DT UI \u2014 Lightweight, customizable Vue components for DT projects").version("0.1.0");
437
+ program.command("init").description("Initialize dt-ui in your project").action(initCommand);
438
+ program.command("add").description("Add a component to your project").argument("[components...]", "Component names to add").action(addCommand);
439
+ program.command("list").description("List all available components").action(listCommand);
440
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "aetherx-dt-ui",
3
+ "version": "0.1.0",
4
+ "description": "Lightweight, customizable Vue components for DT projects",
5
+ "type": "module",
6
+ "bin": {
7
+ "dt-ui": "dist/cli/index.mjs"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "src/registry"
12
+ ],
13
+ "scripts": {
14
+ "build": "unbuild",
15
+ "dev": "unbuild --stub",
16
+ "docs:dev": "vitepress dev docs",
17
+ "docs:build": "vitepress build docs",
18
+ "docs:preview": "vitepress preview docs"
19
+ },
20
+ "dependencies": {
21
+ "@clack/prompts": "^0.9.1",
22
+ "commander": "^13.1.0",
23
+ "picocolors": "^1.1.1"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^22.13.0",
27
+ "typescript": "^5.7.0",
28
+ "unbuild": "^3.3.1",
29
+ "vitepress": "^1.6.3",
30
+ "vue": "^3.5.0"
31
+ },
32
+ "peerDependencies": {
33
+ "vue": "^3.3.0"
34
+ },
35
+ "peerDependenciesMeta": {
36
+ "vue": {
37
+ "optional": true
38
+ }
39
+ },
40
+ "keywords": [
41
+ "vue",
42
+ "components",
43
+ "ui",
44
+ "design-system",
45
+ "dt"
46
+ ],
47
+ "license": "MIT",
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/ashomurodov/dt-ui.git"
51
+ },
52
+ "homepage": "https://github.com/ashomurodov/dt-ui#readme",
53
+ "bugs": {
54
+ "url": "https://github.com/ashomurodov/dt-ui/issues"
55
+ }
56
+ }
@@ -0,0 +1,94 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+
4
+ export type BadgeVariant = 'default' | 'secondary' | 'outline' | 'destructive' | 'success' | 'warning'
5
+ export type BadgeSize = 'sm' | 'default'
6
+
7
+ const props = withDefaults(defineProps<{
8
+ variant?: BadgeVariant
9
+ size?: BadgeSize
10
+ dot?: boolean
11
+ }>(), {
12
+ variant: 'default',
13
+ size: 'default',
14
+ })
15
+
16
+ const classes = computed(() => [
17
+ 'dt-badge',
18
+ `dt-badge--${props.variant}`,
19
+ `dt-badge--${props.size}`,
20
+ props.dot && 'dt-badge--dot',
21
+ ].filter(Boolean))
22
+ </script>
23
+
24
+ <template>
25
+ <span :class="classes" v-bind="$attrs">
26
+ <span v-if="dot" class="dt-badge__dot" aria-hidden="true" />
27
+ <slot />
28
+ </span>
29
+ </template>
30
+
31
+ <style scoped>
32
+ .dt-badge {
33
+ display: inline-flex;
34
+ align-items: center;
35
+ gap: var(--dt-space-1);
36
+ font-weight: 500;
37
+ border-radius: var(--dt-radius-full);
38
+ white-space: nowrap;
39
+ transition: background-color var(--dt-transition-base), color var(--dt-transition-base);
40
+ border: 1px solid transparent;
41
+ line-height: 1;
42
+ }
43
+
44
+ /* Sizes */
45
+ .dt-badge--sm {
46
+ padding: 0.125rem 0.5rem;
47
+ font-size: var(--dt-font-size-xs);
48
+ }
49
+ .dt-badge--default {
50
+ padding: 0.25rem 0.625rem;
51
+ font-size: var(--dt-font-size-sm);
52
+ }
53
+
54
+ /* Variants */
55
+ .dt-badge--default {
56
+ background-color: var(--dt-primary);
57
+ color: var(--dt-primary-foreground);
58
+ }
59
+
60
+ .dt-badge--secondary {
61
+ background-color: var(--dt-secondary);
62
+ color: var(--dt-secondary-foreground);
63
+ }
64
+
65
+ .dt-badge--outline {
66
+ border-color: var(--dt-border);
67
+ background-color: transparent;
68
+ color: var(--dt-foreground);
69
+ }
70
+
71
+ .dt-badge--destructive {
72
+ background-color: var(--dt-destructive);
73
+ color: var(--dt-destructive-foreground);
74
+ }
75
+
76
+ .dt-badge--success {
77
+ background-color: var(--dt-success);
78
+ color: var(--dt-success-foreground);
79
+ }
80
+
81
+ .dt-badge--warning {
82
+ background-color: var(--dt-warning);
83
+ color: var(--dt-warning-foreground);
84
+ }
85
+
86
+ /* Dot */
87
+ .dt-badge__dot {
88
+ width: 0.375rem;
89
+ height: 0.375rem;
90
+ border-radius: var(--dt-radius-full);
91
+ background-color: currentColor;
92
+ flex-shrink: 0;
93
+ }
94
+ </style>
@@ -0,0 +1,2 @@
1
+ export { default as DtBadge } from './DtBadge.vue'
2
+ export type { BadgeVariant, BadgeSize } from './DtBadge.vue'