@object-ui/components 3.3.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +21 -1
  3. package/dist/index.css +6339 -2
  4. package/dist/index.js +17600 -17481
  5. package/dist/index.umd.cjs +36 -36
  6. package/dist/packages/components/src/custom/empty.d.ts +12 -1
  7. package/dist/packages/components/src/renderers/action/action-bar.d.ts +12 -1
  8. package/dist/packages/components/src/ui/chart.d.ts +10 -29
  9. package/package.json +65 -44
  10. package/.turbo/turbo-build.log +0 -84
  11. package/README_SHADCN_SYNC.md +0 -281
  12. package/TESTING.md +0 -335
  13. package/docs/FilterBuilder.md +0 -268
  14. package/metadata/Chart.component.yml +0 -30
  15. package/metadata/FilterBuilder.component.yml +0 -39
  16. package/metadata/GridLayout.component.yml +0 -27
  17. package/metadata/Menu.component.yml +0 -31
  18. package/metadata/ObjectForm.component.yml +0 -34
  19. package/metadata/ObjectGrid.component.yml +0 -72
  20. package/metadata/Page.component.yml +0 -24
  21. package/postcss.config.js +0 -14
  22. package/shadcn-components.json +0 -440
  23. package/src/SchemaRenderer.tsx +0 -28
  24. package/src/__tests__/PageRendererRegions.test.tsx +0 -668
  25. package/src/__tests__/README.md +0 -124
  26. package/src/__tests__/__snapshots__/snapshot-critical.test.tsx.snap +0 -811
  27. package/src/__tests__/__snapshots__/snapshot.test.tsx.snap +0 -327
  28. package/src/__tests__/accessibility.test.tsx +0 -137
  29. package/src/__tests__/action-bar.test.tsx +0 -206
  30. package/src/__tests__/api-consistency.test.tsx +0 -596
  31. package/src/__tests__/basic-renderers.test.tsx +0 -255
  32. package/src/__tests__/color-contrast.test.tsx +0 -212
  33. package/src/__tests__/complex-disclosure-renderers.test.tsx +0 -302
  34. package/src/__tests__/compliance.test.tsx +0 -72
  35. package/src/__tests__/config-field-renderer.test.tsx +0 -307
  36. package/src/__tests__/config-panel-renderer.test.tsx +0 -580
  37. package/src/__tests__/config-primitives.test.tsx +0 -106
  38. package/src/__tests__/edge-cases.test.tsx +0 -285
  39. package/src/__tests__/feedback-overlay-renderers.test.tsx +0 -349
  40. package/src/__tests__/filter-builder.test.tsx +0 -409
  41. package/src/__tests__/form-renderers.test.tsx +0 -364
  42. package/src/__tests__/layout-data-renderers.test.tsx +0 -340
  43. package/src/__tests__/mobile-accessibility.test.tsx +0 -120
  44. package/src/__tests__/navigation-overlay.test.tsx +0 -370
  45. package/src/__tests__/snapshot-critical.test.tsx +0 -317
  46. package/src/__tests__/snapshot.test.tsx +0 -205
  47. package/src/__tests__/test-utils.tsx +0 -190
  48. package/src/__tests__/use-config-draft.test.tsx +0 -295
  49. package/src/__tests__/view-compliance.test.tsx +0 -153
  50. package/src/__tests__/wcag-audit.test.tsx +0 -493
  51. package/src/custom/action-param-dialog.tsx +0 -264
  52. package/src/custom/button-group.tsx +0 -91
  53. package/src/custom/combobox.tsx +0 -104
  54. package/src/custom/config-field-renderer.tsx +0 -276
  55. package/src/custom/config-panel-renderer.tsx +0 -306
  56. package/src/custom/config-row.tsx +0 -50
  57. package/src/custom/date-picker.tsx +0 -61
  58. package/src/custom/empty.tsx +0 -112
  59. package/src/custom/field.tsx +0 -81
  60. package/src/custom/filter-builder.tsx +0 -418
  61. package/src/custom/index.ts +0 -21
  62. package/src/custom/input-group.tsx +0 -53
  63. package/src/custom/item.tsx +0 -201
  64. package/src/custom/kbd.tsx +0 -36
  65. package/src/custom/mobile-dialog-content.tsx +0 -67
  66. package/src/custom/native-select.tsx +0 -33
  67. package/src/custom/navigation-overlay.tsx +0 -334
  68. package/src/custom/section-header.tsx +0 -68
  69. package/src/custom/sort-builder.tsx +0 -129
  70. package/src/custom/spinner.tsx +0 -26
  71. package/src/custom/view-skeleton.tsx +0 -243
  72. package/src/custom/view-states.tsx +0 -153
  73. package/src/debug/DebugPanel.tsx +0 -313
  74. package/src/debug/__tests__/DebugPanel.test.tsx +0 -134
  75. package/src/debug/index.ts +0 -10
  76. package/src/hooks/use-config-draft.ts +0 -127
  77. package/src/hooks/use-mobile.tsx +0 -27
  78. package/src/index.css +0 -245
  79. package/src/index.ts +0 -47
  80. package/src/lib/use-sync-external-store-shim.ts +0 -10
  81. package/src/lib/use-sync-external-store-with-selector-shim.ts +0 -90
  82. package/src/lib/utils.tsx +0 -35
  83. package/src/new-components.test.ts +0 -73
  84. package/src/renderers/action/action-bar.tsx +0 -221
  85. package/src/renderers/action/action-button.tsx +0 -158
  86. package/src/renderers/action/action-group.tsx +0 -270
  87. package/src/renderers/action/action-icon.tsx +0 -150
  88. package/src/renderers/action/action-menu.tsx +0 -203
  89. package/src/renderers/action/index.ts +0 -19
  90. package/src/renderers/action/resolve-icon.ts +0 -35
  91. package/src/renderers/basic/button-group.tsx +0 -79
  92. package/src/renderers/basic/div.tsx +0 -60
  93. package/src/renderers/basic/html.tsx +0 -43
  94. package/src/renderers/basic/icon.tsx +0 -89
  95. package/src/renderers/basic/image.tsx +0 -49
  96. package/src/renderers/basic/index.ts +0 -18
  97. package/src/renderers/basic/navigation-menu.tsx +0 -81
  98. package/src/renderers/basic/pagination.tsx +0 -109
  99. package/src/renderers/basic/separator.tsx +0 -57
  100. package/src/renderers/basic/span.tsx +0 -63
  101. package/src/renderers/basic/text.tsx +0 -52
  102. package/src/renderers/complex/README-KANBAN.md +0 -208
  103. package/src/renderers/complex/TIMELINE.md +0 -353
  104. package/src/renderers/complex/__tests__/data-table-airtable-ux.test.tsx +0 -239
  105. package/src/renderers/complex/__tests__/data-table-batch-editing.test.tsx +0 -275
  106. package/src/renderers/complex/__tests__/data-table-cell-renderer.test.tsx +0 -120
  107. package/src/renderers/complex/__tests__/data-table-editing.test.tsx +0 -221
  108. package/src/renderers/complex/__tests__/data-table.test.ts +0 -76
  109. package/src/renderers/complex/carousel.tsx +0 -69
  110. package/src/renderers/complex/data-table.tsx +0 -1243
  111. package/src/renderers/complex/filter-builder.tsx +0 -77
  112. package/src/renderers/complex/index.ts +0 -16
  113. package/src/renderers/complex/resizable.tsx +0 -66
  114. package/src/renderers/complex/scroll-area.tsx +0 -58
  115. package/src/renderers/complex/table.tsx +0 -95
  116. package/src/renderers/data-display/alert.tsx +0 -46
  117. package/src/renderers/data-display/avatar.tsx +0 -38
  118. package/src/renderers/data-display/badge.tsx +0 -55
  119. package/src/renderers/data-display/breadcrumb.tsx +0 -61
  120. package/src/renderers/data-display/index.ts +0 -18
  121. package/src/renderers/data-display/kbd.tsx +0 -50
  122. package/src/renderers/data-display/list.tsx +0 -75
  123. package/src/renderers/data-display/statistic.tsx +0 -95
  124. package/src/renderers/data-display/table.tsx +0 -78
  125. package/src/renderers/data-display/tree-view.tsx +0 -176
  126. package/src/renderers/disclosure/accordion.tsx +0 -69
  127. package/src/renderers/disclosure/collapsible.tsx +0 -53
  128. package/src/renderers/disclosure/index.ts +0 -11
  129. package/src/renderers/disclosure/toggle-group.tsx +0 -79
  130. package/src/renderers/feedback/empty.tsx +0 -49
  131. package/src/renderers/feedback/index.ts +0 -16
  132. package/src/renderers/feedback/loading.tsx +0 -78
  133. package/src/renderers/feedback/progress.tsx +0 -29
  134. package/src/renderers/feedback/skeleton.tsx +0 -31
  135. package/src/renderers/feedback/sonner.tsx +0 -56
  136. package/src/renderers/feedback/spinner.tsx +0 -55
  137. package/src/renderers/feedback/toast.tsx +0 -59
  138. package/src/renderers/feedback/toaster.tsx +0 -23
  139. package/src/renderers/form/button.tsx +0 -103
  140. package/src/renderers/form/calendar.tsx +0 -34
  141. package/src/renderers/form/checkbox.tsx +0 -71
  142. package/src/renderers/form/combobox.tsx +0 -48
  143. package/src/renderers/form/command.tsx +0 -58
  144. package/src/renderers/form/date-picker.tsx +0 -84
  145. package/src/renderers/form/file-upload.tsx +0 -184
  146. package/src/renderers/form/form.tsx +0 -540
  147. package/src/renderers/form/index.ts +0 -26
  148. package/src/renderers/form/input-otp.tsx +0 -51
  149. package/src/renderers/form/input.tsx +0 -121
  150. package/src/renderers/form/label.tsx +0 -45
  151. package/src/renderers/form/radio-group.tsx +0 -63
  152. package/src/renderers/form/select.tsx +0 -94
  153. package/src/renderers/form/slider.tsx +0 -61
  154. package/src/renderers/form/switch.tsx +0 -48
  155. package/src/renderers/form/textarea.tsx +0 -76
  156. package/src/renderers/form/toggle.tsx +0 -42
  157. package/src/renderers/index.ts +0 -18
  158. package/src/renderers/layout/aspect-ratio.tsx +0 -51
  159. package/src/renderers/layout/card.tsx +0 -85
  160. package/src/renderers/layout/container.tsx +0 -122
  161. package/src/renderers/layout/flex.tsx +0 -132
  162. package/src/renderers/layout/grid.tsx +0 -178
  163. package/src/renderers/layout/index.ts +0 -19
  164. package/src/renderers/layout/page.tsx +0 -466
  165. package/src/renderers/layout/semantic.tsx +0 -48
  166. package/src/renderers/layout/stack.tsx +0 -132
  167. package/src/renderers/layout/tabs.tsx +0 -97
  168. package/src/renderers/navigation/header-bar.tsx +0 -118
  169. package/src/renderers/navigation/index.ts +0 -10
  170. package/src/renderers/navigation/sidebar.tsx +0 -208
  171. package/src/renderers/overlay/alert-dialog.tsx +0 -72
  172. package/src/renderers/overlay/context-menu.tsx +0 -100
  173. package/src/renderers/overlay/dialog.tsx +0 -77
  174. package/src/renderers/overlay/drawer.tsx +0 -77
  175. package/src/renderers/overlay/dropdown-menu.tsx +0 -99
  176. package/src/renderers/overlay/hover-card.tsx +0 -55
  177. package/src/renderers/overlay/index.ts +0 -18
  178. package/src/renderers/overlay/menubar.tsx +0 -76
  179. package/src/renderers/overlay/popover.tsx +0 -56
  180. package/src/renderers/overlay/sheet.tsx +0 -77
  181. package/src/renderers/overlay/tooltip.tsx +0 -67
  182. package/src/renderers/placeholders.tsx +0 -107
  183. package/src/stories/CRMApp.stories.tsx +0 -706
  184. package/src/stories/ConfigPanel.stories.tsx +0 -232
  185. package/src/stories/Guide.mdx +0 -55
  186. package/src/stories/MockedData.stories.tsx +0 -121
  187. package/src/stories/assets/accessibility.png +0 -0
  188. package/src/stories/assets/accessibility.svg +0 -1
  189. package/src/stories/assets/addon-library.png +0 -0
  190. package/src/stories/assets/assets.png +0 -0
  191. package/src/stories/assets/avif-test-image.avif +0 -0
  192. package/src/stories/assets/context.png +0 -0
  193. package/src/stories/assets/discord.svg +0 -1
  194. package/src/stories/assets/docs.png +0 -0
  195. package/src/stories/assets/figma-plugin.png +0 -0
  196. package/src/stories/assets/github.svg +0 -1
  197. package/src/stories/assets/share.png +0 -0
  198. package/src/stories/assets/styling.png +0 -0
  199. package/src/stories/assets/testing.png +0 -0
  200. package/src/stories/assets/theming.png +0 -0
  201. package/src/stories/assets/tutorials.svg +0 -1
  202. package/src/stories/assets/youtube.svg +0 -1
  203. package/src/stories/button.css +0 -30
  204. package/src/stories/header.css +0 -32
  205. package/src/stories/page.css +0 -68
  206. package/src/stories-json/Accessibility.mdx +0 -297
  207. package/src/stories-json/EdgeCases.stories.tsx +0 -160
  208. package/src/stories-json/GettingStarted.mdx +0 -89
  209. package/src/stories-json/Introduction.mdx +0 -127
  210. package/src/stories-json/accordion.stories.tsx +0 -43
  211. package/src/stories-json/aggrid.stories.tsx +0 -103
  212. package/src/stories-json/alert.stories.tsx +0 -39
  213. package/src/stories-json/aspect-ratio.stories.tsx +0 -34
  214. package/src/stories-json/avatar.stories.tsx +0 -38
  215. package/src/stories-json/badge.stories.tsx +0 -53
  216. package/src/stories-json/breadcrumb.stories.tsx +0 -30
  217. package/src/stories-json/button-group.stories.tsx +0 -43
  218. package/src/stories-json/button.stories.tsx +0 -73
  219. package/src/stories-json/calendar.stories.tsx +0 -85
  220. package/src/stories-json/card.stories.tsx +0 -48
  221. package/src/stories-json/carousel.stories.tsx +0 -33
  222. package/src/stories-json/charts.stories.tsx +0 -195
  223. package/src/stories-json/chatbot.stories.tsx +0 -349
  224. package/src/stories-json/code-editor.stories.tsx +0 -92
  225. package/src/stories-json/collapsible.stories.tsx +0 -40
  226. package/src/stories-json/controls.stories.tsx +0 -36
  227. package/src/stories-json/crm-live-data.stories.tsx +0 -154
  228. package/src/stories-json/dashboard.stories.tsx +0 -318
  229. package/src/stories-json/data-table.stories.tsx +0 -136
  230. package/src/stories-json/data_display_extras.stories.tsx +0 -102
  231. package/src/stories-json/date-picker.stories.tsx +0 -28
  232. package/src/stories-json/detail-view.stories.tsx +0 -258
  233. package/src/stories-json/dialog.stories.tsx +0 -43
  234. package/src/stories-json/feedback_extras.stories.tsx +0 -40
  235. package/src/stories-json/feedback_others.stories.tsx +0 -46
  236. package/src/stories-json/form-variants.stories.tsx +0 -210
  237. package/src/stories-json/form_advanced.stories.tsx +0 -117
  238. package/src/stories-json/form_extras.stories.tsx +0 -123
  239. package/src/stories-json/grid.stories.tsx +0 -56
  240. package/src/stories-json/icon.stories.tsx +0 -36
  241. package/src/stories-json/input.stories.tsx +0 -52
  242. package/src/stories-json/kanban.stories.tsx +0 -295
  243. package/src/stories-json/layout_extended.stories.tsx +0 -76
  244. package/src/stories-json/layout_flex.stories.tsx +0 -107
  245. package/src/stories-json/list-view.stories.tsx +0 -97
  246. package/src/stories-json/markdown.stories.tsx +0 -129
  247. package/src/stories-json/menus.stories.tsx +0 -63
  248. package/src/stories-json/metric-card.stories.tsx +0 -143
  249. package/src/stories-json/navigation-menu.stories.tsx +0 -37
  250. package/src/stories-json/object-aggrid-advanced.stories.tsx +0 -389
  251. package/src/stories-json/object-aggrid.stories.tsx +0 -252
  252. package/src/stories-json/object-form.stories.tsx +0 -130
  253. package/src/stories-json/object-gantt.stories.tsx +0 -114
  254. package/src/stories-json/object-grid.stories.tsx +0 -315
  255. package/src/stories-json/object-map.stories.tsx +0 -116
  256. package/src/stories-json/object-view.stories.tsx +0 -118
  257. package/src/stories-json/overlay_extras.stories.tsx +0 -113
  258. package/src/stories-json/overlay_others.stories.tsx +0 -76
  259. package/src/stories-json/page.stories.tsx +0 -55
  260. package/src/stories-json/reports.stories.tsx +0 -163
  261. package/src/stories-json/resizable.stories.tsx +0 -44
  262. package/src/stories-json/select.stories.tsx +0 -34
  263. package/src/stories-json/separator.stories.tsx +0 -41
  264. package/src/stories-json/sidebar.stories.tsx +0 -147
  265. package/src/stories-json/statistic.stories.tsx +0 -44
  266. package/src/stories-json/tabs.stories.tsx +0 -51
  267. package/src/stories-json/timeline.stories.tsx +0 -188
  268. package/src/stories-json/typography.stories.tsx +0 -45
  269. package/src/types/config-panel.ts +0 -101
  270. package/src/ui/accordion.tsx +0 -66
  271. package/src/ui/alert-dialog.tsx +0 -149
  272. package/src/ui/alert.tsx +0 -67
  273. package/src/ui/aspect-ratio.tsx +0 -15
  274. package/src/ui/avatar.tsx +0 -58
  275. package/src/ui/badge.tsx +0 -44
  276. package/src/ui/breadcrumb.tsx +0 -123
  277. package/src/ui/button.tsx +0 -64
  278. package/src/ui/calendar.tsx +0 -221
  279. package/src/ui/card.tsx +0 -87
  280. package/src/ui/carousel.tsx +0 -270
  281. package/src/ui/chart.tsx +0 -377
  282. package/src/ui/checkbox.tsx +0 -38
  283. package/src/ui/collapsible.tsx +0 -19
  284. package/src/ui/command.tsx +0 -161
  285. package/src/ui/context-menu.tsx +0 -208
  286. package/src/ui/dialog.tsx +0 -130
  287. package/src/ui/drawer.tsx +0 -126
  288. package/src/ui/dropdown-menu.tsx +0 -208
  289. package/src/ui/form.tsx +0 -186
  290. package/src/ui/hover-card.tsx +0 -37
  291. package/src/ui/index.ts +0 -56
  292. package/src/ui/input-otp.tsx +0 -79
  293. package/src/ui/input.tsx +0 -30
  294. package/src/ui/label.tsx +0 -34
  295. package/src/ui/menubar.tsx +0 -264
  296. package/src/ui/navigation-menu.tsx +0 -136
  297. package/src/ui/pagination.tsx +0 -125
  298. package/src/ui/popover.tsx +0 -39
  299. package/src/ui/progress.tsx +0 -36
  300. package/src/ui/radio-group.tsx +0 -52
  301. package/src/ui/resizable.tsx +0 -53
  302. package/src/ui/scroll-area.tsx +0 -56
  303. package/src/ui/select.tsx +0 -168
  304. package/src/ui/separator.tsx +0 -39
  305. package/src/ui/sheet.tsx +0 -150
  306. package/src/ui/sidebar.tsx +0 -781
  307. package/src/ui/skeleton.tsx +0 -23
  308. package/src/ui/slider.tsx +0 -39
  309. package/src/ui/sonner.tsx +0 -53
  310. package/src/ui/switch.tsx +0 -37
  311. package/src/ui/table.tsx +0 -125
  312. package/src/ui/tabs.tsx +0 -63
  313. package/src/ui/textarea.tsx +0 -30
  314. package/src/ui/toast.tsx +0 -137
  315. package/src/ui/toggle-group.tsx +0 -69
  316. package/src/ui/toggle.tsx +0 -53
  317. package/src/ui/tooltip.tsx +0 -38
  318. package/src/ui/typography.tsx +0 -85
  319. package/tsconfig.json +0 -19
  320. package/vite.config.ts +0 -71
  321. package/vitest.config.ts +0 -5
@@ -1,68 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- import { ChevronDown, ChevronRight } from "lucide-react"
10
-
11
- import { cn } from "../lib/utils"
12
-
13
- export interface SectionHeaderProps {
14
- /** Section heading text */
15
- title: string
16
- /** Icon rendered before the title */
17
- icon?: React.ReactNode
18
- /** Enable collapse/expand toggle */
19
- collapsible?: boolean
20
- /** Current collapsed state */
21
- collapsed?: boolean
22
- /** Callback when toggling collapse/expand */
23
- onToggle?: () => void
24
- /** Data-testid attribute */
25
- testId?: string
26
- /** Additional CSS class name */
27
- className?: string
28
- }
29
-
30
- /**
31
- * Section heading with optional collapse/expand support.
32
- *
33
- * Renders as a `<button>` when collapsible, with a chevron icon
34
- * indicating the expand/collapse state. Uses `aria-expanded` for accessibility.
35
- */
36
- function SectionHeader({ title, icon, collapsible, collapsed, onToggle, testId, className }: SectionHeaderProps) {
37
- const titleContent = (
38
- <h3 className="text-xs font-semibold text-foreground uppercase tracking-wider flex items-center gap-1.5">
39
- {icon && <span className="text-muted-foreground shrink-0" aria-hidden="true">{icon}</span>}
40
- {title}
41
- </h3>
42
- )
43
- if (collapsible) {
44
- return (
45
- <button
46
- data-testid={testId}
47
- className={cn("flex items-center justify-between pt-4 pb-1.5 first:pt-0 w-full text-left", className)}
48
- onClick={onToggle}
49
- type="button"
50
- aria-expanded={!collapsed}
51
- >
52
- {titleContent}
53
- {collapsed ? (
54
- <ChevronRight className="h-3 w-3 text-muted-foreground" />
55
- ) : (
56
- <ChevronDown className="h-3 w-3 text-muted-foreground" />
57
- )}
58
- </button>
59
- )
60
- }
61
- return (
62
- <div className={cn("pt-4 pb-1.5 first:pt-0", className)} data-testid={testId}>
63
- {titleContent}
64
- </div>
65
- )
66
- }
67
-
68
- export { SectionHeader }
@@ -1,129 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- import * as React from "react"
10
- import { X, Plus, Trash2 } from "lucide-react"
11
-
12
- import { cn } from "../lib/utils"
13
- import { Button } from "../ui/button"
14
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"
15
-
16
- export interface SortItem {
17
- id: string;
18
- field: string;
19
- order: 'asc' | 'desc';
20
- }
21
-
22
- export interface SortBuilderProps {
23
- fields?: Array<{
24
- value: string
25
- label: string
26
- }>;
27
- value?: SortItem[];
28
- onChange?: (value: SortItem[]) => void;
29
- className?: string;
30
- }
31
-
32
- export function SortBuilder({
33
- fields = [],
34
- value = [],
35
- onChange,
36
- className,
37
- }: SortBuilderProps) {
38
- // Use internal state initialization prop changes
39
- const [items, setItems] = React.useState<SortItem[]>(value || []);
40
-
41
- React.useEffect(() => {
42
- if (value && JSON.stringify(value) !== JSON.stringify(items)) {
43
- setItems(value);
44
- }
45
- }, [value]);
46
-
47
- const handleChange = (newItems: SortItem[]) => {
48
- setItems(newItems);
49
- onChange?.(newItems);
50
- };
51
-
52
- const addItem = () => {
53
- const newItem: SortItem = {
54
- id: crypto.randomUUID(),
55
- field: fields[0]?.value || "",
56
- order: 'asc',
57
- };
58
- handleChange([...items, newItem]);
59
- };
60
-
61
- const updateItem = (id: string, updates: Partial<SortItem>) => {
62
- handleChange(items.map(item => item.id === id ? { ...item, ...updates } : item));
63
- };
64
-
65
- const removeItem = (id: string) => {
66
- handleChange(items.filter(item => item.id !== id));
67
- };
68
-
69
- return (
70
- <div className={cn("space-y-3", className)}>
71
- <div className="space-y-2">
72
- {items.map((item, index) => (
73
- <div key={item.id} className="flex items-center gap-2">
74
- <span className="text-sm font-medium w-16 text-muted-foreground">
75
- {index === 0 ? "Sort by" : "Then by"}
76
- </span>
77
- <div className="flex-1">
78
- <Select
79
- value={item.field}
80
- onValueChange={(val) => updateItem(item.id, { field: val })}
81
- >
82
- <SelectTrigger className="h-9">
83
- <SelectValue placeholder="Select field" />
84
- </SelectTrigger>
85
- <SelectContent>
86
- {fields.map(f => (
87
- <SelectItem key={f.value} value={f.value}>{f.label}</SelectItem>
88
- ))}
89
- </SelectContent>
90
- </Select>
91
- </div>
92
- <div className="w-28">
93
- <Select
94
- value={item.order}
95
- onValueChange={(val) => updateItem(item.id, { order: val as 'asc' | 'desc' })}
96
- >
97
- <SelectTrigger className="h-9">
98
- <SelectValue />
99
- </SelectTrigger>
100
- <SelectContent>
101
- <SelectItem value="asc">A -&gt; Z</SelectItem>
102
- <SelectItem value="desc">Z -&gt; A</SelectItem>
103
- </SelectContent>
104
- </Select>
105
- </div>
106
- <Button
107
- variant="ghost"
108
- size="icon"
109
- className="h-9 w-9 shrink-0"
110
- onClick={() => removeItem(item.id)}
111
- >
112
- <X className="h-4 w-4" />
113
- </Button>
114
- </div>
115
- ))}
116
- </div>
117
- <Button
118
- variant="outline"
119
- size="sm"
120
- onClick={addItem}
121
- className="h-8"
122
- disabled={fields.length === 0}
123
- >
124
- <Plus className="h-3 w-3 mr-2" />
125
- Add sort
126
- </Button>
127
- </div>
128
- );
129
- }
@@ -1,26 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- import * as React from "react"
10
- import { cn } from "../lib/utils"
11
- import { Loader2 } from "lucide-react"
12
-
13
- function Spinner({ className, ...props }: React.ComponentProps<"div">) {
14
- return (
15
- <div
16
- role="status"
17
- aria-label="Loading"
18
- className={cn("flex items-center justify-center", className)}
19
- {...props}
20
- >
21
- <Loader2 className="animate-spin text-muted-foreground w-full h-full min-w-4 min-h-4" />
22
- </div>
23
- )
24
- }
25
-
26
- export { Spinner }
@@ -1,243 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- import * as React from "react"
10
- import { cn } from "../lib/utils"
11
- import { Skeleton } from "../ui/skeleton"
12
-
13
- // ---------------------------------------------------------------------------
14
- // Shared types
15
- // ---------------------------------------------------------------------------
16
-
17
- export interface ViewSkeletonProps extends React.ComponentProps<"div"> {
18
- /** Number of rows/items to render */
19
- rows?: number
20
- }
21
-
22
- // ---------------------------------------------------------------------------
23
- // GridSkeleton – table rows with header and column cells
24
- // ---------------------------------------------------------------------------
25
-
26
- export interface GridSkeletonProps extends ViewSkeletonProps {
27
- /** Number of columns to render */
28
- columns?: number
29
- }
30
-
31
- function GridSkeleton({
32
- rows = 5,
33
- columns = 4,
34
- className,
35
- ...props
36
- }: GridSkeletonProps) {
37
- return (
38
- <div
39
- data-slot="grid-skeleton"
40
- className={cn("w-full space-y-2", className)}
41
- {...props}
42
- >
43
- {/* Header row */}
44
- <div className="flex gap-4 px-4 py-2">
45
- {Array.from({ length: columns }).map((_, col) => (
46
- <Skeleton key={col} className="h-4 flex-1 rounded" />
47
- ))}
48
- </div>
49
-
50
- {/* Data rows */}
51
- {Array.from({ length: rows }).map((_, row) => (
52
- <div key={row} className="flex gap-4 rounded-md border px-4 py-3">
53
- {Array.from({ length: columns }).map((_, col) => (
54
- <Skeleton
55
- key={col}
56
- className={cn("h-4 flex-1 rounded", col === 0 && "max-w-[40%]")}
57
- />
58
- ))}
59
- </div>
60
- ))}
61
- </div>
62
- )
63
- }
64
-
65
- // ---------------------------------------------------------------------------
66
- // KanbanSkeleton – columns with placeholder cards
67
- // ---------------------------------------------------------------------------
68
-
69
- export interface KanbanSkeletonProps extends ViewSkeletonProps {
70
- /** Number of kanban columns to render */
71
- columns?: number
72
- /** Number of cards per column */
73
- cardsPerColumn?: number
74
- }
75
-
76
- function KanbanSkeleton({
77
- columns = 3,
78
- cardsPerColumn = 3,
79
- className,
80
- ...props
81
- }: KanbanSkeletonProps) {
82
- return (
83
- <div
84
- data-slot="kanban-skeleton"
85
- className={cn("flex gap-4 overflow-x-auto", className)}
86
- {...props}
87
- >
88
- {Array.from({ length: columns }).map((_, col) => (
89
- <div
90
- key={col}
91
- className="flex w-72 shrink-0 flex-col gap-3 rounded-lg border bg-muted/30 p-3"
92
- >
93
- {/* Column header */}
94
- <Skeleton className="h-5 w-24 rounded" />
95
-
96
- {/* Cards */}
97
- {Array.from({ length: cardsPerColumn }).map((_, card) => (
98
- <div key={card} className="space-y-2 rounded-md border bg-background p-3">
99
- <Skeleton className="h-4 w-3/4 rounded" />
100
- <Skeleton className="h-3 w-1/2 rounded" />
101
- </div>
102
- ))}
103
- </div>
104
- ))}
105
- </div>
106
- )
107
- }
108
-
109
- // ---------------------------------------------------------------------------
110
- // FormSkeleton – labeled form fields
111
- // ---------------------------------------------------------------------------
112
-
113
- function FormSkeleton({
114
- rows = 4,
115
- className,
116
- ...props
117
- }: ViewSkeletonProps) {
118
- return (
119
- <div
120
- data-slot="form-skeleton"
121
- className={cn("w-full max-w-lg space-y-6", className)}
122
- {...props}
123
- >
124
- {Array.from({ length: rows }).map((_, i) => (
125
- <div key={i} className="space-y-2">
126
- {/* Label */}
127
- <Skeleton className="h-4 w-28 rounded" />
128
- {/* Input */}
129
- <Skeleton className="h-9 w-full rounded-md" />
130
- </div>
131
- ))}
132
-
133
- {/* Submit button */}
134
- <Skeleton className="h-9 w-24 rounded-md" />
135
- </div>
136
- )
137
- }
138
-
139
- // ---------------------------------------------------------------------------
140
- // ListSkeleton – stacked list items
141
- // ---------------------------------------------------------------------------
142
-
143
- function ListSkeleton({
144
- rows = 5,
145
- className,
146
- ...props
147
- }: ViewSkeletonProps) {
148
- return (
149
- <div
150
- data-slot="list-skeleton"
151
- className={cn("w-full space-y-3", className)}
152
- {...props}
153
- >
154
- {Array.from({ length: rows }).map((_, i) => (
155
- <div
156
- key={i}
157
- className="flex items-center gap-3 rounded-md border px-4 py-3"
158
- >
159
- <Skeleton className="size-8 shrink-0 rounded-full" />
160
- <div className="flex-1 space-y-2">
161
- <Skeleton className="h-4 w-3/5 rounded" />
162
- <Skeleton className="h-3 w-2/5 rounded" />
163
- </div>
164
- </div>
165
- ))}
166
- </div>
167
- )
168
- }
169
-
170
- // ---------------------------------------------------------------------------
171
- // ChartSkeleton – chart area placeholder
172
- // ---------------------------------------------------------------------------
173
-
174
- function ChartSkeleton({
175
- className,
176
- ...props
177
- }: Omit<ViewSkeletonProps, "rows">) {
178
- return (
179
- <div
180
- data-slot="chart-skeleton"
181
- className={cn("w-full space-y-4", className)}
182
- {...props}
183
- >
184
- {/* Chart title */}
185
- <Skeleton className="h-5 w-40 rounded" />
186
-
187
- {/* Chart area with bar placeholders */}
188
- <div className="flex h-48 items-end gap-2 rounded-md border p-4">
189
- {(["h-2/5", "h-3/5", "h-1/3", "h-4/5", "h-1/2", "h-3/4", "h-2/5"] as const).map((heightClass, i) => (
190
- <Skeleton
191
- key={i}
192
- className={cn("flex-1 rounded-t", heightClass)}
193
- />
194
- ))}
195
- </div>
196
-
197
- {/* Legend */}
198
- <div className="flex gap-4">
199
- <Skeleton className="h-3 w-16 rounded" />
200
- <Skeleton className="h-3 w-16 rounded" />
201
- <Skeleton className="h-3 w-16 rounded" />
202
- </div>
203
- </div>
204
- )
205
- }
206
-
207
- // ---------------------------------------------------------------------------
208
- // ViewSkeleton – convenience wrapper that dispatches by variant
209
- // ---------------------------------------------------------------------------
210
-
211
- export type ViewSkeletonVariant = "grid" | "kanban" | "form" | "list" | "chart"
212
-
213
- export interface ViewSkeletonDispatchProps extends ViewSkeletonProps {
214
- variant: ViewSkeletonVariant
215
- /** Number of columns (grid / kanban) */
216
- columns?: number
217
- /** Cards per column (kanban only) */
218
- cardsPerColumn?: number
219
- }
220
-
221
- function ViewSkeleton({ variant, ...props }: ViewSkeletonDispatchProps) {
222
- switch (variant) {
223
- case "grid":
224
- return <GridSkeleton {...props} />
225
- case "kanban":
226
- return <KanbanSkeleton {...props} />
227
- case "form":
228
- return <FormSkeleton {...props} />
229
- case "list":
230
- return <ListSkeleton {...props} />
231
- case "chart":
232
- return <ChartSkeleton {...props} />
233
- }
234
- }
235
-
236
- export {
237
- ViewSkeleton,
238
- GridSkeleton,
239
- KanbanSkeleton,
240
- FormSkeleton,
241
- ListSkeleton,
242
- ChartSkeleton,
243
- }
@@ -1,153 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- import * as React from "react"
10
- import { Loader2, InboxIcon, AlertCircle } from "lucide-react"
11
-
12
- import { cn } from "../lib/utils"
13
- import { Button } from "../ui/button"
14
-
15
- // ---------------------------------------------------------------------------
16
- // DataLoadingState
17
- // ---------------------------------------------------------------------------
18
-
19
- interface DataLoadingStateProps extends React.ComponentProps<"div"> {
20
- /** Message displayed below the spinner */
21
- message?: string
22
- }
23
-
24
- function DataLoadingState({
25
- className,
26
- message = "Loading…",
27
- ...props
28
- }: DataLoadingStateProps) {
29
- return (
30
- <div
31
- role="status"
32
- aria-label={message}
33
- data-slot="data-loading-state"
34
- className={cn(
35
- "flex flex-col items-center justify-center gap-3 p-6 text-center",
36
- className
37
- )}
38
- {...props}
39
- >
40
- <Loader2 className="size-6 animate-spin text-muted-foreground" />
41
- {message && (
42
- <p className="text-sm text-muted-foreground">{message}</p>
43
- )}
44
- </div>
45
- )
46
- }
47
-
48
- // ---------------------------------------------------------------------------
49
- // DataEmptyState
50
- // ---------------------------------------------------------------------------
51
-
52
- interface DataEmptyStateProps extends React.ComponentProps<"div"> {
53
- /** Icon rendered above the title */
54
- icon?: React.ReactNode
55
- title?: string
56
- description?: string
57
- /** Optional action rendered below the description */
58
- action?: React.ReactNode
59
- }
60
-
61
- function DataEmptyState({
62
- className,
63
- icon,
64
- title = "No data",
65
- description,
66
- action,
67
- children,
68
- ...props
69
- }: DataEmptyStateProps) {
70
- return (
71
- <div
72
- data-slot="data-empty-state"
73
- className={cn(
74
- "flex flex-col items-center justify-center gap-3 p-6 text-center",
75
- className
76
- )}
77
- {...props}
78
- >
79
- <div className="flex size-10 items-center justify-center rounded-lg bg-muted">
80
- {icon ?? <InboxIcon className="size-5 text-muted-foreground" />}
81
- </div>
82
- {title && (
83
- <h3 className="text-sm font-medium">{title}</h3>
84
- )}
85
- {description && (
86
- <p className="max-w-sm text-sm text-muted-foreground">{description}</p>
87
- )}
88
- {action}
89
- {children}
90
- </div>
91
- )
92
- }
93
-
94
- // ---------------------------------------------------------------------------
95
- // DataErrorState
96
- // ---------------------------------------------------------------------------
97
-
98
- interface DataErrorStateProps extends React.ComponentProps<"div"> {
99
- title?: string
100
- /** Error message or description */
101
- message?: string
102
- /** Callback invoked when the retry button is clicked */
103
- onRetry?: () => void
104
- /** Label for the retry button */
105
- retryLabel?: string
106
- }
107
-
108
- function DataErrorState({
109
- className,
110
- title = "Something went wrong",
111
- message,
112
- onRetry,
113
- retryLabel = "Retry",
114
- children,
115
- ...props
116
- }: DataErrorStateProps) {
117
- return (
118
- <div
119
- role="alert"
120
- data-slot="data-error-state"
121
- className={cn(
122
- "flex flex-col items-center justify-center gap-3 p-6 text-center",
123
- className
124
- )}
125
- {...props}
126
- >
127
- <div className="flex size-10 items-center justify-center rounded-lg bg-destructive/10">
128
- <AlertCircle className="size-5 text-destructive" />
129
- </div>
130
- {title && (
131
- <h3 className="text-sm font-medium">{title}</h3>
132
- )}
133
- {message && (
134
- <p className="max-w-sm text-sm text-muted-foreground">{message}</p>
135
- )}
136
- {onRetry && (
137
- <Button variant="outline" size="sm" onClick={onRetry}>
138
- {retryLabel}
139
- </Button>
140
- )}
141
- {children}
142
- </div>
143
- )
144
- }
145
-
146
- export {
147
- DataLoadingState,
148
- DataEmptyState,
149
- DataErrorState,
150
- type DataLoadingStateProps,
151
- type DataEmptyStateProps,
152
- type DataErrorStateProps,
153
- }