@hyperpackai/hyperui 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 (321) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +82 -0
  3. package/dist/components/Accordion/index.d.ts +17 -0
  4. package/dist/components/Accordion/index.d.ts.map +1 -0
  5. package/dist/components/Accordion/index.js +46 -0
  6. package/dist/components/Alert/index.d.ts +13 -0
  7. package/dist/components/Alert/index.d.ts.map +1 -0
  8. package/dist/components/Alert/index.js +46 -0
  9. package/dist/components/AppBar/index.d.ts +19 -0
  10. package/dist/components/AppBar/index.d.ts.map +1 -0
  11. package/dist/components/AppBar/index.js +48 -0
  12. package/dist/components/AspectRatio/index.d.ts +8 -0
  13. package/dist/components/AspectRatio/index.d.ts.map +1 -0
  14. package/dist/components/AspectRatio/index.js +32 -0
  15. package/dist/components/Autocomplete/index.d.ts +21 -0
  16. package/dist/components/Autocomplete/index.d.ts.map +1 -0
  17. package/dist/components/Autocomplete/index.js +94 -0
  18. package/dist/components/Avatar/index.d.ts +12 -0
  19. package/dist/components/Avatar/index.d.ts.map +1 -0
  20. package/dist/components/Avatar/index.js +32 -0
  21. package/dist/components/AvatarGroup/index.d.ts +9 -0
  22. package/dist/components/AvatarGroup/index.d.ts.map +1 -0
  23. package/dist/components/AvatarGroup/index.js +24 -0
  24. package/dist/components/Backdrop/index.d.ts +10 -0
  25. package/dist/components/Backdrop/index.d.ts.map +1 -0
  26. package/dist/components/Backdrop/index.js +25 -0
  27. package/dist/components/Badge/index.d.ts +10 -0
  28. package/dist/components/Badge/index.d.ts.map +1 -0
  29. package/dist/components/Badge/index.js +30 -0
  30. package/dist/components/BottomNavigation/index.d.ts +16 -0
  31. package/dist/components/BottomNavigation/index.d.ts.map +1 -0
  32. package/dist/components/BottomNavigation/index.js +43 -0
  33. package/dist/components/Box/index.d.ts +21 -0
  34. package/dist/components/Box/index.d.ts.map +1 -0
  35. package/dist/components/Box/index.js +30 -0
  36. package/dist/components/Breadcrumb/index.d.ts +13 -0
  37. package/dist/components/Breadcrumb/index.d.ts.map +1 -0
  38. package/dist/components/Breadcrumb/index.js +19 -0
  39. package/dist/components/Button/index.d.ts +22 -0
  40. package/dist/components/Button/index.d.ts.map +1 -0
  41. package/dist/components/Button/index.js +93 -0
  42. package/dist/components/ButtonGroup/index.d.ts +9 -0
  43. package/dist/components/ButtonGroup/index.d.ts.map +1 -0
  44. package/dist/components/ButtonGroup/index.js +27 -0
  45. package/dist/components/Card/index.d.ts +14 -0
  46. package/dist/components/Card/index.d.ts.map +1 -0
  47. package/dist/components/Card/index.js +33 -0
  48. package/dist/components/Checkbox/index.d.ts +17 -0
  49. package/dist/components/Checkbox/index.d.ts.map +1 -0
  50. package/dist/components/Checkbox/index.js +42 -0
  51. package/dist/components/Chip/index.d.ts +18 -0
  52. package/dist/components/Chip/index.d.ts.map +1 -0
  53. package/dist/components/Chip/index.js +60 -0
  54. package/dist/components/CircularProgress/index.d.ts +14 -0
  55. package/dist/components/CircularProgress/index.d.ts.map +1 -0
  56. package/dist/components/CircularProgress/index.js +58 -0
  57. package/dist/components/ClickAwayListener/index.d.ts +11 -0
  58. package/dist/components/ClickAwayListener/index.d.ts.map +1 -0
  59. package/dist/components/ClickAwayListener/index.js +31 -0
  60. package/dist/components/Code/index.d.ts +9 -0
  61. package/dist/components/Code/index.d.ts.map +1 -0
  62. package/dist/components/Code/index.js +50 -0
  63. package/dist/components/Collapse/index.d.ts +11 -0
  64. package/dist/components/Collapse/index.d.ts.map +1 -0
  65. package/dist/components/Collapse/index.js +30 -0
  66. package/dist/components/CommandPalette/index.d.ts +26 -0
  67. package/dist/components/CommandPalette/index.d.ts.map +1 -0
  68. package/dist/components/CommandPalette/index.js +141 -0
  69. package/dist/components/Container/index.d.ts +11 -0
  70. package/dist/components/Container/index.d.ts.map +1 -0
  71. package/dist/components/Container/index.js +18 -0
  72. package/dist/components/DashboardLayout/index.d.ts +15 -0
  73. package/dist/components/DashboardLayout/index.d.ts.map +1 -0
  74. package/dist/components/DashboardLayout/index.js +67 -0
  75. package/dist/components/DataTable/index.d.ts +27 -0
  76. package/dist/components/DataTable/index.d.ts.map +1 -0
  77. package/dist/components/DataTable/index.js +59 -0
  78. package/dist/components/Dialog/index.d.ts +19 -0
  79. package/dist/components/Dialog/index.d.ts.map +1 -0
  80. package/dist/components/Dialog/index.js +96 -0
  81. package/dist/components/Divider/index.d.ts +13 -0
  82. package/dist/components/Divider/index.d.ts.map +1 -0
  83. package/dist/components/Divider/index.js +40 -0
  84. package/dist/components/Drawer/index.d.ts +17 -0
  85. package/dist/components/Drawer/index.d.ts.map +1 -0
  86. package/dist/components/Drawer/index.js +77 -0
  87. package/dist/components/DropdownMenu/index.d.ts +25 -0
  88. package/dist/components/DropdownMenu/index.d.ts.map +1 -0
  89. package/dist/components/DropdownMenu/index.js +67 -0
  90. package/dist/components/EmptyState/index.d.ts +11 -0
  91. package/dist/components/EmptyState/index.d.ts.map +1 -0
  92. package/dist/components/EmptyState/index.js +53 -0
  93. package/dist/components/ErrorState/index.d.ts +12 -0
  94. package/dist/components/ErrorState/index.d.ts.map +1 -0
  95. package/dist/components/ErrorState/index.js +54 -0
  96. package/dist/components/Fab/index.d.ts +16 -0
  97. package/dist/components/Fab/index.d.ts.map +1 -0
  98. package/dist/components/Fab/index.js +39 -0
  99. package/dist/components/Fade/index.d.ts +10 -0
  100. package/dist/components/Fade/index.d.ts.map +1 -0
  101. package/dist/components/Fade/index.js +13 -0
  102. package/dist/components/FocusTrap/index.d.ts +11 -0
  103. package/dist/components/FocusTrap/index.d.ts.map +1 -0
  104. package/dist/components/FocusTrap/index.js +69 -0
  105. package/dist/components/FormControl/index.d.ts +34 -0
  106. package/dist/components/FormControl/index.d.ts.map +1 -0
  107. package/dist/components/FormControl/index.js +52 -0
  108. package/dist/components/GlobalSearch/index.d.ts +23 -0
  109. package/dist/components/GlobalSearch/index.d.ts.map +1 -0
  110. package/dist/components/GlobalSearch/index.js +91 -0
  111. package/dist/components/Grid/index.d.ts +19 -0
  112. package/dist/components/Grid/index.d.ts.map +1 -0
  113. package/dist/components/Grid/index.js +30 -0
  114. package/dist/components/Grow/index.d.ts +10 -0
  115. package/dist/components/Grow/index.d.ts.map +1 -0
  116. package/dist/components/Grow/index.js +13 -0
  117. package/dist/components/IconButton/index.d.ts +16 -0
  118. package/dist/components/IconButton/index.d.ts.map +1 -0
  119. package/dist/components/IconButton/index.js +43 -0
  120. package/dist/components/ImageList/index.d.ts +21 -0
  121. package/dist/components/ImageList/index.d.ts.map +1 -0
  122. package/dist/components/ImageList/index.js +39 -0
  123. package/dist/components/Input/index.d.ts +33 -0
  124. package/dist/components/Input/index.d.ts.map +1 -0
  125. package/dist/components/Input/index.js +45 -0
  126. package/dist/components/Kbd/index.d.ts +8 -0
  127. package/dist/components/Kbd/index.d.ts.map +1 -0
  128. package/dist/components/Kbd/index.js +41 -0
  129. package/dist/components/KeyboardShortcut/index.d.ts +20 -0
  130. package/dist/components/KeyboardShortcut/index.d.ts.map +1 -0
  131. package/dist/components/KeyboardShortcut/index.js +63 -0
  132. package/dist/components/Label/index.d.ts +10 -0
  133. package/dist/components/Label/index.d.ts.map +1 -0
  134. package/dist/components/Label/index.js +17 -0
  135. package/dist/components/LinearProgress/index.d.ts +13 -0
  136. package/dist/components/LinearProgress/index.d.ts.map +1 -0
  137. package/dist/components/LinearProgress/index.js +69 -0
  138. package/dist/components/Link/index.d.ts +16 -0
  139. package/dist/components/Link/index.d.ts.map +1 -0
  140. package/dist/components/Link/index.js +25 -0
  141. package/dist/components/List/index.d.ts +40 -0
  142. package/dist/components/List/index.d.ts.map +1 -0
  143. package/dist/components/List/index.js +70 -0
  144. package/dist/components/LoadingState/index.d.ts +11 -0
  145. package/dist/components/LoadingState/index.d.ts.map +1 -0
  146. package/dist/components/LoadingState/index.js +66 -0
  147. package/dist/components/Menu/index.d.ts +40 -0
  148. package/dist/components/Menu/index.d.ts.map +1 -0
  149. package/dist/components/Menu/index.js +103 -0
  150. package/dist/components/MobileStepper/index.d.ts +16 -0
  151. package/dist/components/MobileStepper/index.d.ts.map +1 -0
  152. package/dist/components/MobileStepper/index.js +67 -0
  153. package/dist/components/Modal/index.d.ts +14 -0
  154. package/dist/components/Modal/index.d.ts.map +1 -0
  155. package/dist/components/Modal/index.js +51 -0
  156. package/dist/components/Navbar/index.d.ts +14 -0
  157. package/dist/components/Navbar/index.d.ts.map +1 -0
  158. package/dist/components/Navbar/index.js +27 -0
  159. package/dist/components/NoSSR/index.d.ts +7 -0
  160. package/dist/components/NoSSR/index.d.ts.map +1 -0
  161. package/dist/components/NoSSR/index.js +9 -0
  162. package/dist/components/PageLayout/index.d.ts +13 -0
  163. package/dist/components/PageLayout/index.d.ts.map +1 -0
  164. package/dist/components/PageLayout/index.js +41 -0
  165. package/dist/components/Pagination/index.d.ts +11 -0
  166. package/dist/components/Pagination/index.d.ts.map +1 -0
  167. package/dist/components/Pagination/index.js +56 -0
  168. package/dist/components/Paper/index.d.ts +12 -0
  169. package/dist/components/Paper/index.d.ts.map +1 -0
  170. package/dist/components/Paper/index.js +24 -0
  171. package/dist/components/Popover/index.d.ts +13 -0
  172. package/dist/components/Popover/index.d.ts.map +1 -0
  173. package/dist/components/Popover/index.js +34 -0
  174. package/dist/components/Progress/index.d.ts +13 -0
  175. package/dist/components/Progress/index.d.ts.map +1 -0
  176. package/dist/components/Progress/index.js +40 -0
  177. package/dist/components/Radio/index.d.ts +7 -0
  178. package/dist/components/Radio/index.d.ts.map +1 -0
  179. package/dist/components/Radio/index.js +28 -0
  180. package/dist/components/Rating/index.d.ts +15 -0
  181. package/dist/components/Rating/index.d.ts.map +1 -0
  182. package/dist/components/Rating/index.js +41 -0
  183. package/dist/components/ResizablePanel/index.d.ts +16 -0
  184. package/dist/components/ResizablePanel/index.d.ts.map +1 -0
  185. package/dist/components/ResizablePanel/index.js +41 -0
  186. package/dist/components/ScrollArea/index.d.ts +12 -0
  187. package/dist/components/ScrollArea/index.d.ts.map +1 -0
  188. package/dist/components/ScrollArea/index.js +50 -0
  189. package/dist/components/Select/index.d.ts +23 -0
  190. package/dist/components/Select/index.d.ts.map +1 -0
  191. package/dist/components/Select/index.js +52 -0
  192. package/dist/components/Sheet/index.d.ts +15 -0
  193. package/dist/components/Sheet/index.d.ts.map +1 -0
  194. package/dist/components/Sheet/index.js +61 -0
  195. package/dist/components/Sidebar/index.d.ts +23 -0
  196. package/dist/components/Sidebar/index.d.ts.map +1 -0
  197. package/dist/components/Sidebar/index.js +37 -0
  198. package/dist/components/Skeleton/index.d.ts +9 -0
  199. package/dist/components/Skeleton/index.d.ts.map +1 -0
  200. package/dist/components/Skeleton/index.js +22 -0
  201. package/dist/components/Slide/index.d.ts +12 -0
  202. package/dist/components/Slide/index.d.ts.map +1 -0
  203. package/dist/components/Slide/index.js +21 -0
  204. package/dist/components/Slider/index.d.ts +19 -0
  205. package/dist/components/Slider/index.d.ts.map +1 -0
  206. package/dist/components/Slider/index.js +49 -0
  207. package/dist/components/Snackbar/index.d.ts +28 -0
  208. package/dist/components/Snackbar/index.d.ts.map +1 -0
  209. package/dist/components/Snackbar/index.js +71 -0
  210. package/dist/components/SpeedDial/index.d.ts +18 -0
  211. package/dist/components/SpeedDial/index.d.ts.map +1 -0
  212. package/dist/components/SpeedDial/index.js +71 -0
  213. package/dist/components/Spinner/index.d.ts +10 -0
  214. package/dist/components/Spinner/index.d.ts.map +1 -0
  215. package/dist/components/Spinner/index.js +67 -0
  216. package/dist/components/SplitPane/index.d.ts +11 -0
  217. package/dist/components/SplitPane/index.d.ts.map +1 -0
  218. package/dist/components/SplitPane/index.js +46 -0
  219. package/dist/components/Stack/index.d.ts +17 -0
  220. package/dist/components/Stack/index.d.ts.map +1 -0
  221. package/dist/components/Stack/index.js +30 -0
  222. package/dist/components/Stepper/index.d.ts +20 -0
  223. package/dist/components/Stepper/index.d.ts.map +1 -0
  224. package/dist/components/Stepper/index.js +66 -0
  225. package/dist/components/Switch/index.d.ts +13 -0
  226. package/dist/components/Switch/index.d.ts.map +1 -0
  227. package/dist/components/Switch/index.js +38 -0
  228. package/dist/components/Tabs/index.d.ts +20 -0
  229. package/dist/components/Tabs/index.d.ts.map +1 -0
  230. package/dist/components/Tabs/index.js +62 -0
  231. package/dist/components/TextField/index.d.ts +35 -0
  232. package/dist/components/TextField/index.d.ts.map +1 -0
  233. package/dist/components/TextField/index.js +69 -0
  234. package/dist/components/Textarea/index.d.ts +22 -0
  235. package/dist/components/Textarea/index.d.ts.map +1 -0
  236. package/dist/components/Textarea/index.js +27 -0
  237. package/dist/components/Timeline/index.d.ts +16 -0
  238. package/dist/components/Timeline/index.d.ts.map +1 -0
  239. package/dist/components/Timeline/index.js +30 -0
  240. package/dist/components/Toast/index.d.ts +34 -0
  241. package/dist/components/Toast/index.d.ts.map +1 -0
  242. package/dist/components/Toast/index.js +106 -0
  243. package/dist/components/ToggleButton/index.d.ts +21 -0
  244. package/dist/components/ToggleButton/index.d.ts.map +1 -0
  245. package/dist/components/ToggleButton/index.js +81 -0
  246. package/dist/components/Tooltip/index.d.ts +14 -0
  247. package/dist/components/Tooltip/index.d.ts.map +1 -0
  248. package/dist/components/Tooltip/index.js +47 -0
  249. package/dist/components/TreeView/index.d.ts +19 -0
  250. package/dist/components/TreeView/index.d.ts.map +1 -0
  251. package/dist/components/TreeView/index.js +50 -0
  252. package/dist/components/Typography/index.d.ts +17 -0
  253. package/dist/components/Typography/index.d.ts.map +1 -0
  254. package/dist/components/Typography/index.js +44 -0
  255. package/dist/components/VisuallyHidden/index.d.ts +7 -0
  256. package/dist/components/VisuallyHidden/index.d.ts.map +1 -0
  257. package/dist/components/VisuallyHidden/index.js +18 -0
  258. package/dist/components/Zoom/index.d.ts +10 -0
  259. package/dist/components/Zoom/index.d.ts.map +1 -0
  260. package/dist/components/Zoom/index.js +13 -0
  261. package/dist/components/ai.d.ts +133 -0
  262. package/dist/components/ai.d.ts.map +1 -0
  263. package/dist/components/ai.js +184 -0
  264. package/dist/components/charts.d.ts +143 -0
  265. package/dist/components/charts.d.ts.map +1 -0
  266. package/dist/components/charts.js +435 -0
  267. package/dist/components/data.d.ts +192 -0
  268. package/dist/components/data.d.ts.map +1 -0
  269. package/dist/components/data.js +581 -0
  270. package/dist/components/date.d.ts +73 -0
  271. package/dist/components/date.d.ts.map +1 -0
  272. package/dist/components/date.js +199 -0
  273. package/dist/components/enterprise.d.ts +246 -0
  274. package/dist/components/enterprise.d.ts.map +1 -0
  275. package/dist/components/enterprise.js +428 -0
  276. package/dist/components/form.d.ts +132 -0
  277. package/dist/components/form.d.ts.map +1 -0
  278. package/dist/components/form.js +380 -0
  279. package/dist/components/index.d.ts +173 -0
  280. package/dist/components/index.d.ts.map +1 -0
  281. package/dist/components/index.js +107 -0
  282. package/dist/components/inputs.d.ts +169 -0
  283. package/dist/components/inputs.d.ts.map +1 -0
  284. package/dist/components/inputs.js +437 -0
  285. package/dist/components/layout.d.ts +224 -0
  286. package/dist/components/layout.d.ts.map +1 -0
  287. package/dist/components/layout.js +644 -0
  288. package/dist/components/overlay.d.ts +102 -0
  289. package/dist/components/overlay.d.ts.map +1 -0
  290. package/dist/components/overlay.js +318 -0
  291. package/dist/components/surfaces.d.ts +180 -0
  292. package/dist/components/surfaces.d.ts.map +1 -0
  293. package/dist/components/surfaces.js +423 -0
  294. package/dist/components/typography.d.ts +69 -0
  295. package/dist/components/typography.d.ts.map +1 -0
  296. package/dist/components/typography.js +206 -0
  297. package/dist/index.d.ts +23 -0
  298. package/dist/index.d.ts.map +1 -0
  299. package/dist/index.js +29 -0
  300. package/dist/portal.d.ts +3 -0
  301. package/dist/portal.d.ts.map +1 -0
  302. package/dist/portal.js +17 -0
  303. package/dist/theme/index.d.ts +31 -0
  304. package/dist/theme/index.d.ts.map +1 -0
  305. package/dist/theme/index.js +258 -0
  306. package/dist/tokens/component.d.ts +124 -0
  307. package/dist/tokens/component.d.ts.map +1 -0
  308. package/dist/tokens/component.js +113 -0
  309. package/dist/tokens/index.d.ts +494 -0
  310. package/dist/tokens/index.d.ts.map +1 -0
  311. package/dist/tokens/index.js +345 -0
  312. package/dist/tokens/primitives.d.ts +675 -0
  313. package/dist/tokens/primitives.d.ts.map +1 -0
  314. package/dist/tokens/primitives.js +356 -0
  315. package/dist/tokens/semantic.d.ts +252 -0
  316. package/dist/tokens/semantic.d.ts.map +1 -0
  317. package/dist/tokens/semantic.js +242 -0
  318. package/dist/tokens/themes.d.ts +18 -0
  319. package/dist/tokens/themes.d.ts.map +1 -0
  320. package/dist/tokens/themes.js +316 -0
  321. package/package.json +69 -0
@@ -0,0 +1,437 @@
1
+ /**
2
+ * HyperUI Input Components
3
+ * TextField · IconButton · ButtonGroup · ToggleButton · FAB · Rating · Slider · Autocomplete · FormControl
4
+ */
5
+ import { signal } from "@hyperpackai/hyperion";
6
+ import { injectCSS, cn, h } from "../theme/index.js";
7
+ // ============================================================
8
+ // TEXT FIELD
9
+ // ============================================================
10
+ const TEXTFIELD_CSS = `
11
+ .hu-textfield { display: flex; flex-direction: column; gap: var(--hu-space-1); width: 100%; }
12
+ .hu-textfield__label { font-size: var(--hu-font-size-sm); font-weight: var(--hu-font-weight-medium); color: var(--hu-text-2); }
13
+ .hu-textfield__label--required::after { content: " *"; color: var(--hu-error); }
14
+ .hu-textfield__input-wrap { position: relative; display: flex; align-items: center; }
15
+ .hu-textfield__input {
16
+ width: 100%; padding: var(--hu-space-2-5) var(--hu-space-3);
17
+ font-size: var(--hu-font-size-sm); font-family: var(--hu-font-sans);
18
+ background: var(--hu-bg); color: var(--hu-text);
19
+ border: 1px solid var(--hu-border); border-radius: var(--hu-radius);
20
+ transition: all var(--hu-duration) var(--hu-ease); outline: none; box-sizing: border-box;
21
+ }
22
+ .hu-textfield__input:hover { border-color: var(--hu-border-2); }
23
+ .hu-textfield__input:focus { border-color: var(--hu-primary); box-shadow: 0 0 0 3px var(--hu-primary-bg); }
24
+ .hu-textfield__input:disabled { opacity: .6; cursor: not-allowed; background: var(--hu-bg-3); }
25
+ .hu-textfield__input::placeholder { color: var(--hu-text-3); }
26
+ .hu-textfield--outlined .hu-textfield__input { background: transparent; }
27
+ .hu-textfield--filled .hu-textfield__input {
28
+ background: var(--hu-bg-3); border-bottom: 2px solid var(--hu-border); border-radius: var(--hu-radius) var(--hu-radius) 0 0;
29
+ border-left: none; border-right: none; border-top: none;
30
+ }
31
+ .hu-textfield--filled .hu-textfield__input:focus { border-bottom-color: var(--hu-primary); background: var(--hu-bg-4); }
32
+ .hu-textfield--standard .hu-textfield__input { border: none; border-bottom: 1px solid var(--hu-border); border-radius: 0; padding-left: 0; padding-right: 0; background: transparent; }
33
+ .hu-textfield--standard .hu-textfield__input:focus { border-bottom: 2px solid var(--hu-primary); box-shadow: none; }
34
+ .hu-textfield--error .hu-textfield__input { border-color: var(--hu-error); }
35
+ .hu-textfield--error .hu-textfield__input:focus { box-shadow: 0 0 0 3px var(--hu-error-bg); }
36
+ .hu-textfield--success .hu-textfield__input { border-color: var(--hu-success); }
37
+ .hu-textfield__start-icon { position: absolute; left: var(--hu-space-3); color: var(--hu-text-2); pointer-events: none; }
38
+ .hu-textfield__end-icon { position: absolute; right: var(--hu-space-3); color: var(--hu-text-2); }
39
+ .hu-textfield__input--has-start { padding-left: calc(var(--hu-space-3) * 2 + 18px); }
40
+ .hu-textfield__input--has-end { padding-right: calc(var(--hu-space-3) * 2 + 18px); }
41
+ .hu-textfield__helper { font-size: var(--hu-font-size-xs); color: var(--hu-text-2); }
42
+ .hu-textfield--error .hu-textfield__helper { color: var(--hu-error); }
43
+ .hu-textfield--success .hu-textfield__helper { color: var(--hu-success); }
44
+ .hu-textfield__char-count { font-size: var(--hu-font-size-xs); color: var(--hu-text-2); text-align: right; }
45
+ .hu-textfield--sm .hu-textfield__input { padding: var(--hu-space-1-5) var(--hu-space-2-5); font-size: var(--hu-font-size-xs); }
46
+ .hu-textfield--lg .hu-textfield__input { padding: var(--hu-space-3) var(--hu-space-4); font-size: var(--hu-font-size-base); }
47
+ `;
48
+ export function TextField(props) {
49
+ injectCSS("hu-textfield", TEXTFIELD_CSS);
50
+ const { label, placeholder, value, type = "text", variant = "outlined", size = "md", helperText, error, success, required, disabled, readOnly, multiline, rows = 3, startIcon, endIcon, maxLength, id, name, autoFocus, autoComplete, onChange, onBlur, onFocus } = props;
51
+ const errorMsg = typeof error === "string" ? error : undefined;
52
+ const hasError = !!error;
53
+ const hasStartIcon = startIcon != null;
54
+ const hasEndIcon = endIcon != null;
55
+ const inputProps = {
56
+ class: cn("hu-textfield__input", hasStartIcon && "hu-textfield__input--has-start", hasEndIcon && "hu-textfield__input--has-end"),
57
+ id, name, placeholder, disabled, required, "readonly": readOnly,
58
+ autofocus: autoFocus, autocomplete: autoComplete,
59
+ maxlength: maxLength,
60
+ onInput: onChange ? (e) => onChange(e.target.value, e) : undefined,
61
+ onBlur, onFocus
62
+ };
63
+ if (value !== undefined)
64
+ inputProps["value"] = value;
65
+ if (props.defaultValue !== undefined)
66
+ inputProps["value"] = props.defaultValue;
67
+ const inputEl = multiline
68
+ ? h("textarea", { ...inputProps, rows })
69
+ : h("input", { ...inputProps, type });
70
+ return h("div", {
71
+ class: cn("hu-textfield", `hu-textfield--${variant}`, size !== "md" && `hu-textfield--${size}`, hasError && "hu-textfield--error", success && "hu-textfield--success", props.fullWidth && "hu-textfield--full", props.class)
72
+ }, label && h("label", {
73
+ class: cn("hu-textfield__label", required && "hu-textfield__label--required"),
74
+ for: id
75
+ }, label), h("div", { class: "hu-textfield__input-wrap" }, startIcon && h("span", { class: "hu-textfield__start-icon" }, startIcon), inputEl, endIcon && h("span", { class: "hu-textfield__end-icon" }, endIcon)), (helperText || errorMsg) && h("span", { class: "hu-textfield__helper" }, errorMsg ?? helperText), maxLength && h("span", { class: "hu-textfield__char-count" }, `${(value ?? "").length}/${maxLength}`));
76
+ }
77
+ // ============================================================
78
+ // ICON BUTTON
79
+ // ============================================================
80
+ const ICON_BUTTON_CSS = `
81
+ .hu-icon-btn {
82
+ display: inline-flex; align-items: center; justify-content: center;
83
+ border: none; background: transparent; border-radius: 50%; cursor: pointer;
84
+ color: var(--hu-text-2); transition: all var(--hu-duration) var(--hu-ease);
85
+ padding: 0; position: relative; user-select: none;
86
+ }
87
+ .hu-icon-btn::after {
88
+ content: ""; position: absolute; inset: 0; border-radius: 50%;
89
+ background: currentColor; opacity: 0; transition: opacity var(--hu-duration) var(--hu-ease);
90
+ }
91
+ .hu-icon-btn:hover::after { opacity: .08; }
92
+ .hu-icon-btn:active::after { opacity: .16; }
93
+ .hu-icon-btn:focus-visible { outline: 2px solid var(--hu-primary); outline-offset: 2px; }
94
+ .hu-icon-btn:disabled { opacity: .4; pointer-events: none; }
95
+ .hu-icon-btn--sm { width: 32px; height: 32px; font-size: 16px; }
96
+ .hu-icon-btn--md { width: 40px; height: 40px; font-size: 20px; }
97
+ .hu-icon-btn--lg { width: 48px; height: 48px; font-size: 24px; }
98
+ .hu-icon-btn--primary { color: var(--hu-primary); }
99
+ .hu-icon-btn--error { color: var(--hu-error); }
100
+ .hu-icon-btn--warning { color: var(--hu-warning); }
101
+ .hu-icon-btn--success { color: var(--hu-success); }
102
+ .hu-icon-btn--contained { background: var(--hu-bg-3); border: 1px solid var(--hu-border); border-radius: 50%; }
103
+ `;
104
+ export function IconButton(props) {
105
+ injectCSS("hu-icon-btn", ICON_BUTTON_CSS);
106
+ const { color = "default", size = "md", variant = "standard", disabled, onClick, children } = props;
107
+ return h("button", {
108
+ class: cn("hu-icon-btn", `hu-icon-btn--${size}`, color !== "default" && `hu-icon-btn--${color}`, variant === "contained" && "hu-icon-btn--contained", props.class),
109
+ type: props.type ?? "button",
110
+ disabled,
111
+ onClick,
112
+ "aria-label": props["aria-label"]
113
+ }, children);
114
+ }
115
+ // ============================================================
116
+ // BUTTON GROUP
117
+ // ============================================================
118
+ const BUTTON_GROUP_CSS = `
119
+ .hu-btn-group { display: inline-flex; align-items: stretch; }
120
+ .hu-btn-group--full { width: 100%; }
121
+ .hu-btn-group--vertical { flex-direction: column; }
122
+ .hu-btn-group .hu-btn { border-radius: 0; }
123
+ .hu-btn-group--horizontal .hu-btn:not(:last-child) { border-right-width: 0; }
124
+ .hu-btn-group--horizontal .hu-btn:first-child { border-radius: var(--hu-radius) 0 0 var(--hu-radius); }
125
+ .hu-btn-group--horizontal .hu-btn:last-child { border-radius: 0 var(--hu-radius) var(--hu-radius) 0; border-right-width: 1px; }
126
+ .hu-btn-group--vertical .hu-btn:not(:last-child) { border-bottom-width: 0; }
127
+ .hu-btn-group--vertical .hu-btn:first-child { border-radius: var(--hu-radius) var(--hu-radius) 0 0; }
128
+ .hu-btn-group--vertical .hu-btn:last-child { border-radius: 0 0 var(--hu-radius) var(--hu-radius); border-bottom-width: 1px; }
129
+ .hu-btn-group .hu-btn:focus { z-index: 1; }
130
+ `;
131
+ export function ButtonGroup(props) {
132
+ injectCSS("hu-btn-group", BUTTON_GROUP_CSS);
133
+ const { orientation = "horizontal", fullWidth } = props;
134
+ return h("div", {
135
+ class: cn("hu-btn-group", `hu-btn-group--${orientation}`, fullWidth && "hu-btn-group--full", props.class),
136
+ role: "group"
137
+ }, props.children);
138
+ }
139
+ // ============================================================
140
+ // TOGGLE BUTTON / TOGGLE BUTTON GROUP
141
+ // ============================================================
142
+ const TOGGLE_BTN_CSS = `
143
+ .hu-toggle-btn {
144
+ display: inline-flex; align-items: center; justify-content: center; gap: var(--hu-space-1);
145
+ padding: var(--hu-space-2) var(--hu-space-3); font-size: var(--hu-font-size-sm);
146
+ font-family: var(--hu-font-sans); border: 1px solid var(--hu-border);
147
+ background: transparent; color: var(--hu-text-2); cursor: pointer;
148
+ transition: all var(--hu-duration) var(--hu-ease); user-select: none;
149
+ }
150
+ .hu-toggle-btn:hover { background: var(--hu-bg-3); color: var(--hu-text); }
151
+ .hu-toggle-btn--selected { background: var(--hu-primary-bg); color: var(--hu-primary); border-color: var(--hu-primary); }
152
+ .hu-toggle-btn:disabled { opacity: .4; pointer-events: none; }
153
+ .hu-toggle-btn-group { display: inline-flex; }
154
+ .hu-toggle-btn-group .hu-toggle-btn { border-radius: 0; }
155
+ .hu-toggle-btn-group .hu-toggle-btn:not(:last-child) { border-right-width: 0; }
156
+ .hu-toggle-btn-group .hu-toggle-btn:first-child { border-radius: var(--hu-radius) 0 0 var(--hu-radius); }
157
+ .hu-toggle-btn-group .hu-toggle-btn:last-child { border-radius: 0 var(--hu-radius) var(--hu-radius) 0; border-right-width: 1px; }
158
+ .hu-toggle-btn-group--vertical { flex-direction: column; }
159
+ .hu-toggle-btn-group--vertical .hu-toggle-btn { border-radius: 0; border-right-width: 1px; }
160
+ .hu-toggle-btn-group--vertical .hu-toggle-btn:not(:last-child) { border-bottom-width: 0; }
161
+ .hu-toggle-btn-group--vertical .hu-toggle-btn:first-child { border-radius: var(--hu-radius) var(--hu-radius) 0 0; }
162
+ .hu-toggle-btn-group--vertical .hu-toggle-btn:last-child { border-radius: 0 0 var(--hu-radius) var(--hu-radius); border-bottom-width: 1px; }
163
+ `;
164
+ export function ToggleButton(props) {
165
+ injectCSS("hu-toggle-btn", TOGGLE_BTN_CSS);
166
+ const { value, selected, disabled, onChange, children } = props;
167
+ return h("button", {
168
+ class: cn("hu-toggle-btn", selected && "hu-toggle-btn--selected", props.class),
169
+ type: "button",
170
+ "aria-pressed": selected,
171
+ disabled,
172
+ onClick: () => onChange?.(value)
173
+ }, children);
174
+ }
175
+ export function ToggleButtonGroup(props) {
176
+ injectCSS("hu-toggle-btn", TOGGLE_BTN_CSS);
177
+ const { value, exclusive = false, orientation = "horizontal", onChange, children = [] } = props;
178
+ const isSelected = (v) => Array.isArray(value) ? value.includes(v) : value === v;
179
+ const handleChange = (v) => {
180
+ if (!onChange)
181
+ return;
182
+ if (exclusive) {
183
+ onChange(isSelected(v) ? "" : v);
184
+ }
185
+ else {
186
+ const arr = Array.isArray(value) ? value : (value ? [value] : []);
187
+ onChange(isSelected(v) ? arr.filter(x => x !== v) : [...arr, v]);
188
+ }
189
+ };
190
+ return h("div", {
191
+ class: cn("hu-toggle-btn-group", orientation === "vertical" && "hu-toggle-btn-group--vertical", props.class),
192
+ role: "group"
193
+ }, ...children.map(child => ToggleButton({ ...child, selected: isSelected(child.value), onChange: handleChange })));
194
+ }
195
+ // ============================================================
196
+ // FAB (Floating Action Button)
197
+ // ============================================================
198
+ const FAB_CSS = `
199
+ .hu-fab {
200
+ display: inline-flex; align-items: center; justify-content: center; gap: var(--hu-space-2);
201
+ border: none; border-radius: 9999px; cursor: pointer;
202
+ font-family: var(--hu-font-sans); font-size: var(--hu-font-size-sm);
203
+ font-weight: var(--hu-font-weight-semibold);
204
+ box-shadow: 0 3px 8px rgba(0,0,0,.25); transition: all var(--hu-duration) var(--hu-ease);
205
+ user-select: none; position: relative; overflow: hidden;
206
+ background: var(--hu-primary); color: var(--hu-primary-text);
207
+ }
208
+ .hu-fab:hover { box-shadow: 0 6px 14px rgba(0,0,0,.3); transform: translateY(-1px); filter: brightness(.95); }
209
+ .hu-fab:active { transform: translateY(0); box-shadow: 0 2px 6px rgba(0,0,0,.25); }
210
+ .hu-fab:focus-visible { outline: 2px solid var(--hu-primary); outline-offset: 3px; }
211
+ .hu-fab:disabled { opacity: .4; pointer-events: none; box-shadow: none; }
212
+ .hu-fab--sm { width: 40px; height: 40px; font-size: 18px; }
213
+ .hu-fab--md { width: 56px; height: 56px; font-size: 22px; }
214
+ .hu-fab--lg { width: 64px; height: 64px; font-size: 26px; }
215
+ .hu-fab--extended { padding: 0 var(--hu-space-4); width: auto; height: 48px; }
216
+ .hu-fab--secondary { background: var(--hu-bg-3); color: var(--hu-text); }
217
+ .hu-fab--error { background: var(--hu-error); color: #fff; }
218
+ .hu-fab--fixed { position: fixed; bottom: var(--hu-space-6); right: var(--hu-space-6); z-index: 999; }
219
+ `;
220
+ export function Fab(props) {
221
+ injectCSS("hu-fab", FAB_CSS);
222
+ const { color = "primary", size = "md", extended, fixed, disabled, onClick, children } = props;
223
+ return h("button", {
224
+ class: cn("hu-fab", `hu-fab--${size}`, color !== "primary" && `hu-fab--${color}`, extended && "hu-fab--extended", fixed && "hu-fab--fixed", props.class),
225
+ type: "button", disabled, onClick,
226
+ "aria-label": props["aria-label"]
227
+ }, children);
228
+ }
229
+ // ============================================================
230
+ // RATING
231
+ // ============================================================
232
+ const RATING_CSS = `
233
+ .hu-rating { display: inline-flex; gap: 2px; user-select: none; }
234
+ .hu-rating__star {
235
+ font-size: 24px; cursor: pointer; color: var(--hu-border-2);
236
+ transition: color var(--hu-duration) var(--hu-ease), transform 80ms;
237
+ line-height: 1;
238
+ }
239
+ .hu-rating__star--filled { color: #f59e0b; }
240
+ .hu-rating__star--half { position: relative; color: var(--hu-border-2); }
241
+ .hu-rating__star--half::after {
242
+ content: "★"; position: absolute; left: 0; top: 0; width: 50%; overflow: hidden; color: #f59e0b;
243
+ }
244
+ .hu-rating__star:hover { transform: scale(1.15); }
245
+ .hu-rating--sm .hu-rating__star { font-size: 18px; }
246
+ .hu-rating--lg .hu-rating__star { font-size: 30px; }
247
+ .hu-rating--readonly .hu-rating__star { cursor: default; }
248
+ .hu-rating--readonly .hu-rating__star:hover { transform: none; }
249
+ .hu-rating--disabled { opacity: .5; pointer-events: none; }
250
+ `;
251
+ export function Rating(props) {
252
+ injectCSS("hu-rating", RATING_CSS);
253
+ const { max = 5, precision = 1, size = "md", readOnly, disabled, onChange } = props;
254
+ const val = signal(props.value ?? props.defaultValue ?? 0);
255
+ const stars = Array.from({ length: max }, (_, i) => {
256
+ const starVal = i + 1;
257
+ const filled = val.value >= starVal;
258
+ const half = !filled && precision === 0.5 && val.value >= starVal - 0.5;
259
+ return h("span", {
260
+ class: cn("hu-rating__star", filled && "hu-rating__star--filled", half && "hu-rating__star--half"),
261
+ onClick: !readOnly && !disabled ? () => { val.value = starVal; onChange?.(starVal); } : undefined,
262
+ "aria-label": `${starVal} star${starVal > 1 ? "s" : ""}`
263
+ }, "★");
264
+ });
265
+ return h("div", {
266
+ class: cn("hu-rating", `hu-rating--${size}`, readOnly && "hu-rating--readonly", disabled && "hu-rating--disabled", props.class),
267
+ role: "radiogroup",
268
+ "aria-label": "rating"
269
+ }, ...stars);
270
+ }
271
+ // ============================================================
272
+ // SLIDER
273
+ // ============================================================
274
+ const SLIDER_CSS = `
275
+ .hu-slider { display: flex; align-items: center; width: 100%; position: relative; padding: 12px 0; cursor: pointer; user-select: none; }
276
+ .hu-slider__track-bg {
277
+ width: 100%; height: 4px; border-radius: 2px;
278
+ background: var(--hu-border-2); position: relative;
279
+ }
280
+ .hu-slider__track-fill {
281
+ position: absolute; left: 0; top: 0; height: 100%; border-radius: 2px;
282
+ background: var(--hu-primary); transition: width 0ms;
283
+ }
284
+ .hu-slider__thumb {
285
+ position: absolute; top: 50%; transform: translate(-50%, -50%);
286
+ width: 18px; height: 18px; border-radius: 50%; background: var(--hu-primary);
287
+ box-shadow: 0 1px 4px rgba(0,0,0,.25); transition: box-shadow var(--hu-duration);
288
+ }
289
+ .hu-slider__thumb:hover { box-shadow: 0 0 0 8px var(--hu-primary-bg); }
290
+ .hu-slider:focus-within .hu-slider__thumb { box-shadow: 0 0 0 10px var(--hu-primary-bg); }
291
+ .hu-slider__input { position: absolute; inset: 0; opacity: 0; width: 100%; cursor: pointer; margin: 0; }
292
+ .hu-slider--disabled { opacity: .5; pointer-events: none; }
293
+ .hu-slider--sm .hu-slider__track-bg { height: 2px; }
294
+ .hu-slider--sm .hu-slider__thumb { width: 14px; height: 14px; }
295
+ .hu-slider--lg .hu-slider__track-bg { height: 6px; }
296
+ .hu-slider--lg .hu-slider__thumb { width: 22px; height: 22px; }
297
+ .hu-slider__mark { position: absolute; top: 50%; transform: translate(-50%, -50%); width: 6px; height: 6px; border-radius: 50%; background: var(--hu-primary-bg); border: 2px solid var(--hu-primary); }
298
+ .hu-slider__value-label {
299
+ position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%);
300
+ background: var(--hu-text); color: var(--hu-bg); font-size: 11px; padding: 2px 6px;
301
+ border-radius: var(--hu-radius-sm); white-space: nowrap; pointer-events: none;
302
+ }
303
+ `;
304
+ export function Slider(props) {
305
+ injectCSS("hu-slider", SLIDER_CSS);
306
+ const { min = 0, max = 100, step = 1, size = "md", disabled, onChange } = props;
307
+ const val = signal(props.value ?? props.defaultValue ?? 0);
308
+ const pct = () => ((val.value - min) / (max - min)) * 100;
309
+ return h("div", {
310
+ class: cn("hu-slider", `hu-slider--${size}`, disabled && "hu-slider--disabled", props.class)
311
+ }, h("div", { class: "hu-slider__track-bg" }, h("div", { class: "hu-slider__track-fill", style: `width:${pct()}%` }), h("div", { class: "hu-slider__thumb", style: `left:${pct()}%` }, props.showValueLabel && h("div", { class: "hu-slider__value-label" }, String(val.value)))), h("input", {
312
+ class: "hu-slider__input",
313
+ type: "range", min, max, step,
314
+ value: val.value, disabled,
315
+ onInput: (e) => {
316
+ val.value = Number(e.target.value);
317
+ onChange?.(val.value);
318
+ }
319
+ }));
320
+ }
321
+ // ============================================================
322
+ // AUTOCOMPLETE
323
+ // ============================================================
324
+ const AUTOCOMPLETE_CSS = `
325
+ .hu-autocomplete { position: relative; width: 100%; }
326
+ .hu-autocomplete__input-wrap { position: relative; }
327
+ .hu-autocomplete__input {
328
+ width: 100%; padding: var(--hu-space-2-5) var(--hu-space-3);
329
+ padding-right: var(--hu-space-8); font-size: var(--hu-font-size-sm);
330
+ font-family: var(--hu-font-sans); background: var(--hu-bg); color: var(--hu-text);
331
+ border: 1px solid var(--hu-border); border-radius: var(--hu-radius);
332
+ outline: none; box-sizing: border-box; transition: all var(--hu-duration) var(--hu-ease);
333
+ }
334
+ .hu-autocomplete__input:focus { border-color: var(--hu-primary); box-shadow: 0 0 0 3px var(--hu-primary-bg); }
335
+ .hu-autocomplete__arrow {
336
+ position: absolute; right: var(--hu-space-3); top: 50%; transform: translateY(-50%);
337
+ color: var(--hu-text-2); pointer-events: none; font-size: 12px; transition: transform var(--hu-duration);
338
+ }
339
+ .hu-autocomplete--open .hu-autocomplete__arrow { transform: translateY(-50%) rotate(180deg); }
340
+ .hu-autocomplete__clear {
341
+ position: absolute; right: 28px; top: 50%; transform: translateY(-50%);
342
+ background: none; border: none; cursor: pointer; color: var(--hu-text-2); font-size: 16px; line-height: 1; padding: 2px;
343
+ }
344
+ .hu-autocomplete__listbox {
345
+ position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 100;
346
+ background: var(--hu-bg); border: 1px solid var(--hu-border); border-radius: var(--hu-radius-md);
347
+ box-shadow: var(--hu-shadow-lg); max-height: 240px; overflow-y: auto; padding: 4px 0;
348
+ }
349
+ .hu-autocomplete__option {
350
+ padding: var(--hu-space-2-5) var(--hu-space-3); cursor: pointer;
351
+ font-size: var(--hu-font-size-sm); color: var(--hu-text); display: flex; align-items: center; gap: var(--hu-space-2);
352
+ transition: background var(--hu-duration);
353
+ }
354
+ .hu-autocomplete__option:hover, .hu-autocomplete__option--focused { background: var(--hu-bg-3); }
355
+ .hu-autocomplete__option--selected { background: var(--hu-primary-bg); color: var(--hu-primary); font-weight: var(--hu-font-weight-medium); }
356
+ .hu-autocomplete__no-options { padding: var(--hu-space-3); font-size: var(--hu-font-size-sm); color: var(--hu-text-2); text-align: center; }
357
+ .hu-autocomplete__group-label { padding: var(--hu-space-1-5) var(--hu-space-3); font-size: var(--hu-font-size-xs); font-weight: var(--hu-font-weight-semibold); color: var(--hu-text-2); text-transform: uppercase; letter-spacing: .06em; }
358
+ `;
359
+ export function Autocomplete(props) {
360
+ injectCSS("hu-autocomplete", AUTOCOMPLETE_CSS);
361
+ const { options, placeholder, label, clearable, disabled, noOptionsText = "No options", onChange } = props;
362
+ const inputVal = signal(props.value ? (options.find(o => o.value === props.value)?.label ?? "") : "");
363
+ const isOpen = signal(false);
364
+ const selected = signal(props.value ?? "");
365
+ const filtered = () => options.filter(o => !inputVal.value || o.label.toLowerCase().includes(inputVal.value.toLowerCase()));
366
+ return h("div", {
367
+ class: cn("hu-autocomplete", isOpen.value && "hu-autocomplete--open", props.class)
368
+ }, label && h("label", { class: "hu-textfield__label" }, label), h("div", { class: "hu-autocomplete__input-wrap" }, h("input", {
369
+ class: "hu-autocomplete__input",
370
+ value: inputVal.value, placeholder, disabled,
371
+ onFocus: () => { isOpen.value = true; },
372
+ onInput: (e) => { inputVal.value = e.target.value; isOpen.value = true; },
373
+ onBlur: () => setTimeout(() => { isOpen.value = false; }, 150)
374
+ }), clearable && selected.value && h("button", {
375
+ class: "hu-autocomplete__clear",
376
+ type: "button",
377
+ onMouseDown: (e) => {
378
+ e.preventDefault();
379
+ selected.value = "";
380
+ inputVal.value = "";
381
+ onChange?.(null);
382
+ }
383
+ }, "×"), h("span", { class: "hu-autocomplete__arrow" }, "▾")), isOpen.value && h("ul", { class: "hu-autocomplete__listbox", role: "listbox" }, filtered().length === 0
384
+ ? h("li", { class: "hu-autocomplete__no-options" }, noOptionsText)
385
+ : filtered().map(opt => h("li", {
386
+ class: cn("hu-autocomplete__option", selected.value === opt.value && "hu-autocomplete__option--selected"),
387
+ role: "option",
388
+ "aria-selected": selected.value === opt.value,
389
+ onMouseDown: (e) => {
390
+ e.preventDefault();
391
+ selected.value = opt.value;
392
+ inputVal.value = opt.label;
393
+ isOpen.value = false;
394
+ onChange?.(opt.value);
395
+ }
396
+ }, opt.label))));
397
+ }
398
+ // ============================================================
399
+ // FORM CONTROL / FORM GROUP / FORM LABEL / FORM HELPER TEXT
400
+ // ============================================================
401
+ const FORM_CSS = `
402
+ .hu-form-control { display: flex; flex-direction: column; gap: var(--hu-space-1); }
403
+ .hu-form-control--full { width: 100%; }
404
+ .hu-form-control--row { flex-direction: row; flex-wrap: wrap; gap: var(--hu-space-3); }
405
+ .hu-form-group { display: flex; flex-direction: column; gap: var(--hu-space-2); border: none; padding: 0; margin: 0; }
406
+ .hu-form-group--row { flex-direction: row; flex-wrap: wrap; gap: var(--hu-space-4); }
407
+ .hu-form-label { font-size: var(--hu-font-size-sm); font-weight: var(--hu-font-weight-medium); color: var(--hu-text-2); display: flex; gap: var(--hu-space-1); align-items: center; }
408
+ .hu-form-label--required::after { content: " *"; color: var(--hu-error); }
409
+ .hu-form-label--focused { color: var(--hu-primary); }
410
+ .hu-form-label--error { color: var(--hu-error); }
411
+ .hu-form-helper { font-size: var(--hu-font-size-xs); color: var(--hu-text-2); }
412
+ .hu-form-helper--error { color: var(--hu-error); }
413
+ .hu-form-helper--success { color: var(--hu-success); }
414
+ `;
415
+ export function FormControl(props) {
416
+ injectCSS("hu-form", FORM_CSS);
417
+ return h("div", {
418
+ class: cn("hu-form-control", props.fullWidth && "hu-form-control--full", props.row && "hu-form-control--row", props.class)
419
+ }, props.children);
420
+ }
421
+ export function FormGroup(props) {
422
+ injectCSS("hu-form", FORM_CSS);
423
+ return h("fieldset", { class: cn("hu-form-group", props.row && "hu-form-group--row", props.class) }, props.children);
424
+ }
425
+ export function FormLabel(props) {
426
+ injectCSS("hu-form", FORM_CSS);
427
+ return h("label", {
428
+ class: cn("hu-form-label", props.required && "hu-form-label--required", props.focused && "hu-form-label--focused", props.error && "hu-form-label--error", props.class),
429
+ for: props.for
430
+ }, props.children);
431
+ }
432
+ export function FormHelperText(props) {
433
+ injectCSS("hu-form", FORM_CSS);
434
+ return h("p", {
435
+ class: cn("hu-form-helper", props.error && "hu-form-helper--error", props.success && "hu-form-helper--success", props.class)
436
+ }, props.children);
437
+ }
@@ -0,0 +1,224 @@
1
+ /**
2
+ * HyperUI Layout & Navigation Components
3
+ * Card · Alert · Badge · Avatar · Skeleton · Progress · Accordion
4
+ * Tabs · Breadcrumb · Pagination · Navbar · Sidebar · DataTable
5
+ */
6
+ import { type Signal } from "@hyperpackai/hyperion";
7
+ import { type VNode } from "../theme/index.js";
8
+ export interface CardProps {
9
+ title?: string;
10
+ description?: string;
11
+ media?: unknown;
12
+ footer?: unknown;
13
+ hoverable?: boolean;
14
+ variant?: "default" | "ghost" | "elevated";
15
+ onClick?: (e: MouseEvent) => void;
16
+ class?: string;
17
+ children?: unknown;
18
+ }
19
+ export declare function Card(props: CardProps): VNode;
20
+ export interface AlertProps {
21
+ type?: "info" | "success" | "warning" | "error";
22
+ title?: string;
23
+ description?: string;
24
+ icon?: unknown | false;
25
+ class?: string;
26
+ children?: unknown;
27
+ }
28
+ export declare function Alert(props: AlertProps): VNode;
29
+ export interface BadgeProps {
30
+ variant?: "default" | "primary" | "success" | "warning" | "error" | "info" | "solid-primary" | "solid-success" | "solid-error";
31
+ size?: "xs" | "sm" | "md" | "lg";
32
+ dot?: boolean;
33
+ class?: string;
34
+ children?: unknown;
35
+ }
36
+ export declare function Badge(props: BadgeProps): VNode;
37
+ export interface AvatarProps {
38
+ src?: string;
39
+ alt?: string;
40
+ name?: string;
41
+ size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
42
+ shape?: "circle" | "square";
43
+ color?: string;
44
+ class?: string;
45
+ }
46
+ export declare function Avatar(props: AvatarProps): VNode;
47
+ export interface SkeletonProps {
48
+ width?: string | number;
49
+ height?: string | number;
50
+ variant?: "rect" | "text" | "circle" | "title";
51
+ class?: string;
52
+ }
53
+ export declare function Skeleton(props: SkeletonProps): VNode;
54
+ export interface ProgressProps {
55
+ value?: number;
56
+ max?: number;
57
+ label?: string;
58
+ showValue?: boolean;
59
+ size?: "sm" | "md" | "lg";
60
+ color?: "primary" | "success" | "error" | "warning";
61
+ indeterminate?: boolean;
62
+ class?: string;
63
+ }
64
+ export declare function Progress(props: ProgressProps): VNode;
65
+ export interface TabItem {
66
+ id: string;
67
+ label: string;
68
+ icon?: unknown;
69
+ badge?: string | number;
70
+ disabled?: boolean;
71
+ content: unknown;
72
+ }
73
+ export interface TabsProps {
74
+ items: TabItem[];
75
+ defaultTab?: string;
76
+ activeTab?: string | Signal<string>;
77
+ variant?: "underline" | "pill";
78
+ onChange?: (id: string) => void;
79
+ class?: string;
80
+ }
81
+ export declare function Tabs(props: TabsProps): VNode;
82
+ export interface AccordionItem {
83
+ id: string;
84
+ title: string;
85
+ content: unknown;
86
+ icon?: unknown;
87
+ disabled?: boolean;
88
+ }
89
+ export interface AccordionProps {
90
+ items: AccordionItem[];
91
+ multiple?: boolean;
92
+ defaultOpen?: string[];
93
+ variant?: "default" | "ghost";
94
+ class?: string;
95
+ }
96
+ export declare function Accordion(props: AccordionProps): VNode;
97
+ export interface BreadcrumbItem {
98
+ label: string;
99
+ href?: string;
100
+ onClick?: () => void;
101
+ }
102
+ export interface BreadcrumbProps {
103
+ items: BreadcrumbItem[];
104
+ separator?: string;
105
+ class?: string;
106
+ }
107
+ export declare function Breadcrumb(props: BreadcrumbProps): VNode;
108
+ export interface PaginationProps {
109
+ page: number;
110
+ totalPages: number;
111
+ siblingCount?: number;
112
+ onChange: (page: number) => void;
113
+ showFirstLast?: boolean;
114
+ class?: string;
115
+ }
116
+ export declare function Pagination(props: PaginationProps): VNode;
117
+ export interface StepperItem {
118
+ id: string;
119
+ label: string;
120
+ description?: string;
121
+ icon?: unknown;
122
+ optional?: boolean;
123
+ disabled?: boolean;
124
+ error?: boolean;
125
+ }
126
+ export interface StepperProps {
127
+ steps: StepperItem[];
128
+ activeStep?: string | number;
129
+ completed?: string[];
130
+ orientation?: "horizontal" | "vertical";
131
+ onStepClick?: (id: string, index: number) => void;
132
+ class?: string;
133
+ }
134
+ export declare function Stepper(props: StepperProps): VNode;
135
+ export interface TimelineItem {
136
+ id: string;
137
+ title: string;
138
+ description?: unknown;
139
+ time?: string;
140
+ status?: "default" | "success" | "warning" | "error" | "info";
141
+ marker?: unknown;
142
+ actions?: unknown;
143
+ }
144
+ export interface TimelineProps {
145
+ items: TimelineItem[];
146
+ class?: string;
147
+ }
148
+ export declare function Timeline(props: TimelineProps): VNode;
149
+ export interface TreeViewItem {
150
+ id: string;
151
+ label: string;
152
+ icon?: unknown;
153
+ badge?: unknown;
154
+ disabled?: boolean;
155
+ children?: TreeViewItem[];
156
+ }
157
+ export interface TreeViewProps {
158
+ items: TreeViewItem[];
159
+ expanded?: string[];
160
+ selected?: string;
161
+ onToggle?: (id: string, expanded: boolean) => void;
162
+ onSelect?: (id: string) => void;
163
+ class?: string;
164
+ }
165
+ export declare function TreeView(props: TreeViewProps): VNode;
166
+ export interface NavLink {
167
+ label: string;
168
+ href: string;
169
+ active?: boolean;
170
+ }
171
+ export interface NavbarProps {
172
+ brand?: unknown;
173
+ links?: NavLink[];
174
+ actions?: unknown;
175
+ class?: string;
176
+ }
177
+ export declare function Navbar(props: NavbarProps): VNode;
178
+ export interface SidebarItem {
179
+ id: string;
180
+ label: string;
181
+ icon?: unknown;
182
+ badge?: unknown;
183
+ href?: string;
184
+ active?: boolean;
185
+ onClick?: () => void;
186
+ }
187
+ export interface SidebarSection {
188
+ label?: string;
189
+ items: SidebarItem[];
190
+ }
191
+ export interface SidebarProps {
192
+ header?: unknown;
193
+ sections: SidebarSection[];
194
+ footer?: unknown;
195
+ width?: "sm" | "md" | "lg";
196
+ class?: string;
197
+ }
198
+ export declare function Sidebar(props: SidebarProps): VNode;
199
+ export interface TableColumn<T> {
200
+ key: string;
201
+ header: string;
202
+ width?: string;
203
+ sortable?: boolean;
204
+ render?: (row: T, i: number) => unknown;
205
+ align?: "left" | "center" | "right";
206
+ }
207
+ export interface DataTableProps<T extends Record<string, unknown>> {
208
+ columns: TableColumn<T>[];
209
+ rows: T[];
210
+ rowKey?: (row: T) => string;
211
+ sortColumn?: string;
212
+ sortDir?: "asc" | "desc";
213
+ onSort?: (key: string) => void;
214
+ onRowClick?: (row: T) => void;
215
+ emptyMessage?: string;
216
+ footer?: unknown;
217
+ selectable?: boolean;
218
+ selectedRows?: Set<string>;
219
+ onSelectRow?: (key: string, selected: boolean) => void;
220
+ onSelectAll?: (selected: boolean) => void;
221
+ class?: string;
222
+ }
223
+ export declare function DataTable<T extends Record<string, unknown>>(props: DataTableProps<T>): VNode;
224
+ //# sourceMappingURL=layout.d.ts.map