@jameskabz/nextcraft-ui 0.6.5 → 0.6.6

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 (357) hide show
  1. package/dist/index.cjs +3448 -103
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +746 -54
  4. package/dist/index.d.ts +746 -54
  5. package/dist/index.js +3388 -50
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -26
  8. package/dist/components/craft-alert.cjs +0 -69
  9. package/dist/components/craft-alert.cjs.map +0 -1
  10. package/dist/components/craft-alert.d.cts +0 -16
  11. package/dist/components/craft-alert.d.ts +0 -16
  12. package/dist/components/craft-alert.js +0 -45
  13. package/dist/components/craft-alert.js.map +0 -1
  14. package/dist/components/craft-badge.cjs +0 -54
  15. package/dist/components/craft-badge.cjs.map +0 -1
  16. package/dist/components/craft-badge.d.cts +0 -12
  17. package/dist/components/craft-badge.d.ts +0 -12
  18. package/dist/components/craft-badge.js +0 -30
  19. package/dist/components/craft-badge.js.map +0 -1
  20. package/dist/components/craft-button.cjs +0 -66
  21. package/dist/components/craft-button.cjs.map +0 -1
  22. package/dist/components/craft-button.d.cts +0 -15
  23. package/dist/components/craft-button.d.ts +0 -15
  24. package/dist/components/craft-button.js +0 -42
  25. package/dist/components/craft-button.js.map +0 -1
  26. package/dist/components/craft-card.cjs +0 -63
  27. package/dist/components/craft-card.cjs.map +0 -1
  28. package/dist/components/craft-card.d.cts +0 -13
  29. package/dist/components/craft-card.d.ts +0 -13
  30. package/dist/components/craft-card.js +0 -39
  31. package/dist/components/craft-card.js.map +0 -1
  32. package/dist/components/craft-checkbox.cjs +0 -103
  33. package/dist/components/craft-checkbox.cjs.map +0 -1
  34. package/dist/components/craft-checkbox.d.cts +0 -16
  35. package/dist/components/craft-checkbox.d.ts +0 -16
  36. package/dist/components/craft-checkbox.js +0 -69
  37. package/dist/components/craft-checkbox.js.map +0 -1
  38. package/dist/components/craft-command-palette.cjs +0 -134
  39. package/dist/components/craft-command-palette.cjs.map +0 -1
  40. package/dist/components/craft-command-palette.d.cts +0 -28
  41. package/dist/components/craft-command-palette.d.ts +0 -28
  42. package/dist/components/craft-command-palette.js +0 -100
  43. package/dist/components/craft-command-palette.js.map +0 -1
  44. package/dist/components/craft-confirm-dialog.cjs +0 -114
  45. package/dist/components/craft-confirm-dialog.cjs.map +0 -1
  46. package/dist/components/craft-confirm-dialog.d.cts +0 -21
  47. package/dist/components/craft-confirm-dialog.d.ts +0 -21
  48. package/dist/components/craft-confirm-dialog.js +0 -80
  49. package/dist/components/craft-confirm-dialog.js.map +0 -1
  50. package/dist/components/craft-create-edit-drawer.cjs +0 -112
  51. package/dist/components/craft-create-edit-drawer.cjs.map +0 -1
  52. package/dist/components/craft-create-edit-drawer.d.cts +0 -28
  53. package/dist/components/craft-create-edit-drawer.d.ts +0 -28
  54. package/dist/components/craft-create-edit-drawer.js +0 -78
  55. package/dist/components/craft-create-edit-drawer.js.map +0 -1
  56. package/dist/components/craft-currency-input.cjs +0 -68
  57. package/dist/components/craft-currency-input.cjs.map +0 -1
  58. package/dist/components/craft-currency-input.d.cts +0 -14
  59. package/dist/components/craft-currency-input.d.ts +0 -14
  60. package/dist/components/craft-currency-input.js +0 -34
  61. package/dist/components/craft-currency-input.js.map +0 -1
  62. package/dist/components/craft-data-table.cjs +0 -407
  63. package/dist/components/craft-data-table.cjs.map +0 -1
  64. package/dist/components/craft-data-table.d.cts +0 -58
  65. package/dist/components/craft-data-table.d.ts +0 -58
  66. package/dist/components/craft-data-table.js +0 -373
  67. package/dist/components/craft-data-table.js.map +0 -1
  68. package/dist/components/craft-date-picker.cjs +0 -226
  69. package/dist/components/craft-date-picker.cjs.map +0 -1
  70. package/dist/components/craft-date-picker.d.cts +0 -17
  71. package/dist/components/craft-date-picker.d.ts +0 -17
  72. package/dist/components/craft-date-picker.js +0 -192
  73. package/dist/components/craft-date-picker.js.map +0 -1
  74. package/dist/components/craft-drawer.cjs +0 -126
  75. package/dist/components/craft-drawer.cjs.map +0 -1
  76. package/dist/components/craft-drawer.d.cts +0 -19
  77. package/dist/components/craft-drawer.d.ts +0 -19
  78. package/dist/components/craft-drawer.js +0 -92
  79. package/dist/components/craft-drawer.js.map +0 -1
  80. package/dist/components/craft-dropdown-menu.cjs +0 -127
  81. package/dist/components/craft-dropdown-menu.cjs.map +0 -1
  82. package/dist/components/craft-dropdown-menu.d.cts +0 -28
  83. package/dist/components/craft-dropdown-menu.d.ts +0 -28
  84. package/dist/components/craft-dropdown-menu.js +0 -93
  85. package/dist/components/craft-dropdown-menu.js.map +0 -1
  86. package/dist/components/craft-empty-state.cjs +0 -58
  87. package/dist/components/craft-empty-state.cjs.map +0 -1
  88. package/dist/components/craft-empty-state.d.cts +0 -14
  89. package/dist/components/craft-empty-state.d.ts +0 -14
  90. package/dist/components/craft-empty-state.js +0 -34
  91. package/dist/components/craft-empty-state.js.map +0 -1
  92. package/dist/components/craft-error-state.cjs +0 -60
  93. package/dist/components/craft-error-state.cjs.map +0 -1
  94. package/dist/components/craft-error-state.d.cts +0 -15
  95. package/dist/components/craft-error-state.d.ts +0 -15
  96. package/dist/components/craft-error-state.js +0 -36
  97. package/dist/components/craft-error-state.js.map +0 -1
  98. package/dist/components/craft-filter-bar.cjs +0 -76
  99. package/dist/components/craft-filter-bar.cjs.map +0 -1
  100. package/dist/components/craft-filter-bar.d.cts +0 -18
  101. package/dist/components/craft-filter-bar.d.ts +0 -18
  102. package/dist/components/craft-filter-bar.js +0 -52
  103. package/dist/components/craft-filter-bar.js.map +0 -1
  104. package/dist/components/craft-form-builder.cjs +0 -330
  105. package/dist/components/craft-form-builder.cjs.map +0 -1
  106. package/dist/components/craft-form-builder.d.cts +0 -57
  107. package/dist/components/craft-form-builder.d.ts +0 -57
  108. package/dist/components/craft-form-builder.js +0 -301
  109. package/dist/components/craft-form-builder.js.map +0 -1
  110. package/dist/components/craft-form-field.cjs +0 -301
  111. package/dist/components/craft-form-field.cjs.map +0 -1
  112. package/dist/components/craft-form-field.d.cts +0 -30
  113. package/dist/components/craft-form-field.d.ts +0 -30
  114. package/dist/components/craft-form-field.js +0 -280
  115. package/dist/components/craft-form-field.js.map +0 -1
  116. package/dist/components/craft-form.cjs +0 -114
  117. package/dist/components/craft-form.cjs.map +0 -1
  118. package/dist/components/craft-form.d.cts +0 -27
  119. package/dist/components/craft-form.d.ts +0 -27
  120. package/dist/components/craft-form.js +0 -80
  121. package/dist/components/craft-form.js.map +0 -1
  122. package/dist/components/craft-icon.cjs +0 -102
  123. package/dist/components/craft-icon.cjs.map +0 -1
  124. package/dist/components/craft-icon.d.cts +0 -19
  125. package/dist/components/craft-icon.d.ts +0 -19
  126. package/dist/components/craft-icon.js +0 -67
  127. package/dist/components/craft-icon.js.map +0 -1
  128. package/dist/components/craft-input.cjs +0 -78
  129. package/dist/components/craft-input.cjs.map +0 -1
  130. package/dist/components/craft-input.d.cts +0 -19
  131. package/dist/components/craft-input.d.ts +0 -19
  132. package/dist/components/craft-input.js +0 -44
  133. package/dist/components/craft-input.js.map +0 -1
  134. package/dist/components/craft-link.cjs +0 -70
  135. package/dist/components/craft-link.cjs.map +0 -1
  136. package/dist/components/craft-link.d.cts +0 -14
  137. package/dist/components/craft-link.d.ts +0 -14
  138. package/dist/components/craft-link.js +0 -36
  139. package/dist/components/craft-link.js.map +0 -1
  140. package/dist/components/craft-loading-state.cjs +0 -64
  141. package/dist/components/craft-loading-state.cjs.map +0 -1
  142. package/dist/components/craft-loading-state.d.cts +0 -13
  143. package/dist/components/craft-loading-state.d.ts +0 -13
  144. package/dist/components/craft-loading-state.js +0 -40
  145. package/dist/components/craft-loading-state.js.map +0 -1
  146. package/dist/components/craft-modal.cjs +0 -174
  147. package/dist/components/craft-modal.cjs.map +0 -1
  148. package/dist/components/craft-modal.d.cts +0 -19
  149. package/dist/components/craft-modal.d.ts +0 -19
  150. package/dist/components/craft-modal.js +0 -140
  151. package/dist/components/craft-modal.js.map +0 -1
  152. package/dist/components/craft-number-input.cjs +0 -63
  153. package/dist/components/craft-number-input.cjs.map +0 -1
  154. package/dist/components/craft-number-input.d.cts +0 -12
  155. package/dist/components/craft-number-input.d.ts +0 -12
  156. package/dist/components/craft-number-input.js +0 -29
  157. package/dist/components/craft-number-input.js.map +0 -1
  158. package/dist/components/craft-pagination.cjs +0 -130
  159. package/dist/components/craft-pagination.cjs.map +0 -1
  160. package/dist/components/craft-pagination.d.cts +0 -19
  161. package/dist/components/craft-pagination.d.ts +0 -19
  162. package/dist/components/craft-pagination.js +0 -106
  163. package/dist/components/craft-pagination.js.map +0 -1
  164. package/dist/components/craft-popover.cjs +0 -123
  165. package/dist/components/craft-popover.cjs.map +0 -1
  166. package/dist/components/craft-popover.d.cts +0 -20
  167. package/dist/components/craft-popover.d.ts +0 -20
  168. package/dist/components/craft-popover.js +0 -89
  169. package/dist/components/craft-popover.js.map +0 -1
  170. package/dist/components/craft-select.cjs +0 -84
  171. package/dist/components/craft-select.cjs.map +0 -1
  172. package/dist/components/craft-select.d.cts +0 -12
  173. package/dist/components/craft-select.d.ts +0 -12
  174. package/dist/components/craft-select.js +0 -50
  175. package/dist/components/craft-select.js.map +0 -1
  176. package/dist/components/craft-skeleton.cjs +0 -45
  177. package/dist/components/craft-skeleton.cjs.map +0 -1
  178. package/dist/components/craft-skeleton.d.cts +0 -10
  179. package/dist/components/craft-skeleton.d.ts +0 -10
  180. package/dist/components/craft-skeleton.js +0 -21
  181. package/dist/components/craft-skeleton.js.map +0 -1
  182. package/dist/components/craft-stat-card.cjs +0 -67
  183. package/dist/components/craft-stat-card.cjs.map +0 -1
  184. package/dist/components/craft-stat-card.d.cts +0 -17
  185. package/dist/components/craft-stat-card.d.ts +0 -17
  186. package/dist/components/craft-stat-card.js +0 -43
  187. package/dist/components/craft-stat-card.js.map +0 -1
  188. package/dist/components/craft-submit-button.cjs +0 -71
  189. package/dist/components/craft-submit-button.cjs.map +0 -1
  190. package/dist/components/craft-submit-button.d.cts +0 -13
  191. package/dist/components/craft-submit-button.d.ts +0 -13
  192. package/dist/components/craft-submit-button.js +0 -47
  193. package/dist/components/craft-submit-button.js.map +0 -1
  194. package/dist/components/craft-switch.cjs +0 -82
  195. package/dist/components/craft-switch.cjs.map +0 -1
  196. package/dist/components/craft-switch.d.cts +0 -14
  197. package/dist/components/craft-switch.d.ts +0 -14
  198. package/dist/components/craft-switch.js +0 -48
  199. package/dist/components/craft-switch.js.map +0 -1
  200. package/dist/components/craft-table-toolbar.cjs +0 -79
  201. package/dist/components/craft-table-toolbar.cjs.map +0 -1
  202. package/dist/components/craft-table-toolbar.d.cts +0 -19
  203. package/dist/components/craft-table-toolbar.d.ts +0 -19
  204. package/dist/components/craft-table-toolbar.js +0 -55
  205. package/dist/components/craft-table-toolbar.js.map +0 -1
  206. package/dist/components/craft-tabs.cjs +0 -105
  207. package/dist/components/craft-tabs.cjs.map +0 -1
  208. package/dist/components/craft-tabs.d.cts +0 -19
  209. package/dist/components/craft-tabs.d.ts +0 -19
  210. package/dist/components/craft-tabs.js +0 -71
  211. package/dist/components/craft-tabs.js.map +0 -1
  212. package/dist/components/craft-textarea.cjs +0 -69
  213. package/dist/components/craft-textarea.cjs.map +0 -1
  214. package/dist/components/craft-textarea.d.cts +0 -12
  215. package/dist/components/craft-textarea.d.ts +0 -12
  216. package/dist/components/craft-textarea.js +0 -35
  217. package/dist/components/craft-textarea.js.map +0 -1
  218. package/dist/components/craft-toast.cjs +0 -98
  219. package/dist/components/craft-toast.cjs.map +0 -1
  220. package/dist/components/craft-toast.d.cts +0 -24
  221. package/dist/components/craft-toast.d.ts +0 -24
  222. package/dist/components/craft-toast.js +0 -63
  223. package/dist/components/craft-toast.js.map +0 -1
  224. package/dist/components/craft-tooltip.cjs +0 -75
  225. package/dist/components/craft-tooltip.cjs.map +0 -1
  226. package/dist/components/craft-tooltip.d.cts +0 -13
  227. package/dist/components/craft-tooltip.d.ts +0 -13
  228. package/dist/components/craft-tooltip.js +0 -41
  229. package/dist/components/craft-tooltip.js.map +0 -1
  230. package/dist/components/forms/types.cjs +0 -17
  231. package/dist/components/forms/types.cjs.map +0 -1
  232. package/dist/components/forms/types.d.cts +0 -7
  233. package/dist/components/forms/types.d.ts +0 -7
  234. package/dist/components/forms/types.js +0 -1
  235. package/dist/components/forms/types.js.map +0 -1
  236. package/dist/components/glass-card.cjs +0 -64
  237. package/dist/components/glass-card.cjs.map +0 -1
  238. package/dist/components/glass-card.d.cts +0 -12
  239. package/dist/components/glass-card.d.ts +0 -12
  240. package/dist/components/glass-card.js +0 -40
  241. package/dist/components/glass-card.js.map +0 -1
  242. package/dist/components/layout/app-shell.cjs +0 -49
  243. package/dist/components/layout/app-shell.cjs.map +0 -1
  244. package/dist/components/layout/app-shell.d.cts +0 -10
  245. package/dist/components/layout/app-shell.d.ts +0 -10
  246. package/dist/components/layout/app-shell.js +0 -25
  247. package/dist/components/layout/app-shell.js.map +0 -1
  248. package/dist/components/layout/app-template.cjs +0 -104
  249. package/dist/components/layout/app-template.cjs.map +0 -1
  250. package/dist/components/layout/app-template.d.cts +0 -19
  251. package/dist/components/layout/app-template.d.ts +0 -19
  252. package/dist/components/layout/app-template.js +0 -70
  253. package/dist/components/layout/app-template.js.map +0 -1
  254. package/dist/components/layout/auth-layout.cjs +0 -65
  255. package/dist/components/layout/auth-layout.cjs.map +0 -1
  256. package/dist/components/layout/auth-layout.d.cts +0 -12
  257. package/dist/components/layout/auth-layout.d.ts +0 -12
  258. package/dist/components/layout/auth-layout.js +0 -41
  259. package/dist/components/layout/auth-layout.js.map +0 -1
  260. package/dist/components/layout/breadcrumbs.cjs +0 -39
  261. package/dist/components/layout/breadcrumbs.cjs.map +0 -1
  262. package/dist/components/layout/breadcrumbs.d.cts +0 -13
  263. package/dist/components/layout/breadcrumbs.d.ts +0 -13
  264. package/dist/components/layout/breadcrumbs.js +0 -15
  265. package/dist/components/layout/breadcrumbs.js.map +0 -1
  266. package/dist/components/layout/container.cjs +0 -45
  267. package/dist/components/layout/container.cjs.map +0 -1
  268. package/dist/components/layout/container.d.cts +0 -9
  269. package/dist/components/layout/container.d.ts +0 -9
  270. package/dist/components/layout/container.js +0 -21
  271. package/dist/components/layout/container.js.map +0 -1
  272. package/dist/components/layout/grid.cjs +0 -47
  273. package/dist/components/layout/grid.cjs.map +0 -1
  274. package/dist/components/layout/grid.d.cts +0 -10
  275. package/dist/components/layout/grid.d.ts +0 -10
  276. package/dist/components/layout/grid.js +0 -23
  277. package/dist/components/layout/grid.js.map +0 -1
  278. package/dist/components/layout/layout-config.cjs +0 -78
  279. package/dist/components/layout/layout-config.cjs.map +0 -1
  280. package/dist/components/layout/layout-config.d.cts +0 -92
  281. package/dist/components/layout/layout-config.d.ts +0 -92
  282. package/dist/components/layout/layout-config.js +0 -54
  283. package/dist/components/layout/layout-config.js.map +0 -1
  284. package/dist/components/layout/page-header.cjs +0 -52
  285. package/dist/components/layout/page-header.cjs.map +0 -1
  286. package/dist/components/layout/page-header.d.cts +0 -11
  287. package/dist/components/layout/page-header.d.ts +0 -11
  288. package/dist/components/layout/page-header.js +0 -28
  289. package/dist/components/layout/page-header.js.map +0 -1
  290. package/dist/components/layout/sidebar.cjs +0 -64
  291. package/dist/components/layout/sidebar.cjs.map +0 -1
  292. package/dist/components/layout/sidebar.d.cts +0 -17
  293. package/dist/components/layout/sidebar.d.ts +0 -17
  294. package/dist/components/layout/sidebar.js +0 -40
  295. package/dist/components/layout/sidebar.js.map +0 -1
  296. package/dist/components/layout/top-nav.cjs +0 -49
  297. package/dist/components/layout/top-nav.cjs.map +0 -1
  298. package/dist/components/layout/top-nav.d.cts +0 -11
  299. package/dist/components/layout/top-nav.d.ts +0 -11
  300. package/dist/components/layout/top-nav.js +0 -25
  301. package/dist/components/layout/top-nav.js.map +0 -1
  302. package/dist/components/layout/types.cjs +0 -29
  303. package/dist/components/layout/types.cjs.map +0 -1
  304. package/dist/components/layout/types.d.cts +0 -12
  305. package/dist/components/layout/types.d.ts +0 -12
  306. package/dist/components/layout/types.js +0 -5
  307. package/dist/components/layout/types.js.map +0 -1
  308. package/dist/components/table/types.cjs +0 -17
  309. package/dist/components/table/types.cjs.map +0 -1
  310. package/dist/components/table/types.d.cts +0 -7
  311. package/dist/components/table/types.d.ts +0 -7
  312. package/dist/components/table/types.js +0 -1
  313. package/dist/components/table/types.js.map +0 -1
  314. package/dist/components/theme-switcher.cjs +0 -72
  315. package/dist/components/theme-switcher.cjs.map +0 -1
  316. package/dist/components/theme-switcher.d.cts +0 -9
  317. package/dist/components/theme-switcher.d.ts +0 -9
  318. package/dist/components/theme-switcher.js +0 -48
  319. package/dist/components/theme-switcher.js.map +0 -1
  320. package/dist/craft/components.cjs +0 -123
  321. package/dist/craft/components.cjs.map +0 -1
  322. package/dist/craft/components.d.cts +0 -36
  323. package/dist/craft/components.d.ts +0 -36
  324. package/dist/craft/components.js +0 -67
  325. package/dist/craft/components.js.map +0 -1
  326. package/dist/craft/forms.cjs +0 -35
  327. package/dist/craft/forms.cjs.map +0 -1
  328. package/dist/craft/forms.d.cts +0 -7
  329. package/dist/craft/forms.d.ts +0 -7
  330. package/dist/craft/forms.js +0 -9
  331. package/dist/craft/forms.js.map +0 -1
  332. package/dist/craft/layout.cjs +0 -56
  333. package/dist/craft/layout.cjs.map +0 -1
  334. package/dist/craft/layout.d.cts +0 -12
  335. package/dist/craft/layout.d.ts +0 -12
  336. package/dist/craft/layout.js +0 -23
  337. package/dist/craft/layout.js.map +0 -1
  338. package/dist/craft/table.cjs +0 -38
  339. package/dist/craft/table.cjs.map +0 -1
  340. package/dist/craft/table.d.cts +0 -7
  341. package/dist/craft/table.d.ts +0 -7
  342. package/dist/craft/table.js +0 -11
  343. package/dist/craft/table.js.map +0 -1
  344. package/dist/craft/theme.cjs +0 -34
  345. package/dist/craft/theme.cjs.map +0 -1
  346. package/dist/craft/theme.d.cts +0 -4
  347. package/dist/craft/theme.d.ts +0 -4
  348. package/dist/craft/theme.js +0 -8
  349. package/dist/craft/theme.js.map +0 -1
  350. package/dist/theme-context-EVI9PfKv.d.cts +0 -22
  351. package/dist/theme-context-EVI9PfKv.d.ts +0 -22
  352. package/dist/utils/cn.cjs +0 -31
  353. package/dist/utils/cn.cjs.map +0 -1
  354. package/dist/utils/cn.d.cts +0 -3
  355. package/dist/utils/cn.d.ts +0 -3
  356. package/dist/utils/cn.js +0 -7
  357. package/dist/utils/cn.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,53 +1,3391 @@
1
- import { CraftButton } from "./components/craft-button";
2
- import { GlassCard } from "./components/glass-card";
3
- import { CraftInput } from "./components/craft-input";
4
- import { CraftTextarea } from "./components/craft-textarea";
5
- import { CraftSelect } from "./components/craft-select";
6
- import { CraftCheckbox } from "./components/craft-checkbox";
7
- import { CraftSwitch } from "./components/craft-switch";
8
- import { CraftBadge } from "./components/craft-badge";
9
- import { CraftAlert } from "./components/craft-alert";
10
- import { CraftErrorState } from "./components/craft-error-state";
11
- import { CraftLoadingState } from "./components/craft-loading-state";
12
- import { CraftCard } from "./components/craft-card";
13
- import { CraftModal } from "./components/craft-modal";
14
- import { CraftDrawer } from "./components/craft-drawer";
15
- import { CraftTabs } from "./components/craft-tabs";
16
- import { CraftTooltip } from "./components/craft-tooltip";
17
- import { CraftToastHost, useCraftToast } from "./components/craft-toast";
18
- import { CraftSkeleton } from "./components/craft-skeleton";
19
- import { CraftEmptyState } from "./components/craft-empty-state";
20
- import { CraftPopover } from "./components/craft-popover";
21
- import { CraftDropdownMenu } from "./components/craft-dropdown-menu";
22
- import { CraftCommandPalette } from "./components/craft-command-palette";
23
- import { CraftLink } from "./components/craft-link";
24
- import { CraftStatCard } from "./components/craft-stat-card";
25
- import { CraftDatePicker } from "./components/craft-date-picker";
26
- import { CraftIcon, CraftIconProvider } from "./components/craft-icon";
27
- import { CraftNumberInput } from "./components/craft-number-input";
28
- import { CraftCurrencyInput } from "./components/craft-currency-input";
29
- import { CraftForm } from "./components/craft-form";
30
- import { CraftFormBuilder } from "./components/craft-form-builder";
31
- import { CraftFormField } from "./components/craft-form-field";
32
- import { CraftSubmitButton } from "./components/craft-submit-button";
33
- import { CraftConfirmDialog } from "./components/craft-confirm-dialog";
34
- import { CraftCreateEditDrawer } from "./components/craft-create-edit-drawer";
35
- import { CraftFilterBar } from "./components/craft-filter-bar";
36
- import { CraftTableToolbar } from "./components/craft-table-toolbar";
37
- import { CraftDataTable } from "./components/craft-data-table";
38
- import { CraftPagination } from "./components/craft-pagination";
39
- import { AppShell } from "./components/layout/app-shell";
40
- import { AppTemplate } from "./components/layout/app-template";
41
- import { layoutConfigSchema } from "./components/layout/layout-config";
42
- import { Sidebar } from "./components/layout/sidebar";
43
- import { TopNav } from "./components/layout/top-nav";
44
- import { PageHeader } from "./components/layout/page-header";
45
- import { Breadcrumbs } from "./components/layout/breadcrumbs";
46
- import { AuthLayout } from "./components/layout/auth-layout";
47
- import { Container } from "./components/layout/container";
48
- import { Grid } from "./components/layout/grid";
49
- import { ThemeSwitcher } from "./components/theme-switcher";
50
- import { ThemeProvider, useTheme } from "./theme/theme-context";
1
+ // src/utils/cn.ts
2
+ function cn(...values) {
3
+ return values.filter(Boolean).join(" ");
4
+ }
5
+
6
+ // src/components/craft-button.tsx
7
+ import { jsx } from "react/jsx-runtime";
8
+ var sizeClasses = {
9
+ sm: "h-9 px-4 text-xs",
10
+ md: "h-11 px-6 text-sm",
11
+ lg: "h-13 px-8 text-base"
12
+ };
13
+ var variantClasses = {
14
+ solid: "bg-gradient-to-br from-[rgb(var(--nc-accent-1))] via-[rgb(var(--nc-accent-2))] to-[rgb(var(--nc-accent-3))] text-white shadow-[0_12px_30px_rgb(var(--nc-accent-1)/0.45)] hover:shadow-[0_16px_36px_rgb(var(--nc-accent-1)/0.6)] hover:scale-[1.02] active:scale-[0.98]",
15
+ ghost: "bg-[color:rgb(var(--nc-surface)/0.12)] text-[rgb(var(--nc-fg))] hover:bg-[color:rgb(var(--nc-surface)/0.18)] backdrop-blur-sm border border-[rgb(var(--nc-border)/0.35)] hover:border-[color:rgb(var(--nc-border)/0.5)]",
16
+ outline: "bg-transparent text-[color:rgb(var(--nc-accent-1))] border-2 border-[color:rgb(var(--nc-accent-1)/0.5)] hover:border-[color:rgb(var(--nc-accent-1))] hover:bg-[color:rgb(var(--nc-accent-1)/0.1)]",
17
+ gradient: "bg-gradient-to-r from-[rgb(var(--nc-accent-1))] via-[rgb(var(--nc-accent-2))] to-[rgb(var(--nc-accent-3))] text-white shadow-[0_12px_30px_rgb(var(--nc-accent-2)/0.45)] hover:shadow-[0_16px_36px_rgb(var(--nc-accent-2)/0.6)] hover:scale-[1.02] active:scale-[0.98]"
18
+ };
19
+ function CraftButton({
20
+ className,
21
+ variant = "solid",
22
+ size = "md",
23
+ glow = true,
24
+ tone,
25
+ disabled,
26
+ ...props
27
+ }) {
28
+ return /* @__PURE__ */ jsx(
29
+ "button",
30
+ {
31
+ className: cn(
32
+ "relative inline-flex items-center justify-center gap-2 rounded-xl font-semibold tracking-wide transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[rgb(var(--nc-accent-1)/0.6)] focus-visible:ring-offset-2 focus-visible:ring-offset-slate-900 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100",
33
+ sizeClasses[size],
34
+ variantClasses[variant],
35
+ glow && (variant === "solid" || variant === "gradient") ? "before:absolute before:-inset-1 before:rounded-xl before:bg-linear-to-r before:from-[rgb(var(--nc-accent-1)/0.2)] before:via-[rgb(var(--nc-accent-2)/0.2)] before:to-[rgb(var(--nc-accent-3)/0.2)] before:blur-xl before:-z-10 before:opacity-0 hover:before:opacity-100 before:transition-opacity" : "",
36
+ className
37
+ ),
38
+ "data-nc-theme": tone,
39
+ disabled,
40
+ ...props
41
+ }
42
+ );
43
+ }
44
+
45
+ // src/components/glass-card.tsx
46
+ import { jsx as jsx2 } from "react/jsx-runtime";
47
+ var intensityClasses = {
48
+ subtle: "backdrop-blur-md bg-opacity-50",
49
+ medium: "backdrop-blur-xl bg-opacity-70",
50
+ strong: "backdrop-blur-2xl bg-opacity-90"
51
+ };
52
+ function GlassCard({
53
+ className,
54
+ tone,
55
+ intensity = "medium",
56
+ bordered = true,
57
+ children,
58
+ ...props
59
+ }) {
60
+ return /* @__PURE__ */ jsx2(
61
+ "div",
62
+ {
63
+ className: cn(
64
+ "relative overflow-hidden rounded-3xl p-6 text-[rgb(var(--nc-fg))]",
65
+ "shadow-[0_8px_32px_rgba(0,0,0,0.3)]",
66
+ "transition-all duration-300",
67
+ "hover:shadow-[0_8px_40px_rgba(0,0,0,0.4)]",
68
+ intensityClasses[intensity],
69
+ "bg-linear-to-br from-[rgb(var(--nc-accent-1)/0.15)] via-[rgb(var(--nc-accent-2)/0.10)] to-[rgb(var(--nc-accent-3)/0.15)]",
70
+ "border-[rgb(var(--nc-accent-1)/0.3)]",
71
+ bordered ? "border-2" : "border-0",
72
+ "before:absolute before:inset-0 before:bg-linear-to-br before:from-white/10 before:to-transparent before:opacity-0 hover:before:opacity-100 before:transition-opacity before:duration-300",
73
+ className
74
+ ),
75
+ "data-nc-theme": tone,
76
+ ...props,
77
+ children: /* @__PURE__ */ jsx2("div", { className: "relative z-10", children })
78
+ }
79
+ );
80
+ }
81
+
82
+ // src/components/craft-input.tsx
83
+ import * as React from "react";
84
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
85
+ var inputSizeClasses = {
86
+ sm: "h-10 px-4 text-sm",
87
+ md: "h-12 px-5 text-base",
88
+ lg: "h-14 px-6 text-lg"
89
+ };
90
+ var CraftInput = React.forwardRef(
91
+ ({ className, tone, inputSize = "md", glow = true, icon, ...props }, ref) => {
92
+ return /* @__PURE__ */ jsxs("div", { className: "relative w-full", "data-nc-theme": tone, children: [
93
+ icon && /* @__PURE__ */ jsx3("div", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]", children: icon }),
94
+ /* @__PURE__ */ jsx3(
95
+ "input",
96
+ {
97
+ ref,
98
+ className: cn(
99
+ "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
100
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
101
+ "focus:outline-none focus:ring-4",
102
+ "transition-all duration-300",
103
+ "disabled:opacity-50 disabled:cursor-not-allowed",
104
+ inputSizeClasses[inputSize],
105
+ "border-[rgb(var(--nc-border)/0.35)]",
106
+ "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
107
+ "placeholder:text-[rgb(var(--nc-fg-soft))]",
108
+ glow ? "focus:shadow-[0_0_30px_-5px_var(--glow-color)]" : "",
109
+ icon ? "pl-12" : "",
110
+ className
111
+ ),
112
+ style: {
113
+ "--glow-color": "rgb(var(--nc-accent-1) / 0.5)"
114
+ },
115
+ ...props
116
+ }
117
+ )
118
+ ] });
119
+ }
120
+ );
121
+ CraftInput.displayName = "CraftInput";
122
+
123
+ // src/components/craft-textarea.tsx
124
+ import * as React2 from "react";
125
+ import { jsx as jsx4 } from "react/jsx-runtime";
126
+ var CraftTextarea = React2.forwardRef(
127
+ ({ className, tone, rows = 4, ...props }, ref) => {
128
+ return /* @__PURE__ */ jsx4("div", { className: "relative w-full", "data-nc-theme": tone, children: /* @__PURE__ */ jsx4(
129
+ "textarea",
130
+ {
131
+ ref,
132
+ rows,
133
+ className: cn(
134
+ "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
135
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
136
+ "focus:outline-none focus:ring-4",
137
+ "transition-all duration-300",
138
+ "disabled:opacity-50 disabled:cursor-not-allowed",
139
+ "border-[rgb(var(--nc-border)/0.35)]",
140
+ "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
141
+ "placeholder:text-[rgb(var(--nc-fg-soft))]",
142
+ "px-5 py-3 text-base",
143
+ className
144
+ ),
145
+ style: {
146
+ "--glow-color": "rgb(var(--nc-accent-1) / 0.5)"
147
+ },
148
+ ...props
149
+ }
150
+ ) });
151
+ }
152
+ );
153
+ CraftTextarea.displayName = "CraftTextarea";
154
+
155
+ // src/components/craft-select.tsx
156
+ import * as React3 from "react";
157
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
158
+ var CraftSelect = React3.forwardRef(
159
+ ({ className, tone, children, ...props }, ref) => {
160
+ return /* @__PURE__ */ jsxs2("div", { className: "relative w-full", "data-nc-theme": tone, children: [
161
+ /* @__PURE__ */ jsx5(
162
+ "select",
163
+ {
164
+ ref,
165
+ className: cn(
166
+ "w-full appearance-none rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
167
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
168
+ "focus:outline-none focus:ring-4",
169
+ "transition-all duration-300",
170
+ "disabled:opacity-50 disabled:cursor-not-allowed",
171
+ "border-[rgb(var(--nc-border)/0.35)]",
172
+ "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
173
+ "px-5 py-3 pr-10 text-base",
174
+ className
175
+ ),
176
+ ...props,
177
+ children
178
+ }
179
+ ),
180
+ /* @__PURE__ */ jsx5(
181
+ "svg",
182
+ {
183
+ className: "pointer-events-none absolute right-4 top-1/2 h-4 w-4 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]",
184
+ viewBox: "0 0 20 20",
185
+ fill: "currentColor",
186
+ "aria-hidden": "true",
187
+ children: /* @__PURE__ */ jsx5(
188
+ "path",
189
+ {
190
+ fillRule: "evenodd",
191
+ d: "M5.23 7.21a.75.75 0 011.06.02L10 10.94l3.71-3.7a.75.75 0 111.06 1.06l-4.24 4.24a.75.75 0 01-1.06 0L5.21 8.29a.75.75 0 01.02-1.08z",
192
+ clipRule: "evenodd"
193
+ }
194
+ )
195
+ }
196
+ )
197
+ ] });
198
+ }
199
+ );
200
+ CraftSelect.displayName = "CraftSelect";
201
+
202
+ // src/components/craft-checkbox.tsx
203
+ import * as React4 from "react";
204
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
205
+ var CraftCheckbox = React4.forwardRef(
206
+ ({ className, tone, label, description, ...props }, ref) => {
207
+ return /* @__PURE__ */ jsxs3(
208
+ "label",
209
+ {
210
+ className: cn(
211
+ "flex items-start gap-3 text-sm text-[rgb(var(--nc-fg))]",
212
+ props.disabled ? "opacity-60" : "cursor-pointer",
213
+ className
214
+ ),
215
+ "data-nc-theme": tone,
216
+ children: [
217
+ /* @__PURE__ */ jsxs3("span", { className: "relative mt-0.5", children: [
218
+ /* @__PURE__ */ jsx6(
219
+ "input",
220
+ {
221
+ ref,
222
+ type: "checkbox",
223
+ className: "peer sr-only",
224
+ ...props
225
+ }
226
+ ),
227
+ /* @__PURE__ */ jsx6(
228
+ "span",
229
+ {
230
+ className: cn(
231
+ "flex h-5 w-5 items-center justify-center rounded-md border-2",
232
+ "border-[rgb(var(--nc-border)/0.45)] bg-[rgb(var(--nc-surface)/0.08)]",
233
+ "transition-all duration-200",
234
+ "peer-checked:border-[rgb(var(--nc-accent-1))] peer-checked:bg-[rgb(var(--nc-accent-1)/0.25)]",
235
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-[rgb(var(--nc-accent-1)/0.5)]"
236
+ ),
237
+ children: /* @__PURE__ */ jsx6(
238
+ "svg",
239
+ {
240
+ className: "h-3 w-3 text-[rgb(var(--nc-fg))] opacity-0 transition-opacity peer-checked:opacity-100",
241
+ viewBox: "0 0 20 20",
242
+ fill: "currentColor",
243
+ "aria-hidden": "true",
244
+ children: /* @__PURE__ */ jsx6(
245
+ "path",
246
+ {
247
+ fillRule: "evenodd",
248
+ d: "M16.704 5.29a1 1 0 010 1.415l-7.2 7.2a1 1 0 01-1.415 0l-3.2-3.2a1 1 0 111.415-1.415l2.492 2.493 6.493-6.493a1 1 0 011.415 0z",
249
+ clipRule: "evenodd"
250
+ }
251
+ )
252
+ }
253
+ )
254
+ }
255
+ )
256
+ ] }),
257
+ /* @__PURE__ */ jsxs3("span", { className: "space-y-1", children: [
258
+ label && /* @__PURE__ */ jsx6("span", { className: "block font-medium text-[rgb(var(--nc-fg))]", children: label }),
259
+ description && /* @__PURE__ */ jsx6("span", { className: "block text-xs text-[rgb(var(--nc-fg-muted))]", children: description })
260
+ ] })
261
+ ]
262
+ }
263
+ );
264
+ }
265
+ );
266
+ CraftCheckbox.displayName = "CraftCheckbox";
267
+
268
+ // src/components/craft-switch.tsx
269
+ import * as React5 from "react";
270
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
271
+ var CraftSwitch = React5.forwardRef(
272
+ ({ className, tone, label, ...props }, ref) => {
273
+ return /* @__PURE__ */ jsxs4(
274
+ "label",
275
+ {
276
+ className: cn(
277
+ "inline-flex items-center gap-3 text-sm text-[rgb(var(--nc-fg))]",
278
+ props.disabled ? "opacity-60" : "cursor-pointer",
279
+ className
280
+ ),
281
+ "data-nc-theme": tone,
282
+ children: [
283
+ /* @__PURE__ */ jsx7("input", { ref, type: "checkbox", className: "peer sr-only", ...props }),
284
+ /* @__PURE__ */ jsx7(
285
+ "span",
286
+ {
287
+ className: cn(
288
+ "relative h-6 w-11 rounded-full border-2 border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.08)]",
289
+ "transition-all duration-200",
290
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-[rgb(var(--nc-accent-1)/0.5)]",
291
+ "peer-checked:border-[rgb(var(--nc-accent-1)/0.6)] peer-checked:bg-[rgb(var(--nc-accent-1)/0.25)]"
292
+ ),
293
+ children: /* @__PURE__ */ jsx7(
294
+ "span",
295
+ {
296
+ className: cn(
297
+ "absolute left-0.5 top-0.5 h-4 w-4 rounded-full bg-[rgb(var(--nc-surface-muted)/0.9)]",
298
+ "transition-all duration-200",
299
+ "peer-checked:translate-x-5 peer-checked:bg-[rgb(var(--nc-surface-muted))]"
300
+ )
301
+ }
302
+ )
303
+ }
304
+ ),
305
+ label && /* @__PURE__ */ jsx7("span", { children: label })
306
+ ]
307
+ }
308
+ );
309
+ }
310
+ );
311
+ CraftSwitch.displayName = "CraftSwitch";
312
+
313
+ // src/components/craft-badge.tsx
314
+ import { jsx as jsx8 } from "react/jsx-runtime";
315
+ var variantClasses2 = {
316
+ solid: "bg-[color:rgb(var(--nc-accent-1))] text-white shadow-[0_10px_20px_rgb(var(--nc-accent-1)/0.35)]",
317
+ soft: "bg-[color:rgb(var(--nc-accent-1)/0.2)] text-[rgb(var(--nc-fg))]",
318
+ outline: "border border-[color:rgb(var(--nc-accent-1)/0.6)] text-[rgb(var(--nc-fg))]"
319
+ };
320
+ function CraftBadge({
321
+ className,
322
+ variant = "soft",
323
+ tone,
324
+ ...props
325
+ }) {
326
+ return /* @__PURE__ */ jsx8(
327
+ "span",
328
+ {
329
+ className: cn(
330
+ "inline-flex items-center rounded-full px-3 py-1 text-xs font-semibold uppercase tracking-wide",
331
+ variantClasses2[variant],
332
+ className
333
+ ),
334
+ "data-nc-theme": tone,
335
+ ...props
336
+ }
337
+ );
338
+ }
339
+
340
+ // src/components/craft-alert.tsx
341
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
342
+ var variantClasses3 = {
343
+ info: "border-[rgb(var(--nc-accent-1)/0.45)] bg-[rgb(var(--nc-accent-1)/0.12)]",
344
+ success: "border-[rgb(var(--nc-accent-2)/0.45)] bg-[rgb(var(--nc-accent-2)/0.12)]",
345
+ warning: "border-[rgb(var(--nc-accent-3)/0.45)] bg-[rgb(var(--nc-accent-3)/0.12)]",
346
+ error: "border-[rgb(var(--nc-accent-3)/0.65)] bg-[rgb(var(--nc-accent-3)/0.18)]"
347
+ };
348
+ function CraftAlert({
349
+ title,
350
+ description,
351
+ variant = "info",
352
+ icon,
353
+ actions,
354
+ tone,
355
+ className,
356
+ ...props
357
+ }) {
358
+ return /* @__PURE__ */ jsxs5(
359
+ "div",
360
+ {
361
+ className: cn(
362
+ "rounded-2xl border p-4 text-[rgb(var(--nc-fg))] backdrop-blur-xl",
363
+ variantClasses3[variant],
364
+ className
365
+ ),
366
+ "data-nc-theme": tone,
367
+ ...props,
368
+ children: [
369
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-3", children: [
370
+ icon && /* @__PURE__ */ jsx9("div", { className: "mt-1 text-[rgb(var(--nc-fg))]", children: icon }),
371
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-1", children: [
372
+ title && /* @__PURE__ */ jsx9("p", { className: "text-sm font-semibold", children: title }),
373
+ description && /* @__PURE__ */ jsx9("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description })
374
+ ] })
375
+ ] }),
376
+ actions && /* @__PURE__ */ jsx9("div", { className: "mt-3 flex flex-wrap gap-2", children: actions })
377
+ ]
378
+ }
379
+ );
380
+ }
381
+
382
+ // src/components/craft-error-state.tsx
383
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
384
+ function CraftErrorState({
385
+ title = "Something went wrong",
386
+ description = "Try again or check your connection.",
387
+ actionLabel = "Retry",
388
+ onAction,
389
+ action,
390
+ tone,
391
+ className,
392
+ ...props
393
+ }) {
394
+ return /* @__PURE__ */ jsxs6(
395
+ "div",
396
+ {
397
+ className: cn(
398
+ "rounded-3xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.12)] p-6 text-[rgb(var(--nc-fg))] shadow-[0_12px_30px_rgba(0,0,0,0.25)] backdrop-blur-xl",
399
+ className
400
+ ),
401
+ "data-nc-theme": tone,
402
+ ...props,
403
+ children: [
404
+ /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
405
+ /* @__PURE__ */ jsx10("h3", { className: "text-lg font-semibold", children: title }),
406
+ /* @__PURE__ */ jsx10("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description })
407
+ ] }),
408
+ /* @__PURE__ */ jsx10("div", { className: "mt-4", children: action != null ? action : onAction && /* @__PURE__ */ jsx10(CraftButton, { size: "sm", onClick: onAction, children: actionLabel }) })
409
+ ]
410
+ }
411
+ );
412
+ }
413
+
414
+ // src/components/craft-loading-state.tsx
415
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
416
+ var sizeClasses2 = {
417
+ sm: "h-4 w-4 border-2",
418
+ md: "h-6 w-6 border-2",
419
+ lg: "h-8 w-8 border-[3px]"
420
+ };
421
+ function CraftLoadingState({
422
+ label = "Loading...",
423
+ size = "md",
424
+ tone,
425
+ className,
426
+ ...props
427
+ }) {
428
+ return /* @__PURE__ */ jsxs7(
429
+ "div",
430
+ {
431
+ className: cn("flex items-center gap-3 text-[rgb(var(--nc-fg))]", className),
432
+ "data-nc-theme": tone,
433
+ ...props,
434
+ children: [
435
+ /* @__PURE__ */ jsx11(
436
+ "span",
437
+ {
438
+ className: cn(
439
+ "inline-block animate-spin rounded-full border-[rgb(var(--nc-accent-1)/0.25)] border-t-[rgb(var(--nc-accent-1))]",
440
+ sizeClasses2[size]
441
+ ),
442
+ "aria-hidden": "true"
443
+ }
444
+ ),
445
+ label && /* @__PURE__ */ jsx11("span", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: label })
446
+ ]
447
+ }
448
+ );
449
+ }
450
+
451
+ // src/components/craft-card.tsx
452
+ import { jsx as jsx12 } from "react/jsx-runtime";
453
+ var intensityClasses2 = {
454
+ subtle: "backdrop-blur-md bg-opacity-50",
455
+ medium: "backdrop-blur-xl bg-opacity-70",
456
+ strong: "backdrop-blur-2xl bg-opacity-90"
457
+ };
458
+ function CraftCard({
459
+ className,
460
+ tone,
461
+ elevated = true,
462
+ intensity = "medium",
463
+ bordered = true,
464
+ children,
465
+ ...props
466
+ }) {
467
+ return /* @__PURE__ */ jsx12(
468
+ "div",
469
+ {
470
+ className: cn(
471
+ "relative overflow-hidden rounded-3xl p-6 text-[rgb(var(--nc-fg))]",
472
+ intensityClasses2[intensity],
473
+ "bg-linear-to-br from-[rgb(var(--nc-accent-1)/0.15)] via-[rgb(var(--nc-accent-2)/0.10)] to-[rgb(var(--nc-accent-3)/0.15)]",
474
+ bordered ? "border-2 border-[rgb(var(--nc-accent-1)/0.3)]" : "border-0",
475
+ elevated ? "shadow-[0_8px_32px_rgba(0,0,0,0.3)] hover:shadow-[0_8px_40px_rgba(0,0,0,0.4)]" : "shadow-none",
476
+ "before:absolute before:inset-0 before:bg-linear-to-br before:from-white/10 before:to-transparent before:opacity-0 hover:before:opacity-100 before:transition-opacity before:duration-300",
477
+ "transition-all duration-300",
478
+ className
479
+ ),
480
+ "data-nc-theme": tone,
481
+ ...props,
482
+ children: /* @__PURE__ */ jsx12("div", { className: "relative z-10", children })
483
+ }
484
+ );
485
+ }
486
+
487
+ // src/components/craft-modal.tsx
488
+ import * as React6 from "react";
489
+ import { createPortal } from "react-dom";
490
+ import { Fragment, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
491
+ var FOCUSABLE_SELECTORS = [
492
+ "a[href]",
493
+ "button:not([disabled])",
494
+ "textarea:not([disabled])",
495
+ "input:not([disabled])",
496
+ "select:not([disabled])",
497
+ "[tabindex]:not([tabindex='-1'])"
498
+ ].join(",");
499
+ function useFocusTrap(active) {
500
+ const ref = React6.useRef(null);
501
+ React6.useEffect(() => {
502
+ if (!active || !ref.current) return;
503
+ const root = ref.current;
504
+ const getFocusable = () => Array.from(root.querySelectorAll(FOCUSABLE_SELECTORS));
505
+ const focusables = getFocusable();
506
+ if (focusables.length) {
507
+ focusables[0].focus();
508
+ } else {
509
+ root.focus();
510
+ }
511
+ const handleKeyDown = (event) => {
512
+ if (event.key !== "Tab") return;
513
+ const items = getFocusable();
514
+ if (!items.length) return;
515
+ const first = items[0];
516
+ const last = items[items.length - 1];
517
+ const activeEl = document.activeElement;
518
+ if (event.shiftKey && activeEl === first) {
519
+ event.preventDefault();
520
+ last.focus();
521
+ } else if (!event.shiftKey && activeEl === last) {
522
+ event.preventDefault();
523
+ first.focus();
524
+ }
525
+ };
526
+ root.addEventListener("keydown", handleKeyDown);
527
+ return () => root.removeEventListener("keydown", handleKeyDown);
528
+ }, [active]);
529
+ return ref;
530
+ }
531
+ function CraftModal({
532
+ open,
533
+ defaultOpen = false,
534
+ onOpenChange,
535
+ tone,
536
+ title,
537
+ description,
538
+ children,
539
+ trigger,
540
+ footer,
541
+ className
542
+ }) {
543
+ const [uncontrolledOpen, setUncontrolledOpen] = React6.useState(defaultOpen);
544
+ const isControlled = typeof open === "boolean";
545
+ const isOpen = isControlled ? open : uncontrolledOpen;
546
+ const setOpen = React6.useCallback(
547
+ (next) => {
548
+ if (!isControlled) {
549
+ setUncontrolledOpen(next);
550
+ }
551
+ onOpenChange == null ? void 0 : onOpenChange(next);
552
+ },
553
+ [isControlled, onOpenChange]
554
+ );
555
+ React6.useEffect(() => {
556
+ if (!isOpen) return;
557
+ const handleKey = (event) => {
558
+ if (event.key === "Escape") setOpen(false);
559
+ };
560
+ document.addEventListener("keydown", handleKey);
561
+ return () => document.removeEventListener("keydown", handleKey);
562
+ }, [isOpen, setOpen]);
563
+ const ref = useFocusTrap(isOpen);
564
+ const content = isOpen ? /* @__PURE__ */ jsxs8("div", { className: "fixed inset-0 z-50 flex items-center justify-center px-4 py-8", children: [
565
+ /* @__PURE__ */ jsx13(
566
+ "div",
567
+ {
568
+ className: "absolute inset-0 backdrop-blur-sm",
569
+ onClick: () => setOpen(false)
570
+ }
571
+ ),
572
+ /* @__PURE__ */ jsxs8(
573
+ "div",
574
+ {
575
+ ref,
576
+ tabIndex: -1,
577
+ className: cn(
578
+ "relative z-10 w-full max-w-7xl rounded-3xl border border-[rgb(var(--nc-border)/0.45)] p-6 text-[rgb(var(--nc-fg))] shadow-[0_20px_60px_rgba(0,0,0,0.45)] backdrop-blur-2xl",
579
+ "max-h-[calc(100vh-1rem)] overflow-y-auto",
580
+ className
581
+ ),
582
+ "data-nc-theme": tone,
583
+ children: [
584
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-start justify-between gap-4", children: [
585
+ /* @__PURE__ */ jsxs8("div", { className: "space-y-1", children: [
586
+ title && /* @__PURE__ */ jsx13("h3", { className: "text-2xl font-semibold", children: title }),
587
+ description && /* @__PURE__ */ jsx13("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: description })
588
+ ] }),
589
+ /* @__PURE__ */ jsx13(
590
+ "button",
591
+ {
592
+ className: "rounded-full border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] p-2 text-[rgb(var(--nc-fg-soft))] transition hover:text-[rgb(var(--nc-fg))]",
593
+ onClick: () => setOpen(false),
594
+ "aria-label": "Close",
595
+ children: /* @__PURE__ */ jsx13("svg", { viewBox: "0 0 20 20", className: "h-4 w-4", fill: "currentColor", children: /* @__PURE__ */ jsx13("path", { d: "M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" }) })
596
+ }
597
+ )
598
+ ] }),
599
+ /* @__PURE__ */ jsx13("div", { className: "mt-5 space-y-4", children }),
600
+ footer && /* @__PURE__ */ jsx13("div", { className: "mt-6", children: footer })
601
+ ]
602
+ }
603
+ )
604
+ ] }) : null;
605
+ return /* @__PURE__ */ jsxs8(Fragment, { children: [
606
+ trigger && /* @__PURE__ */ jsx13(
607
+ "span",
608
+ {
609
+ onClick: () => setOpen(true),
610
+ onKeyDown: (event) => {
611
+ if (event.key === "Enter" || event.key === " ") setOpen(true);
612
+ },
613
+ role: "button",
614
+ tabIndex: 0,
615
+ className: "inline-flex",
616
+ children: trigger
617
+ }
618
+ ),
619
+ typeof document !== "undefined" && content ? createPortal(content, document.body) : content
620
+ ] });
621
+ }
622
+
623
+ // src/components/craft-drawer.tsx
624
+ import * as React7 from "react";
625
+ import { createPortal as createPortal2 } from "react-dom";
626
+ import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
627
+ function CraftDrawer({
628
+ open,
629
+ defaultOpen = false,
630
+ onOpenChange,
631
+ tone,
632
+ side = "left",
633
+ title,
634
+ children,
635
+ trigger,
636
+ footer,
637
+ className
638
+ }) {
639
+ const [uncontrolledOpen, setUncontrolledOpen] = React7.useState(defaultOpen);
640
+ const isControlled = typeof open === "boolean";
641
+ const isOpen = isControlled ? open : uncontrolledOpen;
642
+ const setOpen = React7.useCallback(
643
+ (next) => {
644
+ if (!isControlled) setUncontrolledOpen(next);
645
+ onOpenChange == null ? void 0 : onOpenChange(next);
646
+ },
647
+ [isControlled, onOpenChange]
648
+ );
649
+ React7.useEffect(() => {
650
+ if (!isOpen) return;
651
+ const handleKey = (event) => {
652
+ if (event.key === "Escape") setOpen(false);
653
+ };
654
+ document.addEventListener("keydown", handleKey);
655
+ return () => document.removeEventListener("keydown", handleKey);
656
+ }, [isOpen, setOpen]);
657
+ const content = isOpen ? /* @__PURE__ */ jsxs9("div", { className: "fixed inset-0 z-50 overflow-hidden", children: [
658
+ /* @__PURE__ */ jsx14(
659
+ "div",
660
+ {
661
+ className: "absolute inset-0 backdrop-blur-sm",
662
+ onClick: () => setOpen(false)
663
+ }
664
+ ),
665
+ /* @__PURE__ */ jsxs9(
666
+ "div",
667
+ {
668
+ className: cn(
669
+ "absolute top-0 h-full w-full max-w-md border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] text-[rgb(var(--nc-fg))] shadow-[0_20px_60px_rgba(0,0,0,0.45)] backdrop-blur-2xl",
670
+ side === "right" ? "right-0" : "left-0",
671
+ className
672
+ ),
673
+ "data-nc-theme": tone,
674
+ children: [
675
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between border-b border-[rgb(var(--nc-border)/0.3)] p-6", children: [
676
+ title && /* @__PURE__ */ jsx14("h3", { className: "text-xl font-semibold", children: title }),
677
+ /* @__PURE__ */ jsx14(
678
+ "button",
679
+ {
680
+ className: "rounded-full border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] p-2 text-[rgb(var(--nc-fg-soft))] transition hover:text-[rgb(var(--nc-fg))]",
681
+ onClick: () => setOpen(false),
682
+ "aria-label": "Close",
683
+ children: /* @__PURE__ */ jsx14("svg", { viewBox: "0 0 20 20", className: "h-4 w-4", fill: "currentColor", children: /* @__PURE__ */ jsx14("path", { d: "M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" }) })
684
+ }
685
+ )
686
+ ] }),
687
+ /* @__PURE__ */ jsx14("div", { className: "p-6 space-y-4 overflow-y-auto h-[calc(100%-5.5rem)]", children }),
688
+ footer && /* @__PURE__ */ jsx14("div", { className: "border-t border-[rgb(var(--nc-border)/0.3)] p-6", children: footer })
689
+ ]
690
+ }
691
+ )
692
+ ] }) : null;
693
+ return /* @__PURE__ */ jsxs9(Fragment2, { children: [
694
+ trigger && /* @__PURE__ */ jsx14(
695
+ "span",
696
+ {
697
+ onClick: () => setOpen(true),
698
+ onKeyDown: (event) => {
699
+ if (event.key === "Enter" || event.key === " ") setOpen(true);
700
+ },
701
+ role: "button",
702
+ tabIndex: 0,
703
+ className: "inline-flex",
704
+ children: trigger
705
+ }
706
+ ),
707
+ typeof document !== "undefined" && content ? createPortal2(content, document.body) : content
708
+ ] });
709
+ }
710
+
711
+ // src/components/craft-tabs.tsx
712
+ import * as React8 from "react";
713
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
714
+ function CraftTabs({
715
+ value,
716
+ defaultValue,
717
+ onValueChange,
718
+ tone,
719
+ tabs,
720
+ panels,
721
+ className
722
+ }) {
723
+ var _a, _b;
724
+ const fallback = (_b = (_a = tabs[0]) == null ? void 0 : _a.value) != null ? _b : "";
725
+ const [uncontrolledValue, setUncontrolledValue] = React8.useState(
726
+ defaultValue != null ? defaultValue : fallback
727
+ );
728
+ const isControlled = value !== void 0;
729
+ const activeValue = isControlled ? value : uncontrolledValue;
730
+ const setValue = React8.useCallback(
731
+ (next) => {
732
+ if (!isControlled) setUncontrolledValue(next);
733
+ onValueChange == null ? void 0 : onValueChange(next);
734
+ },
735
+ [isControlled, onValueChange]
736
+ );
737
+ const onKeyDown = (event) => {
738
+ if (!tabs.length) return;
739
+ const currentIndex = tabs.findIndex((tab) => tab.value === activeValue);
740
+ if (event.key === "ArrowRight") {
741
+ event.preventDefault();
742
+ const next = tabs[(currentIndex + 1) % tabs.length];
743
+ setValue(next.value);
744
+ }
745
+ if (event.key === "ArrowLeft") {
746
+ event.preventDefault();
747
+ const next = tabs[(currentIndex - 1 + tabs.length) % tabs.length];
748
+ setValue(next.value);
749
+ }
750
+ };
751
+ return /* @__PURE__ */ jsxs10("div", { className: cn("space-y-4", className), "data-nc-theme": tone, children: [
752
+ /* @__PURE__ */ jsx15(
753
+ "div",
754
+ {
755
+ className: "inline-flex flex-wrap items-center gap-2 rounded-full border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] p-2",
756
+ role: "tablist",
757
+ onKeyDown,
758
+ children: tabs.map((tab) => /* @__PURE__ */ jsx15(
759
+ "button",
760
+ {
761
+ role: "tab",
762
+ "aria-selected": activeValue === tab.value,
763
+ onClick: () => setValue(tab.value),
764
+ className: cn(
765
+ "rounded-full px-4 py-2 text-sm font-semibold transition-all",
766
+ activeValue === tab.value ? "bg-[rgb(var(--nc-accent-1)/0.65)] text-white shadow-[0_7px_5px_rgb(var(--nc-accent-1)/0.35)]" : "text-[rgb(var(--nc-fg-muted))] hover:text-[rgb(var(--nc-fg))]"
767
+ ),
768
+ children: tab.label
769
+ },
770
+ tab.value
771
+ ))
772
+ }
773
+ ),
774
+ /* @__PURE__ */ jsx15("div", { className: "rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] p-4 text-[rgb(var(--nc-fg))]", children: panels[activeValue] })
775
+ ] });
776
+ }
777
+
778
+ // src/components/craft-tooltip.tsx
779
+ import * as React9 from "react";
780
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
781
+ function CraftTooltip({ content, tone, children, side = "top" }) {
782
+ const [open, setOpen] = React9.useState(false);
783
+ return /* @__PURE__ */ jsxs11(
784
+ "span",
785
+ {
786
+ className: "relative inline-flex",
787
+ onMouseEnter: () => setOpen(true),
788
+ onMouseLeave: () => setOpen(false),
789
+ onFocus: () => setOpen(true),
790
+ onBlur: () => setOpen(false),
791
+ children: [
792
+ children,
793
+ /* @__PURE__ */ jsx16(
794
+ "span",
795
+ {
796
+ className: cn(
797
+ "pointer-events-none absolute z-20 whitespace-nowrap rounded-lg border border-white/10 bg-black/80 px-3 py-2 text-xs text-white shadow-lg transition-all",
798
+ "backdrop-blur-xl",
799
+ open ? "opacity-100 translate-y-0" : "opacity-0 translate-y-1",
800
+ side === "top" && "bottom-full left-1/2 -translate-x-1/2 -translate-y-2",
801
+ side === "bottom" && "top-full left-1/2 -translate-x-1/2 translate-y-2",
802
+ side === "left" && "right-full top-1/2 -translate-y-1/2 -translate-x-2",
803
+ side === "right" && "left-full top-1/2 -translate-y-1/2 translate-x-2"
804
+ ),
805
+ "data-nc-theme": tone,
806
+ role: "tooltip",
807
+ children: content
808
+ }
809
+ )
810
+ ]
811
+ }
812
+ );
813
+ }
814
+
815
+ // src/components/craft-toast.tsx
816
+ import * as React10 from "react";
817
+ import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
818
+ var variantClasses4 = {
819
+ info: "border-[color:rgb(var(--nc-accent-1)/0.4)]",
820
+ success: "border-emerald-400/40",
821
+ warning: "border-amber-400/40",
822
+ error: "border-rose-400/40"
823
+ };
824
+ function useCraftToast() {
825
+ const [toasts, setToasts] = React10.useState([]);
826
+ const push = React10.useCallback((toast) => {
827
+ const id = `${Date.now()}-${Math.random().toString(16).slice(2)}`;
828
+ setToasts((prev) => [...prev, { ...toast, id }]);
829
+ return id;
830
+ }, []);
831
+ const remove = React10.useCallback((id) => {
832
+ setToasts((prev) => prev.filter((toast) => toast.id !== id));
833
+ }, []);
834
+ return { toasts, push, remove };
835
+ }
836
+ function CraftToastHost({ toasts, onDismiss, tone }) {
837
+ return /* @__PURE__ */ jsx17(
838
+ "div",
839
+ {
840
+ className: "fixed right-6 top-6 z-50 flex w-full max-w-sm flex-col gap-3",
841
+ "data-nc-theme": tone,
842
+ children: toasts.map((toast) => {
843
+ var _a;
844
+ return /* @__PURE__ */ jsx17(
845
+ "div",
846
+ {
847
+ className: cn(
848
+ "rounded-2xl border bg-[rgb(var(--nc-surface)/0.12)] p-4 text-[rgb(var(--nc-fg))] shadow-[0_15px_35px_rgba(0,0,0,0.35)] backdrop-blur-xl",
849
+ variantClasses4[(_a = toast.variant) != null ? _a : "info"]
850
+ ),
851
+ children: /* @__PURE__ */ jsxs12("div", { className: "flex items-start justify-between gap-4", children: [
852
+ /* @__PURE__ */ jsxs12("div", { children: [
853
+ /* @__PURE__ */ jsx17("p", { className: "text-sm font-semibold", children: toast.title }),
854
+ toast.description && /* @__PURE__ */ jsx17("p", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: toast.description })
855
+ ] }),
856
+ /* @__PURE__ */ jsx17(
857
+ "button",
858
+ {
859
+ className: "text-[rgb(var(--nc-fg-soft))] hover:text-[rgb(var(--nc-fg))]",
860
+ onClick: () => onDismiss(toast.id),
861
+ children: "\u2715"
862
+ }
863
+ )
864
+ ] })
865
+ },
866
+ toast.id
867
+ );
868
+ })
869
+ }
870
+ );
871
+ }
872
+
873
+ // src/components/craft-skeleton.tsx
874
+ import { jsx as jsx18 } from "react/jsx-runtime";
875
+ function CraftSkeleton({ className, tone, ...props }) {
876
+ return /* @__PURE__ */ jsx18(
877
+ "div",
878
+ {
879
+ className: cn(
880
+ "relative overflow-hidden rounded-2xl bg-[rgb(var(--nc-surface)/0.12)]",
881
+ "after:absolute after:inset-0 after:-translate-x-full after:bg-linear-to-r after:from-transparent after:via-white/20 after:to-transparent",
882
+ "after:animate-[shimmer_1.6s_infinite]",
883
+ className
884
+ ),
885
+ "data-nc-theme": tone,
886
+ ...props
887
+ }
888
+ );
889
+ }
890
+
891
+ // src/components/craft-empty-state.tsx
892
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
893
+ function CraftEmptyState({
894
+ className,
895
+ tone,
896
+ title,
897
+ description,
898
+ icon,
899
+ action,
900
+ ...props
901
+ }) {
902
+ return /* @__PURE__ */ jsxs13(
903
+ "div",
904
+ {
905
+ className: cn(
906
+ "rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] p-8 text-center text-[rgb(var(--nc-fg))] backdrop-blur-xl",
907
+ "shadow-[0_18px_40px_rgba(0,0,0,0.25)]",
908
+ className
909
+ ),
910
+ "data-nc-theme": tone,
911
+ ...props,
912
+ children: [
913
+ icon && /* @__PURE__ */ jsx19("div", { className: "mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-2xl bg-[rgb(var(--nc-accent-1)/0.2)] text-[rgb(var(--nc-accent-1))]", children: icon }),
914
+ /* @__PURE__ */ jsx19("h3", { className: "text-xl font-semibold", children: title }),
915
+ description && /* @__PURE__ */ jsx19("p", { className: "mt-2 text-sm text-[rgb(var(--nc-fg-muted))]", children: description }),
916
+ action && /* @__PURE__ */ jsx19("div", { className: "mt-6 flex justify-center", children: action })
917
+ ]
918
+ }
919
+ );
920
+ }
921
+
922
+ // src/components/craft-popover.tsx
923
+ import * as React11 from "react";
924
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
925
+ var alignClasses = {
926
+ start: "left-0",
927
+ center: "left-1/2 -translate-x-1/2",
928
+ end: "right-0"
929
+ };
930
+ function CraftPopover({
931
+ open,
932
+ defaultOpen = false,
933
+ onOpenChange,
934
+ trigger,
935
+ content,
936
+ align = "start",
937
+ sideOffset = 10,
938
+ tone,
939
+ className,
940
+ contentClassName
941
+ }) {
942
+ const [uncontrolledOpen, setUncontrolledOpen] = React11.useState(defaultOpen);
943
+ const isControlled = typeof open === "boolean";
944
+ const isOpen = isControlled ? open : uncontrolledOpen;
945
+ const rootRef = React11.useRef(null);
946
+ const setOpen = React11.useCallback(
947
+ (next) => {
948
+ if (!isControlled) setUncontrolledOpen(next);
949
+ onOpenChange == null ? void 0 : onOpenChange(next);
950
+ },
951
+ [isControlled, onOpenChange]
952
+ );
953
+ React11.useEffect(() => {
954
+ if (!isOpen) return;
955
+ const handleClick = (event) => {
956
+ if (!rootRef.current) return;
957
+ if (!rootRef.current.contains(event.target)) setOpen(false);
958
+ };
959
+ const handleKey = (event) => {
960
+ if (event.key === "Escape") setOpen(false);
961
+ };
962
+ document.addEventListener("mousedown", handleClick);
963
+ document.addEventListener("keydown", handleKey);
964
+ return () => {
965
+ document.removeEventListener("mousedown", handleClick);
966
+ document.removeEventListener("keydown", handleKey);
967
+ };
968
+ }, [isOpen, setOpen]);
969
+ const triggerNode = React11.isValidElement(trigger) ? React11.cloneElement(trigger, {
970
+ onClick: (event) => {
971
+ const handler = trigger.props.onClick;
972
+ handler == null ? void 0 : handler(event);
973
+ if (!event.defaultPrevented) setOpen(!isOpen);
974
+ },
975
+ "aria-expanded": isOpen,
976
+ "aria-haspopup": "dialog"
977
+ }) : /* @__PURE__ */ jsx20(
978
+ "button",
979
+ {
980
+ type: "button",
981
+ onClick: () => setOpen(!isOpen),
982
+ className: "inline-flex",
983
+ "aria-expanded": isOpen,
984
+ "aria-haspopup": "dialog",
985
+ children: trigger
986
+ }
987
+ );
988
+ return /* @__PURE__ */ jsxs14("div", { className: cn("relative inline-flex", className), ref: rootRef, children: [
989
+ triggerNode,
990
+ isOpen && /* @__PURE__ */ jsx20(
991
+ "div",
992
+ {
993
+ className: cn(
994
+ "absolute z-40 w-max min-w-48 rounded-2xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.08)] p-3 text-[rgb(var(--nc-fg))] shadow-[0_18px_40px_rgba(0,0,0,0.35)] backdrop-blur-2xl",
995
+ alignClasses[align],
996
+ contentClassName
997
+ ),
998
+ style: { marginTop: sideOffset },
999
+ role: "dialog",
1000
+ "data-nc-theme": tone,
1001
+ children: content
1002
+ }
1003
+ )
1004
+ ] });
1005
+ }
1006
+
1007
+ // src/components/craft-dropdown-menu.tsx
1008
+ import * as React12 from "react";
1009
+ import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
1010
+ function CraftDropdownMenu({
1011
+ trigger,
1012
+ items = [],
1013
+ content,
1014
+ open,
1015
+ defaultOpen = false,
1016
+ onOpenChange,
1017
+ align = "end",
1018
+ tone,
1019
+ className,
1020
+ menuClassName
1021
+ }) {
1022
+ const [uncontrolledOpen, setUncontrolledOpen] = React12.useState(defaultOpen);
1023
+ const isControlled = typeof open === "boolean";
1024
+ const isOpen = isControlled ? open : uncontrolledOpen;
1025
+ const setOpen = React12.useCallback(
1026
+ (next) => {
1027
+ if (!isControlled) setUncontrolledOpen(next);
1028
+ onOpenChange == null ? void 0 : onOpenChange(next);
1029
+ },
1030
+ [isControlled, onOpenChange]
1031
+ );
1032
+ const menuContent = content != null ? content : items.length ? /* @__PURE__ */ jsx21("div", { className: cn("space-y-1", menuClassName), role: "menu", children: items.map((item, index) => {
1033
+ var _a;
1034
+ const key = (_a = item.id) != null ? _a : `${index}-${String(item.label)}`;
1035
+ const itemClasses = cn(
1036
+ "flex w-full items-start gap-3 rounded-xl px-3 py-2 text-left text-sm transition",
1037
+ item.disabled ? "cursor-not-allowed text-[rgb(var(--nc-fg-soft))] opacity-60" : "text-[rgb(var(--nc-fg))] hover:bg-[rgb(var(--nc-surface)/0.12)]"
1038
+ );
1039
+ const contentNode = /* @__PURE__ */ jsxs15(Fragment3, { children: [
1040
+ item.icon && /* @__PURE__ */ jsx21("span", { className: "mt-0.5", children: item.icon }),
1041
+ /* @__PURE__ */ jsxs15("span", { className: "flex-1", children: [
1042
+ /* @__PURE__ */ jsx21("span", { className: "block font-medium", children: item.label }),
1043
+ item.description && /* @__PURE__ */ jsx21("span", { className: "block text-xs text-[rgb(var(--nc-fg-muted))]", children: item.description })
1044
+ ] })
1045
+ ] });
1046
+ if (item.href) {
1047
+ return /* @__PURE__ */ jsx21(
1048
+ "a",
1049
+ {
1050
+ href: item.href,
1051
+ className: itemClasses,
1052
+ role: "menuitem",
1053
+ onClick: () => {
1054
+ var _a2;
1055
+ if (item.disabled) return;
1056
+ (_a2 = item.onSelect) == null ? void 0 : _a2.call(item);
1057
+ setOpen(false);
1058
+ },
1059
+ children: contentNode
1060
+ },
1061
+ key
1062
+ );
1063
+ }
1064
+ return /* @__PURE__ */ jsx21(
1065
+ "button",
1066
+ {
1067
+ type: "button",
1068
+ className: itemClasses,
1069
+ role: "menuitem",
1070
+ onClick: () => {
1071
+ var _a2;
1072
+ if (item.disabled) return;
1073
+ (_a2 = item.onSelect) == null ? void 0 : _a2.call(item);
1074
+ setOpen(false);
1075
+ },
1076
+ children: contentNode
1077
+ },
1078
+ key
1079
+ );
1080
+ }) }) : null;
1081
+ return /* @__PURE__ */ jsx21(
1082
+ CraftPopover,
1083
+ {
1084
+ trigger,
1085
+ content: menuContent,
1086
+ open: isOpen,
1087
+ onOpenChange: setOpen,
1088
+ align,
1089
+ tone,
1090
+ className
1091
+ }
1092
+ );
1093
+ }
1094
+
1095
+ // src/components/craft-command-palette.tsx
1096
+ import * as React13 from "react";
1097
+ import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
1098
+ function CraftCommandPalette({
1099
+ items,
1100
+ open,
1101
+ defaultOpen = false,
1102
+ onOpenChange,
1103
+ trigger,
1104
+ title = "Command Palette",
1105
+ placeholder = "Search commands...",
1106
+ emptyText = "No results found.",
1107
+ tone,
1108
+ className
1109
+ }) {
1110
+ const [uncontrolledOpen, setUncontrolledOpen] = React13.useState(defaultOpen);
1111
+ const isControlled = typeof open === "boolean";
1112
+ const isOpen = isControlled ? open : uncontrolledOpen;
1113
+ const [query, setQuery] = React13.useState("");
1114
+ const setOpen = React13.useCallback(
1115
+ (next) => {
1116
+ if (!isControlled) setUncontrolledOpen(next);
1117
+ onOpenChange == null ? void 0 : onOpenChange(next);
1118
+ },
1119
+ [isControlled, onOpenChange]
1120
+ );
1121
+ const filtered = React13.useMemo(() => {
1122
+ const q = query.trim().toLowerCase();
1123
+ if (!q) return items;
1124
+ return items.filter((item) => {
1125
+ var _a, _b;
1126
+ const haystack = [
1127
+ item.label,
1128
+ (_a = item.description) != null ? _a : "",
1129
+ ...(_b = item.keywords) != null ? _b : []
1130
+ ].join(" ").toLowerCase();
1131
+ return haystack.includes(q);
1132
+ });
1133
+ }, [items, query]);
1134
+ React13.useEffect(() => {
1135
+ if (!isOpen) setQuery("");
1136
+ }, [isOpen]);
1137
+ return /* @__PURE__ */ jsx22(
1138
+ CraftModal,
1139
+ {
1140
+ open: isOpen,
1141
+ onOpenChange: setOpen,
1142
+ trigger,
1143
+ title,
1144
+ tone,
1145
+ className: cn("max-w-xl", className),
1146
+ children: /* @__PURE__ */ jsxs16("div", { className: "space-y-4", children: [
1147
+ /* @__PURE__ */ jsx22(
1148
+ CraftInput,
1149
+ {
1150
+ type: "search",
1151
+ placeholder,
1152
+ value: query,
1153
+ onChange: (event) => setQuery(event.target.value)
1154
+ }
1155
+ ),
1156
+ /* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
1157
+ filtered.length === 0 && /* @__PURE__ */ jsx22("div", { className: "rounded-2xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.12)] p-4 text-sm text-[rgb(var(--nc-fg-muted))]", children: emptyText }),
1158
+ filtered.map((item) => /* @__PURE__ */ jsxs16(
1159
+ "button",
1160
+ {
1161
+ type: "button",
1162
+ disabled: item.disabled,
1163
+ onClick: () => {
1164
+ var _a;
1165
+ if (item.disabled) return;
1166
+ (_a = item.onSelect) == null ? void 0 : _a.call(item);
1167
+ setOpen(false);
1168
+ },
1169
+ className: cn(
1170
+ "flex w-full items-start gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.08)] px-4 py-3 text-left transition",
1171
+ item.disabled ? "cursor-not-allowed opacity-60" : "hover:bg-[rgb(var(--nc-surface)/0.16)]"
1172
+ ),
1173
+ children: [
1174
+ item.icon && /* @__PURE__ */ jsx22("span", { className: "mt-1", children: item.icon }),
1175
+ /* @__PURE__ */ jsxs16("span", { children: [
1176
+ /* @__PURE__ */ jsx22("span", { className: "block text-sm font-semibold", children: item.label }),
1177
+ item.description && /* @__PURE__ */ jsx22("span", { className: "block text-xs text-[rgb(var(--nc-fg-muted))]", children: item.description })
1178
+ ] })
1179
+ ]
1180
+ },
1181
+ item.id
1182
+ ))
1183
+ ] })
1184
+ ] })
1185
+ }
1186
+ );
1187
+ }
1188
+
1189
+ // src/components/craft-link.tsx
1190
+ import Link from "next/link";
1191
+ import { jsx as jsx23 } from "react/jsx-runtime";
1192
+ var variantClasses5 = {
1193
+ default: "text-[rgb(var(--nc-accent-1))] hover:text-[rgb(var(--nc-accent-1))]",
1194
+ muted: "text-[rgb(var(--nc-fg-muted))] hover:text-[rgb(var(--nc-fg))]",
1195
+ button: "inline-flex items-center rounded-xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.12)] px-4 py-2 text-sm font-semibold text-[rgb(var(--nc-fg))] transition hover:bg-[rgb(var(--nc-surface)/0.2)]",
1196
+ ghost: "inline-flex items-center rounded-xl px-4 py-2 text-sm font-semibold text-[rgb(var(--nc-fg))] transition hover:bg-[rgb(var(--nc-surface)/0.18)]"
1197
+ };
1198
+ function CraftLink({
1199
+ variant = "default",
1200
+ underline = false,
1201
+ tone,
1202
+ className,
1203
+ children,
1204
+ ...props
1205
+ }) {
1206
+ return /* @__PURE__ */ jsx23(
1207
+ Link,
1208
+ {
1209
+ className: cn(
1210
+ "transition-colors",
1211
+ variantClasses5[variant],
1212
+ underline && "underline underline-offset-4",
1213
+ className
1214
+ ),
1215
+ "data-nc-theme": tone,
1216
+ ...props,
1217
+ children
1218
+ }
1219
+ );
1220
+ }
1221
+
1222
+ // src/components/craft-stat-card.tsx
1223
+ import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1224
+ var trendClasses = {
1225
+ up: "text-emerald-300",
1226
+ down: "text-rose-300",
1227
+ neutral: "text-[rgb(var(--nc-fg-muted))]"
1228
+ };
1229
+ function CraftStatCard({
1230
+ label,
1231
+ value,
1232
+ delta,
1233
+ trend = "neutral",
1234
+ icon,
1235
+ footer,
1236
+ tone,
1237
+ className,
1238
+ ...props
1239
+ }) {
1240
+ return /* @__PURE__ */ jsxs17(
1241
+ CraftCard,
1242
+ {
1243
+ className: cn("space-y-3", className),
1244
+ tone,
1245
+ ...props,
1246
+ children: [
1247
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between", children: [
1248
+ /* @__PURE__ */ jsx24("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: label }),
1249
+ icon && /* @__PURE__ */ jsx24("div", { className: "text-[rgb(var(--nc-fg-soft))]", children: icon })
1250
+ ] }),
1251
+ /* @__PURE__ */ jsx24("p", { className: "text-3xl font-semibold", children: value }),
1252
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between text-xs", children: [
1253
+ delta && /* @__PURE__ */ jsx24("span", { className: trendClasses[trend], children: delta }),
1254
+ footer && /* @__PURE__ */ jsx24("span", { className: "text-[rgb(var(--nc-fg-muted))]", children: footer })
1255
+ ] })
1256
+ ]
1257
+ }
1258
+ );
1259
+ }
1260
+
1261
+ // src/components/craft-date-picker.tsx
1262
+ import * as React14 from "react";
1263
+ import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1264
+ var WEEK_DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
1265
+ function formatDate(date) {
1266
+ const year = date.getFullYear();
1267
+ const month = `${date.getMonth() + 1}`.padStart(2, "0");
1268
+ const day = `${date.getDate()}`.padStart(2, "0");
1269
+ return `${year}-${month}-${day}`;
1270
+ }
1271
+ function parseDate(value) {
1272
+ if (!value) return null;
1273
+ const [year, month, day] = value.split("-").map(Number);
1274
+ if (!year || !month || !day) return null;
1275
+ return new Date(year, month - 1, day);
1276
+ }
1277
+ function isSameDay(a, b) {
1278
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
1279
+ }
1280
+ function isOutsideRange(date, min, max) {
1281
+ const minDate = parseDate(min);
1282
+ const maxDate = parseDate(max);
1283
+ if (minDate && date < minDate) return true;
1284
+ if (maxDate && date > maxDate) return true;
1285
+ return false;
1286
+ }
1287
+ function CraftDatePicker({
1288
+ value,
1289
+ defaultValue,
1290
+ onChange,
1291
+ tone,
1292
+ min,
1293
+ max,
1294
+ placeholder = "Select date",
1295
+ className
1296
+ }) {
1297
+ const [open, setOpen] = React14.useState(false);
1298
+ const [uncontrolledValue, setUncontrolledValue] = React14.useState(defaultValue != null ? defaultValue : "");
1299
+ const isControlled = value !== void 0;
1300
+ const selectedValue = isControlled ? value != null ? value : "" : uncontrolledValue;
1301
+ const selectedDate = parseDate(selectedValue);
1302
+ const initialMonth = selectedDate != null ? selectedDate : /* @__PURE__ */ new Date();
1303
+ const [viewDate, setViewDate] = React14.useState(initialMonth);
1304
+ React14.useEffect(() => {
1305
+ if (selectedDate) setViewDate(selectedDate);
1306
+ }, [selectedDate]);
1307
+ const wrapperRef = React14.useRef(null);
1308
+ React14.useEffect(() => {
1309
+ if (!open) return;
1310
+ const handleClick = (event) => {
1311
+ var _a;
1312
+ if (!((_a = wrapperRef.current) == null ? void 0 : _a.contains(event.target))) {
1313
+ setOpen(false);
1314
+ }
1315
+ };
1316
+ const handleKey = (event) => {
1317
+ if (event.key === "Escape") setOpen(false);
1318
+ };
1319
+ document.addEventListener("mousedown", handleClick);
1320
+ document.addEventListener("keydown", handleKey);
1321
+ return () => {
1322
+ document.removeEventListener("mousedown", handleClick);
1323
+ document.removeEventListener("keydown", handleKey);
1324
+ };
1325
+ }, [open]);
1326
+ const setValue = React14.useCallback(
1327
+ (next) => {
1328
+ if (!isControlled) setUncontrolledValue(next);
1329
+ onChange == null ? void 0 : onChange(next);
1330
+ },
1331
+ [isControlled, onChange]
1332
+ );
1333
+ const monthStart = new Date(viewDate.getFullYear(), viewDate.getMonth(), 1);
1334
+ const monthEnd = new Date(viewDate.getFullYear(), viewDate.getMonth() + 1, 0);
1335
+ const startDay = monthStart.getDay();
1336
+ const daysInMonth = monthEnd.getDate();
1337
+ const cells = Array.from({ length: startDay + daysInMonth }, (_, i) => {
1338
+ const dayNumber = i - startDay + 1;
1339
+ if (dayNumber < 1) return null;
1340
+ return new Date(viewDate.getFullYear(), viewDate.getMonth(), dayNumber);
1341
+ });
1342
+ const handleDaySelect = (date) => {
1343
+ if (isOutsideRange(date, min, max)) return;
1344
+ const next = formatDate(date);
1345
+ setValue(next);
1346
+ setOpen(false);
1347
+ };
1348
+ const handleKeyDown = (event) => {
1349
+ if (!open) return;
1350
+ if (!selectedDate) return;
1351
+ const next = new Date(selectedDate);
1352
+ if (event.key === "ArrowRight") next.setDate(next.getDate() + 1);
1353
+ if (event.key === "ArrowLeft") next.setDate(next.getDate() - 1);
1354
+ if (event.key === "ArrowDown") next.setDate(next.getDate() + 7);
1355
+ if (event.key === "ArrowUp") next.setDate(next.getDate() - 7);
1356
+ if (event.key === "Enter") {
1357
+ event.preventDefault();
1358
+ handleDaySelect(selectedDate);
1359
+ return;
1360
+ }
1361
+ if (next.getTime() !== selectedDate.getTime()) {
1362
+ event.preventDefault();
1363
+ if (!isOutsideRange(next, min, max)) {
1364
+ setValue(formatDate(next));
1365
+ setViewDate(next);
1366
+ }
1367
+ }
1368
+ };
1369
+ return /* @__PURE__ */ jsxs18("div", { className: "relative w-full", "data-nc-theme": tone, ref: wrapperRef, children: [
1370
+ /* @__PURE__ */ jsxs18(
1371
+ "button",
1372
+ {
1373
+ type: "button",
1374
+ onClick: () => setOpen((prev) => !prev),
1375
+ className: cn(
1376
+ "flex w-full items-center justify-between rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] px-5 py-3 text-left text-base text-[rgb(var(--nc-fg))] backdrop-blur-xl",
1377
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
1378
+ "transition-all duration-300",
1379
+ "border-[rgb(var(--nc-border)/0.35)]",
1380
+ "focus:outline-none focus:ring-4 focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
1381
+ className
1382
+ ),
1383
+ children: [
1384
+ /* @__PURE__ */ jsx25("span", { className: selectedValue ? "text-[rgb(var(--nc-fg))]" : "text-[rgb(var(--nc-fg-soft))]", children: selectedValue || placeholder }),
1385
+ /* @__PURE__ */ jsx25("svg", { className: "h-4 w-4 text-[rgb(var(--nc-fg-soft))]", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx25("path", { d: "M6 2a1 1 0 011 1v1h6V3a1 1 0 112 0v1h1a2 2 0 012 2v10a2 2 0 01-2 2H4a2 2 0 01-2-2V6a2 2 0 012-2h1V3a1 1 0 011-1zm10 6H4v8h12V8z" }) })
1386
+ ]
1387
+ }
1388
+ ),
1389
+ open && /* @__PURE__ */ jsxs18(
1390
+ "div",
1391
+ {
1392
+ className: cn(
1393
+ "absolute left-0 top-full z-20 mt-3 w-full rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/1.52)] p-4 text-[rgb(var(--nc-fg))] shadow-[0_20px_60px_rgba(0,0,0,0.55)] backdrop-blur-10xl"
1394
+ ),
1395
+ onKeyDown: handleKeyDown,
1396
+ tabIndex: -1,
1397
+ children: [
1398
+ /* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between", children: [
1399
+ /* @__PURE__ */ jsx25(
1400
+ "button",
1401
+ {
1402
+ type: "button",
1403
+ className: "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-sm text-[rgb(var(--nc-fg))]",
1404
+ onClick: () => setViewDate(
1405
+ new Date(viewDate.getFullYear(), viewDate.getMonth() - 1, 1)
1406
+ ),
1407
+ children: "Prev"
1408
+ }
1409
+ ),
1410
+ /* @__PURE__ */ jsx25("div", { className: "text-sm font-semibold", children: viewDate.toLocaleString(void 0, { month: "long", year: "numeric" }) }),
1411
+ /* @__PURE__ */ jsx25(
1412
+ "button",
1413
+ {
1414
+ type: "button",
1415
+ className: "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-sm text-[rgb(var(--nc-fg))]",
1416
+ onClick: () => setViewDate(
1417
+ new Date(viewDate.getFullYear(), viewDate.getMonth() + 1, 1)
1418
+ ),
1419
+ children: "Next"
1420
+ }
1421
+ )
1422
+ ] }),
1423
+ /* @__PURE__ */ jsx25("div", { className: "mt-4 grid grid-cols-7 gap-2 text-xs text-[rgb(var(--nc-fg-muted))]", children: WEEK_DAYS.map((day) => /* @__PURE__ */ jsx25("div", { className: "text-center", children: day }, day)) }),
1424
+ /* @__PURE__ */ jsx25("div", { className: "mt-2 grid grid-cols-7 gap-2", children: cells.map((date, index) => {
1425
+ if (!date) return /* @__PURE__ */ jsx25("div", {}, `empty-${index}`);
1426
+ const disabled = isOutsideRange(date, min, max);
1427
+ const selected = selectedDate && isSameDay(date, selectedDate);
1428
+ return /* @__PURE__ */ jsx25(
1429
+ "button",
1430
+ {
1431
+ type: "button",
1432
+ onClick: () => handleDaySelect(date),
1433
+ disabled,
1434
+ className: cn(
1435
+ "rounded-lg py-2 text-sm transition-all",
1436
+ selected ? "bg-[rgb(var(--nc-accent-1)/0.3)] text-[rgb(var(--nc-fg))]" : "text-[rgb(var(--nc-fg-muted))] hover:bg-[rgb(var(--nc-surface)/0.12)]",
1437
+ disabled && "opacity-40 hover:bg-transparent"
1438
+ ),
1439
+ children: date.getDate()
1440
+ },
1441
+ date.toISOString()
1442
+ );
1443
+ }) })
1444
+ ]
1445
+ }
1446
+ )
1447
+ ] });
1448
+ }
1449
+
1450
+ // src/components/craft-icon.tsx
1451
+ import * as React15 from "react";
1452
+ import { jsx as jsx26 } from "react/jsx-runtime";
1453
+ var CraftIconContext = React15.createContext(null);
1454
+ function CraftIconProvider({ icons, children }) {
1455
+ return /* @__PURE__ */ jsx26(CraftIconContext.Provider, { value: icons, children });
1456
+ }
1457
+ function CraftIcon({
1458
+ name,
1459
+ className,
1460
+ "aria-label": ariaLabel,
1461
+ icons,
1462
+ useLucide = true
1463
+ }) {
1464
+ const contextRegistry = React15.useContext(CraftIconContext);
1465
+ const registry = icons != null ? icons : contextRegistry;
1466
+ const icon = registry == null ? void 0 : registry[name];
1467
+ const [LucideIcon, setLucideIcon] = React15.useState(
1468
+ null
1469
+ );
1470
+ React15.useEffect(() => {
1471
+ if (!useLucide || icon || LucideIcon) return;
1472
+ let mounted = true;
1473
+ (async () => {
1474
+ try {
1475
+ const mod = await Function(
1476
+ "return import('lucide-react/dynamic')"
1477
+ )();
1478
+ if (mounted) {
1479
+ setLucideIcon(() => mod.DynamicIcon);
1480
+ }
1481
+ } catch {
1482
+ if (mounted) setLucideIcon(null);
1483
+ }
1484
+ })();
1485
+ return () => {
1486
+ mounted = false;
1487
+ };
1488
+ }, [LucideIcon, icon, useLucide]);
1489
+ if (!icon) {
1490
+ if (!useLucide) return null;
1491
+ if (!LucideIcon) return null;
1492
+ return /* @__PURE__ */ jsx26(
1493
+ LucideIcon,
1494
+ {
1495
+ name,
1496
+ className,
1497
+ "aria-hidden": ariaLabel ? void 0 : true,
1498
+ "aria-label": ariaLabel
1499
+ }
1500
+ );
1501
+ }
1502
+ if (React15.isValidElement(icon)) {
1503
+ return React15.cloneElement(icon, {
1504
+ className: cn(icon.props.className, className),
1505
+ "aria-hidden": ariaLabel ? void 0 : true,
1506
+ "aria-label": ariaLabel
1507
+ });
1508
+ }
1509
+ return /* @__PURE__ */ jsx26("span", { className, "aria-label": ariaLabel, children: icon });
1510
+ }
1511
+
1512
+ // src/components/craft-number-input.tsx
1513
+ import * as React16 from "react";
1514
+ import { jsx as jsx27 } from "react/jsx-runtime";
1515
+ var CraftNumberInput = React16.forwardRef(({ className, tone, ...props }, ref) => {
1516
+ return /* @__PURE__ */ jsx27("div", { className: "relative w-full", "data-nc-theme": tone, children: /* @__PURE__ */ jsx27(
1517
+ "input",
1518
+ {
1519
+ ref,
1520
+ type: "number",
1521
+ className: cn(
1522
+ "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
1523
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
1524
+ "focus:outline-none focus:ring-4",
1525
+ "transition-all duration-300",
1526
+ "disabled:opacity-50 disabled:cursor-not-allowed",
1527
+ "border-[rgb(var(--nc-border)/0.35)]",
1528
+ "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
1529
+ "px-5 py-3 text-base",
1530
+ className
1531
+ ),
1532
+ ...props
1533
+ }
1534
+ ) });
1535
+ });
1536
+ CraftNumberInput.displayName = "CraftNumberInput";
1537
+
1538
+ // src/components/craft-currency-input.tsx
1539
+ import * as React17 from "react";
1540
+ import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
1541
+ var CraftCurrencyInput = React17.forwardRef(({ className, tone, currencySymbol = "$", ...props }, ref) => {
1542
+ return /* @__PURE__ */ jsxs19("div", { className: "relative w-full", "data-nc-theme": tone, children: [
1543
+ /* @__PURE__ */ jsx28("span", { className: "pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]", children: currencySymbol }),
1544
+ /* @__PURE__ */ jsx28(
1545
+ "input",
1546
+ {
1547
+ ref,
1548
+ type: "text",
1549
+ inputMode: "decimal",
1550
+ className: cn(
1551
+ "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
1552
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
1553
+ "focus:outline-none focus:ring-4",
1554
+ "transition-all duration-300",
1555
+ "disabled:opacity-50 disabled:cursor-not-allowed",
1556
+ "border-[rgb(var(--nc-border)/0.35)]",
1557
+ "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
1558
+ "placeholder:text-[rgb(var(--nc-fg-soft))]",
1559
+ "px-5 py-3 pl-9 text-base",
1560
+ className
1561
+ ),
1562
+ ...props
1563
+ }
1564
+ )
1565
+ ] });
1566
+ });
1567
+ CraftCurrencyInput.displayName = "CraftCurrencyInput";
1568
+
1569
+ // src/components/craft-form.tsx
1570
+ import * as React18 from "react";
1571
+ import { FormProvider } from "react-hook-form";
1572
+
1573
+ // src/components/craft-submit-button.tsx
1574
+ import { useFormContext } from "react-hook-form";
1575
+ import { jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
1576
+ function CraftSubmitButton({
1577
+ className,
1578
+ tone,
1579
+ loading,
1580
+ loadingLabel = "Submitting...",
1581
+ disableWhenInvalid = true,
1582
+ disabled,
1583
+ children,
1584
+ ...props
1585
+ }) {
1586
+ var _a, _b, _c, _d;
1587
+ const form = useFormContext();
1588
+ const isSubmitting = (_b = loading != null ? loading : (_a = form == null ? void 0 : form.formState) == null ? void 0 : _a.isSubmitting) != null ? _b : false;
1589
+ const isValid = (_d = (_c = form == null ? void 0 : form.formState) == null ? void 0 : _c.isValid) != null ? _d : true;
1590
+ const isDisabled = disabled || isSubmitting || disableWhenInvalid && !isValid;
1591
+ return /* @__PURE__ */ jsxs20(
1592
+ "button",
1593
+ {
1594
+ type: "submit",
1595
+ className: cn(
1596
+ "relative inline-flex items-center justify-center gap-2 rounded-xl px-6 py-2 text-sm font-semibold",
1597
+ "bg-linear-to-br from-[rgb(var(--nc-accent-1))] via-[rgb(var(--nc-accent-2))] to-[rgb(var(--nc-accent-3))]",
1598
+ "text-white shadow-[0_12px_30px_rgb(var(--nc-accent-1)/0.35)]",
1599
+ "transition-all duration-200",
1600
+ "hover:shadow-[0_16px_36px_rgb(var(--nc-accent-1)/0.5)] hover:scale-[1.02] active:scale-[0.98]",
1601
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[rgb(var(--nc-accent-1)/0.6)]",
1602
+ "disabled:opacity-60 disabled:cursor-not-allowed disabled:hover:scale-100",
1603
+ className
1604
+ ),
1605
+ "data-nc-theme": tone,
1606
+ disabled: isDisabled,
1607
+ ...props,
1608
+ children: [
1609
+ isSubmitting && /* @__PURE__ */ jsx29("span", { className: "inline-flex h-4 w-4 animate-spin rounded-full border-2 border-white/60 border-t-white" }),
1610
+ /* @__PURE__ */ jsx29("span", { children: isSubmitting ? loadingLabel : children })
1611
+ ]
1612
+ }
1613
+ );
1614
+ }
1615
+
1616
+ // src/components/craft-form.tsx
1617
+ import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
1618
+ function CraftForm({
1619
+ form,
1620
+ onSubmit,
1621
+ open,
1622
+ defaultOpen = false,
1623
+ onOpenChange,
1624
+ trigger,
1625
+ title,
1626
+ description,
1627
+ submitLabel = "Save",
1628
+ cancelLabel = "Cancel",
1629
+ tone,
1630
+ className,
1631
+ children,
1632
+ footer,
1633
+ disableSubmitWhenInvalid = true,
1634
+ closeOnSubmit = true,
1635
+ formClassName
1636
+ }) {
1637
+ const [uncontrolledOpen, setUncontrolledOpen] = React18.useState(defaultOpen);
1638
+ const isControlled = typeof open === "boolean";
1639
+ const isOpen = isControlled ? open : uncontrolledOpen;
1640
+ const setOpen = React18.useCallback(
1641
+ (next) => {
1642
+ if (!isControlled) setUncontrolledOpen(next);
1643
+ onOpenChange == null ? void 0 : onOpenChange(next);
1644
+ },
1645
+ [isControlled, onOpenChange]
1646
+ );
1647
+ const formId = React18.useId();
1648
+ const handleSubmit = form.handleSubmit(async (values) => {
1649
+ await onSubmit(values);
1650
+ if (closeOnSubmit) setOpen(false);
1651
+ });
1652
+ const footerContent = footer != null ? footer : /* @__PURE__ */ jsxs21("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
1653
+ /* @__PURE__ */ jsx30(CraftButton, { type: "button", variant: "ghost", onClick: () => setOpen(false), children: cancelLabel }),
1654
+ /* @__PURE__ */ jsx30(
1655
+ CraftSubmitButton,
1656
+ {
1657
+ form: formId,
1658
+ disableWhenInvalid: disableSubmitWhenInvalid,
1659
+ children: submitLabel
1660
+ }
1661
+ )
1662
+ ] });
1663
+ return /* @__PURE__ */ jsx30(FormProvider, { ...form, children: /* @__PURE__ */ jsx30(
1664
+ CraftModal,
1665
+ {
1666
+ open: isOpen,
1667
+ onOpenChange: setOpen,
1668
+ trigger,
1669
+ title,
1670
+ description,
1671
+ tone,
1672
+ className,
1673
+ footer: footerContent,
1674
+ children: /* @__PURE__ */ jsx30(
1675
+ "form",
1676
+ {
1677
+ id: formId,
1678
+ onSubmit: handleSubmit,
1679
+ className: cn("space-y-5", formClassName),
1680
+ children
1681
+ }
1682
+ )
1683
+ }
1684
+ ) });
1685
+ }
1686
+
1687
+ // src/components/craft-form-builder.tsx
1688
+ import * as React19 from "react";
1689
+ import {
1690
+ FormProvider as FormProvider2,
1691
+ useForm
1692
+ } from "react-hook-form";
1693
+
1694
+ // src/components/craft-form-field.tsx
1695
+ import {
1696
+ Controller,
1697
+ useFormContext as useFormContext2
1698
+ } from "react-hook-form";
1699
+ import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
1700
+ function getFieldError(errors, name) {
1701
+ if (!errors || typeof errors !== "object") return void 0;
1702
+ const segments = name.split(".");
1703
+ let current = errors;
1704
+ for (const segment of segments) {
1705
+ if (!current || typeof current !== "object") return void 0;
1706
+ current = current[segment];
1707
+ }
1708
+ return current;
1709
+ }
1710
+ var baseInputClass = "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)] focus:outline-none focus:ring-4 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed border-[rgb(var(--nc-border)/0.35)] focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)] px-5 py-3 text-base placeholder:text-[rgb(var(--nc-fg-soft))]";
1711
+ function CraftFormField({
1712
+ name,
1713
+ label,
1714
+ description,
1715
+ type = "text",
1716
+ options = [],
1717
+ placeholder,
1718
+ tone,
1719
+ className,
1720
+ inputClassName,
1721
+ labelClassName,
1722
+ descriptionClassName,
1723
+ rules,
1724
+ disabled,
1725
+ fieldProps
1726
+ }) {
1727
+ const { register, control, formState } = useFormContext2();
1728
+ const error = getFieldError(formState.errors, name);
1729
+ const errorMessage = typeof (error == null ? void 0 : error.message) === "string" ? error.message : void 0;
1730
+ if (type === "hidden") {
1731
+ return /* @__PURE__ */ jsx31("input", { type: "hidden", ...register(name, rules) });
1732
+ }
1733
+ const labelNode = label ? /* @__PURE__ */ jsx31(
1734
+ "label",
1735
+ {
1736
+ htmlFor: name,
1737
+ className: cn(
1738
+ "text-sm font-semibold text-[rgb(var(--nc-fg))]",
1739
+ labelClassName
1740
+ ),
1741
+ children: label
1742
+ }
1743
+ ) : null;
1744
+ const descriptionNode = description ? /* @__PURE__ */ jsx31(
1745
+ "p",
1746
+ {
1747
+ className: cn(
1748
+ "text-xs text-[rgb(var(--nc-fg-muted))]",
1749
+ descriptionClassName
1750
+ ),
1751
+ children: description
1752
+ }
1753
+ ) : null;
1754
+ const errorNode = errorMessage ? /* @__PURE__ */ jsx31("p", { className: "text-xs text-[rgb(var(--nc-accent-3))]", children: errorMessage }) : null;
1755
+ const renderInput = () => {
1756
+ if (type === "textarea") {
1757
+ return /* @__PURE__ */ jsx31(
1758
+ CraftTextarea,
1759
+ {
1760
+ id: name,
1761
+ placeholder,
1762
+ tone,
1763
+ className: inputClassName,
1764
+ disabled,
1765
+ ...fieldProps,
1766
+ ...register(name, rules)
1767
+ }
1768
+ );
1769
+ }
1770
+ if (type === "select" || type === "multiselect") {
1771
+ return /* @__PURE__ */ jsxs22(
1772
+ CraftSelect,
1773
+ {
1774
+ id: name,
1775
+ tone,
1776
+ className: inputClassName,
1777
+ multiple: type === "multiselect",
1778
+ disabled,
1779
+ ...fieldProps,
1780
+ ...register(name, rules),
1781
+ children: [
1782
+ placeholder && /* @__PURE__ */ jsx31("option", { value: "", disabled: true, children: placeholder }),
1783
+ options.map((option) => /* @__PURE__ */ jsx31(
1784
+ "option",
1785
+ {
1786
+ value: option.value,
1787
+ disabled: option.disabled,
1788
+ children: option.label
1789
+ },
1790
+ option.value
1791
+ ))
1792
+ ]
1793
+ }
1794
+ );
1795
+ }
1796
+ if (type === "checkbox") {
1797
+ return /* @__PURE__ */ jsx31(
1798
+ CraftCheckbox,
1799
+ {
1800
+ tone,
1801
+ label,
1802
+ description,
1803
+ disabled,
1804
+ ...fieldProps,
1805
+ ...register(name, rules)
1806
+ }
1807
+ );
1808
+ }
1809
+ if (type === "switch") {
1810
+ return /* @__PURE__ */ jsx31(
1811
+ CraftSwitch,
1812
+ {
1813
+ tone,
1814
+ label,
1815
+ disabled,
1816
+ ...fieldProps,
1817
+ ...register(name, rules)
1818
+ }
1819
+ );
1820
+ }
1821
+ if (type === "date") {
1822
+ return /* @__PURE__ */ jsx31(
1823
+ Controller,
1824
+ {
1825
+ control,
1826
+ name,
1827
+ rules,
1828
+ render: ({ field }) => {
1829
+ var _a;
1830
+ return /* @__PURE__ */ jsx31(
1831
+ CraftDatePicker,
1832
+ {
1833
+ value: (_a = field.value) != null ? _a : "",
1834
+ onChange: field.onChange,
1835
+ tone,
1836
+ placeholder,
1837
+ ...fieldProps
1838
+ }
1839
+ );
1840
+ }
1841
+ }
1842
+ );
1843
+ }
1844
+ if (type === "number") {
1845
+ return /* @__PURE__ */ jsx31(
1846
+ CraftNumberInput,
1847
+ {
1848
+ id: name,
1849
+ tone,
1850
+ placeholder,
1851
+ className: inputClassName,
1852
+ disabled,
1853
+ ...fieldProps,
1854
+ ...register(name, rules)
1855
+ }
1856
+ );
1857
+ }
1858
+ if (type === "currency") {
1859
+ return /* @__PURE__ */ jsx31(
1860
+ CraftCurrencyInput,
1861
+ {
1862
+ id: name,
1863
+ tone,
1864
+ placeholder,
1865
+ className: inputClassName,
1866
+ disabled,
1867
+ ...fieldProps,
1868
+ ...register(name, rules)
1869
+ }
1870
+ );
1871
+ }
1872
+ if (type === "radio") {
1873
+ return /* @__PURE__ */ jsx31("div", { className: "grid gap-3", children: options.map((option) => /* @__PURE__ */ jsxs22(
1874
+ "label",
1875
+ {
1876
+ className: cn(
1877
+ "flex items-center gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.08)] px-4 py-3 text-sm text-[rgb(var(--nc-fg))]",
1878
+ "transition-all duration-200",
1879
+ "focus-within:ring-2 focus-within:ring-[rgb(var(--nc-accent-1)/0.5)]",
1880
+ option.disabled ? "opacity-60" : "cursor-pointer"
1881
+ ),
1882
+ "data-nc-theme": tone,
1883
+ children: [
1884
+ /* @__PURE__ */ jsx31(
1885
+ "input",
1886
+ {
1887
+ type: "radio",
1888
+ value: option.value,
1889
+ disabled: option.disabled || disabled,
1890
+ className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
1891
+ ...fieldProps,
1892
+ ...register(name, rules)
1893
+ }
1894
+ ),
1895
+ /* @__PURE__ */ jsx31("span", { children: option.label })
1896
+ ]
1897
+ },
1898
+ option.value
1899
+ )) });
1900
+ }
1901
+ if (type === "range" || type === "slider") {
1902
+ return /* @__PURE__ */ jsx31(
1903
+ "input",
1904
+ {
1905
+ id: name,
1906
+ type: "range",
1907
+ className: cn(
1908
+ "w-full accent-[rgb(var(--nc-accent-1))]",
1909
+ inputClassName
1910
+ ),
1911
+ disabled,
1912
+ ...fieldProps,
1913
+ ...register(name, rules)
1914
+ }
1915
+ );
1916
+ }
1917
+ if (type === "file" || type === "multifile") {
1918
+ return /* @__PURE__ */ jsx31(
1919
+ "input",
1920
+ {
1921
+ id: name,
1922
+ type: "file",
1923
+ multiple: type === "multifile",
1924
+ className: cn(
1925
+ baseInputClass,
1926
+ "file:mr-4 file:rounded-xl file:border-0 file:bg-[rgb(var(--nc-surface)/0.35)] file:px-4 file:py-2 file:text-sm file:font-semibold file:text-[rgb(var(--nc-fg))]",
1927
+ inputClassName
1928
+ ),
1929
+ disabled,
1930
+ ...fieldProps,
1931
+ ...register(name, rules)
1932
+ }
1933
+ );
1934
+ }
1935
+ const inputType = type === "search" || type === "password" || type === "email" || type === "tel" || type === "url" || type === "time" || type === "datetime-local" || type === "month" || type === "week" || type === "color" ? type : "text";
1936
+ return /* @__PURE__ */ jsx31(
1937
+ CraftInput,
1938
+ {
1939
+ id: name,
1940
+ type: inputType,
1941
+ placeholder,
1942
+ tone,
1943
+ className: inputClassName,
1944
+ disabled,
1945
+ ...fieldProps,
1946
+ ...register(name, rules)
1947
+ }
1948
+ );
1949
+ };
1950
+ const showLabel = type !== "checkbox" && type !== "switch";
1951
+ const showDescriptionAbove = type !== "checkbox" && type !== "switch";
1952
+ const showDescriptionBelow = type === "switch";
1953
+ return /* @__PURE__ */ jsxs22("div", { className: cn("space-y-2", className), "data-nc-theme": tone, children: [
1954
+ showLabel ? labelNode : null,
1955
+ showDescriptionAbove ? descriptionNode : null,
1956
+ renderInput(),
1957
+ showDescriptionBelow ? descriptionNode : null,
1958
+ errorNode
1959
+ ] });
1960
+ }
1961
+
1962
+ // src/components/craft-form-builder.tsx
1963
+ import { jsx as jsx32, jsxs as jsxs23 } from "react/jsx-runtime";
1964
+ function defaultValueForField(field) {
1965
+ var _a, _b, _c, _d;
1966
+ if (field.defaultValue !== void 0) return field.defaultValue;
1967
+ switch (field.type) {
1968
+ case "checkbox":
1969
+ case "switch":
1970
+ return false;
1971
+ case "number":
1972
+ case "slider":
1973
+ case "range":
1974
+ return (_a = field.min) != null ? _a : 0;
1975
+ case "multifile":
1976
+ return [];
1977
+ case "file":
1978
+ return null;
1979
+ case "multiselect":
1980
+ return [];
1981
+ case "radio":
1982
+ return (_d = (_c = (_b = field.options) == null ? void 0 : _b[0]) == null ? void 0 : _c.value) != null ? _d : "";
1983
+ default:
1984
+ return "";
1985
+ }
1986
+ }
1987
+ function buildDefaultValues(fields, initialData) {
1988
+ const values = {};
1989
+ fields.forEach((field) => {
1990
+ const initialValue = initialData == null ? void 0 : initialData[field.name];
1991
+ if (initialValue !== void 0 && initialValue !== null) {
1992
+ values[field.name] = initialValue;
1993
+ } else {
1994
+ values[field.name] = defaultValueForField(field);
1995
+ }
1996
+ });
1997
+ return values;
1998
+ }
1999
+ function buildRules(field, getValues) {
2000
+ var _a;
2001
+ const rules = { ...field.rules };
2002
+ const mergeValidate = (current, next) => {
2003
+ if (!current) return next;
2004
+ if (typeof current === "function") {
2005
+ return (value) => {
2006
+ const result = current(
2007
+ value,
2008
+ getValues()
2009
+ );
2010
+ if (result !== true) return result;
2011
+ return next(value);
2012
+ };
2013
+ }
2014
+ if (typeof current === "object") {
2015
+ return (value) => {
2016
+ const entries = Object.entries(current);
2017
+ for (const [, validator] of entries) {
2018
+ const result = validator(
2019
+ value,
2020
+ getValues()
2021
+ );
2022
+ if (result !== true) return result;
2023
+ }
2024
+ return next(value);
2025
+ };
2026
+ }
2027
+ return next;
2028
+ };
2029
+ if (field.required && field.type !== "hidden") {
2030
+ if (field.type === "checkbox" || field.type === "switch") {
2031
+ rules.validate = mergeValidate(
2032
+ rules.validate,
2033
+ (value) => {
2034
+ var _a2;
2035
+ return value ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
2036
+ }
2037
+ );
2038
+ } else if (field.type === "multiselect") {
2039
+ rules.validate = mergeValidate(
2040
+ rules.validate,
2041
+ (value) => {
2042
+ var _a2;
2043
+ return Array.isArray(value) && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
2044
+ }
2045
+ );
2046
+ } else if (field.type === "file") {
2047
+ rules.validate = mergeValidate(
2048
+ rules.validate,
2049
+ (value) => {
2050
+ var _a2;
2051
+ return value instanceof FileList && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
2052
+ }
2053
+ );
2054
+ } else if (field.type === "multifile") {
2055
+ rules.validate = mergeValidate(
2056
+ rules.validate,
2057
+ (value) => {
2058
+ var _a2;
2059
+ return Array.isArray(value) && value.length > 0 ? true : `${String((_a2 = field.label) != null ? _a2 : field.name)} is required`;
2060
+ }
2061
+ );
2062
+ } else {
2063
+ rules.required = `${String((_a = field.label) != null ? _a : field.name)} is required`;
2064
+ }
2065
+ }
2066
+ if (field.min !== void 0) {
2067
+ rules.min = { value: field.min, message: `Min ${field.min}` };
2068
+ }
2069
+ if (field.max !== void 0) {
2070
+ rules.max = { value: field.max, message: `Max ${field.max}` };
2071
+ }
2072
+ if (field.type === "email") {
2073
+ rules.pattern = {
2074
+ value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
2075
+ message: "Please enter a valid email address"
2076
+ };
2077
+ }
2078
+ if (field.type === "url") {
2079
+ rules.pattern = {
2080
+ value: /^https?:\/\/.+/,
2081
+ message: "Please enter a valid URL"
2082
+ };
2083
+ }
2084
+ if (field.validate) {
2085
+ rules.validate = mergeValidate(
2086
+ rules.validate,
2087
+ (value) => {
2088
+ var _a2;
2089
+ return (_a2 = field.validate) == null ? void 0 : _a2.call(field, value, getValues());
2090
+ }
2091
+ );
2092
+ }
2093
+ return rules;
2094
+ }
2095
+ function CraftFormBuilder({
2096
+ title = "Form",
2097
+ description,
2098
+ fields,
2099
+ initialData = null,
2100
+ open,
2101
+ defaultOpen = false,
2102
+ onOpenChange,
2103
+ trigger,
2104
+ submitLabel = "Submit",
2105
+ cancelLabel = "Cancel",
2106
+ resetLabel = "Reset",
2107
+ showReset = true,
2108
+ showCancel = true,
2109
+ tone,
2110
+ className,
2111
+ formClassName,
2112
+ loading = false,
2113
+ disableSubmitWhenInvalid = true,
2114
+ closeOnSubmit = true,
2115
+ closeOnCancel = true,
2116
+ onSubmit,
2117
+ onReset,
2118
+ onCancel,
2119
+ customValidation
2120
+ }) {
2121
+ const [uncontrolledOpen, setUncontrolledOpen] = React19.useState(defaultOpen);
2122
+ const isControlled = typeof open === "boolean";
2123
+ const isOpen = isControlled ? open : uncontrolledOpen;
2124
+ const setOpen = React19.useCallback(
2125
+ (next) => {
2126
+ if (!isControlled) setUncontrolledOpen(next);
2127
+ onOpenChange == null ? void 0 : onOpenChange(next);
2128
+ },
2129
+ [isControlled, onOpenChange]
2130
+ );
2131
+ const defaultValues = React19.useMemo(
2132
+ () => buildDefaultValues(fields, initialData),
2133
+ [fields, initialData]
2134
+ );
2135
+ const form = useForm({
2136
+ mode: "onChange",
2137
+ defaultValues
2138
+ });
2139
+ const formId = React19.useId();
2140
+ React19.useEffect(() => {
2141
+ form.reset(defaultValues);
2142
+ }, [defaultValues, form]);
2143
+ const handleSubmit = form.handleSubmit(async (values) => {
2144
+ if (customValidation) {
2145
+ const customErrors = customValidation(values);
2146
+ if (customErrors && Object.keys(customErrors).length > 0) {
2147
+ Object.entries(customErrors).forEach(([key, message]) => {
2148
+ if (message) {
2149
+ form.setError(key, {
2150
+ type: "custom",
2151
+ message: String(message)
2152
+ });
2153
+ }
2154
+ });
2155
+ return;
2156
+ }
2157
+ }
2158
+ await onSubmit(values);
2159
+ if (closeOnSubmit) setOpen(false);
2160
+ });
2161
+ const handleReset = () => {
2162
+ form.reset(defaultValues);
2163
+ onReset == null ? void 0 : onReset();
2164
+ };
2165
+ const handleCancel = () => {
2166
+ onCancel == null ? void 0 : onCancel();
2167
+ if (closeOnCancel) setOpen(false);
2168
+ };
2169
+ return /* @__PURE__ */ jsx32(FormProvider2, { ...form, children: /* @__PURE__ */ jsx32(
2170
+ CraftModal,
2171
+ {
2172
+ open: isOpen,
2173
+ onOpenChange: setOpen,
2174
+ trigger,
2175
+ title,
2176
+ description,
2177
+ tone,
2178
+ className,
2179
+ footer: /* @__PURE__ */ jsxs23("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
2180
+ showReset && /* @__PURE__ */ jsx32(
2181
+ CraftButton,
2182
+ {
2183
+ type: "button",
2184
+ variant: "outline",
2185
+ onClick: handleReset,
2186
+ disabled: loading,
2187
+ children: resetLabel
2188
+ }
2189
+ ),
2190
+ showCancel && /* @__PURE__ */ jsx32(
2191
+ CraftButton,
2192
+ {
2193
+ type: "button",
2194
+ variant: "ghost",
2195
+ onClick: handleCancel,
2196
+ disabled: loading,
2197
+ children: cancelLabel
2198
+ }
2199
+ ),
2200
+ /* @__PURE__ */ jsx32(
2201
+ CraftSubmitButton,
2202
+ {
2203
+ loading,
2204
+ disableWhenInvalid: disableSubmitWhenInvalid,
2205
+ form: formId,
2206
+ children: submitLabel
2207
+ }
2208
+ )
2209
+ ] }),
2210
+ children: /* @__PURE__ */ jsx32(
2211
+ "form",
2212
+ {
2213
+ id: formId,
2214
+ onSubmit: handleSubmit,
2215
+ className: cn("space-y-5", formClassName),
2216
+ children: fields.map((field) => /* @__PURE__ */ jsxs23("div", { className: "space-y-2", children: [
2217
+ field.helpText && /* @__PURE__ */ jsx32("p", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: field.helpText }),
2218
+ /* @__PURE__ */ jsx32(
2219
+ CraftFormField,
2220
+ {
2221
+ name: field.name,
2222
+ label: field.label,
2223
+ description: field.description,
2224
+ type: field.type,
2225
+ placeholder: field.placeholder,
2226
+ options: field.options,
2227
+ tone,
2228
+ disabled: field.disabled || loading,
2229
+ rules: buildRules(field, form.getValues),
2230
+ fieldProps: {
2231
+ min: field.min,
2232
+ max: field.max,
2233
+ step: field.step,
2234
+ rows: field.rows,
2235
+ accept: field.accept,
2236
+ multiple: field.type === "multifile",
2237
+ ...field.fieldProps
2238
+ }
2239
+ }
2240
+ )
2241
+ ] }, field.name))
2242
+ }
2243
+ )
2244
+ }
2245
+ ) });
2246
+ }
2247
+
2248
+ // src/components/craft-confirm-dialog.tsx
2249
+ import * as React20 from "react";
2250
+ import { jsx as jsx33, jsxs as jsxs24 } from "react/jsx-runtime";
2251
+ function CraftConfirmDialog({
2252
+ open,
2253
+ defaultOpen = false,
2254
+ onOpenChange,
2255
+ tone,
2256
+ title = "Confirm action",
2257
+ description,
2258
+ confirmLabel = "Confirm",
2259
+ cancelLabel = "Cancel",
2260
+ onConfirm,
2261
+ trigger,
2262
+ className,
2263
+ confirmVariant = "solid"
2264
+ }) {
2265
+ const [uncontrolledOpen, setUncontrolledOpen] = React20.useState(defaultOpen);
2266
+ const isControlled = typeof open === "boolean";
2267
+ const isOpen = isControlled ? open : uncontrolledOpen;
2268
+ const setOpen = React20.useCallback(
2269
+ (next) => {
2270
+ if (!isControlled) setUncontrolledOpen(next);
2271
+ onOpenChange == null ? void 0 : onOpenChange(next);
2272
+ },
2273
+ [isControlled, onOpenChange]
2274
+ );
2275
+ const [isLoading, setIsLoading] = React20.useState(false);
2276
+ const handleConfirm = async () => {
2277
+ if (!onConfirm) {
2278
+ setOpen(false);
2279
+ return;
2280
+ }
2281
+ setIsLoading(true);
2282
+ await onConfirm();
2283
+ setIsLoading(false);
2284
+ setOpen(false);
2285
+ };
2286
+ return /* @__PURE__ */ jsx33(
2287
+ CraftModal,
2288
+ {
2289
+ open: isOpen,
2290
+ onOpenChange: setOpen,
2291
+ trigger,
2292
+ title,
2293
+ description,
2294
+ tone,
2295
+ className: cn("max-w-md", className),
2296
+ footer: /* @__PURE__ */ jsxs24("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
2297
+ /* @__PURE__ */ jsx33(
2298
+ CraftButton,
2299
+ {
2300
+ type: "button",
2301
+ variant: "ghost",
2302
+ onClick: () => setOpen(false),
2303
+ children: cancelLabel
2304
+ }
2305
+ ),
2306
+ /* @__PURE__ */ jsx33(
2307
+ CraftButton,
2308
+ {
2309
+ type: "button",
2310
+ variant: confirmVariant,
2311
+ disabled: isLoading,
2312
+ onClick: handleConfirm,
2313
+ children: isLoading ? "Working..." : confirmLabel
2314
+ }
2315
+ )
2316
+ ] }),
2317
+ children: /* @__PURE__ */ jsx33("div", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description })
2318
+ }
2319
+ );
2320
+ }
2321
+
2322
+ // src/components/craft-create-edit-drawer.tsx
2323
+ import * as React21 from "react";
2324
+ import { FormProvider as FormProvider3 } from "react-hook-form";
2325
+ import { jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
2326
+ function CraftCreateEditDrawer({
2327
+ mode = "create",
2328
+ form,
2329
+ onSubmit,
2330
+ open,
2331
+ defaultOpen = false,
2332
+ onOpenChange,
2333
+ trigger,
2334
+ title,
2335
+ description,
2336
+ submitLabel,
2337
+ cancelLabel = "Cancel",
2338
+ tone,
2339
+ className,
2340
+ children,
2341
+ footer,
2342
+ disableSubmitWhenInvalid = true,
2343
+ closeOnSubmit = true,
2344
+ side = "right"
2345
+ }) {
2346
+ const [uncontrolledOpen, setUncontrolledOpen] = React21.useState(defaultOpen);
2347
+ const isControlled = typeof open === "boolean";
2348
+ const isOpen = isControlled ? open : uncontrolledOpen;
2349
+ const setOpen = React21.useCallback(
2350
+ (next) => {
2351
+ if (!isControlled) setUncontrolledOpen(next);
2352
+ onOpenChange == null ? void 0 : onOpenChange(next);
2353
+ },
2354
+ [isControlled, onOpenChange]
2355
+ );
2356
+ const formId = React21.useId();
2357
+ const handleSubmit = form.handleSubmit(async (values) => {
2358
+ await onSubmit(values);
2359
+ if (closeOnSubmit) setOpen(false);
2360
+ });
2361
+ const resolvedTitle = title != null ? title : mode === "create" ? "Create item" : "Edit item";
2362
+ const resolvedSubmitLabel = submitLabel != null ? submitLabel : mode === "create" ? "Create" : "Save changes";
2363
+ const footerContent = footer != null ? footer : /* @__PURE__ */ jsxs25("div", { className: "flex flex-wrap items-center justify-end gap-3", children: [
2364
+ /* @__PURE__ */ jsx34(CraftButton, { type: "button", variant: "ghost", onClick: () => setOpen(false), children: cancelLabel }),
2365
+ /* @__PURE__ */ jsx34(
2366
+ CraftSubmitButton,
2367
+ {
2368
+ form: formId,
2369
+ disableWhenInvalid: disableSubmitWhenInvalid,
2370
+ children: resolvedSubmitLabel
2371
+ }
2372
+ )
2373
+ ] });
2374
+ return /* @__PURE__ */ jsx34(FormProvider3, { ...form, children: /* @__PURE__ */ jsx34(
2375
+ CraftDrawer,
2376
+ {
2377
+ open: isOpen,
2378
+ onOpenChange: setOpen,
2379
+ trigger,
2380
+ title: resolvedTitle,
2381
+ tone,
2382
+ side,
2383
+ className: cn("flex flex-col", className),
2384
+ footer: footerContent,
2385
+ children: /* @__PURE__ */ jsxs25("form", { id: formId, onSubmit: handleSubmit, className: "space-y-5", children: [
2386
+ description && /* @__PURE__ */ jsx34("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description }),
2387
+ children
2388
+ ] })
2389
+ }
2390
+ ) });
2391
+ }
2392
+
2393
+ // src/components/craft-filter-bar.tsx
2394
+ import { jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
2395
+ function CraftFilterBar({
2396
+ title,
2397
+ description,
2398
+ searchValue,
2399
+ onSearchChange,
2400
+ searchPlaceholder = "Search...",
2401
+ actions,
2402
+ filters,
2403
+ tone,
2404
+ className
2405
+ }) {
2406
+ return /* @__PURE__ */ jsxs26(
2407
+ "div",
2408
+ {
2409
+ className: cn(
2410
+ "rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] p-4 text-[rgb(var(--nc-fg))] shadow-[0_12px_36px_rgba(0,0,0,0.2)] backdrop-blur-2xl",
2411
+ className
2412
+ ),
2413
+ "data-nc-theme": tone,
2414
+ children: [
2415
+ /* @__PURE__ */ jsxs26("div", { className: "flex flex-wrap items-center justify-between gap-4", children: [
2416
+ /* @__PURE__ */ jsxs26("div", { children: [
2417
+ title && /* @__PURE__ */ jsx35("h3", { className: "text-lg font-semibold", children: title }),
2418
+ description && /* @__PURE__ */ jsx35("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description })
2419
+ ] }),
2420
+ actions && /* @__PURE__ */ jsx35("div", { className: "flex items-center gap-3", children: actions })
2421
+ ] }),
2422
+ /* @__PURE__ */ jsxs26("div", { className: "mt-4 grid gap-4 md:grid-cols-[minmax(0,1fr)_auto]", children: [
2423
+ /* @__PURE__ */ jsx35(
2424
+ CraftInput,
2425
+ {
2426
+ type: "search",
2427
+ placeholder: searchPlaceholder,
2428
+ value: searchValue != null ? searchValue : "",
2429
+ onChange: (event) => onSearchChange == null ? void 0 : onSearchChange(event.target.value),
2430
+ tone
2431
+ }
2432
+ ),
2433
+ filters && /* @__PURE__ */ jsx35("div", { className: "flex flex-wrap items-center gap-3", children: filters })
2434
+ ] })
2435
+ ]
2436
+ }
2437
+ );
2438
+ }
2439
+
2440
+ // src/components/craft-table-toolbar.tsx
2441
+ import { jsx as jsx36, jsxs as jsxs27 } from "react/jsx-runtime";
2442
+ function CraftTableToolbar({
2443
+ title,
2444
+ description,
2445
+ searchValue,
2446
+ onSearchChange,
2447
+ searchPlaceholder = "Search table...",
2448
+ actions,
2449
+ filters,
2450
+ bulkActions,
2451
+ tone,
2452
+ className
2453
+ }) {
2454
+ return /* @__PURE__ */ jsxs27(
2455
+ "div",
2456
+ {
2457
+ className: cn(
2458
+ "rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] p-4 text-[rgb(var(--nc-fg))] shadow-[0_12px_36px_rgba(0,0,0,0.2)] backdrop-blur-2xl",
2459
+ className
2460
+ ),
2461
+ "data-nc-theme": tone,
2462
+ children: [
2463
+ /* @__PURE__ */ jsxs27("div", { className: "flex flex-wrap items-center justify-between gap-4", children: [
2464
+ /* @__PURE__ */ jsxs27("div", { children: [
2465
+ title && /* @__PURE__ */ jsx36("h3", { className: "text-lg font-semibold", children: title }),
2466
+ description && /* @__PURE__ */ jsx36("p", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: description })
2467
+ ] }),
2468
+ actions && /* @__PURE__ */ jsx36("div", { className: "flex items-center gap-3", children: actions })
2469
+ ] }),
2470
+ /* @__PURE__ */ jsxs27("div", { className: "mt-4 grid gap-4 lg:grid-cols-[minmax(0,1fr)_auto]", children: [
2471
+ /* @__PURE__ */ jsx36(
2472
+ CraftInput,
2473
+ {
2474
+ type: "search",
2475
+ placeholder: searchPlaceholder,
2476
+ value: searchValue != null ? searchValue : "",
2477
+ onChange: (event) => onSearchChange == null ? void 0 : onSearchChange(event.target.value),
2478
+ tone
2479
+ }
2480
+ ),
2481
+ /* @__PURE__ */ jsxs27("div", { className: "flex flex-wrap items-center gap-3", children: [
2482
+ filters,
2483
+ bulkActions
2484
+ ] })
2485
+ ] })
2486
+ ]
2487
+ }
2488
+ );
2489
+ }
2490
+
2491
+ // src/components/craft-data-table.tsx
2492
+ import * as React22 from "react";
2493
+
2494
+ // src/components/craft-pagination.tsx
2495
+ import { jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
2496
+ function getPageNumbers(pageIndex, pageCount, maxButtons = 5) {
2497
+ if (pageCount <= maxButtons) {
2498
+ return Array.from({ length: pageCount }, (_, i) => i);
2499
+ }
2500
+ const pages = [];
2501
+ const start = Math.max(0, pageIndex - 1);
2502
+ const end = Math.min(pageCount - 1, pageIndex + 1);
2503
+ pages.push(0);
2504
+ if (start > 1) pages.push("ellipsis");
2505
+ for (let i = start; i <= end; i += 1) {
2506
+ if (i !== 0 && i !== pageCount - 1) pages.push(i);
2507
+ }
2508
+ if (end < pageCount - 2) pages.push("ellipsis");
2509
+ pages.push(pageCount - 1);
2510
+ return pages;
2511
+ }
2512
+ function CraftPagination({
2513
+ pageIndex,
2514
+ pageCount,
2515
+ onPageChange,
2516
+ canPrevious = pageIndex > 0,
2517
+ canNext = pageIndex < pageCount - 1,
2518
+ pageSize,
2519
+ pageSizeOptions = [10, 20, 50],
2520
+ onPageSizeChange,
2521
+ tone,
2522
+ className
2523
+ }) {
2524
+ const pages = getPageNumbers(pageIndex, pageCount);
2525
+ return /* @__PURE__ */ jsxs28(
2526
+ "div",
2527
+ {
2528
+ className: cn(
2529
+ "flex flex-wrap items-center justify-between gap-4",
2530
+ className
2531
+ ),
2532
+ "data-nc-theme": tone,
2533
+ children: [
2534
+ /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2", children: [
2535
+ /* @__PURE__ */ jsx37(
2536
+ "button",
2537
+ {
2538
+ type: "button",
2539
+ className: cn(
2540
+ "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-2 text-xs text-[rgb(var(--nc-fg))] transition",
2541
+ "hover:bg-[rgb(var(--nc-surface)/0.2)]",
2542
+ !canPrevious && "opacity-50 cursor-not-allowed"
2543
+ ),
2544
+ onClick: () => onPageChange(Math.max(pageIndex - 1, 0)),
2545
+ disabled: !canPrevious,
2546
+ children: "Prev"
2547
+ }
2548
+ ),
2549
+ pages.map(
2550
+ (page, index) => page === "ellipsis" ? /* @__PURE__ */ jsx37("span", { className: "px-2 text-[rgb(var(--nc-fg-muted))]", children: "..." }, `ellipsis-${index}`) : /* @__PURE__ */ jsx37(
2551
+ "button",
2552
+ {
2553
+ type: "button",
2554
+ className: cn(
2555
+ "rounded-xl border px-3 py-2 text-xs transition",
2556
+ page === pageIndex ? "border-[rgb(var(--nc-accent-1)/0.6)] bg-[rgb(var(--nc-accent-1)/0.2)] text-[rgb(var(--nc-fg))]" : "border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] text-[rgb(var(--nc-fg-muted))] hover:text-[rgb(var(--nc-fg))] hover:bg-[rgb(var(--nc-surface)/0.2)]"
2557
+ ),
2558
+ onClick: () => onPageChange(page),
2559
+ children: page + 1
2560
+ },
2561
+ page
2562
+ )
2563
+ ),
2564
+ /* @__PURE__ */ jsx37(
2565
+ "button",
2566
+ {
2567
+ type: "button",
2568
+ className: cn(
2569
+ "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-2 text-xs text-[rgb(var(--nc-fg))] transition",
2570
+ "hover:bg-[rgb(var(--nc-surface)/0.2)]",
2571
+ !canNext && "opacity-50 cursor-not-allowed"
2572
+ ),
2573
+ onClick: () => onPageChange(Math.min(pageIndex + 1, pageCount - 1)),
2574
+ disabled: !canNext,
2575
+ children: "Next"
2576
+ }
2577
+ )
2578
+ ] }),
2579
+ onPageSizeChange && /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2 text-xs text-[rgb(var(--nc-fg-muted))]", children: [
2580
+ /* @__PURE__ */ jsx37("span", { children: "Rows" }),
2581
+ /* @__PURE__ */ jsx37(
2582
+ "select",
2583
+ {
2584
+ className: "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-2 py-1 text-xs text-[rgb(var(--nc-fg))]",
2585
+ value: pageSize,
2586
+ onChange: (event) => onPageSizeChange(Number(event.target.value)),
2587
+ children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx37("option", { value: size, children: size }, size))
2588
+ }
2589
+ )
2590
+ ] })
2591
+ ]
2592
+ }
2593
+ );
2594
+ }
2595
+
2596
+ // src/components/craft-data-table.tsx
2597
+ import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
2598
+ function getColumnValue(column, row) {
2599
+ if (typeof column.accessor === "function") return column.accessor(row);
2600
+ const record = row;
2601
+ if (typeof column.accessor === "string") return record[column.accessor];
2602
+ return record[column.id];
2603
+ }
2604
+ function normalizeValue(value) {
2605
+ if (value === null || value === void 0) return "";
2606
+ if (typeof value === "number") return value;
2607
+ if (typeof value === "string") return value.toLowerCase();
2608
+ if (value instanceof Date) return value.getTime();
2609
+ return String(value).toLowerCase();
2610
+ }
2611
+ function CraftDataTable({
2612
+ data,
2613
+ columns,
2614
+ tone,
2615
+ className,
2616
+ loading = false,
2617
+ emptyState,
2618
+ toolbar,
2619
+ enableSorting = true,
2620
+ enableFiltering = true,
2621
+ enableColumnVisibility = true,
2622
+ enableRowSelection = true,
2623
+ enablePagination = true,
2624
+ showGlobalFilter,
2625
+ manualSorting = false,
2626
+ manualFiltering = false,
2627
+ manualPagination = false,
2628
+ sortBy,
2629
+ onSortChange,
2630
+ filters,
2631
+ onFiltersChange,
2632
+ globalFilter,
2633
+ onGlobalFilterChange,
2634
+ columnVisibility,
2635
+ onColumnVisibilityChange,
2636
+ selectedRowIds,
2637
+ onRowSelectionChange,
2638
+ getRowId,
2639
+ pageIndex,
2640
+ pageSize = 10,
2641
+ pageCount,
2642
+ onPageChange,
2643
+ onPageSizeChange
2644
+ }) {
2645
+ const [internalSort, setInternalSort] = React22.useState(null);
2646
+ const [internalFilters, setInternalFilters] = React22.useState({});
2647
+ const [internalGlobalFilter, setInternalGlobalFilter] = React22.useState("");
2648
+ const [internalVisibility, setInternalVisibility] = React22.useState(
2649
+ () => columns.reduce((acc, column) => {
2650
+ acc[column.id] = !column.hidden;
2651
+ return acc;
2652
+ }, {})
2653
+ );
2654
+ const [internalSelection, setInternalSelection] = React22.useState({});
2655
+ const [internalPageIndex, setInternalPageIndex] = React22.useState(0);
2656
+ const [showColumns, setShowColumns] = React22.useState(false);
2657
+ const resolvedSort = sortBy != null ? sortBy : internalSort;
2658
+ const resolvedFilters = filters != null ? filters : internalFilters;
2659
+ const resolvedGlobalFilter = globalFilter != null ? globalFilter : internalGlobalFilter;
2660
+ const resolvedVisibility = columnVisibility != null ? columnVisibility : internalVisibility;
2661
+ const resolvedSelection = selectedRowIds != null ? selectedRowIds : internalSelection;
2662
+ const resolvedPageIndex = pageIndex != null ? pageIndex : internalPageIndex;
2663
+ const setSort = (next) => {
2664
+ if (sortBy === void 0) setInternalSort(next);
2665
+ onSortChange == null ? void 0 : onSortChange(next);
2666
+ };
2667
+ const setFilters = (next) => {
2668
+ if (filters === void 0) setInternalFilters(next);
2669
+ onFiltersChange == null ? void 0 : onFiltersChange(next);
2670
+ };
2671
+ const setVisibility = (next) => {
2672
+ if (columnVisibility === void 0) setInternalVisibility(next);
2673
+ onColumnVisibilityChange == null ? void 0 : onColumnVisibilityChange(next);
2674
+ };
2675
+ const setSelection = (next) => {
2676
+ if (selectedRowIds === void 0) setInternalSelection(next);
2677
+ onRowSelectionChange == null ? void 0 : onRowSelectionChange(next);
2678
+ };
2679
+ const setPageIndex = React22.useCallback(
2680
+ (next) => {
2681
+ if (pageIndex === void 0) setInternalPageIndex(next);
2682
+ onPageChange == null ? void 0 : onPageChange(next);
2683
+ },
2684
+ [pageIndex, onPageChange]
2685
+ );
2686
+ const visibleColumns = columns.filter(
2687
+ (column) => resolvedVisibility[column.id] !== false
2688
+ );
2689
+ const filteredData = React22.useMemo(() => {
2690
+ if (manualFiltering) return data;
2691
+ const globalValue = resolvedGlobalFilter.trim();
2692
+ return data.filter((row) => {
2693
+ if (globalValue) {
2694
+ const matchesGlobal = columns.some((column) => {
2695
+ const value = normalizeValue(getColumnValue(column, row));
2696
+ return String(value).includes(globalValue.toLowerCase());
2697
+ });
2698
+ if (!matchesGlobal) return false;
2699
+ }
2700
+ return Object.entries(resolvedFilters).every(([columnId, value]) => {
2701
+ if (!value) return true;
2702
+ const column = columns.find((col) => col.id === columnId);
2703
+ if (!column) return true;
2704
+ const cellValue = normalizeValue(getColumnValue(column, row));
2705
+ return String(cellValue).includes(value.toLowerCase());
2706
+ });
2707
+ });
2708
+ }, [columns, data, manualFiltering, resolvedFilters, resolvedGlobalFilter]);
2709
+ const sortedData = React22.useMemo(() => {
2710
+ if (manualSorting || !resolvedSort) return filteredData;
2711
+ const column = columns.find((col) => col.id === resolvedSort.id);
2712
+ if (!column) return filteredData;
2713
+ const sorted = [...filteredData].sort((a, b) => {
2714
+ const valueA = normalizeValue(getColumnValue(column, a));
2715
+ const valueB = normalizeValue(getColumnValue(column, b));
2716
+ if (typeof valueA === "number" && typeof valueB === "number") {
2717
+ return valueA - valueB;
2718
+ }
2719
+ return String(valueA).localeCompare(String(valueB));
2720
+ });
2721
+ return resolvedSort.desc ? sorted.reverse() : sorted;
2722
+ }, [columns, filteredData, manualSorting, resolvedSort]);
2723
+ const resolvedPageCount = manualPagination ? Math.max(pageCount != null ? pageCount : 1, 1) : Math.max(Math.ceil(sortedData.length / pageSize), 1);
2724
+ React22.useEffect(() => {
2725
+ if (resolvedPageIndex > resolvedPageCount - 1) {
2726
+ setPageIndex(Math.max(resolvedPageCount - 1, 0));
2727
+ }
2728
+ }, [resolvedPageCount, resolvedPageIndex, setPageIndex]);
2729
+ const pagedData = React22.useMemo(() => {
2730
+ if (!enablePagination || manualPagination) return sortedData;
2731
+ const start = resolvedPageIndex * pageSize;
2732
+ return sortedData.slice(start, start + pageSize);
2733
+ }, [enablePagination, manualPagination, pageSize, resolvedPageIndex, sortedData]);
2734
+ const rowIdFor = React22.useCallback(
2735
+ (row, index) => {
2736
+ var _a;
2737
+ return (_a = getRowId == null ? void 0 : getRowId(row, index)) != null ? _a : String(index);
2738
+ },
2739
+ [getRowId]
2740
+ );
2741
+ const pageStartIndex = enablePagination && !manualPagination ? resolvedPageIndex * pageSize : 0;
2742
+ const pageRowIds = pagedData.map(
2743
+ (row, index) => rowIdFor(row, pageStartIndex + index)
2744
+ );
2745
+ const allSelected = pageRowIds.length > 0 && pageRowIds.every((id) => resolvedSelection[id]);
2746
+ const someSelected = pageRowIds.some((id) => resolvedSelection[id]);
2747
+ const headerCheckboxRef = React22.useRef(null);
2748
+ React22.useEffect(() => {
2749
+ if (headerCheckboxRef.current) {
2750
+ headerCheckboxRef.current.indeterminate = someSelected && !allSelected;
2751
+ }
2752
+ }, [someSelected, allSelected]);
2753
+ const toggleSort = (column) => {
2754
+ if (!enableSorting || column.sortable === false) return;
2755
+ const current = resolvedSort;
2756
+ if (!current || current.id !== column.id) {
2757
+ setSort({ id: column.id, desc: false });
2758
+ return;
2759
+ }
2760
+ if (!current.desc) {
2761
+ setSort({ id: column.id, desc: true });
2762
+ return;
2763
+ }
2764
+ setSort(null);
2765
+ };
2766
+ const emptyContent = emptyState != null ? emptyState : /* @__PURE__ */ jsx38("div", { className: "text-center text-sm text-[rgb(var(--nc-fg-muted))]", children: "No results found." });
2767
+ const resolvedShowGlobalFilter = showGlobalFilter != null ? showGlobalFilter : enableFiltering && !toolbar;
2768
+ const setGlobalFilter = (next) => {
2769
+ if (globalFilter === void 0) setInternalGlobalFilter(next);
2770
+ onGlobalFilterChange == null ? void 0 : onGlobalFilterChange(next);
2771
+ };
2772
+ return /* @__PURE__ */ jsxs29("div", { className: cn("space-y-4", className), "data-nc-theme": tone, children: [
2773
+ toolbar,
2774
+ resolvedShowGlobalFilter && /* @__PURE__ */ jsxs29("div", { className: "flex items-center justify-between gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-2 text-sm text-[rgb(var(--nc-fg))]", children: [
2775
+ /* @__PURE__ */ jsx38("span", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: "Global filter" }),
2776
+ /* @__PURE__ */ jsx38(
2777
+ "input",
2778
+ {
2779
+ type: "search",
2780
+ value: resolvedGlobalFilter,
2781
+ onChange: (event) => setGlobalFilter(event.target.value),
2782
+ placeholder: "Search all columns...",
2783
+ className: "w-full max-w-xs rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.18)] px-3 py-2 text-xs text-[rgb(var(--nc-fg))]"
2784
+ }
2785
+ )
2786
+ ] }),
2787
+ enableColumnVisibility && /* @__PURE__ */ jsxs29("div", { className: "relative flex justify-end", children: [
2788
+ /* @__PURE__ */ jsx38(
2789
+ "button",
2790
+ {
2791
+ type: "button",
2792
+ className: "rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-2 text-xs text-[rgb(var(--nc-fg))] transition hover:bg-[rgb(var(--nc-surface)/0.2)]",
2793
+ onClick: () => setShowColumns((prev) => !prev),
2794
+ children: "Columns"
2795
+ }
2796
+ ),
2797
+ showColumns && /* @__PURE__ */ jsx38("div", { className: "absolute right-0 top-10 z-20 w-48 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.2)] p-3 shadow-[0_12px_30px_rgba(0,0,0,0.35)] backdrop-blur-2xl", children: /* @__PURE__ */ jsx38("div", { className: "grid gap-2", children: columns.map((column) => /* @__PURE__ */ jsxs29(
2798
+ "label",
2799
+ {
2800
+ className: "flex items-center gap-2 text-xs text-[rgb(var(--nc-fg))]",
2801
+ children: [
2802
+ /* @__PURE__ */ jsx38(
2803
+ "input",
2804
+ {
2805
+ type: "checkbox",
2806
+ className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
2807
+ checked: resolvedVisibility[column.id] !== false,
2808
+ onChange: (event) => setVisibility({
2809
+ ...resolvedVisibility,
2810
+ [column.id]: event.target.checked
2811
+ })
2812
+ }
2813
+ ),
2814
+ column.header
2815
+ ]
2816
+ },
2817
+ column.id
2818
+ )) }) })
2819
+ ] }),
2820
+ /* @__PURE__ */ jsx38("div", { className: "overflow-hidden rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] shadow-[0_18px_50px_rgba(0,0,0,0.35)] backdrop-blur-2xl", children: /* @__PURE__ */ jsxs29("table", { className: "w-full border-collapse text-left text-sm", children: [
2821
+ /* @__PURE__ */ jsx38("thead", { className: "bg-[rgb(var(--nc-surface)/0.12)] text-[rgb(var(--nc-fg-muted))]", children: /* @__PURE__ */ jsxs29("tr", { children: [
2822
+ enableRowSelection && /* @__PURE__ */ jsx38("th", { className: "w-12 px-4 py-3", children: /* @__PURE__ */ jsx38(
2823
+ "input",
2824
+ {
2825
+ ref: headerCheckboxRef,
2826
+ type: "checkbox",
2827
+ className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
2828
+ checked: allSelected,
2829
+ onChange: (event) => {
2830
+ const next = { ...resolvedSelection };
2831
+ pageRowIds.forEach((id) => {
2832
+ next[id] = event.target.checked;
2833
+ });
2834
+ setSelection(next);
2835
+ }
2836
+ }
2837
+ ) }),
2838
+ visibleColumns.map((column) => {
2839
+ var _a;
2840
+ return /* @__PURE__ */ jsxs29(
2841
+ "th",
2842
+ {
2843
+ className: cn(
2844
+ "px-4 py-3 text-xs font-semibold uppercase tracking-[0.2em]",
2845
+ column.headerClassName
2846
+ ),
2847
+ style: { width: column.width },
2848
+ children: [
2849
+ /* @__PURE__ */ jsxs29(
2850
+ "button",
2851
+ {
2852
+ type: "button",
2853
+ className: cn(
2854
+ "flex items-center gap-2",
2855
+ enableSorting && column.sortable !== false ? "cursor-pointer" : "cursor-default"
2856
+ ),
2857
+ onClick: () => toggleSort(column),
2858
+ children: [
2859
+ /* @__PURE__ */ jsx38("span", { children: column.header }),
2860
+ (resolvedSort == null ? void 0 : resolvedSort.id) === column.id && /* @__PURE__ */ jsx38("span", { className: "text-[rgb(var(--nc-accent-1))]", children: resolvedSort.desc ? "\u2193" : "\u2191" })
2861
+ ]
2862
+ }
2863
+ ),
2864
+ enableFiltering && column.filterable !== false && /* @__PURE__ */ jsx38(
2865
+ "input",
2866
+ {
2867
+ type: "text",
2868
+ value: (_a = resolvedFilters[column.id]) != null ? _a : "",
2869
+ onChange: (event) => setFilters({
2870
+ ...resolvedFilters,
2871
+ [column.id]: event.target.value
2872
+ }),
2873
+ placeholder: "Filter",
2874
+ className: "mt-2 w-full rounded-xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.18)] px-2 py-1 text-xs text-[rgb(var(--nc-fg))]"
2875
+ }
2876
+ )
2877
+ ]
2878
+ },
2879
+ column.id
2880
+ );
2881
+ })
2882
+ ] }) }),
2883
+ /* @__PURE__ */ jsxs29("tbody", { className: "text-[rgb(var(--nc-fg))]", children: [
2884
+ loading && /* @__PURE__ */ jsx38("tr", { children: /* @__PURE__ */ jsx38(
2885
+ "td",
2886
+ {
2887
+ colSpan: visibleColumns.length + (enableRowSelection ? 1 : 0),
2888
+ className: "px-4 py-10 text-center text-sm text-[rgb(var(--nc-fg-muted))]",
2889
+ children: /* @__PURE__ */ jsxs29("span", { className: "inline-flex items-center gap-2", children: [
2890
+ /* @__PURE__ */ jsx38("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-[rgb(var(--nc-fg-muted))] border-t-transparent" }),
2891
+ "Loading data..."
2892
+ ] })
2893
+ }
2894
+ ) }),
2895
+ !loading && pagedData.length === 0 && /* @__PURE__ */ jsx38("tr", { children: /* @__PURE__ */ jsx38(
2896
+ "td",
2897
+ {
2898
+ colSpan: visibleColumns.length + (enableRowSelection ? 1 : 0),
2899
+ className: "px-4 py-10",
2900
+ children: emptyContent
2901
+ }
2902
+ ) }),
2903
+ !loading && pagedData.map((row, rowIndex) => {
2904
+ const rowId = rowIdFor(row, pageStartIndex + rowIndex);
2905
+ const isSelected = resolvedSelection[rowId];
2906
+ return /* @__PURE__ */ jsxs29(
2907
+ "tr",
2908
+ {
2909
+ className: cn(
2910
+ "border-t border-[rgb(var(--nc-border)/0.15)]",
2911
+ isSelected && "bg-[rgb(var(--nc-accent-1)/0.08)]"
2912
+ ),
2913
+ children: [
2914
+ enableRowSelection && /* @__PURE__ */ jsx38("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx38(
2915
+ "input",
2916
+ {
2917
+ type: "checkbox",
2918
+ className: "h-4 w-4 accent-[rgb(var(--nc-accent-1))]",
2919
+ checked: isSelected,
2920
+ onChange: (event) => setSelection({
2921
+ ...resolvedSelection,
2922
+ [rowId]: event.target.checked
2923
+ })
2924
+ }
2925
+ ) }),
2926
+ visibleColumns.map((column) => {
2927
+ var _a;
2928
+ return /* @__PURE__ */ jsx38(
2929
+ "td",
2930
+ {
2931
+ className: cn(
2932
+ "px-4 py-4",
2933
+ column.align === "center" && "text-center",
2934
+ column.align === "right" && "text-right",
2935
+ column.cellClassName
2936
+ ),
2937
+ children: column.cell ? column.cell(row) : String((_a = getColumnValue(column, row)) != null ? _a : "")
2938
+ },
2939
+ column.id
2940
+ );
2941
+ })
2942
+ ]
2943
+ },
2944
+ rowId
2945
+ );
2946
+ })
2947
+ ] })
2948
+ ] }) }),
2949
+ enablePagination && /* @__PURE__ */ jsx38(
2950
+ CraftPagination,
2951
+ {
2952
+ pageIndex: resolvedPageIndex,
2953
+ pageCount: resolvedPageCount,
2954
+ onPageChange: setPageIndex,
2955
+ pageSize,
2956
+ onPageSizeChange,
2957
+ tone
2958
+ }
2959
+ )
2960
+ ] });
2961
+ }
2962
+
2963
+ // src/components/layout/app-shell.tsx
2964
+ import { jsx as jsx39, jsxs as jsxs30 } from "react/jsx-runtime";
2965
+ function AppShell({ className, sidebar, topNav, children, ...props }) {
2966
+ return /* @__PURE__ */ jsxs30(
2967
+ "div",
2968
+ {
2969
+ className: cn(
2970
+ "grid min-h-screen grid-cols-1 gap-6 bg-background p-6 lg:grid-cols-[260px_1fr]",
2971
+ className
2972
+ ),
2973
+ ...props,
2974
+ children: [
2975
+ sidebar && /* @__PURE__ */ jsx39("div", { className: "h-full lg:sticky lg:top-6 lg:self-start lg:max-h-[calc(100vh-3rem)] lg:overflow-y-auto", children: sidebar }),
2976
+ /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-6", children: [
2977
+ topNav && /* @__PURE__ */ jsx39("div", { className: "lg:sticky lg:top-6 lg:z-20", children: topNav }),
2978
+ /* @__PURE__ */ jsx39("main", { className: "flex-1", children })
2979
+ ] })
2980
+ ]
2981
+ }
2982
+ );
2983
+ }
2984
+
2985
+ // src/components/layout/app-template.tsx
2986
+ import * as React23 from "react";
2987
+
2988
+ // src/components/layout/breadcrumbs.tsx
2989
+ import { jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
2990
+ function Breadcrumbs({ className, items, ...props }) {
2991
+ return /* @__PURE__ */ jsx40("nav", { className: cn("flex items-center text-sm text-[rgb(var(--nc-fg-muted))]", className), ...props, children: items.map((item, index) => {
2992
+ const content = item.href ? /* @__PURE__ */ jsx40("a", { href: item.href, className: "transition hover:text-[rgb(var(--nc-fg))]", children: item.label }) : /* @__PURE__ */ jsx40("span", { className: "text-[rgb(var(--nc-fg))]", children: item.label });
2993
+ return /* @__PURE__ */ jsxs31("span", { className: "flex items-center", children: [
2994
+ content,
2995
+ index < items.length - 1 && /* @__PURE__ */ jsx40("span", { className: "mx-2 text-[rgb(var(--nc-fg-soft))]", children: "/" })
2996
+ ] }, `${item.label}-${index}`);
2997
+ }) });
2998
+ }
2999
+
3000
+ // src/components/layout/sidebar.tsx
3001
+ import { jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
3002
+ function Sidebar({ className, title, items, footer, ...props }) {
3003
+ return /* @__PURE__ */ jsxs32(
3004
+ "aside",
3005
+ {
3006
+ className: cn(
3007
+ "flex h-full w-full flex-col gap-6 rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] p-6 text-[rgb(var(--nc-fg))] backdrop-blur-xl",
3008
+ className
3009
+ ),
3010
+ ...props,
3011
+ children: [
3012
+ title && /* @__PURE__ */ jsx41("div", { className: "text-lg font-semibold", children: title }),
3013
+ /* @__PURE__ */ jsx41("nav", { className: "flex flex-col gap-2", children: items.map((item, index) => {
3014
+ var _a;
3015
+ return /* @__PURE__ */ jsxs32(
3016
+ "a",
3017
+ {
3018
+ href: (_a = item.href) != null ? _a : "#",
3019
+ className: cn(
3020
+ "flex items-center gap-3 rounded-2xl px-3 py-2 text-sm transition",
3021
+ item.active ? "bg-[rgb(var(--nc-accent-1)/0.25)] text-[rgb(var(--nc-fg))]" : "text-[rgb(var(--nc-fg-muted))] hover:bg-[rgb(var(--nc-surface)/0.12)] hover:text-[rgb(var(--nc-fg))]"
3022
+ ),
3023
+ children: [
3024
+ item.icon,
3025
+ /* @__PURE__ */ jsx41("span", { children: item.label })
3026
+ ]
3027
+ },
3028
+ `${item.label}-${index}`
3029
+ );
3030
+ }) }),
3031
+ footer && /* @__PURE__ */ jsx41("div", { className: "mt-auto pt-4", children: footer })
3032
+ ]
3033
+ }
3034
+ );
3035
+ }
3036
+
3037
+ // src/components/layout/top-nav.tsx
3038
+ import { jsx as jsx42, jsxs as jsxs33 } from "react/jsx-runtime";
3039
+ function TopNav({ className, title, actions, breadcrumb, ...props }) {
3040
+ return /* @__PURE__ */ jsxs33(
3041
+ "header",
3042
+ {
3043
+ className: cn(
3044
+ "flex flex-wrap items-center justify-between gap-4 rounded-3xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] px-6 py-4 text-[rgb(var(--nc-fg))] backdrop-blur-xl",
3045
+ className
3046
+ ),
3047
+ ...props,
3048
+ children: [
3049
+ /* @__PURE__ */ jsxs33("div", { className: "space-y-1", children: [
3050
+ breadcrumb,
3051
+ title && /* @__PURE__ */ jsx42("div", { className: "text-xl font-semibold", children: title })
3052
+ ] }),
3053
+ actions && /* @__PURE__ */ jsx42("div", { className: "flex flex-wrap gap-3", children: actions })
3054
+ ]
3055
+ }
3056
+ );
3057
+ }
3058
+
3059
+ // src/components/layout/app-template.tsx
3060
+ import { jsx as jsx43 } from "react/jsx-runtime";
3061
+ function AppTemplate({
3062
+ config,
3063
+ headerActions,
3064
+ headerBreadcrumb,
3065
+ sidebarFooter,
3066
+ resolveIcon,
3067
+ icons,
3068
+ activePath,
3069
+ getActivePath,
3070
+ lucideFallback = true,
3071
+ children
3072
+ }) {
3073
+ const sidebarConfig = config.sidebar;
3074
+ const headerConfig = config.header;
3075
+ const resolvedActivePath = activePath != null ? activePath : getActivePath == null ? void 0 : getActivePath();
3076
+ const buildIcon = React23.useCallback(
3077
+ (name) => {
3078
+ if (!name) return void 0;
3079
+ if (resolveIcon) return resolveIcon(name);
3080
+ if (icons == null ? void 0 : icons[name]) return icons[name];
3081
+ return /* @__PURE__ */ jsx43(CraftIcon, { name, useLucide: lucideFallback });
3082
+ },
3083
+ [icons, lucideFallback, resolveIcon]
3084
+ );
3085
+ const sidebarItems = sidebarConfig ? sidebarConfig.items.map((item) => {
3086
+ var _a;
3087
+ return {
3088
+ label: item.label,
3089
+ href: item.href,
3090
+ active: (_a = item.active) != null ? _a : resolvedActivePath && item.href ? item.href === resolvedActivePath : false,
3091
+ icon: buildIcon(item.icon)
3092
+ };
3093
+ }) : null;
3094
+ const breadcrumbNode = headerBreadcrumb != null ? headerBreadcrumb : (headerConfig == null ? void 0 : headerConfig.breadcrumb) ? /* @__PURE__ */ jsx43(Breadcrumbs, { items: headerConfig.breadcrumb }) : null;
3095
+ const sidebarFooterNode = sidebarFooter != null ? sidebarFooter : (sidebarConfig == null ? void 0 : sidebarConfig.footerText) ? /* @__PURE__ */ jsx43("div", { className: "text-xs text-[rgb(var(--nc-fg-muted))]", children: sidebarConfig.footerText }) : null;
3096
+ return /* @__PURE__ */ jsx43(
3097
+ AppShell,
3098
+ {
3099
+ sidebar: sidebarConfig && sidebarItems ? /* @__PURE__ */ jsx43(
3100
+ Sidebar,
3101
+ {
3102
+ title: sidebarConfig.title,
3103
+ items: sidebarItems,
3104
+ footer: sidebarFooterNode
3105
+ }
3106
+ ) : void 0,
3107
+ topNav: headerConfig ? /* @__PURE__ */ jsx43(
3108
+ TopNav,
3109
+ {
3110
+ title: headerConfig.title,
3111
+ breadcrumb: breadcrumbNode,
3112
+ actions: headerActions
3113
+ }
3114
+ ) : void 0,
3115
+ children
3116
+ }
3117
+ );
3118
+ }
3119
+
3120
+ // src/components/layout/layout-config.ts
3121
+ var layoutConfigSchema = {
3122
+ $schema: "https://json-schema.org/draft/2020-12/schema",
3123
+ title: "Nextcraft UI Layout Config",
3124
+ type: "object",
3125
+ additionalProperties: false,
3126
+ properties: {
3127
+ sidebar: {
3128
+ type: "object",
3129
+ additionalProperties: false,
3130
+ properties: {
3131
+ title: { type: "string" },
3132
+ footerText: { type: "string" },
3133
+ items: {
3134
+ type: "array",
3135
+ items: {
3136
+ type: "object",
3137
+ additionalProperties: false,
3138
+ properties: {
3139
+ label: { type: "string" },
3140
+ href: { type: "string" },
3141
+ icon: { type: "string" },
3142
+ active: { type: "boolean" }
3143
+ },
3144
+ required: ["label"]
3145
+ }
3146
+ }
3147
+ },
3148
+ required: ["items"]
3149
+ },
3150
+ header: {
3151
+ type: "object",
3152
+ additionalProperties: false,
3153
+ properties: {
3154
+ title: { type: "string" },
3155
+ breadcrumb: {
3156
+ type: "array",
3157
+ items: {
3158
+ type: "object",
3159
+ additionalProperties: false,
3160
+ properties: {
3161
+ label: { type: "string" },
3162
+ href: { type: "string" }
3163
+ },
3164
+ required: ["label"]
3165
+ }
3166
+ }
3167
+ }
3168
+ }
3169
+ }
3170
+ };
3171
+
3172
+ // src/components/layout/page-header.tsx
3173
+ import { jsx as jsx44, jsxs as jsxs34 } from "react/jsx-runtime";
3174
+ function PageHeader({
3175
+ className,
3176
+ title,
3177
+ description,
3178
+ actions,
3179
+ ...props
3180
+ }) {
3181
+ return /* @__PURE__ */ jsxs34(
3182
+ "div",
3183
+ {
3184
+ className: cn("flex flex-wrap items-start justify-between gap-6", className),
3185
+ ...props,
3186
+ children: [
3187
+ /* @__PURE__ */ jsxs34("div", { className: "space-y-2", children: [
3188
+ /* @__PURE__ */ jsx44("h1", { className: "text-3xl font-bold text-[rgb(var(--nc-fg))]", children: title }),
3189
+ description && /* @__PURE__ */ jsx44("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: description })
3190
+ ] }),
3191
+ actions && /* @__PURE__ */ jsx44("div", { className: "flex flex-wrap gap-3", children: actions })
3192
+ ]
3193
+ }
3194
+ );
3195
+ }
3196
+
3197
+ // src/components/layout/auth-layout.tsx
3198
+ import { jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
3199
+ function AuthLayout({
3200
+ className,
3201
+ title,
3202
+ description,
3203
+ footer,
3204
+ graphic,
3205
+ children,
3206
+ ...props
3207
+ }) {
3208
+ return /* @__PURE__ */ jsxs35(
3209
+ "div",
3210
+ {
3211
+ className: cn(
3212
+ "grid min-h-screen grid-cols-1 bg-background",
3213
+ "lg:grid-cols-[1.1fr_0.9fr]",
3214
+ className
3215
+ ),
3216
+ ...props,
3217
+ children: [
3218
+ /* @__PURE__ */ jsx45("div", { className: "flex flex-col justify-center px-6 py-16 sm:px-12", children: /* @__PURE__ */ jsxs35("div", { className: "mx-auto w-full max-w-md space-y-6", children: [
3219
+ (title || description) && /* @__PURE__ */ jsxs35("div", { className: "space-y-2", children: [
3220
+ title && /* @__PURE__ */ jsx45("h1", { className: "text-3xl font-bold text-[rgb(var(--nc-fg))]", children: title }),
3221
+ description && /* @__PURE__ */ jsx45("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: description })
3222
+ ] }),
3223
+ children,
3224
+ footer && /* @__PURE__ */ jsx45("div", { className: "text-sm text-[rgb(var(--nc-fg-muted))]", children: footer })
3225
+ ] }) }),
3226
+ /* @__PURE__ */ jsx45("div", { className: "hidden items-center justify-center border-l border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] p-12 text-[rgb(var(--nc-fg))] lg:flex", children: graphic != null ? graphic : /* @__PURE__ */ jsxs35("div", { className: "max-w-sm space-y-4 text-center", children: [
3227
+ /* @__PURE__ */ jsx45("h2", { className: "text-2xl font-semibold", children: "Crafted experiences" }),
3228
+ /* @__PURE__ */ jsx45("p", { className: "text-[rgb(var(--nc-fg-muted))]", children: "Build authentication flows that feel premium and cohesive." })
3229
+ ] }) })
3230
+ ]
3231
+ }
3232
+ );
3233
+ }
3234
+
3235
+ // src/components/layout/container.tsx
3236
+ import { jsx as jsx46 } from "react/jsx-runtime";
3237
+ var sizeClasses3 = {
3238
+ sm: "max-w-3xl",
3239
+ md: "max-w-5xl",
3240
+ lg: "max-w-6xl",
3241
+ xl: "max-w-7xl"
3242
+ };
3243
+ function Container({ className, size = "lg", ...props }) {
3244
+ return /* @__PURE__ */ jsx46(
3245
+ "div",
3246
+ {
3247
+ className: cn("mx-auto w-full px-4 sm:px-6 lg:px-8", sizeClasses3[size], className),
3248
+ ...props
3249
+ }
3250
+ );
3251
+ }
3252
+
3253
+ // src/components/layout/grid.tsx
3254
+ import { jsx as jsx47 } from "react/jsx-runtime";
3255
+ var colClasses = {
3256
+ 1: "grid-cols-1",
3257
+ 2: "grid-cols-1 md:grid-cols-2",
3258
+ 3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
3259
+ 4: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
3260
+ 5: "grid-cols-1 md:grid-cols-2 lg:grid-cols-5",
3261
+ 6: "grid-cols-1 md:grid-cols-3 lg:grid-cols-6"
3262
+ };
3263
+ var gapClasses = {
3264
+ sm: "gap-4",
3265
+ md: "gap-6",
3266
+ lg: "gap-8",
3267
+ xl: "gap-10"
3268
+ };
3269
+ function Grid({ className, columns = 3, gap = "md", ...props }) {
3270
+ return /* @__PURE__ */ jsx47("div", { className: cn("grid", colClasses[columns], gapClasses[gap], className), ...props });
3271
+ }
3272
+
3273
+ // src/theme/theme-context.tsx
3274
+ import * as React24 from "react";
3275
+ import { jsx as jsx48 } from "react/jsx-runtime";
3276
+ var THEME_NAMES = [
3277
+ "aurora",
3278
+ "ember",
3279
+ "ocean",
3280
+ "midnight",
3281
+ "cosmic"
3282
+ ];
3283
+ var ThemeContext = React24.createContext(null);
3284
+ var DEFAULT_THEME_KEY = "nextcraft-theme";
3285
+ var DEFAULT_MODE_KEY = "nextcraft-mode";
3286
+ function ThemeProvider({
3287
+ children,
3288
+ defaultTheme = "ocean",
3289
+ defaultMode = "system",
3290
+ storageKeyTheme = DEFAULT_THEME_KEY,
3291
+ storageKeyMode = DEFAULT_MODE_KEY
3292
+ }) {
3293
+ const [theme, setTheme] = React24.useState(defaultTheme);
3294
+ const [mode, setMode] = React24.useState(defaultMode);
3295
+ React24.useEffect(() => {
3296
+ if (typeof window === "undefined") return;
3297
+ try {
3298
+ const storedTheme = window.localStorage.getItem(storageKeyTheme);
3299
+ const storedMode = window.localStorage.getItem(storageKeyMode);
3300
+ if (storedTheme) setTheme(storedTheme);
3301
+ if (storedMode) setMode(storedMode);
3302
+ } catch {
3303
+ }
3304
+ }, [storageKeyTheme, storageKeyMode]);
3305
+ React24.useEffect(() => {
3306
+ if (typeof window === "undefined") return;
3307
+ try {
3308
+ window.localStorage.setItem(storageKeyTheme, theme);
3309
+ window.localStorage.setItem(storageKeyMode, mode);
3310
+ } catch {
3311
+ }
3312
+ }, [theme, mode, storageKeyTheme, storageKeyMode]);
3313
+ React24.useEffect(() => {
3314
+ if (typeof document === "undefined") return;
3315
+ const root = document.documentElement;
3316
+ root.dataset.ncTheme = theme;
3317
+ if (mode !== "system") {
3318
+ root.dataset.ncMode = mode;
3319
+ return;
3320
+ }
3321
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
3322
+ const applySystem = () => {
3323
+ root.dataset.ncMode = mediaQuery.matches ? "dark" : "light";
3324
+ };
3325
+ applySystem();
3326
+ if (typeof mediaQuery.addEventListener === "function") {
3327
+ mediaQuery.addEventListener("change", applySystem);
3328
+ return () => mediaQuery.removeEventListener("change", applySystem);
3329
+ }
3330
+ mediaQuery.addListener(applySystem);
3331
+ return () => mediaQuery.removeListener(applySystem);
3332
+ }, [theme, mode]);
3333
+ const value = React24.useMemo(
3334
+ () => ({ theme, mode, setTheme, setMode }),
3335
+ [theme, mode]
3336
+ );
3337
+ return /* @__PURE__ */ jsx48(ThemeContext.Provider, { value, children });
3338
+ }
3339
+ function useTheme() {
3340
+ const context = React24.useContext(ThemeContext);
3341
+ if (!context) {
3342
+ throw new Error("useTheme must be used within ThemeProvider");
3343
+ }
3344
+ return context;
3345
+ }
3346
+
3347
+ // src/components/theme-switcher.tsx
3348
+ import { jsx as jsx49, jsxs as jsxs36 } from "react/jsx-runtime";
3349
+ var MODE_OPTIONS = ["system", "light", "dark"];
3350
+ function ThemeSwitcher({ className, showLabels = true, ...props }) {
3351
+ const { theme, mode, setTheme, setMode } = useTheme();
3352
+ return /* @__PURE__ */ jsxs36(
3353
+ "div",
3354
+ {
3355
+ className: cn(
3356
+ "flex flex-wrap items-center gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] px-4 py-3 text-sm text-[rgb(var(--nc-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.06)]",
3357
+ className
3358
+ ),
3359
+ ...props,
3360
+ children: [
3361
+ /* @__PURE__ */ jsxs36("label", { className: "flex items-center gap-2", children: [
3362
+ showLabels && /* @__PURE__ */ jsx49("span", { className: "text-[rgb(var(--nc-fg-muted))]", children: "Theme" }),
3363
+ /* @__PURE__ */ jsx49(
3364
+ "select",
3365
+ {
3366
+ className: "rounded-lg border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-[rgb(var(--nc-fg))] outline-none focus:ring-2 focus:ring-[rgb(var(--nc-accent-1)/0.5)]",
3367
+ value: theme,
3368
+ onChange: (event) => setTheme(event.target.value),
3369
+ children: THEME_NAMES.map((name) => /* @__PURE__ */ jsx49("option", { value: name, className: "text-slate-900", children: name }, name))
3370
+ }
3371
+ )
3372
+ ] }),
3373
+ /* @__PURE__ */ jsxs36("label", { className: "flex items-center gap-2", children: [
3374
+ showLabels && /* @__PURE__ */ jsx49("span", { className: "text-[rgb(var(--nc-fg-muted))]", children: "Mode" }),
3375
+ /* @__PURE__ */ jsx49(
3376
+ "select",
3377
+ {
3378
+ className: "rounded-lg border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-[rgb(var(--nc-fg))] outline-none focus:ring-2 focus:ring-[rgb(var(--nc-accent-1)/0.5)]",
3379
+ value: mode,
3380
+ onChange: (event) => setMode(event.target.value),
3381
+ children: MODE_OPTIONS.map((value) => /* @__PURE__ */ jsx49("option", { value, className: "text-slate-900", children: value }, value))
3382
+ }
3383
+ )
3384
+ ] })
3385
+ ]
3386
+ }
3387
+ );
3388
+ }
51
3389
  export {
52
3390
  AppShell,
53
3391
  AppTemplate,