@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.
Files changed (208) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/build.ts +286 -0
  4. package/dist/cyberdesign-vars-only.css +116 -0
  5. package/dist/cyberdesign.css +8377 -0
  6. package/dist/fonts/JetBrainsMono-Variable.woff2 +0 -0
  7. package/dist/fonts/OFL.txt +93 -0
  8. package/dist/react/Accordion.d.ts +34 -0
  9. package/dist/react/Accordion.js +13 -0
  10. package/dist/react/Alert.d.ts +19 -0
  11. package/dist/react/Alert.js +6 -0
  12. package/dist/react/AugButton.d.ts +12 -0
  13. package/dist/react/AugButton.js +6 -0
  14. package/dist/react/AugPanel.d.ts +10 -0
  15. package/dist/react/AugPanel.js +6 -0
  16. package/dist/react/Avatar.d.ts +28 -0
  17. package/dist/react/Avatar.js +11 -0
  18. package/dist/react/Badge.d.ts +10 -0
  19. package/dist/react/Badge.js +6 -0
  20. package/dist/react/Breadcrumb.d.ts +19 -0
  21. package/dist/react/Breadcrumb.js +10 -0
  22. package/dist/react/Button.d.ts +12 -0
  23. package/dist/react/Button.js +6 -0
  24. package/dist/react/Checkbox.d.ts +9 -0
  25. package/dist/react/Checkbox.js +9 -0
  26. package/dist/react/Dropdown.d.ts +35 -0
  27. package/dist/react/Dropdown.js +20 -0
  28. package/dist/react/Field.d.ts +13 -0
  29. package/dist/react/Field.js +6 -0
  30. package/dist/react/Gauge.d.ts +19 -0
  31. package/dist/react/Gauge.js +6 -0
  32. package/dist/react/GlowCard.d.ts +12 -0
  33. package/dist/react/GlowCard.js +4 -0
  34. package/dist/react/HudBar.d.ts +34 -0
  35. package/dist/react/HudBar.js +10 -0
  36. package/dist/react/HudFrame.d.ts +19 -0
  37. package/dist/react/HudFrame.js +6 -0
  38. package/dist/react/Input.d.ts +11 -0
  39. package/dist/react/Input.js +6 -0
  40. package/dist/react/Interference.d.ts +18 -0
  41. package/dist/react/Interference.js +6 -0
  42. package/dist/react/Kbd.d.ts +18 -0
  43. package/dist/react/Kbd.js +11 -0
  44. package/dist/react/Label.d.ts +8 -0
  45. package/dist/react/Label.js +6 -0
  46. package/dist/react/Modal.d.ts +19 -0
  47. package/dist/react/Modal.js +9 -0
  48. package/dist/react/Pagination.d.ts +23 -0
  49. package/dist/react/Pagination.js +28 -0
  50. package/dist/react/PanelHeader.d.ts +9 -0
  51. package/dist/react/PanelHeader.js +6 -0
  52. package/dist/react/Progress.d.ts +13 -0
  53. package/dist/react/Progress.js +6 -0
  54. package/dist/react/Radio.d.ts +9 -0
  55. package/dist/react/Radio.js +9 -0
  56. package/dist/react/Scanner.d.ts +11 -0
  57. package/dist/react/Scanner.js +6 -0
  58. package/dist/react/Select.d.ts +13 -0
  59. package/dist/react/Select.js +6 -0
  60. package/dist/react/Separator.d.ts +11 -0
  61. package/dist/react/Separator.js +7 -0
  62. package/dist/react/Skeleton.d.ts +11 -0
  63. package/dist/react/Skeleton.js +13 -0
  64. package/dist/react/Slider.d.ts +9 -0
  65. package/dist/react/Slider.js +9 -0
  66. package/dist/react/Spinner.d.ts +11 -0
  67. package/dist/react/Spinner.js +6 -0
  68. package/dist/react/Stat.d.ts +20 -0
  69. package/dist/react/Stat.js +11 -0
  70. package/dist/react/Switch.d.ts +9 -0
  71. package/dist/react/Switch.js +6 -0
  72. package/dist/react/Table.d.ts +55 -0
  73. package/dist/react/Table.js +36 -0
  74. package/dist/react/Tabs.d.ts +28 -0
  75. package/dist/react/Tabs.js +16 -0
  76. package/dist/react/Terminal.d.ts +33 -0
  77. package/dist/react/Terminal.js +6 -0
  78. package/dist/react/Textarea.d.ts +7 -0
  79. package/dist/react/Textarea.js +6 -0
  80. package/dist/react/Ticker.d.ts +13 -0
  81. package/dist/react/Ticker.js +7 -0
  82. package/dist/react/Toast.d.ts +15 -0
  83. package/dist/react/Toast.js +6 -0
  84. package/dist/react/Tooltip.d.ts +11 -0
  85. package/dist/react/Tooltip.js +6 -0
  86. package/dist/react/index.d.ts +39 -0
  87. package/dist/react/index.js +46 -0
  88. package/dist/tailwind-theme.css +171 -0
  89. package/dist/tokens/base.d.ts +33 -0
  90. package/dist/tokens/base.js +41 -0
  91. package/dist/tokens/index.d.ts +7 -0
  92. package/dist/tokens/index.js +7 -0
  93. package/dist/tokens/semantic.d.ts +1 -0
  94. package/dist/tokens/semantic.js +54 -0
  95. package/dist/tokens/themes/cyan.d.ts +1 -0
  96. package/dist/tokens/themes/cyan.js +15 -0
  97. package/dist/tokens/themes/green.d.ts +1 -0
  98. package/dist/tokens/themes/green.js +15 -0
  99. package/dist/tokens/themes/orange.d.ts +1 -0
  100. package/dist/tokens/themes/orange.js +15 -0
  101. package/dist/tokens/themes/red.d.ts +1 -0
  102. package/dist/tokens/themes/red.js +15 -0
  103. package/dist/tokens/themes/steel.d.ts +1 -0
  104. package/dist/tokens/themes/steel.js +15 -0
  105. package/package.json +73 -0
  106. package/src/css/a11y.css +67 -0
  107. package/src/css/animations.css +111 -0
  108. package/src/css/base.css +34 -0
  109. package/src/css/components/accordion.css +148 -0
  110. package/src/css/components/alert.css +116 -0
  111. package/src/css/components/app-patterns.css +894 -0
  112. package/src/css/components/augmented.css +474 -0
  113. package/src/css/components/avatar.css +105 -0
  114. package/src/css/components/badge.css +46 -0
  115. package/src/css/components/breadcrumb.css +75 -0
  116. package/src/css/components/button.css +130 -0
  117. package/src/css/components/calendar.css +135 -0
  118. package/src/css/components/card.css +68 -0
  119. package/src/css/components/carousel.css +69 -0
  120. package/src/css/components/charts.css +464 -0
  121. package/src/css/components/checkbox.css +136 -0
  122. package/src/css/components/command.css +162 -0
  123. package/src/css/components/dropdown.css +187 -0
  124. package/src/css/components/form.css +280 -0
  125. package/src/css/components/gauge.css +156 -0
  126. package/src/css/components/glow-card.css +32 -0
  127. package/src/css/components/hud.css +165 -0
  128. package/src/css/components/image.css +164 -0
  129. package/src/css/components/input-otp.css +53 -0
  130. package/src/css/components/input.css +182 -0
  131. package/src/css/components/interference.css +217 -0
  132. package/src/css/components/kbd.css +54 -0
  133. package/src/css/components/layout-extras.css +256 -0
  134. package/src/css/components/modal.css +146 -0
  135. package/src/css/components/navigation-extras.css +280 -0
  136. package/src/css/components/pagination.css +122 -0
  137. package/src/css/components/panel-header.css +55 -0
  138. package/src/css/components/popover.css +112 -0
  139. package/src/css/components/scanner.css +125 -0
  140. package/src/css/components/select.css +99 -0
  141. package/src/css/components/sheet.css +149 -0
  142. package/src/css/components/skeleton.css +77 -0
  143. package/src/css/components/slider.css +116 -0
  144. package/src/css/components/spinner.css +101 -0
  145. package/src/css/components/spreadsheet.css +314 -0
  146. package/src/css/components/svg.css +104 -0
  147. package/src/css/components/switch.css +114 -0
  148. package/src/css/components/table.css +115 -0
  149. package/src/css/components/tabs.css +159 -0
  150. package/src/css/components/terminal.css +259 -0
  151. package/src/css/components/ticker.css +100 -0
  152. package/src/css/components/toast.css +137 -0
  153. package/src/css/components/toaster.css +48 -0
  154. package/src/css/components/toggle.css +99 -0
  155. package/src/css/components/typography.css +122 -0
  156. package/src/css/components/vectorbg.css +57 -0
  157. package/src/css/utilities.css +165 -0
  158. package/src/fonts/JetBrainsMono-Variable.woff2 +0 -0
  159. package/src/fonts/OFL.txt +93 -0
  160. package/src/js/charts.js +533 -0
  161. package/src/react/Accordion.tsx +85 -0
  162. package/src/react/Alert.tsx +58 -0
  163. package/src/react/AugButton.tsx +40 -0
  164. package/src/react/AugPanel.tsx +36 -0
  165. package/src/react/Avatar.tsx +69 -0
  166. package/src/react/Badge.tsx +28 -0
  167. package/src/react/Breadcrumb.tsx +63 -0
  168. package/src/react/Button.tsx +39 -0
  169. package/src/react/Checkbox.tsx +31 -0
  170. package/src/react/Dropdown.tsx +104 -0
  171. package/src/react/Field.tsx +36 -0
  172. package/src/react/Gauge.tsx +57 -0
  173. package/src/react/GlowCard.tsx +25 -0
  174. package/src/react/HudBar.tsx +86 -0
  175. package/src/react/HudFrame.tsx +52 -0
  176. package/src/react/Input.tsx +38 -0
  177. package/src/react/Interference.tsx +53 -0
  178. package/src/react/Kbd.tsx +62 -0
  179. package/src/react/Label.tsx +31 -0
  180. package/src/react/Modal.tsx +63 -0
  181. package/src/react/Pagination.tsx +113 -0
  182. package/src/react/PanelHeader.tsx +28 -0
  183. package/src/react/Progress.tsx +47 -0
  184. package/src/react/Radio.tsx +31 -0
  185. package/src/react/Scanner.tsx +37 -0
  186. package/src/react/Select.tsx +43 -0
  187. package/src/react/Separator.tsx +40 -0
  188. package/src/react/Skeleton.tsx +50 -0
  189. package/src/react/Slider.tsx +28 -0
  190. package/src/react/Spinner.tsx +39 -0
  191. package/src/react/Stat.tsx +52 -0
  192. package/src/react/Switch.tsx +25 -0
  193. package/src/react/Table.tsx +144 -0
  194. package/src/react/Tabs.tsx +97 -0
  195. package/src/react/Terminal.tsx +95 -0
  196. package/src/react/Textarea.tsx +20 -0
  197. package/src/react/Ticker.tsx +46 -0
  198. package/src/react/Toast.tsx +43 -0
  199. package/src/react/Tooltip.tsx +32 -0
  200. package/src/react/index.ts +52 -0
  201. package/src/tokens/base.ts +48 -0
  202. package/src/tokens/index.ts +7 -0
  203. package/src/tokens/semantic.ts +63 -0
  204. package/src/tokens/themes/cyan.ts +16 -0
  205. package/src/tokens/themes/green.ts +16 -0
  206. package/src/tokens/themes/orange.ts +16 -0
  207. package/src/tokens/themes/red.ts +16 -0
  208. package/src/tokens/themes/steel.ts +16 -0
@@ -0,0 +1,52 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+
3
+ const cx = (...parts: Array<string | false | null | undefined>) =>
4
+ parts.filter(Boolean).join(' ');
5
+
6
+ export interface StatProps extends HTMLAttributes<HTMLDivElement> {
7
+ /** Uppercase caption above the value. */
8
+ label: ReactNode;
9
+ /** The headline metric. */
10
+ value: ReactNode;
11
+ /** Secondary change/context line below the value. */
12
+ delta?: ReactNode;
13
+ /** Tints the delta green (`up`) or red (`down`). */
14
+ trend?: 'up' | 'down';
15
+ /** Color treatment for the value. Default is the neon-green metric look. */
16
+ variant?: 'default' | 'accent' | 'red' | 'yellow' | 'blue' | 'magenta';
17
+ }
18
+
19
+ /** Metric block — uppercase label, neon value and optional trend delta. */
20
+ export function Stat({
21
+ label,
22
+ value,
23
+ delta,
24
+ trend,
25
+ variant = 'default',
26
+ className = '',
27
+ ...rest
28
+ }: StatProps) {
29
+ return (
30
+ <div
31
+ className={cx('cd-stat', variant !== 'default' && `cd-stat--${variant}`, className)}
32
+ {...rest}
33
+ >
34
+ <span className="cd-stat__label">{label}</span>
35
+ <span className="cd-stat__value">{value}</span>
36
+ {delta != null && (
37
+ <span className={cx('cd-stat__delta', trend && `cd-stat__delta--${trend}`)}>{delta}</span>
38
+ )}
39
+ </div>
40
+ );
41
+ }
42
+
43
+ /** Grid container that separates `Stat` cards with 1px border lines. */
44
+ export function StatGrid({ className = '', children, ...rest }: HTMLAttributes<HTMLDivElement>) {
45
+ return (
46
+ <div className={cx('cd-stats', className)} {...rest}>
47
+ {children}
48
+ </div>
49
+ );
50
+ }
51
+
52
+ Stat.Grid = StatGrid;
@@ -0,0 +1,25 @@
1
+ import type { InputHTMLAttributes, ReactNode } from 'react';
2
+
3
+ const cx = (...parts: Array<string | false | null | undefined>) =>
4
+ parts.filter(Boolean).join(' ');
5
+
6
+ export interface SwitchProps
7
+ extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
8
+ /** `sm` is the compact track; default is the standard size. */
9
+ size?: 'sm' | 'md';
10
+ /** Text shown beside the toggle. */
11
+ label?: ReactNode;
12
+ }
13
+
14
+ /** Toggle switch — visually-hidden checkbox driving a neon track + thumb. */
15
+ export function Switch({ size = 'md', label, className = '', ...rest }: SwitchProps) {
16
+ return (
17
+ <label className={cx('cd-switch', size === 'sm' && 'cd-switch--sm', className)}>
18
+ <input type="checkbox" className="cd-switch__input" {...rest} />
19
+ <span className="cd-switch__track">
20
+ <span className="cd-switch__thumb" />
21
+ </span>
22
+ {label != null && <span className="cd-switch__label">{label}</span>}
23
+ </label>
24
+ );
25
+ }
@@ -0,0 +1,144 @@
1
+ import type {
2
+ HTMLAttributes,
3
+ TableHTMLAttributes,
4
+ ThHTMLAttributes,
5
+ TdHTMLAttributes,
6
+ ReactNode,
7
+ } from 'react';
8
+
9
+ const cx = (...parts: Array<string | false | null | undefined>) =>
10
+ parts.filter(Boolean).join(' ');
11
+
12
+ export interface TableProps extends TableHTMLAttributes<HTMLTableElement> {
13
+ /** Tighter padding and smaller type. */
14
+ compact?: boolean;
15
+ /** Draw cell borders. */
16
+ bordered?: boolean;
17
+ /** Wrap the table in a horizontally-scrollable `cd-table-wrap` container. */
18
+ scroll?: boolean;
19
+ /** Props forwarded to the wrapping `cd-table-wrap` div when `scroll` is set. */
20
+ wrapProps?: HTMLAttributes<HTMLDivElement>;
21
+ children?: ReactNode;
22
+ }
23
+
24
+ /** Cyber data table — accent uppercase headers, status dots, numeric cells. Compose with Table.Head/Body/Row/HeaderCell/Cell. */
25
+ export function Table({
26
+ compact = false,
27
+ bordered = false,
28
+ scroll = false,
29
+ wrapProps,
30
+ className = '',
31
+ children,
32
+ ...rest
33
+ }: TableProps) {
34
+ const table = (
35
+ <table
36
+ className={cx(
37
+ 'cd-table',
38
+ compact && 'cd-table--compact',
39
+ bordered && 'cd-table--bordered',
40
+ className,
41
+ )}
42
+ {...rest}
43
+ >
44
+ {children}
45
+ </table>
46
+ );
47
+
48
+ if (!scroll) return table;
49
+
50
+ const { className: wrapClassName = '', ...wrapRest } = wrapProps ?? {};
51
+ return (
52
+ <div className={cx('cd-table-wrap', wrapClassName)} {...wrapRest}>
53
+ {table}
54
+ </div>
55
+ );
56
+ }
57
+
58
+ export interface TableHeadProps extends HTMLAttributes<HTMLTableSectionElement> {
59
+ children?: ReactNode;
60
+ }
61
+
62
+ /** `<thead>` group for the table header row(s). */
63
+ function TableHead({ children, ...rest }: TableHeadProps) {
64
+ return <thead {...rest}>{children}</thead>;
65
+ }
66
+
67
+ export interface TableBodyProps extends HTMLAttributes<HTMLTableSectionElement> {
68
+ children?: ReactNode;
69
+ }
70
+
71
+ /** `<tbody>` group for the table data rows. */
72
+ function TableBody({ children, ...rest }: TableBodyProps) {
73
+ return <tbody {...rest}>{children}</tbody>;
74
+ }
75
+
76
+ export interface TableRowProps extends HTMLAttributes<HTMLTableRowElement> {
77
+ children?: ReactNode;
78
+ }
79
+
80
+ /** `<tr>` table row. */
81
+ function TableRow({ children, ...rest }: TableRowProps) {
82
+ return <tr {...rest}>{children}</tr>;
83
+ }
84
+
85
+ export interface TableHeaderCellProps extends ThHTMLAttributes<HTMLTableCellElement> {
86
+ /** Right-aligned tabular-numeric header cell (`cd-table__num`). */
87
+ numeric?: boolean;
88
+ /** Mark column sortable; `'asc'`/`'desc'` show a direction arrow (sets `data-sort`). */
89
+ sort?: boolean | 'asc' | 'desc';
90
+ children?: ReactNode;
91
+ }
92
+
93
+ /** `<th>` header cell — supports numeric alignment and a sortable `data-sort` indicator. */
94
+ function TableHeaderCell({
95
+ numeric = false,
96
+ sort,
97
+ className = '',
98
+ children,
99
+ ...rest
100
+ }: TableHeaderCellProps) {
101
+ const dataSort = sort === true ? '' : sort || undefined;
102
+ return (
103
+ <th
104
+ className={cx(numeric && 'cd-table__num', className)}
105
+ data-sort={dataSort}
106
+ {...rest}
107
+ >
108
+ {children}
109
+ </th>
110
+ );
111
+ }
112
+
113
+ export interface TableCellProps extends TdHTMLAttributes<HTMLTableCellElement> {
114
+ /** Right-aligned tabular-numeric, accent-colored cell (`cd-table__num`). */
115
+ numeric?: boolean;
116
+ /** Status dot prefix (sets `data-status`). */
117
+ status?: 'ok' | 'warn' | 'err' | 'idle';
118
+ children?: ReactNode;
119
+ }
120
+
121
+ /** `<td>` data cell — supports numeric alignment and a leading status dot. */
122
+ function TableCell({
123
+ numeric = false,
124
+ status,
125
+ className = '',
126
+ children,
127
+ ...rest
128
+ }: TableCellProps) {
129
+ return (
130
+ <td
131
+ className={cx(numeric && 'cd-table__num', className)}
132
+ data-status={status}
133
+ {...rest}
134
+ >
135
+ {children}
136
+ </td>
137
+ );
138
+ }
139
+
140
+ Table.Head = TableHead;
141
+ Table.Body = TableBody;
142
+ Table.Row = TableRow;
143
+ Table.HeaderCell = TableHeaderCell;
144
+ Table.Cell = TableCell;
@@ -0,0 +1,97 @@
1
+ import { useState } from 'react';
2
+ import type { ReactNode } from 'react';
3
+
4
+ const cx = (...parts: Array<string | false | null | undefined>) =>
5
+ parts.filter(Boolean).join(' ');
6
+
7
+ export interface TabItem {
8
+ /** Tab label (also the trigger text). */
9
+ label: ReactNode;
10
+ /** Panel content shown when this tab is active. */
11
+ content?: ReactNode;
12
+ /** Optional trailing badge node in the trigger (e.g. a count). */
13
+ badge?: ReactNode;
14
+ /** Disable selection of this tab. */
15
+ disabled?: boolean;
16
+ }
17
+
18
+ export interface TabsProps {
19
+ /** The tabs to render, in order. */
20
+ items: TabItem[];
21
+ /** Layout style: underline (default), pills, or vertical. */
22
+ variant?: 'underline' | 'pills' | 'vertical';
23
+ /** Index of the initially-active tab (uncontrolled). */
24
+ defaultActive?: number;
25
+ /** Controlled active index. When set, `onTabChange` should update it. */
26
+ active?: number;
27
+ /** Fires with the new index when a tab is selected. */
28
+ onTabChange?: (index: number) => void;
29
+ /** Hide the panels region (trigger-only, e.g. a filter bar). */
30
+ hidePanels?: boolean;
31
+ className?: string;
32
+ }
33
+
34
+ /** Tabbed navigation — underline / pills / vertical, with optional badges and panels. */
35
+ export function Tabs({
36
+ items,
37
+ variant = 'underline',
38
+ defaultActive = 0,
39
+ active,
40
+ onTabChange,
41
+ hidePanels = false,
42
+ className = '',
43
+ }: TabsProps) {
44
+ const [internal, setInternal] = useState(defaultActive);
45
+ const current = active ?? internal;
46
+
47
+ const select = (i: number) => {
48
+ if (items[i]?.disabled) return;
49
+ if (active == null) setInternal(i);
50
+ onTabChange?.(i);
51
+ };
52
+
53
+ return (
54
+ <div
55
+ className={cx(
56
+ 'cd-tabs',
57
+ variant === 'pills' && 'cd-tabs--pills',
58
+ variant === 'vertical' && 'cd-tabs--vertical',
59
+ className,
60
+ )}
61
+ >
62
+ <div className="cd-tabs__list" role="tablist">
63
+ {items.map((item, i) => (
64
+ <button
65
+ key={i}
66
+ type="button"
67
+ role="tab"
68
+ aria-selected={i === current}
69
+ disabled={item.disabled}
70
+ className={cx('cd-tabs__trigger', i === current && 'is-active')}
71
+ onClick={() => select(i)}
72
+ >
73
+ {item.label}
74
+ {item.badge != null && (
75
+ <span className="cd-badge cd-badge--orange" style={{ marginLeft: 4 }}>
76
+ {item.badge}
77
+ </span>
78
+ )}
79
+ </button>
80
+ ))}
81
+ </div>
82
+ {!hidePanels && (
83
+ <div className="cd-tabs__panels">
84
+ {items.map((item, i) => (
85
+ <div
86
+ key={i}
87
+ role="tabpanel"
88
+ className={cx('cd-tabs__panel', i === current && 'is-active')}
89
+ >
90
+ {item.content}
91
+ </div>
92
+ ))}
93
+ </div>
94
+ )}
95
+ </div>
96
+ );
97
+ }
@@ -0,0 +1,95 @@
1
+ import type { HTMLAttributes, InputHTMLAttributes, ReactNode } from 'react';
2
+
3
+ const cx = (...parts: Array<string | false | null | undefined>) =>
4
+ parts.filter(Boolean).join(' ');
5
+
6
+ /** Semantic line kinds — map to `cd-terminal__line--*` modifiers. */
7
+ export type TerminalLineType = 'system' | 'prompt' | 'command' | 'output' | 'error';
8
+
9
+ export interface TerminalLine {
10
+ /** Line text content. */
11
+ text: ReactNode;
12
+ /** Line kind; omit for the default (plain) line. */
13
+ type?: TerminalLineType;
14
+ /** Prompt glyph shown before the text (for `prompt` lines, e.g. `root@net> `). */
15
+ prompt?: ReactNode;
16
+ }
17
+
18
+ export interface TerminalProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
19
+ /** Header title text (theme-accent colored). Omit to hide the header. */
20
+ title?: ReactNode;
21
+ /** Show the min/max/close window control dots in the header. */
22
+ controls?: boolean;
23
+ /** The log lines to render in the body. */
24
+ lines?: TerminalLine[];
25
+ /** Tighter spacing / smaller type. */
26
+ compact?: boolean;
27
+ /** Extra CRT inner scanline overlay. */
28
+ crt?: boolean;
29
+ /** Render a bottom command input row. */
30
+ input?: boolean;
31
+ /** Prompt glyph shown before the input field. */
32
+ inputPrompt?: ReactNode;
33
+ /** Props forwarded to the input field element. */
34
+ inputProps?: InputHTMLAttributes<HTMLInputElement>;
35
+ /** Extra body content rendered after `lines`. */
36
+ children?: ReactNode;
37
+ }
38
+
39
+ /** Cyberpunk terminal/console window — header, scrollable log body and optional command input. */
40
+ export function Terminal({
41
+ title,
42
+ controls = false,
43
+ lines = [],
44
+ compact = false,
45
+ crt = false,
46
+ input = false,
47
+ inputPrompt = 'root@net> ',
48
+ inputProps,
49
+ className = '',
50
+ children,
51
+ ...rest
52
+ }: TerminalProps) {
53
+ return (
54
+ <div
55
+ className={cx(
56
+ 'cd-terminal',
57
+ compact && 'cd-terminal--compact',
58
+ crt && 'cd-terminal--crt',
59
+ className,
60
+ )}
61
+ {...rest}
62
+ >
63
+ {(title != null || controls) && (
64
+ <div className="cd-terminal__header">
65
+ {title != null && <span className="cd-terminal__title">{title}</span>}
66
+ {controls && (
67
+ <div className="cd-terminal__controls">
68
+ <span className="cd-terminal__dot cd-terminal__dot--min" title="Minimize" />
69
+ <span className="cd-terminal__dot cd-terminal__dot--max" title="Maximize" />
70
+ <span className="cd-terminal__dot cd-terminal__dot--close" title="Close" />
71
+ </div>
72
+ )}
73
+ </div>
74
+ )}
75
+ <div className="cd-terminal__body cd-scrollbar">
76
+ {lines.map((line, i) => (
77
+ <div
78
+ key={i}
79
+ className={cx('cd-terminal__line', line.type && `cd-terminal__line--${line.type}`)}
80
+ >
81
+ {line.prompt != null && <span className="cd-terminal__prompt">{line.prompt}</span>}
82
+ {line.text}
83
+ </div>
84
+ ))}
85
+ {children}
86
+ </div>
87
+ {input && (
88
+ <div className="cd-terminal__input">
89
+ {inputPrompt != null && <span className="cd-terminal__prompt">{inputPrompt}</span>}
90
+ <input className="cd-terminal__field" placeholder="type command..." {...inputProps} />
91
+ </div>
92
+ )}
93
+ </div>
94
+ );
95
+ }
@@ -0,0 +1,20 @@
1
+ import type { TextareaHTMLAttributes } from 'react';
2
+
3
+ const cx = (...parts: Array<string | false | null | undefined>) =>
4
+ parts.filter(Boolean).join(' ');
5
+
6
+ export interface TextareaProps
7
+ extends TextareaHTMLAttributes<HTMLTextAreaElement> {
8
+ /** Error state — red border. */
9
+ error?: boolean;
10
+ }
11
+
12
+ /** Cyber multi-line text area — vertical resize, neon focus ring, error state. */
13
+ export function Textarea({ error = false, className = '', ...rest }: TextareaProps) {
14
+ return (
15
+ <textarea
16
+ className={cx('cd-textarea', error && 'cd-textarea--error', className)}
17
+ {...rest}
18
+ />
19
+ );
20
+ }
@@ -0,0 +1,46 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+
3
+ const cx = (...parts: Array<string | false | null | undefined>) =>
4
+ parts.filter(Boolean).join(' ');
5
+
6
+ export interface TickerProps extends HTMLAttributes<HTMLDivElement> {
7
+ /** The feed items to scroll, in order. */
8
+ items: ReactNode[];
9
+ /** Scroll speed; `fast` ≈ 9s, `slow` ≈ 32s (default ≈ 18s). */
10
+ speed?: 'fast' | 'slow';
11
+ /** Shorthand for `speed="fast"`. */
12
+ fast?: boolean;
13
+ /** Scroll vertically instead of horizontally. */
14
+ vertical?: boolean;
15
+ }
16
+
17
+ /** Auto-scrolling data ticker / feed — pauses on hover, respects reduced motion. */
18
+ export function Ticker({
19
+ items,
20
+ speed,
21
+ fast = false,
22
+ vertical = false,
23
+ className = '',
24
+ ...rest
25
+ }: TickerProps) {
26
+ const resolvedSpeed = fast ? 'fast' : speed;
27
+ return (
28
+ <div
29
+ className={cx(
30
+ 'cd-ticker',
31
+ resolvedSpeed && `cd-ticker--${resolvedSpeed}`,
32
+ vertical && 'cd-ticker--vertical',
33
+ className,
34
+ )}
35
+ {...rest}
36
+ >
37
+ <div className="cd-ticker__inner">
38
+ {items.map((item, i) => (
39
+ <span key={i} className="cd-ticker__item">
40
+ {item}
41
+ </span>
42
+ ))}
43
+ </div>
44
+ </div>
45
+ );
46
+ }
@@ -0,0 +1,43 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+
3
+ const cx = (...parts: Array<string | false | null | undefined>) =>
4
+ parts.filter(Boolean).join(' ');
5
+
6
+ export interface ToastProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
7
+ /** Semantic color. `accent` follows the active theme accent. */
8
+ variant?: 'info' | 'success' | 'warning' | 'error' | 'accent';
9
+ /** Leading glyph (e.g. ℹ ✓ ⚠ ✕ ⬡). */
10
+ icon?: ReactNode;
11
+ /** Bold uppercase heading line. */
12
+ title?: ReactNode;
13
+ /** When provided, renders a dismiss ✕ that calls this on click. */
14
+ onDismiss?: () => void;
15
+ /** Message body. */
16
+ children?: ReactNode;
17
+ }
18
+
19
+ /** Single notification toast — semantic color, icon, title/body and optional dismiss. */
20
+ export function Toast({
21
+ variant = 'info',
22
+ icon,
23
+ title,
24
+ onDismiss,
25
+ className = '',
26
+ children,
27
+ ...rest
28
+ }: ToastProps) {
29
+ return (
30
+ <div className={cx('cd-toast', `cd-toast--${variant}`, className)} {...rest}>
31
+ {icon != null && <span className="cd-toast__icon">{icon}</span>}
32
+ <div className="cd-toast__content">
33
+ {title != null && <div className="cd-toast__title">{title}</div>}
34
+ {children != null && <div className="cd-toast__body">{children}</div>}
35
+ </div>
36
+ {onDismiss && (
37
+ <button className="cd-toast__dismiss" onClick={onDismiss} aria-label="Dismiss">
38
+
39
+ </button>
40
+ )}
41
+ </div>
42
+ );
43
+ }
@@ -0,0 +1,32 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+
3
+ const cx = (...parts: Array<string | false | null | undefined>) =>
4
+ parts.filter(Boolean).join(' ');
5
+
6
+ export interface TooltipProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'content'> {
7
+ /** Tooltip text shown on hover (rendered via the `data-tip` attribute). */
8
+ tip: string;
9
+ /** Show the tooltip below the trigger instead of above. */
10
+ below?: boolean;
11
+ /** The trigger content the tooltip wraps. */
12
+ children?: ReactNode;
13
+ }
14
+
15
+ /** CSS-only tooltip — wraps a trigger and reveals `tip` text on hover. */
16
+ export function Tooltip({
17
+ tip,
18
+ below = false,
19
+ className = '',
20
+ children,
21
+ ...rest
22
+ }: TooltipProps) {
23
+ return (
24
+ <span
25
+ className={cx('cd-tooltip', below && 'cd-tooltip--below', className)}
26
+ data-tip={tip}
27
+ {...rest}
28
+ >
29
+ {children}
30
+ </span>
31
+ );
32
+ }
@@ -0,0 +1,52 @@
1
+ // cyberdesign React bindings — thin wrappers over the cd-* CSS contract.
2
+ // The look comes from dist/cyberdesign.css; these components only apply classes.
3
+
4
+ export * from './GlowCard';
5
+
6
+ // Primitives
7
+ export * from './Button';
8
+ export * from './AugButton';
9
+ export * from './Badge';
10
+ export * from './Kbd';
11
+ export * from './Spinner';
12
+ export * from './Skeleton';
13
+ export * from './Avatar';
14
+
15
+ // Form controls
16
+ export * from './Input';
17
+ export * from './Textarea';
18
+ export * from './Select';
19
+ export * from './Checkbox';
20
+ export * from './Radio';
21
+ export * from './Switch';
22
+ export * from './Slider';
23
+ export * from './Label';
24
+ export * from './Field';
25
+
26
+ // Feedback & display
27
+ export * from './Alert';
28
+ export * from './Toast';
29
+ export * from './Tooltip';
30
+ export * from './Progress';
31
+ export * from './Separator';
32
+ export * from './PanelHeader';
33
+ export * from './Stat';
34
+
35
+ // Navigation & layout
36
+ export * from './Tabs';
37
+ export * from './Accordion';
38
+ export * from './Breadcrumb';
39
+ export * from './Pagination';
40
+ export * from './Dropdown';
41
+ export * from './Modal';
42
+ export * from './Table';
43
+ export * from './AugPanel';
44
+
45
+ // Cyber / terminal
46
+ export * from './Terminal';
47
+ export * from './HudFrame';
48
+ export * from './HudBar';
49
+ export * from './Gauge';
50
+ export * from './Ticker';
51
+ export * from './Scanner';
52
+ export * from './Interference';
@@ -0,0 +1,48 @@
1
+ export const palette = {
2
+ // Backgrounds — unified range from both source apps
3
+ bgBase: '#05060a', // AI-shell app's darkest
4
+ bgPanel: '#0b0f18', // AI-shell app bg-light / dashboard app panel midpoint
5
+ bgPanelHover: '#111827', // AI-shell app bg-lighter / dashboard app hover midpoint
6
+ bgDark: '#0a0a0c', // dashboard app's darkest (kept for compat)
7
+
8
+ // Borders
9
+ borderDim: '#1e1e24', // dashboard app --color-border-dim
10
+ borderMid: '#26324c', // AI-shell app --border
11
+
12
+ // Text — warm (dashboard app) and cool (AI-shell app) variants both exposed
13
+ textPrimary: '#e8e4e0', // dashboard app warm off-white
14
+ textPrimaryAlt: '#f2f7ff', // AI-shell app cool white
15
+ textSecondary: '#a7b7d6', // AI-shell app --text-secondary
16
+ textMuted: '#8a8078', // bumped for WCAG AA 4.5:1+ (was #706860)
17
+ textMutedAlt: '#7a8599', // bumped for WCAG AA (was #687797, cooler variant)
18
+ textDim: '#6a625c', // bumped for ~3.3:1 large/decorative text (was #4a4440)
19
+
20
+ // Orange family (dashboard app primary accent)
21
+ orange: '#ff8800', // normalized from #f80
22
+ amber: '#ffaa00', // normalized from #fa0
23
+ gold: '#ffcc00', // normalized from #fc0
24
+
25
+ // Cyan family (AI-shell app primary accent)
26
+ cyan: '#47f6ff',
27
+ cyanBright: '#bdffff',
28
+
29
+ // Shared secondary accents
30
+ magenta: '#ff2bd6', // AI-shell app; close to dashboard app's #f0f
31
+ magentaAlt: '#ff00ff', // dashboard app pure magenta (kept as alias)
32
+ purple: '#9d7cff', // AI-shell app --purple / --violet
33
+ green: '#00ff00', // dashboard app pure green
34
+ greenBright: '#52ff9f', // AI-shell app --green-bright
35
+ red: '#ff4444', // dashboard app #f44
36
+ redAlt: '#ff456c', // AI-shell app --red
37
+ redBright: '#ff7777', // lighter red for accent-bright
38
+ blue: '#4488ff', // dashboard app #48f
39
+ blueAlt: '#6aa8ff', // AI-shell app --ai-blue
40
+ yellow: '#f7ff5a', // AI-shell app --viz-active
41
+
42
+ // Steel / metallic family
43
+ steel: '#9aafc4', // blue-grey steel
44
+ steelBright: '#c8d8e8', // chrome highlight
45
+
46
+ // Surface
47
+ surfaceGlass: 'rgba(11, 15, 24, 0.94)',
48
+ } as const;
@@ -0,0 +1,7 @@
1
+ export { palette } from './base.js';
2
+ export { semanticTokens } from './semantic.js';
3
+ export { orangeTheme } from './themes/orange.js';
4
+ export { cyanTheme } from './themes/cyan.js';
5
+ export { greenTheme } from './themes/green.js';
6
+ export { redTheme } from './themes/red.js';
7
+ export { steelTheme } from './themes/steel.js';