torch-glare 2.4.4 → 2.5.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 (147) hide show
  1. package/apps/lib/components/DataViews/{badgeAdapter.ts → badge.ts} +2 -2
  2. package/apps/lib/components/DataViews/cell.tsx +324 -0
  3. package/apps/lib/components/DataViews/context.ts +144 -0
  4. package/apps/lib/components/DataViews/data-views.tsx +383 -0
  5. package/apps/lib/components/DataViews/filters/children.tsx +98 -0
  6. package/apps/lib/components/DataViews/filters/custom.tsx +34 -0
  7. package/apps/lib/components/DataViews/filters/filters.tsx +163 -0
  8. package/apps/lib/components/DataViews/filters/index.ts +4 -0
  9. package/apps/lib/components/DataViews/filters/labelled.tsx +20 -0
  10. package/apps/lib/components/DataViews/filters/presets.tsx +65 -0
  11. package/apps/lib/components/DataViews/filters/summary.tsx +65 -0
  12. package/apps/lib/components/DataViews/filters/sync.tsx +35 -0
  13. package/apps/lib/components/DataViews/filters/values.ts +173 -0
  14. package/apps/lib/components/DataViews/header.tsx +217 -0
  15. package/apps/lib/components/DataViews/hooks/index.ts +5 -0
  16. package/apps/lib/components/DataViews/hooks/useActiveRow.ts +22 -0
  17. package/apps/lib/components/DataViews/hooks/useControllable.ts +52 -0
  18. package/apps/lib/components/DataViews/index.ts +74 -26
  19. package/apps/lib/components/DataViews/panel/columns.tsx +153 -0
  20. package/apps/lib/components/DataViews/panel/controls.tsx +106 -0
  21. package/apps/lib/components/DataViews/panel/index.ts +3 -0
  22. package/apps/lib/components/DataViews/panel/panel.tsx +164 -0
  23. package/apps/lib/components/DataViews/panel/saved-views.tsx +67 -0
  24. package/apps/lib/components/DataViews/panel/section.tsx +79 -0
  25. package/apps/lib/components/DataViews/panel/sort.tsx +42 -0
  26. package/apps/lib/components/DataViews/panel/tab.tsx +31 -0
  27. package/apps/lib/components/DataViews/slots.ts +63 -0
  28. package/apps/lib/components/DataViews/states.tsx +38 -0
  29. package/apps/lib/components/DataViews/types.ts +485 -178
  30. package/apps/lib/components/DataViews/views/board-view.tsx +379 -0
  31. package/apps/lib/components/DataViews/views/card-rows.tsx +36 -0
  32. package/apps/lib/components/DataViews/views/inbox-view.tsx +257 -0
  33. package/apps/lib/components/DataViews/views/pane-views.tsx +192 -0
  34. package/apps/lib/components/DataViews/views/table-view.tsx +426 -0
  35. package/apps/lib/components/DataViews/views/tree-view.tsx +365 -0
  36. package/apps/lib/components/FormBuilder/context.ts +20 -6
  37. package/apps/lib/components/FormBuilder/field-kind.ts +28 -0
  38. package/apps/lib/components/FormBuilder/fields/DateField.tsx +3 -3
  39. package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +7 -6
  40. package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +30 -4
  41. package/apps/lib/components/FormBuilder/fields/SelectField.tsx +7 -7
  42. package/apps/lib/components/FormBuilder/fields/TableField.tsx +80 -52
  43. package/apps/lib/components/FormBuilder/fields/TextField.tsx +9 -9
  44. package/apps/lib/components/FormBuilder/form-builder.tsx +66 -6
  45. package/apps/lib/components/FormBuilder/index.ts +3 -1
  46. package/apps/lib/components/FormBuilder/types.ts +40 -0
  47. package/apps/lib/components/Input.tsx +3 -0
  48. package/apps/lib/components/SearchableTable.tsx +5 -4
  49. package/apps/lib/components/SectionBlock.tsx +58 -11
  50. package/apps/lib/components/Select.tsx +3 -1
  51. package/apps/lib/components/TabSwitch.tsx +16 -4
  52. package/apps/lib/components/Table.tsx +265 -67
  53. package/apps/lib/components/TreeFolder/TreeFolder.tsx +6 -3
  54. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +16 -14
  55. package/apps/lib/components/TreeFolder/index.ts +1 -1
  56. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +70 -207
  57. package/apps/lib/hooks/useDragDrop.tsx +365 -0
  58. package/apps/lib/hooks/useInfiniteScroll.ts +108 -0
  59. package/apps/lib/registry.json +159 -4
  60. package/apps/lib/tsconfig.tsbuildinfo +1 -1
  61. package/apps/lib/utils/dataViews/path.ts +67 -0
  62. package/apps/lib/utils/dataViews/query.ts +73 -0
  63. package/apps/lib/utils/dataViews/types.ts +187 -0
  64. package/docs/components/breadcrumb.md +1 -1
  65. package/docs/components/button-group.md +1 -1
  66. package/docs/components/button.md +1 -1
  67. package/docs/components/card.md +1 -1
  68. package/docs/components/checkbox.md +1 -1
  69. package/docs/components/data-views/backend-response.md +324 -0
  70. package/docs/components/data-views/examples/a11y-rtl.md +250 -0
  71. package/docs/components/data-views/examples/api-orders-route.md +130 -0
  72. package/docs/components/data-views/examples/fields.md +362 -0
  73. package/docs/components/data-views/examples/filters.md +308 -0
  74. package/docs/components/data-views/examples/inbox-routing.md +218 -0
  75. package/docs/components/data-views/examples/index.md +29 -0
  76. package/docs/components/data-views/examples/overview.md +244 -0
  77. package/docs/components/data-views/examples/panel.md +212 -0
  78. package/docs/components/data-views/examples/scale.md +231 -0
  79. package/docs/components/data-views/examples/server-side.md +210 -0
  80. package/docs/components/data-views/examples/state.md +250 -0
  81. package/docs/components/data-views/examples/tree-custom.md +388 -0
  82. package/docs/components/data-views/examples/view-registry.md +313 -0
  83. package/docs/components/data-views/examples/views.md +534 -0
  84. package/docs/components/data-views/guide.md +405 -0
  85. package/docs/components/data-views/index.md +1504 -0
  86. package/docs/components/data-views/migration.md +79 -0
  87. package/docs/components/date-picker.md +0 -1
  88. package/docs/components/form-builder.md +19 -8
  89. package/docs/components/form-renderer.md +2 -1
  90. package/docs/components/form.md +1 -1
  91. package/docs/components/input-field.md +1 -1
  92. package/docs/components/input-otp.md +1 -1
  93. package/docs/components/input.md +1 -1
  94. package/docs/components/labeled-check-box.md +1 -1
  95. package/docs/components/labeled-radio.md +1 -1
  96. package/docs/components/radio-card.md +1 -1
  97. package/docs/components/radio.md +1 -1
  98. package/docs/components/search-field.md +1 -1
  99. package/docs/components/section-block.md +79 -3
  100. package/docs/components/select.md +1 -1
  101. package/docs/components/simple-select.md +1 -1
  102. package/docs/components/switch.md +1 -1
  103. package/docs/components/tab-switch.md +1 -1
  104. package/docs/components/table.md +45 -8
  105. package/docs/components/text-editor.md +1 -1
  106. package/docs/components/textarea.md +1 -1
  107. package/docs/components/toggle-button.md +1 -1
  108. package/docs/components/toggle.md +1 -1
  109. package/docs/components/tree-folder.md +110 -0
  110. package/docs/how-to/forms-with-form-builder.md +6 -4
  111. package/docs/reference/components.md +16 -6
  112. package/docs/tutorials/component-composition.md +11 -13
  113. package/package.json +3 -2
  114. package/apps/lib/components/DataViews/DataViewRadio.tsx +0 -49
  115. package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +0 -393
  116. package/apps/lib/components/DataViews/DataViewsHeader.tsx +0 -207
  117. package/apps/lib/components/DataViews/DataViewsLayout.tsx +0 -332
  118. package/apps/lib/components/DataViews/FilterPanel.tsx +0 -493
  119. package/apps/lib/components/DataViews/HeaderSearch.tsx +0 -93
  120. package/apps/lib/components/DataViews/InboxView.tsx +0 -463
  121. package/apps/lib/components/DataViews/InboxViewCard.tsx +0 -127
  122. package/apps/lib/components/DataViews/KanbanView.tsx +0 -336
  123. package/apps/lib/components/DataViews/PanelControls.tsx +0 -39
  124. package/apps/lib/components/DataViews/SettingsPanel.tsx +0 -279
  125. package/apps/lib/components/DataViews/TableView.tsx +0 -212
  126. package/apps/lib/components/DataViews/TreeView.tsx +0 -364
  127. package/apps/lib/components/DataViews/fieldRenderers.tsx +0 -299
  128. package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +0 -87
  129. package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +0 -120
  130. package/apps/lib/components/DataViews/filters/PresetChips.tsx +0 -45
  131. package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +0 -165
  132. package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +0 -50
  133. package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +0 -74
  134. package/apps/lib/hooks/useDataViewsState.ts +0 -175
  135. package/apps/lib/utils/dataViews/columnUtils.ts +0 -132
  136. package/apps/lib/utils/dataViews/fieldUtils.ts +0 -197
  137. package/apps/lib/utils/dataViews/nestedDataUtils.tsx +0 -371
  138. package/apps/lib/utils/dataViews/pathUtils.ts +0 -139
  139. package/apps/lib/utils/dataViews/rangeUtils.ts +0 -234
  140. package/apps/lib/utils/dataViews/treeUtils.ts +0 -396
  141. package/docs/components/data-views-config-panel.md +0 -208
  142. package/docs/components/data-views-layout.md +0 -291
  143. package/docs/components/inbox-view.md +0 -170
  144. package/docs/components/kanban-view.md +0 -135
  145. package/docs/components/table-view.md +0 -141
  146. package/docs/components/tree-view.md +0 -147
  147. package/docs/how-to/data-views-from-backend-response.md +0 -194
@@ -1,332 +0,0 @@
1
- "use client";
2
-
3
- import {
4
- forwardRef,
5
- useCallback,
6
- useEffect,
7
- useMemo,
8
- useRef,
9
- useState,
10
- type ElementType,
11
- type ReactNode,
12
- } from "react";
13
- import { List, LayoutGrid, Inbox as InboxIcon, Network } from "lucide-react";
14
- import type {
15
- DynamicRecord,
16
- DynamicColumnConfig,
17
- DynamicFilterConfig,
18
- FilterState,
19
- FieldConfig,
20
- InboxConfig,
21
- TreeConfig,
22
- ViewConfig,
23
- ViewType,
24
- ViewVisibility,
25
- } from "./types";
26
- import { TableView } from "./TableView";
27
- import { KanbanView } from "./KanbanView";
28
- import { InboxView } from "./InboxView";
29
- import { TreeView } from "./TreeView";
30
- import { DataViewsHeader, type DataViewsHeaderView } from "./DataViewsHeader";
31
- import { DataViewsConfigPanel } from "./DataViewsConfigPanel";
32
- import { useDataViewsState } from "../../hooks/useDataViewsState";
33
- import { cn } from "../../utils/cn";
34
- import type { Themes } from "../../utils/types";
35
-
36
- export type DataViewsLayoutProps = {
37
- data?: DynamicRecord[];
38
- config?: Partial<ViewConfig>;
39
- title?: string;
40
- description?: string;
41
-
42
- fields?: FieldConfig[];
43
- inboxConfig?: InboxConfig;
44
- treeConfig?: TreeConfig;
45
- kanbanGroupBy?: string;
46
- kanbanTitleField?: string;
47
- onKanbanColumnAction?: (columnId: string) => void;
48
-
49
- views?: ViewVisibility;
50
-
51
- columns?: Partial<DynamicColumnConfig>[];
52
- filters?: DynamicFilterConfig[];
53
-
54
- filterState?: FilterState;
55
- onFilterChange?: (filters: FilterState) => void;
56
-
57
- showFilters?: boolean;
58
- showSettings?: boolean;
59
- showTitle?: boolean;
60
-
61
- onAddNew?: () => void;
62
- addNewLabel?: string;
63
-
64
- inboxItemHref?: (item: DynamicRecord, id: unknown) => string;
65
- /**
66
- * Component used to render inbox item links when `inboxItemHref` is set.
67
- * Defaults to a plain `<a>` (full-page navigation). Pass your router's link
68
- * (e.g. Next.js `Link`, React Router `Link`) for client-side navigation.
69
- */
70
- inboxLinkComponent?: ElementType;
71
- inboxSelectedId?: unknown;
72
- inboxRenderDetail?: (item: DynamicRecord | null) => ReactNode;
73
-
74
- searchValue?: string;
75
- onSearchChange?: (value: string) => void;
76
- searchPlaceholder?: string;
77
-
78
- className?: string;
79
- theme?: Themes;
80
- };
81
-
82
- const VIEW_META: Record<ViewType, { label: string; icon: DataViewsHeaderView["icon"] }> = {
83
- table: { label: "List", icon: <List /> },
84
- kanban: { label: "Board", icon: <LayoutGrid /> },
85
- inbox: { label: "Inbox", icon: <InboxIcon /> },
86
- tree: { label: "Tree", icon: <Network /> },
87
- };
88
-
89
- const VIEW_ORDER: ViewType[] = ["table", "kanban", "inbox", "tree"];
90
-
91
- export const DataViewsLayout = forwardRef<HTMLDivElement, DataViewsLayoutProps>(
92
- function DataViewsLayout(props, ref) {
93
- const {
94
- title = "Data Views",
95
- data,
96
- config: initialConfig,
97
- fields,
98
- inboxConfig,
99
- treeConfig,
100
- kanbanGroupBy,
101
- kanbanTitleField,
102
- onKanbanColumnAction,
103
- views,
104
- columns,
105
- filters,
106
- filterState: externalFilterState,
107
- onFilterChange,
108
- // `showFilters` is retained on the public API but filters now live in the
109
- // right-side config rail rather than an inline per-view panel.
110
- showSettings = true,
111
- showTitle = true,
112
- onAddNew,
113
- addNewLabel,
114
- inboxItemHref,
115
- inboxLinkComponent,
116
- inboxSelectedId,
117
- inboxRenderDetail,
118
- searchValue,
119
- onSearchChange,
120
- searchPlaceholder,
121
- className,
122
- theme,
123
- } = props;
124
-
125
- const {
126
- items,
127
- flatItems,
128
- resolvedFields,
129
- detectedColumns,
130
- config,
131
- setConfig,
132
- currentView,
133
- setCurrentView,
134
- filterState,
135
- setFilterState,
136
- onDataUpdate,
137
- enabledViews,
138
- } = useDataViewsState({
139
- data,
140
- fields,
141
- columns,
142
- config: initialConfig,
143
- treeConfig,
144
- views,
145
- filterState: externalFilterState,
146
- onFilterChange,
147
- });
148
-
149
- // `panelOpen` drives intent; `panelMounted` keeps the panel in the tree
150
- // through the close animation before unmounting.
151
- const [panelOpen, setPanelOpen] = useState(false);
152
- const [panelMounted, setPanelMounted] = useState(false);
153
- const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
154
-
155
- const openPanel = useCallback(() => {
156
- if (closeTimer.current) {
157
- clearTimeout(closeTimer.current);
158
- closeTimer.current = null;
159
- }
160
- // Mount at width 0 first, then flip to open on the next frame so the
161
- // width transition animates from 0 → 260px instead of snapping.
162
- setPanelMounted(true);
163
- requestAnimationFrame(() => requestAnimationFrame(() => setPanelOpen(true)));
164
- }, []);
165
-
166
- const closePanel = useCallback(() => {
167
- setPanelOpen(false);
168
- if (closeTimer.current) clearTimeout(closeTimer.current);
169
- // Keep mounted through the width/fade animation (300ms) before unmounting.
170
- closeTimer.current = setTimeout(() => setPanelMounted(false), 300);
171
- }, []);
172
-
173
- const togglePanel = useCallback(() => {
174
- if (panelOpen) closePanel();
175
- else openPanel();
176
- }, [panelOpen, openPanel, closePanel]);
177
-
178
- useEffect(() => {
179
- return () => {
180
- if (closeTimer.current) clearTimeout(closeTimer.current);
181
- };
182
- }, []);
183
-
184
- const effectiveKanbanGroupBy = kanbanGroupBy ?? config.kanbanGroupBy;
185
- // Filters now live in the right-side rail, not as an inline per-view panel.
186
- const effectiveConfig: ViewConfig = { ...config, showFilters: false };
187
-
188
- const headerViews = useMemo<DataViewsHeaderView[]>(
189
- () =>
190
- VIEW_ORDER.filter((v) => enabledViews[v]).map((v) => ({
191
- id: v,
192
- label: VIEW_META[v].label,
193
- icon: VIEW_META[v].icon,
194
- })),
195
- [enabledViews],
196
- );
197
-
198
- return (
199
- <div
200
- ref={ref}
201
- data-theme={theme}
202
- className={cn(
203
- // Shell is always black (matches Figma): the dark header and config
204
- // rail sit on it; the Master Container is the white surface inside.
205
- // `overflow-hidden` traps any child overflow — without it, a tall
206
- // config-panel body escapes and creates a page-level scrollbar in
207
- // addition to the panel's own.
208
- "flex h-screen gap-2 overflow-hidden bg-black text-content-presentation-global-primary",
209
- className,
210
- )}
211
- >
212
- {/* Left column: header + content. Shrinks as the panel expands. */}
213
- <div className="flex min-w-0 flex-1 flex-col gap-2">
214
- {showTitle && (
215
- <DataViewsHeader
216
- title={title}
217
- views={headerViews}
218
- currentView={currentView}
219
- onViewChange={setCurrentView}
220
- showSettings={showSettings}
221
- settingsOpen={panelOpen}
222
- onToggleSettings={togglePanel}
223
- onAddNew={onAddNew}
224
- addNewLabel={addNewLabel}
225
- searchValue={searchValue}
226
- onSearchChange={onSearchChange}
227
- searchPlaceholder={searchPlaceholder}
228
- />
229
- )}
230
-
231
- <main className="flex min-h-0 flex-1 overflow-hidden ">
232
- {/* Master Container — white card, 16px radius, #D4D4D4 hairline
233
- border. Fixed surface (matches header chrome). */}
234
- <div className="flex flex-1 overflow-hidden rounded-[16px]">
235
- {/* Clip the scrollable surface to the parent radius MINUS the 1px
236
- border (16 − 1 = 15px). Using the full 16px here let the
237
- opaque view background sit flush with the parent's outer edge
238
- and bleed past the border as a ~1px light line on the
239
- left/right straight sides. */}
240
- <div className="flex-1 overflow-auto rounded-[15px]">
241
- {currentView === "table" && enabledViews.table && (
242
- <TableView
243
- data={flatItems}
244
- columns={detectedColumns}
245
- fields={resolvedFields}
246
- config={effectiveConfig}
247
- onDataUpdate={onDataUpdate}
248
- onSortChange={(sortBy, sortOrder) => setConfig({ sortBy, sortOrder })}
249
- filters={filters}
250
- filterState={filterState}
251
- onFilterChange={setFilterState}
252
- showFilters={false}
253
- />
254
- )}
255
- {currentView === "kanban" && enabledViews.kanban && (
256
- <KanbanView
257
- data={flatItems}
258
- columns={detectedColumns}
259
- fields={resolvedFields}
260
- config={effectiveConfig}
261
- onDataUpdate={onDataUpdate}
262
- groupByField={effectiveKanbanGroupBy}
263
- titleField={kanbanTitleField}
264
- onColumnAction={onKanbanColumnAction}
265
- />
266
- )}
267
- {currentView === "inbox" && enabledViews.inbox && (
268
- <InboxView
269
- data={flatItems}
270
- columns={detectedColumns}
271
- fields={resolvedFields}
272
- inboxConfig={inboxConfig}
273
- config={effectiveConfig}
274
- onDataUpdate={onDataUpdate}
275
- filters={filters}
276
- filterState={filterState}
277
- onFilterChange={setFilterState}
278
- showFilters={false}
279
- itemHref={inboxItemHref}
280
- linkComponent={inboxLinkComponent}
281
- selectedItemId={inboxSelectedId}
282
- renderDetail={inboxRenderDetail}
283
- />
284
- )}
285
- {currentView === "tree" && enabledViews.tree && (
286
- <TreeView
287
- data={items}
288
- columns={detectedColumns}
289
- fields={resolvedFields}
290
- treeConfig={treeConfig}
291
- config={effectiveConfig}
292
- onDataUpdate={onDataUpdate}
293
- filters={filters}
294
- filterState={filterState}
295
- onFilterChange={setFilterState}
296
- showFilters={false}
297
- />
298
- )}
299
- </div>
300
- </div>
301
- </main>
302
- </div>
303
-
304
- {/* Right rail: full-height sibling of the [header + content] column, so
305
- opening it pushes the header as well as the content. The wrapper
306
- animates its width so the left column reflows in sync with the
307
- panel's slide-in. */}
308
- {showSettings && panelMounted && (
309
- <div
310
- className={cn(
311
- "shrink-0 overflow-hidden transition-[width] duration-300 ease-in-out",
312
- panelOpen ? "w-[260px]" : "w-0",
313
- )}
314
- >
315
- <DataViewsConfigPanel
316
- state={panelOpen ? "open" : "closed"}
317
- config={config}
318
- onConfigChange={setConfig}
319
- onClose={closePanel}
320
- currentView={currentView}
321
- fields={resolvedFields}
322
- data={flatItems}
323
- filterState={filterState}
324
- onFilterChange={setFilterState}
325
- filterConfig={filters}
326
- />
327
- </div>
328
- )}
329
- </div>
330
- );
331
- },
332
- );