@questpie/admin 0.0.1 → 1.0.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 (250) hide show
  1. package/README.md +439 -424
  2. package/dist/auth-layout-M8K8_q5R.mjs +181 -0
  3. package/dist/auth-layout-M8K8_q5R.mjs.map +1 -0
  4. package/dist/bulk-upload-dialog-h7zXD78Y.mjs +274 -0
  5. package/dist/bulk-upload-dialog-h7zXD78Y.mjs.map +1 -0
  6. package/dist/{components/ui/card.mjs → card-BKHjBQfw.mjs} +8 -8
  7. package/dist/card-BKHjBQfw.mjs.map +1 -0
  8. package/dist/client/styles/index.css +434 -0
  9. package/dist/client-BCGpkAz6.mjs +22635 -0
  10. package/dist/client-BCGpkAz6.mjs.map +1 -0
  11. package/dist/client-CcWZbkBP.d.mts +13585 -0
  12. package/dist/client-CcWZbkBP.d.mts.map +1 -0
  13. package/dist/client.d.mts +3 -0
  14. package/dist/client.mjs +14 -0
  15. package/dist/content-locales-provider-BXvuIgfg.mjs +1650 -0
  16. package/dist/content-locales-provider-BXvuIgfg.mjs.map +1 -0
  17. package/dist/dashboard-page-B4PGEdc2.mjs +2500 -0
  18. package/dist/dashboard-page-B4PGEdc2.mjs.map +1 -0
  19. package/dist/dashboard-page-CVlyR40m.mjs +6 -0
  20. package/dist/dropzone-Do3awXKd.mjs +634 -0
  21. package/dist/dropzone-Do3awXKd.mjs.map +1 -0
  22. package/dist/{views/auth/forgot-password-form.mjs → forgot-password-page-Bcp-An4Y.mjs} +87 -14
  23. package/dist/forgot-password-page-Bcp-An4Y.mjs.map +1 -0
  24. package/dist/forgot-password-page-CIILVhfo.mjs +7 -0
  25. package/dist/index-B9Xwk4hi.d.mts +2753 -0
  26. package/dist/index-B9Xwk4hi.d.mts.map +1 -0
  27. package/dist/index.d.mts +3 -0
  28. package/dist/index.mjs +14 -0
  29. package/dist/login-page-8K7fo0qK.mjs +7 -0
  30. package/dist/login-page-CP4gA-dl.mjs +298 -0
  31. package/dist/login-page-CP4gA-dl.mjs.map +1 -0
  32. package/dist/preview-utils-BKQ9-TMa.mjs +65 -0
  33. package/dist/preview-utils-BKQ9-TMa.mjs.map +1 -0
  34. package/dist/{views/auth/reset-password-form.mjs → reset-password-page-BqfDmLxA.mjs} +111 -14
  35. package/dist/reset-password-page-BqfDmLxA.mjs.map +1 -0
  36. package/dist/reset-password-page-DLATv0xQ.mjs +7 -0
  37. package/dist/runtime-6VZM878K.mjs +69 -0
  38. package/dist/runtime-6VZM878K.mjs.map +1 -0
  39. package/dist/saved-views.types-BMsz5mCy.d.mts +42 -0
  40. package/dist/saved-views.types-BMsz5mCy.d.mts.map +1 -0
  41. package/dist/server.d.mts +250 -0
  42. package/dist/server.d.mts.map +1 -0
  43. package/dist/server.mjs +832 -0
  44. package/dist/server.mjs.map +1 -0
  45. package/dist/setup-page-CMZ5P_OE.mjs +6 -0
  46. package/dist/setup-page-YAP_fzqh.mjs +264 -0
  47. package/dist/setup-page-YAP_fzqh.mjs.map +1 -0
  48. package/dist/shared.d.mts +57 -0
  49. package/dist/shared.d.mts.map +1 -0
  50. package/dist/shared.mjs +3 -0
  51. package/dist/{hooks/use-auth.mjs → use-auth-BoLmWtmU.mjs} +42 -30
  52. package/dist/use-auth-BoLmWtmU.mjs.map +1 -0
  53. package/package.json +48 -197
  54. package/.turbo/turbo-build.log +0 -108
  55. package/CHANGELOG.md +0 -10
  56. package/STATUS.md +0 -917
  57. package/VALIDATION.md +0 -602
  58. package/components.json +0 -24
  59. package/dist/__tests__/setup.mjs +0 -38
  60. package/dist/__tests__/test-utils.mjs +0 -45
  61. package/dist/__tests__/vitest.d.mjs +0 -3
  62. package/dist/components/admin-app.mjs +0 -69
  63. package/dist/components/fields/array-field.mjs +0 -190
  64. package/dist/components/fields/checkbox-field.mjs +0 -34
  65. package/dist/components/fields/custom-field.mjs +0 -32
  66. package/dist/components/fields/date-field.mjs +0 -41
  67. package/dist/components/fields/datetime-field.mjs +0 -42
  68. package/dist/components/fields/email-field.mjs +0 -37
  69. package/dist/components/fields/embedded-collection.mjs +0 -253
  70. package/dist/components/fields/field-types.mjs +0 -1
  71. package/dist/components/fields/field-utils.mjs +0 -10
  72. package/dist/components/fields/field-wrapper.mjs +0 -34
  73. package/dist/components/fields/index.mjs +0 -23
  74. package/dist/components/fields/json-field.mjs +0 -243
  75. package/dist/components/fields/locale-badge.mjs +0 -16
  76. package/dist/components/fields/number-field.mjs +0 -39
  77. package/dist/components/fields/password-field.mjs +0 -37
  78. package/dist/components/fields/relation-field.mjs +0 -104
  79. package/dist/components/fields/relation-picker.mjs +0 -229
  80. package/dist/components/fields/relation-select.mjs +0 -188
  81. package/dist/components/fields/rich-text-editor/index.mjs +0 -897
  82. package/dist/components/fields/select-field.mjs +0 -41
  83. package/dist/components/fields/switch-field.mjs +0 -34
  84. package/dist/components/fields/text-field.mjs +0 -38
  85. package/dist/components/fields/textarea-field.mjs +0 -38
  86. package/dist/components/index.mjs +0 -59
  87. package/dist/components/primitives/checkbox-input.mjs +0 -127
  88. package/dist/components/primitives/date-input.mjs +0 -303
  89. package/dist/components/primitives/index.mjs +0 -12
  90. package/dist/components/primitives/number-input.mjs +0 -104
  91. package/dist/components/primitives/select-input.mjs +0 -177
  92. package/dist/components/primitives/tag-input.mjs +0 -135
  93. package/dist/components/primitives/text-input.mjs +0 -39
  94. package/dist/components/primitives/textarea-input.mjs +0 -37
  95. package/dist/components/primitives/toggle-input.mjs +0 -31
  96. package/dist/components/primitives/types.mjs +0 -12
  97. package/dist/components/ui/accordion.mjs +0 -55
  98. package/dist/components/ui/avatar.mjs +0 -54
  99. package/dist/components/ui/badge.mjs +0 -34
  100. package/dist/components/ui/button.mjs +0 -48
  101. package/dist/components/ui/checkbox.mjs +0 -21
  102. package/dist/components/ui/combobox.mjs +0 -163
  103. package/dist/components/ui/dialog.mjs +0 -95
  104. package/dist/components/ui/dropdown-menu.mjs +0 -138
  105. package/dist/components/ui/field.mjs +0 -113
  106. package/dist/components/ui/input-group.mjs +0 -82
  107. package/dist/components/ui/input.mjs +0 -17
  108. package/dist/components/ui/label.mjs +0 -15
  109. package/dist/components/ui/popover.mjs +0 -56
  110. package/dist/components/ui/scroll-area.mjs +0 -38
  111. package/dist/components/ui/select.mjs +0 -100
  112. package/dist/components/ui/separator.mjs +0 -16
  113. package/dist/components/ui/sheet.mjs +0 -90
  114. package/dist/components/ui/sidebar.mjs +0 -387
  115. package/dist/components/ui/skeleton.mjs +0 -14
  116. package/dist/components/ui/spinner.mjs +0 -16
  117. package/dist/components/ui/switch.mjs +0 -22
  118. package/dist/components/ui/table.mjs +0 -68
  119. package/dist/components/ui/tabs.mjs +0 -48
  120. package/dist/components/ui/textarea.mjs +0 -15
  121. package/dist/components/ui/tooltip.mjs +0 -44
  122. package/dist/config/component-registry.mjs +0 -38
  123. package/dist/config/index.mjs +0 -129
  124. package/dist/hooks/admin-provider.mjs +0 -70
  125. package/dist/hooks/index.mjs +0 -7
  126. package/dist/hooks/store.mjs +0 -178
  127. package/dist/hooks/use-collection-db.mjs +0 -146
  128. package/dist/hooks/use-collection.mjs +0 -112
  129. package/dist/hooks/use-global.mjs +0 -46
  130. package/dist/hooks/use-mobile.mjs +0 -20
  131. package/dist/lib/utils.mjs +0 -10
  132. package/dist/styles/index.css +0 -336
  133. package/dist/styles/index.mjs +0 -1
  134. package/dist/utils/index.mjs +0 -9
  135. package/dist/views/auth/auth-layout.mjs +0 -52
  136. package/dist/views/auth/index.mjs +0 -6
  137. package/dist/views/auth/login-form.mjs +0 -156
  138. package/dist/views/collection/auto-form-fields.mjs +0 -525
  139. package/dist/views/collection/collection-form.mjs +0 -91
  140. package/dist/views/collection/collection-list.mjs +0 -76
  141. package/dist/views/collection/form-field.mjs +0 -42
  142. package/dist/views/collection/index.mjs +0 -6
  143. package/dist/views/common/index.mjs +0 -4
  144. package/dist/views/common/locale-switcher.mjs +0 -39
  145. package/dist/views/common/version-history.mjs +0 -272
  146. package/dist/views/index.mjs +0 -9
  147. package/dist/views/layout/admin-layout.mjs +0 -40
  148. package/dist/views/layout/admin-router.mjs +0 -95
  149. package/dist/views/layout/admin-sidebar.mjs +0 -63
  150. package/dist/views/layout/index.mjs +0 -5
  151. package/src/__tests__/setup.ts +0 -44
  152. package/src/__tests__/test-utils.tsx +0 -49
  153. package/src/__tests__/vitest.d.ts +0 -9
  154. package/src/components/admin-app.tsx +0 -221
  155. package/src/components/fields/array-field.tsx +0 -237
  156. package/src/components/fields/checkbox-field.tsx +0 -47
  157. package/src/components/fields/custom-field.tsx +0 -50
  158. package/src/components/fields/date-field.tsx +0 -65
  159. package/src/components/fields/datetime-field.tsx +0 -67
  160. package/src/components/fields/email-field.tsx +0 -51
  161. package/src/components/fields/embedded-collection.tsx +0 -315
  162. package/src/components/fields/field-types.ts +0 -162
  163. package/src/components/fields/field-utils.ts +0 -6
  164. package/src/components/fields/field-wrapper.tsx +0 -52
  165. package/src/components/fields/index.ts +0 -66
  166. package/src/components/fields/json-field.tsx +0 -440
  167. package/src/components/fields/locale-badge.tsx +0 -15
  168. package/src/components/fields/number-field.tsx +0 -57
  169. package/src/components/fields/password-field.tsx +0 -51
  170. package/src/components/fields/relation-field.tsx +0 -243
  171. package/src/components/fields/relation-picker.tsx +0 -402
  172. package/src/components/fields/relation-select.tsx +0 -327
  173. package/src/components/fields/rich-text-editor/index.tsx +0 -1337
  174. package/src/components/fields/select-field.tsx +0 -61
  175. package/src/components/fields/switch-field.tsx +0 -47
  176. package/src/components/fields/text-field.tsx +0 -55
  177. package/src/components/fields/textarea-field.tsx +0 -55
  178. package/src/components/index.ts +0 -40
  179. package/src/components/primitives/checkbox-input.tsx +0 -193
  180. package/src/components/primitives/date-input.tsx +0 -401
  181. package/src/components/primitives/index.ts +0 -24
  182. package/src/components/primitives/number-input.tsx +0 -132
  183. package/src/components/primitives/select-input.tsx +0 -296
  184. package/src/components/primitives/tag-input.tsx +0 -200
  185. package/src/components/primitives/text-input.tsx +0 -49
  186. package/src/components/primitives/textarea-input.tsx +0 -46
  187. package/src/components/primitives/toggle-input.tsx +0 -36
  188. package/src/components/primitives/types.ts +0 -235
  189. package/src/components/ui/accordion.tsx +0 -72
  190. package/src/components/ui/avatar.tsx +0 -106
  191. package/src/components/ui/badge.tsx +0 -48
  192. package/src/components/ui/button.tsx +0 -53
  193. package/src/components/ui/card.tsx +0 -94
  194. package/src/components/ui/checkbox.tsx +0 -27
  195. package/src/components/ui/combobox.tsx +0 -290
  196. package/src/components/ui/dialog.tsx +0 -151
  197. package/src/components/ui/dropdown-menu.tsx +0 -254
  198. package/src/components/ui/field.tsx +0 -227
  199. package/src/components/ui/input-group.tsx +0 -149
  200. package/src/components/ui/input.tsx +0 -20
  201. package/src/components/ui/label.tsx +0 -18
  202. package/src/components/ui/popover.tsx +0 -88
  203. package/src/components/ui/scroll-area.tsx +0 -53
  204. package/src/components/ui/select.tsx +0 -192
  205. package/src/components/ui/separator.tsx +0 -23
  206. package/src/components/ui/sheet.tsx +0 -127
  207. package/src/components/ui/sidebar.tsx +0 -723
  208. package/src/components/ui/skeleton.tsx +0 -13
  209. package/src/components/ui/spinner.tsx +0 -10
  210. package/src/components/ui/switch.tsx +0 -32
  211. package/src/components/ui/table.tsx +0 -99
  212. package/src/components/ui/tabs.tsx +0 -82
  213. package/src/components/ui/textarea.tsx +0 -18
  214. package/src/components/ui/tooltip.tsx +0 -70
  215. package/src/config/component-registry.ts +0 -190
  216. package/src/config/index.ts +0 -1099
  217. package/src/hooks/README.md +0 -269
  218. package/src/hooks/admin-provider.tsx +0 -110
  219. package/src/hooks/index.ts +0 -41
  220. package/src/hooks/store.ts +0 -248
  221. package/src/hooks/use-auth.ts +0 -168
  222. package/src/hooks/use-collection-db.ts +0 -209
  223. package/src/hooks/use-collection.ts +0 -156
  224. package/src/hooks/use-global.ts +0 -69
  225. package/src/hooks/use-mobile.ts +0 -21
  226. package/src/lib/utils.ts +0 -6
  227. package/src/styles/index.css +0 -340
  228. package/src/utils/index.ts +0 -6
  229. package/src/views/auth/auth-layout.tsx +0 -77
  230. package/src/views/auth/forgot-password-form.tsx +0 -192
  231. package/src/views/auth/index.ts +0 -21
  232. package/src/views/auth/login-form.tsx +0 -229
  233. package/src/views/auth/reset-password-form.tsx +0 -232
  234. package/src/views/collection/auto-form-fields.tsx +0 -982
  235. package/src/views/collection/collection-form.tsx +0 -186
  236. package/src/views/collection/collection-list.tsx +0 -223
  237. package/src/views/collection/form-field.tsx +0 -52
  238. package/src/views/collection/index.ts +0 -15
  239. package/src/views/common/index.ts +0 -8
  240. package/src/views/common/locale-switcher.tsx +0 -45
  241. package/src/views/common/version-history.tsx +0 -406
  242. package/src/views/index.ts +0 -25
  243. package/src/views/layout/admin-layout.tsx +0 -117
  244. package/src/views/layout/admin-router.tsx +0 -206
  245. package/src/views/layout/admin-sidebar.tsx +0 -185
  246. package/src/views/layout/index.ts +0 -12
  247. package/tsconfig.json +0 -13
  248. package/tsconfig.tsbuildinfo +0 -1
  249. package/tsdown.config.ts +0 -13
  250. package/vitest.config.ts +0 -29
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-page-B4PGEdc2.mjs","names":["Accordion","AccordionPrimitive","Tabs","TabsPrimitive","React","variantStyles: Record<WidgetCardVariant, string>","variantContentStyles: Record<WidgetCardVariant, string>","variantStyles","React","key: string","variantStyles","variantStyles","result: Record<string, any>","queryOptions: any","React","gridClasses: Record<number, string>","spanClasses: Record<number, string>","Accordion","Tabs"],"sources":["../src/client/components/ui/badge.tsx","../src/client/views/collection/cells/primitive-cells.tsx","../src/client/components/ui/accordion.tsx","../src/client/components/ui/tabs.tsx","../src/client/hooks/use-collection.ts","../src/client/components/ui/skeleton.tsx","../src/client/components/error-boundary.tsx","../src/client/views/dashboard/widget-card.tsx","../src/client/components/widgets/widget-skeletons.tsx","../src/client/components/widgets/chart-widget.tsx","../src/client/components/widgets/progress-widget.tsx","../src/client/components/widgets/quick-actions-widget.tsx","../src/client/components/widgets/recent-items-widget.tsx","../src/client/components/widgets/stats-widget.tsx","../src/client/components/widgets/table-widget.tsx","../src/client/components/widgets/timeline-widget.tsx","../src/client/components/widgets/value-widget.tsx","../src/client/views/dashboard/dashboard-widget.tsx","../src/client/views/dashboard/dashboard-grid.tsx","../src/client/views/pages/dashboard-page.tsx"],"sourcesContent":["import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"../../lib/utils\";\n\nconst badgeVariants = cva(\n \"h-5 gap-1 rounded-none border border-transparent px-2 py-0.5 text-[0.625rem] font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-2.5! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary/10 text-primary border-primary border backdrop-blur-sm [a]:hover:bg-primary/80\",\n secondary:\n \"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80\",\n destructive:\n \"bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20\",\n outline:\n \"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground bg-input/20 \",\n ghost:\n \"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction Badge({\n className,\n variant = \"default\",\n render,\n ...props\n}: useRender.ComponentProps<\"span\"> & VariantProps<typeof badgeVariants>) {\n return useRender({\n defaultTagName: \"span\",\n props: mergeProps<\"span\">(\n {\n className: cn(badgeVariants({ className, variant })),\n },\n props,\n ),\n render,\n state: {\n slot: \"badge\",\n variant,\n },\n });\n}\n\nexport { Badge, badgeVariants };\n","/**\n * Primitive Cell Components\n *\n * Simple cell renderers for basic data types:\n * - Text, Number, Boolean\n * - Date, DateTime, Time\n * - Email, Select\n * - DefaultCell (ultra-simple fallback)\n */\n\nimport * as React from \"react\";\nimport { Badge } from \"../../../components/ui/badge\";\n\n// ============================================================================\n// Default Cell (Ultra-Simple Fallback)\n// ============================================================================\n\n/**\n * Ultra-simple default cell renderer\n * Used as fallback when field has no .cell defined\n */\nexport function DefaultCell({ value }: { value: unknown }) {\n\tif (value === null || value === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\treturn <span>{String(value)}</span>;\n}\n\n// ============================================================================\n// Text Cells\n// ============================================================================\n\n/**\n * Text cell - simple text display with truncation\n */\nexport function TextCell({ value }: { value: unknown }) {\n\tif (value === null || value === undefined || value === \"\") {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\tconst text = String(value);\n\treturn (\n\t\t<span className=\"truncate max-w-[300px] block\" title={text}>\n\t\t\t{text}\n\t\t</span>\n\t);\n}\n\nfunction stripHtmlTags(value: string): string {\n\treturn value\n\t\t.replace(/<[^>]*>/g, \" \")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n}\n\nfunction extractTextFromNode(node: any): string {\n\tif (!node) return \"\";\n\tif (Array.isArray(node)) {\n\t\treturn node.map(extractTextFromNode).filter(Boolean).join(\" \");\n\t}\n\tif (typeof node.text === \"string\") return node.text;\n\tif (Array.isArray(node.content)) {\n\t\treturn node.content.map(extractTextFromNode).filter(Boolean).join(\" \");\n\t}\n\treturn \"\";\n}\n\nfunction getRichTextPreview(value: unknown): string {\n\tif (value === null || value === undefined) return \"\";\n\tif (typeof value === \"string\") {\n\t\tconst hasHtml = /<\\/?[a-z][\\s\\S]*>/i.test(value);\n\t\treturn hasHtml ? stripHtmlTags(value) : value.trim();\n\t}\n\tif (typeof value === \"object\") {\n\t\tconst text = extractTextFromNode(value);\n\t\treturn text.replace(/\\s+/g, \" \").trim();\n\t}\n\treturn String(value);\n}\n\nexport function RichTextCell({ value }: { value: unknown }) {\n\tconst text = getRichTextPreview(value);\n\tif (!text) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\treturn (\n\t\t<span className=\"truncate max-w-[300px] block\" title={text}>\n\t\t\t{text}\n\t\t</span>\n\t);\n}\n\n// ============================================================================\n// Number Cell\n// ============================================================================\n\n/**\n * Number cell - right-aligned number display\n */\nexport function NumberCell({ value }: { value: unknown }) {\n\tif (value === null || value === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\tconst num = Number(value);\n\treturn (\n\t\t<span className=\"tabular-nums\">\n\t\t\t{Number.isNaN(num) ? String(value) : num.toLocaleString()}\n\t\t</span>\n\t);\n}\n\n// ============================================================================\n// Boolean Cell\n// ============================================================================\n\n/**\n * Boolean cell - badge display\n */\nexport function BooleanCell({ value }: { value: unknown }) {\n\treturn (\n\t\t<Badge variant={value ? \"default\" : \"secondary\"}>\n\t\t\t{value ? \"Yes\" : \"No\"}\n\t\t</Badge>\n\t);\n}\n\n// ============================================================================\n// Date/Time Cells\n// ============================================================================\n\n/**\n * Date cell - formatted date display\n */\nexport function DateCell({ value }: { value: unknown }) {\n\tif (value === null || value === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\tconst date = value instanceof Date ? value : new Date(String(value));\n\tif (Number.isNaN(date.getTime())) {\n\t\treturn <span className=\"text-muted-foreground\">{String(value)}</span>;\n\t}\n\treturn <span className=\"tabular-nums\">{date.toLocaleDateString()}</span>;\n}\n\n/**\n * DateTime cell - formatted date and time display\n */\nexport function DateTimeCell({ value }: { value: unknown }) {\n\tif (value === null || value === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\tconst date = value instanceof Date ? value : new Date(String(value));\n\tif (Number.isNaN(date.getTime())) {\n\t\treturn <span className=\"text-muted-foreground\">{String(value)}</span>;\n\t}\n\treturn (\n\t\t<span className=\"tabular-nums\">\n\t\t\t{date.toLocaleDateString()} {date.toLocaleTimeString()}\n\t\t</span>\n\t);\n}\n\n/**\n * Time cell - formatted time display (for time-only values stored as string)\n */\nexport function TimeCell({ value }: { value: unknown }) {\n\tif (value === null || value === undefined || value === \"\") {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\t// Time values are stored as \"HH:mm\" or \"HH:mm:ss\" strings\n\treturn <span className=\"tabular-nums\">{String(value)}</span>;\n}\n\n// ============================================================================\n// Special Text Cells\n// ============================================================================\n\n/**\n * Email cell - displays email with mailto link styling\n */\nexport function EmailCell({ value }: { value: unknown }) {\n\tif (value === null || value === undefined || value === \"\") {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\treturn <span className=\"text-primary\">{String(value)}</span>;\n}\n\n/**\n * Select/Status cell - badge display\n */\nexport function SelectCell({ value }: { value: unknown }) {\n\tif (value === null || value === undefined || value === \"\") {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\treturn <Badge variant=\"outline\">{String(value)}</Badge>;\n}\n","import { Accordion as AccordionPrimitive } from \"@base-ui/react/accordion\";\nimport { CaretDownIcon, CaretUpIcon } from \"@phosphor-icons/react\";\nimport { cn } from \"../../lib/utils\";\n\nfunction Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n className={cn(\n \"overflow-hidden border border-border/60 bg-card/30 backdrop-blur-md flex w-full flex-col\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\n \"data-open:bg-muted/30 data-open:backdrop-blur-sm not-last:border-b border-border/40 transition-colors\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: AccordionPrimitive.Trigger.Props) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n \"**:data-[slot=accordion-trigger-icon]:text-muted-foreground gap-4 px-4 py-3 text-left text-sm font-medium hover:bg-muted/20 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 group/accordion-trigger relative flex flex-1 items-center justify-between transition-all outline-none disabled:pointer-events-none disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n {children}\n <CaretDownIcon\n data-slot=\"accordion-trigger-icon\"\n className=\"pointer-events-none shrink-0 transition-transform duration-200 group-aria-expanded/accordion-trigger:rotate-180\"\n />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n );\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: AccordionPrimitive.Panel.Props) {\n return (\n <AccordionPrimitive.Panel\n data-slot=\"accordion-content\"\n className=\"data-open:animate-accordion-down data-closed:animate-accordion-up overflow-hidden\"\n {...props}\n >\n <div\n className={cn(\n \"px-4 pt-0 pb-4 text-sm [&_a]:hover:text-foreground h-(--accordion-panel-height) data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4\",\n className,\n )}\n >\n {children}\n </div>\n </AccordionPrimitive.Panel>\n );\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n","\"use client\";\n\nimport { Tabs as TabsPrimitive } from \"@base-ui/react/tabs\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"../../lib/utils\";\n\nfunction Tabs({\n className,\n orientation = \"horizontal\",\n ...props\n}: TabsPrimitive.Root.Props) {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n data-orientation={orientation}\n className={cn(\n \"gap-2 group/tabs flex data-[orientation=horizontal]:flex-col\",\n className,\n )}\n {...props}\n />\n );\n}\n\nconst tabsListVariants = cva(\n \"p-[3px] group-data-horizontal/tabs:h-8 group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col\",\n {\n variants: {\n variant: {\n default: \"bg-muted\",\n line: \"gap-1 bg-transparent\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction TabsList({\n className,\n variant = \"default\",\n ...props\n}: TabsPrimitive.List.Props & VariantProps<typeof tabsListVariants>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n data-variant={variant}\n className={cn(tabsListVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nfunction TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"tabs-trigger\"\n className={cn(\n \"gap-1.5 border border-transparent px-1.5 py-0.5 text-xs font-medium group-data-vertical/tabs:py-[calc(--spacing(1.25))] [&_svg:not([class*='size-'])]:size-3.5 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n \"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent\",\n \"data-active:bg-background dark:data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 data-active:text-foreground\",\n \"after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TabsContent({ className, ...props }: TabsPrimitive.Panel.Props) {\n return (\n <TabsPrimitive.Panel\n data-slot=\"tabs-content\"\n className={cn(\"text-xs/relaxed flex-1 outline-none\", className)}\n {...props}\n />\n );\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };\n","import { createQuestpieQueryOptions } from \"@questpie/tanstack-query\";\nimport {\n\ttype UseMutationOptions,\n\ttype UseQueryOptions,\n\tuseMutation,\n\tuseQuery,\n\tuseQueryClient,\n} from \"@tanstack/react-query\";\nimport type { Questpie } from \"questpie\";\nimport type { QuestpieClient } from \"questpie/client\";\nimport type {\n\tRegisteredCMS,\n\tRegisteredCollectionNames,\n} from \"../builder/registry\";\nimport { selectClient, useAdminStore, useScopedLocale } from \"../runtime\";\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\n/**\n * Resolved CMS type (Questpie<any> if not registered)\n */\ntype ResolvedCMS =\n\tRegisteredCMS extends Questpie<any> ? RegisteredCMS : Questpie<any>;\n\n/**\n * Resolved collection names (string if not registered)\n */\ntype ResolvedCollectionNames =\n\tRegisteredCMS extends Questpie<any> ? RegisteredCollectionNames : string;\n\n// ============================================================================\n// Collection Hooks\n// ============================================================================\n\n/**\n * Hook to fetch collection list with filters, sorting, pagination\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { data } = useCollectionList(\"barbers\");\n * ```\n */\nexport function useCollectionList<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\toptions?: any,\n\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n): any {\n\tconst client = useAdminStore(selectClient);\n\t// Use scoped locale (from LocaleScopeProvider in ResourceSheet) or global locale\n\tconst { locale: contentLocale } = useScopedLocale();\n\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\tconst queryOpts = createQuestpieQueryOptions(\n\t\tclient as any,\n\t\t{\n\t\t\tkeyPrefix,\n\t\t\tlocale: contentLocale,\n\t\t} as any,\n\t);\n\n\treturn useQuery({\n\t\t...(queryOpts as any).collections[collection as string].find({\n\t\t\t...options,\n\t\t\tlocale: contentLocale,\n\t\t} as any),\n\t\t...queryOptions,\n\t});\n}\n\n/**\n * Hook to count collection items with optional filters\n *\n * More efficient than useCollectionList when you only need the count.\n * Uses dedicated count endpoint that doesn't fetch actual documents.\n *\n * @example\n * ```tsx\n * // Count all items\n * const { data: count } = useCollectionCount(\"barbers\");\n *\n * // Count with filter\n * const { data: count } = useCollectionCount(\"appointments\", {\n * where: { status: \"pending\" }\n * });\n * ```\n */\nexport function useCollectionCount<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\toptions?: { where?: any; includeDeleted?: boolean },\n\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n): any {\n\tconst client = useAdminStore(selectClient);\n\t// Use scoped locale (from LocaleScopeProvider in ResourceSheet) or global locale\n\tconst { locale: contentLocale } = useScopedLocale();\n\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\tconst queryOpts = createQuestpieQueryOptions(\n\t\tclient as any,\n\t\t{\n\t\t\tkeyPrefix,\n\t\t\tlocale: contentLocale,\n\t\t} as any,\n\t);\n\n\treturn useQuery({\n\t\t...(queryOpts as any).collections[collection as string].count({\n\t\t\t...options,\n\t\t\tlocale: contentLocale,\n\t\t} as any),\n\t\t...queryOptions,\n\t});\n}\n\n/**\n * Hook to fetch single collection item\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { data } = useCollectionItem(\"barbers\", \"123\");\n * ```\n */\nexport function useCollectionItem<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\tid: string,\n\toptions?: Omit<\n\t\tParameters<\n\t\t\tQuestpieClient<ResolvedCMS>[\"collections\"][K & string][\"findOne\"]\n\t\t>[0],\n\t\t\"where\"\n\t> & {\n\t\tlocaleFallback?: boolean;\n\t\twith?: Record<string, boolean>;\n\t},\n\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n): any {\n\tconst client = useAdminStore(selectClient);\n\t// Use scoped locale (from LocaleScopeProvider in ResourceSheet) or global locale\n\tconst { locale: contentLocale } = useScopedLocale();\n\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\tconst queryOpts = createQuestpieQueryOptions(client as any, {\n\t\tkeyPrefix,\n\t\tlocale: contentLocale,\n\t});\n\n\treturn useQuery({\n\t\t...(queryOpts as any).collections[collection as string].findOne({\n\t\t\twhere: { id },\n\t\t\tlocale: contentLocale,\n\t\t\t...options,\n\t\t}),\n\t\t...queryOptions,\n\t});\n}\n\n/**\n * Hook to create collection item\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { mutate } = useCollectionCreate(\"barbers\");\n * mutate({ name: \"John\", ... });\n * ```\n */\nexport function useCollectionCreate<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n): any {\n\tconst client = useAdminStore(selectClient);\n\t// Use scoped locale (from LocaleScopeProvider in ResourceSheet) or global locale\n\tconst { locale: contentLocale } = useScopedLocale();\n\tconst queryClient = useQueryClient();\n\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\tconst queryOpts = createQuestpieQueryOptions(client as any, {\n\t\tkeyPrefix,\n\t\tlocale: contentLocale,\n\t});\n\n\tconst baseOptions = queryOpts.collections[collection as string].create();\n\tconst listQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"find\",\n\t\tcontentLocale,\n\t]);\n\tconst countQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"count\",\n\t\tcontentLocale,\n\t]);\n\n\treturn useMutation({\n\t\t...baseOptions,\n\t\tonSuccess: (data: any, variables: any, context: any) => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: listQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: countQueryKey,\n\t\t\t});\n\t\t\t(mutationOptions?.onSuccess as any)?.(data, variables, context);\n\t\t},\n\t\tonSettled: (data: any, error: any, variables: any, context: any) => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: listQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: countQueryKey,\n\t\t\t});\n\t\t\t(mutationOptions?.onSettled as any)?.(data, error, variables, context);\n\t\t},\n\t\t...mutationOptions,\n\t} as any);\n}\n\n/**\n * Hook to update collection item\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { mutate } = useCollectionUpdate(\"barbers\");\n * mutate({ id: \"123\", data: { name: \"John\" } });\n * ```\n */\nexport function useCollectionUpdate<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n): any {\n\tconst client = useAdminStore(selectClient);\n\t// Use scoped locale (from LocaleScopeProvider in ResourceSheet) or global locale\n\tconst { locale: contentLocale } = useScopedLocale();\n\tconst queryClient = useQueryClient();\n\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\tconst queryOpts = createQuestpieQueryOptions(client as any, {\n\t\tkeyPrefix,\n\t\tlocale: contentLocale,\n\t});\n\n\tconst baseOptions = queryOpts.collections[collection as string].update();\n\tconst listQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"find\",\n\t\tcontentLocale,\n\t]);\n\tconst countQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"count\",\n\t\tcontentLocale,\n\t]);\n\tconst itemQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"findOne\",\n\t\tcontentLocale,\n\t]);\n\n\treturn useMutation({\n\t\t...baseOptions,\n\t\tonSuccess: (data: any, variables: any, context: any) => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: listQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: countQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: itemQueryKey,\n\t\t\t});\n\t\t\t(mutationOptions?.onSuccess as any)?.(data, variables, context);\n\t\t},\n\t\tonSettled: (data: any, error: any, variables: any, context: any) => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: listQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: countQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: itemQueryKey,\n\t\t\t});\n\t\t\t(mutationOptions?.onSettled as any)?.(data, error, variables, context);\n\t\t},\n\t\t...mutationOptions,\n\t} as any);\n}\n\n/**\n * Hook to delete collection item\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { mutate } = useCollectionDelete(\"barbers\");\n * mutate(\"123\");\n * ```\n */\nexport function useCollectionDelete<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n): any {\n\tconst client = useAdminStore(selectClient);\n\t// Use scoped locale (from LocaleScopeProvider in ResourceSheet) or global locale\n\tconst { locale: contentLocale } = useScopedLocale();\n\tconst queryClient = useQueryClient();\n\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\tconst queryOpts = createQuestpieQueryOptions(client as any, {\n\t\tkeyPrefix,\n\t\tlocale: contentLocale,\n\t});\n\n\tconst baseOptions = queryOpts.collections[collection as string].delete();\n\tconst listQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"find\",\n\t\tcontentLocale,\n\t]);\n\tconst countQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"count\",\n\t\tcontentLocale,\n\t]);\n\tconst itemQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"findOne\",\n\t\tcontentLocale,\n\t]);\n\n\treturn useMutation({\n\t\t...baseOptions,\n\t\tonSuccess: (data: any, variables: any, context: any) => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: listQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: countQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: itemQueryKey,\n\t\t\t});\n\t\t\t(mutationOptions?.onSuccess as any)?.(data, variables, context);\n\t\t},\n\t\tonSettled: (data: any, error: any, variables: any, context: any) => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: listQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: countQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: itemQueryKey,\n\t\t\t});\n\t\t\t(mutationOptions?.onSettled as any)?.(data, error, variables, context);\n\t\t},\n\t\t...mutationOptions,\n\t} as any);\n}\n","import { cn } from \"../../lib/utils\";\n\nfunction Skeleton({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"skeleton\"\n className={cn(\"bg-muted animate-pulse\", className)}\n {...props}\n />\n );\n}\n\nexport { Skeleton };\n","\"use client\";\n\nimport * as React from \"react\";\n\ninterface ErrorBoundaryProps {\n children: React.ReactNode;\n fallback?: React.ReactNode | ((error: Error) => React.ReactNode);\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n/**\n * ErrorBoundary - Catches JavaScript errors in child component tree\n *\n * Prevents entire UI from crashing when a component throws an error.\n * Use around widgets, sections, or any component that might fail.\n *\n * @example\n * ```tsx\n * <ErrorBoundary fallback={<WidgetError />}>\n * <ChartWidget config={config} />\n * </ErrorBoundary>\n *\n * // With error callback\n * <ErrorBoundary\n * fallback={(error) => <p>Error: {error.message}</p>}\n * onError={(error) => logToService(error)}\n * >\n * <DashboardWidget config={config} />\n * </ErrorBoundary>\n * ```\n */\nexport class ErrorBoundary extends React.Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n this.props.onError?.(error, errorInfo);\n }\n\n render(): React.ReactNode {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n\n if (typeof fallback === \"function\") {\n return fallback(this.state.error);\n }\n\n if (fallback) {\n return fallback;\n }\n\n // Default fallback\n return (\n <div className=\"rounded-lg border border-destructive/20 bg-destructive/5 p-4\">\n <p className=\"text-sm font-medium text-destructive\">\n Something went wrong\n </p>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {this.state.error.message}\n </p>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\n/**\n * WidgetErrorBoundary - Specialized error boundary for dashboard widgets\n */\nexport function WidgetErrorBoundary({\n children,\n widgetType,\n}: {\n children: React.ReactNode;\n widgetType?: string;\n}) {\n return (\n <ErrorBoundary\n fallback={(error) => (\n <div className=\"rounded-lg border border-destructive/20 bg-destructive/5 p-4\">\n <p className=\"text-sm font-medium text-destructive\">Widget Error</p>\n {widgetType && (\n <p className=\"text-xs text-muted-foreground\">Type: {widgetType}</p>\n )}\n <p className=\"mt-1 text-xs text-muted-foreground\">{error.message}</p>\n </div>\n )}\n >\n {children}\n </ErrorBoundary>\n );\n}\n","/**\n * WidgetCard Component\n *\n * Standardized card wrapper for dashboard widgets with multiple variants.\n * Provides consistent styling, header actions, and loading/error states.\n */\n\nimport { ArrowClockwise, ArrowsOutSimple } from \"@phosphor-icons/react\";\nimport type * as React from \"react\";\nimport type { WidgetAction, WidgetCardVariant } from \"../../builder\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n\tCard,\n\tCardAction,\n\tCardContent,\n\tCardDescription,\n\tCardHeader,\n\tCardTitle,\n} from \"../../components/ui/card\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { cn } from \"../../lib/utils\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetCardProps {\n\t/** Widget title */\n\ttitle?: string;\n\t/** Widget description */\n\tdescription?: string;\n\t/** Widget icon */\n\ticon?: React.ComponentType<{ className?: string }>;\n\t/** Card visual variant */\n\tvariant?: WidgetCardVariant;\n\t/** Loading state (initial load) */\n\tisLoading?: boolean;\n\t/** Refreshing state (background refetch) */\n\tisRefreshing?: boolean;\n\t/** Error state */\n\terror?: Error | null;\n\t/** Refresh handler */\n\tonRefresh?: () => void;\n\t/** Expand handler (for full screen view) */\n\tonExpand?: () => void;\n\t/** Header actions */\n\tactions?: WidgetAction[];\n\t/** Custom CSS class */\n\tclassName?: string;\n\t/** Custom loading skeleton */\n\tloadingSkeleton?: React.ReactNode;\n\t/** Children content (optional when loading/error) */\n\tchildren?: React.ReactNode;\n}\n\n// ============================================================================\n// Variant Styles\n// ============================================================================\n\nconst variantStyles: Record<WidgetCardVariant, string> = {\n\tdefault: \"\",\n\tcompact: \"py-3 gap-3\",\n\tfeatured:\n\t\t\"border-primary/30 bg-gradient-to-br from-primary/5 to-transparent shadow-sm\",\n};\n\nconst variantContentStyles: Record<WidgetCardVariant, string> = {\n\tdefault: \"\",\n\tcompact: \"pt-0\",\n\tfeatured: \"\",\n};\n\n// ============================================================================\n// Sub-components\n// ============================================================================\n\nfunction WidgetCardLoading({\n\tvariant = \"default\",\n}: {\n\tvariant?: WidgetCardVariant;\n}) {\n\treturn (\n\t\t<Card className={cn(\"h-full flex flex-col\", variantStyles[variant])}>\n\t\t\t<CardHeader>\n\t\t\t\t<Skeleton className=\"h-4 w-24\" />\n\t\t\t</CardHeader>\n\t\t\t<CardContent className={cn(\"flex-1\", variantContentStyles[variant])}>\n\t\t\t\t<Skeleton className=\"h-20 w-full\" />\n\t\t\t</CardContent>\n\t\t</Card>\n\t);\n}\n\nfunction WidgetCardError({\n\terror,\n\tvariant = \"default\",\n\tonRetry,\n}: {\n\terror: Error;\n\tvariant?: WidgetCardVariant;\n\tonRetry?: () => void;\n}) {\n\treturn (\n\t\t<Card\n\t\t\tclassName={cn(\n\t\t\t\t\"h-full flex flex-col border-destructive/20 bg-destructive/5\",\n\t\t\t\tvariantStyles[variant],\n\t\t\t)}\n\t\t>\n\t\t\t<CardHeader>\n\t\t\t\t<CardTitle className=\"text-sm font-medium text-destructive\">\n\t\t\t\t\tError\n\t\t\t\t</CardTitle>\n\t\t\t\t{onRetry && (\n\t\t\t\t\t<CardAction>\n\t\t\t\t\t\t<Button variant=\"ghost\" size=\"icon-xs\" onClick={onRetry}>\n\t\t\t\t\t\t\t<ArrowClockwise className=\"h-3.5 w-3.5\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</CardAction>\n\t\t\t\t)}\n\t\t\t</CardHeader>\n\t\t\t<CardContent className={cn(\"flex-1\", variantContentStyles[variant])}>\n\t\t\t\t<p className=\"text-xs text-muted-foreground\">{error.message}</p>\n\t\t\t</CardContent>\n\t\t</Card>\n\t);\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * WidgetCard - Standardized card wrapper for dashboard widgets\n *\n * @example\n * ```tsx\n * <WidgetCard\n * title=\"Revenue\"\n * description=\"Monthly sales total\"\n * variant=\"featured\"\n * onRefresh={() => refetch()}\n * >\n * <div className=\"text-2xl font-bold\">$12,345</div>\n * </WidgetCard>\n * ```\n */\nexport function WidgetCard({\n\ttitle,\n\tdescription,\n\ticon: Icon,\n\tvariant = \"default\",\n\tisLoading,\n\tisRefreshing,\n\terror,\n\tonRefresh,\n\tonExpand,\n\tactions,\n\tclassName,\n\tloadingSkeleton,\n\tchildren,\n}: WidgetCardProps): React.ReactElement {\n\t// Loading state\n\tif (isLoading) {\n\t\tif (loadingSkeleton) {\n\t\t\treturn (\n\t\t\t\t<Card\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"h-full flex flex-col\",\n\t\t\t\t\t\tvariantStyles[variant],\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t<Skeleton className=\"h-4 w-24\" />\n\t\t\t\t\t</CardHeader>\n\t\t\t\t\t<CardContent className={cn(\"flex-1\", variantContentStyles[variant])}>\n\t\t\t\t\t\t{loadingSkeleton}\n\t\t\t\t\t</CardContent>\n\t\t\t\t</Card>\n\t\t\t);\n\t\t}\n\t\treturn <WidgetCardLoading variant={variant} />;\n\t}\n\n\t// Error state\n\tif (error) {\n\t\treturn (\n\t\t\t<WidgetCardError error={error} variant={variant} onRetry={onRefresh} />\n\t\t);\n\t}\n\n\tconst hasHeader =\n\t\ttitle || description || Icon || onRefresh || onExpand || actions?.length;\n\n\treturn (\n\t\t<Card\n\t\t\tclassName={cn(\"h-full flex flex-col\", variantStyles[variant], className)}\n\t\t>\n\t\t\t{hasHeader && (\n\t\t\t\t<CardHeader>\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t{Icon && <Icon className=\"h-4 w-4 text-muted-foreground\" />}\n\t\t\t\t\t\t<div className=\"flex-1 min-w-0\">\n\t\t\t\t\t\t\t{title && (\n\t\t\t\t\t\t\t\t<CardTitle className=\"text-sm font-medium truncate\">\n\t\t\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t\t\t</CardTitle>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{description && (\n\t\t\t\t\t\t\t\t<CardDescription className=\"truncate\">\n\t\t\t\t\t\t\t\t\t{description}\n\t\t\t\t\t\t\t\t</CardDescription>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{(onRefresh || onExpand || actions?.length) && (\n\t\t\t\t\t\t<CardAction>\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t\t{actions?.map((action) => (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tkey={action.id}\n\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\t\t\t\t\tonClick={action.onClick}\n\t\t\t\t\t\t\t\t\t\ttitle={action.label}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{action.icon && typeof action.icon !== \"string\" && (\n\t\t\t\t\t\t\t\t\t\t\t<action.icon className=\"h-3.5 w-3.5\" />\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t{onRefresh && (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\t\t\t\t\tonClick={onRefresh}\n\t\t\t\t\t\t\t\t\t\ttitle=\"Refresh\"\n\t\t\t\t\t\t\t\t\t\tdisabled={isRefreshing}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ArrowClockwise\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\"h-3.5 w-3.5\",\n\t\t\t\t\t\t\t\t\t\t\t\tisRefreshing && \"animate-spin\",\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{onExpand && (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\t\t\t\t\tonClick={onExpand}\n\t\t\t\t\t\t\t\t\t\ttitle=\"Expand\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ArrowsOutSimple className=\"h-3.5 w-3.5\" />\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</CardAction>\n\t\t\t\t\t)}\n\t\t\t\t</CardHeader>\n\t\t\t)}\n\t\t\t<CardContent\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex-1\",\n\t\t\t\t\tvariantContentStyles[variant],\n\t\t\t\t\t!hasHeader && \"pt-0\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</CardContent>\n\t\t</Card>\n\t);\n}\n\nexport default WidgetCard;\n","/**\n * Widget Skeletons\n *\n * Loading skeleton components for different widget types.\n * Provides visual feedback while data is being fetched.\n */\n\nimport { cn } from \"../../lib/utils\";\nimport { Skeleton } from \"../ui/skeleton\";\n\n// ============================================================================\n// Stats Widget Skeleton\n// ============================================================================\n\nexport function StatsWidgetSkeleton() {\n\treturn (\n\t\t<div className=\"space-y-3\">\n\t\t\t<Skeleton className=\"h-8 w-20\" />\n\t\t\t<Skeleton className=\"h-4 w-32\" />\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Chart Widget Skeleton\n// ============================================================================\n\nexport function ChartWidgetSkeleton() {\n\treturn (\n\t\t<div className=\"h-48 w-full flex items-end gap-2 pt-4\">\n\t\t\t{/* Bar chart style skeleton */}\n\t\t\t<Skeleton className=\"flex-1 rounded-t h-[40%]\" />\n\t\t\t<Skeleton className=\"flex-1 rounded-t h-[65%]\" />\n\t\t\t<Skeleton className=\"flex-1 rounded-t h-[45%]\" />\n\t\t\t<Skeleton className=\"flex-1 rounded-t h-[80%]\" />\n\t\t\t<Skeleton className=\"flex-1 rounded-t h-[55%]\" />\n\t\t\t<Skeleton className=\"flex-1 rounded-t h-[70%]\" />\n\t\t\t<Skeleton className=\"flex-1 rounded-t h-[50%]\" />\n\t\t\t<Skeleton className=\"flex-1 rounded-t h-[75%]\" />\n\t\t\t<Skeleton className=\"flex-1 rounded-t h-[60%]\" />\n\t\t\t<Skeleton className=\"flex-1 rounded-t h-[85%]\" />\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Recent Items Widget Skeleton\n// ============================================================================\n\nexport function RecentItemsWidgetSkeleton({ count = 5 }: { count?: number }) {\n\treturn (\n\t\t<div className=\"space-y-1\">\n\t\t\t<SkeletonRow />\n\t\t\t{count > 1 && <SkeletonRow />}\n\t\t\t{count > 2 && <SkeletonRow />}\n\t\t\t{count > 3 && <SkeletonRow />}\n\t\t\t{count > 4 && <SkeletonRow />}\n\t\t</div>\n\t);\n}\n\nfunction SkeletonRow() {\n\treturn (\n\t\t<div className=\"flex items-center gap-3 p-2\">\n\t\t\t<div className=\"flex-1 space-y-2\">\n\t\t\t\t<Skeleton className=\"h-4 w-3/4\" />\n\t\t\t\t<Skeleton className=\"h-3 w-1/2\" />\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Quick Actions Widget Skeleton\n// ============================================================================\n\nexport function QuickActionsWidgetSkeleton({\n\tcount = 3,\n\tlayout = \"list\",\n}: {\n\tcount?: number;\n\tlayout?: \"list\" | \"grid\";\n}) {\n\tif (layout === \"grid\") {\n\t\treturn (\n\t\t\t<div className=\"grid grid-cols-2 gap-2\">\n\t\t\t\t<ActionGridItem />\n\t\t\t\t{count > 1 && <ActionGridItem />}\n\t\t\t\t{count > 2 && <ActionGridItem />}\n\t\t\t\t{count > 3 && <ActionGridItem />}\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"space-y-1 -mx-1\">\n\t\t\t<ActionListItem />\n\t\t\t{count > 1 && <ActionListItem />}\n\t\t\t{count > 2 && <ActionListItem />}\n\t\t</div>\n\t);\n}\n\nfunction ActionGridItem() {\n\treturn (\n\t\t<div className=\"flex flex-col items-center justify-center gap-2 p-3\">\n\t\t\t<Skeleton className=\"h-9 w-9 rounded-md\" />\n\t\t\t<Skeleton className=\"h-3 w-16\" />\n\t\t</div>\n\t);\n}\n\nfunction ActionListItem() {\n\treturn (\n\t\t<div className=\"flex items-center gap-3 px-2 py-2\">\n\t\t\t<Skeleton className=\"h-8 w-8 rounded-md shrink-0\" />\n\t\t\t<Skeleton className=\"h-4 flex-1\" />\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Table Widget Skeleton\n// ============================================================================\n\nexport function TableWidgetSkeleton({\n\trows = 5,\n\tcolumns = 3,\n}: {\n\trows?: number;\n\tcolumns?: number;\n}) {\n\treturn (\n\t\t<div className=\"-mx-5\">\n\t\t\t{/* Header */}\n\t\t\t<div className=\"flex gap-4 px-5 py-2 border-b border-border/50\">\n\t\t\t\t<Skeleton className=\"h-4 w-24\" />\n\t\t\t\t{columns > 1 && <Skeleton className=\"h-4 flex-1\" />}\n\t\t\t\t{columns > 2 && <Skeleton className=\"h-4 flex-1\" />}\n\t\t\t</div>\n\t\t\t{/* Rows */}\n\t\t\t<TableSkeletonRow columns={columns} />\n\t\t\t{rows > 1 && <TableSkeletonRow columns={columns} />}\n\t\t\t{rows > 2 && <TableSkeletonRow columns={columns} />}\n\t\t\t{rows > 3 && <TableSkeletonRow columns={columns} />}\n\t\t\t{rows > 4 && <TableSkeletonRow columns={columns} last />}\n\t\t</div>\n\t);\n}\n\nfunction TableSkeletonRow({\n\tcolumns = 3,\n\tlast = false,\n}: {\n\tcolumns?: number;\n\tlast?: boolean;\n}) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"flex gap-4 px-5 py-3 border-b border-border/30\",\n\t\t\t\tlast && \"border-0\",\n\t\t\t)}\n\t\t>\n\t\t\t<Skeleton className=\"h-4 w-20\" />\n\t\t\t{columns > 1 && <Skeleton className=\"h-4 flex-1\" />}\n\t\t\t{columns > 2 && <Skeleton className=\"h-4 flex-1\" />}\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Timeline Widget Skeleton\n// ============================================================================\n\nexport function TimelineWidgetSkeleton({ count = 5 }: { count?: number }) {\n\treturn (\n\t\t<div className=\"space-y-4\">\n\t\t\t<TimelineSkeletonItem />\n\t\t\t{count > 1 && <TimelineSkeletonItem />}\n\t\t\t{count > 2 && <TimelineSkeletonItem />}\n\t\t\t{count > 3 && <TimelineSkeletonItem />}\n\t\t\t{count > 4 && <TimelineSkeletonItem last />}\n\t\t</div>\n\t);\n}\n\nfunction TimelineSkeletonItem({ last = false }: { last?: boolean }) {\n\treturn (\n\t\t<div className=\"flex gap-3\">\n\t\t\t{/* Timeline dot */}\n\t\t\t<div className=\"flex flex-col items-center\">\n\t\t\t\t<Skeleton className=\"h-3 w-3 rounded-full\" />\n\t\t\t\t{!last && <Skeleton className=\"w-0.5 flex-1 mt-1\" />}\n\t\t\t</div>\n\t\t\t{/* Content */}\n\t\t\t<div className=\"flex-1 space-y-1 pb-4\">\n\t\t\t\t<Skeleton className=\"h-4 w-3/4\" />\n\t\t\t\t<Skeleton className=\"h-3 w-1/2\" />\n\t\t\t\t<Skeleton className=\"h-3 w-20\" />\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Progress Widget Skeleton\n// ============================================================================\n\nexport function ProgressWidgetSkeleton() {\n\treturn (\n\t\t<div className=\"space-y-3\">\n\t\t\t<div className=\"flex justify-between items-center\">\n\t\t\t\t<Skeleton className=\"h-4 w-32\" />\n\t\t\t\t<Skeleton className=\"h-4 w-12\" />\n\t\t\t</div>\n\t\t\t<Skeleton className=\"h-2 w-full rounded-full\" />\n\t\t\t<Skeleton className=\"h-3 w-24\" />\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Value Widget Skeleton\n// ============================================================================\n\nexport function ValueWidgetSkeleton({\n\tfeatured = false,\n}: {\n\tfeatured?: boolean;\n}) {\n\treturn (\n\t\t<div className=\"space-y-3\">\n\t\t\t<div className=\"flex items-start gap-3\">\n\t\t\t\t<Skeleton className=\"h-10 w-10 rounded-md shrink-0\" />\n\t\t\t\t<div className=\"flex-1 space-y-2\">\n\t\t\t\t\t<Skeleton className=\"h-4 w-24\" />\n\t\t\t\t\t<Skeleton className={cn(\"h-8\", featured ? \"w-40\" : \"w-24\")} />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<Skeleton className=\"h-3 w-32\" />\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Generic Widget Skeleton\n// ============================================================================\n\nexport function GenericWidgetSkeleton() {\n\treturn (\n\t\t<div className=\"space-y-4\">\n\t\t\t<Skeleton className=\"h-20 w-full\" />\n\t\t</div>\n\t);\n}\n","/**\n * Chart Widget\n *\n * Displays data visualization over time.\n * Uses WidgetCard for consistent styling.\n */\n\nimport * as React from \"react\";\nimport {\n\tArea,\n\tAreaChart,\n\tBar,\n\tBarChart,\n\tCartesianGrid,\n\tCell,\n\tLine,\n\tLineChart,\n\tPie,\n\tPieChart,\n\tResponsiveContainer,\n\tTooltip,\n\ttype TooltipProps,\n\tXAxis,\n\tYAxis,\n} from \"recharts\";\nimport type {\n\tNameType,\n\tValueType,\n} from \"recharts/types/component/DefaultTooltipContent\";\nimport { useCollectionList } from \"../../hooks/use-collection\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { formatCollectionName } from \"../../lib/utils\";\nimport { WidgetCard } from \"../../views/dashboard/widget-card\";\nimport { ChartWidgetSkeleton } from \"./widget-skeletons\";\n\n/**\n * Chart widget config (local type for component props)\n */\nexport type ChartWidgetConfig = {\n\tcollection: string;\n\t/** Field to aggregate by (e.g., \"createdAt\" for time series, \"status\" for categories) */\n\tfield: string;\n\tchartType?: \"line\" | \"bar\" | \"area\" | \"pie\";\n\ttimeRange?: \"7d\" | \"30d\" | \"90d\" | \"1y\";\n\tlabel?: string;\n\t/** Color for the chart (CSS color value) */\n\tcolor?: string;\n\t/** Show grid lines */\n\tshowGrid?: boolean;\n\t/** Aggregation type */\n\taggregation?: \"count\" | \"sum\" | \"average\";\n\t/** Value field for sum/average aggregation */\n\tvalueField?: string;\n};\n\n/**\n * Chart widget props\n */\nexport type ChartWidgetProps = {\n\tconfig: ChartWidgetConfig;\n};\n\n// Theme-aware chart colors using CSS variables\n// Note: CSS vars contain full oklch() value, so use var() directly\nconst CHART_COLORS = [\n\t\"var(--color-chart-1)\",\n\t\"var(--color-chart-2)\",\n\t\"var(--color-chart-3)\",\n\t\"var(--color-chart-4)\",\n\t\"var(--color-chart-5)\",\n];\n\n/**\n * Custom tooltip component matching shadcn style\n */\nfunction ChartTooltip({\n\tactive,\n\tpayload,\n\tlabel,\n}: TooltipProps<ValueType, NameType>) {\n\tif (!active || !payload?.length) return null;\n\n\treturn (\n\t\t<div className=\"rounded-md border border-border bg-background px-3 py-2 text-xs shadow-md\">\n\t\t\t<p className=\"font-medium text-foreground\">{label}</p>\n\t\t\t{payload.map((entry) => (\n\t\t\t\t<p key={String(entry.name)} className=\"text-muted-foreground\">\n\t\t\t\t\t{entry.name}:{\" \"}\n\t\t\t\t\t<span className=\"font-medium text-foreground\">{entry.value}</span>\n\t\t\t\t</p>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\n/**\n * Chart widget component\n *\n * Displays:\n * - Time series data visualization\n * - Multiple chart types (line, bar, area, pie)\n * - Configurable time ranges\n */\nexport default function ChartWidget({ config }: ChartWidgetProps) {\n\tconst resolveText = useResolveText();\n\tconst {\n\t\tcollection,\n\t\tfield,\n\t\tchartType = \"area\",\n\t\ttimeRange = \"30d\",\n\t\tlabel,\n\t\tcolor = \"var(--color-chart-1)\",\n\t\tshowGrid = true,\n\t} = config;\n\n\t// Fetch collection data (limited to 1000 items for performance)\n\tconst { data, isLoading, error, refetch } = useCollectionList(\n\t\tcollection as any,\n\t\t{\n\t\t\tlimit: 1000,\n\t\t},\n\t);\n\n\t// API returns PaginatedResult with { docs, totalDocs, ... }\n\tconst items = Array.isArray(data?.docs) ? data.docs : [];\n\tconst displayLabel = label\n\t\t? resolveText(label)\n\t\t: `${formatCollectionName(collection)} by ${field}`;\n\n\t// Process data for chart\n\tconst chartData = React.useMemo(() => {\n\t\tif (!items.length) return [];\n\n\t\t// Group by field value\n\t\tconst grouped = items.reduce(\n\t\t\t(acc: Record<string, number>, item: any) => {\n\t\t\t\tconst value = item[field];\n\t\t\t\tif (value === undefined || value === null) return acc;\n\n\t\t\t\t// For date fields, group by day/week/month based on timeRange\n\t\t\t\tlet key: string;\n\t\t\t\tif (value instanceof Date || !isNaN(Date.parse(value))) {\n\t\t\t\t\tconst date = new Date(value);\n\t\t\t\t\tkey = formatDateForRange(date, timeRange);\n\t\t\t\t} else {\n\t\t\t\t\tkey = String(value);\n\t\t\t\t}\n\n\t\t\t\tacc[key] = (acc[key] || 0) + 1;\n\t\t\t\treturn acc;\n\t\t\t},\n\t\t\t{} as Record<string, number>,\n\t\t);\n\n\t\t// Convert to array and sort\n\t\treturn Object.entries(grouped)\n\t\t\t.map(([name, value]) => ({ name, value: value as number }))\n\t\t\t.sort((a, b) => a.name.localeCompare(b.name));\n\t}, [items, field, timeRange]);\n\n\t// Empty state content\n\tconst emptyContent = (\n\t\t<div className=\"flex h-48 items-center justify-center text-muted-foreground\">\n\t\t\t<p className=\"text-sm\">No data available</p>\n\t\t</div>\n\t);\n\n\t// Chart content\n\tconst chartContent =\n\t\tchartData.length === 0 ? (\n\t\t\temptyContent\n\t\t) : (\n\t\t\t<div className=\"h-48 w-full\">\n\t\t\t\t<ResponsiveContainer width=\"100%\" height=\"100%\">\n\t\t\t\t\t{renderChart(chartType, chartData, color, showGrid)}\n\t\t\t\t</ResponsiveContainer>\n\t\t\t</div>\n\t\t);\n\n\treturn (\n\t\t<WidgetCard\n\t\t\ttitle={displayLabel}\n\t\t\tisLoading={isLoading}\n\t\t\tloadingSkeleton={<ChartWidgetSkeleton />}\n\t\t\terror={\n\t\t\t\terror instanceof Error ? error : error ? new Error(String(error)) : null\n\t\t\t}\n\t\t\tonRefresh={() => refetch()}\n\t\t>\n\t\t\t{chartContent}\n\t\t</WidgetCard>\n\t);\n}\n\n/**\n * Render the appropriate chart type\n */\nfunction renderChart(\n\ttype: ChartWidgetConfig[\"chartType\"],\n\tdata: Array<{ name: string; value: number }>,\n\tcolor: string,\n\tshowGrid: boolean,\n) {\n\tconst commonProps = {\n\t\tdata,\n\t\tmargin: { top: 5, right: 5, left: -20, bottom: 5 },\n\t};\n\n\t// Use CSS color variables (already contain full oklch values)\n\tconst axisStyle = {\n\t\tfontSize: 10,\n\t\tfill: \"var(--color-muted-foreground)\",\n\t};\n\n\tswitch (type) {\n\t\tcase \"line\":\n\t\t\treturn (\n\t\t\t\t<LineChart {...commonProps}>\n\t\t\t\t\t{showGrid && (\n\t\t\t\t\t\t<CartesianGrid\n\t\t\t\t\t\t\tstrokeDasharray=\"3 3\"\n\t\t\t\t\t\t\tstroke=\"var(--color-border)\"\n\t\t\t\t\t\t\topacity={0.5}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t<XAxis\n\t\t\t\t\t\tdataKey=\"name\"\n\t\t\t\t\t\ttick={axisStyle}\n\t\t\t\t\t\ttickLine={false}\n\t\t\t\t\t\taxisLine={false}\n\t\t\t\t\t/>\n\t\t\t\t\t<YAxis tick={axisStyle} tickLine={false} axisLine={false} />\n\t\t\t\t\t<Tooltip content={<ChartTooltip />} />\n\t\t\t\t\t<Line\n\t\t\t\t\t\ttype=\"monotone\"\n\t\t\t\t\t\tdataKey=\"value\"\n\t\t\t\t\t\tstroke={color}\n\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t\tdot={false}\n\t\t\t\t\t/>\n\t\t\t\t</LineChart>\n\t\t\t);\n\n\t\tcase \"bar\":\n\t\t\treturn (\n\t\t\t\t<BarChart {...commonProps}>\n\t\t\t\t\t{showGrid && (\n\t\t\t\t\t\t<CartesianGrid\n\t\t\t\t\t\t\tstrokeDasharray=\"3 3\"\n\t\t\t\t\t\t\tstroke=\"var(--color-border)\"\n\t\t\t\t\t\t\topacity={0.5}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t<XAxis\n\t\t\t\t\t\tdataKey=\"name\"\n\t\t\t\t\t\ttick={axisStyle}\n\t\t\t\t\t\ttickLine={false}\n\t\t\t\t\t\taxisLine={false}\n\t\t\t\t\t/>\n\t\t\t\t\t<YAxis tick={axisStyle} tickLine={false} axisLine={false} />\n\t\t\t\t\t<Tooltip\n\t\t\t\t\t\tcontent={<ChartTooltip />}\n\t\t\t\t\t\tcursor={{ fill: \"var(--color-muted)\", opacity: 0.3 }}\n\t\t\t\t\t/>\n\t\t\t\t\t<Bar dataKey=\"value\" fill={color} radius={[2, 2, 0, 0]} />\n\t\t\t\t</BarChart>\n\t\t\t);\n\n\t\tcase \"pie\":\n\t\t\treturn (\n\t\t\t\t<PieChart>\n\t\t\t\t\t<Pie\n\t\t\t\t\t\tdata={data}\n\t\t\t\t\t\tdataKey=\"value\"\n\t\t\t\t\t\tnameKey=\"name\"\n\t\t\t\t\t\tcx=\"50%\"\n\t\t\t\t\t\tcy=\"50%\"\n\t\t\t\t\t\touterRadius={60}\n\t\t\t\t\t\tlabel={({ name }) => name}\n\t\t\t\t\t\tlabelLine={false}\n\t\t\t\t\t\tstroke=\"var(--color-background)\"\n\t\t\t\t\t\tstrokeWidth={2}\n\t\t\t\t\t>\n\t\t\t\t\t\t{data.map((entry) => (\n\t\t\t\t\t\t\t<Cell\n\t\t\t\t\t\t\t\tkey={`cell-${entry.name}`}\n\t\t\t\t\t\t\t\tfill={CHART_COLORS[data.indexOf(entry) % CHART_COLORS.length]}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Pie>\n\t\t\t\t\t<Tooltip content={<ChartTooltip />} />\n\t\t\t\t</PieChart>\n\t\t\t);\n\n\t\tcase \"area\":\n\t\tdefault:\n\t\t\treturn (\n\t\t\t\t<AreaChart {...commonProps}>\n\t\t\t\t\t{showGrid && (\n\t\t\t\t\t\t<CartesianGrid\n\t\t\t\t\t\t\tstrokeDasharray=\"3 3\"\n\t\t\t\t\t\t\tstroke=\"var(--color-border)\"\n\t\t\t\t\t\t\topacity={0.5}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t<XAxis\n\t\t\t\t\t\tdataKey=\"name\"\n\t\t\t\t\t\ttick={axisStyle}\n\t\t\t\t\t\ttickLine={false}\n\t\t\t\t\t\taxisLine={false}\n\t\t\t\t\t/>\n\t\t\t\t\t<YAxis tick={axisStyle} tickLine={false} axisLine={false} />\n\t\t\t\t\t<Tooltip content={<ChartTooltip />} />\n\t\t\t\t\t<Area\n\t\t\t\t\t\ttype=\"monotone\"\n\t\t\t\t\t\tdataKey=\"value\"\n\t\t\t\t\t\tstroke={color}\n\t\t\t\t\t\tfill={color}\n\t\t\t\t\t\tfillOpacity={0.15}\n\t\t\t\t\t/>\n\t\t\t\t</AreaChart>\n\t\t\t);\n\t}\n}\n\n/**\n * Format date based on time range for grouping\n */\nfunction formatDateForRange(\n\tdate: Date,\n\ttimeRange: ChartWidgetConfig[\"timeRange\"],\n): string {\n\tconst months = [\n\t\t\"Jan\",\n\t\t\"Feb\",\n\t\t\"Mar\",\n\t\t\"Apr\",\n\t\t\"May\",\n\t\t\"Jun\",\n\t\t\"Jul\",\n\t\t\"Aug\",\n\t\t\"Sep\",\n\t\t\"Oct\",\n\t\t\"Nov\",\n\t\t\"Dec\",\n\t];\n\n\tswitch (timeRange) {\n\t\tcase \"7d\": {\n\t\t\t// Group by day: \"Mon 15\"\n\t\t\tconst days = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n\t\t\treturn `${days[date.getDay()]} ${date.getDate()}`;\n\t\t}\n\n\t\tcase \"30d\":\n\t\t\t// Group by day: \"Jan 15\"\n\t\t\treturn `${months[date.getMonth()]} ${date.getDate()}`;\n\n\t\tcase \"90d\": {\n\t\t\t// Group by week: \"W1 Jan\"\n\t\t\tconst weekNum = Math.ceil(date.getDate() / 7);\n\t\t\treturn `W${weekNum} ${months[date.getMonth()]}`;\n\t\t}\n\n\t\tcase \"1y\":\n\t\t\t// Group by month: \"Jan 2024\"\n\t\t\treturn `${months[date.getMonth()]} ${date.getFullYear()}`;\n\n\t\tdefault:\n\t\t\treturn `${months[date.getMonth()]} ${date.getDate()}`;\n\t}\n}\n","/**\n * Progress Widget\n *\n * Displays progress towards a goal.\n * Uses WidgetCard for consistent styling.\n */\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { ProgressWidgetConfig } from \"../../builder/types/widget-types\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { selectClient, useAdminStore } from \"../../runtime\";\nimport { WidgetCard } from \"../../views/dashboard/widget-card\";\nimport { ProgressWidgetSkeleton } from \"./widget-skeletons\";\n\n/**\n * Progress widget props\n */\nexport interface ProgressWidgetProps {\n\tconfig: ProgressWidgetConfig;\n}\n\n/**\n * Progress Widget Component\n *\n * Displays a progress bar with current/target values.\n *\n * @example\n * ```tsx\n * <ProgressWidget\n * config={{\n * type: \"progress\",\n * id: \"monthly-sales\",\n * title: \"Monthly Sales Goal\",\n * fetchFn: async (client) => ({\n * current: 75000,\n * target: 100000,\n * label: \"$75,000 / $100,000\"\n * }),\n * showPercentage: true,\n * }}\n * />\n * ```\n */\nexport default function ProgressWidget({ config }: ProgressWidgetProps) {\n\tconst client = useAdminStore(selectClient);\n\tconst resolveText = useResolveText();\n\tconst { color, showPercentage = true } = config;\n\n\tconst { data, isLoading, error, refetch } = useQuery<{\n\t\tcurrent: number;\n\t\ttarget: number;\n\t\tlabel?: string;\n\t\tsubtitle?: string;\n\t}>({\n\t\tqueryKey: [\"widget\", \"progress\", config.id],\n\t\tqueryFn: () => config.fetchFn(client),\n\t\trefetchInterval: config.refreshInterval,\n\t});\n\n\tconst title = config.title ? resolveText(config.title) : undefined;\n\n\t// Calculate percentage\n\tconst percentage = data\n\t\t? Math.min((data.current / data.target) * 100, 100)\n\t\t: 0;\n\tconst percentageFormatted = percentage.toFixed(0);\n\n\t// Determine color based on progress\n\tconst getProgressColor = () => {\n\t\tif (color) return color;\n\t\tif (percentage >= 100) return \"bg-green-500\";\n\t\tif (percentage >= 75) return \"bg-primary\";\n\t\tif (percentage >= 50) return \"bg-yellow-500\";\n\t\treturn \"bg-muted-foreground\";\n\t};\n\n\t// Progress content\n\tconst progressContent = data ? (\n\t\t<div className=\"space-y-3\">\n\t\t\t{/* Progress bar */}\n\t\t\t<div className=\"relative\">\n\t\t\t\t<div className=\"h-2 w-full overflow-hidden rounded-full bg-muted\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"h-full rounded-full transition-all duration-500\",\n\t\t\t\t\t\t\tgetProgressColor(),\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tstyle={{ width: `${percentage}%` }}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Labels */}\n\t\t\t<div className=\"flex items-center justify-between text-sm\">\n\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t{data.label ||\n\t\t\t\t\t\t`${data.current.toLocaleString()} / ${data.target.toLocaleString()}`}\n\t\t\t\t</span>\n\t\t\t\t{showPercentage && (\n\t\t\t\t\t<span className=\"font-medium\">{percentageFormatted}%</span>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Subtitle */}\n\t\t\t{data.subtitle && (\n\t\t\t\t<p className=\"text-xs text-muted-foreground\">{data.subtitle}</p>\n\t\t\t)}\n\t\t</div>\n\t) : null;\n\n\treturn (\n\t\t<WidgetCard\n\t\t\ttitle={title}\n\t\t\tisLoading={isLoading}\n\t\t\tloadingSkeleton={<ProgressWidgetSkeleton />}\n\t\t\terror={\n\t\t\t\terror instanceof Error ? error : error ? new Error(String(error)) : null\n\t\t\t}\n\t\t\tonRefresh={() => refetch()}\n\t\t>\n\t\t\t{progressContent}\n\t\t</WidgetCard>\n\t);\n}\n","/**\n * Quick Actions Widget\n *\n * Displays shortcuts to common actions with icons and proper styling.\n * Uses WidgetCard for consistent styling.\n */\n\nimport { ArrowRight } from \"@phosphor-icons/react\";\nimport type * as React from \"react\";\nimport type { QuickActionsWidgetConfig } from \"../../builder/types/widget-types\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn, formatCollectionName } from \"../../lib/utils\";\nimport { WidgetCard } from \"../../views/dashboard/widget-card\";\n\n/**\n * Quick actions widget props\n */\nexport interface QuickActionsWidgetProps {\n\tconfig: QuickActionsWidgetConfig;\n\tbasePath?: string;\n\tnavigate?: (path: string) => void;\n}\n\n/**\n * Quick actions widget component\n *\n * Displays a list of action items with icons, matching the style\n * of other dashboard widgets like recent-items.\n */\nexport default function QuickActionsWidget({\n\tconfig,\n\tbasePath = \"/admin\",\n\tnavigate,\n}: QuickActionsWidgetProps) {\n\tconst resolveText = useResolveText();\n\tconst { quickActions, layout = \"list\" } = config;\n\tconst title = config.title ? resolveText(config.title) : \"Quick Actions\";\n\n\t// Parse actions - handle both string shortcuts and full config objects\n\tconst parsedActions = quickActions.map((action, index) => {\n\t\tif (typeof action === \"string\") {\n\t\t\t// Format: \"collection.action\" e.g., \"posts.create\"\n\t\t\tconst [collection, actionType] = action.split(\".\");\n\t\t\treturn {\n\t\t\t\tid: `${action}-${index}`,\n\t\t\t\tlabel: `${actionType === \"create\" ? \"New\" : actionType} ${formatCollectionName(collection)}`,\n\t\t\t\thref: `${basePath}/collections/${collection}/${actionType === \"create\" ? \"create\" : \"\"}`,\n\t\t\t\ticon: undefined,\n\t\t\t\tvariant: \"default\" as const,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tid: `action-${index}`,\n\t\t\tlabel: resolveText(action.label),\n\t\t\thref: action.href,\n\t\t\tonClick: action.onClick,\n\t\t\ticon: action.icon,\n\t\t\tvariant: action.variant || (\"default\" as const),\n\t\t};\n\t});\n\n\t// Handle action click\n\tconst handleClick = (action: (typeof parsedActions)[0]) => {\n\t\tif (action.onClick) {\n\t\t\taction.onClick();\n\t\t} else if (action.href && navigate) {\n\t\t\tnavigate(action.href);\n\t\t}\n\t};\n\n\t// Variant styles for the action items\n\tconst variantStyles = {\n\t\tdefault: \"hover:bg-muted/50 cursor-pointer\",\n\t\tprimary:\n\t\t\t\"bg-primary/5 hover:bg-primary/10 border-primary/20 text-primary [&_svg]:text-primary cursor-pointer\",\n\t\tsecondary: \"hover:bg-secondary cursor-pointer\",\n\t\toutline: \"border border-border hover:bg-muted/50 cursor-pointer\",\n\t};\n\n\tconst iconVariantStyles = {\n\t\tdefault: \"bg-muted text-muted-foreground\",\n\t\tprimary: \"bg-primary/10 text-primary\",\n\t\tsecondary: \"bg-secondary text-secondary-foreground\",\n\t\toutline: \"bg-background text-muted-foreground\",\n\t};\n\n\t// Empty state\n\tif (parsedActions.length === 0) {\n\t\treturn (\n\t\t\t<WidgetCard title={title}>\n\t\t\t\t<p className=\"text-sm text-muted-foreground\">No actions configured</p>\n\t\t\t</WidgetCard>\n\t\t);\n\t}\n\n\t// Grid layout\n\tif (layout === \"grid\") {\n\t\treturn (\n\t\t\t<WidgetCard title={title}>\n\t\t\t\t<div className=\"grid grid-cols-2 gap-2\">\n\t\t\t\t\t{parsedActions.map((action) => {\n\t\t\t\t\t\tconst Icon =\n\t\t\t\t\t\t\taction.icon && typeof action.icon !== \"string\"\n\t\t\t\t\t\t\t\t? action.icon\n\t\t\t\t\t\t\t\t: null;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tkey={action.id}\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => handleClick(action)}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"flex flex-col items-center justify-center gap-2 rounded-md p-3 text-center transition-colors\",\n\t\t\t\t\t\t\t\t\tvariantStyles[action.variant],\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{Icon && (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\"flex h-9 w-9 items-center justify-center rounded-md\",\n\t\t\t\t\t\t\t\t\t\t\ticonVariantStyles[action.variant],\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Icon className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<span className=\"text-xs font-medium\">{action.label}</span>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t</WidgetCard>\n\t\t);\n\t}\n\n\t// List layout (default) - matches recent-items style\n\treturn (\n\t\t<WidgetCard title={title}>\n\t\t\t<div className=\"space-y-1 -mx-1\">\n\t\t\t\t{parsedActions.map((action) => {\n\t\t\t\t\tconst Icon =\n\t\t\t\t\t\taction.icon && typeof action.icon !== \"string\" ? action.icon : null;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={action.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => handleClick(action)}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"flex w-full items-center gap-3 rounded-md px-2 py-2 text-left transition-colors\",\n\t\t\t\t\t\t\t\tvariantStyles[action.variant],\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{Icon && (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"flex h-8 w-8 shrink-0 items-center justify-center rounded-md\",\n\t\t\t\t\t\t\t\t\t\ticonVariantStyles[action.variant],\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<span className=\"flex-1 text-sm font-medium truncate\">\n\t\t\t\t\t\t\t\t{action.label}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<ArrowRight className=\"h-4 w-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity\" />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</WidgetCard>\n\t);\n}\n","/**\n * Recent Items Widget\n *\n * Displays latest items from a collection.\n * Uses WidgetCard for consistent styling.\n */\n\nimport { useCollectionList } from \"../../hooks/use-collection\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { formatCollectionName } from \"../../lib/utils\";\nimport { WidgetCard } from \"../../views/dashboard/widget-card\";\nimport { RecentItemsWidgetSkeleton } from \"./widget-skeletons\";\n\n/**\n * Recent items widget config (local type for component props)\n */\nexport type RecentItemsWidgetConfig = {\n\tcollection: string;\n\tlimit?: number;\n\t/** Field to use as title (default: \"_title\") */\n\ttitleField?: string;\n\t/** Field to use for date (default: \"createdAt\") */\n\tdateField?: string;\n\t/** Fields to display as subtitle */\n\tsubtitleFields?: string[];\n\tlabel?: string;\n\t/** Base path for item links */\n\tbasePath?: string;\n\t/** Click handler for items */\n\tonItemClick?: (item: any) => void;\n};\n\n/**\n * Recent items widget props\n */\nexport type RecentItemsWidgetProps = {\n\tconfig: RecentItemsWidgetConfig;\n};\n\n/**\n * Recent items widget component\n *\n * Displays:\n * - List of most recently created/updated items\n * - Configurable number of items\n * - Links to edit each item\n */\nexport default function RecentItemsWidget({ config }: RecentItemsWidgetProps) {\n\tconst resolveText = useResolveText();\n\tconst {\n\t\tcollection,\n\t\tlimit = 5,\n\t\tlabel,\n\t\ttitleField = \"_title\",\n\t\tdateField = \"createdAt\",\n\t\tsubtitleFields,\n\t\tonItemClick,\n\t} = config;\n\n\t// Fetch recent items sorted by date\n\tconst { data, isLoading, error, refetch } = useCollectionList(\n\t\tcollection as any,\n\t\t{\n\t\t\torderBy: { [dateField]: \"desc\" },\n\t\t\tlimit,\n\t\t} as any,\n\t);\n\n\t// API returns PaginatedResult with { docs, totalDocs, ... }\n\tconst items = Array.isArray(data?.docs) ? data.docs : [];\n\tconst displayLabel = label\n\t\t? resolveText(label)\n\t\t: `Recent ${formatCollectionName(collection)}`;\n\n\t// Determine title field - prefer _title computed field from backend\n\tconst getTitleValue = (item: any): string => {\n\t\tif (titleField && item[titleField]) return String(item[titleField]);\n\t\tif (item._title) return String(item._title);\n\t\tif (item.name) return String(item.name);\n\t\tif (item.title) return String(item.title);\n\t\tif (item.label) return String(item.label);\n\t\treturn `Item #${item.id}`;\n\t};\n\n\t// Get subtitle from fields\n\tconst getSubtitle = (item: any): string | null => {\n\t\tif (!subtitleFields?.length) return null;\n\t\treturn subtitleFields\n\t\t\t.map((field) => item[field])\n\t\t\t.filter(Boolean)\n\t\t\t.join(\" - \");\n\t};\n\n\t// Handle item click\n\tconst handleItemClick = (item: any) => {\n\t\tif (onItemClick) {\n\t\t\tonItemClick(item);\n\t\t}\n\t};\n\n\t// List content\n\tconst listContent =\n\t\titems.length === 0 ? (\n\t\t\t<p className=\"text-sm text-muted-foreground\">No items yet</p>\n\t\t) : (\n\t\t\t<div className=\"space-y-1\">\n\t\t\t\t{items.map((item: any) => {\n\t\t\t\t\tconst dateValue = item[dateField];\n\t\t\t\t\tconst subtitle = getSubtitle(item);\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\tonClick={() => handleItemClick(item)}\n\t\t\t\t\t\t\tclassName=\"flex w-full items-center gap-3 rounded-md p-2 hover:bg-muted/50 cursor-pointer transition-colors text-left\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div className=\"flex-1 min-w-0\">\n\t\t\t\t\t\t\t\t<p className=\"text-sm font-medium truncate\">\n\t\t\t\t\t\t\t\t\t{getTitleValue(item)}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{dateValue && (\n\t\t\t\t\t\t\t\t\t\t<span>{formatRelativeTime(new Date(dateValue))}</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t{subtitle && (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t<span>-</span>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"truncate\">{subtitle}</span>\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t);\n\n\treturn (\n\t\t<WidgetCard\n\t\t\ttitle={displayLabel}\n\t\t\tisLoading={isLoading}\n\t\t\tloadingSkeleton={<RecentItemsWidgetSkeleton count={limit} />}\n\t\t\terror={\n\t\t\t\terror instanceof Error ? error : error ? new Error(String(error)) : null\n\t\t\t}\n\t\t\tonRefresh={() => refetch()}\n\t\t>\n\t\t\t{listContent}\n\t\t</WidgetCard>\n\t);\n}\n\n/**\n * Format relative time\n */\nfunction formatRelativeTime(date: Date): string {\n\tconst now = new Date();\n\tconst diff = now.getTime() - date.getTime();\n\tconst seconds = Math.floor(diff / 1000);\n\tconst minutes = Math.floor(seconds / 60);\n\tconst hours = Math.floor(minutes / 60);\n\tconst days = Math.floor(hours / 24);\n\n\tif (days > 0) return `${days}d ago`;\n\tif (hours > 0) return `${hours}h ago`;\n\tif (minutes > 0) return `${minutes}m ago`;\n\treturn \"just now\";\n}\n","/**\n * Stats Widget\n *\n * Displays count and change percentage for a collection.\n * Uses WidgetCard for consistent styling.\n */\n\nimport type * as React from \"react\";\nimport { useMemo } from \"react\";\nimport type {\n\tDateFilterConfig,\n\tDateFilterPreset,\n} from \"../../builder/types/widget-types\";\nimport { useCollectionCount } from \"../../hooks/use-collection\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn, formatCollectionName } from \"../../lib/utils\";\nimport { WidgetCard } from \"../../views/dashboard/widget-card\";\nimport { StatsWidgetSkeleton } from \"./widget-skeletons\";\n\n/**\n * Stats widget config (local type for component props)\n */\nexport type StatsWidgetConfig = {\n\tcollection: string;\n\tlabel?: string;\n\t/** Static filter (evaluated at build time) */\n\tfilter?: Record<string, any>;\n\t/** Dynamic filter function (evaluated at render time) */\n\tfilterFn?: () => Record<string, any>;\n\t/** Date filter preset (evaluated at render time) */\n\tdateFilter?: DateFilterConfig;\n\t/** Icon component or name */\n\ticon?: React.ComponentType<{ className?: string }> | string;\n\t/** Color variant for the stat card */\n\tvariant?: \"default\" | \"primary\" | \"success\" | \"warning\" | \"danger\";\n};\n\n/**\n * Stats widget props\n */\nexport type StatsWidgetProps = {\n\tconfig: StatsWidgetConfig;\n};\n\n/**\n * Get date range for a preset\n */\nfunction getDateRange(preset: DateFilterPreset): { gte: Date; lte: Date } {\n\tconst now = new Date();\n\tconst today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n\n\tswitch (preset) {\n\t\tcase \"today\":\n\t\t\treturn {\n\t\t\t\tgte: today,\n\t\t\t\tlte: new Date(today.getTime() + 24 * 60 * 60 * 1000 - 1),\n\t\t\t};\n\t\tcase \"yesterday\": {\n\t\t\tconst yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);\n\t\t\treturn {\n\t\t\t\tgte: yesterday,\n\t\t\t\tlte: new Date(today.getTime() - 1),\n\t\t\t};\n\t\t}\n\t\tcase \"thisWeek\": {\n\t\t\tconst dayOfWeek = today.getDay();\n\t\t\tconst monday = new Date(\n\t\t\t\ttoday.getTime() -\n\t\t\t\t\t(dayOfWeek === 0 ? 6 : dayOfWeek - 1) * 24 * 60 * 60 * 1000,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tgte: monday,\n\t\t\t\tlte: now,\n\t\t\t};\n\t\t}\n\t\tcase \"lastWeek\": {\n\t\t\tconst dayOfWeek = today.getDay();\n\t\t\tconst thisMonday = new Date(\n\t\t\t\ttoday.getTime() -\n\t\t\t\t\t(dayOfWeek === 0 ? 6 : dayOfWeek - 1) * 24 * 60 * 60 * 1000,\n\t\t\t);\n\t\t\tconst lastMonday = new Date(\n\t\t\t\tthisMonday.getTime() - 7 * 24 * 60 * 60 * 1000,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tgte: lastMonday,\n\t\t\t\tlte: new Date(thisMonday.getTime() - 1),\n\t\t\t};\n\t\t}\n\t\tcase \"thisMonth\":\n\t\t\treturn {\n\t\t\t\tgte: new Date(now.getFullYear(), now.getMonth(), 1),\n\t\t\t\tlte: now,\n\t\t\t};\n\t\tcase \"lastMonth\": {\n\t\t\tconst firstOfThisMonth = new Date(now.getFullYear(), now.getMonth(), 1);\n\t\t\treturn {\n\t\t\t\tgte: new Date(now.getFullYear(), now.getMonth() - 1, 1),\n\t\t\t\tlte: new Date(firstOfThisMonth.getTime() - 1),\n\t\t\t};\n\t\t}\n\t\tcase \"last7days\":\n\t\t\treturn {\n\t\t\t\tgte: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000),\n\t\t\t\tlte: now,\n\t\t\t};\n\t\tcase \"last30days\":\n\t\t\treturn {\n\t\t\t\tgte: new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000),\n\t\t\t\tlte: now,\n\t\t\t};\n\t\tcase \"last90days\":\n\t\t\treturn {\n\t\t\t\tgte: new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000),\n\t\t\t\tlte: now,\n\t\t\t};\n\t\tcase \"thisYear\":\n\t\t\treturn {\n\t\t\t\tgte: new Date(now.getFullYear(), 0, 1),\n\t\t\t\tlte: now,\n\t\t\t};\n\t\tcase \"lastYear\":\n\t\t\treturn {\n\t\t\t\tgte: new Date(now.getFullYear() - 1, 0, 1),\n\t\t\t\tlte: new Date(now.getFullYear() - 1, 11, 31, 23, 59, 59),\n\t\t\t};\n\t\tdefault:\n\t\t\treturn { gte: today, lte: now };\n\t}\n}\n\n// Variant styles for the card border/background\nconst variantStyles = {\n\tdefault: \"\",\n\tprimary: \"border-primary/30 bg-primary/5\",\n\tsuccess: \"border-green-500/30 bg-green-500/5\",\n\twarning: \"border-yellow-500/30 bg-yellow-500/5\",\n\tdanger: \"border-red-500/30 bg-red-500/5\",\n};\n\n// Variant styles for the value text\nconst variantValueStyles = {\n\tdefault: \"\",\n\tprimary: \"text-primary\",\n\tsuccess: \"text-green-600 dark:text-green-400\",\n\twarning: \"text-yellow-600 dark:text-yellow-400\",\n\tdanger: \"text-red-600 dark:text-red-400\",\n};\n\n/**\n * Stats widget component\n *\n * Shows:\n * - Total count for a collection\n * - Optional icon\n * - Color variant for visual distinction\n */\nexport default function StatsWidget({ config }: StatsWidgetProps) {\n\tconst resolveText = useResolveText();\n\tconst {\n\t\tcollection,\n\t\tlabel,\n\t\tfilter,\n\t\tfilterFn,\n\t\tdateFilter,\n\t\ticon: Icon,\n\t\tvariant = \"default\",\n\t} = config;\n\n\t// Build the final filter - evaluated at render time\n\tconst computedFilter = useMemo(() => {\n\t\tlet result: Record<string, any> = {};\n\n\t\t// 1. Static filter\n\t\tif (filter) {\n\t\t\tresult = { ...result, ...filter };\n\t\t}\n\n\t\t// 2. Dynamic filter function\n\t\tif (filterFn) {\n\t\t\tresult = { ...result, ...filterFn() };\n\t\t}\n\n\t\t// 3. Date filter preset\n\t\tif (dateFilter) {\n\t\t\tconst { gte, lte } = getDateRange(dateFilter.range);\n\t\t\tresult[dateFilter.field] = {\n\t\t\t\tgte: gte.toISOString(),\n\t\t\t\tlte: lte.toISOString(),\n\t\t\t};\n\t\t}\n\n\t\treturn Object.keys(result).length > 0 ? result : undefined;\n\t}, [filter, filterFn, dateFilter]);\n\n\t// Fetch count using dedicated count endpoint (more efficient than fetching all docs)\n\tconst {\n\t\tdata: count = 0,\n\t\tisLoading,\n\t\terror,\n\t\trefetch,\n\t} = useCollectionCount(\n\t\tcollection as any,\n\t\tcomputedFilter ? { where: computedFilter } : undefined,\n\t);\n\n\tconst displayLabel = label\n\t\t? resolveText(label)\n\t\t: formatCollectionName(collection);\n\n\t// Resolve icon - only use if it's a component, not a string\n\tconst IconComponent =\n\t\tIcon && typeof Icon !== \"string\"\n\t\t\t? (Icon as React.ComponentType<{ className?: string }>)\n\t\t\t: undefined;\n\n\treturn (\n\t\t<WidgetCard\n\t\t\ttitle={displayLabel}\n\t\t\ticon={IconComponent}\n\t\t\tisLoading={isLoading}\n\t\t\tloadingSkeleton={<StatsWidgetSkeleton />}\n\t\t\terror={\n\t\t\t\terror instanceof Error ? error : error ? new Error(String(error)) : null\n\t\t\t}\n\t\t\tonRefresh={() => refetch()}\n\t\t\tclassName={variantStyles[variant]}\n\t\t>\n\t\t\t<div className={cn(\"text-2xl font-bold\", variantValueStyles[variant])}>\n\t\t\t\t{count.toLocaleString()}\n\t\t\t</div>\n\t\t</WidgetCard>\n\t);\n}\n","/**\n * Table Widget\n *\n * Displays a mini table with collection data.\n * Automatically uses field definitions from collection config for:\n * - Column labels (from field.label)\n * - Cell rendering (from field.cell)\n *\n * Columns can be simple field keys or objects with overrides.\n */\n\nimport type * as React from \"react\";\nimport type { FieldDefinition } from \"../../builder/field/field\";\nimport type {\n\tTableWidgetColumn,\n\tTableWidgetColumnConfig,\n\tTableWidgetConfig,\n} from \"../../builder/types/widget-types\";\nimport { useCollectionList } from \"../../hooks/use-collection\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport type { I18nText } from \"../../i18n/types\";\nimport { cn } from \"../../lib/utils\";\nimport { selectAdmin, useAdminStore } from \"../../runtime\";\nimport { DefaultCell } from \"../../views/collection/cells/primitive-cells\";\nimport { WidgetCard } from \"../../views/dashboard/widget-card\";\nimport { TableWidgetSkeleton } from \"./widget-skeletons\";\n\n/**\n * Table widget props\n */\nexport interface TableWidgetProps {\n\tconfig: TableWidgetConfig;\n\t/** Base path for navigation */\n\tbasePath?: string;\n\t/** Navigate function for row clicks */\n\tnavigate?: (path: string) => void;\n}\n\n/**\n * Field types that need fieldDef passed to their cell component\n */\nconst FIELD_TYPES_NEEDING_FIELD_DEF = new Set([\n\t\"object\",\n\t\"array\",\n\t\"relation\",\n\t\"reverseRelation\",\n]);\n\n/**\n * Normalize column config - converts string to object format\n */\nfunction normalizeColumn(column: TableWidgetColumn): TableWidgetColumnConfig {\n\tif (typeof column === \"string\") {\n\t\treturn { key: column };\n\t}\n\treturn column;\n}\n\n/**\n * Get column label from field definition or column config\n */\nfunction getColumnLabel(\n\tcolumn: TableWidgetColumnConfig,\n\tfieldDef: FieldDefinition | undefined,\n): I18nText | string {\n\t// Use override if provided\n\tif (column.label) {\n\t\treturn column.label;\n\t}\n\t// Use field label if available\n\tconst fieldOptions = fieldDef?.[\"~options\"] as\n\t\t| { label?: I18nText }\n\t\t| undefined;\n\tif (fieldOptions?.label) {\n\t\treturn fieldOptions.label;\n\t}\n\t// Fallback to formatted key\n\treturn column.key\n\t\t.replace(/([A-Z])/g, \" $1\")\n\t\t.replace(/^./, (s) => s.toUpperCase())\n\t\t.trim();\n}\n\n/**\n * Resolve cell component from field definition\n */\nfunction resolveCellComponent(\n\tfieldDef: FieldDefinition | undefined,\n): React.ComponentType<{\n\tvalue: unknown;\n\trow?: unknown;\n\tfieldDef?: FieldDefinition;\n}> {\n\tif (fieldDef?.cell?.component) {\n\t\treturn fieldDef.cell.component as React.ComponentType<{\n\t\t\tvalue: unknown;\n\t\t\trow?: unknown;\n\t\t\tfieldDef?: FieldDefinition;\n\t\t}>;\n\t}\n\treturn DefaultCell;\n}\n\n/**\n * Table Widget Component\n *\n * Displays a mini table of collection items.\n * Uses field definitions from admin config for labels and cell rendering.\n */\nexport default function TableWidget({\n\tconfig,\n\tbasePath = \"/admin\",\n\tnavigate,\n}: TableWidgetProps) {\n\tconst resolveText = useResolveText();\n\tconst admin = useAdminStore(selectAdmin);\n\n\tconst {\n\t\tcollection,\n\t\tcolumns: rawColumns,\n\t\tlimit = 5,\n\t\tsortBy,\n\t\tsortOrder = \"desc\",\n\t\tfilter,\n\t\tlinkToDetail,\n\t\temptyMessage,\n\t} = config;\n\n\t// Normalize columns (convert strings to objects)\n\tconst columns = rawColumns.map(normalizeColumn);\n\n\t// Get collection config and field definitions from admin\n\tconst collections = admin?.getCollections() ?? {};\n\tconst collectionConfig = collections[collection];\n\tconst fields = (collectionConfig as any)?.fields as\n\t\t| Record<string, FieldDefinition>\n\t\t| undefined;\n\n\t// Build query options\n\tconst queryOptions: any = { limit };\n\tif (sortBy) {\n\t\tqueryOptions.orderBy = { [sortBy]: sortOrder };\n\t}\n\tif (filter) {\n\t\tqueryOptions.where = filter;\n\t}\n\n\t// Fetch collection data\n\tconst { data, isLoading, error, refetch } = useCollectionList(\n\t\tcollection as any,\n\t\tqueryOptions,\n\t);\n\n\tconst items = Array.isArray(data?.docs) ? data.docs : [];\n\tconst title = config.title ? resolveText(config.title) : undefined;\n\n\t// Handle row click\n\tconst handleRowClick = (item: any) => {\n\t\tif (linkToDetail && navigate) {\n\t\t\tnavigate(`${basePath}/collections/${collection}/${item.id}`);\n\t\t}\n\t};\n\n\t// Render cell value\n\tconst renderCell = (\n\t\titem: any,\n\t\tcolumn: TableWidgetColumnConfig,\n\t): React.ReactNode => {\n\t\tconst value = item[column.key];\n\n\t\t// Use custom renderer if provided in column config\n\t\tif (column.render) {\n\t\t\treturn column.render(value, item);\n\t\t}\n\n\t\t// Get field definition and resolve cell component\n\t\tconst fieldDef = fields?.[column.key];\n\t\tconst CellComponent = resolveCellComponent(fieldDef);\n\t\tconst fieldType = fieldDef?.name ?? \"text\";\n\t\tconst needsFieldDef = FIELD_TYPES_NEEDING_FIELD_DEF.has(fieldType);\n\n\t\treturn needsFieldDef ? (\n\t\t\t<CellComponent value={value} row={item} fieldDef={fieldDef} />\n\t\t) : (\n\t\t\t<CellComponent value={value} row={item} />\n\t\t);\n\t};\n\n\t// Empty state\n\tconst emptyContent = (\n\t\t<div className=\"flex h-24 items-center justify-center text-muted-foreground\">\n\t\t\t<p className=\"text-sm\">\n\t\t\t\t{emptyMessage ? resolveText(emptyMessage) : \"No data available\"}\n\t\t\t</p>\n\t\t</div>\n\t);\n\n\t// Table content\n\tconst tableContent =\n\t\titems.length === 0 ? (\n\t\t\temptyContent\n\t\t) : (\n\t\t\t<div className=\"-mx-5 -mb-1\">\n\t\t\t\t{/* Header */}\n\t\t\t\t<div className=\"flex items-center gap-2 px-5 py-2 border-b border-border/30 text-[10px] font-medium uppercase tracking-wider text-muted-foreground bg-muted/20 backdrop-blur-sm\">\n\t\t\t\t\t{columns.map((column) => {\n\t\t\t\t\t\tconst fieldDef = fields?.[column.key];\n\t\t\t\t\t\tconst label = getColumnLabel(column, fieldDef);\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={column.key}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"flex-1 min-w-0\",\n\t\t\t\t\t\t\t\t\tcolumn.align === \"center\" && \"text-center\",\n\t\t\t\t\t\t\t\t\tcolumn.align === \"right\" && \"text-right\",\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t\tcolumn.width\n\t\t\t\t\t\t\t\t\t\t? { width: column.width, flex: \"none\" }\n\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{resolveText(label)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t\t{/* Rows */}\n\t\t\t\t{items.map((item: any) =>\n\t\t\t\t\tlinkToDetail ? (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tclassName=\"flex w-full items-center gap-2 px-5 py-2.5 border-b border-border/20 last:border-0 transition-all cursor-pointer hover:bg-muted/30 hover:backdrop-blur-sm text-left\"\n\t\t\t\t\t\t\tonClick={() => handleRowClick(item)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tkey={column.key}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"flex-1 min-w-0 text-sm truncate\",\n\t\t\t\t\t\t\t\t\t\tcolumn.align === \"center\" && \"text-center\",\n\t\t\t\t\t\t\t\t\t\tcolumn.align === \"right\" && \"text-right\",\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t\t\tcolumn.width\n\t\t\t\t\t\t\t\t\t\t\t? { width: column.width, flex: \"none\" }\n\t\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{renderCell(item, column)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\tclassName=\"flex items-center gap-2 px-5 py-2.5 border-b border-border/20 last:border-0\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tkey={column.key}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"flex-1 min-w-0 text-sm truncate\",\n\t\t\t\t\t\t\t\t\t\tcolumn.align === \"center\" && \"text-center\",\n\t\t\t\t\t\t\t\t\t\tcolumn.align === \"right\" && \"text-right\",\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t\t\tcolumn.width\n\t\t\t\t\t\t\t\t\t\t\t? { width: column.width, flex: \"none\" }\n\t\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{renderCell(item, column)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t),\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\n\treturn (\n\t\t<WidgetCard\n\t\t\ttitle={title}\n\t\t\tisLoading={isLoading}\n\t\t\tloadingSkeleton={\n\t\t\t\t<TableWidgetSkeleton rows={limit} columns={columns.length} />\n\t\t\t}\n\t\t\terror={\n\t\t\t\terror instanceof Error ? error : error ? new Error(String(error)) : null\n\t\t\t}\n\t\t\tonRefresh={() => refetch()}\n\t\t>\n\t\t\t{tableContent}\n\t\t</WidgetCard>\n\t);\n}\n","/**\n * Timeline Widget\n *\n * Displays an activity/event timeline.\n * Uses WidgetCard for consistent styling.\n */\n\nimport { Circle } from \"@phosphor-icons/react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport type * as React from \"react\";\nimport type {\n\tTimelineItem,\n\tTimelineWidgetConfig,\n} from \"../../builder/types/widget-types\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { selectClient, useAdminStore } from \"../../runtime\";\nimport { WidgetCard } from \"../../views/dashboard/widget-card\";\nimport { TimelineWidgetSkeleton } from \"./widget-skeletons\";\n\n/**\n * Timeline widget props\n */\nexport interface TimelineWidgetProps {\n\tconfig: TimelineWidgetConfig;\n\t/** Navigate function for item clicks */\n\tnavigate?: (path: string) => void;\n}\n\n// Variant styles for timeline items\nconst variantStyles = {\n\tdefault: \"bg-muted-foreground\",\n\tsuccess: \"bg-green-500\",\n\twarning: \"bg-yellow-500\",\n\terror: \"bg-red-500\",\n\tinfo: \"bg-blue-500\",\n};\n\n/**\n * Format timestamp based on format option\n */\nfunction formatTimestamp(\n\tdate: Date | string,\n\tformat: TimelineWidgetConfig[\"timestampFormat\"] = \"relative\",\n): string {\n\tconst d = typeof date === \"string\" ? new Date(date) : date;\n\n\tswitch (format) {\n\t\tcase \"absolute\":\n\t\t\treturn d.toLocaleDateString();\n\n\t\tcase \"datetime\":\n\t\t\treturn d.toLocaleString();\n\n\t\tcase \"relative\":\n\t\tdefault: {\n\t\t\tconst now = new Date();\n\t\t\tconst diff = now.getTime() - d.getTime();\n\t\t\tconst seconds = Math.floor(diff / 1000);\n\t\t\tconst minutes = Math.floor(seconds / 60);\n\t\t\tconst hours = Math.floor(minutes / 60);\n\t\t\tconst days = Math.floor(hours / 24);\n\n\t\t\tif (days > 7) return d.toLocaleDateString();\n\t\t\tif (days > 0) return `${days}d ago`;\n\t\t\tif (hours > 0) return `${hours}h ago`;\n\t\t\tif (minutes > 0) return `${minutes}m ago`;\n\t\t\treturn \"just now\";\n\t\t}\n\t}\n}\n\n/**\n * Timeline Widget Component\n *\n * Displays a vertical timeline of events/activities.\n *\n * @example\n * ```tsx\n * <TimelineWidget\n * config={{\n * type: \"timeline\",\n * id: \"recent-activity\",\n * title: \"Recent Activity\",\n * fetchFn: async (client) => {\n * const activities = await client.collections.activities.findMany({\n * limit: 10,\n * orderBy: { createdAt: \"desc\" }\n * });\n * return activities.map(a => ({\n * id: a.id,\n * title: a.action,\n * description: a.description,\n * timestamp: a.createdAt,\n * variant: a.type === \"error\" ? \"error\" : \"default\"\n * }));\n * }\n * }}\n * />\n * ```\n */\nexport default function TimelineWidget({\n\tconfig,\n\tnavigate,\n}: TimelineWidgetProps) {\n\tconst client = useAdminStore(selectClient);\n\tconst resolveText = useResolveText();\n\tconst {\n\t\tmaxItems = 10,\n\t\tshowTimestamps = true,\n\t\ttimestampFormat = \"relative\",\n\t\temptyMessage,\n\t} = config;\n\n\tconst { data, isLoading, error, refetch } = useQuery<TimelineItem[]>({\n\t\tqueryKey: [\"widget\", \"timeline\", config.id],\n\t\tqueryFn: () => config.fetchFn(client),\n\t\trefetchInterval: config.refreshInterval,\n\t});\n\n\tconst items = data?.slice(0, maxItems) ?? [];\n\tconst title = config.title ? resolveText(config.title) : undefined;\n\n\t// Handle item click\n\tconst handleItemClick = (item: TimelineItem) => {\n\t\tif (item.href && navigate) {\n\t\t\tnavigate(item.href);\n\t\t}\n\t};\n\n\t// Empty state\n\tconst emptyContent = (\n\t\t<div className=\"flex h-24 items-center justify-center text-muted-foreground\">\n\t\t\t<p className=\"text-sm\">\n\t\t\t\t{emptyMessage ? resolveText(emptyMessage) : \"No activity yet\"}\n\t\t\t</p>\n\t\t</div>\n\t);\n\n\t// Timeline content\n\tconst timelineContent =\n\t\titems.length === 0 ? (\n\t\t\temptyContent\n\t\t) : (\n\t\t\t<div className=\"space-y-0\">\n\t\t\t\t{items.map((item, index) => {\n\t\t\t\t\tconst Icon = item.icon || Circle;\n\t\t\t\t\tconst variant = item.variant || \"default\";\n\t\t\t\t\tconst isLast = index === items.length - 1;\n\t\t\t\t\tconst isClickable = !!(item.href && navigate);\n\n\t\t\t\t\tconst itemContent = (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{/* Timeline line */}\n\t\t\t\t\t\t\t{!isLast && (\n\t\t\t\t\t\t\t\t<div className=\"absolute left-[11px] top-6 bottom-0 w-px bg-border\" />\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* Icon dot */}\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"relative z-10 flex h-6 w-6 shrink-0 items-center justify-center rounded-full\",\n\t\t\t\t\t\t\t\t\tvariantStyles[variant],\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Icon className=\"h-3 w-3 text-white\" weight=\"bold\" />\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{/* Content */}\n\t\t\t\t\t\t\t<div className=\"flex-1 min-w-0 pt-0.5 text-left\">\n\t\t\t\t\t\t\t\t<p className=\"text-sm font-medium truncate\">{item.title}</p>\n\t\t\t\t\t\t\t\t{item.description && (\n\t\t\t\t\t\t\t\t\t<p className=\"text-xs text-muted-foreground mt-0.5 line-clamp-2\">\n\t\t\t\t\t\t\t\t\t\t{item.description}\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{showTimestamps && item.timestamp && (\n\t\t\t\t\t\t\t\t\t<p className=\"text-xs text-muted-foreground mt-1\">\n\t\t\t\t\t\t\t\t\t\t{formatTimestamp(item.timestamp, timestampFormat)}\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</>\n\t\t\t\t\t);\n\n\t\t\t\t\tif (isClickable) {\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"relative flex gap-3 pb-4 w-full\",\n\t\t\t\t\t\t\t\t\t\"cursor-pointer hover:bg-muted/30 -mx-2 px-2 rounded-md transition-colors\",\n\t\t\t\t\t\t\t\t\tisLast && \"pb-0\",\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\tonClick={() => handleItemClick(item)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{itemContent}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\tclassName={cn(\"relative flex gap-3 pb-4\", isLast && \"pb-0\")}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{itemContent}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t);\n\n\treturn (\n\t\t<WidgetCard\n\t\t\ttitle={title}\n\t\t\tisLoading={isLoading}\n\t\t\tloadingSkeleton={<TimelineWidgetSkeleton count={maxItems} />}\n\t\t\terror={\n\t\t\t\terror instanceof Error ? error : error ? new Error(String(error)) : null\n\t\t\t}\n\t\t\tonRefresh={() => refetch()}\n\t\t>\n\t\t\t{timelineContent}\n\t\t</WidgetCard>\n\t);\n}\n","/**\n * Value Widget\n *\n * Flexible widget with async data fetching and full Tailwind customization.\n * Uses WidgetCard for consistent styling while allowing custom classNames.\n */\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport type {\n\tValueWidgetConfig,\n\tValueWidgetResult,\n} from \"../../builder/types/widget-types\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { selectClient, useAdminStore } from \"../../runtime\";\nimport { WidgetCard } from \"../../views/dashboard/widget-card\";\nimport { ValueWidgetSkeleton } from \"./widget-skeletons\";\n\n/**\n * Value widget props\n */\nexport interface ValueWidgetProps {\n\tconfig: ValueWidgetConfig;\n}\n\n/**\n * Format value for display\n */\nfunction formatValue(value: number | string): string {\n\tif (typeof value === \"number\") {\n\t\treturn value.toLocaleString();\n\t}\n\treturn value;\n}\n\n/**\n * Value Widget Component\n *\n * Fetches data via async function and renders with full customization.\n *\n * @example\n * ```tsx\n * <ValueWidget\n * config={{\n * type: \"value\",\n * id: \"total-revenue\",\n * fetchFn: async (client) => ({\n * value: 42,\n * label: \"Total\",\n * classNames: { root: \"bg-blue-50\" },\n * }),\n * }}\n * />\n * ```\n */\nexport default function ValueWidget({ config }: ValueWidgetProps) {\n\tconst client = useAdminStore(selectClient);\n\tconst resolveText = useResolveText();\n\n\tconst { data, isLoading, error, refetch, isFetching } =\n\t\tuseQuery<ValueWidgetResult>({\n\t\t\tqueryKey: [\"widget\", \"value\", config.id],\n\t\t\tqueryFn: () => config.fetchFn(client),\n\t\t\trefetchInterval: config.refreshInterval,\n\t\t});\n\n\t// Determine if this is a featured variant based on config\n\tconst isFeatured = config.cardVariant === \"featured\";\n\n\t// Handle loading/error via WidgetCard\n\tif (isLoading || error || !data) {\n\t\treturn (\n\t\t\t<WidgetCard\n\t\t\t\ttitle={config.title ? resolveText(config.title) : undefined}\n\t\t\t\tisLoading={isLoading}\n\t\t\t\tloadingSkeleton={<ValueWidgetSkeleton featured={isFeatured} />}\n\t\t\t\terror={\n\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t? error\n\t\t\t\t\t\t: !data && !isLoading\n\t\t\t\t\t\t\t? new Error(\"No data returned\")\n\t\t\t\t\t\t\t: null\n\t\t\t\t}\n\t\t\t\tonRefresh={() => refetch()}\n\t\t\t\tclassName={data?.classNames?.root}\n\t\t\t/>\n\t\t);\n\t}\n\n\tconst cls = data.classNames ?? {};\n\tconst Icon = data.icon;\n\tconst TrendIcon = data.trend?.icon;\n\n\t// Resolve all text fields (supports both string and i18n objects)\n\tconst label = data.label ? resolveText(data.label) : undefined;\n\tconst subtitle = data.subtitle ? resolveText(data.subtitle) : undefined;\n\tconst footer = data.footer ? resolveText(data.footer) : undefined;\n\n\treturn (\n\t\t<WidgetCard\n\t\t\ttitle={label}\n\t\t\ticon={Icon}\n\t\t\tonRefresh={() => refetch()}\n\t\t\tisRefreshing={isFetching && !isLoading}\n\t\t\tclassName={cls.root}\n\t\t>\n\t\t\t<div className={cn(\"space-y-1\", cls.content)}>\n\t\t\t\t{/* Main value */}\n\t\t\t\t<div className={cn(\"text-2xl font-bold\", cls.value)}>\n\t\t\t\t\t{data.formatted ?? formatValue(data.value)}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Trend indicator */}\n\t\t\t\t{data.trend && (\n\t\t\t\t\t<div className={cn(\"flex items-center gap-1 text-sm\", cls.trend)}>\n\t\t\t\t\t\t{TrendIcon && (\n\t\t\t\t\t\t\t<TrendIcon className={cn(\"h-3 w-3\", cls.trendIcon)} />\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<span>{data.trend.value}</span>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Subtitle */}\n\t\t\t\t{subtitle && (\n\t\t\t\t\t<p className={cn(\"text-xs text-muted-foreground\", cls.subtitle)}>\n\t\t\t\t\t\t{subtitle}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\n\t\t\t\t{/* Footer */}\n\t\t\t\t{footer && (\n\t\t\t\t\t<p className={cn(\"text-xs text-muted-foreground pt-2\", cls.footer)}>\n\t\t\t\t\t\t{footer}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</WidgetCard>\n\t);\n}\n","/**\n * DashboardWidget Component\n *\n * Renders individual dashboard widgets based on their type configuration.\n * Supports built-in widget types and custom components.\n */\n\nimport * as React from \"react\";\nimport type {\n\tAnyWidgetConfig,\n\tChartWidgetConfig,\n\tProgressWidgetConfig,\n\tQuickActionsWidgetConfig,\n\tRecentItemsWidgetConfig,\n\tStatsWidgetConfig,\n\tTableWidgetConfig,\n\tTimelineWidgetConfig,\n\tValueWidgetConfig,\n\tWidgetComponentProps,\n} from \"../../builder\";\nimport { WidgetErrorBoundary } from \"../../components/error-boundary\";\nimport ChartWidget from \"../../components/widgets/chart-widget\";\nimport ProgressWidget from \"../../components/widgets/progress-widget\";\nimport QuickActionsWidget from \"../../components/widgets/quick-actions-widget\";\nimport RecentItemsWidget from \"../../components/widgets/recent-items-widget\";\n// Import built-in widgets\nimport StatsWidget from \"../../components/widgets/stats-widget\";\nimport TableWidget from \"../../components/widgets/table-widget\";\nimport TimelineWidget from \"../../components/widgets/timeline-widget\";\nimport ValueWidget from \"../../components/widgets/value-widget\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { WidgetCard } from \"./widget-card\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardWidgetProps {\n\t/**\n\t * Widget configuration\n\t */\n\tconfig: AnyWidgetConfig;\n\n\t/**\n\t * Base path for navigation links\n\t */\n\tbasePath?: string;\n\n\t/**\n\t * Navigate function for item clicks\n\t */\n\tnavigate?: (path: string) => void;\n\n\t/**\n\t * Custom widget registry for overrides\n\t */\n\twidgetRegistry?: Record<string, React.ComponentType<WidgetComponentProps>>;\n}\n\n// ============================================================================\n// Loading & Error States\n// ============================================================================\n\nfunction UnknownWidget({ type }: { type: string }) {\n\treturn (\n\t\t<WidgetCard\n\t\t\ttitle=\"Unknown Widget\"\n\t\t\tclassName=\"border-yellow-500/20 bg-yellow-500/5\"\n\t\t>\n\t\t\t<p className=\"text-xs text-muted-foreground\">\n\t\t\t\tWidget type \"{type}\" is not recognized.\n\t\t\t</p>\n\t\t</WidgetCard>\n\t);\n}\n\n// ============================================================================\n// Custom Widget Renderer (handles lazy loading)\n// ============================================================================\n\ninterface CustomWidgetRendererProps {\n\tloader: any;\n\twidgetConfig: Record<string, any>;\n\tspan?: number;\n}\n\nfunction CustomWidgetRenderer({\n\tloader,\n\twidgetConfig,\n\tspan,\n}: CustomWidgetRendererProps) {\n\tconst [state, setState] = React.useState<{\n\t\tComponent: React.ComponentType<WidgetComponentProps> | null;\n\t\tloading: boolean;\n\t\terror: Error | null;\n\t}>({\n\t\tComponent: null,\n\t\tloading: true,\n\t\terror: null,\n\t});\n\n\tReact.useEffect(() => {\n\t\tif (!loader) {\n\t\t\tsetState({ Component: null, loading: false, error: null });\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if it's already a component (not a lazy loader function)\n\t\tconst isLazyLoader =\n\t\t\ttypeof loader === \"function\" &&\n\t\t\t!loader.prototype?.render &&\n\t\t\t!loader.prototype?.isReactComponent &&\n\t\t\tloader.length === 0;\n\n\t\tif (!isLazyLoader) {\n\t\t\tsetState({ Component: loader, loading: false, error: null });\n\t\t\treturn;\n\t\t}\n\n\t\t// Load lazy component\n\t\tlet mounted = true;\n\n\t\t(async () => {\n\t\t\ttry {\n\t\t\t\tconst result = await loader();\n\t\t\t\tif (mounted) {\n\t\t\t\t\tconst Component = result.default || result;\n\t\t\t\t\tsetState({ Component, loading: false, error: null });\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tif (mounted) {\n\t\t\t\t\tsetState({\n\t\t\t\t\t\tComponent: null,\n\t\t\t\t\t\tloading: false,\n\t\t\t\t\t\terror:\n\t\t\t\t\t\t\terr instanceof Error\n\t\t\t\t\t\t\t\t? err\n\t\t\t\t\t\t\t\t: new Error(\"Failed to load component\"),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\treturn () => {\n\t\t\tmounted = false;\n\t\t};\n\t}, [loader]);\n\n\tif (state.loading) {\n\t\treturn <WidgetCard isLoading />;\n\t}\n\n\tif (state.error) {\n\t\treturn <WidgetCard error={state.error} />;\n\t}\n\n\tif (!state.Component) {\n\t\treturn <WidgetCard error={new Error(\"Component not found\")} />;\n\t}\n\n\tconst Component = state.Component;\n\treturn <Component config={widgetConfig} span={span} />;\n}\n\n// ============================================================================\n// Built-in Widget Renderers\n// ============================================================================\n\nfunction StatsWidgetRenderer({ config }: { config: StatsWidgetConfig }) {\n\tconst resolveText = useResolveText();\n\treturn (\n\t\t<StatsWidget\n\t\t\tconfig={{\n\t\t\t\tcollection: config.collection,\n\t\t\t\tlabel: config.label ? resolveText(config.label) : undefined,\n\t\t\t\tfilter: config.filter,\n\t\t\t\tfilterFn: config.filterFn,\n\t\t\t\tdateFilter: config.dateFilter,\n\t\t\t\ticon: config.icon,\n\t\t\t\tvariant: config.variant,\n\t\t\t}}\n\t\t/>\n\t);\n}\n\nfunction ChartWidgetRenderer({ config }: { config: ChartWidgetConfig }) {\n\tconst resolveText = useResolveText();\n\treturn (\n\t\t<ChartWidget\n\t\t\tconfig={{\n\t\t\t\tcollection: config.collection,\n\t\t\t\tfield: config.field,\n\t\t\t\tchartType: config.chartType,\n\t\t\t\ttimeRange: config.timeRange,\n\t\t\t\tlabel: config.label ? resolveText(config.label) : undefined,\n\t\t\t\tcolor: config.color,\n\t\t\t\tshowGrid: config.showGrid,\n\t\t\t\taggregation: config.aggregation,\n\t\t\t\tvalueField: config.valueField,\n\t\t\t}}\n\t\t/>\n\t);\n}\n\nfunction RecentItemsWidgetRenderer({\n\tconfig,\n\tbasePath,\n\tnavigate,\n}: {\n\tconfig: RecentItemsWidgetConfig;\n\tbasePath: string;\n\tnavigate?: (path: string) => void;\n}) {\n\tconst resolveText = useResolveText();\n\treturn (\n\t\t<RecentItemsWidget\n\t\t\tconfig={{\n\t\t\t\tcollection: config.collection,\n\t\t\t\tlimit: config.limit,\n\t\t\t\tlabel: config.label ? resolveText(config.label) : undefined,\n\t\t\t\ttitleField: config.titleField,\n\t\t\t\tdateField: config.dateField,\n\t\t\t\tsubtitleFields: config.subtitleFields,\n\t\t\t\tbasePath,\n\t\t\t\tonItemClick: navigate\n\t\t\t\t\t? (item: any) =>\n\t\t\t\t\t\t\tnavigate(\n\t\t\t\t\t\t\t\t`${basePath}/collections/${config.collection}/${item.id}`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t: undefined,\n\t\t\t}}\n\t\t/>\n\t);\n}\n\nfunction QuickActionsWidgetRenderer({\n\tconfig,\n\tbasePath,\n\tnavigate,\n}: {\n\tconfig: QuickActionsWidgetConfig;\n\tbasePath: string;\n\tnavigate?: (path: string) => void;\n}) {\n\treturn (\n\t\t<QuickActionsWidget\n\t\t\tconfig={config}\n\t\t\tbasePath={basePath}\n\t\t\tnavigate={navigate}\n\t\t/>\n\t);\n}\n\nfunction TableWidgetRenderer({\n\tconfig,\n\tbasePath,\n\tnavigate,\n}: {\n\tconfig: TableWidgetConfig;\n\tbasePath: string;\n\tnavigate?: (path: string) => void;\n}) {\n\treturn (\n\t\t<TableWidget config={config} basePath={basePath} navigate={navigate} />\n\t);\n}\n\nfunction TimelineWidgetRenderer({\n\tconfig,\n\tnavigate,\n}: {\n\tconfig: TimelineWidgetConfig;\n\tnavigate?: (path: string) => void;\n}) {\n\treturn <TimelineWidget config={config} navigate={navigate} />;\n}\n\nfunction ProgressWidgetRenderer({ config }: { config: ProgressWidgetConfig }) {\n\treturn <ProgressWidget config={config} />;\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * DashboardWidget - Renders a single widget based on its configuration\n *\n * @example\n * ```tsx\n * <DashboardWidget\n * config={{ type: \"stats\", collection: \"posts\", label: \"Total Posts\" }}\n * basePath=\"/admin\"\n * navigate={navigate}\n * />\n * ```\n */\nexport function DashboardWidget({\n\tconfig,\n\tbasePath = \"/admin\",\n\tnavigate,\n\twidgetRegistry,\n}: DashboardWidgetProps): React.ReactElement {\n\t// Wrap all widget rendering in ErrorBoundary to prevent crashes\n\tconst renderWidget = (): React.ReactElement => {\n\t\t// Handle custom widget type\n\t\tif (config.type === \"custom\") {\n\t\t\treturn (\n\t\t\t\t<CustomWidgetRenderer\n\t\t\t\t\tloader={config.component}\n\t\t\t\t\twidgetConfig={config.config || {}}\n\t\t\t\t\tspan={config.span}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\n\t\t// Check widget registry for overrides\n\t\tif (widgetRegistry?.[config.type]) {\n\t\t\tconst CustomWidget = widgetRegistry[config.type];\n\t\t\treturn <CustomWidget config={config as any} span={config.span} />;\n\t\t}\n\n\t\t// Render built-in widgets - use type assertions since GenericWidgetConfig\n\t\t// prevents proper narrowing\n\t\tswitch (config.type) {\n\t\t\tcase \"stats\":\n\t\t\t\treturn <StatsWidgetRenderer config={config as StatsWidgetConfig} />;\n\n\t\t\tcase \"chart\":\n\t\t\t\treturn <ChartWidgetRenderer config={config as ChartWidgetConfig} />;\n\n\t\t\tcase \"recentItems\":\n\t\t\t\treturn (\n\t\t\t\t\t<RecentItemsWidgetRenderer\n\t\t\t\t\t\tconfig={config as RecentItemsWidgetConfig}\n\t\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\t/>\n\t\t\t\t);\n\n\t\t\tcase \"quickActions\":\n\t\t\t\treturn (\n\t\t\t\t\t<QuickActionsWidgetRenderer\n\t\t\t\t\t\tconfig={config as QuickActionsWidgetConfig}\n\t\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\t/>\n\t\t\t\t);\n\n\t\t\tcase \"value\":\n\t\t\t\treturn <ValueWidget config={config as ValueWidgetConfig} />;\n\n\t\t\tcase \"table\":\n\t\t\t\treturn (\n\t\t\t\t\t<TableWidgetRenderer\n\t\t\t\t\t\tconfig={config as TableWidgetConfig}\n\t\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\t/>\n\t\t\t\t);\n\n\t\t\tcase \"timeline\":\n\t\t\t\treturn (\n\t\t\t\t\t<TimelineWidgetRenderer\n\t\t\t\t\t\tconfig={config as TimelineWidgetConfig}\n\t\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\t/>\n\t\t\t\t);\n\n\t\t\tcase \"progress\":\n\t\t\t\treturn (\n\t\t\t\t\t<ProgressWidgetRenderer config={config as ProgressWidgetConfig} />\n\t\t\t\t);\n\n\t\t\tdefault:\n\t\t\t\treturn <UnknownWidget type={config.type} />;\n\t\t}\n\t};\n\n\treturn (\n\t\t<WidgetErrorBoundary widgetType={config.type}>\n\t\t\t{renderWidget()}\n\t\t</WidgetErrorBoundary>\n\t);\n}\n\nexport default DashboardWidget;\n","/**\n * DashboardGrid Component\n *\n * Renders a grid of dashboard widgets based on configuration.\n * Supports:\n * - Responsive layouts with container queries\n * - Widget spanning\n * - Dashboard sections (grouped widgets)\n * - Dashboard tabs (tabbed widget groups)\n * - Recursive nesting of sections/tabs\n */\n\nimport type * as React from \"react\";\nimport type {\n\tDashboardAction,\n\tDashboardConfig,\n\tDashboardLayoutItem,\n\tDashboardSection,\n\tDashboardTabConfig,\n\tDashboardTabs,\n\tWidgetComponentProps,\n\tWidgetConfig,\n} from \"../../builder\";\nimport {\n\tAccordion,\n\tAccordionContent,\n\tAccordionItem,\n\tAccordionTrigger,\n} from \"../../components/ui/accordion\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n\tCard,\n\tCardContent,\n\tCardHeader,\n\tCardTitle,\n} from \"../../components/ui/card\";\nimport {\n\tTabs,\n\tTabsContent,\n\tTabsList,\n\tTabsTrigger,\n} from \"../../components/ui/tabs\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { DashboardWidget } from \"./dashboard-widget\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardGridProps {\n\t/**\n\t * Dashboard configuration\n\t */\n\tconfig: DashboardConfig;\n\n\t/**\n\t * Base path for navigation links (default: \"/admin\")\n\t */\n\tbasePath?: string;\n\n\t/**\n\t * Navigate function for item clicks\n\t */\n\tnavigate?: (path: string) => void;\n\n\t/**\n\t * Custom widget registry for overrides\n\t */\n\twidgetRegistry?: Record<string, React.ComponentType<WidgetComponentProps>>;\n\n\t/**\n\t * Additional CSS class\n\t */\n\tclassName?: string;\n}\n\n// ============================================================================\n// Grid Classes - Using Container Queries\n// ============================================================================\n\n/**\n * Grid column classes for different column counts\n * Uses container queries (@container) for responsive behavior\n */\nconst gridClasses: Record<number, string> = {\n\t1: \"grid-cols-1\",\n\t2: \"grid-cols-1 @xs:grid-cols-2\",\n\t3: \"grid-cols-1 @xs:grid-cols-2 @md:grid-cols-3\",\n\t4: \"grid-cols-1 @xs:grid-cols-2 @md:grid-cols-3 @lg:grid-cols-4\",\n\t5: \"grid-cols-1 @xs:grid-cols-2 @sm:grid-cols-3 @md:grid-cols-4 @lg:grid-cols-5\",\n\t6: \"grid-cols-1 @xs:grid-cols-2 @sm:grid-cols-3 @md:grid-cols-4 @lg:grid-cols-5 @xl:grid-cols-6\",\n\t12: \"grid-cols-1 @xs:grid-cols-2 @sm:grid-cols-4 @md:grid-cols-6 @lg:grid-cols-12\",\n};\n\n/**\n * Span classes for widget column spanning\n */\nconst spanClasses: Record<number, string> = {\n\t1: \"col-span-1\",\n\t2: \"col-span-1 @xs:col-span-2\",\n\t3: \"col-span-1 @xs:col-span-2 @md:col-span-3\",\n\t4: \"col-span-1 @xs:col-span-2 @md:col-span-3 @lg:col-span-4\",\n\t5: \"col-span-1 @xs:col-span-2 @md:col-span-3 @lg:col-span-5\",\n\t6: \"col-span-1 @xs:col-span-2 @md:col-span-3 @lg:col-span-6\",\n\t12: \"col-span-full\",\n};\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Get grid columns class based on column count\n */\nfunction getGridClass(columns: number): string {\n\treturn gridClasses[columns] || gridClasses[4];\n}\n\n/**\n * Get column span class for a widget\n */\nfunction getSpanClass(span: number | undefined): string {\n\tif (!span || span <= 1) return \"\";\n\treturn spanClasses[span] || \"\";\n}\n\n/**\n * Check if item is a widget config\n */\nfunction isWidgetConfig(item: DashboardLayoutItem): item is WidgetConfig {\n\treturn (\n\t\ttypeof item === \"object\" &&\n\t\t\"type\" in item &&\n\t\titem.type !== \"section\" &&\n\t\titem.type !== \"tabs\"\n\t);\n}\n\n/**\n * Check if item is a section config\n */\nfunction isSectionConfig(item: DashboardLayoutItem): item is DashboardSection {\n\treturn typeof item === \"object\" && \"type\" in item && item.type === \"section\";\n}\n\n/**\n * Check if item is a tabs config\n */\nfunction isTabsConfig(item: DashboardLayoutItem): item is DashboardTabs {\n\treturn typeof item === \"object\" && \"type\" in item && item.type === \"tabs\";\n}\n\n/**\n * Generate a unique key for a layout item\n */\nfunction getLayoutItemKey(item: DashboardLayoutItem, index: number): string {\n\tif (isWidgetConfig(item)) {\n\t\treturn `widget-${item.id || item.type}-${index}`;\n\t}\n\tif (isSectionConfig(item)) {\n\t\treturn `section-${index}`;\n\t}\n\tif (isTabsConfig(item)) {\n\t\tconst tabIds = item.tabs.map((t) => t.id).join(\"-\");\n\t\treturn `tabs-${tabIds || index}`;\n\t}\n\treturn `item-${index}`;\n}\n\n// ============================================================================\n// Sub-components\n// ============================================================================\n\ninterface DashboardHeaderProps {\n\ttitle?: string;\n\tdescription?: string;\n\tactions?: DashboardAction[];\n\tnavigate?: (path: string) => void;\n\tresolveText: (text: any) => string;\n}\n\nfunction DashboardHeader({\n\ttitle,\n\tdescription,\n\tactions,\n\tnavigate,\n\tresolveText,\n}: DashboardHeaderProps) {\n\tif (!title && !description && !actions?.length) return null;\n\n\tconst handleActionClick = (action: DashboardAction) => {\n\t\tif (action.onClick) {\n\t\t\taction.onClick();\n\t\t} else if (action.href && navigate) {\n\t\t\tnavigate(action.href);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className=\"mb-8 flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n\t\t\t<div className=\"min-w-0 flex-1\">\n\t\t\t\t{title && (\n\t\t\t\t\t<h1 className=\"text-2xl md:text-3xl font-extrabold tracking-tight\">\n\t\t\t\t\t\t{title}\n\t\t\t\t\t</h1>\n\t\t\t\t)}\n\t\t\t\t{description && (\n\t\t\t\t\t<p className=\"mt-1 text-muted-foreground\">{description}</p>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t{actions && actions.length > 0 && (\n\t\t\t\t<div className=\"flex items-center gap-2 shrink-0\">\n\t\t\t\t\t{actions.map((action) => {\n\t\t\t\t\t\tconst Icon =\n\t\t\t\t\t\t\taction.icon && typeof action.icon !== \"string\"\n\t\t\t\t\t\t\t\t? action.icon\n\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\tconst variant = action.variant || \"default\";\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tkey={action.id}\n\t\t\t\t\t\t\t\tvariant={variant === \"primary\" ? \"default\" : variant}\n\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\tonClick={() => handleActionClick(action)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{Icon && <Icon className=\"h-4 w-4 mr-2\" />}\n\t\t\t\t\t\t\t\t{resolveText(action.label)}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Layout Item Renderer\n// ============================================================================\n\ninterface LayoutItemRendererProps {\n\titem: DashboardLayoutItem;\n\tindex: number;\n\tcolumns: number;\n\tbasePath: string;\n\tnavigate?: (path: string) => void;\n\twidgetRegistry?: Record<string, React.ComponentType<WidgetComponentProps>>;\n\tresolveText: (text: any) => string;\n}\n\nfunction LayoutItemRenderer({\n\titem,\n\tindex,\n\tcolumns,\n\tbasePath,\n\tnavigate,\n\twidgetRegistry,\n\tresolveText,\n}: LayoutItemRendererProps) {\n\t// Widget\n\tif (isWidgetConfig(item)) {\n\t\tconst spanClass = getSpanClass(item.span);\n\t\treturn (\n\t\t\t<div className={cn(\"min-h-0 h-full\", spanClass)}>\n\t\t\t\t<DashboardWidget\n\t\t\t\t\tconfig={item}\n\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\twidgetRegistry={widgetRegistry}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Section\n\tif (isSectionConfig(item)) {\n\t\treturn (\n\t\t\t<SectionRenderer\n\t\t\t\tkey={`section-${index}`}\n\t\t\t\tsection={item}\n\t\t\t\tbasePath={basePath}\n\t\t\t\tnavigate={navigate}\n\t\t\t\twidgetRegistry={widgetRegistry}\n\t\t\t\tresolveText={resolveText}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// Tabs\n\tif (isTabsConfig(item)) {\n\t\treturn (\n\t\t\t<TabsRenderer\n\t\t\t\tkey={`tabs-${index}`}\n\t\t\t\ttabs={item}\n\t\t\t\tbasePath={basePath}\n\t\t\t\tnavigate={navigate}\n\t\t\t\twidgetRegistry={widgetRegistry}\n\t\t\t\tresolveText={resolveText}\n\t\t\t/>\n\t\t);\n\t}\n\n\treturn null;\n}\n\n// ============================================================================\n// Section Renderer\n// ============================================================================\n\ninterface SectionRendererProps {\n\tsection: DashboardSection;\n\tbasePath: string;\n\tnavigate?: (path: string) => void;\n\twidgetRegistry?: Record<string, React.ComponentType<WidgetComponentProps>>;\n\tresolveText: (text: any) => string;\n}\n\nfunction SectionRenderer({\n\tsection,\n\tbasePath,\n\tnavigate,\n\twidgetRegistry,\n\tresolveText,\n}: SectionRendererProps) {\n\tconst {\n\t\tlabel,\n\t\tdescription,\n\t\twrapper = \"flat\",\n\t\tdefaultCollapsed = false,\n\t\tlayout = \"grid\",\n\t\tcolumns = 4,\n\t\tgap,\n\t\titems,\n\t\tclassName,\n\t} = section;\n\n\tconst sectionLabel = label ? resolveText(label) : undefined;\n\tconst sectionDescription = description ? resolveText(description) : undefined;\n\n\t// Render items grid with container queries\n\tconst itemsContent = (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"@container\",\n\t\t\t\tlayout === \"grid\" && \"grid gap-4 items-stretch\",\n\t\t\t\tlayout === \"grid\" && getGridClass(columns),\n\t\t\t\tlayout === \"stack\" && \"flex flex-col gap-4\",\n\t\t\t)}\n\t\t\tstyle={gap ? { gap: `${gap * 0.25}rem` } : undefined}\n\t\t>\n\t\t\t{items.map((item, index) => (\n\t\t\t\t<LayoutItemRenderer\n\t\t\t\t\tkey={getLayoutItemKey(item, index)}\n\t\t\t\t\titem={item}\n\t\t\t\t\tindex={index}\n\t\t\t\t\tcolumns={columns}\n\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\twidgetRegistry={widgetRegistry}\n\t\t\t\t\tresolveText={resolveText}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</div>\n\t);\n\n\t// Flat wrapper (just label + content)\n\tif (wrapper === \"flat\") {\n\t\treturn (\n\t\t\t<div className={cn(\"col-span-full\", className)}>\n\t\t\t\t{(sectionLabel || sectionDescription) && (\n\t\t\t\t\t<div className=\"mb-4\">\n\t\t\t\t\t\t{sectionLabel && (\n\t\t\t\t\t\t\t<h2 className=\"text-lg font-semibold\">{sectionLabel}</h2>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{sectionDescription && (\n\t\t\t\t\t\t\t<p className=\"text-sm text-muted-foreground mt-1\">\n\t\t\t\t\t\t\t\t{sectionDescription}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t{itemsContent}\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Card wrapper\n\tif (wrapper === \"card\") {\n\t\treturn (\n\t\t\t<Card className={cn(\"col-span-full\", className)}>\n\t\t\t\t{(sectionLabel || sectionDescription) && (\n\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t{sectionLabel && <CardTitle>{sectionLabel}</CardTitle>}\n\t\t\t\t\t\t{sectionDescription && (\n\t\t\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t\t{sectionDescription}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</CardHeader>\n\t\t\t\t)}\n\t\t\t\t<CardContent>{itemsContent}</CardContent>\n\t\t\t</Card>\n\t\t);\n\t}\n\n\t// Collapsible wrapper\n\tif (wrapper === \"collapsible\") {\n\t\treturn (\n\t\t\t<Accordion\n\t\t\t\tdefaultValue={defaultCollapsed ? [] : [0]}\n\t\t\t\tclassName={cn(\"col-span-full\", className)}\n\t\t\t>\n\t\t\t\t<AccordionItem className=\"border-none\">\n\t\t\t\t\t<AccordionTrigger className=\"hover:no-underline py-2\">\n\t\t\t\t\t\t<div className=\"text-left\">\n\t\t\t\t\t\t\t{sectionLabel && (\n\t\t\t\t\t\t\t\t<span className=\"text-lg font-semibold\">{sectionLabel}</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{sectionDescription && (\n\t\t\t\t\t\t\t\t<p className=\"text-sm text-muted-foreground font-normal\">\n\t\t\t\t\t\t\t\t\t{sectionDescription}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</AccordionTrigger>\n\t\t\t\t\t<AccordionContent className=\"pt-4\">{itemsContent}</AccordionContent>\n\t\t\t\t</AccordionItem>\n\t\t\t</Accordion>\n\t\t);\n\t}\n\n\treturn itemsContent;\n}\n\n// ============================================================================\n// Tabs Renderer\n// ============================================================================\n\ninterface TabsRendererProps {\n\ttabs: DashboardTabs;\n\tbasePath: string;\n\tnavigate?: (path: string) => void;\n\twidgetRegistry?: Record<string, React.ComponentType<WidgetComponentProps>>;\n\tresolveText: (text: any) => string;\n}\n\nfunction TabsRenderer({\n\ttabs,\n\tbasePath,\n\tnavigate,\n\twidgetRegistry,\n\tresolveText,\n}: TabsRendererProps) {\n\tconst { tabs: tabConfigs, defaultTab, variant = \"default\" } = tabs;\n\n\tconst defaultValue = defaultTab || tabConfigs[0]?.id;\n\n\treturn (\n\t\t<Tabs defaultValue={defaultValue} className=\"col-span-full\">\n\t\t\t<TabsList\n\t\t\t\tvariant={variant === \"line\" ? \"line\" : \"default\"}\n\t\t\t\tclassName=\"mb-4\"\n\t\t\t>\n\t\t\t\t{tabConfigs.map((tab) => (\n\t\t\t\t\t<TabsTrigger key={tab.id} value={tab.id}>\n\t\t\t\t\t\t{tab.icon && <tab.icon className=\"h-4 w-4 mr-2\" />}\n\t\t\t\t\t\t{resolveText(tab.label)}\n\t\t\t\t\t\t{tab.badge !== undefined && (\n\t\t\t\t\t\t\t<span className=\"ml-2 rounded-full bg-muted px-2 py-0.5 text-xs\">\n\t\t\t\t\t\t\t\t{tab.badge}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</TabsTrigger>\n\t\t\t\t))}\n\t\t\t</TabsList>\n\n\t\t\t{tabConfigs.map((tab) => (\n\t\t\t\t<TabsContent key={tab.id} value={tab.id}>\n\t\t\t\t\t<TabContentRenderer\n\t\t\t\t\t\ttab={tab}\n\t\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\t\twidgetRegistry={widgetRegistry}\n\t\t\t\t\t\tresolveText={resolveText}\n\t\t\t\t\t/>\n\t\t\t\t</TabsContent>\n\t\t\t))}\n\t\t</Tabs>\n\t);\n}\n\ninterface TabContentRendererProps {\n\ttab: DashboardTabConfig;\n\tbasePath: string;\n\tnavigate?: (path: string) => void;\n\twidgetRegistry?: Record<string, React.ComponentType<WidgetComponentProps>>;\n\tresolveText: (text: any) => string;\n}\n\nfunction TabContentRenderer({\n\ttab,\n\tbasePath,\n\tnavigate,\n\twidgetRegistry,\n\tresolveText,\n}: TabContentRendererProps) {\n\t// Default to 4 columns for tab content\n\tconst columns = 4;\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"@container grid gap-4 items-stretch\",\n\t\t\t\tgetGridClass(columns),\n\t\t\t)}\n\t\t>\n\t\t\t{tab.items.map((item, index) => (\n\t\t\t\t<LayoutItemRenderer\n\t\t\t\t\tkey={getLayoutItemKey(item, index)}\n\t\t\t\t\titem={item}\n\t\t\t\t\tindex={index}\n\t\t\t\t\tcolumns={columns}\n\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\twidgetRegistry={widgetRegistry}\n\t\t\t\t\tresolveText={resolveText}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * DashboardGrid - Renders a configurable grid of dashboard widgets\n *\n * @example\n * ```tsx\n * const dashboardConfig: DashboardConfig = {\n * title: \"Dashboard\",\n * description: \"Welcome to your admin dashboard\",\n * columns: 4,\n * items: [\n * { type: \"stats\", collection: \"posts\", label: \"Total Posts\", span: 1 },\n * { type: \"stats\", collection: \"users\", label: \"Total Users\", span: 1 },\n * {\n * type: \"section\",\n * label: \"Analytics\",\n * wrapper: \"card\",\n * items: [\n * { type: \"chart\", collection: \"posts\", field: \"createdAt\", span: 2 },\n * ]\n * },\n * {\n * type: \"tabs\",\n * tabs: [\n * { id: \"recent\", label: \"Recent\", items: [...] },\n * { id: \"popular\", label: \"Popular\", items: [...] },\n * ]\n * }\n * ],\n * };\n *\n * <DashboardGrid config={dashboardConfig} basePath=\"/admin\" navigate={navigate} />\n * ```\n */\nexport function DashboardGrid({\n\tconfig,\n\tbasePath = \"/admin\",\n\tnavigate,\n\twidgetRegistry,\n\tclassName,\n}: DashboardGridProps): React.ReactElement {\n\tconst resolveText = useResolveText();\n\tconst { title, description, columns = 4 } = config;\n\n\t// Support both new `items` and legacy `widgets` array\n\tconst layoutItems = config.items || config.widgets || [];\n\n\tconst resolvedTitle = title ? resolveText(title) : undefined;\n\tconst resolvedDescription = description\n\t\t? resolveText(description)\n\t\t: undefined;\n\n\t// If no items, show empty state\n\tif (layoutItems.length === 0) {\n\t\treturn (\n\t\t\t<div className={cn(\"@container\", className)}>\n\t\t\t\t<DashboardHeader\n\t\t\t\t\ttitle={resolvedTitle}\n\t\t\t\t\tdescription={resolvedDescription}\n\t\t\t\t\tactions={config.actions}\n\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\tresolveText={resolveText}\n\t\t\t\t/>\n\t\t\t\t<div className=\"flex h-64 items-center justify-center border border-dashed border-border bg-card/50 rounded-lg\">\n\t\t\t\t\t<div className=\"text-center\">\n\t\t\t\t\t\t<p className=\"text-muted-foreground font-medium\">\n\t\t\t\t\t\t\tNo widgets configured\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p className=\"mt-1 text-sm text-muted-foreground\">\n\t\t\t\t\t\t\tAdd widgets to your dashboard configuration to display data here.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className={cn(\"@container\", className)}>\n\t\t\t<DashboardHeader\n\t\t\t\ttitle={resolvedTitle}\n\t\t\t\tdescription={resolvedDescription}\n\t\t\t\tactions={config.actions}\n\t\t\t\tnavigate={navigate}\n\t\t\t\tresolveText={resolveText}\n\t\t\t/>\n\n\t\t\t<div className={cn(\"grid gap-4 items-stretch\", getGridClass(columns))}>\n\t\t\t\t{layoutItems.map((item, index) => (\n\t\t\t\t\t<LayoutItemRenderer\n\t\t\t\t\t\tkey={getLayoutItemKey(item, index)}\n\t\t\t\t\t\titem={item}\n\t\t\t\t\t\tindex={index}\n\t\t\t\t\t\tcolumns={columns}\n\t\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\t\twidgetRegistry={widgetRegistry}\n\t\t\t\t\t\tresolveText={resolveText}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default DashboardGrid;\n","/**\n * Dashboard Page\n *\n * Default dashboard page that renders the DashboardGrid component\n * based on the admin configuration.\n */\n\nimport * as React from \"react\";\nimport {\n selectAdmin,\n selectBasePath,\n selectNavigate,\n useAdminStore,\n} from \"../../runtime/provider\";\nimport { DashboardGrid } from \"../dashboard/dashboard-grid\";\n\nexport interface DashboardPageProps {\n /**\n * Override dashboard title\n */\n title?: string;\n\n /**\n * Override dashboard description\n */\n description?: string;\n\n /**\n * Additional CSS class\n */\n className?: string;\n}\n\n/**\n * Default dashboard page component.\n *\n * Reads dashboard configuration from AdminProvider and renders DashboardGrid.\n *\n * @example\n * ```tsx\n * // In your admin config\n * const admin = qa<AppCMS>()\n * .use(coreAdminModule)\n * .dashboard({\n * title: \"Welcome\",\n * widgets: [\n * { type: \"stats\", collection: \"posts\" },\n * ],\n * })\n * ```\n */\nexport function DashboardPage({\n title,\n description,\n className,\n}: DashboardPageProps) {\n const admin = useAdminStore(selectAdmin);\n const basePath = useAdminStore(selectBasePath);\n const navigate = useAdminStore(selectNavigate);\n\n const dashboardConfig = admin.getDashboard();\n\n // Merge props with config\n const config = {\n ...dashboardConfig,\n ...(title && { title }),\n ...(description && { description }),\n };\n\n return (\n <DashboardGrid\n config={config}\n basePath={basePath}\n navigate={navigate}\n className={className}\n />\n );\n}\n\nexport default DashboardPage;\n"],"mappings":";;;;;;;;;;;;;;;;;AAMA,MAAM,gBAAgB,IACpB,2gBACA;CACE,UAAU,EACR,SAAS;EACP,SACE;EACF,WACE;EACF,aACE;EACF,SACE;EACF,OACE;EACF,MAAM;EACP,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;AAED,SAAS,MAAM,EACb,WACA,UAAU,WACV,QACA,GAAG,SACqE;AACxE,QAAO,UAAU;EACf,gBAAgB;EAChB,OAAO,WACL,EACE,WAAW,GAAG,cAAc;GAAE;GAAW;GAAS,CAAC,CAAC,EACrD,EACD,MACD;EACD;EACA,OAAO;GACL,MAAM;GACN;GACD;EACF,CAAC;;;;;;;;;AC5BJ,SAAgB,YAAY,EAAE,SAA6B;AAC1D,KAAI,UAAU,QAAQ,UAAU,OAC/B,QAAO,oBAAC;EAAK,WAAU;YAAwB;GAAQ;AAExD,QAAO,oBAAC,oBAAM,OAAO,MAAM,GAAQ;;;;;AAUpC,SAAgB,SAAS,EAAE,SAA6B;AACvD,KAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,GACtD,QAAO,oBAAC;EAAK,WAAU;YAAwB;GAAQ;CAExD,MAAM,OAAO,OAAO,MAAM;AAC1B,QACC,oBAAC;EAAK,WAAU;EAA+B,OAAO;YACpD;GACK;;AAIT,SAAS,cAAc,OAAuB;AAC7C,QAAO,MACL,QAAQ,YAAY,IAAI,CACxB,QAAQ,QAAQ,IAAI,CACpB,MAAM;;AAGT,SAAS,oBAAoB,MAAmB;AAC/C,KAAI,CAAC,KAAM,QAAO;AAClB,KAAI,MAAM,QAAQ,KAAK,CACtB,QAAO,KAAK,IAAI,oBAAoB,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI;AAE/D,KAAI,OAAO,KAAK,SAAS,SAAU,QAAO,KAAK;AAC/C,KAAI,MAAM,QAAQ,KAAK,QAAQ,CAC9B,QAAO,KAAK,QAAQ,IAAI,oBAAoB,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI;AAEvE,QAAO;;AAGR,SAAS,mBAAmB,OAAwB;AACnD,KAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,KAAI,OAAO,UAAU,SAEpB,QADgB,qBAAqB,KAAK,MAAM,GAC/B,cAAc,MAAM,GAAG,MAAM,MAAM;AAErD,KAAI,OAAO,UAAU,SAEpB,QADa,oBAAoB,MAAM,CAC3B,QAAQ,QAAQ,IAAI,CAAC,MAAM;AAExC,QAAO,OAAO,MAAM;;AAGrB,SAAgB,aAAa,EAAE,SAA6B;CAC3D,MAAM,OAAO,mBAAmB,MAAM;AACtC,KAAI,CAAC,KACJ,QAAO,oBAAC;EAAK,WAAU;YAAwB;GAAQ;AAExD,QACC,oBAAC;EAAK,WAAU;EAA+B,OAAO;YACpD;GACK;;;;;AAWT,SAAgB,WAAW,EAAE,SAA6B;AACzD,KAAI,UAAU,QAAQ,UAAU,OAC/B,QAAO,oBAAC;EAAK,WAAU;YAAwB;GAAQ;CAExD,MAAM,MAAM,OAAO,MAAM;AACzB,QACC,oBAAC;EAAK,WAAU;YACd,OAAO,MAAM,IAAI,GAAG,OAAO,MAAM,GAAG,IAAI,gBAAgB;GACnD;;;;;AAWT,SAAgB,YAAY,EAAE,SAA6B;AAC1D,QACC,oBAAC;EAAM,SAAS,QAAQ,YAAY;YAClC,QAAQ,QAAQ;GACV;;;;;AAWV,SAAgB,SAAS,EAAE,SAA6B;AACvD,KAAI,UAAU,QAAQ,UAAU,OAC/B,QAAO,oBAAC;EAAK,WAAU;YAAwB;GAAQ;CAExD,MAAM,OAAO,iBAAiB,OAAO,QAAQ,IAAI,KAAK,OAAO,MAAM,CAAC;AACpE,KAAI,OAAO,MAAM,KAAK,SAAS,CAAC,CAC/B,QAAO,oBAAC;EAAK,WAAU;YAAyB,OAAO,MAAM;GAAQ;AAEtE,QAAO,oBAAC;EAAK,WAAU;YAAgB,KAAK,oBAAoB;GAAQ;;;;;AAMzE,SAAgB,aAAa,EAAE,SAA6B;AAC3D,KAAI,UAAU,QAAQ,UAAU,OAC/B,QAAO,oBAAC;EAAK,WAAU;YAAwB;GAAQ;CAExD,MAAM,OAAO,iBAAiB,OAAO,QAAQ,IAAI,KAAK,OAAO,MAAM,CAAC;AACpE,KAAI,OAAO,MAAM,KAAK,SAAS,CAAC,CAC/B,QAAO,oBAAC;EAAK,WAAU;YAAyB,OAAO,MAAM;GAAQ;AAEtE,QACC,qBAAC;EAAK,WAAU;;GACd,KAAK,oBAAoB;GAAC;GAAE,KAAK,oBAAoB;;GAChD;;;;;AAOT,SAAgB,SAAS,EAAE,SAA6B;AACvD,KAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,GACtD,QAAO,oBAAC;EAAK,WAAU;YAAwB;GAAQ;AAGxD,QAAO,oBAAC;EAAK,WAAU;YAAgB,OAAO,MAAM;GAAQ;;;;;AAU7D,SAAgB,UAAU,EAAE,SAA6B;AACxD,KAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,GACtD,QAAO,oBAAC;EAAK,WAAU;YAAwB;GAAQ;AAExD,QAAO,oBAAC;EAAK,WAAU;YAAgB,OAAO,MAAM;GAAQ;;;;;AAM7D,SAAgB,WAAW,EAAE,SAA6B;AACzD,KAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,GACtD,QAAO,oBAAC;EAAK,WAAU;YAAwB;GAAQ;AAExD,QAAO,oBAAC;EAAM,SAAQ;YAAW,OAAO,MAAM;GAAS;;;;;AC7LxD,SAASA,YAAU,EAAE,WAAW,GAAG,SAAwC;AACzE,QACE,oBAACC,UAAmB;EAClB,aAAU;EACV,WAAW,GACT,4FACA,UACD;EACD,GAAI;GACJ;;AAIN,SAAS,cAAc,EAAE,WAAW,GAAG,SAAwC;AAC7E,QACE,oBAACA,UAAmB;EAClB,aAAU;EACV,WAAW,GACT,yGACA,UACD;EACD,GAAI;GACJ;;AAIN,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACgC;AACnC,QACE,oBAACA,UAAmB;EAAO,WAAU;YACnC,qBAACA,UAAmB;GAClB,aAAU;GACV,WAAW,GACT,iXACA,UACD;GACD,GAAI;cAEH,UACD,oBAAC;IACC,aAAU;IACV,WAAU;KACV;IACyB;GACH;;AAIhC,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SAC8B;AACjC,QACE,oBAACA,UAAmB;EAClB,aAAU;EACV,WAAU;EACV,GAAI;YAEJ,oBAAC;GACC,WAAW,GACT,sMACA,UACD;GAEA;IACG;GACmB;;;;;ACnE/B,SAASC,OAAK,EACZ,WACA,cAAc,cACd,GAAG,SACwB;AAC3B,QACE,oBAACC,KAAc;EACb,aAAU;EACV,oBAAkB;EAClB,WAAW,GACT,gEACA,UACD;EACD,GAAI;GACJ;;AAIN,MAAM,mBAAmB,IACvB,2NACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,MAAM;EACP,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;AAED,SAAS,SAAS,EAChB,WACA,UAAU,WACV,GAAG,SACgE;AACnE,QACE,oBAACA,KAAc;EACb,aAAU;EACV,gBAAc;EACd,WAAW,GAAG,iBAAiB,EAAE,SAAS,CAAC,EAAE,UAAU;EACvD,GAAI;GACJ;;AAIN,SAAS,YAAY,EAAE,WAAW,GAAG,SAAkC;AACrE,QACE,oBAACA,KAAc;EACb,aAAU;EACV,WAAW,GACT,+qBACA,iQACA,qJACA,4dACA,UACD;EACD,GAAI;GACJ;;AAIN,SAAS,YAAY,EAAE,WAAW,GAAG,SAAoC;AACvE,QACE,oBAACA,KAAc;EACb,aAAU;EACV,WAAW,GAAG,uCAAuC,UAAU;EAC/D,GAAI;GACJ;;;;;;;;;;;;;;;;AC9BN,SAAgB,kBACf,YACA,SACA,cACM;CACN,MAAM,SAAS,cAAc,aAAa;CAE1C,MAAM,EAAE,QAAQ,kBAAkB,iBAAiB;AAUnD,QAAO,SAAS;EACf,GATiB,2BACjB,QACA;GACC,WAJgB,CAAC,YAAY,cAAc;GAK3C,QAAQ;GACR,CACD,CAGsB,YAAY,YAAsB,KAAK;GAC5D,GAAG;GACH,QAAQ;GACR,CAAQ;EACT,GAAG;EACH,CAAC;;;;;;;;;;;;;;;;;;;AAoBH,SAAgB,mBACf,YACA,SACA,cACM;CACN,MAAM,SAAS,cAAc,aAAa;CAE1C,MAAM,EAAE,QAAQ,kBAAkB,iBAAiB;AAUnD,QAAO,SAAS;EACf,GATiB,2BACjB,QACA;GACC,WAJgB,CAAC,YAAY,cAAc;GAK3C,QAAQ;GACR,CACD,CAGsB,YAAY,YAAsB,MAAM;GAC7D,GAAG;GACH,QAAQ;GACR,CAAQ;EACT,GAAG;EACH,CAAC;;;;;;;;;;;;;AAcH,SAAgB,kBACf,YACA,IACA,SASA,cACM;CACN,MAAM,SAAS,cAAc,aAAa;CAE1C,MAAM,EAAE,QAAQ,kBAAkB,iBAAiB;AAOnD,QAAO,SAAS;EACf,GANiB,2BAA2B,QAAe;GAC3D,WAFiB,CAAC,YAAY,cAAc;GAG5C,QAAQ;GACR,CAAC,CAGqB,YAAY,YAAsB,QAAQ;GAC/D,OAAO,EAAE,IAAI;GACb,QAAQ;GACR,GAAG;GACH,CAAC;EACF,GAAG;EACH,CAAC;;;;;;;;;;;;;;AAeH,SAAgB,oBACf,YACA,iBACM;CACN,MAAM,SAAS,cAAc,aAAa;CAE1C,MAAM,EAAE,QAAQ,kBAAkB,iBAAiB;CACnD,MAAM,cAAc,gBAAgB;CAEpC,MAAM,YAAY,2BAA2B,QAAe;EAC3D,WAFiB,CAAC,YAAY,cAAc;EAG5C,QAAQ;EACR,CAAC;CAEF,MAAM,cAAc,UAAU,YAAY,YAAsB,QAAQ;CACxE,MAAM,eAAe,UAAU,IAAI;EAClC;EACA;EACA;EACA;EACA,CAAC;CACF,MAAM,gBAAgB,UAAU,IAAI;EACnC;EACA;EACA;EACA;EACA,CAAC;AAEF,QAAO,YAAY;EAClB,GAAG;EACH,YAAY,MAAW,WAAgB,YAAiB;AACvD,eAAY,kBAAkB,EAC7B,UAAU,cACV,CAAC;AACF,eAAY,kBAAkB,EAC7B,UAAU,eACV,CAAC;AACF,IAAC,iBAAiB,aAAoB,MAAM,WAAW,QAAQ;;EAEhE,YAAY,MAAW,OAAY,WAAgB,YAAiB;AACnE,eAAY,kBAAkB,EAC7B,UAAU,cACV,CAAC;AACF,eAAY,kBAAkB,EAC7B,UAAU,eACV,CAAC;AACF,IAAC,iBAAiB,aAAoB,MAAM,OAAO,WAAW,QAAQ;;EAEvE,GAAG;EACH,CAAQ;;;;;;;;;;;;;;AAeV,SAAgB,oBACf,YACA,iBACM;CACN,MAAM,SAAS,cAAc,aAAa;CAE1C,MAAM,EAAE,QAAQ,kBAAkB,iBAAiB;CACnD,MAAM,cAAc,gBAAgB;CAEpC,MAAM,YAAY,2BAA2B,QAAe;EAC3D,WAFiB,CAAC,YAAY,cAAc;EAG5C,QAAQ;EACR,CAAC;CAEF,MAAM,cAAc,UAAU,YAAY,YAAsB,QAAQ;CACxE,MAAM,eAAe,UAAU,IAAI;EAClC;EACA;EACA;EACA;EACA,CAAC;CACF,MAAM,gBAAgB,UAAU,IAAI;EACnC;EACA;EACA;EACA;EACA,CAAC;CACF,MAAM,eAAe,UAAU,IAAI;EAClC;EACA;EACA;EACA;EACA,CAAC;AAEF,QAAO,YAAY;EAClB,GAAG;EACH,YAAY,MAAW,WAAgB,YAAiB;AACvD,eAAY,kBAAkB,EAC7B,UAAU,cACV,CAAC;AACF,eAAY,kBAAkB,EAC7B,UAAU,eACV,CAAC;AACF,eAAY,kBAAkB,EAC7B,UAAU,cACV,CAAC;AACF,IAAC,iBAAiB,aAAoB,MAAM,WAAW,QAAQ;;EAEhE,YAAY,MAAW,OAAY,WAAgB,YAAiB;AACnE,eAAY,kBAAkB,EAC7B,UAAU,cACV,CAAC;AACF,eAAY,kBAAkB,EAC7B,UAAU,eACV,CAAC;AACF,eAAY,kBAAkB,EAC7B,UAAU,cACV,CAAC;AACF,IAAC,iBAAiB,aAAoB,MAAM,OAAO,WAAW,QAAQ;;EAEvE,GAAG;EACH,CAAQ;;;;;;;;;;;;;;AAeV,SAAgB,oBACf,YACA,iBACM;CACN,MAAM,SAAS,cAAc,aAAa;CAE1C,MAAM,EAAE,QAAQ,kBAAkB,iBAAiB;CACnD,MAAM,cAAc,gBAAgB;CAEpC,MAAM,YAAY,2BAA2B,QAAe;EAC3D,WAFiB,CAAC,YAAY,cAAc;EAG5C,QAAQ;EACR,CAAC;CAEF,MAAM,cAAc,UAAU,YAAY,YAAsB,QAAQ;CACxE,MAAM,eAAe,UAAU,IAAI;EAClC;EACA;EACA;EACA;EACA,CAAC;CACF,MAAM,gBAAgB,UAAU,IAAI;EACnC;EACA;EACA;EACA;EACA,CAAC;CACF,MAAM,eAAe,UAAU,IAAI;EAClC;EACA;EACA;EACA;EACA,CAAC;AAEF,QAAO,YAAY;EAClB,GAAG;EACH,YAAY,MAAW,WAAgB,YAAiB;AACvD,eAAY,kBAAkB,EAC7B,UAAU,cACV,CAAC;AACF,eAAY,kBAAkB,EAC7B,UAAU,eACV,CAAC;AACF,eAAY,kBAAkB,EAC7B,UAAU,cACV,CAAC;AACF,IAAC,iBAAiB,aAAoB,MAAM,WAAW,QAAQ;;EAEhE,YAAY,MAAW,OAAY,WAAgB,YAAiB;AACnE,eAAY,kBAAkB,EAC7B,UAAU,cACV,CAAC;AACF,eAAY,kBAAkB,EAC7B,UAAU,eACV,CAAC;AACF,eAAY,kBAAkB,EAC7B,UAAU,cACV,CAAC;AACF,IAAC,iBAAiB,aAAoB,MAAM,OAAO,WAAW,QAAQ;;EAEvE,GAAG;EACH,CAAQ;;;;;ACnXV,SAAS,SAAS,EAAE,WAAW,GAAG,SAAsC;AACtE,QACE,oBAAC;EACC,aAAU;EACV,WAAW,GAAG,0BAA0B,UAAU;EAClD,GAAI;GACJ;;;;;;;;;;;;;;;;;;;;;;;;;;AC4BN,IAAa,gBAAb,cAAmCC,QAAM,UAGvC;CACA,YAAY,OAA2B;AACrC,QAAM,MAAM;AACZ,OAAK,QAAQ;GAAE,UAAU;GAAO,OAAO;GAAM;;CAG/C,OAAO,yBAAyB,OAAkC;AAChE,SAAO;GAAE,UAAU;GAAM;GAAO;;CAGlC,kBAAkB,OAAc,WAAkC;AAChE,OAAK,MAAM,UAAU,OAAO,UAAU;;CAGxC,SAA0B;AACxB,MAAI,KAAK,MAAM,YAAY,KAAK,MAAM,OAAO;GAC3C,MAAM,EAAE,aAAa,KAAK;AAE1B,OAAI,OAAO,aAAa,WACtB,QAAO,SAAS,KAAK,MAAM,MAAM;AAGnC,OAAI,SACF,QAAO;AAIT,UACE,qBAAC;IAAI,WAAU;eACb,oBAAC;KAAE,WAAU;eAAuC;MAEhD,EACJ,oBAAC;KAAE,WAAU;eACV,KAAK,MAAM,MAAM;MAChB;KACA;;AAIV,SAAO,KAAK,MAAM;;;;;;AAOtB,SAAgB,oBAAoB,EAClC,UACA,cAIC;AACD,QACE,oBAAC;EACC,WAAW,UACT,qBAAC;GAAI,WAAU;;IACb,oBAAC;KAAE,WAAU;eAAuC;MAAgB;IACnE,cACC,qBAAC;KAAE,WAAU;gBAAgC,UAAO;MAAe;IAErE,oBAAC;KAAE,WAAU;eAAsC,MAAM;MAAY;;IACjE;EAGP;GACa;;;;;;;;;;;AC9CpB,MAAMC,kBAAmD;CACxD,SAAS;CACT,SAAS;CACT,UACC;CACD;AAED,MAAMC,uBAA0D;CAC/D,SAAS;CACT,SAAS;CACT,UAAU;CACV;AAMD,SAAS,kBAAkB,EAC1B,UAAU,aAGR;AACF,QACC,qBAAC;EAAK,WAAW,GAAG,wBAAwBC,gBAAc,SAAS;aAClE,oBAAC,wBACA,oBAAC,YAAS,WAAU,aAAa,GACrB,EACb,oBAAC;GAAY,WAAW,GAAG,UAAU,qBAAqB,SAAS;aAClE,oBAAC,YAAS,WAAU,gBAAgB;IACvB;GACR;;AAIT,SAAS,gBAAgB,EACxB,OACA,UAAU,WACV,WAKE;AACF,QACC,qBAAC;EACA,WAAW,GACV,+DACAA,gBAAc,SACd;aAED,qBAAC,yBACA,oBAAC;GAAU,WAAU;aAAuC;IAEhD,EACX,WACA,oBAAC,wBACA,oBAAC;GAAO,SAAQ;GAAQ,MAAK;GAAU,SAAS;aAC/C,oBAAC,kBAAe,WAAU,gBAAgB;IAClC,GACG,IAEF,EACb,oBAAC;GAAY,WAAW,GAAG,UAAU,qBAAqB,SAAS;aAClE,oBAAC;IAAE,WAAU;cAAiC,MAAM;KAAY;IACnD;GACR;;;;;;;;;;;;;;;;;AAuBT,SAAgB,WAAW,EAC1B,OACA,aACA,MAAM,MACN,UAAU,WACV,WACA,cACA,OACA,WACA,UACA,SACA,WACA,iBACA,YACuC;AAEvC,KAAI,WAAW;AACd,MAAI,gBACH,QACC,qBAAC;GACA,WAAW,GACV,wBACAA,gBAAc,UACd,UACA;cAED,oBAAC,wBACA,oBAAC,YAAS,WAAU,aAAa,GACrB,EACb,oBAAC;IAAY,WAAW,GAAG,UAAU,qBAAqB,SAAS;cACjE;KACY;IACR;AAGT,SAAO,oBAAC,qBAA2B,UAAW;;AAI/C,KAAI,MACH,QACC,oBAAC;EAAuB;EAAgB;EAAS,SAAS;GAAa;CAIzE,MAAM,YACL,SAAS,eAAe,QAAQ,aAAa,YAAY,SAAS;AAEnE,QACC,qBAAC;EACA,WAAW,GAAG,wBAAwBA,gBAAc,UAAU,UAAU;aAEvE,aACA,qBAAC,yBACA,qBAAC;GAAI,WAAU;cACb,QAAQ,oBAAC,QAAK,WAAU,kCAAkC,EAC3D,qBAAC;IAAI,WAAU;eACb,SACA,oBAAC;KAAU,WAAU;eACnB;MACU,EAEZ,eACA,oBAAC;KAAgB,WAAU;eACzB;MACgB;KAEd;IACD,GACJ,aAAa,YAAY,SAAS,WACnC,oBAAC,wBACA,qBAAC;GAAI,WAAU;;IACb,SAAS,KAAK,WACd,oBAAC;KAEA,SAAQ;KACR,MAAK;KACL,SAAS,OAAO;KAChB,OAAO,OAAO;eAEb,OAAO,QAAQ,OAAO,OAAO,SAAS,YACtC,oBAAC,OAAO,QAAK,WAAU,gBAAgB;OAPnC,OAAO,GASJ,CACR;IACD,aACA,oBAAC;KACA,SAAQ;KACR,MAAK;KACL,SAAS;KACT,OAAM;KACN,UAAU;eAEV,oBAAC,kBACA,WAAW,GACV,eACA,gBAAgB,eAChB,GACA;MACM;IAET,YACA,oBAAC;KACA,SAAQ;KACR,MAAK;KACL,SAAS;KACT,OAAM;eAEN,oBAAC,mBAAgB,WAAU,gBAAgB;MACnC;;IAEL,GACM,IAEF,EAEd,oBAAC;GACA,WAAW,GACV,UACA,qBAAqB,UACrB,CAAC,aAAa,OACd;GAEA;IACY;GACR;;;;;;;;;;;AClQT,SAAgB,sBAAsB;AACrC,QACC,qBAAC;EAAI,WAAU;aACd,oBAAC,YAAS,WAAU,aAAa,EACjC,oBAAC,YAAS,WAAU,aAAa;GAC5B;;AAQR,SAAgB,sBAAsB;AACrC,QACC,qBAAC;EAAI,WAAU;;GAEd,oBAAC,YAAS,WAAU,6BAA6B;GACjD,oBAAC,YAAS,WAAU,6BAA6B;GACjD,oBAAC,YAAS,WAAU,6BAA6B;GACjD,oBAAC,YAAS,WAAU,6BAA6B;GACjD,oBAAC,YAAS,WAAU,6BAA6B;GACjD,oBAAC,YAAS,WAAU,6BAA6B;GACjD,oBAAC,YAAS,WAAU,6BAA6B;GACjD,oBAAC,YAAS,WAAU,6BAA6B;GACjD,oBAAC,YAAS,WAAU,6BAA6B;GACjD,oBAAC,YAAS,WAAU,6BAA6B;;GAC5C;;AAQR,SAAgB,0BAA0B,EAAE,QAAQ,KAAyB;AAC5E,QACC,qBAAC;EAAI,WAAU;;GACd,oBAAC,gBAAc;GACd,QAAQ,KAAK,oBAAC,gBAAc;GAC5B,QAAQ,KAAK,oBAAC,gBAAc;GAC5B,QAAQ,KAAK,oBAAC,gBAAc;GAC5B,QAAQ,KAAK,oBAAC,gBAAc;;GACxB;;AAIR,SAAS,cAAc;AACtB,QACC,oBAAC;EAAI,WAAU;YACd,qBAAC;GAAI,WAAU;cACd,oBAAC,YAAS,WAAU,cAAc,EAClC,oBAAC,YAAS,WAAU,cAAc;IAC7B;GACD;;AAyDR,SAAgB,oBAAoB,EACnC,OAAO,GACP,UAAU,KAIR;AACF,QACC,qBAAC;EAAI,WAAU;;GAEd,qBAAC;IAAI,WAAU;;KACd,oBAAC,YAAS,WAAU,aAAa;KAChC,UAAU,KAAK,oBAAC,YAAS,WAAU,eAAe;KAClD,UAAU,KAAK,oBAAC,YAAS,WAAU,eAAe;;KAC9C;GAEN,oBAAC,oBAA0B,UAAW;GACrC,OAAO,KAAK,oBAAC,oBAA0B,UAAW;GAClD,OAAO,KAAK,oBAAC,oBAA0B,UAAW;GAClD,OAAO,KAAK,oBAAC,oBAA0B,UAAW;GAClD,OAAO,KAAK,oBAAC;IAA0B;IAAS;KAAO;;GACnD;;AAIR,SAAS,iBAAiB,EACzB,UAAU,GACV,OAAO,SAIL;AACF,QACC,qBAAC;EACA,WAAW,GACV,kDACA,QAAQ,WACR;;GAED,oBAAC,YAAS,WAAU,aAAa;GAChC,UAAU,KAAK,oBAAC,YAAS,WAAU,eAAe;GAClD,UAAU,KAAK,oBAAC,YAAS,WAAU,eAAe;;GAC9C;;AAQR,SAAgB,uBAAuB,EAAE,QAAQ,KAAyB;AACzE,QACC,qBAAC;EAAI,WAAU;;GACd,oBAAC,yBAAuB;GACvB,QAAQ,KAAK,oBAAC,yBAAuB;GACrC,QAAQ,KAAK,oBAAC,yBAAuB;GACrC,QAAQ,KAAK,oBAAC,yBAAuB;GACrC,QAAQ,KAAK,oBAAC,wBAAqB,aAAO;;GACtC;;AAIR,SAAS,qBAAqB,EAAE,OAAO,SAA6B;AACnE,QACC,qBAAC;EAAI,WAAU;aAEd,qBAAC;GAAI,WAAU;cACd,oBAAC,YAAS,WAAU,yBAAyB,EAC5C,CAAC,QAAQ,oBAAC,YAAS,WAAU,sBAAsB;IAC/C,EAEN,qBAAC;GAAI,WAAU;;IACd,oBAAC,YAAS,WAAU,cAAc;IAClC,oBAAC,YAAS,WAAU,cAAc;IAClC,oBAAC,YAAS,WAAU,aAAa;;IAC5B;GACD;;AAQR,SAAgB,yBAAyB;AACxC,QACC,qBAAC;EAAI,WAAU;;GACd,qBAAC;IAAI,WAAU;eACd,oBAAC,YAAS,WAAU,aAAa,EACjC,oBAAC,YAAS,WAAU,aAAa;KAC5B;GACN,oBAAC,YAAS,WAAU,4BAA4B;GAChD,oBAAC,YAAS,WAAU,aAAa;;GAC5B;;AAQR,SAAgB,oBAAoB,EACnC,WAAW,SAGT;AACF,QACC,qBAAC;EAAI,WAAU;aACd,qBAAC;GAAI,WAAU;cACd,oBAAC,YAAS,WAAU,kCAAkC,EACtD,qBAAC;IAAI,WAAU;eACd,oBAAC,YAAS,WAAU,aAAa,EACjC,oBAAC,YAAS,WAAW,GAAG,OAAO,WAAW,SAAS,OAAO,GAAI;KACzD;IACD,EACN,oBAAC,YAAS,WAAU,aAAa;GAC5B;;;;;;;;;;;ACjLR,MAAM,eAAe;CACpB;CACA;CACA;CACA;CACA;CACA;;;;AAKD,SAAS,aAAa,EACrB,QACA,SACA,SACqC;AACrC,KAAI,CAAC,UAAU,CAAC,SAAS,OAAQ,QAAO;AAExC,QACC,qBAAC;EAAI,WAAU;aACd,oBAAC;GAAE,WAAU;aAA+B;IAAU,EACrD,QAAQ,KAAK,UACb,qBAAC;GAA2B,WAAU;;IACpC,MAAM;IAAK;IAAE;IACd,oBAAC;KAAK,WAAU;eAA+B,MAAM;MAAa;;KAF3D,OAAO,MAAM,KAAK,CAGtB,CACH;GACG;;;;;;;;;;AAYR,SAAwB,YAAY,EAAE,UAA4B;CACjE,MAAM,cAAc,gBAAgB;CACpC,MAAM,EACL,YACA,OACA,YAAY,QACZ,YAAY,OACZ,OACA,QAAQ,wBACR,WAAW,SACR;CAGJ,MAAM,EAAE,MAAM,WAAW,OAAO,YAAY,kBAC3C,YACA,EACC,OAAO,KACP,CACD;CAGD,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAK,GAAG,KAAK,OAAO,EAAE;CACxD,MAAM,eAAe,QAClB,YAAY,MAAM,GAClB,GAAG,qBAAqB,WAAW,CAAC,MAAM;CAG7C,MAAM,YAAYC,QAAM,cAAc;AACrC,MAAI,CAAC,MAAM,OAAQ,QAAO,EAAE;EAG5B,MAAM,UAAU,MAAM,QACpB,KAA6B,SAAc;GAC3C,MAAM,QAAQ,KAAK;AACnB,OAAI,UAAU,UAAa,UAAU,KAAM,QAAO;GAGlD,IAAIC;AACJ,OAAI,iBAAiB,QAAQ,CAAC,MAAM,KAAK,MAAM,MAAM,CAAC,CAErD,OAAM,mBADO,IAAI,KAAK,MAAM,EACG,UAAU;OAEzC,OAAM,OAAO,MAAM;AAGpB,OAAI,QAAQ,IAAI,QAAQ,KAAK;AAC7B,UAAO;KAER,EAAE,CACF;AAGD,SAAO,OAAO,QAAQ,QAAQ,CAC5B,KAAK,CAAC,MAAM,YAAY;GAAE;GAAa;GAAiB,EAAE,CAC1D,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC;IAC5C;EAAC;EAAO;EAAO;EAAU,CAAC;CAG7B,MAAM,eACL,oBAAC;EAAI,WAAU;YACd,oBAAC;GAAE,WAAU;aAAU;IAAqB;GACvC;CAIP,MAAM,eACL,UAAU,WAAW,IACpB,eAEA,oBAAC;EAAI,WAAU;YACd,oBAAC;GAAoB,OAAM;GAAO,QAAO;aACvC,YAAY,WAAW,WAAW,OAAO,SAAS;IAC9B;GACjB;AAGR,QACC,oBAAC;EACA,OAAO;EACI;EACX,iBAAiB,oBAAC,wBAAsB;EACxC,OACC,iBAAiB,QAAQ,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,GAAG;EAErE,iBAAiB,SAAS;YAEzB;GACW;;;;;AAOf,SAAS,YACR,MACA,MACA,OACA,UACC;CACD,MAAM,cAAc;EACnB;EACA,QAAQ;GAAE,KAAK;GAAG,OAAO;GAAG,MAAM;GAAK,QAAQ;GAAG;EAClD;CAGD,MAAM,YAAY;EACjB,UAAU;EACV,MAAM;EACN;AAED,SAAQ,MAAR;EACC,KAAK,OACJ,QACC,qBAAC;GAAU,GAAI;;IACb,YACA,oBAAC;KACA,iBAAgB;KAChB,QAAO;KACP,SAAS;MACR;IAEH,oBAAC;KACA,SAAQ;KACR,MAAM;KACN,UAAU;KACV,UAAU;MACT;IACF,oBAAC;KAAM,MAAM;KAAW,UAAU;KAAO,UAAU;MAAS;IAC5D,oBAAC,WAAQ,SAAS,oBAAC,iBAAe,GAAI;IACtC,oBAAC;KACA,MAAK;KACL,SAAQ;KACR,QAAQ;KACR,aAAa;KACb,KAAK;MACJ;;IACS;EAGd,KAAK,MACJ,QACC,qBAAC;GAAS,GAAI;;IACZ,YACA,oBAAC;KACA,iBAAgB;KAChB,QAAO;KACP,SAAS;MACR;IAEH,oBAAC;KACA,SAAQ;KACR,MAAM;KACN,UAAU;KACV,UAAU;MACT;IACF,oBAAC;KAAM,MAAM;KAAW,UAAU;KAAO,UAAU;MAAS;IAC5D,oBAAC;KACA,SAAS,oBAAC,iBAAe;KACzB,QAAQ;MAAE,MAAM;MAAsB,SAAS;MAAK;MACnD;IACF,oBAAC;KAAI,SAAQ;KAAQ,MAAM;KAAO,QAAQ;MAAC;MAAG;MAAG;MAAG;MAAE;MAAI;;IAChD;EAGb,KAAK,MACJ,QACC,qBAAC,uBACA,oBAAC;GACM;GACN,SAAQ;GACR,SAAQ;GACR,IAAG;GACH,IAAG;GACH,aAAa;GACb,QAAQ,EAAE,WAAW;GACrB,WAAW;GACX,QAAO;GACP,aAAa;aAEZ,KAAK,KAAK,UACV,oBAAC,QAEA,MAAM,aAAa,KAAK,QAAQ,MAAM,GAAG,aAAa,WADjD,QAAQ,MAAM,OAElB,CACD;IACG,EACN,oBAAC,WAAQ,SAAS,oBAAC,iBAAe,GAAI,IAC5B;EAGb,KAAK;EACL,QACC,QACC,qBAAC;GAAU,GAAI;;IACb,YACA,oBAAC;KACA,iBAAgB;KAChB,QAAO;KACP,SAAS;MACR;IAEH,oBAAC;KACA,SAAQ;KACR,MAAM;KACN,UAAU;KACV,UAAU;MACT;IACF,oBAAC;KAAM,MAAM;KAAW,UAAU;KAAO,UAAU;MAAS;IAC5D,oBAAC,WAAQ,SAAS,oBAAC,iBAAe,GAAI;IACtC,oBAAC;KACA,MAAK;KACL,SAAQ;KACR,QAAQ;KACR,MAAM;KACN,aAAa;MACZ;;IACS;;;;;;AAQhB,SAAS,mBACR,MACA,WACS;CACT,MAAM,SAAS;EACd;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AAED,SAAQ,WAAR;EACC,KAAK,KAGJ,QAAO,GADM;GAAC;GAAO;GAAO;GAAO;GAAO;GAAO;GAAO;GAAM,CAC/C,KAAK,QAAQ,EAAE,GAAG,KAAK,SAAS;EAGhD,KAAK,MAEJ,QAAO,GAAG,OAAO,KAAK,UAAU,EAAE,GAAG,KAAK,SAAS;EAEpD,KAAK,MAGJ,QAAO,IADS,KAAK,KAAK,KAAK,SAAS,GAAG,EAAE,CAC1B,GAAG,OAAO,KAAK,UAAU;EAG7C,KAAK,KAEJ,QAAO,GAAG,OAAO,KAAK,UAAU,EAAE,GAAG,KAAK,aAAa;EAExD,QACC,QAAO,GAAG,OAAO,KAAK,UAAU,EAAE,GAAG,KAAK,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrUtD,SAAwB,eAAe,EAAE,UAA+B;CACvE,MAAM,SAAS,cAAc,aAAa;CAC1C,MAAM,cAAc,gBAAgB;CACpC,MAAM,EAAE,OAAO,iBAAiB,SAAS;CAEzC,MAAM,EAAE,MAAM,WAAW,OAAO,YAAY,SAKzC;EACF,UAAU;GAAC;GAAU;GAAY,OAAO;GAAG;EAC3C,eAAe,OAAO,QAAQ,OAAO;EACrC,iBAAiB,OAAO;EACxB,CAAC;CAEF,MAAM,QAAQ,OAAO,QAAQ,YAAY,OAAO,MAAM,GAAG;CAGzD,MAAM,aAAa,OAChB,KAAK,IAAK,KAAK,UAAU,KAAK,SAAU,KAAK,IAAI,GACjD;CACH,MAAM,sBAAsB,WAAW,QAAQ,EAAE;CAGjD,MAAM,yBAAyB;AAC9B,MAAI,MAAO,QAAO;AAClB,MAAI,cAAc,IAAK,QAAO;AAC9B,MAAI,cAAc,GAAI,QAAO;AAC7B,MAAI,cAAc,GAAI,QAAO;AAC7B,SAAO;;CAIR,MAAM,kBAAkB,OACvB,qBAAC;EAAI,WAAU;;GAEd,oBAAC;IAAI,WAAU;cACd,oBAAC;KAAI,WAAU;eACd,oBAAC;MACA,WAAW,GACV,mDACA,kBAAkB,CAClB;MACD,OAAO,EAAE,OAAO,GAAG,WAAW,IAAI;OACjC;MACG;KACD;GAGN,qBAAC;IAAI,WAAU;eACd,oBAAC;KAAK,WAAU;eACd,KAAK,SACL,GAAG,KAAK,QAAQ,gBAAgB,CAAC,KAAK,KAAK,OAAO,gBAAgB;MAC7D,EACN,kBACA,qBAAC;KAAK,WAAU;gBAAe,qBAAoB;MAAQ;KAEvD;GAGL,KAAK,YACL,oBAAC;IAAE,WAAU;cAAiC,KAAK;KAAa;;GAE5D,GACH;AAEJ,QACC,oBAAC;EACO;EACI;EACX,iBAAiB,oBAAC,2BAAyB;EAC3C,OACC,iBAAiB,QAAQ,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,GAAG;EAErE,iBAAiB,SAAS;YAEzB;GACW;;;;;;;;;;;;;;;;;AC7Ff,SAAwB,mBAAmB,EAC1C,QACA,WAAW,UACX,YAC2B;CAC3B,MAAM,cAAc,gBAAgB;CACpC,MAAM,EAAE,cAAc,SAAS,WAAW;CAC1C,MAAM,QAAQ,OAAO,QAAQ,YAAY,OAAO,MAAM,GAAG;CAGzD,MAAM,gBAAgB,aAAa,KAAK,QAAQ,UAAU;AACzD,MAAI,OAAO,WAAW,UAAU;GAE/B,MAAM,CAAC,YAAY,cAAc,OAAO,MAAM,IAAI;AAClD,UAAO;IACN,IAAI,GAAG,OAAO,GAAG;IACjB,OAAO,GAAG,eAAe,WAAW,QAAQ,WAAW,GAAG,qBAAqB,WAAW;IAC1F,MAAM,GAAG,SAAS,eAAe,WAAW,GAAG,eAAe,WAAW,WAAW;IACpF,MAAM;IACN,SAAS;IACT;;AAEF,SAAO;GACN,IAAI,UAAU;GACd,OAAO,YAAY,OAAO,MAAM;GAChC,MAAM,OAAO;GACb,SAAS,OAAO;GAChB,MAAM,OAAO;GACb,SAAS,OAAO,WAAY;GAC5B;GACA;CAGF,MAAM,eAAe,WAAsC;AAC1D,MAAI,OAAO,QACV,QAAO,SAAS;WACN,OAAO,QAAQ,SACzB,UAAS,OAAO,KAAK;;CAKvB,MAAMC,kBAAgB;EACrB,SAAS;EACT,SACC;EACD,WAAW;EACX,SAAS;EACT;CAED,MAAM,oBAAoB;EACzB,SAAS;EACT,SAAS;EACT,WAAW;EACX,SAAS;EACT;AAGD,KAAI,cAAc,WAAW,EAC5B,QACC,oBAAC;EAAkB;YAClB,oBAAC;GAAE,WAAU;aAAgC;IAAyB;GAC1D;AAKf,KAAI,WAAW,OACd,QACC,oBAAC;EAAkB;YAClB,oBAAC;GAAI,WAAU;aACb,cAAc,KAAK,WAAW;IAC9B,MAAM,OACL,OAAO,QAAQ,OAAO,OAAO,SAAS,WACnC,OAAO,OACP;AAEJ,WACC,qBAAC;KAEA,MAAK;KACL,eAAe,YAAY,OAAO;KAClC,WAAW,GACV,gGACAA,gBAAc,OAAO,SACrB;gBAEA,QACA,oBAAC;MACA,WAAW,GACV,uDACA,kBAAkB,OAAO,SACzB;gBAED,oBAAC,QAAK,WAAU,YAAY;OACvB,EAEP,oBAAC;MAAK,WAAU;gBAAuB,OAAO;OAAa;OAlBtD,OAAO,GAmBJ;KAET;IACG;GACM;AAKf,QACC,oBAAC;EAAkB;YAClB,oBAAC;GAAI,WAAU;aACb,cAAc,KAAK,WAAW;IAC9B,MAAM,OACL,OAAO,QAAQ,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO;AAEhE,WACC,qBAAC;KAEA,MAAK;KACL,eAAe,YAAY,OAAO;KAClC,WAAW,GACV,mFACAA,gBAAc,OAAO,SACrB;;MAEA,QACA,oBAAC;OACA,WAAW,GACV,gEACA,kBAAkB,OAAO,SACzB;iBAED,oBAAC,QAAK,WAAU,YAAY;QACvB;MAEP,oBAAC;OAAK,WAAU;iBACd,OAAO;QACF;MACP,oBAAC,cAAW,WAAU,uFAAuF;;OArBxG,OAAO,GAsBJ;KAET;IACG;GACM;;;;;;;;;;;;;;;;;;;AC5Hf,SAAwB,kBAAkB,EAAE,UAAkC;CAC7E,MAAM,cAAc,gBAAgB;CACpC,MAAM,EACL,YACA,QAAQ,GACR,OACA,aAAa,UACb,YAAY,aACZ,gBACA,gBACG;CAGJ,MAAM,EAAE,MAAM,WAAW,OAAO,YAAY,kBAC3C,YACA;EACC,SAAS,GAAG,YAAY,QAAQ;EAChC;EACA,CACD;CAGD,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAK,GAAG,KAAK,OAAO,EAAE;CACxD,MAAM,eAAe,QAClB,YAAY,MAAM,GAClB,UAAU,qBAAqB,WAAW;CAG7C,MAAM,iBAAiB,SAAsB;AAC5C,MAAI,cAAc,KAAK,YAAa,QAAO,OAAO,KAAK,YAAY;AACnE,MAAI,KAAK,OAAQ,QAAO,OAAO,KAAK,OAAO;AAC3C,MAAI,KAAK,KAAM,QAAO,OAAO,KAAK,KAAK;AACvC,MAAI,KAAK,MAAO,QAAO,OAAO,KAAK,MAAM;AACzC,MAAI,KAAK,MAAO,QAAO,OAAO,KAAK,MAAM;AACzC,SAAO,SAAS,KAAK;;CAItB,MAAM,eAAe,SAA6B;AACjD,MAAI,CAAC,gBAAgB,OAAQ,QAAO;AACpC,SAAO,eACL,KAAK,UAAU,KAAK,OAAO,CAC3B,OAAO,QAAQ,CACf,KAAK,MAAM;;CAId,MAAM,mBAAmB,SAAc;AACtC,MAAI,YACH,aAAY,KAAK;;CAKnB,MAAM,cACL,MAAM,WAAW,IAChB,oBAAC;EAAE,WAAU;YAAgC;GAAgB,GAE7D,oBAAC;EAAI,WAAU;YACb,MAAM,KAAK,SAAc;GACzB,MAAM,YAAY,KAAK;GACvB,MAAM,WAAW,YAAY,KAAK;AAElC,UACC,oBAAC;IACA,MAAK;IAEL,eAAe,gBAAgB,KAAK;IACpC,WAAU;cAEV,qBAAC;KAAI,WAAU;gBACd,oBAAC;MAAE,WAAU;gBACX,cAAc,KAAK;OACjB,EACJ,qBAAC;MAAI,WAAU;iBACb,aACA,oBAAC,oBAAM,mBAAmB,IAAI,KAAK,UAAU,CAAC,GAAQ,EAEtD,YACA,4CACC,oBAAC,oBAAK,MAAQ,EACd,oBAAC;OAAK,WAAU;iBAAY;QAAgB,IAC1C;OAEC;MACD;MAnBD,KAAK,GAoBF;IAET;GACG;AAGR,QACC,oBAAC;EACA,OAAO;EACI;EACX,iBAAiB,oBAAC,6BAA0B,OAAO,QAAS;EAC5D,OACC,iBAAiB,QAAQ,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,GAAG;EAErE,iBAAiB,SAAS;YAEzB;GACW;;;;;AAOf,SAAS,mBAAmB,MAAoB;CAE/C,MAAM,wBADM,IAAI,MAAM,EACL,SAAS,GAAG,KAAK,SAAS;CAC3C,MAAM,UAAU,KAAK,MAAM,OAAO,IAAK;CACvC,MAAM,UAAU,KAAK,MAAM,UAAU,GAAG;CACxC,MAAM,QAAQ,KAAK,MAAM,UAAU,GAAG;CACtC,MAAM,OAAO,KAAK,MAAM,QAAQ,GAAG;AAEnC,KAAI,OAAO,EAAG,QAAO,GAAG,KAAK;AAC7B,KAAI,QAAQ,EAAG,QAAO,GAAG,MAAM;AAC/B,KAAI,UAAU,EAAG,QAAO,GAAG,QAAQ;AACnC,QAAO;;;;;;;;ACzHR,SAAS,aAAa,QAAoD;CACzE,MAAM,sBAAM,IAAI,MAAM;CACtB,MAAM,QAAQ,IAAI,KAAK,IAAI,aAAa,EAAE,IAAI,UAAU,EAAE,IAAI,SAAS,CAAC;AAExE,SAAQ,QAAR;EACC,KAAK,QACJ,QAAO;GACN,KAAK;GACL,qBAAK,IAAI,KAAK,MAAM,SAAS,GAAG,OAAU,KAAK,MAAO,EAAE;GACxD;EACF,KAAK,YAEJ,QAAO;GACN,qBAFiB,IAAI,KAAK,MAAM,SAAS,GAAG,OAAU,KAAK,IAAK;GAGhE,qBAAK,IAAI,KAAK,MAAM,SAAS,GAAG,EAAE;GAClC;EAEF,KAAK,YAAY;GAChB,MAAM,YAAY,MAAM,QAAQ;AAKhC,UAAO;IACN,qBALc,IAAI,KAClB,MAAM,SAAS,IACb,cAAc,IAAI,IAAI,YAAY,KAAK,KAAK,KAAK,KAAK,IACxD;IAGA,KAAK;IACL;;EAEF,KAAK,YAAY;GAChB,MAAM,YAAY,MAAM,QAAQ;GAChC,MAAM,6BAAa,IAAI,KACtB,MAAM,SAAS,IACb,cAAc,IAAI,IAAI,YAAY,KAAK,KAAK,KAAK,KAAK,IACxD;AAID,UAAO;IACN,qBAJkB,IAAI,KACtB,WAAW,SAAS,GAAG,QAAc,KAAK,IAC1C;IAGA,qBAAK,IAAI,KAAK,WAAW,SAAS,GAAG,EAAE;IACvC;;EAEF,KAAK,YACJ,QAAO;GACN,KAAK,IAAI,KAAK,IAAI,aAAa,EAAE,IAAI,UAAU,EAAE,EAAE;GACnD,KAAK;GACL;EACF,KAAK,aAAa;GACjB,MAAM,mBAAmB,IAAI,KAAK,IAAI,aAAa,EAAE,IAAI,UAAU,EAAE,EAAE;AACvE,UAAO;IACN,KAAK,IAAI,KAAK,IAAI,aAAa,EAAE,IAAI,UAAU,GAAG,GAAG,EAAE;IACvD,qBAAK,IAAI,KAAK,iBAAiB,SAAS,GAAG,EAAE;IAC7C;;EAEF,KAAK,YACJ,QAAO;GACN,qBAAK,IAAI,KAAK,IAAI,SAAS,GAAG,QAAc,KAAK,IAAK;GACtD,KAAK;GACL;EACF,KAAK,aACJ,QAAO;GACN,qBAAK,IAAI,KAAK,IAAI,SAAS,GAAG,MAAU,KAAK,KAAK,IAAK;GACvD,KAAK;GACL;EACF,KAAK,aACJ,QAAO;GACN,qBAAK,IAAI,KAAK,IAAI,SAAS,GAAG,OAAU,KAAK,KAAK,IAAK;GACvD,KAAK;GACL;EACF,KAAK,WACJ,QAAO;GACN,KAAK,IAAI,KAAK,IAAI,aAAa,EAAE,GAAG,EAAE;GACtC,KAAK;GACL;EACF,KAAK,WACJ,QAAO;GACN,KAAK,IAAI,KAAK,IAAI,aAAa,GAAG,GAAG,GAAG,EAAE;GAC1C,KAAK,IAAI,KAAK,IAAI,aAAa,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG;GACxD;EACF,QACC,QAAO;GAAE,KAAK;GAAO,KAAK;GAAK;;;AAKlC,MAAMC,kBAAgB;CACrB,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,QAAQ;CACR;AAGD,MAAM,qBAAqB;CAC1B,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,QAAQ;CACR;;;;;;;;;AAUD,SAAwB,YAAY,EAAE,UAA4B;CACjE,MAAM,cAAc,gBAAgB;CACpC,MAAM,EACL,YACA,OACA,QACA,UACA,YACA,MAAM,MACN,UAAU,cACP;CAGJ,MAAM,iBAAiB,cAAc;EACpC,IAAIC,SAA8B,EAAE;AAGpC,MAAI,OACH,UAAS;GAAE,GAAG;GAAQ,GAAG;GAAQ;AAIlC,MAAI,SACH,UAAS;GAAE,GAAG;GAAQ,GAAG,UAAU;GAAE;AAItC,MAAI,YAAY;GACf,MAAM,EAAE,KAAK,QAAQ,aAAa,WAAW,MAAM;AACnD,UAAO,WAAW,SAAS;IAC1B,KAAK,IAAI,aAAa;IACtB,KAAK,IAAI,aAAa;IACtB;;AAGF,SAAO,OAAO,KAAK,OAAO,CAAC,SAAS,IAAI,SAAS;IAC/C;EAAC;EAAQ;EAAU;EAAW,CAAC;CAGlC,MAAM,EACL,MAAM,QAAQ,GACd,WACA,OACA,YACG,mBACH,YACA,iBAAiB,EAAE,OAAO,gBAAgB,GAAG,OAC7C;AAYD,QACC,oBAAC;EACA,OAZmB,QAClB,YAAY,MAAM,GAClB,qBAAqB,WAAW;EAWjC,MAPD,QAAQ,OAAO,SAAS,WACpB,OACD;EAMS;EACX,iBAAiB,oBAAC,wBAAsB;EACxC,OACC,iBAAiB,QAAQ,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,GAAG;EAErE,iBAAiB,SAAS;EAC1B,WAAWD,gBAAc;YAEzB,oBAAC;GAAI,WAAW,GAAG,sBAAsB,mBAAmB,SAAS;aACnE,MAAM,gBAAgB;IAClB;GACM;;;;;;;;AC9Lf,MAAM,gCAAgC,IAAI,IAAI;CAC7C;CACA;CACA;CACA;CACA,CAAC;;;;AAKF,SAAS,gBAAgB,QAAoD;AAC5E,KAAI,OAAO,WAAW,SACrB,QAAO,EAAE,KAAK,QAAQ;AAEvB,QAAO;;;;;AAMR,SAAS,eACR,QACA,UACoB;AAEpB,KAAI,OAAO,MACV,QAAO,OAAO;CAGf,MAAM,eAAe,WAAW;AAGhC,KAAI,cAAc,MACjB,QAAO,aAAa;AAGrB,QAAO,OAAO,IACZ,QAAQ,YAAY,MAAM,CAC1B,QAAQ,OAAO,MAAM,EAAE,aAAa,CAAC,CACrC,MAAM;;;;;AAMT,SAAS,qBACR,UAKE;AACF,KAAI,UAAU,MAAM,UACnB,QAAO,SAAS,KAAK;AAMtB,QAAO;;;;;;;;AASR,SAAwB,YAAY,EACnC,QACA,WAAW,UACX,YACoB;CACpB,MAAM,cAAc,gBAAgB;CACpC,MAAM,QAAQ,cAAc,YAAY;CAExC,MAAM,EACL,YACA,SAAS,YACT,QAAQ,GACR,QACA,YAAY,QACZ,QACA,cACA,iBACG;CAGJ,MAAM,UAAU,WAAW,IAAI,gBAAgB;CAK/C,MAAM,UAFc,OAAO,gBAAgB,IAAI,EAAE,EACZ,aACK;CAK1C,MAAME,eAAoB,EAAE,OAAO;AACnC,KAAI,OACH,cAAa,UAAU,GAAG,SAAS,WAAW;AAE/C,KAAI,OACH,cAAa,QAAQ;CAItB,MAAM,EAAE,MAAM,WAAW,OAAO,YAAY,kBAC3C,YACA,aACA;CAED,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAK,GAAG,KAAK,OAAO,EAAE;CACxD,MAAM,QAAQ,OAAO,QAAQ,YAAY,OAAO,MAAM,GAAG;CAGzD,MAAM,kBAAkB,SAAc;AACrC,MAAI,gBAAgB,SACnB,UAAS,GAAG,SAAS,eAAe,WAAW,GAAG,KAAK,KAAK;;CAK9D,MAAM,cACL,MACA,WACqB;EACrB,MAAM,QAAQ,KAAK,OAAO;AAG1B,MAAI,OAAO,OACV,QAAO,OAAO,OAAO,OAAO,KAAK;EAIlC,MAAM,WAAW,SAAS,OAAO;EACjC,MAAM,gBAAgB,qBAAqB,SAAS;EACpD,MAAM,YAAY,UAAU,QAAQ;AAGpC,SAFsB,8BAA8B,IAAI,UAAU,GAGjE,oBAAC;GAAqB;GAAO,KAAK;GAAgB;IAAY,GAE9D,oBAAC;GAAqB;GAAO,KAAK;IAAQ;;CAK5C,MAAM,eACL,oBAAC;EAAI,WAAU;YACd,oBAAC;GAAE,WAAU;aACX,eAAe,YAAY,aAAa,GAAG;IACzC;GACC;CAIP,MAAM,eACL,MAAM,WAAW,IAChB,eAEA,qBAAC;EAAI,WAAU;aAEd,oBAAC;GAAI,WAAU;aACb,QAAQ,KAAK,WAAW;IACxB,MAAM,WAAW,SAAS,OAAO;IACjC,MAAM,QAAQ,eAAe,QAAQ,SAAS;AAE9C,WACC,oBAAC;KAEA,WAAW,GACV,kBACA,OAAO,UAAU,YAAY,eAC7B,OAAO,UAAU,WAAW,aAC5B;KACD,OACC,OAAO,QACJ;MAAE,OAAO,OAAO;MAAO,MAAM;MAAQ,GACrC;eAGH,YAAY,MAAM;OAZd,OAAO,IAaP;KAEN;IACG,EAEL,MAAM,KAAK,SACX,eACC,oBAAC;GAEA,MAAK;GACL,WAAU;GACV,eAAe,eAAe,KAAK;aAElC,QAAQ,KAAK,WACb,oBAAC;IAEA,WAAW,GACV,mCACA,OAAO,UAAU,YAAY,eAC7B,OAAO,UAAU,WAAW,aAC5B;IACD,OACC,OAAO,QACJ;KAAE,OAAO,OAAO;KAAO,MAAM;KAAQ,GACrC;cAGH,WAAW,MAAM,OAAO;MAZpB,OAAO,IAaP,CACL;KArBG,KAAK,GAsBF,GAET,oBAAC;GAEA,WAAU;aAET,QAAQ,KAAK,WACb,oBAAC;IAEA,WAAW,GACV,mCACA,OAAO,UAAU,YAAY,eAC7B,OAAO,UAAU,WAAW,aAC5B;IACD,OACC,OAAO,QACJ;KAAE,OAAO,OAAO;KAAO,MAAM;KAAQ,GACrC;cAGH,WAAW,MAAM,OAAO;MAZpB,OAAO,IAaP,CACL;KAnBG,KAAK,GAoBL,CAEP;GACI;AAGR,QACC,oBAAC;EACO;EACI;EACX,iBACC,oBAAC;GAAoB,MAAM;GAAO,SAAS,QAAQ;IAAU;EAE9D,OACC,iBAAiB,QAAQ,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,GAAG;EAErE,iBAAiB,SAAS;YAEzB;GACW;;;;;;;;;;;AC1Qf,MAAM,gBAAgB;CACrB,SAAS;CACT,SAAS;CACT,SAAS;CACT,OAAO;CACP,MAAM;CACN;;;;AAKD,SAAS,gBACR,MACA,SAAkD,YACzC;CACT,MAAM,IAAI,OAAO,SAAS,WAAW,IAAI,KAAK,KAAK,GAAG;AAEtD,SAAQ,QAAR;EACC,KAAK,WACJ,QAAO,EAAE,oBAAoB;EAE9B,KAAK,WACJ,QAAO,EAAE,gBAAgB;EAE1B,KAAK;EACL,SAAS;GAER,MAAM,wBADM,IAAI,MAAM,EACL,SAAS,GAAG,EAAE,SAAS;GACxC,MAAM,UAAU,KAAK,MAAM,OAAO,IAAK;GACvC,MAAM,UAAU,KAAK,MAAM,UAAU,GAAG;GACxC,MAAM,QAAQ,KAAK,MAAM,UAAU,GAAG;GACtC,MAAM,OAAO,KAAK,MAAM,QAAQ,GAAG;AAEnC,OAAI,OAAO,EAAG,QAAO,EAAE,oBAAoB;AAC3C,OAAI,OAAO,EAAG,QAAO,GAAG,KAAK;AAC7B,OAAI,QAAQ,EAAG,QAAO,GAAG,MAAM;AAC/B,OAAI,UAAU,EAAG,QAAO,GAAG,QAAQ;AACnC,UAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCV,SAAwB,eAAe,EACtC,QACA,YACuB;CACvB,MAAM,SAAS,cAAc,aAAa;CAC1C,MAAM,cAAc,gBAAgB;CACpC,MAAM,EACL,WAAW,IACX,iBAAiB,MACjB,kBAAkB,YAClB,iBACG;CAEJ,MAAM,EAAE,MAAM,WAAW,OAAO,YAAY,SAAyB;EACpE,UAAU;GAAC;GAAU;GAAY,OAAO;GAAG;EAC3C,eAAe,OAAO,QAAQ,OAAO;EACrC,iBAAiB,OAAO;EACxB,CAAC;CAEF,MAAM,QAAQ,MAAM,MAAM,GAAG,SAAS,IAAI,EAAE;CAC5C,MAAM,QAAQ,OAAO,QAAQ,YAAY,OAAO,MAAM,GAAG;CAGzD,MAAM,mBAAmB,SAAuB;AAC/C,MAAI,KAAK,QAAQ,SAChB,UAAS,KAAK,KAAK;;CAKrB,MAAM,eACL,oBAAC;EAAI,WAAU;YACd,oBAAC;GAAE,WAAU;aACX,eAAe,YAAY,aAAa,GAAG;IACzC;GACC;CAIP,MAAM,kBACL,MAAM,WAAW,IAChB,eAEA,oBAAC;EAAI,WAAU;YACb,MAAM,KAAK,MAAM,UAAU;GAC3B,MAAM,OAAO,KAAK,QAAQ;GAC1B,MAAM,UAAU,KAAK,WAAW;GAChC,MAAM,SAAS,UAAU,MAAM,SAAS;GACxC,MAAM,cAAc,CAAC,EAAE,KAAK,QAAQ;GAEpC,MAAM,cACL;IAEE,CAAC,UACD,oBAAC,SAAI,WAAU,uDAAuD;IAIvE,oBAAC;KACA,WAAW,GACV,gFACA,cAAc,SACd;eAED,oBAAC;MAAK,WAAU;MAAqB,QAAO;OAAS;MAChD;IAGN,qBAAC;KAAI,WAAU;;MACd,oBAAC;OAAE,WAAU;iBAAgC,KAAK;QAAU;MAC3D,KAAK,eACL,oBAAC;OAAE,WAAU;iBACX,KAAK;QACH;MAEJ,kBAAkB,KAAK,aACvB,oBAAC;OAAE,WAAU;iBACX,gBAAgB,KAAK,WAAW,gBAAgB;QAC9C;;MAEA;OACJ;AAGJ,OAAI,YACH,QACC,oBAAC;IAEA,MAAK;IACL,WAAW,GACV,mCACA,4EACA,UAAU,OACV;IACD,eAAe,gBAAgB,KAAK;cAEnC;MATI,KAAK,GAUF;AAIX,UACC,oBAAC;IAEA,WAAW,GAAG,4BAA4B,UAAU,OAAO;cAE1D;MAHI,KAAK,GAIL;IAEN;GACG;AAGR,QACC,oBAAC;EACO;EACI;EACX,iBAAiB,oBAAC,0BAAuB,OAAO,WAAY;EAC5D,OACC,iBAAiB,QAAQ,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,GAAG;EAErE,iBAAiB,SAAS;YAEzB;GACW;;;;;;;;;;;;;;ACrMf,SAAS,YAAY,OAAgC;AACpD,KAAI,OAAO,UAAU,SACpB,QAAO,MAAM,gBAAgB;AAE9B,QAAO;;;;;;;;;;;;;;;;;;;;;;AAuBR,SAAwB,YAAY,EAAE,UAA4B;CACjE,MAAM,SAAS,cAAc,aAAa;CAC1C,MAAM,cAAc,gBAAgB;CAEpC,MAAM,EAAE,MAAM,WAAW,OAAO,SAAS,eACxC,SAA4B;EAC3B,UAAU;GAAC;GAAU;GAAS,OAAO;GAAG;EACxC,eAAe,OAAO,QAAQ,OAAO;EACrC,iBAAiB,OAAO;EACxB,CAAC;CAGH,MAAM,aAAa,OAAO,gBAAgB;AAG1C,KAAI,aAAa,SAAS,CAAC,KAC1B,QACC,oBAAC;EACA,OAAO,OAAO,QAAQ,YAAY,OAAO,MAAM,GAAG;EACvC;EACX,iBAAiB,oBAAC,uBAAoB,UAAU,aAAc;EAC9D,OACC,iBAAiB,QACd,QACA,CAAC,QAAQ,CAAC,4BACT,IAAI,MAAM,mBAAmB,GAC7B;EAEL,iBAAiB,SAAS;EAC1B,WAAW,MAAM,YAAY;GAC5B;CAIJ,MAAM,MAAM,KAAK,cAAc,EAAE;CACjC,MAAM,OAAO,KAAK;CAClB,MAAM,YAAY,KAAK,OAAO;CAG9B,MAAM,QAAQ,KAAK,QAAQ,YAAY,KAAK,MAAM,GAAG;CACrD,MAAM,WAAW,KAAK,WAAW,YAAY,KAAK,SAAS,GAAG;CAC9D,MAAM,SAAS,KAAK,SAAS,YAAY,KAAK,OAAO,GAAG;AAExD,QACC,oBAAC;EACA,OAAO;EACP,MAAM;EACN,iBAAiB,SAAS;EAC1B,cAAc,cAAc,CAAC;EAC7B,WAAW,IAAI;YAEf,qBAAC;GAAI,WAAW,GAAG,aAAa,IAAI,QAAQ;;IAE3C,oBAAC;KAAI,WAAW,GAAG,sBAAsB,IAAI,MAAM;eACjD,KAAK,aAAa,YAAY,KAAK,MAAM;MACrC;IAGL,KAAK,SACL,qBAAC;KAAI,WAAW,GAAG,mCAAmC,IAAI,MAAM;gBAC9D,aACA,oBAAC,aAAU,WAAW,GAAG,WAAW,IAAI,UAAU,GAAI,EAEvD,oBAAC,oBAAM,KAAK,MAAM,QAAa;MAC1B;IAIN,YACA,oBAAC;KAAE,WAAW,GAAG,iCAAiC,IAAI,SAAS;eAC7D;MACE;IAIJ,UACA,oBAAC;KAAE,WAAW,GAAG,sCAAsC,IAAI,OAAO;eAChE;MACE;;IAEA;GACM;;;;;;;;;;;ACzEf,SAAS,cAAc,EAAE,QAA0B;AAClD,QACC,oBAAC;EACA,OAAM;EACN,WAAU;YAEV,qBAAC;GAAE,WAAU;;IAAgC;IAC9B;IAAK;;IAChB;GACQ;;AAcf,SAAS,qBAAqB,EAC7B,QACA,cACA,QAC6B;CAC7B,MAAM,CAAC,OAAO,YAAYC,QAAM,SAI7B;EACF,WAAW;EACX,SAAS;EACT,OAAO;EACP,CAAC;AAEF,SAAM,gBAAgB;AACrB,MAAI,CAAC,QAAQ;AACZ,YAAS;IAAE,WAAW;IAAM,SAAS;IAAO,OAAO;IAAM,CAAC;AAC1D;;AAUD,MAAI,EALH,OAAO,WAAW,cAClB,CAAC,OAAO,WAAW,UACnB,CAAC,OAAO,WAAW,oBACnB,OAAO,WAAW,IAEA;AAClB,YAAS;IAAE,WAAW;IAAQ,SAAS;IAAO,OAAO;IAAM,CAAC;AAC5D;;EAID,IAAI,UAAU;AAEd,GAAC,YAAY;AACZ,OAAI;IACH,MAAM,SAAS,MAAM,QAAQ;AAC7B,QAAI,QAEH,UAAS;KAAE,WADO,OAAO,WAAW;KACd,SAAS;KAAO,OAAO;KAAM,CAAC;YAE7C,KAAK;AACb,QAAI,QACH,UAAS;KACR,WAAW;KACX,SAAS;KACT,OACC,eAAe,QACZ,sBACA,IAAI,MAAM,2BAA2B;KACzC,CAAC;;MAGD;AAEJ,eAAa;AACZ,aAAU;;IAET,CAAC,OAAO,CAAC;AAEZ,KAAI,MAAM,QACT,QAAO,oBAAC,cAAW,kBAAY;AAGhC,KAAI,MAAM,MACT,QAAO,oBAAC,cAAW,OAAO,MAAM,QAAS;AAG1C,KAAI,CAAC,MAAM,UACV,QAAO,oBAAC,cAAW,uBAAO,IAAI,MAAM,sBAAsB,GAAI;CAG/D,MAAM,YAAY,MAAM;AACxB,QAAO,oBAAC;EAAU,QAAQ;EAAoB;GAAQ;;AAOvD,SAAS,oBAAoB,EAAE,UAAyC;CACvE,MAAM,cAAc,gBAAgB;AACpC,QACC,oBAAC,eACA,QAAQ;EACP,YAAY,OAAO;EACnB,OAAO,OAAO,QAAQ,YAAY,OAAO,MAAM,GAAG;EAClD,QAAQ,OAAO;EACf,UAAU,OAAO;EACjB,YAAY,OAAO;EACnB,MAAM,OAAO;EACb,SAAS,OAAO;EAChB,GACA;;AAIJ,SAAS,oBAAoB,EAAE,UAAyC;CACvE,MAAM,cAAc,gBAAgB;AACpC,QACC,oBAAC,eACA,QAAQ;EACP,YAAY,OAAO;EACnB,OAAO,OAAO;EACd,WAAW,OAAO;EAClB,WAAW,OAAO;EAClB,OAAO,OAAO,QAAQ,YAAY,OAAO,MAAM,GAAG;EAClD,OAAO,OAAO;EACd,UAAU,OAAO;EACjB,aAAa,OAAO;EACpB,YAAY,OAAO;EACnB,GACA;;AAIJ,SAAS,0BAA0B,EAClC,QACA,UACA,YAKE;CACF,MAAM,cAAc,gBAAgB;AACpC,QACC,oBAAC,qBACA,QAAQ;EACP,YAAY,OAAO;EACnB,OAAO,OAAO;EACd,OAAO,OAAO,QAAQ,YAAY,OAAO,MAAM,GAAG;EAClD,YAAY,OAAO;EACnB,WAAW,OAAO;EAClB,gBAAgB,OAAO;EACvB;EACA,aAAa,YACT,SACD,SACC,GAAG,SAAS,eAAe,OAAO,WAAW,GAAG,KAAK,KACrD,GACD;EACH,GACA;;AAIJ,SAAS,2BAA2B,EACnC,QACA,UACA,YAKE;AACF,QACC,oBAAC;EACQ;EACE;EACA;GACT;;AAIJ,SAAS,oBAAoB,EAC5B,QACA,UACA,YAKE;AACF,QACC,oBAAC;EAAoB;EAAkB;EAAoB;GAAY;;AAIzE,SAAS,uBAAuB,EAC/B,QACA,YAIE;AACF,QAAO,oBAAC;EAAuB;EAAkB;GAAY;;AAG9D,SAAS,uBAAuB,EAAE,UAA4C;AAC7E,QAAO,oBAAC,kBAAuB,SAAU;;;;;;;;;;;;;;AAmB1C,SAAgB,gBAAgB,EAC/B,QACA,WAAW,UACX,UACA,kBAC4C;CAE5C,MAAM,qBAAyC;AAE9C,MAAI,OAAO,SAAS,SACnB,QACC,oBAAC;GACA,QAAQ,OAAO;GACf,cAAc,OAAO,UAAU,EAAE;GACjC,MAAM,OAAO;IACZ;AAKJ,MAAI,iBAAiB,OAAO,OAAO;GAClC,MAAM,eAAe,eAAe,OAAO;AAC3C,UAAO,oBAAC;IAAqB;IAAe,MAAM,OAAO;KAAQ;;AAKlE,UAAQ,OAAO,MAAf;GACC,KAAK,QACJ,QAAO,oBAAC,uBAA4B,SAA+B;GAEpE,KAAK,QACJ,QAAO,oBAAC,uBAA4B,SAA+B;GAEpE,KAAK,cACJ,QACC,oBAAC;IACQ;IACE;IACA;KACT;GAGJ,KAAK,eACJ,QACC,oBAAC;IACQ;IACE;IACA;KACT;GAGJ,KAAK,QACJ,QAAO,oBAAC,eAAoB,SAA+B;GAE5D,KAAK,QACJ,QACC,oBAAC;IACQ;IACE;IACA;KACT;GAGJ,KAAK,WACJ,QACC,oBAAC;IACQ;IACE;KACT;GAGJ,KAAK,WACJ,QACC,oBAAC,0BAA+B,SAAkC;GAGpE,QACC,QAAO,oBAAC,iBAAc,MAAM,OAAO,OAAQ;;;AAI9C,QACC,oBAAC;EAAoB,YAAY,OAAO;YACtC,cAAc;GACM;;;;;;;;;ACzSxB,MAAMC,cAAsC;CAC3C,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,IAAI;CACJ;;;;AAKD,MAAMC,cAAsC;CAC3C,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,IAAI;CACJ;;;;AASD,SAAS,aAAa,SAAyB;AAC9C,QAAO,YAAY,YAAY,YAAY;;;;;AAM5C,SAAS,aAAa,MAAkC;AACvD,KAAI,CAAC,QAAQ,QAAQ,EAAG,QAAO;AAC/B,QAAO,YAAY,SAAS;;;;;AAM7B,SAAS,eAAe,MAAiD;AACxE,QACC,OAAO,SAAS,YAChB,UAAU,QACV,KAAK,SAAS,aACd,KAAK,SAAS;;;;;AAOhB,SAAS,gBAAgB,MAAqD;AAC7E,QAAO,OAAO,SAAS,YAAY,UAAU,QAAQ,KAAK,SAAS;;;;;AAMpE,SAAS,aAAa,MAAkD;AACvE,QAAO,OAAO,SAAS,YAAY,UAAU,QAAQ,KAAK,SAAS;;;;;AAMpE,SAAS,iBAAiB,MAA2B,OAAuB;AAC3E,KAAI,eAAe,KAAK,CACvB,QAAO,UAAU,KAAK,MAAM,KAAK,KAAK,GAAG;AAE1C,KAAI,gBAAgB,KAAK,CACxB,QAAO,WAAW;AAEnB,KAAI,aAAa,KAAK,CAErB,QAAO,QADQ,KAAK,KAAK,KAAK,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,IAC1B;AAE1B,QAAO,QAAQ;;AAehB,SAAS,gBAAgB,EACxB,OACA,aACA,SACA,UACA,eACwB;AACxB,KAAI,CAAC,SAAS,CAAC,eAAe,CAAC,SAAS,OAAQ,QAAO;CAEvD,MAAM,qBAAqB,WAA4B;AACtD,MAAI,OAAO,QACV,QAAO,SAAS;WACN,OAAO,QAAQ,SACzB,UAAS,OAAO,KAAK;;AAIvB,QACC,qBAAC;EAAI,WAAU;aACd,qBAAC;GAAI,WAAU;cACb,SACA,oBAAC;IAAG,WAAU;cACZ;KACG,EAEL,eACA,oBAAC;IAAE,WAAU;cAA8B;KAAgB;IAEvD,EACL,WAAW,QAAQ,SAAS,KAC5B,oBAAC;GAAI,WAAU;aACb,QAAQ,KAAK,WAAW;IACxB,MAAM,OACL,OAAO,QAAQ,OAAO,OAAO,SAAS,WACnC,OAAO,OACP;IACJ,MAAM,UAAU,OAAO,WAAW;AAElC,WACC,qBAAC;KAEA,SAAS,YAAY,YAAY,YAAY;KAC7C,MAAK;KACL,eAAe,kBAAkB,OAAO;gBAEvC,QAAQ,oBAAC,QAAK,WAAU,iBAAiB,EACzC,YAAY,OAAO,MAAM;OANrB,OAAO,GAOJ;KAET;IACG;GAEF;;AAkBR,SAAS,mBAAmB,EAC3B,MACA,OACA,SACA,UACA,UACA,gBACA,eAC2B;AAE3B,KAAI,eAAe,KAAK,CAEvB,QACC,oBAAC;EAAI,WAAW,GAAG,kBAFF,aAAa,KAAK,KAAK,CAEO;YAC9C,oBAAC;GACA,QAAQ;GACE;GACA;GACM;IACf;GACG;AAKR,KAAI,gBAAgB,KAAK,CACxB,QACC,oBAAC;EAEA,SAAS;EACC;EACA;EACM;EACH;IALR,WAAW,QAMf;AAKJ,KAAI,aAAa,KAAK,CACrB,QACC,oBAAC;EAEA,MAAM;EACI;EACA;EACM;EACH;IALR,QAAQ,QAMZ;AAIJ,QAAO;;AAeR,SAAS,gBAAgB,EACxB,SACA,UACA,UACA,gBACA,eACwB;CACxB,MAAM,EACL,OACA,aACA,UAAU,QACV,mBAAmB,OACnB,SAAS,QACT,UAAU,GACV,KACA,OACA,cACG;CAEJ,MAAM,eAAe,QAAQ,YAAY,MAAM,GAAG;CAClD,MAAM,qBAAqB,cAAc,YAAY,YAAY,GAAG;CAGpE,MAAM,eACL,oBAAC;EACA,WAAW,GACV,cACA,WAAW,UAAU,4BACrB,WAAW,UAAU,aAAa,QAAQ,EAC1C,WAAW,WAAW,sBACtB;EACD,OAAO,MAAM,EAAE,KAAK,GAAG,MAAM,IAAK,MAAM,GAAG;YAE1C,MAAM,KAAK,MAAM,UACjB,oBAAC;GAEM;GACC;GACE;GACC;GACA;GACM;GACH;KAPR,iBAAiB,MAAM,MAAM,CAQjC,CACD;GACG;AAIP,KAAI,YAAY,OACf,QACC,qBAAC;EAAI,WAAW,GAAG,iBAAiB,UAAU;cAC3C,gBAAgB,uBACjB,qBAAC;GAAI,WAAU;cACb,gBACA,oBAAC;IAAG,WAAU;cAAyB;KAAkB,EAEzD,sBACA,oBAAC;IAAE,WAAU;cACX;KACE;IAEA,EAEN;GACI;AAKR,KAAI,YAAY,OACf,QACC,qBAAC;EAAK,WAAW,GAAG,iBAAiB,UAAU;cAC5C,gBAAgB,uBACjB,qBAAC,yBACC,gBAAgB,oBAAC,uBAAW,eAAyB,EACrD,sBACA,oBAAC;GAAE,WAAU;aACX;IACE,IAEO,EAEd,oBAAC,yBAAa,eAA2B;GACnC;AAKT,KAAI,YAAY,cACf,QACC,oBAACC;EACA,cAAc,mBAAmB,EAAE,GAAG,CAAC,EAAE;EACzC,WAAW,GAAG,iBAAiB,UAAU;YAEzC,qBAAC;GAAc,WAAU;cACxB,oBAAC;IAAiB,WAAU;cAC3B,qBAAC;KAAI,WAAU;gBACb,gBACA,oBAAC;MAAK,WAAU;gBAAyB;OAAoB,EAE7D,sBACA,oBAAC;MAAE,WAAU;gBACX;OACE;MAEA;KACY,EACnB,oBAAC;IAAiB,WAAU;cAAQ;KAAgC;IACrD;GACL;AAId,QAAO;;AAeR,SAAS,aAAa,EACrB,MACA,UACA,UACA,gBACA,eACqB;CACrB,MAAM,EAAE,MAAM,YAAY,YAAY,UAAU,cAAc;AAI9D,QACC,qBAACC;EAAK,cAHc,cAAc,WAAW,IAAI;EAGf,WAAU;aAC3C,oBAAC;GACA,SAAS,YAAY,SAAS,SAAS;GACvC,WAAU;aAET,WAAW,KAAK,QAChB,qBAAC;IAAyB,OAAO,IAAI;;KACnC,IAAI,QAAQ,oBAAC,IAAI,QAAK,WAAU,iBAAiB;KACjD,YAAY,IAAI,MAAM;KACtB,IAAI,UAAU,UACd,oBAAC;MAAK,WAAU;gBACd,IAAI;OACC;;MANS,IAAI,GAQR,CACb;IACQ,EAEV,WAAW,KAAK,QAChB,oBAAC;GAAyB,OAAO,IAAI;aACpC,oBAAC;IACK;IACK;IACA;IACM;IACH;KACZ;KAPe,IAAI,GAQR,CACb;GACI;;AAYT,SAAS,mBAAmB,EAC3B,KACA,UACA,UACA,gBACA,eAC2B;CAE3B,MAAM,UAAU;AAEhB,QACC,oBAAC;EACA,WAAW,GACV,uCACA,aAAa,QAAQ,CACrB;YAEA,IAAI,MAAM,KAAK,MAAM,UACrB,oBAAC;GAEM;GACC;GACE;GACC;GACA;GACM;GACH;KAPR,iBAAiB,MAAM,MAAM,CAQjC,CACD;GACG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCR,SAAgB,cAAc,EAC7B,QACA,WAAW,UACX,UACA,gBACA,aAC0C;CAC1C,MAAM,cAAc,gBAAgB;CACpC,MAAM,EAAE,OAAO,aAAa,UAAU,MAAM;CAG5C,MAAM,cAAc,OAAO,SAAS,OAAO,WAAW,EAAE;CAExD,MAAM,gBAAgB,QAAQ,YAAY,MAAM,GAAG;CACnD,MAAM,sBAAsB,cACzB,YAAY,YAAY,GACxB;AAGH,KAAI,YAAY,WAAW,EAC1B,QACC,qBAAC;EAAI,WAAW,GAAG,cAAc,UAAU;aAC1C,oBAAC;GACA,OAAO;GACP,aAAa;GACb,SAAS,OAAO;GACN;GACG;IACZ,EACF,oBAAC;GAAI,WAAU;aACd,qBAAC;IAAI,WAAU;eACd,oBAAC;KAAE,WAAU;eAAoC;MAE7C,EACJ,oBAAC;KAAE,WAAU;eAAqC;MAE9C;KACC;IACD;GACD;AAIR,QACC,qBAAC;EAAI,WAAW,GAAG,cAAc,UAAU;aAC1C,oBAAC;GACA,OAAO;GACP,aAAa;GACb,SAAS,OAAO;GACN;GACG;IACZ,EAEF,oBAAC;GAAI,WAAW,GAAG,4BAA4B,aAAa,QAAQ,CAAC;aACnE,YAAY,KAAK,MAAM,UACvB,oBAAC;IAEM;IACC;IACE;IACC;IACA;IACM;IACH;MAPR,iBAAiB,MAAM,MAAM,CAQjC,CACD;IACG;GACD;;;;;;;;;;;;;;;;;;;;;;;AC3kBR,SAAgB,cAAc,EAC5B,OACA,aACA,aACqB;CACrB,MAAM,QAAQ,cAAc,YAAY;CACxC,MAAM,WAAW,cAAc,eAAe;CAC9C,MAAM,WAAW,cAAc,eAAe;AAW9C,QACE,oBAAC;EACC,QARW;GACb,GAJsB,MAAM,cAAc;GAK1C,GAAI,SAAS,EAAE,OAAO;GACtB,GAAI,eAAe,EAAE,aAAa;GACnC;EAKa;EACA;EACC;GACX;;AAIN,6BAAe"}
@@ -0,0 +1,6 @@
1
+ import "./content-locales-provider-BXvuIgfg.mjs";
2
+ import { n as dashboard_page_default, t as DashboardPage } from "./dashboard-page-B4PGEdc2.mjs";
3
+ import "./runtime-6VZM878K.mjs";
4
+ import "./card-BKHjBQfw.mjs";
5
+
6
+ export { DashboardPage, dashboard_page_default as default };