@svadmin/ui 0.29.3 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (444) hide show
  1. package/dist/README.md +18 -0
  2. package/dist/actions.d.ts +35 -0
  3. package/dist/actions.js +84 -0
  4. package/dist/app.css +673 -0
  5. package/dist/component-registry.svelte.d.ts +36 -0
  6. package/dist/component-registry.svelte.js +20 -0
  7. package/dist/components/AICommandBar.svelte +180 -0
  8. package/dist/components/AICommandBar.svelte.d.ts +6 -0
  9. package/dist/components/AboutSettings.svelte +106 -0
  10. package/dist/components/AboutSettings.svelte.d.ts +18 -0
  11. package/dist/components/AdminApp.svelte +205 -0
  12. package/dist/components/AdminApp.svelte.d.ts +28 -0
  13. package/dist/components/AnimatedCounter.svelte +46 -0
  14. package/dist/components/AnimatedCounter.svelte.d.ts +11 -0
  15. package/dist/components/AnomalyBadge.svelte +65 -0
  16. package/dist/components/AnomalyBadge.svelte.d.ts +16 -0
  17. package/dist/components/AppearanceSettings.svelte +183 -0
  18. package/dist/components/AppearanceSettings.svelte.d.ts +3 -0
  19. package/dist/components/AuditLogDrawer.svelte +93 -0
  20. package/dist/components/AuditLogDrawer.svelte.d.ts +8 -0
  21. package/dist/components/AuditLogViewer.svelte +226 -0
  22. package/dist/components/AuditLogViewer.svelte.d.ts +3 -0
  23. package/dist/components/Authenticated.svelte +51 -0
  24. package/dist/components/Authenticated.svelte.d.ts +11 -0
  25. package/dist/components/AutoForm.svelte +244 -0
  26. package/dist/components/AutoForm.svelte.d.ts +20 -0
  27. package/dist/components/AutoSaveIndicator.svelte +35 -0
  28. package/dist/components/AutoSaveIndicator.svelte.d.ts +9 -0
  29. package/dist/components/AutoTable.svelte +839 -0
  30. package/dist/components/AutoTable.svelte.d.ts +44 -0
  31. package/dist/components/Breadcrumbs.svelte +58 -0
  32. package/dist/components/Breadcrumbs.svelte.d.ts +3 -0
  33. package/dist/components/CanAccess.svelte +23 -0
  34. package/dist/components/CanAccess.svelte.d.ts +12 -0
  35. package/dist/components/CatchAllNavigate.svelte +21 -0
  36. package/dist/components/CatchAllNavigate.svelte.d.ts +3 -0
  37. package/dist/components/ChatDialog.svelte +535 -0
  38. package/dist/components/ChatDialog.svelte.d.ts +14 -0
  39. package/dist/components/ComboboxField.svelte +129 -0
  40. package/dist/components/ComboboxField.svelte.d.ts +17 -0
  41. package/dist/components/CommandPalette.svelte +135 -0
  42. package/dist/components/CommandPalette.svelte.d.ts +8 -0
  43. package/dist/components/ConfigErrorScreen.svelte +126 -0
  44. package/dist/components/ConfigErrorScreen.svelte.d.ts +11 -0
  45. package/dist/components/ConfirmDialog.svelte +53 -0
  46. package/dist/components/ConfirmDialog.svelte.d.ts +13 -0
  47. package/dist/components/CopilotPanel.svelte +163 -0
  48. package/dist/components/CopilotPanel.svelte.d.ts +6 -0
  49. package/dist/components/CreatePage.svelte +39 -0
  50. package/dist/components/CreatePage.svelte.d.ts +10 -0
  51. package/dist/components/DevTools.svelte +149 -0
  52. package/dist/components/DevTools.svelte.d.ts +3 -0
  53. package/dist/components/DraggableGrid.svelte +86 -0
  54. package/dist/components/DraggableGrid.svelte.d.ts +17 -0
  55. package/dist/components/DraggableHeader.svelte +112 -0
  56. package/dist/components/DraggableHeader.svelte.d.ts +25 -0
  57. package/dist/components/DrawerForm.svelte +35 -0
  58. package/dist/components/DrawerForm.svelte.d.ts +11 -0
  59. package/dist/components/EditPage.svelte +52 -0
  60. package/dist/components/EditPage.svelte.d.ts +12 -0
  61. package/dist/components/EmptyState.svelte +31 -0
  62. package/dist/components/EmptyState.svelte.d.ts +8 -0
  63. package/dist/components/ErrorBoundary.svelte +49 -0
  64. package/dist/components/ErrorBoundary.svelte.d.ts +12 -0
  65. package/dist/components/ErrorComponent.svelte +36 -0
  66. package/dist/components/ErrorComponent.svelte.d.ts +9 -0
  67. package/dist/components/FieldRenderer.svelte +357 -0
  68. package/dist/components/FieldRenderer.svelte.d.ts +13 -0
  69. package/dist/components/ForgotPasswordPage.svelte +112 -0
  70. package/dist/components/ForgotPasswordPage.svelte.d.ts +6 -0
  71. package/dist/components/Header.svelte +94 -0
  72. package/dist/components/Header.svelte.d.ts +12 -0
  73. package/dist/components/InferencerPanel.svelte +192 -0
  74. package/dist/components/InferencerPanel.svelte.d.ts +3 -0
  75. package/dist/components/InfiniteList.svelte +93 -0
  76. package/dist/components/InfiniteList.svelte.d.ts +20 -0
  77. package/dist/components/InlineEdit.svelte +88 -0
  78. package/dist/components/InlineEdit.svelte.d.ts +12 -0
  79. package/dist/components/InsightCard.svelte +98 -0
  80. package/dist/components/InsightCard.svelte.d.ts +11 -0
  81. package/dist/components/KeyboardShortcuts.svelte +61 -0
  82. package/dist/components/KeyboardShortcuts.svelte.d.ts +6 -0
  83. package/dist/components/Layout.svelte +167 -0
  84. package/dist/components/Layout.svelte.d.ts +12 -0
  85. package/dist/components/ListPage.svelte +71 -0
  86. package/dist/components/ListPage.svelte.d.ts +32 -0
  87. package/dist/components/LiveIndicator.svelte +58 -0
  88. package/dist/components/LiveIndicator.svelte.d.ts +12 -0
  89. package/dist/components/LoginPage.svelte +163 -0
  90. package/dist/components/LoginPage.svelte.d.ts +28 -0
  91. package/dist/components/MarkdownRenderer.svelte +127 -0
  92. package/dist/components/MarkdownRenderer.svelte.d.ts +11 -0
  93. package/dist/components/ModalForm.svelte +38 -0
  94. package/dist/components/ModalForm.svelte.d.ts +10 -0
  95. package/dist/components/NavigateToResource.svelte +20 -0
  96. package/dist/components/NavigateToResource.svelte.d.ts +3 -0
  97. package/dist/components/PageHeader.svelte +39 -0
  98. package/dist/components/PageHeader.svelte.d.ts +11 -0
  99. package/dist/components/PageSkeleton.svelte +71 -0
  100. package/dist/components/PageSkeleton.svelte.d.ts +7 -0
  101. package/dist/components/PasswordInput.svelte +96 -0
  102. package/dist/components/PasswordInput.svelte.d.ts +12 -0
  103. package/dist/components/PermissionMatrix.svelte +185 -0
  104. package/dist/components/PermissionMatrix.svelte.d.ts +19 -0
  105. package/dist/components/ProfilePage.svelte +284 -0
  106. package/dist/components/ProfilePage.svelte.d.ts +3 -0
  107. package/dist/components/RegisterPage.svelte +112 -0
  108. package/dist/components/RegisterPage.svelte.d.ts +7 -0
  109. package/dist/components/RolesSettings.svelte +146 -0
  110. package/dist/components/RolesSettings.svelte.d.ts +3 -0
  111. package/dist/components/SettingsPage.svelte +113 -0
  112. package/dist/components/SettingsPage.svelte.d.ts +3 -0
  113. package/dist/components/ShowPage.svelte +73 -0
  114. package/dist/components/ShowPage.svelte.d.ts +7 -0
  115. package/dist/components/Sidebar.svelte +417 -0
  116. package/dist/components/Sidebar.svelte.d.ts +14 -0
  117. package/dist/components/SidebarItem.svelte +129 -0
  118. package/dist/components/SidebarItem.svelte.d.ts +11 -0
  119. package/dist/components/SmartSuggest.svelte +158 -0
  120. package/dist/components/SmartSuggest.svelte.d.ts +19 -0
  121. package/dist/components/StatsCard.svelte +79 -0
  122. package/dist/components/StatsCard.svelte.d.ts +23 -0
  123. package/dist/components/StepsForm.svelte +194 -0
  124. package/dist/components/StepsForm.svelte.d.ts +13 -0
  125. package/dist/components/TaskQueueDrawer.svelte +158 -0
  126. package/dist/components/TaskQueueDrawer.svelte.d.ts +11 -0
  127. package/dist/components/TenantSwitcher.svelte +84 -0
  128. package/dist/components/TenantSwitcher.svelte.d.ts +12 -0
  129. package/dist/components/ThemedTitle.svelte +32 -0
  130. package/dist/components/ThemedTitle.svelte.d.ts +9 -0
  131. package/dist/components/Toast.svelte +46 -0
  132. package/dist/components/Toast.svelte.d.ts +3 -0
  133. package/dist/components/TooltipButton.svelte +42 -0
  134. package/dist/components/TooltipButton.svelte.d.ts +14 -0
  135. package/dist/components/UndoableNotification.svelte +69 -0
  136. package/dist/components/UndoableNotification.svelte.d.ts +9 -0
  137. package/dist/components/UpdatePasswordPage.svelte +89 -0
  138. package/dist/components/UpdatePasswordPage.svelte.d.ts +6 -0
  139. package/dist/components/VirtualTable.svelte +76 -0
  140. package/dist/components/VirtualTable.svelte.d.ts +27 -0
  141. package/dist/components/VoiceInput.svelte +120 -0
  142. package/dist/components/VoiceInput.svelte.d.ts +15 -0
  143. package/dist/components/buttons/CloneButton.svelte +30 -0
  144. package/dist/components/buttons/CloneButton.svelte.d.ts +13 -0
  145. package/dist/components/buttons/CreateButton.svelte +29 -0
  146. package/dist/components/buttons/CreateButton.svelte.d.ts +12 -0
  147. package/dist/components/buttons/DeleteButton.svelte +59 -0
  148. package/dist/components/buttons/DeleteButton.svelte.d.ts +15 -0
  149. package/dist/components/buttons/EditButton.svelte +30 -0
  150. package/dist/components/buttons/EditButton.svelte.d.ts +13 -0
  151. package/dist/components/buttons/ExportButton.svelte +30 -0
  152. package/dist/components/buttons/ExportButton.svelte.d.ts +12 -0
  153. package/dist/components/buttons/ImportButton.svelte +56 -0
  154. package/dist/components/buttons/ImportButton.svelte.d.ts +19 -0
  155. package/dist/components/buttons/ListButton.svelte +23 -0
  156. package/dist/components/buttons/ListButton.svelte.d.ts +8 -0
  157. package/dist/components/buttons/RefreshButton.svelte +36 -0
  158. package/dist/components/buttons/RefreshButton.svelte.d.ts +8 -0
  159. package/dist/components/buttons/SaveButton.svelte +27 -0
  160. package/dist/components/buttons/SaveButton.svelte.d.ts +9 -0
  161. package/dist/components/buttons/ShowButton.svelte +31 -0
  162. package/dist/components/buttons/ShowButton.svelte.d.ts +13 -0
  163. package/dist/components/buttons/index.d.ts +10 -0
  164. package/dist/components/buttons/index.js +10 -0
  165. package/dist/components/charts/BarChart.svelte +69 -0
  166. package/dist/components/charts/BarChart.svelte.d.ts +15 -0
  167. package/dist/components/charts/LineChart.svelte +115 -0
  168. package/dist/components/charts/LineChart.svelte.d.ts +17 -0
  169. package/dist/components/charts/PieChart.svelte +95 -0
  170. package/dist/components/charts/PieChart.svelte.d.ts +15 -0
  171. package/dist/components/charts/index.d.ts +3 -0
  172. package/dist/components/charts/index.js +3 -0
  173. package/dist/components/fieldComponentMap.d.ts +24 -0
  174. package/dist/components/fieldComponentMap.js +65 -0
  175. package/dist/components/fields/ArrayField.svelte +86 -0
  176. package/dist/components/fields/ArrayField.svelte.d.ts +9 -0
  177. package/dist/components/fields/BooleanField.svelte +13 -0
  178. package/dist/components/fields/BooleanField.svelte.d.ts +8 -0
  179. package/dist/components/fields/DateField.svelte +6 -0
  180. package/dist/components/fields/DateField.svelte.d.ts +8 -0
  181. package/dist/components/fields/EmailField.svelte +9 -0
  182. package/dist/components/fields/EmailField.svelte.d.ts +6 -0
  183. package/dist/components/fields/FileField.svelte +14 -0
  184. package/dist/components/fields/FileField.svelte.d.ts +7 -0
  185. package/dist/components/fields/ImageField.svelte +9 -0
  186. package/dist/components/fields/ImageField.svelte.d.ts +9 -0
  187. package/dist/components/fields/JsonField.svelte +72 -0
  188. package/dist/components/fields/JsonField.svelte.d.ts +6 -0
  189. package/dist/components/fields/MarkdownField.svelte +9 -0
  190. package/dist/components/fields/MarkdownField.svelte.d.ts +6 -0
  191. package/dist/components/fields/MultiSelectField.svelte +21 -0
  192. package/dist/components/fields/MultiSelectField.svelte.d.ts +10 -0
  193. package/dist/components/fields/NumberField.svelte +6 -0
  194. package/dist/components/fields/NumberField.svelte.d.ts +8 -0
  195. package/dist/components/fields/RelationField.svelte +24 -0
  196. package/dist/components/fields/RelationField.svelte.d.ts +8 -0
  197. package/dist/components/fields/RichTextField.svelte +35 -0
  198. package/dist/components/fields/RichTextField.svelte.d.ts +7 -0
  199. package/dist/components/fields/SelectField.svelte +14 -0
  200. package/dist/components/fields/SelectField.svelte.d.ts +10 -0
  201. package/dist/components/fields/TagField.svelte +12 -0
  202. package/dist/components/fields/TagField.svelte.d.ts +6 -0
  203. package/dist/components/fields/TextField.svelte +11 -0
  204. package/dist/components/fields/TextField.svelte.d.ts +7 -0
  205. package/dist/components/fields/UrlField.svelte +14 -0
  206. package/dist/components/fields/UrlField.svelte.d.ts +7 -0
  207. package/dist/components/ui/alert/alert-description.svelte +17 -0
  208. package/dist/components/ui/alert/alert-description.svelte.d.ts +6 -0
  209. package/dist/components/ui/alert/alert-title.svelte +17 -0
  210. package/dist/components/ui/alert/alert-title.svelte.d.ts +6 -0
  211. package/dist/components/ui/alert/alert.svelte +44 -0
  212. package/dist/components/ui/alert/alert.svelte.d.ts +32 -0
  213. package/dist/components/ui/alert/index.d.ts +4 -0
  214. package/dist/components/ui/alert/index.js +5 -0
  215. package/dist/components/ui/alert-dialog/alert-dialog-content.svelte +29 -0
  216. package/dist/components/ui/alert-dialog/alert-dialog-content.svelte.d.ts +10 -0
  217. package/dist/components/ui/alert-dialog/alert-dialog-description.svelte +16 -0
  218. package/dist/components/ui/alert-dialog/alert-dialog-description.svelte.d.ts +7 -0
  219. package/dist/components/ui/alert-dialog/alert-dialog-footer.svelte +11 -0
  220. package/dist/components/ui/alert-dialog/alert-dialog-footer.svelte.d.ts +8 -0
  221. package/dist/components/ui/alert-dialog/alert-dialog-header.svelte +11 -0
  222. package/dist/components/ui/alert-dialog/alert-dialog-header.svelte.d.ts +8 -0
  223. package/dist/components/ui/alert-dialog/alert-dialog-overlay.svelte +16 -0
  224. package/dist/components/ui/alert-dialog/alert-dialog-overlay.svelte.d.ts +7 -0
  225. package/dist/components/ui/alert-dialog/alert-dialog-portal.svelte +6 -0
  226. package/dist/components/ui/alert-dialog/alert-dialog-portal.svelte.d.ts +3 -0
  227. package/dist/components/ui/alert-dialog/alert-dialog-title.svelte +16 -0
  228. package/dist/components/ui/alert-dialog/alert-dialog-title.svelte.d.ts +7 -0
  229. package/dist/components/ui/alert-dialog/index.d.ts +13 -0
  230. package/dist/components/ui/alert-dialog/index.js +13 -0
  231. package/dist/components/ui/avatar/avatar.svelte +63 -0
  232. package/dist/components/ui/avatar/avatar.svelte.d.ts +32 -0
  233. package/dist/components/ui/avatar/index.d.ts +2 -0
  234. package/dist/components/ui/avatar/index.js +2 -0
  235. package/dist/components/ui/badge/badge.svelte +49 -0
  236. package/dist/components/ui/badge/badge.svelte.d.ts +38 -0
  237. package/dist/components/ui/badge/index.d.ts +2 -0
  238. package/dist/components/ui/badge/index.js +3 -0
  239. package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +18 -0
  240. package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte.d.ts +4 -0
  241. package/dist/components/ui/breadcrumb/breadcrumb-item.svelte +15 -0
  242. package/dist/components/ui/breadcrumb/breadcrumb-item.svelte.d.ts +8 -0
  243. package/dist/components/ui/breadcrumb/breadcrumb-link.svelte +15 -0
  244. package/dist/components/ui/breadcrumb/breadcrumb-link.svelte.d.ts +8 -0
  245. package/dist/components/ui/breadcrumb/breadcrumb-list.svelte +15 -0
  246. package/dist/components/ui/breadcrumb/breadcrumb-list.svelte.d.ts +8 -0
  247. package/dist/components/ui/breadcrumb/breadcrumb-page.svelte +18 -0
  248. package/dist/components/ui/breadcrumb/breadcrumb-page.svelte.d.ts +8 -0
  249. package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte +22 -0
  250. package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte.d.ts +8 -0
  251. package/dist/components/ui/breadcrumb/breadcrumb.svelte +11 -0
  252. package/dist/components/ui/breadcrumb/breadcrumb.svelte.d.ts +8 -0
  253. package/dist/components/ui/breadcrumb/index.d.ts +7 -0
  254. package/dist/components/ui/breadcrumb/index.js +7 -0
  255. package/dist/components/ui/button/button.svelte +90 -0
  256. package/dist/components/ui/button/button.svelte.d.ts +70 -0
  257. package/dist/components/ui/button/index.d.ts +2 -0
  258. package/dist/components/ui/button/index.js +5 -0
  259. package/dist/components/ui/card/card-action.svelte +23 -0
  260. package/dist/components/ui/card/card-action.svelte.d.ts +5 -0
  261. package/dist/components/ui/card/card-content.svelte +20 -0
  262. package/dist/components/ui/card/card-content.svelte.d.ts +5 -0
  263. package/dist/components/ui/card/card-description.svelte +20 -0
  264. package/dist/components/ui/card/card-description.svelte.d.ts +5 -0
  265. package/dist/components/ui/card/card-footer.svelte +20 -0
  266. package/dist/components/ui/card/card-footer.svelte.d.ts +5 -0
  267. package/dist/components/ui/card/card-header.svelte +23 -0
  268. package/dist/components/ui/card/card-header.svelte.d.ts +5 -0
  269. package/dist/components/ui/card/card-title.svelte +15 -0
  270. package/dist/components/ui/card/card-title.svelte.d.ts +5 -0
  271. package/dist/components/ui/card/card.svelte +22 -0
  272. package/dist/components/ui/card/card.svelte.d.ts +8 -0
  273. package/dist/components/ui/card/index.d.ts +8 -0
  274. package/dist/components/ui/card/index.js +10 -0
  275. package/dist/components/ui/checkbox/checkbox.svelte +39 -0
  276. package/dist/components/ui/checkbox/checkbox.svelte.d.ts +4 -0
  277. package/dist/components/ui/checkbox/index.d.ts +2 -0
  278. package/dist/components/ui/checkbox/index.js +4 -0
  279. package/dist/components/ui/collapsible/index.d.ts +5 -0
  280. package/dist/components/ui/collapsible/index.js +5 -0
  281. package/dist/components/ui/command/command-dialog.svelte +31 -0
  282. package/dist/components/ui/command/command-dialog.svelte.d.ts +10 -0
  283. package/dist/components/ui/command/index.d.ts +2 -0
  284. package/dist/components/ui/command/index.js +2 -0
  285. package/dist/components/ui/context-menu/index.d.ts +9 -0
  286. package/dist/components/ui/context-menu/index.js +9 -0
  287. package/dist/components/ui/dialog/dialog-close.svelte +11 -0
  288. package/dist/components/ui/dialog/dialog-close.svelte.d.ts +4 -0
  289. package/dist/components/ui/dialog/dialog-content.svelte +48 -0
  290. package/dist/components/ui/dialog/dialog-content.svelte.d.ts +13 -0
  291. package/dist/components/ui/dialog/dialog-description.svelte +17 -0
  292. package/dist/components/ui/dialog/dialog-description.svelte.d.ts +4 -0
  293. package/dist/components/ui/dialog/dialog-footer.svelte +32 -0
  294. package/dist/components/ui/dialog/dialog-footer.svelte.d.ts +8 -0
  295. package/dist/components/ui/dialog/dialog-header.svelte +20 -0
  296. package/dist/components/ui/dialog/dialog-header.svelte.d.ts +5 -0
  297. package/dist/components/ui/dialog/dialog-overlay.svelte +17 -0
  298. package/dist/components/ui/dialog/dialog-overlay.svelte.d.ts +4 -0
  299. package/dist/components/ui/dialog/dialog-portal.svelte +7 -0
  300. package/dist/components/ui/dialog/dialog-portal.svelte.d.ts +3 -0
  301. package/dist/components/ui/dialog/dialog-title.svelte +17 -0
  302. package/dist/components/ui/dialog/dialog-title.svelte.d.ts +4 -0
  303. package/dist/components/ui/dialog/dialog-trigger.svelte +11 -0
  304. package/dist/components/ui/dialog/dialog-trigger.svelte.d.ts +4 -0
  305. package/dist/components/ui/dialog/dialog.svelte +7 -0
  306. package/dist/components/ui/dialog/dialog.svelte.d.ts +3 -0
  307. package/dist/components/ui/dialog/index.d.ts +11 -0
  308. package/dist/components/ui/dialog/index.js +13 -0
  309. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +43 -0
  310. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
  311. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +35 -0
  312. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +8 -0
  313. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +36 -0
  314. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +9 -0
  315. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +10 -0
  316. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +6 -0
  317. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +27 -0
  318. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +11 -0
  319. package/dist/components/ui/dropdown-menu/dropdown-menu.svelte +45 -0
  320. package/dist/components/ui/dropdown-menu/dropdown-menu.svelte.d.ts +9 -0
  321. package/dist/components/ui/dropdown-menu/index.d.ts +7 -0
  322. package/dist/components/ui/dropdown-menu/index.js +7 -0
  323. package/dist/components/ui/input/index.d.ts +2 -0
  324. package/dist/components/ui/input/index.js +4 -0
  325. package/dist/components/ui/input/input.svelte +48 -0
  326. package/dist/components/ui/input/input.svelte.d.ts +13 -0
  327. package/dist/components/ui/label/index.d.ts +1 -0
  328. package/dist/components/ui/label/index.js +1 -0
  329. package/dist/components/ui/label/label.svelte +18 -0
  330. package/dist/components/ui/label/label.svelte.d.ts +5 -0
  331. package/dist/components/ui/pagination/index.d.ts +7 -0
  332. package/dist/components/ui/pagination/index.js +7 -0
  333. package/dist/components/ui/pagination/pagination-content.svelte +11 -0
  334. package/dist/components/ui/pagination/pagination-content.svelte.d.ts +8 -0
  335. package/dist/components/ui/pagination/pagination-ellipsis.svelte +12 -0
  336. package/dist/components/ui/pagination/pagination-ellipsis.svelte.d.ts +4 -0
  337. package/dist/components/ui/pagination/pagination-item.svelte +11 -0
  338. package/dist/components/ui/pagination/pagination-item.svelte.d.ts +8 -0
  339. package/dist/components/ui/pagination/pagination-link.svelte +26 -0
  340. package/dist/components/ui/pagination/pagination-link.svelte.d.ts +9 -0
  341. package/dist/components/ui/pagination/pagination-next.svelte +22 -0
  342. package/dist/components/ui/pagination/pagination-next.svelte.d.ts +8 -0
  343. package/dist/components/ui/pagination/pagination-previous.svelte +22 -0
  344. package/dist/components/ui/pagination/pagination-previous.svelte.d.ts +8 -0
  345. package/dist/components/ui/pagination/pagination.svelte +11 -0
  346. package/dist/components/ui/pagination/pagination.svelte.d.ts +8 -0
  347. package/dist/components/ui/popover/index.d.ts +6 -0
  348. package/dist/components/ui/popover/index.js +6 -0
  349. package/dist/components/ui/popover/popover-content.svelte +25 -0
  350. package/dist/components/ui/popover/popover-content.svelte.d.ts +7 -0
  351. package/dist/components/ui/progress/index.d.ts +1 -0
  352. package/dist/components/ui/progress/index.js +1 -0
  353. package/dist/components/ui/progress/progress.svelte +22 -0
  354. package/dist/components/ui/progress/progress.svelte.d.ts +8 -0
  355. package/dist/components/ui/scroll-area/index.d.ts +1 -0
  356. package/dist/components/ui/scroll-area/index.js +1 -0
  357. package/dist/components/ui/scroll-area/scroll-area.svelte +20 -0
  358. package/dist/components/ui/scroll-area/scroll-area.svelte.d.ts +9 -0
  359. package/dist/components/ui/select/index.d.ts +2 -0
  360. package/dist/components/ui/select/index.js +2 -0
  361. package/dist/components/ui/select/select.svelte +36 -0
  362. package/dist/components/ui/select/select.svelte.d.ts +8 -0
  363. package/dist/components/ui/separator/index.d.ts +2 -0
  364. package/dist/components/ui/separator/index.js +4 -0
  365. package/dist/components/ui/separator/separator.svelte +23 -0
  366. package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
  367. package/dist/components/ui/sheet/index.d.ts +7 -0
  368. package/dist/components/ui/sheet/index.js +7 -0
  369. package/dist/components/ui/sheet/sheet-content.svelte +28 -0
  370. package/dist/components/ui/sheet/sheet-content.svelte.d.ts +8 -0
  371. package/dist/components/ui/sheet/sheet-description.svelte +22 -0
  372. package/dist/components/ui/sheet/sheet-description.svelte.d.ts +6 -0
  373. package/dist/components/ui/sheet/sheet-footer.svelte +22 -0
  374. package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +6 -0
  375. package/dist/components/ui/sheet/sheet-header.svelte +22 -0
  376. package/dist/components/ui/sheet/sheet-header.svelte.d.ts +6 -0
  377. package/dist/components/ui/sheet/sheet-title.svelte +22 -0
  378. package/dist/components/ui/sheet/sheet-title.svelte.d.ts +6 -0
  379. package/dist/components/ui/sheet/sheet.svelte +78 -0
  380. package/dist/components/ui/sheet/sheet.svelte.d.ts +10 -0
  381. package/dist/components/ui/skeleton/index.d.ts +2 -0
  382. package/dist/components/ui/skeleton/index.js +2 -0
  383. package/dist/components/ui/skeleton/skeleton.svelte +21 -0
  384. package/dist/components/ui/skeleton/skeleton.svelte.d.ts +8 -0
  385. package/dist/components/ui/switch/index.d.ts +2 -0
  386. package/dist/components/ui/switch/index.js +2 -0
  387. package/dist/components/ui/switch/switch.svelte +49 -0
  388. package/dist/components/ui/switch/switch.svelte.d.ts +10 -0
  389. package/dist/components/ui/table/index.d.ts +9 -0
  390. package/dist/components/ui/table/index.js +11 -0
  391. package/dist/components/ui/table/table-body.svelte +15 -0
  392. package/dist/components/ui/table/table-body.svelte.d.ts +5 -0
  393. package/dist/components/ui/table/table-caption.svelte +20 -0
  394. package/dist/components/ui/table/table-caption.svelte.d.ts +5 -0
  395. package/dist/components/ui/table/table-cell.svelte +15 -0
  396. package/dist/components/ui/table/table-cell.svelte.d.ts +5 -0
  397. package/dist/components/ui/table/table-footer.svelte +20 -0
  398. package/dist/components/ui/table/table-footer.svelte.d.ts +5 -0
  399. package/dist/components/ui/table/table-head.svelte +15 -0
  400. package/dist/components/ui/table/table-head.svelte.d.ts +5 -0
  401. package/dist/components/ui/table/table-header.svelte +20 -0
  402. package/dist/components/ui/table/table-header.svelte.d.ts +5 -0
  403. package/dist/components/ui/table/table-row.svelte +15 -0
  404. package/dist/components/ui/table/table-row.svelte.d.ts +5 -0
  405. package/dist/components/ui/table/table.svelte +17 -0
  406. package/dist/components/ui/table/table.svelte.d.ts +5 -0
  407. package/dist/components/ui/tabs/index.d.ts +5 -0
  408. package/dist/components/ui/tabs/index.js +5 -0
  409. package/dist/components/ui/tabs/tabs-content.svelte +30 -0
  410. package/dist/components/ui/tabs/tabs-content.svelte.d.ts +9 -0
  411. package/dist/components/ui/tabs/tabs-list.svelte +26 -0
  412. package/dist/components/ui/tabs/tabs-list.svelte.d.ts +6 -0
  413. package/dist/components/ui/tabs/tabs-trigger.svelte +37 -0
  414. package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +9 -0
  415. package/dist/components/ui/tabs/tabs.svelte +27 -0
  416. package/dist/components/ui/tabs/tabs.svelte.d.ts +9 -0
  417. package/dist/components/ui/textarea/index.d.ts +2 -0
  418. package/dist/components/ui/textarea/index.js +2 -0
  419. package/dist/components/ui/textarea/textarea.svelte +24 -0
  420. package/dist/components/ui/textarea/textarea.svelte.d.ts +6 -0
  421. package/dist/components/ui/tooltip/index.d.ts +6 -0
  422. package/dist/components/ui/tooltip/index.js +8 -0
  423. package/dist/components/ui/tooltip/tooltip-content.svelte +52 -0
  424. package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +11 -0
  425. package/dist/components/ui/tooltip/tooltip-portal.svelte +7 -0
  426. package/dist/components/ui/tooltip/tooltip-portal.svelte.d.ts +4 -0
  427. package/dist/components/ui/tooltip/tooltip-provider.svelte +7 -0
  428. package/dist/components/ui/tooltip/tooltip-provider.svelte.d.ts +4 -0
  429. package/dist/components/ui/tooltip/tooltip-trigger.svelte +7 -0
  430. package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +4 -0
  431. package/dist/components/ui/tooltip/tooltip.svelte +10 -0
  432. package/dist/components/ui/tooltip/tooltip.svelte.d.ts +4 -0
  433. package/dist/editor-config.svelte.d.ts +15 -0
  434. package/dist/editor-config.svelte.js +19 -0
  435. package/dist/index.d.ts +117 -0
  436. package/dist/index.js +127 -0
  437. package/dist/markdown-deps.d.ts +21 -0
  438. package/dist/router-state.svelte.d.ts +5 -0
  439. package/dist/router-state.svelte.js +58 -0
  440. package/dist/types.d.ts +42 -0
  441. package/dist/types.js +1 -0
  442. package/dist/utils.d.ts +16 -0
  443. package/dist/utils.js +5 -0
  444. package/package.json +2 -2
@@ -0,0 +1,535 @@
1
+ <script lang="ts">
2
+ import { getChatProvider, getChatContext, setChatContext, getAgentProvider, registerApproval, resolveApproval } from '@svadmin/core';
3
+ import type { ChatMessage, ChatAction, AgentEvent } from '@svadmin/core';
4
+ import { t } from '@svadmin/core/i18n';
5
+ import { useParsed } from '@svadmin/core';
6
+ import { fly, fade, scale } from 'svelte/transition';
7
+ import { Button } from './ui/button/index.js';
8
+ import TooltipButton from './TooltipButton.svelte';
9
+ import { MessageCircle, X, Minus, Send, Loader2, Bot, Trash2, ShieldCheck, ShieldX, Wrench, LayoutDashboard } from '@lucide/svelte';
10
+
11
+ interface Props {
12
+ /** localStorage key for chat history persistence. Set to '' to disable. */
13
+ persistKey?: string;
14
+ /** Custom persistence callback — called when messages change */
15
+ onPersist?: (messages: ChatMessage[]) => void;
16
+ /** Custom restore callback — called on mount to load history */
17
+ onRestore?: () => ChatMessage[];
18
+ /** Callback when user clicks an action button in an assistant message */
19
+ onAction?: (action: ChatAction, message: ChatMessage) => void;
20
+ }
21
+
22
+ const {
23
+ persistKey = 'svadmin-chat',
24
+ onPersist,
25
+ onRestore,
26
+ onAction,
27
+ }: Props = $props();
28
+
29
+ let open = $state(false);
30
+ let minimized = $state(false);
31
+ let inputValue = $state('');
32
+ let messages = $state<ChatMessage[]>([]);
33
+ let isStreaming = $state(false);
34
+ let messagesContainer: HTMLDivElement | undefined = $state();
35
+ let abortController: AbortController | null = null;
36
+ let messageIdCounter = $state(0);
37
+ let initialized = $state(false);
38
+
39
+ const provider = $derived(getChatProvider());
40
+ const agent = $derived(getAgentProvider());
41
+ const parsed = useParsed();
42
+
43
+ /** Track pending approval requests for UI rendering */
44
+ let pendingApprovalIds = $state<string[]>([]);
45
+
46
+ // ─── Auto-update ChatContext from current route ─────────────
47
+ $effect(() => {
48
+ setChatContext({
49
+ currentResource: parsed.resource,
50
+ selectedRecordId: parsed.id,
51
+ currentView: parsed.action as 'list' | 'edit' | 'create' | 'show' | undefined,
52
+ pathname: `/${parsed.resource ?? ''}${parsed.action ? '/' + parsed.action : ''}${parsed.id ? '/' + parsed.id : ''}`,
53
+ });
54
+ });
55
+
56
+ // ─── Restore persisted history on mount ─────────────────────
57
+ $effect(() => {
58
+ if (initialized) return;
59
+ initialized = true;
60
+ if (onRestore) {
61
+ messages = onRestore();
62
+ } else if (persistKey) {
63
+ try {
64
+ const stored = localStorage.getItem(persistKey);
65
+ if (stored) {
66
+ const parsed = JSON.parse(stored) as ChatMessage[];
67
+ if (Array.isArray(parsed) && parsed.length > 0) {
68
+ messages = parsed;
69
+ }
70
+ }
71
+ } catch {
72
+ // ignore corrupt data
73
+ }
74
+ }
75
+ });
76
+
77
+ // ─── Persist on change (debounced) ──────────────────────────
78
+ let persistTimer: ReturnType<typeof setTimeout> | null = null;
79
+
80
+ $effect(() => {
81
+ // Access `messages` to subscribe to changes
82
+ const snapshot = messages;
83
+ if (!initialized) return;
84
+
85
+ if (persistTimer) clearTimeout(persistTimer);
86
+ persistTimer = setTimeout(() => {
87
+ if (onPersist) {
88
+ onPersist(snapshot);
89
+ } else if (persistKey) {
90
+ try {
91
+ localStorage.setItem(persistKey, JSON.stringify(snapshot));
92
+ } catch {
93
+ // storage full or unavailable
94
+ }
95
+ }
96
+ }, 300);
97
+ });
98
+
99
+ function genId(): string {
100
+ messageIdCounter++;
101
+ return `msg-${Date.now()}-${messageIdCounter}`;
102
+ }
103
+
104
+ function scrollToBottom() {
105
+ requestAnimationFrame(() => {
106
+ if (messagesContainer) {
107
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
108
+ }
109
+ });
110
+ }
111
+
112
+ /** Build a system message with the current admin context */
113
+ function buildContextSystemMessage(): ChatMessage | null {
114
+ const ctx = getChatContext();
115
+ if (!ctx.currentResource) return null;
116
+
117
+ const parts: string[] = [];
118
+ parts.push(`Resource: ${ctx.currentResource}`);
119
+ if (ctx.currentView) parts.push(`View: ${ctx.currentView}`);
120
+ if (ctx.selectedRecordId) parts.push(`Selected Record ID: ${ctx.selectedRecordId}`);
121
+ if (ctx.pathname) parts.push(`Path: ${ctx.pathname}`);
122
+
123
+ return {
124
+ id: 'ctx-system',
125
+ role: 'system',
126
+ content: `[Admin Context] ${parts.join(' | ')}`,
127
+ timestamp: Date.now(),
128
+ };
129
+ }
130
+
131
+ async function sendMessage() {
132
+ if (!inputValue.trim() || isStreaming || (!provider && !agent)) return;
133
+
134
+ const userMsg: ChatMessage = {
135
+ id: genId(),
136
+ role: 'user',
137
+ content: inputValue.trim(),
138
+ timestamp: Date.now(),
139
+ };
140
+
141
+ messages = [...messages, userMsg];
142
+ inputValue = '';
143
+ scrollToBottom();
144
+
145
+ // Create placeholder assistant message
146
+ const assistantMsg: ChatMessage = {
147
+ id: genId(),
148
+ role: 'assistant',
149
+ content: '',
150
+ timestamp: Date.now(),
151
+ };
152
+ messages = [...messages, assistantMsg];
153
+ isStreaming = true;
154
+ scrollToBottom();
155
+
156
+ abortController = new AbortController();
157
+
158
+ try {
159
+ // Build message list with context system message prepended
160
+ const contextMsg = buildContextSystemMessage();
161
+ const allMessages = messages.filter((m) => m.content);
162
+ const messagesToSend = contextMsg ? [contextMsg, ...allMessages] : allMessages;
163
+
164
+ if (agent) {
165
+ // ─── AgentProvider path: typed event stream ─────────
166
+ const stream = agent.chat(messagesToSend, {
167
+ signal: abortController.signal,
168
+ context: getChatContext(),
169
+ });
170
+
171
+ const collectedActions: ChatAction[] = [];
172
+
173
+ for await (const event of stream) {
174
+ switch (event.type) {
175
+ case 'text':
176
+ assistantMsg.content += event.content;
177
+ messages = [...messages.slice(0, -1), { ...assistantMsg }];
178
+ scrollToBottom();
179
+ break;
180
+
181
+ case 'tool_call':
182
+ assistantMsg.content += `\n🔧 *${event.tool}*(${JSON.stringify(event.args)})`;
183
+ messages = [...messages.slice(0, -1), { ...assistantMsg }];
184
+ scrollToBottom();
185
+ break;
186
+
187
+ case 'tool_result':
188
+ if (event.result.success) {
189
+ assistantMsg.content += `\n✅ ${event.tool} completed`;
190
+ } else {
191
+ assistantMsg.content += `\n❌ ${event.tool} failed: ${event.result.error ?? 'Unknown error'}`;
192
+ }
193
+ messages = [...messages.slice(0, -1), { ...assistantMsg }];
194
+ scrollToBottom();
195
+ break;
196
+
197
+ case 'approval_request': {
198
+ // Register in the core approval system
199
+ const reqId = event.id;
200
+ pendingApprovalIds = [...pendingApprovalIds, reqId];
201
+
202
+ collectedActions.push(
203
+ {
204
+ label: `✅ ${t('common.confirm') || 'Approve'}: ${event.description}`,
205
+ variant: 'default',
206
+ payload: { approvalId: reqId, approved: true },
207
+ },
208
+ {
209
+ label: `❌ ${t('common.cancel') || 'Reject'}`,
210
+ variant: 'destructive',
211
+ payload: { approvalId: reqId, approved: false },
212
+ },
213
+ );
214
+
215
+ assistantMsg.content += `\n⚠️ **${t('chat.approvalRequired') || 'Approval required'}**: ${event.description}`;
216
+ assistantMsg.actions = [...collectedActions];
217
+ messages = [...messages.slice(0, -1), { ...assistantMsg }];
218
+ scrollToBottom();
219
+ break;
220
+ }
221
+
222
+ case 'component':
223
+ assistantMsg.content += `\n📊 [${event.name}]`;
224
+ messages = [...messages.slice(0, -1), { ...assistantMsg }];
225
+ scrollToBottom();
226
+ break;
227
+
228
+ case 'done':
229
+ break;
230
+ }
231
+ }
232
+ } else if (provider) {
233
+ // ─── ChatProvider path: raw text stream ─────────────
234
+ const result = provider.sendMessage(
235
+ messagesToSend,
236
+ { signal: abortController.signal },
237
+ );
238
+
239
+ if (result && typeof result === 'object' && Symbol.asyncIterator in result) {
240
+ for await (const chunk of result as AsyncGenerator<string>) {
241
+ assistantMsg.content += chunk;
242
+ messages = [...messages.slice(0, -1), { ...assistantMsg }];
243
+ scrollToBottom();
244
+ }
245
+ } else {
246
+ const text = await (result as Promise<string>);
247
+ assistantMsg.content = text;
248
+ messages = [...messages.slice(0, -1), { ...assistantMsg }];
249
+ scrollToBottom();
250
+ }
251
+ }
252
+ } catch (err: unknown) {
253
+ if (err instanceof Error && err.name === 'AbortError') return;
254
+ assistantMsg.content = t('chat.error') || 'Sorry, something went wrong. Please try again.';
255
+ messages = [...messages.slice(0, -1), { ...assistantMsg }];
256
+ } finally {
257
+ isStreaming = false;
258
+ abortController = null;
259
+ scrollToBottom();
260
+ }
261
+ }
262
+
263
+ function stopStreaming() {
264
+ if (abortController) {
265
+ abortController.abort();
266
+ isStreaming = false;
267
+ abortController = null;
268
+ }
269
+ }
270
+
271
+ function clearChat() {
272
+ messages = [];
273
+ isStreaming = false;
274
+ if (abortController) {
275
+ abortController.abort();
276
+ abortController = null;
277
+ }
278
+ // Also clear persisted data
279
+ if (persistKey) {
280
+ try { localStorage.removeItem(persistKey); } catch { /* noop */ }
281
+ }
282
+ }
283
+
284
+ function handleKeydown(e: KeyboardEvent) {
285
+ if (e.key === 'Enter' && !e.shiftKey) {
286
+ e.preventDefault();
287
+ sendMessage();
288
+ }
289
+ }
290
+
291
+ function handleGlobalKeydown(e: KeyboardEvent) {
292
+ if (e.ctrlKey && e.shiftKey && e.key === 'L') {
293
+ e.preventDefault();
294
+ if (open && !minimized) {
295
+ open = false;
296
+ } else {
297
+ open = true;
298
+ minimized = false;
299
+ }
300
+ }
301
+ }
302
+
303
+ function handleAction(action: ChatAction, msg: ChatMessage) {
304
+ // Handle approval actions from AgentProvider
305
+ if (action.payload?.approvalId) {
306
+ const id = action.payload.approvalId as string;
307
+ const approved = action.payload.approved as boolean;
308
+ resolveApproval(id, approved);
309
+ pendingApprovalIds = pendingApprovalIds.filter(pid => pid !== id);
310
+ // Remove action buttons after resolution
311
+ msg.actions = undefined;
312
+ messages = [...messages];
313
+ return;
314
+ }
315
+ if (onAction) {
316
+ onAction(action, msg);
317
+ }
318
+ }
319
+
320
+ /** Simple markdown→html: bold, italic, code blocks, inline code, line breaks */
321
+ function renderMarkdown(text: string): string {
322
+ return text
323
+ .replace(/```(\w*)\n([\s\S]*?)```/g, '<pre class="chat-code-block"><code>$2</code></pre>')
324
+ .replace(/`([^`]+)`/g, '<code class="chat-inline-code">$1</code>')
325
+ .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
326
+ .replace(/\*(.+?)\*/g, '<em>$1</em>')
327
+ .replace(/\n/g, '<br>');
328
+ }
329
+
330
+ const suggestions = $derived([
331
+ t('chat.suggestion1') || 'How do I create a new resource?',
332
+ t('chat.suggestion2') || 'Explain the data model',
333
+ t('chat.suggestion3') || 'Help me write a filter query',
334
+ ]);
335
+ </script>
336
+
337
+ <svelte:window onkeydown={handleGlobalKeydown} />
338
+
339
+ {#if provider || agent}
340
+ <!-- FAB Button -->
341
+ {#if !open}
342
+ <div transition:scale={{ duration: 200 }}>
343
+ <TooltipButton
344
+ tooltip={t('chat.title') || 'AI Assistant'}
345
+ variant="default"
346
+ size="icon"
347
+ class="fixed bottom-4 right-4 sm:bottom-6 sm:right-6 z-[9998] h-12 w-12 rounded-full shadow-xl hover:shadow-2xl hover:scale-110 transition-all bg-primary text-primary-foreground"
348
+ onclick={() => { open = true; minimized = false; }}
349
+ >
350
+ <MessageCircle class="h-5 w-5" />
351
+ {#if messages.length > 0}
352
+ <span class="absolute -top-1 -right-1 h-4 w-4 rounded-full bg-destructive text-[10px] font-bold text-destructive-foreground flex items-center justify-center">
353
+ {messages.filter(m => m.role === 'assistant').length}
354
+ </span>
355
+ {/if}
356
+ </TooltipButton>
357
+ </div>
358
+ {/if}
359
+
360
+ <!-- Chat Panel -->
361
+ {#if open}
362
+ <div
363
+ class="fixed z-[9998] flex flex-col rounded-2xl border bg-card shadow-2xl overflow-hidden bottom-3 right-3 sm:bottom-6 sm:right-6"
364
+ class:w-[calc(100vw-1.5rem)]={!minimized}
365
+ class:sm:w-[400px]={!minimized}
366
+ class:h-[calc(100dvh-6rem)]={!minimized}
367
+ class:sm:h-[560px]={!minimized}
368
+ class:w-[280px]={minimized}
369
+ class:h-auto={minimized}
370
+ transition:fly={{ y: 300, duration: 250 }}
371
+ >
372
+ <!-- Header -->
373
+ <div class="flex items-center justify-between px-4 py-3 bg-primary text-primary-foreground shrink-0">
374
+ <div class="flex items-center gap-2.5">
375
+ <div class="flex items-center justify-center h-7 w-7 rounded-full bg-primary-foreground/20">
376
+ <Bot class="h-4 w-4" />
377
+ </div>
378
+ <div>
379
+ <h3 class="text-sm font-semibold leading-none">
380
+ {t('chat.title') || 'AI Assistant'}
381
+ </h3>
382
+ {#if isStreaming}
383
+ <p class="text-[10px] opacity-80 mt-0.5">{t('chat.typing') || 'Typing...'}</p>
384
+ {/if}
385
+ </div>
386
+ </div>
387
+ <div class="flex items-center gap-0.5">
388
+ {#if messages.length > 0}
389
+ <TooltipButton
390
+ tooltip={t('chat.clear') || 'Clear'}
391
+ variant="ghost"
392
+ size="icon"
393
+ class="h-7 w-7 text-primary-foreground/70 hover:text-primary-foreground hover:bg-primary-foreground/10"
394
+ onclick={clearChat}
395
+ >
396
+ <Trash2 class="h-3.5 w-3.5" />
397
+ </TooltipButton>
398
+ {/if}
399
+ <TooltipButton
400
+ tooltip={minimized ? (t('common.expand') || 'Expand') : (t('common.collapse') || 'Minimize')}
401
+ variant="ghost"
402
+ size="icon"
403
+ class="h-7 w-7 text-primary-foreground/70 hover:text-primary-foreground hover:bg-primary-foreground/10"
404
+ onclick={() => minimized = !minimized}
405
+ >
406
+ <Minus class="h-3.5 w-3.5" />
407
+ </TooltipButton>
408
+ <TooltipButton
409
+ tooltip={t('common.close') || 'Close'}
410
+ variant="ghost"
411
+ size="icon"
412
+ class="h-7 w-7 text-primary-foreground/70 hover:text-primary-foreground hover:bg-primary-foreground/10"
413
+ onclick={() => open = false}
414
+ >
415
+ <X class="h-3.5 w-3.5" />
416
+ </TooltipButton>
417
+ </div>
418
+ </div>
419
+
420
+ {#if !minimized}
421
+ <!-- Messages -->
422
+ <div
423
+ bind:this={messagesContainer}
424
+ class="flex-1 overflow-y-auto p-4 space-y-3 scroll-smooth"
425
+ >
426
+ {#if messages.length === 0}
427
+ <!-- Welcome state -->
428
+ <div class="flex flex-col items-center justify-center h-full text-center px-4" in:fade={{ duration: 200 }}>
429
+ <div class="h-12 w-12 rounded-full bg-primary/10 flex items-center justify-center mb-4">
430
+ <Bot class="h-6 w-6 text-primary" />
431
+ </div>
432
+ <h4 class="text-sm font-semibold text-foreground mb-1">
433
+ {t('chat.welcome') || 'How can I help?'}
434
+ </h4>
435
+ <p class="text-xs text-muted-foreground mb-4">
436
+ {t('chat.welcomeDesc') || 'Ask me anything about your admin panel.'}
437
+ </p>
438
+ <div class="flex flex-col gap-2 w-full max-w-[240px]">
439
+ {#each suggestions as suggestion}
440
+ <button
441
+ class="text-left text-xs px-3 py-2 rounded-lg border border-border hover:bg-accent hover:text-accent-foreground transition-colors cursor-pointer"
442
+ onclick={() => { inputValue = suggestion; }}
443
+ >
444
+ {suggestion}
445
+ </button>
446
+ {/each}
447
+ </div>
448
+ </div>
449
+ {:else}
450
+ {#each messages as msg (msg.id)}
451
+ <div
452
+ class="flex {msg.role === 'user' ? 'justify-end' : 'justify-start'}"
453
+ in:fly={{ y: 10, duration: 150 }}
454
+ >
455
+ <div
456
+ class="max-w-[85%] rounded-2xl px-3.5 py-2.5 text-sm leading-relaxed {msg.role === 'user'
457
+ ? 'bg-primary text-primary-foreground rounded-br-md'
458
+ : 'bg-muted text-foreground rounded-bl-md'}"
459
+ >
460
+ {#if msg.role === 'assistant'}
461
+ {#if msg.content}
462
+ <div class="chat-markdown">{@html renderMarkdown(msg.content)}</div>
463
+ <!-- Action Buttons -->
464
+ {#if msg.actions && msg.actions.length > 0}
465
+ <div class="flex flex-wrap gap-1.5 mt-2 pt-2 border-t border-border/50">
466
+ {#each msg.actions as action}
467
+ <Button
468
+ variant={action.variant ?? 'outline'}
469
+ size="sm"
470
+ class="h-7 text-xs"
471
+ onclick={() => handleAction(action, msg)}
472
+ >
473
+ {action.label}
474
+ </Button>
475
+ {/each}
476
+ </div>
477
+ {/if}
478
+ {:else}
479
+ <div class="flex items-center gap-1.5 text-muted-foreground">
480
+ <Loader2 class="h-3.5 w-3.5 animate-spin" />
481
+ <span class="text-xs">{t('chat.thinking') || 'Thinking...'}</span>
482
+ </div>
483
+ {/if}
484
+ {:else}
485
+ {msg.content}
486
+ {/if}
487
+ </div>
488
+ </div>
489
+ {/each}
490
+ {/if}
491
+ </div>
492
+
493
+ <!-- Input area -->
494
+ <div class="shrink-0 border-t bg-card p-3">
495
+ <div class="flex items-end gap-2">
496
+ <textarea
497
+ bind:value={inputValue}
498
+ onkeydown={handleKeydown}
499
+ placeholder={t('chat.placeholder') || 'Type a message...'}
500
+ rows={1}
501
+ disabled={isStreaming}
502
+ class="flex-1 resize-none rounded-xl border border-input bg-background px-3 py-2.5 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 disabled:opacity-50 max-h-[100px] min-h-[40px]"
503
+ ></textarea>
504
+ {#if isStreaming}
505
+ <Button
506
+ variant="destructive"
507
+ size="icon"
508
+ class="h-10 w-10 rounded-xl shrink-0"
509
+ onclick={stopStreaming}
510
+ >
511
+ <X class="h-4 w-4" />
512
+ </Button>
513
+ {:else}
514
+ <Button
515
+ variant="default"
516
+ size="icon"
517
+ class="h-10 w-10 rounded-xl shrink-0"
518
+ onclick={sendMessage}
519
+ disabled={!inputValue.trim()}
520
+ >
521
+ <Send class="h-4 w-4" />
522
+ </Button>
523
+ {/if}
524
+ </div>
525
+ <p class="text-[10px] text-muted-foreground mt-1.5 text-center">
526
+ <kbd class="px-1 py-0.5 rounded border border-border bg-muted text-[9px] font-mono">Ctrl+Shift+L</kbd>
527
+ {t('chat.shortcutHint') || 'to toggle'}
528
+ </p>
529
+ </div>
530
+ {/if}
531
+ </div>
532
+ {/if}
533
+ {/if}
534
+
535
+
@@ -0,0 +1,14 @@
1
+ import type { ChatMessage, ChatAction } from '@svadmin/core';
2
+ interface Props {
3
+ /** localStorage key for chat history persistence. Set to '' to disable. */
4
+ persistKey?: string;
5
+ /** Custom persistence callback — called when messages change */
6
+ onPersist?: (messages: ChatMessage[]) => void;
7
+ /** Custom restore callback — called on mount to load history */
8
+ onRestore?: () => ChatMessage[];
9
+ /** Callback when user clicks an action button in an assistant message */
10
+ onAction?: (action: ChatAction, message: ChatMessage) => void;
11
+ }
12
+ declare const ChatDialog: import("svelte").Component<Props, {}, "">;
13
+ type ChatDialog = ReturnType<typeof ChatDialog>;
14
+ export default ChatDialog;
@@ -0,0 +1,129 @@
1
+ <script lang="ts">
2
+ import { t } from '@svadmin/core/i18n';
3
+ import { useSelect } from '@svadmin/core';
4
+ import type { Filter } from '@svadmin/core';
5
+ import { Button } from './ui/button/index.js';
6
+ import TooltipButton from './TooltipButton.svelte';
7
+ import { Badge } from './ui/badge/index.js';
8
+ import { Command } from 'cmdk-sv';
9
+ import { Skeleton } from './ui/skeleton/index.js';
10
+ import { ChevronsUpDown, Check, X, Search } from '@lucide/svelte';
11
+
12
+ interface Props {
13
+ resource: string;
14
+ value?: string | number | null;
15
+ onchange?: (value: string | number | null) => void;
16
+ optionLabel?: string;
17
+ optionValue?: string;
18
+ placeholder?: string;
19
+ searchable?: boolean;
20
+ onSearch?: (value: string) => Filter[];
21
+ id?: string;
22
+ class?: string;
23
+ [key: string]: any;
24
+ }
25
+
26
+ let {
27
+ resource,
28
+ value = null,
29
+ onchange,
30
+ optionLabel = 'title',
31
+ optionValue = 'id',
32
+ placeholder = 'Select...',
33
+ searchable = true,
34
+ onSearch,
35
+ ...restProps
36
+ }: Props = $props();
37
+
38
+ const { options, query, onSearchChange } = useSelect({
39
+ get resource() { return resource; },
40
+ get optionLabel() { return optionLabel; },
41
+ get optionValue() { return optionValue; },
42
+ get onSearch() { return onSearch ?? (searchable ? (v: string) => v ? [{ field: optionLabel, operator: 'contains' as const, value: v }] : [] : undefined); },
43
+ });
44
+
45
+ let open = $state(false);
46
+ let searchInputValue = $state('');
47
+
48
+ const selectedLabel = $derived(
49
+ (options as { label: string; value: string | number }[])?.find(
50
+ (o: { label: string; value: string | number }) => o.value === value
51
+ )?.label ?? ''
52
+ );
53
+
54
+ function handleSelect(optValue: string | number) {
55
+ onchange?.(optValue === value ? null : optValue);
56
+ open = false;
57
+ searchInputValue = '';
58
+ }
59
+
60
+ function handleClear(e: Event) {
61
+ e.stopPropagation();
62
+ onchange?.(null);
63
+ }
64
+
65
+ function handleSearchInput(e: Event) {
66
+ const v = (e.currentTarget as HTMLInputElement).value;
67
+ searchInputValue = v;
68
+ onSearchChange(v);
69
+ }
70
+ </script>
71
+
72
+ <div class="relative">
73
+ <Button
74
+ variant="outline"
75
+ type="button"
76
+ class="w-full justify-between font-normal"
77
+ onclick={() => { open = !open; }}
78
+ {...restProps}
79
+ >
80
+ {#if selectedLabel}
81
+ <span class="truncate">{selectedLabel}</span>
82
+ <TooltipButton tooltip={t('common.clear')} size="icon-sm" class="h-5 w-5 ml-1" onclick={handleClear}>
83
+ <X class="h-3 w-3" />
84
+ </TooltipButton>
85
+ {:else}
86
+ <span class="text-muted-foreground">{placeholder}</span>
87
+ {/if}
88
+ <ChevronsUpDown class="ml-auto h-4 w-4 shrink-0 opacity-50" />
89
+ </Button>
90
+
91
+ {#if open}
92
+ <div class="absolute z-50 mt-1 w-full rounded-md border bg-popover shadow-lg">
93
+ <Command.Root class="flex flex-col overflow-hidden rounded-md bg-popover text-popover-foreground">
94
+ {#if searchable}
95
+ <div class="flex items-center border-b px-2">
96
+ <Search class="mr-1.5 h-3.5 w-3.5 shrink-0 opacity-50" />
97
+ <Command.Input
98
+ bind:value={searchInputValue}
99
+ oninput={handleSearchInput}
100
+ placeholder="Search..."
101
+ class="flex h-9 w-full bg-transparent py-2 text-sm outline-none placeholder:text-muted-foreground"
102
+ />
103
+ </div>
104
+ {/if}
105
+ <Command.List class="max-h-48 overflow-y-auto p-1">
106
+ <Command.Empty class="py-4 text-center text-xs text-muted-foreground">
107
+ No results.
108
+ </Command.Empty>
109
+ {#if query.isLoading}
110
+ {#each Array(3) as _}
111
+ <div class="px-2 py-1.5"><Skeleton class="h-5 w-full" /></div>
112
+ {/each}
113
+ {:else}
114
+ {#each (options as { label: string; value: string | number }[]) ?? [] as opt}
115
+ <Command.Item
116
+ value={opt.label}
117
+ onSelect={() => handleSelect(opt.value)}
118
+ class="relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground"
119
+ >
120
+ <Check class="mr-2 h-3.5 w-3.5 {value === opt.value ? 'opacity-100' : 'opacity-0'}" />
121
+ {opt.label}
122
+ </Command.Item>
123
+ {/each}
124
+ {/if}
125
+ </Command.List>
126
+ </Command.Root>
127
+ </div>
128
+ {/if}
129
+ </div>
@@ -0,0 +1,17 @@
1
+ import type { Filter } from '@svadmin/core';
2
+ interface Props {
3
+ resource: string;
4
+ value?: string | number | null;
5
+ onchange?: (value: string | number | null) => void;
6
+ optionLabel?: string;
7
+ optionValue?: string;
8
+ placeholder?: string;
9
+ searchable?: boolean;
10
+ onSearch?: (value: string) => Filter[];
11
+ id?: string;
12
+ class?: string;
13
+ [key: string]: any;
14
+ }
15
+ declare const ComboboxField: import("svelte").Component<Props, {}, "">;
16
+ type ComboboxField = ReturnType<typeof ComboboxField>;
17
+ export default ComboboxField;