aback-ui 0.0.0-stage → 0.2.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.
- package/LICENSE +21 -0
- package/README.md +85 -2
- package/dist/args.d.ts +15 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +91 -0
- package/dist/args.js.map +1 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +106 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add.d.ts +29 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +82 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/diff.d.ts +13 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +85 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +45 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +19 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +97 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +11 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +42 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/view.d.ts +11 -0
- package/dist/commands/view.d.ts.map +1 -0
- package/dist/commands/view.js +43 -0
- package/dist/commands/view.js.map +1 -0
- package/dist/config.d.ts +62 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +265 -0
- package/dist/config.js.map +1 -0
- package/dist/diff.d.ts +30 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +121 -0
- package/dist/diff.js.map +1 -0
- package/dist/doctor.d.ts +35 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +203 -0
- package/dist/doctor.js.map +1 -0
- package/dist/errors.d.ts +6 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +12 -0
- package/dist/errors.js.map +1 -0
- package/dist/help.d.ts +3 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +48 -0
- package/dist/help.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/install.d.ts +53 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +119 -0
- package/dist/install.js.map +1 -0
- package/dist/logger.d.ts +14 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +47 -0
- package/dist/logger.js.map +1 -0
- package/dist/paths.d.ts +18 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +76 -0
- package/dist/paths.js.map +1 -0
- package/dist/prompt.d.ts +13 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +25 -0
- package/dist/prompt.js.map +1 -0
- package/dist/registry.d.ts +49 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +216 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +88 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +59 -4
- package/registry/accordion.json +32 -0
- package/registry/alert-dialog.json +28 -0
- package/registry/alert.json +31 -0
- package/registry/article-layout.json +38 -0
- package/registry/avatar.json +31 -0
- package/registry/badge.json +33 -0
- package/registry/breadcrumbs.json +32 -0
- package/registry/button.json +34 -0
- package/registry/calendar.json +29 -0
- package/registry/card.json +30 -0
- package/registry/checkbox.json +33 -0
- package/registry/code-block.json +29 -0
- package/registry/collapsible.json +28 -0
- package/registry/combobox.json +30 -0
- package/registry/command.json +34 -0
- package/registry/contact-form.json +37 -0
- package/registry/cookie-consent.json +28 -0
- package/registry/copy-button.json +33 -0
- package/registry/cta-banner.json +32 -0
- package/registry/dashboard-shell.json +32 -0
- package/registry/date-picker.json +32 -0
- package/registry/description-list.json +28 -0
- package/registry/dialog.json +33 -0
- package/registry/dropdown-menu.json +33 -0
- package/registry/dropzone.json +31 -0
- package/registry/empty-state.json +32 -0
- package/registry/faq.json +31 -0
- package/registry/feature-grid.json +33 -0
- package/registry/field.json +29 -0
- package/registry/hero.json +32 -0
- package/registry/hover-card.json +28 -0
- package/registry/index.json +1633 -0
- package/registry/input-group.json +30 -0
- package/registry/input.json +29 -0
- package/registry/kbd.json +29 -0
- package/registry/label.json +29 -0
- package/registry/layout.json +32 -0
- package/registry/newsletter.json +35 -0
- package/registry/not-found.json +34 -0
- package/registry/page-header.json +29 -0
- package/registry/pagination.json +25 -0
- package/registry/popover.json +28 -0
- package/registry/pricing.json +35 -0
- package/registry/progress.json +28 -0
- package/registry/radio-group.json +28 -0
- package/registry/rating.json +32 -0
- package/registry/reading-progress.json +29 -0
- package/registry/relative-time.json +29 -0
- package/registry/scroll-area.json +28 -0
- package/registry/section-heading.json +30 -0
- package/registry/select.json +32 -0
- package/registry/separator.json +32 -0
- package/registry/settings-section.json +32 -0
- package/registry/share-buttons.json +34 -0
- package/registry/sheet.json +34 -0
- package/registry/sign-in.json +31 -0
- package/registry/site-footer.json +31 -0
- package/registry/site-header.json +37 -0
- package/registry/skeleton.json +28 -0
- package/registry/skip-link.json +30 -0
- package/registry/slider.json +28 -0
- package/registry/spinner.json +32 -0
- package/registry/stat.json +32 -0
- package/registry/steps.json +31 -0
- package/registry/switch.json +32 -0
- package/registry/table-of-contents.json +32 -0
- package/registry/table.json +28 -0
- package/registry/tabs.json +29 -0
- package/registry/textarea.json +29 -0
- package/registry/theme-toggle.json +34 -0
- package/registry/theme.json +16 -0
- package/registry/toast.json +29 -0
- package/registry/toggle-group.json +29 -0
- package/registry/tooltip.json +29 -0
- package/registry/users-table.json +36 -0
- package/registry/utils.json +19 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export interface RegistryFile {
|
|
2
|
+
path: string;
|
|
3
|
+
content: string;
|
|
4
|
+
type?: string;
|
|
5
|
+
target?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface RegistryItemMeta {
|
|
8
|
+
status?: string;
|
|
9
|
+
usedIn?: string[];
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
export interface RegistryItem {
|
|
13
|
+
name: string;
|
|
14
|
+
type: string;
|
|
15
|
+
title?: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
dependencies?: string[];
|
|
18
|
+
devDependencies?: string[];
|
|
19
|
+
registryDependencies?: string[];
|
|
20
|
+
categories?: string[];
|
|
21
|
+
docs?: string;
|
|
22
|
+
meta?: RegistryItemMeta;
|
|
23
|
+
files: RegistryFile[];
|
|
24
|
+
}
|
|
25
|
+
export interface RegistryIndexItem {
|
|
26
|
+
name: string;
|
|
27
|
+
type: string;
|
|
28
|
+
title: string;
|
|
29
|
+
description: string;
|
|
30
|
+
categories?: string[];
|
|
31
|
+
docs?: string;
|
|
32
|
+
dependencies?: string[];
|
|
33
|
+
registryDependencies?: string[];
|
|
34
|
+
meta?: RegistryItemMeta;
|
|
35
|
+
}
|
|
36
|
+
export interface RegistryIndex {
|
|
37
|
+
name?: string;
|
|
38
|
+
homepage?: string;
|
|
39
|
+
items: RegistryIndexItem[];
|
|
40
|
+
}
|
|
41
|
+
export type PackageManager = "bun" | "pnpm" | "yarn" | "npm";
|
|
42
|
+
export interface AbackConfig {
|
|
43
|
+
$schema?: string;
|
|
44
|
+
style?: string;
|
|
45
|
+
rsc?: boolean;
|
|
46
|
+
tsx?: boolean;
|
|
47
|
+
tailwind?: {
|
|
48
|
+
config?: string;
|
|
49
|
+
css?: string;
|
|
50
|
+
baseColor?: string;
|
|
51
|
+
cssVariables?: boolean;
|
|
52
|
+
[key: string]: unknown;
|
|
53
|
+
};
|
|
54
|
+
aliases?: {
|
|
55
|
+
components?: string;
|
|
56
|
+
utils?: string;
|
|
57
|
+
ui?: string;
|
|
58
|
+
lib?: string;
|
|
59
|
+
hooks?: string;
|
|
60
|
+
[key: string]: string | undefined;
|
|
61
|
+
};
|
|
62
|
+
registries?: Record<string, string>;
|
|
63
|
+
[key: string]: unknown;
|
|
64
|
+
}
|
|
65
|
+
export interface InstallDirs {
|
|
66
|
+
components: string;
|
|
67
|
+
ui: string;
|
|
68
|
+
blocks: string;
|
|
69
|
+
lib: string;
|
|
70
|
+
hooks: string;
|
|
71
|
+
styles: string;
|
|
72
|
+
}
|
|
73
|
+
export type OverwriteMode = "prompt" | "always" | "never";
|
|
74
|
+
export interface FileWriteResult {
|
|
75
|
+
item: string;
|
|
76
|
+
target: string;
|
|
77
|
+
absolutePath: string;
|
|
78
|
+
status: "written" | "unchanged" | "skipped";
|
|
79
|
+
}
|
|
80
|
+
export interface RegistryFetch {
|
|
81
|
+
(url: string): Promise<{
|
|
82
|
+
ok: boolean;
|
|
83
|
+
status: number;
|
|
84
|
+
json(): Promise<unknown>;
|
|
85
|
+
text(): Promise<string>;
|
|
86
|
+
}>;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC5B;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE;QACT,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;KACnC,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;CAC7C;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QACrB,EAAE,EAAE,OAAO,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;KACzB,CAAC,CAAC;CACJ"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aback-ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "The Aback UI command line: add accessible React components and blocks to your project as source you own.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Aback Group",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/devvrat-hans/aback-ui.git",
|
|
11
|
+
"directory": "packages/cli"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://abackui.com/docs/cli",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/devvrat-hans/aback-ui/issues"
|
|
16
|
+
},
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=20.9.0"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"bin": {
|
|
24
|
+
"aback-ui": "dist/index.js"
|
|
25
|
+
},
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./package.json": "./package.json"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"registry",
|
|
36
|
+
"LICENSE",
|
|
37
|
+
"README.md"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "rm -rf dist registry node_modules/.cache && tsc -p tsconfig.build.json && chmod +x dist/index.js && bun ../../scripts/bundle-registry.mjs",
|
|
41
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"test:watch": "vitest",
|
|
44
|
+
"prepublishOnly": "bun run typecheck && bun run test && bun run build && bun ../../scripts/verify-publishable.mjs"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^24.10.1",
|
|
48
|
+
"typescript": "^5.9.3",
|
|
49
|
+
"vitest": "^5.0.5"
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"aback",
|
|
53
|
+
"aback-ui",
|
|
54
|
+
"cli",
|
|
55
|
+
"components",
|
|
56
|
+
"design-system",
|
|
57
|
+
"react",
|
|
58
|
+
"tailwindcss",
|
|
59
|
+
"ui"
|
|
60
|
+
]
|
|
61
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "accordion",
|
|
4
|
+
"type": "registry:ui",
|
|
5
|
+
"title": "Accordion",
|
|
6
|
+
"description": "Disclosure sections for FAQs and grouped settings, with full keyboard support.",
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"radix-ui",
|
|
9
|
+
"@tabler/icons-react"
|
|
10
|
+
],
|
|
11
|
+
"registryDependencies": [
|
|
12
|
+
"https://abackui.com/r/utils.json"
|
|
13
|
+
],
|
|
14
|
+
"categories": [
|
|
15
|
+
"Navigation"
|
|
16
|
+
],
|
|
17
|
+
"docs": "https://abackui.com/docs/components/accordion",
|
|
18
|
+
"meta": {
|
|
19
|
+
"status": "stable",
|
|
20
|
+
"usedIn": [
|
|
21
|
+
"aback-tools"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
{
|
|
26
|
+
"path": "components/ui/accordion.tsx",
|
|
27
|
+
"content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\nimport { IconChevronDown } from \"@tabler/icons-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nfunction AccordionItem({\n className,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Item>) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\"border-b border-border\", className)}\n {...props}\n />\n );\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n \"flex flex-1 items-center justify-between gap-3 py-4 text-left text-sm font-medium text-foreground\",\n \"outline-none transition-colors duration-200 hover:text-link\",\n \"focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n \"[&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <IconChevronDown\n aria-hidden=\"true\"\n className=\"size-5 shrink-0 text-muted-foreground transition-transform duration-200\"\n />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n );\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Content>) {\n return (\n <AccordionPrimitive.Content\n data-slot=\"accordion-content\"\n className={cn(\n \"overflow-hidden text-sm text-muted-foreground\",\n \"data-[state=open]:animate-[accordion-down_200ms_ease-out] data-[state=closed]:animate-[accordion-up_200ms_ease-out]\",\n )}\n {...props}\n >\n <div className={cn(\"pb-4 leading-relaxed\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n );\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
|
28
|
+
"type": "registry:ui",
|
|
29
|
+
"target": "components/ui/accordion.tsx"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "alert-dialog",
|
|
4
|
+
"type": "registry:ui",
|
|
5
|
+
"title": "Alert Dialog",
|
|
6
|
+
"description": "A modal that requires an explicit response before an irreversible action runs.",
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"radix-ui"
|
|
9
|
+
],
|
|
10
|
+
"registryDependencies": [
|
|
11
|
+
"https://abackui.com/r/utils.json"
|
|
12
|
+
],
|
|
13
|
+
"categories": [
|
|
14
|
+
"Overlays"
|
|
15
|
+
],
|
|
16
|
+
"docs": "https://abackui.com/docs/components/alert-dialog",
|
|
17
|
+
"meta": {
|
|
18
|
+
"status": "beta"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
{
|
|
22
|
+
"path": "components/ui/alert-dialog.tsx",
|
|
23
|
+
"content": "\"use client\";\n\nimport * as React from \"react\";\nimport { AlertDialog as AlertDialogPrimitive } from \"radix-ui\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst buttonBase =\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap text-sm font-medium outline-none transition-colors duration-200 focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50\";\nconst buttonSizes = {\n default: \"h-9 px-4\",\n sm: \"h-8 px-3\",\n} as const;\n\nfunction AlertDialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {\n return (\n <AlertDialogPrimitive.Overlay\n data-slot=\"alert-dialog-overlay\"\n className={cn(\n \"fixed inset-0 z-50 bg-black/40 backdrop-blur-sm dark:bg-black/60\",\n \"data-[state=open]:animate-in data-[state=open]:fade-in-0\",\n \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AlertDialogContent({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {\n return (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n data-slot=\"alert-dialog-content\"\n className={cn(\n \"fixed left-1/2 top-1/2 z-50 grid max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)] max-w-md -translate-x-1/2 -translate-y-1/2 gap-4 overflow-y-auto\",\n \"border border-border bg-popover p-6 text-popover-foreground shadow-2xl\",\n \"duration-200 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95\",\n \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n );\n}\n\nfunction AlertDialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div data-slot=\"alert-dialog-header\" className={cn(\"flex flex-col gap-1.5\", className)} {...props} />;\n}\n\nfunction AlertDialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-footer\"\n className={cn(\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\", className)}\n {...props}\n />\n );\n}\n\nfunction AlertDialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {\n return (\n <AlertDialogPrimitive.Title\n data-slot=\"alert-dialog-title\"\n className={cn(\"text-lg font-semibold leading-none tracking-tight\", className)}\n {...props}\n />\n );\n}\n\nfunction AlertDialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {\n return (\n <AlertDialogPrimitive.Description\n data-slot=\"alert-dialog-description\"\n className={cn(\"text-sm leading-relaxed text-muted-foreground\", className)}\n {...props}\n />\n );\n}\n\nfunction AlertDialogAction({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {\n return (\n <AlertDialogPrimitive.Action\n data-slot=\"alert-dialog-action\"\n className={cn(\n buttonBase,\n buttonSizes.default,\n \"bg-primary text-primary-foreground hover:bg-primary/90\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AlertDialogCancel({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {\n return (\n <AlertDialogPrimitive.Cancel\n data-slot=\"alert-dialog-cancel\"\n className={cn(\n buttonBase,\n buttonSizes.default,\n \"border border-input bg-background text-foreground shadow-xs hover:bg-muted\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n AlertDialog,\n AlertDialogTrigger,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
|
24
|
+
"type": "registry:ui",
|
|
25
|
+
"target": "components/ui/alert-dialog.tsx"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "alert",
|
|
4
|
+
"type": "registry:ui",
|
|
5
|
+
"title": "Alert",
|
|
6
|
+
"description": "Inline status messages for information, success, warning, and destructive feedback.",
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"class-variance-authority"
|
|
9
|
+
],
|
|
10
|
+
"registryDependencies": [
|
|
11
|
+
"https://abackui.com/r/utils.json"
|
|
12
|
+
],
|
|
13
|
+
"categories": [
|
|
14
|
+
"Feedback"
|
|
15
|
+
],
|
|
16
|
+
"docs": "https://abackui.com/docs/components/alert",
|
|
17
|
+
"meta": {
|
|
18
|
+
"status": "stable",
|
|
19
|
+
"usedIn": [
|
|
20
|
+
"aback-launch"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
{
|
|
25
|
+
"path": "components/ui/alert.tsx",
|
|
26
|
+
"content": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative flex w-full items-start gap-2.5 border p-3 text-sm [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:translate-y-0.5\",\n {\n variants: {\n variant: {\n info:\n \"border-primary-200 bg-brand-wash/60 text-foreground dark:border-primary-800/60\",\n success: \"border-success/25 bg-success-soft text-success-strong\",\n warning: \"border-warning/25 bg-warning-soft text-warning-strong\",\n destructive: \"border-danger/25 bg-danger-soft text-danger-strong\",\n muted: \"border-border bg-muted/40 text-foreground\",\n },\n },\n defaultVariants: {\n variant: \"info\",\n },\n },\n);\n\nexport interface AlertProps\n extends React.ComponentProps<\"div\">,\n VariantProps<typeof alertVariants> {}\n\nfunction Alert({ className, variant = \"info\", ...props }: AlertProps) {\n return (\n <div\n data-slot=\"alert\"\n data-variant={variant}\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nfunction AlertTitle({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"alert-title\"\n className={cn(\"font-medium leading-snug\", className)}\n {...props}\n />\n );\n}\n\nfunction AlertDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-description\"\n className={cn(\"text-sm leading-relaxed text-current\", className)}\n {...props}\n />\n );\n}\n\nexport { Alert, AlertTitle, AlertDescription, alertVariants };\n",
|
|
27
|
+
"type": "registry:ui",
|
|
28
|
+
"target": "components/ui/alert.tsx"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "article-layout",
|
|
4
|
+
"type": "registry:block",
|
|
5
|
+
"title": "Article layout",
|
|
6
|
+
"description": "A long-form page with meta bar, scoped typography, sticky contents, share links, and reading progress.",
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"@tabler/icons-react"
|
|
9
|
+
],
|
|
10
|
+
"registryDependencies": [
|
|
11
|
+
"https://abackui.com/r/avatar.json",
|
|
12
|
+
"https://abackui.com/r/badge.json",
|
|
13
|
+
"https://abackui.com/r/breadcrumbs.json",
|
|
14
|
+
"https://abackui.com/r/collapsible.json",
|
|
15
|
+
"https://abackui.com/r/reading-progress.json",
|
|
16
|
+
"https://abackui.com/r/share-buttons.json",
|
|
17
|
+
"https://abackui.com/r/table-of-contents.json"
|
|
18
|
+
],
|
|
19
|
+
"categories": [
|
|
20
|
+
"Content"
|
|
21
|
+
],
|
|
22
|
+
"docs": "https://abackui.com/docs/blocks/article-layout",
|
|
23
|
+
"meta": {
|
|
24
|
+
"status": "beta",
|
|
25
|
+
"usedIn": [
|
|
26
|
+
"aback-tools",
|
|
27
|
+
"aback-launch"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
{
|
|
32
|
+
"path": "components/blocks/article-layout.tsx",
|
|
33
|
+
"content": "\"use client\";\n\nimport { type ReactNode, useId, useRef } from \"react\";\nimport { IconCalendar, IconChevronDown, IconClock } from \"@tabler/icons-react\";\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Breadcrumbs, type BreadcrumbItem } from \"@/components/ui/breadcrumbs\";\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from \"@/components/ui/collapsible\";\nimport { ReadingProgress } from \"@/components/ui/reading-progress\";\nimport { ShareButtons } from \"@/components/ui/share-buttons\";\nimport { TableOfContents, type TableOfContentsItem } from \"@/components/ui/table-of-contents\";\n\nexport interface ArticleAuthor {\n name: string;\n role?: string;\n initials?: string;\n avatarUrl?: string;\n}\n\nexport interface ArticleLayoutBlockProps {\n title: string;\n /** The lead paragraph under the title. */\n description?: ReactNode;\n category?: string;\n author: ArticleAuthor;\n /** ISO date of publication. Rendered as a stable absolute date. */\n publishedAt: string;\n /** Such as \"6 min read\". Compute it from the real word count. */\n readingTime?: string;\n breadcrumbs?: BreadcrumbItem[];\n /** One entry per h2 or h3 in the body, by id. */\n toc?: TableOfContentsItem[];\n /** The canonical URL, for the share links. */\n shareUrl?: string;\n /** The article body. Plain h2, h3, p, ul, ol, blockquote, and code are styled. */\n children: ReactNode;\n}\n\n// Typography for the body, scoped to this block so it never leaks into the page.\nconst prose = [\n \"flex min-w-0 max-w-[72ch] flex-col gap-4 text-sm leading-relaxed text-muted-foreground\",\n \"[&_h2]:mt-6 [&_h2]:scroll-mt-24 [&_h2]:text-2xl [&_h2]:font-bold [&_h2]:tracking-tight [&_h2]:text-foreground\",\n \"[&_h3]:mt-2 [&_h3]:scroll-mt-24 [&_h3]:text-lg [&_h3]:font-semibold [&_h3]:text-foreground\",\n \"[&_strong]:font-semibold [&_strong]:text-foreground\",\n \"[&_a]:text-link [&_a]:underline [&_a]:underline-offset-4 [&_a:hover]:text-link-hover\",\n \"[&_ul]:ml-6 [&_ul]:list-disc [&_ul]:space-y-1.5 [&_ol]:ml-6 [&_ol]:list-decimal [&_ol]:space-y-1.5 [&_li]:marker:text-muted-foreground\",\n \"[&_blockquote]:border-l-4 [&_blockquote]:border-primary-300 [&_blockquote]:py-1 [&_blockquote]:pl-4 [&_blockquote]:italic dark:[&_blockquote]:border-primary-500\",\n \"[&_:not(pre)>code]:bg-muted [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:font-mono [&_:not(pre)>code]:text-[0.9em] [&_:not(pre)>code]:text-foreground\",\n].join(\" \");\n\nfunction initialsOf(name: string) {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n return parts.length > 1 ? `${parts[0]![0]}${parts[1]![0]}`.toUpperCase() : name.slice(0, 2).toUpperCase();\n}\n\n/**\n * A long-form article page: breadcrumbs, title, author and meta bar, a body\n * with scoped typography, a sticky \"On this page\" list, share links, and a\n * reading progress bar. The aside appears when the block's own container is\n * wide enough, so it adapts inside narrow layouts as well as on wide screens.\n */\nexport function ArticleLayoutBlock({\n title,\n description,\n category,\n author,\n publishedAt,\n readingTime,\n breadcrumbs,\n toc = [],\n shareUrl,\n children,\n}: ArticleLayoutBlockProps) {\n const headingId = useId();\n const article = useRef<HTMLElement>(null);\n const published = new Date(publishedAt);\n const validDate = !Number.isNaN(published.getTime());\n\n return (\n <div className=\"@container mx-auto w-full max-w-6xl px-4 py-10 md:px-6\">\n <ReadingProgress target={article} />\n <article ref={article} className=\"flex flex-col gap-6\" aria-labelledby={headingId}>\n <header className=\"flex flex-col gap-4\">\n {breadcrumbs?.length ? <Breadcrumbs items={breadcrumbs} /> : null}\n {category ? <Badge variant=\"brand\" className=\"self-start\">{category}</Badge> : null}\n <h1 id={headingId} className=\"max-w-3xl text-3xl font-bold leading-tight tracking-tight text-foreground text-balance sm:text-4xl\">\n {title}\n </h1>\n {description ? (\n <p className=\"max-w-[72ch] text-base leading-relaxed text-muted-foreground\">{description}</p>\n ) : null}\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-3 border border-border bg-muted/20 p-4\">\n <div className=\"flex items-center gap-3\">\n <Avatar size=\"lg\">\n {author.avatarUrl ? <AvatarImage src={author.avatarUrl} alt=\"\" /> : null}\n <AvatarFallback>{author.initials ?? initialsOf(author.name)}</AvatarFallback>\n </Avatar>\n <div className=\"flex flex-col\">\n <span className=\"text-sm font-semibold text-foreground\">{author.name}</span>\n {author.role ? <span className=\"text-xs text-muted-foreground\">{author.role}</span> : null}\n </div>\n </div>\n <span aria-hidden=\"true\" className=\"hidden h-8 w-px bg-border sm:block\" />\n <ul className=\"flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground\">\n {validDate ? (\n <li className=\"flex items-center gap-1.5\">\n <IconCalendar aria-hidden=\"true\" className=\"size-3.5\" />\n <span className=\"sr-only\">Published </span>\n <time dateTime={published.toISOString()}>\n {new Intl.DateTimeFormat(\"en-US\", { dateStyle: \"medium\", timeZone: \"UTC\" }).format(published)}\n </time>\n </li>\n ) : null}\n {readingTime ? (\n <li className=\"flex items-center gap-1.5\">\n <IconClock aria-hidden=\"true\" className=\"size-3.5\" />\n {readingTime}\n </li>\n ) : null}\n </ul>\n </div>\n </header>\n\n {toc.length ? (\n <Collapsible className=\"border border-border bg-muted/20 @3xl:hidden\">\n <CollapsibleTrigger className=\"group flex w-full items-center justify-between px-4 py-3 text-sm font-semibold text-foreground outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus-ring\">\n Contents\n <IconChevronDown\n aria-hidden=\"true\"\n className=\"size-4 text-muted-foreground transition-transform duration-200 group-data-[state=open]:rotate-180 motion-reduce:transition-none\"\n />\n </CollapsibleTrigger>\n <CollapsibleContent className=\"px-4 pb-4\">\n <TableOfContents items={toc} />\n </CollapsibleContent>\n </Collapsible>\n ) : null}\n\n <div className=\"grid gap-10 @3xl:grid-cols-[minmax(0,1fr)_240px] @3xl:items-start\">\n <div className=\"flex min-w-0 flex-col gap-10\">\n <div className={prose}>{children}</div>\n {shareUrl ? (\n <footer className=\"flex flex-wrap items-center justify-between gap-3 border-t border-border pt-6\">\n <span className=\"text-sm font-medium text-foreground\">Share this article</span>\n <ShareButtons url={shareUrl} title={title} networks={[\"x\", \"linkedin\", \"email\"]} />\n </footer>\n ) : null}\n </div>\n {toc.length ? (\n <aside className=\"hidden @3xl:sticky @3xl:top-20 @3xl:block @3xl:max-h-[calc(100vh-6rem)] @3xl:overflow-y-auto\">\n <TableOfContents items={toc} className=\"border border-border bg-muted/20 p-4\" />\n </aside>\n ) : null}\n </div>\n </article>\n </div>\n );\n}\n",
|
|
34
|
+
"type": "registry:block",
|
|
35
|
+
"target": "components/blocks/article-layout.tsx"
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "avatar",
|
|
4
|
+
"type": "registry:ui",
|
|
5
|
+
"title": "Avatar",
|
|
6
|
+
"description": "A square identity chip with an initials fallback, and an overlapping group with a counted overflow.",
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"radix-ui"
|
|
9
|
+
],
|
|
10
|
+
"registryDependencies": [
|
|
11
|
+
"https://abackui.com/r/utils.json"
|
|
12
|
+
],
|
|
13
|
+
"categories": [
|
|
14
|
+
"Data Display"
|
|
15
|
+
],
|
|
16
|
+
"docs": "https://abackui.com/docs/components/avatar",
|
|
17
|
+
"meta": {
|
|
18
|
+
"status": "beta",
|
|
19
|
+
"usedIn": [
|
|
20
|
+
"aback-launch"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
{
|
|
25
|
+
"path": "components/ui/avatar.tsx",
|
|
26
|
+
"content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Avatar as AvatarPrimitive } from \"radix-ui\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype AvatarSize = \"xs\" | \"sm\" | \"default\" | \"lg\" | \"xl\";\n\nconst sizeClasses: Record<AvatarSize, string> = {\n xs: \"size-6 text-[10px]\",\n sm: \"size-8 text-xs\",\n default: \"size-9 text-xs\",\n lg: \"size-11 text-sm\",\n xl: \"size-14 text-base\",\n};\n\nexport interface AvatarProps extends React.ComponentProps<typeof AvatarPrimitive.Root> {\n size?: AvatarSize;\n}\n\nfunction Avatar({ className, size = \"default\", ...props }: AvatarProps) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n data-size={size}\n className={cn(\n \"relative inline-flex shrink-0 overflow-hidden border border-border bg-muted\",\n sizeClasses[size],\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AvatarImage({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square size-full object-cover\", className)}\n {...props}\n />\n );\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"flex size-full items-center justify-center bg-muted font-medium uppercase tracking-wide text-foreground\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport interface AvatarGroupProps extends React.ComponentProps<\"div\"> {\n /** Avatars shown before the rest collapse into a \"+N\" count. */\n max?: number;\n /** Total people the group stands for, when more exist than were rendered. */\n total?: number;\n /** Size of the overflow count. Match it to the avatars in the group. */\n size?: AvatarSize;\n}\n\n/**\n * Overlapping avatars for a team, reviewers, or recent participants. Extra\n * people collapse into a count with a text alternative. Name the group with\n * `aria-label` and keep each avatar's alt text, so the list is not only faces.\n */\nfunction AvatarGroup({\n max,\n total,\n size = \"default\",\n className,\n children,\n ...props\n}: AvatarGroupProps) {\n const items = React.Children.toArray(children);\n const visible = max === undefined ? items : items.slice(0, Math.max(0, max));\n const overflow = Math.max(0, (total ?? items.length) - visible.length);\n\n return (\n <div\n role=\"group\"\n data-slot=\"avatar-group\"\n className={cn(\n \"flex items-center -space-x-2 [&>[data-slot=avatar]]:border-2 [&>[data-slot=avatar]]:border-background\",\n className,\n )}\n {...props}\n >\n {visible}\n {overflow > 0 ? (\n <span\n data-slot=\"avatar-group-overflow\"\n className={cn(\n \"relative inline-flex shrink-0 items-center justify-center border-2 border-background bg-secondary font-medium tabular-nums text-secondary-foreground\",\n sizeClasses[size],\n )}\n >\n <span aria-hidden=\"true\">+{overflow}</span>\n <span className=\"sr-only\">and {overflow} more</span>\n </span>\n ) : null}\n </div>\n );\n}\n\nexport { Avatar, AvatarImage, AvatarFallback, AvatarGroup };\n",
|
|
27
|
+
"type": "registry:ui",
|
|
28
|
+
"target": "components/ui/avatar.tsx"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "badge",
|
|
4
|
+
"type": "registry:ui",
|
|
5
|
+
"title": "Badge",
|
|
6
|
+
"description": "Compact labels for status, counts, and categories, with soft status variants and an optional dot.",
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"class-variance-authority"
|
|
9
|
+
],
|
|
10
|
+
"registryDependencies": [
|
|
11
|
+
"https://abackui.com/r/utils.json"
|
|
12
|
+
],
|
|
13
|
+
"categories": [
|
|
14
|
+
"Foundation"
|
|
15
|
+
],
|
|
16
|
+
"docs": "https://abackui.com/docs/components/badge",
|
|
17
|
+
"meta": {
|
|
18
|
+
"status": "stable",
|
|
19
|
+
"usedIn": [
|
|
20
|
+
"aback-tools",
|
|
21
|
+
"aback-launch",
|
|
22
|
+
"aback-group"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
{
|
|
27
|
+
"path": "components/ui/badge.tsx",
|
|
28
|
+
"content": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst badgeVariants = cva(\n \"inline-flex shrink-0 items-center gap-1 border px-2.5 py-0.5 text-xs font-semibold leading-4 [&_svg]:size-3 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"border-transparent bg-primary text-primary-foreground\",\n secondary: \"border-transparent bg-secondary text-secondary-foreground\",\n outline: \"border-border text-foreground\",\n brand:\n \"border-primary-200 bg-brand-chip text-primary-700 dark:border-primary-800/40 dark:text-primary-300\",\n success: \"border-success/20 bg-success-soft text-success-strong\",\n warning: \"border-warning/20 bg-warning-soft text-warning-strong\",\n danger: \"border-danger/20 bg-danger-soft text-danger-strong\",\n info: \"border-info/20 bg-info-soft text-info\",\n destructive: \"border-transparent bg-destructive text-destructive-foreground\",\n muted: \"border-transparent bg-muted/60 text-muted-foreground\",\n },\n },\n defaultVariants: {\n variant: \"secondary\",\n },\n },\n);\n\nexport interface BadgeProps\n extends React.ComponentProps<\"span\">,\n VariantProps<typeof badgeVariants> {\n /**\n * Leads with a small square status dot in the badge's text colour. The dot\n * is decorative; the badge text still has to say what the status is.\n */\n dot?: boolean;\n}\n\nfunction Badge({ className, variant = \"secondary\", dot = false, children, ...props }: BadgeProps) {\n return (\n <span\n data-slot=\"badge\"\n data-variant={variant}\n className={cn(badgeVariants({ variant }), dot && \"gap-1.5\", className)}\n {...props}\n >\n {dot ? (\n <span aria-hidden=\"true\" data-slot=\"badge-dot\" className=\"size-1.5 shrink-0 bg-current\" />\n ) : null}\n {children}\n </span>\n );\n}\n\nexport { Badge, badgeVariants };\n",
|
|
29
|
+
"type": "registry:ui",
|
|
30
|
+
"target": "components/ui/badge.tsx"
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "breadcrumbs",
|
|
4
|
+
"type": "registry:ui",
|
|
5
|
+
"title": "Breadcrumbs",
|
|
6
|
+
"description": "A hierarchical trail back to parent pages with current-page semantics.",
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"@tabler/icons-react"
|
|
9
|
+
],
|
|
10
|
+
"registryDependencies": [
|
|
11
|
+
"https://abackui.com/r/utils.json"
|
|
12
|
+
],
|
|
13
|
+
"categories": [
|
|
14
|
+
"Navigation"
|
|
15
|
+
],
|
|
16
|
+
"docs": "https://abackui.com/docs/components/breadcrumbs",
|
|
17
|
+
"meta": {
|
|
18
|
+
"status": "stable",
|
|
19
|
+
"usedIn": [
|
|
20
|
+
"aback-tools",
|
|
21
|
+
"aback-launch"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
{
|
|
26
|
+
"path": "components/ui/breadcrumbs.tsx",
|
|
27
|
+
"content": "import * as React from \"react\";\nimport { IconChevronRight } from \"@tabler/icons-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport interface BreadcrumbItem {\n label: React.ReactNode;\n href?: string;\n}\n\nexport interface BreadcrumbsProps extends React.ComponentProps<\"nav\"> {\n items: BreadcrumbItem[];\n}\n\nfunction Breadcrumbs({ items, className, ...props }: BreadcrumbsProps) {\n return (\n <nav\n data-slot=\"breadcrumbs\"\n aria-label=\"Breadcrumb\"\n className={cn(\"text-sm\", className)}\n {...props}\n >\n <ol className=\"flex flex-wrap items-center gap-1\">\n {items.map((item, index) => {\n const isCurrent = index === items.length - 1;\n return (\n <li key={item.href ?? index} className=\"flex items-center gap-1\">\n {index > 0 ? (\n <IconChevronRight\n aria-hidden=\"true\"\n className=\"mx-0.5 size-3.5 shrink-0 text-muted-foreground\"\n />\n ) : null}\n {item.href && !isCurrent ? (\n <a\n href={item.href}\n className={cn(\n \"text-muted-foreground underline-offset-4 transition-colors hover:text-foreground hover:underline\",\n \"outline-none focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n )}\n >\n {item.label}\n </a>\n ) : (\n <span\n aria-current={isCurrent ? \"page\" : undefined}\n className={cn(isCurrent ? \"font-medium text-foreground\" : \"text-muted-foreground\")}\n >\n {item.label}\n </span>\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n );\n}\n\nexport { Breadcrumbs };\n",
|
|
28
|
+
"type": "registry:ui",
|
|
29
|
+
"target": "components/ui/breadcrumbs.tsx"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "button",
|
|
4
|
+
"type": "registry:ui",
|
|
5
|
+
"title": "Button",
|
|
6
|
+
"description": "The primary action, with ink, brand, outline, ghost, and destructive variants.",
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"class-variance-authority",
|
|
9
|
+
"radix-ui"
|
|
10
|
+
],
|
|
11
|
+
"registryDependencies": [
|
|
12
|
+
"https://abackui.com/r/utils.json"
|
|
13
|
+
],
|
|
14
|
+
"categories": [
|
|
15
|
+
"Foundation"
|
|
16
|
+
],
|
|
17
|
+
"docs": "https://abackui.com/docs/components/button",
|
|
18
|
+
"meta": {
|
|
19
|
+
"status": "stable",
|
|
20
|
+
"usedIn": [
|
|
21
|
+
"aback-tools",
|
|
22
|
+
"aback-launch",
|
|
23
|
+
"aback-group"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
{
|
|
28
|
+
"path": "components/ui/button.tsx",
|
|
29
|
+
"content": "import * as React from \"react\";\nimport { Slot } from \"radix-ui\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst buttonVariants = cva(\n [\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap text-sm font-medium\",\n \"outline-none transition-[color,background-color,border-color,transform,opacity] duration-200\",\n \"focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n \"disabled:pointer-events-none disabled:opacity-50 active:scale-[0.98]\",\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n ],\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n brand:\n \"bg-brand-fill text-on-brand-fill hover:bg-link-hover dark:hover:bg-primary-300\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background text-foreground shadow-xs hover:bg-muted\",\n secondary: \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"text-foreground hover:bg-muted\",\n link: \"text-link underline-offset-4 hover:text-link-hover hover:underline\",\n },\n size: {\n xs: \"h-6 gap-1 px-2 text-xs [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1.5 px-3\",\n default: \"h-9 px-4 has-[>svg]:px-3\",\n lg: \"h-10 px-6\",\n icon: \"size-9\",\n \"icon-sm\": \"size-8\",\n \"icon-xs\": \"size-6 [&_svg:not([class*='size-'])]:size-3\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nexport interface ButtonProps\n extends React.ComponentProps<\"button\">,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: ButtonProps) {\n const Comp = asChild ? Slot.Root : \"button\";\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n",
|
|
30
|
+
"type": "registry:ui",
|
|
31
|
+
"target": "components/ui/button.tsx"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "calendar",
|
|
4
|
+
"type": "registry:ui",
|
|
5
|
+
"title": "Calendar",
|
|
6
|
+
"description": "A square-cornered month grid with single, multiple, and range selection.",
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"@tabler/icons-react",
|
|
9
|
+
"react-day-picker"
|
|
10
|
+
],
|
|
11
|
+
"registryDependencies": [
|
|
12
|
+
"https://abackui.com/r/utils.json"
|
|
13
|
+
],
|
|
14
|
+
"categories": [
|
|
15
|
+
"Data Display"
|
|
16
|
+
],
|
|
17
|
+
"docs": "https://abackui.com/docs/components/calendar",
|
|
18
|
+
"meta": {
|
|
19
|
+
"status": "beta"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
{
|
|
23
|
+
"path": "components/ui/calendar.tsx",
|
|
24
|
+
"content": "\"use client\";\n\nimport * as React from \"react\";\nimport {\n DateLib,\n DayPicker,\n type ClassNames,\n type CustomComponents,\n type DayPickerProps,\n type Labels,\n} from \"react-day-picker\";\nimport { IconChevronDown, IconChevronLeft, IconChevronRight, IconChevronUp } from \"@tabler/icons-react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/** The `{ from, to }` shape used by range mode, re-exported so consumers do not need a direct dependency. */\nexport type { DateRange } from \"react-day-picker\";\n\nexport type CalendarProps = DayPickerProps & {\n className?: string;\n /**\n * Override individual slots. Slots you omit keep the Aback styling, so a\n * consumer can adjust one element without restyling the whole calendar.\n */\n classNames?: Partial<ClassNames>;\n};\n\nconst DEFAULT_FORMAT: Intl.DateTimeFormatOptions = {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n};\n\n/** Format a date in the visitor's locale, without pulling in a date library. */\nexport function formatCalendarDate(\n date: Date,\n locale?: string,\n options: Intl.DateTimeFormatOptions = DEFAULT_FORMAT,\n): string {\n return new Intl.DateTimeFormat(locale, options).format(date);\n}\n\nconst navButton =\n \"absolute top-0 z-10 inline-flex size-8 items-center justify-center border border-transparent text-muted-foreground transition-colors \" +\n \"hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring \" +\n \"disabled:pointer-events-none disabled:opacity-40\";\n\nconst defaultClassNames: Partial<ClassNames> = {\n root: \"relative w-fit\",\n months: \"flex flex-col gap-4 sm:flex-row sm:gap-6\",\n month: \"relative flex flex-col gap-3\",\n month_caption: \"flex h-8 items-center justify-center px-9\",\n caption_label: \"text-sm font-semibold text-foreground\",\n nav: \"contents\",\n button_previous: cn(navButton, \"left-0\"),\n button_next: cn(navButton, \"right-0\"),\n chevron: \"size-4\",\n month_grid: \"w-full border-collapse\",\n weekdays: \"\",\n weekday:\n \"h-8 w-9 p-0 text-[11px] font-medium uppercase tracking-wide text-muted-foreground\",\n week: \"\",\n day: \"p-0 text-center align-middle\",\n day_button:\n \"mx-auto flex size-9 items-center justify-center text-sm font-normal text-foreground transition-colors \" +\n \"hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus-ring \" +\n \"disabled:pointer-events-none disabled:opacity-40\",\n selected:\n \"[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:font-medium\",\n today: \"[&:not([data-selected=true])>button]:font-semibold [&:not([data-selected=true])>button]:text-brand\",\n outside: \"[&>button]:text-muted-foreground [&>button]:hover:text-foreground\",\n disabled: \"[&>button]:text-muted-foreground/40 [&>button]:line-through\",\n hidden: \"invisible\",\n range_middle:\n \"[&[data-selected=true].rdp-range_middle>button]:bg-muted \" +\n \"[&[data-selected=true].rdp-range_middle>button]:text-foreground \" +\n \"[&[data-selected=true].rdp-range_middle>button]:hover:bg-muted\",\n dropdowns: \"flex items-center justify-center gap-2 px-9\",\n dropdown_root: \"relative inline-flex items-center\",\n dropdown:\n \"h-8 appearance-none border border-input bg-background px-2 pr-6 text-sm text-foreground outline-none \" +\n \"focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-focus-ring\",\n footer: \"border-t border-border px-2 pt-3 text-xs text-muted-foreground\",\n};\n\n// A day button shows only its number, so its accessible name must contain that\n// number as a word (WCAG 2.5.3, Label in Name). The library default reads\n// \"November 1st\", which does not; this reads \"Sunday, November 1, 2026\".\nconst defaultLabels: Partial<Labels> = {\n labelDayButton: (date, modifiers, options, dateLib) => {\n let label = (dateLib ?? new DateLib(options)).format(date, \"EEEE, MMMM d, yyyy\");\n if (modifiers.today) label = `Today, ${label}`;\n if (modifiers.selected) label = `${label}, selected`;\n return label;\n },\n};\n\nconst defaultComponents: Partial<CustomComponents> = {\n Chevron: ({ orientation = \"left\", className, size = 16 }) => {\n const Icon =\n orientation === \"left\"\n ? IconChevronLeft\n : orientation === \"right\"\n ? IconChevronRight\n : orientation === \"up\"\n ? IconChevronUp\n : IconChevronDown;\n return <Icon aria-hidden=\"true\" className={cn(\"size-4\", className)} size={size} />;\n },\n};\n\n/**\n * A month calendar with single, multiple, and range selection.\n *\n * The calendar is a composed control: use it on its own, inside a `Popover`\n * (see `DatePicker`), or inside a dialog. Every date is a real button inside a\n * `grid`, so arrow-key navigation, Home/End, Page Up/Page Down, and the\n * announced selected state come from react-day-picker's accessible grid.\n */\nfunction Calendar({\n className,\n classNames,\n components,\n labels,\n showOutsideDays = true,\n navLayout = \"around\",\n ...props\n}: CalendarProps) {\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n navLayout={navLayout}\n className={cn(\"w-fit bg-background p-3 text-foreground\", className)}\n classNames={{ ...defaultClassNames, ...classNames }}\n components={{ ...defaultComponents, ...components }}\n labels={{ ...defaultLabels, ...labels }}\n {...props}\n />\n );\n}\n\nexport { Calendar };\n",
|
|
25
|
+
"type": "registry:ui",
|
|
26
|
+
"target": "components/ui/calendar.tsx"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "card",
|
|
4
|
+
"type": "registry:ui",
|
|
5
|
+
"title": "Card",
|
|
6
|
+
"description": "A bordered surface for grouping related content and actions.",
|
|
7
|
+
"registryDependencies": [
|
|
8
|
+
"https://abackui.com/r/utils.json"
|
|
9
|
+
],
|
|
10
|
+
"categories": [
|
|
11
|
+
"Foundation"
|
|
12
|
+
],
|
|
13
|
+
"docs": "https://abackui.com/docs/components/card",
|
|
14
|
+
"meta": {
|
|
15
|
+
"status": "stable",
|
|
16
|
+
"usedIn": [
|
|
17
|
+
"aback-tools",
|
|
18
|
+
"aback-launch",
|
|
19
|
+
"aback-group"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
{
|
|
24
|
+
"path": "components/ui/card.tsx",
|
|
25
|
+
"content": "import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Card({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"flex flex-col gap-6 border border-border bg-card py-6 text-card-foreground shadow-sm\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CardTitle({\n className,\n as: Comp = \"h3\",\n ...props\n}: React.ComponentProps<\"h3\"> & { as?: \"h2\" | \"h3\" | \"h4\" }) {\n return (\n <Comp\n data-slot=\"card-title\"\n className={cn(\"font-semibold leading-none tracking-tight\", className)}\n {...props}\n />\n );\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"card-description\"\n className={cn(\"text-sm leading-relaxed text-muted-foreground\", className)}\n {...props}\n />\n );\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\"col-start-2 row-span-2 row-start-1 self-start justify-self-end\", className)}\n {...props}\n />\n );\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div data-slot=\"card-content\" className={cn(\"px-6\", className)} {...props} />;\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"flex items-center px-6\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Card,\n CardHeader,\n CardTitle,\n CardDescription,\n CardAction,\n CardContent,\n CardFooter,\n};\n",
|
|
26
|
+
"type": "registry:ui",
|
|
27
|
+
"target": "components/ui/card.tsx"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "checkbox",
|
|
4
|
+
"type": "registry:ui",
|
|
5
|
+
"title": "Checkbox",
|
|
6
|
+
"description": "A tri-state checkbox with label support and visible focus.",
|
|
7
|
+
"dependencies": [
|
|
8
|
+
"radix-ui",
|
|
9
|
+
"@tabler/icons-react"
|
|
10
|
+
],
|
|
11
|
+
"registryDependencies": [
|
|
12
|
+
"https://abackui.com/r/utils.json"
|
|
13
|
+
],
|
|
14
|
+
"categories": [
|
|
15
|
+
"Forms"
|
|
16
|
+
],
|
|
17
|
+
"docs": "https://abackui.com/docs/components/checkbox",
|
|
18
|
+
"meta": {
|
|
19
|
+
"status": "stable",
|
|
20
|
+
"usedIn": [
|
|
21
|
+
"aback-tools",
|
|
22
|
+
"aback-launch"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
{
|
|
27
|
+
"path": "components/ui/checkbox.tsx",
|
|
28
|
+
"content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Checkbox as CheckboxPrimitive } from \"radix-ui\";\nimport { IconCheck } from \"@tabler/icons-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Checkbox({\n className,\n ...props\n}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n \"peer size-4 shrink-0 cursor-pointer border border-input bg-transparent shadow-xs outline-none transition-colors duration-200\",\n \"focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground\",\n \"data-[state=indeterminate]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground\",\n className,\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"flex items-center justify-center text-current\"\n >\n <IconCheck aria-hidden=\"true\" className=\"size-3.5\" stroke={3} />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n}\n\nexport { Checkbox };\n",
|
|
29
|
+
"type": "registry:ui",
|
|
30
|
+
"target": "components/ui/checkbox.tsx"
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://abackui.com/schema/registry-item.json",
|
|
3
|
+
"name": "code-block",
|
|
4
|
+
"type": "registry:ui",
|
|
5
|
+
"title": "Code Block",
|
|
6
|
+
"description": "A captioned, scrollable code sample with a copy button and optional line numbers.",
|
|
7
|
+
"registryDependencies": [
|
|
8
|
+
"https://abackui.com/r/utils.json",
|
|
9
|
+
"https://abackui.com/r/copy-button.json"
|
|
10
|
+
],
|
|
11
|
+
"categories": [
|
|
12
|
+
"Data Display"
|
|
13
|
+
],
|
|
14
|
+
"docs": "https://abackui.com/docs/components/code-block",
|
|
15
|
+
"meta": {
|
|
16
|
+
"status": "beta",
|
|
17
|
+
"usedIn": [
|
|
18
|
+
"aback-tools"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
{
|
|
23
|
+
"path": "components/ui/code-block.tsx",
|
|
24
|
+
"content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { CopyButton } from \"@/components/ui/copy-button\";\n\nexport interface CodeBlockProps extends Omit<React.ComponentProps<\"figure\">, \"children\"> {\n /** The exact source. It is what the copy button writes. */\n code: string;\n /** Shown in the caption bar, such as \"tsx\" or \"bash\". */\n language?: string;\n /** Shown in the caption bar and used to name the scroll region. */\n filename?: string;\n /** Show the copy button. */\n copyable?: boolean;\n /** Number the lines. Numbers are generated by CSS and never copied. */\n showLineNumbers?: boolean;\n /** Caps the height and scrolls, for long files. */\n maxHeight?: number | string;\n /** Accessible name of the copy button. */\n copyLabel?: string;\n}\n\n/**\n * A captioned code sample with a copy button. The scroll region is focusable\n * so a keyboard can scroll a long line, and it has a name. No highlighter is\n * bundled; the block renders plain text so it stays light and safe.\n */\nfunction CodeBlock({\n code,\n language,\n filename,\n copyable = true,\n showLineNumbers = false,\n maxHeight,\n copyLabel = \"Copy code\",\n className,\n ...props\n}: CodeBlockProps) {\n const lines = React.useMemo(() => code.replace(/\\n$/, \"\").split(\"\\n\"), [code]);\n const hasCaption = Boolean(filename || language || copyable);\n\n return (\n <figure\n data-slot=\"code-block\"\n className={cn(\"min-w-0 overflow-hidden border border-border bg-muted/30\", className)}\n {...props}\n >\n {hasCaption ? (\n <figcaption className=\"flex min-h-10 items-center justify-between gap-3 border-b border-border bg-muted px-4 py-1.5\">\n <span className=\"flex min-w-0 items-center gap-3\">\n {filename ? (\n <span className=\"truncate font-mono text-xs text-foreground\">{filename}</span>\n ) : null}\n {language ? (\n <span className=\"shrink-0 text-[10px] font-bold uppercase tracking-[0.12em] text-foreground\">\n {language}\n </span>\n ) : null}\n </span>\n {copyable ? <CopyButton value={code} label={copyLabel} /> : null}\n </figcaption>\n ) : null}\n <pre\n tabIndex={0}\n aria-label={filename ? `${filename} source` : \"Code sample\"}\n className=\"overflow-auto p-4 text-[13px] leading-relaxed text-foreground outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus-ring\"\n style={maxHeight !== undefined ? { maxHeight } : undefined}\n >\n <code className={cn(\"font-mono\", showLineNumbers && \"grid [counter-reset:line]\")}>\n {showLineNumbers\n ? lines.map((line, index) => (\n <span\n key={index}\n className=\"[counter-increment:line] before:mr-4 before:inline-block before:w-6 before:select-none before:text-right before:text-muted-foreground before:content-[counter(line)]\"\n >\n {line || \" \"}\n </span>\n ))\n : code}\n </code>\n </pre>\n </figure>\n );\n}\n\nexport { CodeBlock };\n",
|
|
25
|
+
"type": "registry:ui",
|
|
26
|
+
"target": "components/ui/code-block.tsx"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|