torch-glare 2.5.1 → 2.5.3
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.
- package/apps/lib/components/DataViews/data-views.tsx +1 -1
- package/apps/lib/components/DataViews/filters/filters.tsx +8 -12
- package/apps/lib/components/DataViews/header.tsx +5 -2
- package/apps/lib/components/DataViews/panel/section.tsx +3 -1
- package/apps/lib/components/DataViews/views/board-view.tsx +3 -1
- package/apps/lib/components/DataViews/views/inbox-view.tsx +4 -1
- package/apps/lib/components/DataViews/views/pane-views.tsx +5 -1
- package/apps/lib/components/DataViews/views/table-view.tsx +34 -4
- package/apps/lib/components/DataViews/views/tree-view.tsx +5 -3
- package/apps/lib/components/FormBuilder/context.ts +17 -26
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +1 -1
- package/apps/lib/components/FormBuilder/form-builder.tsx +32 -172
- package/apps/lib/components/FormBuilder/index.ts +0 -4
- package/apps/lib/components/FormBuilder/submit.tsx +11 -2
- package/apps/lib/components/FormBuilder/types.ts +10 -16
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +2 -2
- package/apps/lib/components/FormRenderer/detail.tsx +6 -6
- package/apps/lib/components/FormRenderer/form-renderer.tsx +167 -35
- package/apps/lib/components/{FormBuilder → FormRenderer}/header.tsx +12 -25
- package/apps/lib/components/FormRenderer/index.ts +4 -0
- package/apps/lib/components/FormRenderer/section.tsx +39 -0
- package/apps/lib/components/{FormBuilder → FormRenderer}/stepper.tsx +65 -22
- package/apps/lib/components/FormRenderer/types.ts +7 -7
- package/apps/lib/components/SectionBlock.tsx +11 -1
- package/apps/lib/components/Table.tsx +54 -29
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +61 -61
- package/apps/lib/registry.json +5 -3
- package/apps/lib/tsconfig.tsbuildinfo +1 -1
- package/docs/components/data-views/index.md +7 -0
- package/docs/components/form-builder.md +65 -89
- package/docs/components/form-renderer.md +62 -26
- package/docs/components/form-summary.md +18 -3
- package/docs/components/section-block.md +1 -1
- package/docs/components/table.md +33 -0
- package/docs/how-to/forms-with-form-builder.md +47 -42
- package/docs/migration/changelog.md +3 -0
- package/docs/migration/form-builder-2.5.2.md +113 -0
- package/package.json +1 -1
|
@@ -18,6 +18,20 @@ const Table = React.forwardRef<
|
|
|
18
18
|
<table
|
|
19
19
|
data-theme={theme}
|
|
20
20
|
ref={ref}
|
|
21
|
+
// `overflow-hidden` is the default, and it is load-bearing twice over: the table is `w-auto`,
|
|
22
|
+
// so one wider than its container would otherwise push the whole page wide and put a horizontal
|
|
23
|
+
// scrollbar on the layout; and callers that give the table a radius rely on it to clip the
|
|
24
|
+
// square header band out of the rounded corners.
|
|
25
|
+
//
|
|
26
|
+
// The cost is that it makes the table its own scroll container, and `TableHeader`'s `sticky`
|
|
27
|
+
// resolves against the *nearest* scrollport — so inside a clipping table the header pins to a
|
|
28
|
+
// box that never scrolls, i.e. does nothing. That is the right default: a header only benefits
|
|
29
|
+
// from sticking when the table sits in a scroller, and such a caller passes `overflow-visible`
|
|
30
|
+
// (tailwind-merge lets theirs win) to bind it to that scroller instead. Only do that where the
|
|
31
|
+
// scroller is `min-w-0`, or the width problem above comes back — `DataViews`' table view is the
|
|
32
|
+
// worked example.
|
|
33
|
+
//
|
|
34
|
+
// `[border-collapse:separate]` is what lets the header cells keep their borders while stuck.
|
|
21
35
|
className={cn("overflow-hidden w-auto [border-collapse:separate] border-spacing-0", className)}
|
|
22
36
|
{...props}
|
|
23
37
|
>
|
|
@@ -34,9 +48,20 @@ const TableHeader = React.forwardRef<
|
|
|
34
48
|
ref={ref}
|
|
35
49
|
// The header band is one continuous bar, not a per-cell background — a background on each
|
|
36
50
|
// `<th>` would paint over the half of the previous column's resize handle that overhangs
|
|
37
|
-
// the boundary.
|
|
51
|
+
// the boundary. That is also why `sticky` sits here rather than on the `<th>`s: per-cell
|
|
52
|
+
// sticky would leave this background behind and let rows show through it.
|
|
53
|
+
//
|
|
54
|
+
// `z-20` clears the `z-10` on the resize handle and sort button inside the cells. In a table
|
|
55
|
+
// that never scrolls vertically, `sticky` keeps the element in flow and changes nothing.
|
|
56
|
+
//
|
|
57
|
+
// The band's token is translucent (`#0003`), so once rows do slide under it they read through.
|
|
58
|
+
// Making it opaque is deliberately NOT done here: it would mean naming one surface colour, and
|
|
59
|
+
// this header paints over whatever its caller sits on — forcing a surface would visibly recolour
|
|
60
|
+
// every table not on that one. A caller whose table actually scrolls supplies the opaque
|
|
61
|
+
// background itself, where the surface is known; `DataViews`' table view is the worked example.
|
|
38
62
|
className={cn(
|
|
39
63
|
"bg-background-presentation-form-header backdrop-blur-[8px]",
|
|
64
|
+
"sticky top-0 z-20",
|
|
40
65
|
"shadow-[0px_4px_8px_0px_rgba(0,0,0,0.15)]",
|
|
41
66
|
className,
|
|
42
67
|
)}
|
|
@@ -108,28 +133,28 @@ const MIN_COLUMN_WIDTH = 40;
|
|
|
108
133
|
const TableHead = React.forwardRef<
|
|
109
134
|
HTMLTableCellElement,
|
|
110
135
|
React.ThHTMLAttributes<HTMLTableCellElement> &
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
TableHeadVariantsProps &
|
|
137
|
+
React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
138
|
+
sortType?: "asc" | "desc" | undefined;
|
|
139
|
+
onSort?: () => void;
|
|
140
|
+
/** Column name for the sort button's accessible label. */
|
|
141
|
+
sortLabel?: string;
|
|
142
|
+
/**
|
|
143
|
+
* Called with the new width (px) while the column is being drag-resized. Pass it to take
|
|
144
|
+
* **control** of the width — the header then renders `style.width` and expects you to
|
|
145
|
+
* feed the new value back. Required whenever the table needs a definite width
|
|
146
|
+
* (`table-layout: fixed`), because only the owner of every column width can total them.
|
|
147
|
+
* Omit for uncontrolled resizing, where the header keeps the width itself.
|
|
148
|
+
*/
|
|
149
|
+
onResize?: (width: number) => void;
|
|
150
|
+
/**
|
|
151
|
+
* Classes for the inner layout box (the flex row holding the label and sort toggle).
|
|
152
|
+
* `className` and every other prop go to the `<th>` — reach for this only when you need
|
|
153
|
+
* to restyle the content box itself, e.g. its typography or colour.
|
|
154
|
+
*/
|
|
155
|
+
contentClassName?: string;
|
|
156
|
+
isDummy?: boolean;
|
|
157
|
+
}
|
|
133
158
|
>(
|
|
134
159
|
(
|
|
135
160
|
{
|
|
@@ -287,11 +312,11 @@ const TableCell = React.forwardRef<
|
|
|
287
312
|
// Never fade a dummy cell — its content is a centred checkbox or drag handle, not
|
|
288
313
|
// clippable text.
|
|
289
314
|
fade &&
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
315
|
+
!isDummy && [
|
|
316
|
+
"[mask-image:linear-gradient(to_right,black_0%,black_0%,black_75%,transparent_100%)]",
|
|
317
|
+
"rtl:[mask-image:linear-gradient(to_left,black_0%,black_0%,black_75%,transparent_100%)]",
|
|
318
|
+
"[&:has(input)]:[mask-image:none]",
|
|
319
|
+
],
|
|
295
320
|
{ "min-w-fit justify-center": isDummy },
|
|
296
321
|
childrenClassName,
|
|
297
322
|
)}
|
|
@@ -307,7 +332,7 @@ const TableCheckbox = React.forwardRef<
|
|
|
307
332
|
React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
308
333
|
id: string;
|
|
309
334
|
}
|
|
310
|
-
|
|
335
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- id destructured to exclude it from the props spread onto Checkbox
|
|
311
336
|
>(({ className, id, ...props }, ref) => {
|
|
312
337
|
return (
|
|
313
338
|
<div className={cn(["flex items-center justify-center"], className)}>
|
|
@@ -311,68 +311,68 @@ export const TreeFolder = forwardRef<TreeFolderHandle, TreeFolderProps>(
|
|
|
311
311
|
|
|
312
312
|
<TreeFolderStyles />
|
|
313
313
|
<DndContext {...contextProps}>
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
314
|
+
<div ref={scrollRef} role="tree" className="tf-scroll flex-1 min-h-0 overflow-auto pt-[6px]">
|
|
315
|
+
{isEmpty ? (
|
|
316
|
+
(emptyState ?? (
|
|
317
|
+
<div className="text-xs text-content-presentation-global-tertiary p-3">
|
|
318
|
+
Nothing here yet.
|
|
319
|
+
</div>
|
|
320
|
+
))
|
|
321
|
+
) : (
|
|
322
|
+
<div className="min-w-max" style={stripStyle}>
|
|
323
|
+
<DragList ids={ids} makeRoom={false}>
|
|
324
|
+
{visibleRows.map((row, idx) => {
|
|
325
|
+
const prevRow = visibleRows[idx - 1];
|
|
326
|
+
const nextRow = visibleRows[idx + 1];
|
|
327
|
+
const isSelected = selectedId === row.node.id;
|
|
328
|
+
const isDescendant = isDescendantOfSelected(row.node.id) && !isSelected;
|
|
329
|
+
const inBand = isSelected || isDescendant;
|
|
330
|
+
|
|
331
|
+
// Neighbour-aware band rounding: a row is "in-band" if it's the selected
|
|
332
|
+
// node itself or one of its descendants. The Set lookup handles deep nesting.
|
|
333
|
+
const prevInBand =
|
|
334
|
+
inBand &&
|
|
335
|
+
!!prevRow &&
|
|
336
|
+
(prevRow.node.id === selectedId || descendantIdSet.has(prevRow.node.id));
|
|
337
|
+
const nextInBand =
|
|
338
|
+
inBand &&
|
|
339
|
+
!!nextRow &&
|
|
340
|
+
(nextRow.node.id === selectedId || descendantIdSet.has(nextRow.node.id));
|
|
341
|
+
|
|
342
|
+
const isDragging = dragIdSet.has(row.node.id);
|
|
343
|
+
const isDropTargetInside =
|
|
344
|
+
dropTarget?.rowId === row.node.id && dropTarget.position === "inside";
|
|
345
|
+
const isDropBefore =
|
|
346
|
+
dropTarget?.rowId === row.node.id && dropTarget.position === "before";
|
|
347
|
+
const isDropAfter =
|
|
348
|
+
dropTarget?.rowId === row.node.id && dropTarget.position === "after";
|
|
349
|
+
|
|
350
|
+
return (
|
|
351
|
+
<TreeFolderRow
|
|
352
|
+
key={row.node.id}
|
|
353
|
+
row={row}
|
|
354
|
+
rowHeight={rowHeight}
|
|
355
|
+
indent={indent}
|
|
356
|
+
iconFor={iconFor}
|
|
357
|
+
isSelected={isSelected}
|
|
358
|
+
isAncestor={isAncestorFn(row.node.id) && !isSelected}
|
|
359
|
+
isDescendantOfSelected={isDescendant}
|
|
360
|
+
isPrevInBand={prevInBand}
|
|
361
|
+
isNextInBand={nextInBand}
|
|
362
|
+
isDragging={isDragging}
|
|
363
|
+
isDropTargetInside={isDropTargetInside}
|
|
364
|
+
isDropBefore={isDropBefore}
|
|
365
|
+
isDropAfter={isDropAfter}
|
|
366
|
+
dndEnabled={dndEnabled}
|
|
367
|
+
onSelect={handleSelect}
|
|
368
|
+
onToggle={handleToggle}
|
|
369
|
+
/>
|
|
370
|
+
);
|
|
371
|
+
})}
|
|
372
|
+
</DragList>
|
|
319
373
|
</div>
|
|
320
|
-
)
|
|
321
|
-
|
|
322
|
-
<div className="min-w-max" style={stripStyle}>
|
|
323
|
-
<DragList ids={ids} makeRoom={false}>
|
|
324
|
-
{visibleRows.map((row, idx) => {
|
|
325
|
-
const prevRow = visibleRows[idx - 1];
|
|
326
|
-
const nextRow = visibleRows[idx + 1];
|
|
327
|
-
const isSelected = selectedId === row.node.id;
|
|
328
|
-
const isDescendant = isDescendantOfSelected(row.node.id) && !isSelected;
|
|
329
|
-
const inBand = isSelected || isDescendant;
|
|
330
|
-
|
|
331
|
-
// Neighbour-aware band rounding: a row is "in-band" if it's the selected
|
|
332
|
-
// node itself or one of its descendants. The Set lookup handles deep nesting.
|
|
333
|
-
const prevInBand =
|
|
334
|
-
inBand &&
|
|
335
|
-
!!prevRow &&
|
|
336
|
-
(prevRow.node.id === selectedId || descendantIdSet.has(prevRow.node.id));
|
|
337
|
-
const nextInBand =
|
|
338
|
-
inBand &&
|
|
339
|
-
!!nextRow &&
|
|
340
|
-
(nextRow.node.id === selectedId || descendantIdSet.has(nextRow.node.id));
|
|
341
|
-
|
|
342
|
-
const isDragging = dragIdSet.has(row.node.id);
|
|
343
|
-
const isDropTargetInside =
|
|
344
|
-
dropTarget?.rowId === row.node.id && dropTarget.position === "inside";
|
|
345
|
-
const isDropBefore =
|
|
346
|
-
dropTarget?.rowId === row.node.id && dropTarget.position === "before";
|
|
347
|
-
const isDropAfter =
|
|
348
|
-
dropTarget?.rowId === row.node.id && dropTarget.position === "after";
|
|
349
|
-
|
|
350
|
-
return (
|
|
351
|
-
<TreeFolderRow
|
|
352
|
-
key={row.node.id}
|
|
353
|
-
row={row}
|
|
354
|
-
rowHeight={rowHeight}
|
|
355
|
-
indent={indent}
|
|
356
|
-
iconFor={iconFor}
|
|
357
|
-
isSelected={isSelected}
|
|
358
|
-
isAncestor={isAncestorFn(row.node.id) && !isSelected}
|
|
359
|
-
isDescendantOfSelected={isDescendant}
|
|
360
|
-
isPrevInBand={prevInBand}
|
|
361
|
-
isNextInBand={nextInBand}
|
|
362
|
-
isDragging={isDragging}
|
|
363
|
-
isDropTargetInside={isDropTargetInside}
|
|
364
|
-
isDropBefore={isDropBefore}
|
|
365
|
-
isDropAfter={isDropAfter}
|
|
366
|
-
dndEnabled={dndEnabled}
|
|
367
|
-
onSelect={handleSelect}
|
|
368
|
-
onToggle={handleToggle}
|
|
369
|
-
/>
|
|
370
|
-
);
|
|
371
|
-
})}
|
|
372
|
-
</DragList>
|
|
373
|
-
</div>
|
|
374
|
-
)}
|
|
375
|
-
</div>
|
|
374
|
+
)}
|
|
375
|
+
</div>
|
|
376
376
|
</DndContext>
|
|
377
377
|
</div>
|
|
378
378
|
);
|
package/apps/lib/registry.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.5.
|
|
2
|
+
"version": "2.5.3",
|
|
3
3
|
"generatedBy": "scripts/bin/generateRegistry",
|
|
4
4
|
"npmVersions": {
|
|
5
5
|
"@dnd-kit/core": "^6.3.1",
|
|
@@ -422,8 +422,6 @@
|
|
|
422
422
|
"components/DatePicker",
|
|
423
423
|
"components/FieldHint",
|
|
424
424
|
"components/Form",
|
|
425
|
-
"components/FormStepper",
|
|
426
|
-
"components/HeaderBar",
|
|
427
425
|
"components/ImageAttachment",
|
|
428
426
|
"components/Input",
|
|
429
427
|
"components/InputField",
|
|
@@ -456,8 +454,12 @@
|
|
|
456
454
|
"react-hook-form"
|
|
457
455
|
],
|
|
458
456
|
"registryDependencies": [
|
|
457
|
+
"components/Button",
|
|
459
458
|
"components/Drawer",
|
|
460
459
|
"components/FormBuilder",
|
|
460
|
+
"components/FormStepper",
|
|
461
|
+
"components/HeaderBar",
|
|
462
|
+
"components/SectionBlock",
|
|
461
463
|
"components/TabFormItem",
|
|
462
464
|
"utils/cn"
|
|
463
465
|
]
|