@bsuite/page-builder 1.0.2 → 1.0.4
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/dist/autoHeight.d.ts +34 -0
- package/dist/autoHeight.d.ts.map +1 -1
- package/dist/autoHeight.js +37 -1
- package/dist/usePageGridLayout.d.ts.map +1 -1
- package/dist/usePageGridLayout.js +50 -18
- package/package.json +1 -1
package/dist/autoHeight.d.ts
CHANGED
|
@@ -44,6 +44,40 @@ export interface ComputeAutoHeightRowsOptions {
|
|
|
44
44
|
* time. Ceiling always over-allocates rather than under-allocates, trading
|
|
45
45
|
* a few pixels of empty card padding for a guarantee that content is never
|
|
46
46
|
* cut off.
|
|
47
|
+
*
|
|
48
|
+
* THE MARGIN IS *BETWEEN* ROWS, NOT INSIDE EVERY ROW. This is the correction
|
|
49
|
+
* that this file existed for a month without.
|
|
50
|
+
*
|
|
51
|
+
* react-grid-layout allocates an item of `n` rows exactly:
|
|
52
|
+
*
|
|
53
|
+
* px(n) = n * rowHeight + (n - 1) * marginY
|
|
54
|
+
*
|
|
55
|
+
* so `n` rows are worth `n * (rowHeight + marginY) - marginY` pixels — one
|
|
56
|
+
* margin LESS than the row unit suggests. Dividing the needed height by the
|
|
57
|
+
* bare row unit therefore credits every item with `marginY` pixels it does
|
|
58
|
+
* not get, and `Math.ceil` cannot rescue that: the shortfall is inside the
|
|
59
|
+
* rounding, not beyond it.
|
|
60
|
+
*
|
|
61
|
+
* Inverting the real formula for the smallest `n` that fits:
|
|
62
|
+
*
|
|
63
|
+
* n * rowHeight + (n - 1) * marginY >= needed
|
|
64
|
+
* n >= (needed + marginY) / (rowHeight + marginY)
|
|
65
|
+
*
|
|
66
|
+
* MEASURED ON PRODUCTION, 2026-08-20, crm7 /clients/create at 1366x768. The
|
|
67
|
+
* card holding the form's Create/Cancel row measured 32px tall around a 36px
|
|
68
|
+
* button, with `overflow-hidden`, so the button was cut off and a neighbouring
|
|
69
|
+
* card's helper text was painted over what remained — `elementFromPoint` at the
|
|
70
|
+
* button's centre returned a `<p>`, not the button. The form could not be
|
|
71
|
+
* submitted by a person. rowHeight 32 + marginY 6: 36px of content came to
|
|
72
|
+
* `ceil((36 + 2) / 38) = 1` row, and one row is 32 pixels.
|
|
73
|
+
*
|
|
74
|
+
* The old form clips whenever the needed height lands 1..marginY pixels above a
|
|
75
|
+
* row boundary — 6 of every 38 possible heights, about one card in six.
|
|
76
|
+
*
|
|
77
|
+
* It survived because the tests asserted the ARITHMETIC rather than the
|
|
78
|
+
* OUTCOME: they checked the division, never whether the resulting row count
|
|
79
|
+
* buys enough pixels. Three of them encoded a clipping case as the expected
|
|
80
|
+
* answer. They now assert against react-grid-layout's own formula instead.
|
|
47
81
|
*/
|
|
48
82
|
export declare function computeAutoHeightRows({ contentPx, cardChromePx, rowHeightPx, marginYPx, minRows, }: ComputeAutoHeightRowsOptions): number;
|
|
49
83
|
//# sourceMappingURL=autoHeight.d.ts.map
|
package/dist/autoHeight.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autoHeight.d.ts","sourceRoot":"","sources":["../src/autoHeight.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,4BAA4B;IAC3C;;;;;;;;;;;OAWG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED
|
|
1
|
+
{"version":3,"file":"autoHeight.d.ts","sourceRoot":"","sources":["../src/autoHeight.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,4BAA4B;IAC3C;;;;;;;;;;;OAWG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,YAAY,EACZ,WAAW,EACX,SAAS,EACT,OAAW,GACZ,EAAE,4BAA4B,GAAG,MAAM,CAOvC"}
|
package/dist/autoHeight.js
CHANGED
|
@@ -6,11 +6,47 @@
|
|
|
6
6
|
* time. Ceiling always over-allocates rather than under-allocates, trading
|
|
7
7
|
* a few pixels of empty card padding for a guarantee that content is never
|
|
8
8
|
* cut off.
|
|
9
|
+
*
|
|
10
|
+
* THE MARGIN IS *BETWEEN* ROWS, NOT INSIDE EVERY ROW. This is the correction
|
|
11
|
+
* that this file existed for a month without.
|
|
12
|
+
*
|
|
13
|
+
* react-grid-layout allocates an item of `n` rows exactly:
|
|
14
|
+
*
|
|
15
|
+
* px(n) = n * rowHeight + (n - 1) * marginY
|
|
16
|
+
*
|
|
17
|
+
* so `n` rows are worth `n * (rowHeight + marginY) - marginY` pixels — one
|
|
18
|
+
* margin LESS than the row unit suggests. Dividing the needed height by the
|
|
19
|
+
* bare row unit therefore credits every item with `marginY` pixels it does
|
|
20
|
+
* not get, and `Math.ceil` cannot rescue that: the shortfall is inside the
|
|
21
|
+
* rounding, not beyond it.
|
|
22
|
+
*
|
|
23
|
+
* Inverting the real formula for the smallest `n` that fits:
|
|
24
|
+
*
|
|
25
|
+
* n * rowHeight + (n - 1) * marginY >= needed
|
|
26
|
+
* n >= (needed + marginY) / (rowHeight + marginY)
|
|
27
|
+
*
|
|
28
|
+
* MEASURED ON PRODUCTION, 2026-08-20, crm7 /clients/create at 1366x768. The
|
|
29
|
+
* card holding the form's Create/Cancel row measured 32px tall around a 36px
|
|
30
|
+
* button, with `overflow-hidden`, so the button was cut off and a neighbouring
|
|
31
|
+
* card's helper text was painted over what remained — `elementFromPoint` at the
|
|
32
|
+
* button's centre returned a `<p>`, not the button. The form could not be
|
|
33
|
+
* submitted by a person. rowHeight 32 + marginY 6: 36px of content came to
|
|
34
|
+
* `ceil((36 + 2) / 38) = 1` row, and one row is 32 pixels.
|
|
35
|
+
*
|
|
36
|
+
* The old form clips whenever the needed height lands 1..marginY pixels above a
|
|
37
|
+
* row boundary — 6 of every 38 possible heights, about one card in six.
|
|
38
|
+
*
|
|
39
|
+
* It survived because the tests asserted the ARITHMETIC rather than the
|
|
40
|
+
* OUTCOME: they checked the division, never whether the resulting row count
|
|
41
|
+
* buys enough pixels. Three of them encoded a clipping case as the expected
|
|
42
|
+
* answer. They now assert against react-grid-layout's own formula instead.
|
|
9
43
|
*/
|
|
10
44
|
export function computeAutoHeightRows({ contentPx, cardChromePx, rowHeightPx, marginYPx, minRows = 1, }) {
|
|
11
45
|
const rowUnitPx = rowHeightPx + marginYPx;
|
|
12
46
|
if (rowUnitPx <= 0)
|
|
13
47
|
return minRows;
|
|
14
|
-
|
|
48
|
+
// `+ marginYPx` inverts px(n) = n*rowHeight + (n-1)*marginY. Without it every
|
|
49
|
+
// item is credited with one margin it never receives. See the docblock.
|
|
50
|
+
const raw = Math.ceil((contentPx + cardChromePx + marginYPx) / rowUnitPx);
|
|
15
51
|
return Math.max(minRows, raw);
|
|
16
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePageGridLayout.d.ts","sourceRoot":"","sources":["../src/usePageGridLayout.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAGV,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,0BAA0B,2IAM7B,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,6BAA6B,CAAC;AAElE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAiBzC,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,cAAc,EACd,WAAgB,EAChB,aAAiB,EACjB,WAAkB,EAClB,gBAA6C,EAC7C,iBAA4C,EAC5C,iBAAiB,GAClB,EAAE,wBAAwB,GAAG,uBAAuB,
|
|
1
|
+
{"version":3,"file":"usePageGridLayout.d.ts","sourceRoot":"","sources":["../src/usePageGridLayout.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAGV,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,0BAA0B,2IAM7B,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,6BAA6B,CAAC;AAElE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAiBzC,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,cAAc,EACd,WAAgB,EAChB,aAAiB,EACjB,WAAkB,EAClB,gBAA6C,EAC7C,iBAA4C,EAC5C,iBAAiB,GAClB,EAAE,wBAAwB,GAAG,uBAAuB,CA4pBpD"}
|
|
@@ -184,13 +184,24 @@ export function usePageGridLayout({ pageKey, defaultLayouts, defaultCols = 12, l
|
|
|
184
184
|
}
|
|
185
185
|
return resolved;
|
|
186
186
|
}, [rawLayouts, baseCols, layoutCols, defaultAutoHeight]);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
187
|
+
/*
|
|
188
|
+
* THERE IS DELIBERATELY NO EFFECT HERE.
|
|
189
|
+
*
|
|
190
|
+
* This used to rescale the stored layout to the new column count and write it
|
|
191
|
+
* back, which made a column change DESTRUCTIVE and unrecoverable. Measured on
|
|
192
|
+
* `rescaleLayout` directly: an 11 -> 2 -> 11 round trip takes
|
|
193
|
+
*
|
|
194
|
+
* a(w4 @x0) b(w3 @x4) c(w4 @x7) / d(w6 @x0) e(w5 @x6)
|
|
195
|
+
*
|
|
196
|
+
* to five items of w6 stacked one per row at x0. Everything narrows to the
|
|
197
|
+
* one-column minimum on the way down, the row-packer puts one item per row,
|
|
198
|
+
* and coming back up cannot recover an arrangement that no longer exists.
|
|
199
|
+
* That is what flattened the operator's dashboard.
|
|
200
|
+
*
|
|
201
|
+
* `currentLayouts` above already derives the DISPLAY at `layoutCols` from the
|
|
202
|
+
* authored layout at `baseCols`. Leaving storage alone makes the column
|
|
203
|
+
* control a view, and the round trip exact.
|
|
204
|
+
*/
|
|
194
205
|
const activeCols = useMemo(() => ({ lg: layoutCols, md: layoutCols, sm: layoutCols, xs: layoutCols, xxs: layoutCols }), [layoutCols]);
|
|
195
206
|
/**
|
|
196
207
|
* The compactor handed to react-grid-layout — the SAME one in edit mode and
|
|
@@ -413,12 +424,22 @@ export function usePageGridLayout({ pageKey, defaultLayouts, defaultCols = 12, l
|
|
|
413
424
|
}
|
|
414
425
|
return next;
|
|
415
426
|
}, []);
|
|
427
|
+
/**
|
|
428
|
+
* Persist a layout the USER authored, and re-base the column count to the one
|
|
429
|
+
* they authored it at.
|
|
430
|
+
*
|
|
431
|
+
* Re-basing belongs here and ONLY here. A column-count change is a view
|
|
432
|
+
* operation and must not touch storage — see `handleColumnChange`. An edit is
|
|
433
|
+
* the one moment the stored arrangement and the stored column count are known
|
|
434
|
+
* to agree, so it is the one moment `baseCols` may move.
|
|
435
|
+
*/
|
|
416
436
|
const commitLayout = useCallback((layouts) => {
|
|
417
437
|
const canonical = canonicaliseLayoutForPersist(layouts);
|
|
418
438
|
if (!canonical)
|
|
419
439
|
return;
|
|
420
440
|
setSavedLayout(stripAutoHeightRows(canonical));
|
|
421
|
-
|
|
441
|
+
setBaseCols(layoutCols);
|
|
442
|
+
}, [canonicaliseLayoutForPersist, layoutCols, setBaseCols, setSavedLayout, stripAutoHeightRows]);
|
|
422
443
|
const onLayoutChange = useCallback((_layout, layouts) => {
|
|
423
444
|
if (!isEditing)
|
|
424
445
|
return;
|
|
@@ -448,12 +469,18 @@ export function usePageGridLayout({ pageKey, defaultLayouts, defaultCols = 12, l
|
|
|
448
469
|
}
|
|
449
470
|
};
|
|
450
471
|
}, []);
|
|
472
|
+
/**
|
|
473
|
+
* Change how many columns the canvas is DISPLAYED at.
|
|
474
|
+
*
|
|
475
|
+
* This writes nothing to storage. `currentLayouts` rescales the authored
|
|
476
|
+
* layout for display on every render, so switching 11 -> 2 -> 11 returns the
|
|
477
|
+
* user to exactly what they authored. The previous version persisted the
|
|
478
|
+
* rescale, which destroyed the arrangement at the narrow end and offered no
|
|
479
|
+
* undo. Storage moves only when the user actually edits — see `commitLayout`.
|
|
480
|
+
*/
|
|
451
481
|
const handleColumnChange = useCallback((newCols) => {
|
|
452
|
-
const rescaled = rescaleLayout(currentLayouts, layoutCols, newCols);
|
|
453
|
-
setSavedLayout(rescaled);
|
|
454
482
|
setLayoutCols(newCols);
|
|
455
|
-
|
|
456
|
-
}, [currentLayouts, layoutCols, setBaseCols, setLayoutCols, setSavedLayout]);
|
|
483
|
+
}, [setLayoutCols]);
|
|
457
484
|
/**
|
|
458
485
|
* Build the object handed to the preference adapter from a new `lg` array.
|
|
459
486
|
*
|
|
@@ -471,6 +498,11 @@ export function usePageGridLayout({ pageKey, defaultLayouts, defaultCols = 12, l
|
|
|
471
498
|
}
|
|
472
499
|
return next;
|
|
473
500
|
}, [currentLayouts]);
|
|
501
|
+
/** Persist a bare `lg` item list from a mutator, re-basing the same way. */
|
|
502
|
+
const commitItems = useCallback((items) => {
|
|
503
|
+
setSavedLayout(layoutsWithLg(items));
|
|
504
|
+
setBaseCols(layoutCols);
|
|
505
|
+
}, [layoutCols, layoutsWithLg, setBaseCols, setSavedLayout]);
|
|
474
506
|
const handleCompact = useCallback(() => {
|
|
475
507
|
if (!currentLayouts.lg)
|
|
476
508
|
return;
|
|
@@ -487,8 +519,8 @@ export function usePageGridLayout({ pageKey, defaultLayouts, defaultCols = 12, l
|
|
|
487
519
|
placed.push(compacted);
|
|
488
520
|
return compacted;
|
|
489
521
|
});
|
|
490
|
-
startTransition(() =>
|
|
491
|
-
}, [currentLayouts,
|
|
522
|
+
startTransition(() => commitItems(result));
|
|
523
|
+
}, [currentLayouts, commitItems]);
|
|
492
524
|
const handleReset = useCallback(() => {
|
|
493
525
|
startTransition(() => {
|
|
494
526
|
setSavedLayout(defaultLayouts);
|
|
@@ -507,7 +539,7 @@ export function usePageGridLayout({ pageKey, defaultLayouts, defaultCols = 12, l
|
|
|
507
539
|
minW: initialSize?.minW,
|
|
508
540
|
minH: initialSize?.minH,
|
|
509
541
|
};
|
|
510
|
-
startTransition(() =>
|
|
542
|
+
startTransition(() => commitItems([...(currentLayouts.lg ?? []), newItem]));
|
|
511
543
|
}, [currentLayouts, layoutCols, layoutsWithLg, setSavedLayout]);
|
|
512
544
|
const moveWidget = useCallback((widgetKey, direction) => {
|
|
513
545
|
const items = [...(currentLayouts.lg ?? [])];
|
|
@@ -524,7 +556,7 @@ export function usePageGridLayout({ pageKey, defaultLayouts, defaultCols = 12, l
|
|
|
524
556
|
moved,
|
|
525
557
|
...withoutMoved.slice(targetIndex),
|
|
526
558
|
];
|
|
527
|
-
startTransition(() =>
|
|
559
|
+
startTransition(() => commitItems(nextItems));
|
|
528
560
|
}, [currentLayouts, layoutsWithLg, setSavedLayout]);
|
|
529
561
|
const setWidgetLocked = useCallback((widgetKey, locked) => {
|
|
530
562
|
const nextItems = (currentLayouts.lg ?? []).map((item) => {
|
|
@@ -537,11 +569,11 @@ export function usePageGridLayout({ pageKey, defaultLayouts, defaultCols = 12, l
|
|
|
537
569
|
isResizable: !locked,
|
|
538
570
|
};
|
|
539
571
|
});
|
|
540
|
-
startTransition(() =>
|
|
572
|
+
startTransition(() => commitItems(nextItems));
|
|
541
573
|
}, [currentLayouts, layoutsWithLg, setSavedLayout]);
|
|
542
574
|
const removeWidget = useCallback((widgetKey) => {
|
|
543
575
|
const nextItems = (currentLayouts.lg ?? []).filter((item) => item.i !== widgetKey);
|
|
544
|
-
startTransition(() =>
|
|
576
|
+
startTransition(() => commitItems(nextItems));
|
|
545
577
|
}, [currentLayouts, layoutsWithLg, setSavedLayout]);
|
|
546
578
|
/**
|
|
547
579
|
* Measured auto-height overrides (widgetKey -> rows). DERIVED, in-memory-
|