@nukleas/cyberdesign 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.
- package/LICENSE +21 -0
- package/README.md +38 -0
- package/build.ts +286 -0
- package/dist/cyberdesign-vars-only.css +116 -0
- package/dist/cyberdesign.css +8377 -0
- package/dist/fonts/JetBrainsMono-Variable.woff2 +0 -0
- package/dist/fonts/OFL.txt +93 -0
- package/dist/react/Accordion.d.ts +34 -0
- package/dist/react/Accordion.js +13 -0
- package/dist/react/Alert.d.ts +19 -0
- package/dist/react/Alert.js +6 -0
- package/dist/react/AugButton.d.ts +12 -0
- package/dist/react/AugButton.js +6 -0
- package/dist/react/AugPanel.d.ts +10 -0
- package/dist/react/AugPanel.js +6 -0
- package/dist/react/Avatar.d.ts +28 -0
- package/dist/react/Avatar.js +11 -0
- package/dist/react/Badge.d.ts +10 -0
- package/dist/react/Badge.js +6 -0
- package/dist/react/Breadcrumb.d.ts +19 -0
- package/dist/react/Breadcrumb.js +10 -0
- package/dist/react/Button.d.ts +12 -0
- package/dist/react/Button.js +6 -0
- package/dist/react/Checkbox.d.ts +9 -0
- package/dist/react/Checkbox.js +9 -0
- package/dist/react/Dropdown.d.ts +35 -0
- package/dist/react/Dropdown.js +20 -0
- package/dist/react/Field.d.ts +13 -0
- package/dist/react/Field.js +6 -0
- package/dist/react/Gauge.d.ts +19 -0
- package/dist/react/Gauge.js +6 -0
- package/dist/react/GlowCard.d.ts +12 -0
- package/dist/react/GlowCard.js +4 -0
- package/dist/react/HudBar.d.ts +34 -0
- package/dist/react/HudBar.js +10 -0
- package/dist/react/HudFrame.d.ts +19 -0
- package/dist/react/HudFrame.js +6 -0
- package/dist/react/Input.d.ts +11 -0
- package/dist/react/Input.js +6 -0
- package/dist/react/Interference.d.ts +18 -0
- package/dist/react/Interference.js +6 -0
- package/dist/react/Kbd.d.ts +18 -0
- package/dist/react/Kbd.js +11 -0
- package/dist/react/Label.d.ts +8 -0
- package/dist/react/Label.js +6 -0
- package/dist/react/Modal.d.ts +19 -0
- package/dist/react/Modal.js +9 -0
- package/dist/react/Pagination.d.ts +23 -0
- package/dist/react/Pagination.js +28 -0
- package/dist/react/PanelHeader.d.ts +9 -0
- package/dist/react/PanelHeader.js +6 -0
- package/dist/react/Progress.d.ts +13 -0
- package/dist/react/Progress.js +6 -0
- package/dist/react/Radio.d.ts +9 -0
- package/dist/react/Radio.js +9 -0
- package/dist/react/Scanner.d.ts +11 -0
- package/dist/react/Scanner.js +6 -0
- package/dist/react/Select.d.ts +13 -0
- package/dist/react/Select.js +6 -0
- package/dist/react/Separator.d.ts +11 -0
- package/dist/react/Separator.js +7 -0
- package/dist/react/Skeleton.d.ts +11 -0
- package/dist/react/Skeleton.js +13 -0
- package/dist/react/Slider.d.ts +9 -0
- package/dist/react/Slider.js +9 -0
- package/dist/react/Spinner.d.ts +11 -0
- package/dist/react/Spinner.js +6 -0
- package/dist/react/Stat.d.ts +20 -0
- package/dist/react/Stat.js +11 -0
- package/dist/react/Switch.d.ts +9 -0
- package/dist/react/Switch.js +6 -0
- package/dist/react/Table.d.ts +55 -0
- package/dist/react/Table.js +36 -0
- package/dist/react/Tabs.d.ts +28 -0
- package/dist/react/Tabs.js +16 -0
- package/dist/react/Terminal.d.ts +33 -0
- package/dist/react/Terminal.js +6 -0
- package/dist/react/Textarea.d.ts +7 -0
- package/dist/react/Textarea.js +6 -0
- package/dist/react/Ticker.d.ts +13 -0
- package/dist/react/Ticker.js +7 -0
- package/dist/react/Toast.d.ts +15 -0
- package/dist/react/Toast.js +6 -0
- package/dist/react/Tooltip.d.ts +11 -0
- package/dist/react/Tooltip.js +6 -0
- package/dist/react/index.d.ts +39 -0
- package/dist/react/index.js +46 -0
- package/dist/tailwind-theme.css +171 -0
- package/dist/tokens/base.d.ts +33 -0
- package/dist/tokens/base.js +41 -0
- package/dist/tokens/index.d.ts +7 -0
- package/dist/tokens/index.js +7 -0
- package/dist/tokens/semantic.d.ts +1 -0
- package/dist/tokens/semantic.js +54 -0
- package/dist/tokens/themes/cyan.d.ts +1 -0
- package/dist/tokens/themes/cyan.js +15 -0
- package/dist/tokens/themes/green.d.ts +1 -0
- package/dist/tokens/themes/green.js +15 -0
- package/dist/tokens/themes/orange.d.ts +1 -0
- package/dist/tokens/themes/orange.js +15 -0
- package/dist/tokens/themes/red.d.ts +1 -0
- package/dist/tokens/themes/red.js +15 -0
- package/dist/tokens/themes/steel.d.ts +1 -0
- package/dist/tokens/themes/steel.js +15 -0
- package/package.json +73 -0
- package/src/css/a11y.css +67 -0
- package/src/css/animations.css +111 -0
- package/src/css/base.css +34 -0
- package/src/css/components/accordion.css +148 -0
- package/src/css/components/alert.css +116 -0
- package/src/css/components/app-patterns.css +894 -0
- package/src/css/components/augmented.css +474 -0
- package/src/css/components/avatar.css +105 -0
- package/src/css/components/badge.css +46 -0
- package/src/css/components/breadcrumb.css +75 -0
- package/src/css/components/button.css +130 -0
- package/src/css/components/calendar.css +135 -0
- package/src/css/components/card.css +68 -0
- package/src/css/components/carousel.css +69 -0
- package/src/css/components/charts.css +464 -0
- package/src/css/components/checkbox.css +136 -0
- package/src/css/components/command.css +162 -0
- package/src/css/components/dropdown.css +187 -0
- package/src/css/components/form.css +280 -0
- package/src/css/components/gauge.css +156 -0
- package/src/css/components/glow-card.css +32 -0
- package/src/css/components/hud.css +165 -0
- package/src/css/components/image.css +164 -0
- package/src/css/components/input-otp.css +53 -0
- package/src/css/components/input.css +182 -0
- package/src/css/components/interference.css +217 -0
- package/src/css/components/kbd.css +54 -0
- package/src/css/components/layout-extras.css +256 -0
- package/src/css/components/modal.css +146 -0
- package/src/css/components/navigation-extras.css +280 -0
- package/src/css/components/pagination.css +122 -0
- package/src/css/components/panel-header.css +55 -0
- package/src/css/components/popover.css +112 -0
- package/src/css/components/scanner.css +125 -0
- package/src/css/components/select.css +99 -0
- package/src/css/components/sheet.css +149 -0
- package/src/css/components/skeleton.css +77 -0
- package/src/css/components/slider.css +116 -0
- package/src/css/components/spinner.css +101 -0
- package/src/css/components/spreadsheet.css +314 -0
- package/src/css/components/svg.css +104 -0
- package/src/css/components/switch.css +114 -0
- package/src/css/components/table.css +115 -0
- package/src/css/components/tabs.css +159 -0
- package/src/css/components/terminal.css +259 -0
- package/src/css/components/ticker.css +100 -0
- package/src/css/components/toast.css +137 -0
- package/src/css/components/toaster.css +48 -0
- package/src/css/components/toggle.css +99 -0
- package/src/css/components/typography.css +122 -0
- package/src/css/components/vectorbg.css +57 -0
- package/src/css/utilities.css +165 -0
- package/src/fonts/JetBrainsMono-Variable.woff2 +0 -0
- package/src/fonts/OFL.txt +93 -0
- package/src/js/charts.js +533 -0
- package/src/react/Accordion.tsx +85 -0
- package/src/react/Alert.tsx +58 -0
- package/src/react/AugButton.tsx +40 -0
- package/src/react/AugPanel.tsx +36 -0
- package/src/react/Avatar.tsx +69 -0
- package/src/react/Badge.tsx +28 -0
- package/src/react/Breadcrumb.tsx +63 -0
- package/src/react/Button.tsx +39 -0
- package/src/react/Checkbox.tsx +31 -0
- package/src/react/Dropdown.tsx +104 -0
- package/src/react/Field.tsx +36 -0
- package/src/react/Gauge.tsx +57 -0
- package/src/react/GlowCard.tsx +25 -0
- package/src/react/HudBar.tsx +86 -0
- package/src/react/HudFrame.tsx +52 -0
- package/src/react/Input.tsx +38 -0
- package/src/react/Interference.tsx +53 -0
- package/src/react/Kbd.tsx +62 -0
- package/src/react/Label.tsx +31 -0
- package/src/react/Modal.tsx +63 -0
- package/src/react/Pagination.tsx +113 -0
- package/src/react/PanelHeader.tsx +28 -0
- package/src/react/Progress.tsx +47 -0
- package/src/react/Radio.tsx +31 -0
- package/src/react/Scanner.tsx +37 -0
- package/src/react/Select.tsx +43 -0
- package/src/react/Separator.tsx +40 -0
- package/src/react/Skeleton.tsx +50 -0
- package/src/react/Slider.tsx +28 -0
- package/src/react/Spinner.tsx +39 -0
- package/src/react/Stat.tsx +52 -0
- package/src/react/Switch.tsx +25 -0
- package/src/react/Table.tsx +144 -0
- package/src/react/Tabs.tsx +97 -0
- package/src/react/Terminal.tsx +95 -0
- package/src/react/Textarea.tsx +20 -0
- package/src/react/Ticker.tsx +46 -0
- package/src/react/Toast.tsx +43 -0
- package/src/react/Tooltip.tsx +32 -0
- package/src/react/index.ts +52 -0
- package/src/tokens/base.ts +48 -0
- package/src/tokens/index.ts +7 -0
- package/src/tokens/semantic.ts +63 -0
- package/src/tokens/themes/cyan.ts +16 -0
- package/src/tokens/themes/green.ts +16 -0
- package/src/tokens/themes/orange.ts +16 -0
- package/src/tokens/themes/red.ts +16 -0
- package/src/tokens/themes/steel.ts +16 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface KbdProps extends HTMLAttributes<HTMLElement> {
|
|
3
|
+
/** `lg` renders the larger standalone key. */
|
|
4
|
+
size?: 'md' | 'lg';
|
|
5
|
+
/** Accent-highlighted key with a neon glow. */
|
|
6
|
+
accent?: boolean;
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
/** Keyboard key — boxed glyph with size and accent variants. */
|
|
10
|
+
export declare function Kbd({ size, accent, className, children, ...rest }: KbdProps): import("react").JSX.Element;
|
|
11
|
+
export interface KbdGroupProps extends HTMLAttributes<HTMLSpanElement> {
|
|
12
|
+
/** Separator rendered between keys (default `+`). */
|
|
13
|
+
separator?: ReactNode;
|
|
14
|
+
/** `Kbd` keys to combine. */
|
|
15
|
+
children?: ReactNode;
|
|
16
|
+
}
|
|
17
|
+
/** Key combination group — joins multiple `Kbd` keys with a separator (e.g. ⌘ + K). */
|
|
18
|
+
export declare function KbdGroup({ separator, className, children, ...rest }: KbdGroupProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Keyboard key — boxed glyph with size and accent variants. */
|
|
4
|
+
export function Kbd({ size = 'md', accent = false, className = '', children, ...rest }) {
|
|
5
|
+
return (_jsx("kbd", { className: cx('cd-kbd', size === 'lg' && 'cd-kbd--lg', accent && 'cd-kbd--accent', className), ...rest, children: children }));
|
|
6
|
+
}
|
|
7
|
+
/** Key combination group — joins multiple `Kbd` keys with a separator (e.g. ⌘ + K). */
|
|
8
|
+
export function KbdGroup({ separator = '+', className = '', children, ...rest }) {
|
|
9
|
+
const keys = Array.isArray(children) ? children : [children];
|
|
10
|
+
return (_jsx("span", { className: cx('cd-kbd-group', className), ...rest, children: keys.map((key, i) => (_jsxs("span", { style: { display: 'contents' }, children: [i > 0 && _jsx("span", { className: "cd-kbd-group__sep", children: separator }), key] }, i))) }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LabelHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement> {
|
|
3
|
+
/** Append a red required asterisk. */
|
|
4
|
+
required?: boolean;
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
/** Uppercase form label — optional required asterisk. */
|
|
8
|
+
export declare function Label({ required, className, children, ...rest }: LabelProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Uppercase form label — optional required asterisk. */
|
|
4
|
+
export function Label({ required = false, className = '', children, ...rest }) {
|
|
5
|
+
return (_jsx("label", { className: cx('cd-form-label', required && 'cd-form-label--required', className), ...rest, children: children }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface ModalProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
3
|
+
/** Controls visibility — adds `is-open` to animate the overlay/panel in. */
|
|
4
|
+
open: boolean;
|
|
5
|
+
/** Fired by the backdrop click, the ✕ close button, and Escape handlers you wire up. */
|
|
6
|
+
onClose?: () => void;
|
|
7
|
+
/** Uppercase accent heading rendered in the header. Omit to hide the header. */
|
|
8
|
+
title?: ReactNode;
|
|
9
|
+
/** Footer content (typically action buttons). Omit to hide the footer. */
|
|
10
|
+
footer?: ReactNode;
|
|
11
|
+
/** Panel width. `default` is 480px; `sm` 340px, `lg` 680px, `xl` 900px. */
|
|
12
|
+
size?: 'default' | 'sm' | 'lg' | 'xl';
|
|
13
|
+
/** Hide the header ✕ close button. */
|
|
14
|
+
hideClose?: boolean;
|
|
15
|
+
/** Dialog body content. */
|
|
16
|
+
children?: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
/** Centered modal dialog over a dimmed backdrop — controlled via `open` / `onClose`. */
|
|
19
|
+
export declare function Modal({ open, onClose, title, footer, size, hideClose, className, children, ...rest }: ModalProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Centered modal dialog over a dimmed backdrop — controlled via `open` / `onClose`. */
|
|
4
|
+
export function Modal({ open, onClose, title, footer, size = 'default', hideClose = false, className = '', children, ...rest }) {
|
|
5
|
+
return (_jsx("div", { className: cx('cd-modal-overlay', open && 'is-open'), onClick: (e) => {
|
|
6
|
+
if (e.target === e.currentTarget)
|
|
7
|
+
onClose?.();
|
|
8
|
+
}, children: _jsxs("div", { className: cx('cd-modal', size !== 'default' && `cd-modal--${size}`, className), role: "dialog", "aria-modal": "true", ...rest, children: [(title != null || !hideClose) && (_jsxs("div", { className: "cd-modal__header", children: [title != null && _jsx("span", { className: "cd-modal__title", children: title }), !hideClose && (_jsx("button", { className: "cd-modal__close", onClick: onClose, "aria-label": "Close", children: "\u2715" }))] })), _jsx("div", { className: "cd-modal__body", children: children }), footer != null && _jsx("div", { className: "cd-modal__footer", children: footer })] }) }));
|
|
9
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
export interface PaginationProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
3
|
+
/** Current page (1-based). */
|
|
4
|
+
page: number;
|
|
5
|
+
/** Total number of pages. */
|
|
6
|
+
pageCount: number;
|
|
7
|
+
/** Fired with the target page when a control is activated. */
|
|
8
|
+
onPageChange?: (page: number) => void;
|
|
9
|
+
/** How many sibling pages to show on each side of the current page. */
|
|
10
|
+
siblingCount?: number;
|
|
11
|
+
/** Size variant. */
|
|
12
|
+
size?: 'default' | 'sm' | 'lg';
|
|
13
|
+
/** Collapse gaps so items share borders. */
|
|
14
|
+
compact?: boolean;
|
|
15
|
+
/** Show "Page X of Y" info text after the controls. */
|
|
16
|
+
showInfo?: boolean;
|
|
17
|
+
/** Prev button label. */
|
|
18
|
+
prevLabel?: React.ReactNode;
|
|
19
|
+
/** Next button label. */
|
|
20
|
+
nextLabel?: React.ReactNode;
|
|
21
|
+
}
|
|
22
|
+
/** Page navigation — windowed page list with prev/next, ellipsis and optional info. */
|
|
23
|
+
export declare function Pagination({ page, pageCount, onPageChange, siblingCount, size, compact, showInfo, prevLabel, nextLabel, className, ...rest }: PaginationProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Build the windowed list of page numbers with `'…'` gaps. */
|
|
4
|
+
function buildPages(page, pageCount, siblingCount) {
|
|
5
|
+
const total = pageCount;
|
|
6
|
+
// pages always shown: first, last, current ± siblingCount
|
|
7
|
+
const left = Math.max(2, page - siblingCount);
|
|
8
|
+
const right = Math.min(total - 1, page + siblingCount);
|
|
9
|
+
const pages = [1];
|
|
10
|
+
if (left > 2)
|
|
11
|
+
pages.push('…');
|
|
12
|
+
for (let p = left; p <= right; p++)
|
|
13
|
+
pages.push(p);
|
|
14
|
+
if (right < total - 1)
|
|
15
|
+
pages.push('…');
|
|
16
|
+
if (total > 1)
|
|
17
|
+
pages.push(total);
|
|
18
|
+
return pages;
|
|
19
|
+
}
|
|
20
|
+
/** Page navigation — windowed page list with prev/next, ellipsis and optional info. */
|
|
21
|
+
export function Pagination({ page, pageCount, onPageChange, siblingCount = 1, size = 'default', compact = false, showInfo = false, prevLabel = '‹ Prev', nextLabel = 'Next ›', className = '', ...rest }) {
|
|
22
|
+
const go = (p) => {
|
|
23
|
+
if (p < 1 || p > pageCount || p === page)
|
|
24
|
+
return;
|
|
25
|
+
onPageChange?.(p);
|
|
26
|
+
};
|
|
27
|
+
return (_jsxs("nav", { className: cx('cd-pagination', size !== 'default' && `cd-pagination--${size}`, compact && 'cd-pagination--compact', className), "aria-label": "Pagination", ...rest, children: [_jsx("button", { type: "button", className: "cd-pagination__prev cd-pagination__item", disabled: page <= 1, "aria-disabled": page <= 1 || undefined, onClick: () => go(page - 1), children: prevLabel }), buildPages(page, pageCount, siblingCount).map((p, i) => p === '…' ? (_jsx("span", { className: "cd-pagination__ellipsis", children: "\u00B7\u00B7\u00B7" }, `e${i}`)) : (_jsx("button", { type: "button", className: cx('cd-pagination__item', p === page && 'is-active'), "aria-current": p === page ? 'page' : undefined, onClick: () => go(p), children: p }, p))), _jsx("button", { type: "button", className: "cd-pagination__next cd-pagination__item", disabled: page >= pageCount, "aria-disabled": page >= pageCount || undefined, onClick: () => go(page + 1), children: nextLabel }), showInfo && (_jsxs("span", { className: "cd-pagination__info", children: ["Page ", page, " of ", pageCount] }))] }));
|
|
28
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface PanelHeaderProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** Trailing actions slot (right-aligned), e.g. a count or status indicator. */
|
|
4
|
+
actions?: ReactNode;
|
|
5
|
+
/** Header label / title content. */
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/** Panel header bar — uppercase neon title with an animated sweep and a right-aligned actions slot. */
|
|
9
|
+
export declare function PanelHeader({ actions, className, children, ...rest }: PanelHeaderProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Panel header bar — uppercase neon title with an animated sweep and a right-aligned actions slot. */
|
|
4
|
+
export function PanelHeader({ actions, className = '', children, ...rest }) {
|
|
5
|
+
return (_jsxs("div", { className: cx('cd-panel-header', className), ...rest, children: [children, actions != null && (_jsx("div", { className: "cd-panel-header__actions", children: actions }))] }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
export interface ProgressProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** Fill percentage (0–100). Ignored when `indeterminate`. */
|
|
4
|
+
value?: number;
|
|
5
|
+
/** Color variant. Default uses the theme accent. */
|
|
6
|
+
variant?: 'default' | 'danger' | 'success' | 'warning';
|
|
7
|
+
/** Taller 8px bar. */
|
|
8
|
+
thick?: boolean;
|
|
9
|
+
/** Scanning/indeterminate animation (no fixed value). */
|
|
10
|
+
indeterminate?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** Progress bar — accent fill driven by `value`%, with color, thick, and indeterminate variants. */
|
|
13
|
+
export declare function Progress({ value, variant, thick, indeterminate, className, ...rest }: ProgressProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Progress bar — accent fill driven by `value`%, with color, thick, and indeterminate variants. */
|
|
4
|
+
export function Progress({ value = 0, variant = 'default', thick = false, indeterminate = false, className = '', ...rest }) {
|
|
5
|
+
return (_jsx("div", { className: cx('cd-progress', variant !== 'default' && `cd-progress--${variant}`, thick && 'cd-progress--thick', indeterminate && 'cd-progress--indeterminate', className), role: "progressbar", "aria-valuenow": indeterminate ? undefined : value, "aria-valuemin": 0, "aria-valuemax": 100, ...rest, children: _jsx("div", { className: "cd-progress__bar", style: indeterminate ? undefined : { width: `${value}%` } }) }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { InputHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
3
|
+
/** Text shown beside the dot. When set, wraps the input in a `cd-control` label. */
|
|
4
|
+
label?: ReactNode;
|
|
5
|
+
/** Smaller helper line below the label. */
|
|
6
|
+
description?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/** Cyber radio — neon filled dot; renders inside a `cd-control` label when labelled. */
|
|
9
|
+
export declare function Radio({ label, description, className, ...rest }: RadioProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Cyber radio — neon filled dot; renders inside a `cd-control` label when labelled. */
|
|
4
|
+
export function Radio({ label, description, className = '', ...rest }) {
|
|
5
|
+
const input = (_jsx("input", { type: "radio", className: cx('cd-radio', !label && className), ...rest }));
|
|
6
|
+
if (label == null && description == null)
|
|
7
|
+
return input;
|
|
8
|
+
return (_jsxs("label", { className: cx('cd-control', className), children: [_jsx("input", { type: "radio", className: "cd-radio", ...rest }), _jsxs("span", { className: "cd-control__label", children: [label, description != null && _jsx("span", { className: "cd-control__desc", children: description })] })] }));
|
|
9
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface ScannerProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** Sweep top-to-bottom instead of left-to-right. */
|
|
4
|
+
vertical?: boolean;
|
|
5
|
+
/** Fainter return-sweep look. */
|
|
6
|
+
ping?: boolean;
|
|
7
|
+
/** Content scanned by the sweep line. */
|
|
8
|
+
children?: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
/** Animated scan/sweep-line overlay — wraps content with a glowing lidar/radar sweep. */
|
|
11
|
+
export declare function Scanner({ vertical, ping, className, children, ...rest }: ScannerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Animated scan/sweep-line overlay — wraps content with a glowing lidar/radar sweep. */
|
|
4
|
+
export function Scanner({ vertical = false, ping = false, className = '', children, ...rest }) {
|
|
5
|
+
return (_jsxs("div", { className: cx('cd-scanner', vertical && 'cd-scanner--vertical', ping && 'cd-scanner--ping', className), ...rest, children: [_jsx("div", { className: "cd-scanner__line" }), children] }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReactNode, SelectHTMLAttributes } from 'react';
|
|
2
|
+
export interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size'> {
|
|
3
|
+
/** `sm` is the compact height; default is the standard height. */
|
|
4
|
+
size?: 'sm' | 'md';
|
|
5
|
+
/** Uppercase tracked label styling (viz-controls pattern). */
|
|
6
|
+
label?: boolean;
|
|
7
|
+
/** Error state — red border. */
|
|
8
|
+
error?: boolean;
|
|
9
|
+
/** `<option>` elements. */
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
/** Native select with custom neon chevron — wraps the element for the arrow. */
|
|
13
|
+
export declare function Select({ size, label, error, className, children, ...rest }: SelectProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Native select with custom neon chevron — wraps the element for the arrow. */
|
|
4
|
+
export function Select({ size = 'md', label = false, error = false, className = '', children, ...rest }) {
|
|
5
|
+
return (_jsx("div", { className: "cd-select-wrap", children: _jsx("select", { className: cx('cd-select', size === 'sm' && 'cd-select--sm', label && 'cd-select--label', error && 'cd-select--error', className), ...rest, children: children }) }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface SeparatorProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** Orientation. `vertical` draws a vertical divider. */
|
|
4
|
+
orientation?: 'horizontal' | 'vertical';
|
|
5
|
+
/** Neon gradient line instead of a plain rule. */
|
|
6
|
+
neon?: boolean;
|
|
7
|
+
/** Optional inline label (e.g. "OR"); centers it between the rules. */
|
|
8
|
+
children?: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
/** Divider rule — horizontal/vertical, optional neon gradient and centered label. */
|
|
11
|
+
export declare function Separator({ orientation, neon, className, children, ...rest }: SeparatorProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Divider rule — horizontal/vertical, optional neon gradient and centered label. */
|
|
4
|
+
export function Separator({ orientation = 'horizontal', neon = false, className = '', children, ...rest }) {
|
|
5
|
+
const hasLabel = children != null;
|
|
6
|
+
return (_jsx("div", { className: cx('cd-separator', orientation === 'vertical' && 'cd-separator--vertical', neon && 'cd-separator--neon', hasLabel && 'cd-separator--label', !hasLabel && orientation === 'horizontal' && 'cd-separator--plain', className), role: "separator", ...rest, children: children }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
export interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** Pre-sized shape. `block`/`card` render the compound containers; the rest are line/avatar/button placeholders. */
|
|
4
|
+
shape?: 'plain' | 'text' | 'heading' | 'avatar' | 'btn' | 'block' | 'card';
|
|
5
|
+
/** Fractional width helper (full / 3/4 / 1/2 / 1/3). Ignored for `block`/`card`. */
|
|
6
|
+
width?: 'full' | '3/4' | '1/2' | '1/3';
|
|
7
|
+
}
|
|
8
|
+
/** Shimmering loading placeholder — text/heading/avatar/btn shapes plus block & card containers. */
|
|
9
|
+
export declare function Skeleton({ shape, width, className, children, ...rest }: SkeletonProps): import("react").JSX.Element;
|
|
10
|
+
/** Inline row inside a `cd-skeleton-block` (e.g. avatar + text lines). */
|
|
11
|
+
export declare function SkeletonRow({ className, children, ...rest }: HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Shimmering loading placeholder — text/heading/avatar/btn shapes plus block & card containers. */
|
|
4
|
+
export function Skeleton({ shape = 'plain', width, className = '', children, ...rest }) {
|
|
5
|
+
if (shape === 'card' || shape === 'block') {
|
|
6
|
+
return (_jsx("div", { className: cx(`cd-skeleton-${shape}`, className), ...rest, children: children }));
|
|
7
|
+
}
|
|
8
|
+
return (_jsx("div", { className: cx('cd-skeleton', shape !== 'plain' && `cd-skeleton--${shape}`, width && `cd-skeleton--w-${width}`, className), ...rest, children: children }));
|
|
9
|
+
}
|
|
10
|
+
/** Inline row inside a `cd-skeleton-block` (e.g. avatar + text lines). */
|
|
11
|
+
export function SkeletonRow({ className = '', children, ...rest }) {
|
|
12
|
+
return (_jsx("div", { className: cx('cd-skeleton-block__row', className), ...rest, children: children }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { InputHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface SliderProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
3
|
+
/** When provided, renders the value label beside the track inside a `cd-slider-wrap`. */
|
|
4
|
+
value?: InputHTMLAttributes<HTMLInputElement>['value'];
|
|
5
|
+
/** Node shown in the trailing `cd-slider-value` label. When set, wraps in `cd-slider-wrap`. */
|
|
6
|
+
valueLabel?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/** Range slider — neon track with 3D thumb; optional trailing value label. */
|
|
9
|
+
export declare function Slider({ valueLabel, className, ...rest }: SliderProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Range slider — neon track with 3D thumb; optional trailing value label. */
|
|
4
|
+
export function Slider({ valueLabel, className = '', ...rest }) {
|
|
5
|
+
const input = (_jsx("input", { type: "range", className: cx('cd-slider', !valueLabel && className), ...rest }));
|
|
6
|
+
if (valueLabel == null)
|
|
7
|
+
return input;
|
|
8
|
+
return (_jsxs("div", { className: cx('cd-slider-wrap', className), children: [_jsx("input", { type: "range", className: "cd-slider", ...rest }), _jsx("span", { className: "cd-slider-value", children: valueLabel })] }));
|
|
9
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
export interface SpinnerProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** Diameter preset. `md` is the default (no modifier). */
|
|
4
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
5
|
+
/** `ring` (default), `dual` counter-rotating rings, or `dots` pulse. */
|
|
6
|
+
variant?: 'ring' | 'dual' | 'dots';
|
|
7
|
+
/** Accessible label announced to screen readers. */
|
|
8
|
+
label?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Loading spinner — ring / dual-ring / dot-pulse variants in five sizes. */
|
|
11
|
+
export declare function Spinner({ size, variant, label, className, ...rest }: SpinnerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Loading spinner — ring / dual-ring / dot-pulse variants in five sizes. */
|
|
4
|
+
export function Spinner({ size = 'md', variant = 'ring', label = 'Loading', className = '', ...rest }) {
|
|
5
|
+
return (_jsx("div", { role: "status", "aria-label": label, className: cx('cd-spinner', size !== 'md' && `cd-spinner--${size}`, variant === 'dual' && 'cd-spinner--dual', variant === 'dots' && 'cd-spinner--dots', className), ...rest, children: variant === 'dots' && _jsx("span", {}) }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface StatProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** Uppercase caption above the value. */
|
|
4
|
+
label: ReactNode;
|
|
5
|
+
/** The headline metric. */
|
|
6
|
+
value: ReactNode;
|
|
7
|
+
/** Secondary change/context line below the value. */
|
|
8
|
+
delta?: ReactNode;
|
|
9
|
+
/** Tints the delta green (`up`) or red (`down`). */
|
|
10
|
+
trend?: 'up' | 'down';
|
|
11
|
+
/** Color treatment for the value. Default is the neon-green metric look. */
|
|
12
|
+
variant?: 'default' | 'accent' | 'red' | 'yellow' | 'blue' | 'magenta';
|
|
13
|
+
}
|
|
14
|
+
/** Metric block — uppercase label, neon value and optional trend delta. */
|
|
15
|
+
export declare function Stat({ label, value, delta, trend, variant, className, ...rest }: StatProps): import("react").JSX.Element;
|
|
16
|
+
export declare namespace Stat {
|
|
17
|
+
var Grid: typeof StatGrid;
|
|
18
|
+
}
|
|
19
|
+
/** Grid container that separates `Stat` cards with 1px border lines. */
|
|
20
|
+
export declare function StatGrid({ className, children, ...rest }: HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Metric block — uppercase label, neon value and optional trend delta. */
|
|
4
|
+
export function Stat({ label, value, delta, trend, variant = 'default', className = '', ...rest }) {
|
|
5
|
+
return (_jsxs("div", { className: cx('cd-stat', variant !== 'default' && `cd-stat--${variant}`, className), ...rest, children: [_jsx("span", { className: "cd-stat__label", children: label }), _jsx("span", { className: "cd-stat__value", children: value }), delta != null && (_jsx("span", { className: cx('cd-stat__delta', trend && `cd-stat__delta--${trend}`), children: delta }))] }));
|
|
6
|
+
}
|
|
7
|
+
/** Grid container that separates `Stat` cards with 1px border lines. */
|
|
8
|
+
export function StatGrid({ className = '', children, ...rest }) {
|
|
9
|
+
return (_jsx("div", { className: cx('cd-stats', className), ...rest, children: children }));
|
|
10
|
+
}
|
|
11
|
+
Stat.Grid = StatGrid;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { InputHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
|
|
3
|
+
/** `sm` is the compact track; default is the standard size. */
|
|
4
|
+
size?: 'sm' | 'md';
|
|
5
|
+
/** Text shown beside the toggle. */
|
|
6
|
+
label?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/** Toggle switch — visually-hidden checkbox driving a neon track + thumb. */
|
|
9
|
+
export declare function Switch({ size, label, className, ...rest }: SwitchProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Toggle switch — visually-hidden checkbox driving a neon track + thumb. */
|
|
4
|
+
export function Switch({ size = 'md', label, className = '', ...rest }) {
|
|
5
|
+
return (_jsxs("label", { className: cx('cd-switch', size === 'sm' && 'cd-switch--sm', className), children: [_jsx("input", { type: "checkbox", className: "cd-switch__input", ...rest }), _jsx("span", { className: "cd-switch__track", children: _jsx("span", { className: "cd-switch__thumb" }) }), label != null && _jsx("span", { className: "cd-switch__label", children: label })] }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { HTMLAttributes, TableHTMLAttributes, ThHTMLAttributes, TdHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface TableProps extends TableHTMLAttributes<HTMLTableElement> {
|
|
3
|
+
/** Tighter padding and smaller type. */
|
|
4
|
+
compact?: boolean;
|
|
5
|
+
/** Draw cell borders. */
|
|
6
|
+
bordered?: boolean;
|
|
7
|
+
/** Wrap the table in a horizontally-scrollable `cd-table-wrap` container. */
|
|
8
|
+
scroll?: boolean;
|
|
9
|
+
/** Props forwarded to the wrapping `cd-table-wrap` div when `scroll` is set. */
|
|
10
|
+
wrapProps?: HTMLAttributes<HTMLDivElement>;
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
/** Cyber data table — accent uppercase headers, status dots, numeric cells. Compose with Table.Head/Body/Row/HeaderCell/Cell. */
|
|
14
|
+
export declare function Table({ compact, bordered, scroll, wrapProps, className, children, ...rest }: TableProps): import("react").JSX.Element;
|
|
15
|
+
export declare namespace Table {
|
|
16
|
+
var Head: typeof TableHead;
|
|
17
|
+
var Body: typeof TableBody;
|
|
18
|
+
var Row: typeof TableRow;
|
|
19
|
+
var HeaderCell: typeof TableHeaderCell;
|
|
20
|
+
var Cell: typeof TableCell;
|
|
21
|
+
}
|
|
22
|
+
export interface TableHeadProps extends HTMLAttributes<HTMLTableSectionElement> {
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
/** `<thead>` group for the table header row(s). */
|
|
26
|
+
declare function TableHead({ children, ...rest }: TableHeadProps): import("react").JSX.Element;
|
|
27
|
+
export interface TableBodyProps extends HTMLAttributes<HTMLTableSectionElement> {
|
|
28
|
+
children?: ReactNode;
|
|
29
|
+
}
|
|
30
|
+
/** `<tbody>` group for the table data rows. */
|
|
31
|
+
declare function TableBody({ children, ...rest }: TableBodyProps): import("react").JSX.Element;
|
|
32
|
+
export interface TableRowProps extends HTMLAttributes<HTMLTableRowElement> {
|
|
33
|
+
children?: ReactNode;
|
|
34
|
+
}
|
|
35
|
+
/** `<tr>` table row. */
|
|
36
|
+
declare function TableRow({ children, ...rest }: TableRowProps): import("react").JSX.Element;
|
|
37
|
+
export interface TableHeaderCellProps extends ThHTMLAttributes<HTMLTableCellElement> {
|
|
38
|
+
/** Right-aligned tabular-numeric header cell (`cd-table__num`). */
|
|
39
|
+
numeric?: boolean;
|
|
40
|
+
/** Mark column sortable; `'asc'`/`'desc'` show a direction arrow (sets `data-sort`). */
|
|
41
|
+
sort?: boolean | 'asc' | 'desc';
|
|
42
|
+
children?: ReactNode;
|
|
43
|
+
}
|
|
44
|
+
/** `<th>` header cell — supports numeric alignment and a sortable `data-sort` indicator. */
|
|
45
|
+
declare function TableHeaderCell({ numeric, sort, className, children, ...rest }: TableHeaderCellProps): import("react").JSX.Element;
|
|
46
|
+
export interface TableCellProps extends TdHTMLAttributes<HTMLTableCellElement> {
|
|
47
|
+
/** Right-aligned tabular-numeric, accent-colored cell (`cd-table__num`). */
|
|
48
|
+
numeric?: boolean;
|
|
49
|
+
/** Status dot prefix (sets `data-status`). */
|
|
50
|
+
status?: 'ok' | 'warn' | 'err' | 'idle';
|
|
51
|
+
children?: ReactNode;
|
|
52
|
+
}
|
|
53
|
+
/** `<td>` data cell — supports numeric alignment and a leading status dot. */
|
|
54
|
+
declare function TableCell({ numeric, status, className, children, ...rest }: TableCellProps): import("react").JSX.Element;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Cyber data table — accent uppercase headers, status dots, numeric cells. Compose with Table.Head/Body/Row/HeaderCell/Cell. */
|
|
4
|
+
export function Table({ compact = false, bordered = false, scroll = false, wrapProps, className = '', children, ...rest }) {
|
|
5
|
+
const table = (_jsx("table", { className: cx('cd-table', compact && 'cd-table--compact', bordered && 'cd-table--bordered', className), ...rest, children: children }));
|
|
6
|
+
if (!scroll)
|
|
7
|
+
return table;
|
|
8
|
+
const { className: wrapClassName = '', ...wrapRest } = wrapProps ?? {};
|
|
9
|
+
return (_jsx("div", { className: cx('cd-table-wrap', wrapClassName), ...wrapRest, children: table }));
|
|
10
|
+
}
|
|
11
|
+
/** `<thead>` group for the table header row(s). */
|
|
12
|
+
function TableHead({ children, ...rest }) {
|
|
13
|
+
return _jsx("thead", { ...rest, children: children });
|
|
14
|
+
}
|
|
15
|
+
/** `<tbody>` group for the table data rows. */
|
|
16
|
+
function TableBody({ children, ...rest }) {
|
|
17
|
+
return _jsx("tbody", { ...rest, children: children });
|
|
18
|
+
}
|
|
19
|
+
/** `<tr>` table row. */
|
|
20
|
+
function TableRow({ children, ...rest }) {
|
|
21
|
+
return _jsx("tr", { ...rest, children: children });
|
|
22
|
+
}
|
|
23
|
+
/** `<th>` header cell — supports numeric alignment and a sortable `data-sort` indicator. */
|
|
24
|
+
function TableHeaderCell({ numeric = false, sort, className = '', children, ...rest }) {
|
|
25
|
+
const dataSort = sort === true ? '' : sort || undefined;
|
|
26
|
+
return (_jsx("th", { className: cx(numeric && 'cd-table__num', className), "data-sort": dataSort, ...rest, children: children }));
|
|
27
|
+
}
|
|
28
|
+
/** `<td>` data cell — supports numeric alignment and a leading status dot. */
|
|
29
|
+
function TableCell({ numeric = false, status, className = '', children, ...rest }) {
|
|
30
|
+
return (_jsx("td", { className: cx(numeric && 'cd-table__num', className), "data-status": status, ...rest, children: children }));
|
|
31
|
+
}
|
|
32
|
+
Table.Head = TableHead;
|
|
33
|
+
Table.Body = TableBody;
|
|
34
|
+
Table.Row = TableRow;
|
|
35
|
+
Table.HeaderCell = TableHeaderCell;
|
|
36
|
+
Table.Cell = TableCell;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface TabItem {
|
|
3
|
+
/** Tab label (also the trigger text). */
|
|
4
|
+
label: ReactNode;
|
|
5
|
+
/** Panel content shown when this tab is active. */
|
|
6
|
+
content?: ReactNode;
|
|
7
|
+
/** Optional trailing badge node in the trigger (e.g. a count). */
|
|
8
|
+
badge?: ReactNode;
|
|
9
|
+
/** Disable selection of this tab. */
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface TabsProps {
|
|
13
|
+
/** The tabs to render, in order. */
|
|
14
|
+
items: TabItem[];
|
|
15
|
+
/** Layout style: underline (default), pills, or vertical. */
|
|
16
|
+
variant?: 'underline' | 'pills' | 'vertical';
|
|
17
|
+
/** Index of the initially-active tab (uncontrolled). */
|
|
18
|
+
defaultActive?: number;
|
|
19
|
+
/** Controlled active index. When set, `onTabChange` should update it. */
|
|
20
|
+
active?: number;
|
|
21
|
+
/** Fires with the new index when a tab is selected. */
|
|
22
|
+
onTabChange?: (index: number) => void;
|
|
23
|
+
/** Hide the panels region (trigger-only, e.g. a filter bar). */
|
|
24
|
+
hidePanels?: boolean;
|
|
25
|
+
className?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Tabbed navigation — underline / pills / vertical, with optional badges and panels. */
|
|
28
|
+
export declare function Tabs({ items, variant, defaultActive, active, onTabChange, hidePanels, className, }: TabsProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
4
|
+
/** Tabbed navigation — underline / pills / vertical, with optional badges and panels. */
|
|
5
|
+
export function Tabs({ items, variant = 'underline', defaultActive = 0, active, onTabChange, hidePanels = false, className = '', }) {
|
|
6
|
+
const [internal, setInternal] = useState(defaultActive);
|
|
7
|
+
const current = active ?? internal;
|
|
8
|
+
const select = (i) => {
|
|
9
|
+
if (items[i]?.disabled)
|
|
10
|
+
return;
|
|
11
|
+
if (active == null)
|
|
12
|
+
setInternal(i);
|
|
13
|
+
onTabChange?.(i);
|
|
14
|
+
};
|
|
15
|
+
return (_jsxs("div", { className: cx('cd-tabs', variant === 'pills' && 'cd-tabs--pills', variant === 'vertical' && 'cd-tabs--vertical', className), children: [_jsx("div", { className: "cd-tabs__list", role: "tablist", children: items.map((item, i) => (_jsxs("button", { type: "button", role: "tab", "aria-selected": i === current, disabled: item.disabled, className: cx('cd-tabs__trigger', i === current && 'is-active'), onClick: () => select(i), children: [item.label, item.badge != null && (_jsx("span", { className: "cd-badge cd-badge--orange", style: { marginLeft: 4 }, children: item.badge }))] }, i))) }), !hidePanels && (_jsx("div", { className: "cd-tabs__panels", children: items.map((item, i) => (_jsx("div", { role: "tabpanel", className: cx('cd-tabs__panel', i === current && 'is-active'), children: item.content }, i))) }))] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { HTMLAttributes, InputHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
/** Semantic line kinds — map to `cd-terminal__line--*` modifiers. */
|
|
3
|
+
export type TerminalLineType = 'system' | 'prompt' | 'command' | 'output' | 'error';
|
|
4
|
+
export interface TerminalLine {
|
|
5
|
+
/** Line text content. */
|
|
6
|
+
text: ReactNode;
|
|
7
|
+
/** Line kind; omit for the default (plain) line. */
|
|
8
|
+
type?: TerminalLineType;
|
|
9
|
+
/** Prompt glyph shown before the text (for `prompt` lines, e.g. `root@net> `). */
|
|
10
|
+
prompt?: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export interface TerminalProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
13
|
+
/** Header title text (theme-accent colored). Omit to hide the header. */
|
|
14
|
+
title?: ReactNode;
|
|
15
|
+
/** Show the min/max/close window control dots in the header. */
|
|
16
|
+
controls?: boolean;
|
|
17
|
+
/** The log lines to render in the body. */
|
|
18
|
+
lines?: TerminalLine[];
|
|
19
|
+
/** Tighter spacing / smaller type. */
|
|
20
|
+
compact?: boolean;
|
|
21
|
+
/** Extra CRT inner scanline overlay. */
|
|
22
|
+
crt?: boolean;
|
|
23
|
+
/** Render a bottom command input row. */
|
|
24
|
+
input?: boolean;
|
|
25
|
+
/** Prompt glyph shown before the input field. */
|
|
26
|
+
inputPrompt?: ReactNode;
|
|
27
|
+
/** Props forwarded to the input field element. */
|
|
28
|
+
inputProps?: InputHTMLAttributes<HTMLInputElement>;
|
|
29
|
+
/** Extra body content rendered after `lines`. */
|
|
30
|
+
children?: ReactNode;
|
|
31
|
+
}
|
|
32
|
+
/** Cyberpunk terminal/console window — header, scrollable log body and optional command input. */
|
|
33
|
+
export declare function Terminal({ title, controls, lines, compact, crt, input, inputPrompt, inputProps, className, children, ...rest }: TerminalProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Cyberpunk terminal/console window — header, scrollable log body and optional command input. */
|
|
4
|
+
export function Terminal({ title, controls = false, lines = [], compact = false, crt = false, input = false, inputPrompt = 'root@net> ', inputProps, className = '', children, ...rest }) {
|
|
5
|
+
return (_jsxs("div", { className: cx('cd-terminal', compact && 'cd-terminal--compact', crt && 'cd-terminal--crt', className), ...rest, children: [(title != null || controls) && (_jsxs("div", { className: "cd-terminal__header", children: [title != null && _jsx("span", { className: "cd-terminal__title", children: title }), controls && (_jsxs("div", { className: "cd-terminal__controls", children: [_jsx("span", { className: "cd-terminal__dot cd-terminal__dot--min", title: "Minimize" }), _jsx("span", { className: "cd-terminal__dot cd-terminal__dot--max", title: "Maximize" }), _jsx("span", { className: "cd-terminal__dot cd-terminal__dot--close", title: "Close" })] }))] })), _jsxs("div", { className: "cd-terminal__body cd-scrollbar", children: [lines.map((line, i) => (_jsxs("div", { className: cx('cd-terminal__line', line.type && `cd-terminal__line--${line.type}`), children: [line.prompt != null && _jsx("span", { className: "cd-terminal__prompt", children: line.prompt }), line.text] }, i))), children] }), input && (_jsxs("div", { className: "cd-terminal__input", children: [inputPrompt != null && _jsx("span", { className: "cd-terminal__prompt", children: inputPrompt }), _jsx("input", { className: "cd-terminal__field", placeholder: "type command...", ...inputProps })] }))] }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TextareaHTMLAttributes } from 'react';
|
|
2
|
+
export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
3
|
+
/** Error state — red border. */
|
|
4
|
+
error?: boolean;
|
|
5
|
+
}
|
|
6
|
+
/** Cyber multi-line text area — vertical resize, neon focus ring, error state. */
|
|
7
|
+
export declare function Textarea({ error, className, ...rest }: TextareaProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
3
|
+
/** Cyber multi-line text area — vertical resize, neon focus ring, error state. */
|
|
4
|
+
export function Textarea({ error = false, className = '', ...rest }) {
|
|
5
|
+
return (_jsx("textarea", { className: cx('cd-textarea', error && 'cd-textarea--error', className), ...rest }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface TickerProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** The feed items to scroll, in order. */
|
|
4
|
+
items: ReactNode[];
|
|
5
|
+
/** Scroll speed; `fast` ≈ 9s, `slow` ≈ 32s (default ≈ 18s). */
|
|
6
|
+
speed?: 'fast' | 'slow';
|
|
7
|
+
/** Shorthand for `speed="fast"`. */
|
|
8
|
+
fast?: boolean;
|
|
9
|
+
/** Scroll vertically instead of horizontally. */
|
|
10
|
+
vertical?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** Auto-scrolling data ticker / feed — pauses on hover, respects reduced motion. */
|
|
13
|
+
export declare function Ticker({ items, speed, fast, vertical, className, ...rest }: TickerProps): import("react").JSX.Element;
|