@bsuite/page-builder 2.1.0 → 2.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageGridLayout.d.ts","sourceRoot":"","sources":["../src/PageGridLayout.tsx"],"names":[],"mappings":"AACA,OAAO,KAQN,MAAM,OAAO,CAAC;AAGf,OAAO,kCAAkC,CAAC;AAC1C,OAAO,gCAAgC,CAAC;AAMxC,OAAO,KAAK,EAAe,mBAAmB,EAA4B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"PageGridLayout.d.ts","sourceRoot":"","sources":["../src/PageGridLayout.tsx"],"names":[],"mappings":"AACA,OAAO,KAQN,MAAM,OAAO,CAAC;AAGf,OAAO,kCAAkC,CAAC;AAC1C,OAAO,gCAAgC,CAAC;AAMxC,OAAO,KAAK,EAAe,mBAAmB,EAA4B,MAAM,YAAY,CAAC;AAyd7F,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,OAAO,EACP,UAAU,EACV,SAAS,EAMT,WAAkB,EAClB,aAAsC,EACtC,QAAQ,EACR,iBAAiB,EAKjB,UAAkB,EAClB,yBAAiE,EACjE,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,+BAA6E,EAC7E,wBAAwB,EACxB,4BAA4B,EAC5B,4BAA4B,GAC7B,EAAE,mBAAmB,qBAyzBrB"}
|
package/dist/PageGridLayout.js
CHANGED
|
@@ -84,6 +84,61 @@ const DEFAULT_ADD_RELATIONSHIP_WIDGET_EVENT_NAMES = [
|
|
|
84
84
|
const RGLResizeHandle = React.forwardRef(function RGLResizeHandle({ axis = 'se', className: injectedClassName, ...rest }, ref) {
|
|
85
85
|
return (_jsx("span", { ref: ref, "data-no-drag": true, className: `react-resizable-handle react-resizable-handle-${axis}${injectedClassName ? ' ' + injectedClassName : ''}`, ...rest }));
|
|
86
86
|
});
|
|
87
|
+
/* A ZERO MEASUREMENT IS DISCARDED SILENTLY, AND THAT IS HOW A CARD GOES INVISIBLE.
|
|
88
|
+
*
|
|
89
|
+
* `reportRows` is guarded by `contentPx > 0` — correctly, because a zero reading
|
|
90
|
+
* during mount would converge the card to nothing. But a card whose content
|
|
91
|
+
* genuinely measures zero then keeps whatever row count it had, inside a wrapper
|
|
92
|
+
* that is `overflow-hidden`. The card renders. The content does not. Nothing
|
|
93
|
+
* fails, and nothing says so.
|
|
94
|
+
*
|
|
95
|
+
* The reachable cause is a percentage height. The measuring div is deliberately
|
|
96
|
+
* UNCONSTRAINED so the observer reads intrinsic height rather than the clipped
|
|
97
|
+
* flex box — that is the whole reason it exists. An unconstrained parent has
|
|
98
|
+
* `height: auto`, and a child asking for `height: 100%` against `auto` resolves
|
|
99
|
+
* to auto, i.e. its own content height. A chart, a canvas or a map that sizes
|
|
100
|
+
* itself from its parent therefore collapses to nothing, and the taller the
|
|
101
|
+
* intended element the more invisible it is. The same CSS rule produced a
|
|
102
|
+
* 1184x0 schema-builder canvas in production with 45 laid-out nodes inside it.
|
|
103
|
+
*
|
|
104
|
+
* This does NOT change layout. Constraining the wrapper would break the
|
|
105
|
+
* measurement it exists to take, and changing the autoHeight default is how
|
|
106
|
+
* page-builder 2.0.0 discarded every saved layout across 1,729 cards. It makes
|
|
107
|
+
* the silent case audible in development and leaves production untouched, which
|
|
108
|
+
* is the same trade @bsuite/theme 1.3.0 made for its missing-provider warning.
|
|
109
|
+
*/
|
|
110
|
+
let warnedAboutCollapsedContent = false;
|
|
111
|
+
function warnOnceAboutCollapsedContent(el) {
|
|
112
|
+
if (warnedAboutCollapsedContent)
|
|
113
|
+
return;
|
|
114
|
+
/* THE SIGNATURE, not merely "height is zero".
|
|
115
|
+
*
|
|
116
|
+
* Requiring childElementCount > 0 is not enough, and jsdom is why: it has no
|
|
117
|
+
* layout engine, so getBoundingClientRect().height is 0 for EVERY element in
|
|
118
|
+
* every test. A warning keyed on that fires on every mounted card in the suite
|
|
119
|
+
* and means nothing — the recorded lesson is that jsdom cannot model the bug
|
|
120
|
+
* this exists to catch, so the check must not pretend it can.
|
|
121
|
+
*
|
|
122
|
+
* The real defect has a distinctive shape, measured in production: laid-out
|
|
123
|
+
* content inside a zero-height box — scrollHeight 1938 against clientHeight 0.
|
|
124
|
+
* Requiring scrollHeight > 0 selects exactly that, and jsdom reports 0 for
|
|
125
|
+
* both, so it stays silent there rather than crying wolf. */
|
|
126
|
+
if (el.scrollHeight <= 0)
|
|
127
|
+
return;
|
|
128
|
+
const isDev = typeof import.meta !== 'undefined' &&
|
|
129
|
+
import.meta.env?.DEV === true;
|
|
130
|
+
if (!isDev)
|
|
131
|
+
return;
|
|
132
|
+
warnedAboutCollapsedContent = true;
|
|
133
|
+
console.error('[@bsuite/page-builder] An autoHeight card measured 0px with content inside it, '
|
|
134
|
+
+ 'so its height was left unchanged and the content is clipped by overflow-hidden — '
|
|
135
|
+
+ 'the card looks empty rather than broken. The usual cause is a child sized with '
|
|
136
|
+
+ 'height:100% (a chart, canvas or map): the measuring wrapper is intentionally '
|
|
137
|
+
+ 'unconstrained so the observer can read intrinsic height, and a percentage height '
|
|
138
|
+
+ 'against an auto-height parent resolves to auto. Give the child an intrinsic height '
|
|
139
|
+
+ '(an aspect ratio, a px/rem height, or min-height), or pass autoHeight={false} on '
|
|
140
|
+
+ 'this card so it renders into the constrained scrollable wrapper instead.');
|
|
141
|
+
}
|
|
87
142
|
const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, isEditing, label, onHide, autoHeight, onAutoHeightChange, chrome = false, children: injectedChildren, className: injectedClassName, style: injectedStyle, ...rest }, ref) {
|
|
88
143
|
// Auto-height measurement (blueprint amendment A1). `measureRef` wraps
|
|
89
144
|
// `content` with NO height constraint of its own — its parent has
|
|
@@ -161,6 +216,8 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
|
|
|
161
216
|
latestContentPxRef.current = contentPx;
|
|
162
217
|
if (contentPx > 0)
|
|
163
218
|
reportRows(contentPx);
|
|
219
|
+
else
|
|
220
|
+
warnOnceAboutCollapsedContent(el);
|
|
164
221
|
}, [autoHeight, onAutoHeightChange, reportRows]);
|
|
165
222
|
useEffect(() => {
|
|
166
223
|
if (!autoHeight || !onAutoHeightChange)
|
|
@@ -214,7 +271,7 @@ const GridItem = React.memo(React.forwardRef(function GridItem({ id, content, is
|
|
|
214
271
|
return (_jsxs("div", { ref: ref, className: outerClass, style: injectedStyle, ...rest, children: [_jsxs("div", { className: "h-full w-full relative", children: [isEditing && (_jsx("div", { className: "absolute inset-0 z-10 pointer-events-none rounded-3xl border-2 border-transparent group-hover:border-primary/50 transition-colors bg-primary/5" })), isEditing && (_jsx("div", { className: "absolute top-2 left-2 z-30 flex items-center gap-1 pointer-events-none", children: _jsx("span", { className: "text-[10px] px-1.5 py-0.5 rounded-md opacity-80 font-medium bg-muted text-muted-foreground", children: label }) })), isEditing && (_jsx("button", { className: "absolute top-2 right-2 z-30 h-6 w-6 rounded-full flex items-center justify-center bg-destructive/80 hover:bg-destructive text-destructive-foreground shadow transition-colors", "data-no-drag": true, onPointerDown: (event) => event.stopPropagation(), onClick: (event) => {
|
|
215
272
|
event.stopPropagation();
|
|
216
273
|
onHide(id);
|
|
217
|
-
}, title: `Hide ${label}`, "aria-label": `Hide ${label}`, children: _jsx(EyeOff, { className: "h-3 w-3", "aria-hidden": "true" }) })), _jsx("div", { "data-slot": "grid-item-surface", "data-chrome": chrome ? 'on' : 'off', className: chrome
|
|
274
|
+
}, title: `Hide ${label}`, "aria-label": `Hide ${label}`, children: _jsx(EyeOff, { className: "h-3 w-3", "aria-hidden": "true" }) })), _jsx("div", { "data-slot": "grid-item-surface", "data-chrome": chrome ? 'on' : 'off', "data-grid-slot-key": id, className: chrome
|
|
218
275
|
? // ONE radius token, read by the grid item AND available to any
|
|
219
276
|
// app card that opts into the same surface. Two surfaces
|
|
220
277
|
// reading the SAME var is what makes their corners align, and
|
|
@@ -21,17 +21,37 @@ export type ResponsiveBreakpoint = (typeof RESPONSIVE_BREAKPOINTS)[number];
|
|
|
21
21
|
* and the SE resize handle could not widen a card that was already at the grid
|
|
22
22
|
* bound nor narrow one whose `minW` had been clamped up to `cols`.
|
|
23
23
|
*
|
|
24
|
-
* `md` and `sm` therefore mirror `lg
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
24
|
+
* `md` and `sm` therefore mirror `lg`. So does `xs`, as of 2026-08-26 — the
|
|
25
|
+
* 2026-08-13 fix stopped ONE BREAKPOINT SHORT of the sessions D-75 was reported
|
|
26
|
+
* from, and the operator kept reporting it.
|
|
27
|
+
*
|
|
28
|
+
* MEASURED on production crm.crm7.app/dashboard, signed in, with a positive
|
|
29
|
+
* control in both directions at a SINGLE viewport (1024x1000) where the only
|
|
30
|
+
* variable is the sidebar:
|
|
31
|
+
*
|
|
32
|
+
* sidebar expanded -> container 664px -> `xs` -> the columns control was
|
|
33
|
+
* INERT: presets 2/4/12 each produced the identical
|
|
34
|
+
* single-column layout.
|
|
35
|
+
* sidebar collapsed -> container 872px -> `sm` -> the control ACTED: three
|
|
36
|
+
* presets, three distinct layouts.
|
|
37
|
+
*
|
|
38
|
+
* Same page, same viewport, same control. And in the inert case the control
|
|
39
|
+
* stayed fully interactive — it accepted the click and updated its own
|
|
40
|
+
* `aria-pressed`/`data-active` while nothing on screen moved.
|
|
41
|
+
*
|
|
42
|
+
* `xs` spans a 480-768px container. At 664px a two-column arrangement is ~330px
|
|
43
|
+
* a side, which is not the "unreadable sliver" the stacking rule was written to
|
|
44
|
+
* prevent; that rationale was about phones, and a 1024px laptop with a sidebar
|
|
45
|
+
* open is not a phone. Only `xxs` (< 480px container) genuinely is, so only
|
|
46
|
+
* `xxs` still stacks.
|
|
28
47
|
*/
|
|
29
|
-
export declare const MIRRORED_BREAKPOINTS: readonly ["md", "sm"];
|
|
48
|
+
export declare const MIRRORED_BREAKPOINTS: readonly ["md", "sm", "xs"];
|
|
30
49
|
/**
|
|
31
50
|
* Breakpoints derived as a single full-width stack — narrow enough that a
|
|
32
|
-
* multi-column arrangement cannot be read.
|
|
51
|
+
* multi-column arrangement genuinely cannot be read. Below a 480px container
|
|
52
|
+
* even two columns are ~230px a side before margins, which is the sliver case.
|
|
33
53
|
*/
|
|
34
|
-
export declare const STACKED_BREAKPOINTS: readonly ["
|
|
54
|
+
export declare const STACKED_BREAKPOINTS: readonly ["xxs"];
|
|
35
55
|
/**
|
|
36
56
|
* Every breakpoint this module DERIVES from `lg`.
|
|
37
57
|
*
|
|
@@ -60,10 +80,11 @@ export interface BuildResponsiveLayoutsOptions {
|
|
|
60
80
|
* Ensure a GridLayouts object has entries for all responsive breakpoints
|
|
61
81
|
* (lg, md, sm, xs, xxs).
|
|
62
82
|
*
|
|
63
|
-
* - `md` and `
|
|
64
|
-
* every desktop and tablet container width (see
|
|
65
|
-
*
|
|
66
|
-
*
|
|
83
|
+
* - `md`, `sm` and `xs` mirror `lg` so the user's chosen column arrangement
|
|
84
|
+
* survives every desktop, laptop and tablet container width (see
|
|
85
|
+
* {@link MIRRORED_BREAKPOINTS}).
|
|
86
|
+
* - `xxs` is derived as a single-column stack so a phone viewport never
|
|
87
|
+
* squashes cards into unreadable slivers.
|
|
67
88
|
* - Consumer-supplied breakpoints are preserved verbatim. Supplying one opts
|
|
68
89
|
* that breakpoint OUT of tracking `lg`, including out of the columns slider —
|
|
69
90
|
* prefer not to.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildResponsiveLayouts.d.ts","sourceRoot":"","sources":["../src/buildResponsiveLayouts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,sBAAsB,0CAA2C,CAAC;AAC/E,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3E
|
|
1
|
+
{"version":3,"file":"buildResponsiveLayouts.d.ts","sourceRoot":"","sources":["../src/buildResponsiveLayouts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,sBAAsB,0CAA2C,CAAC;AAC/E,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,eAAO,MAAM,oBAAoB,6BAA8B,CAAC;AAEhE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,kBAAmB,CAAC;AAEpD;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,oBAAoB,EAG9D,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEvE;AAED,MAAM,WAAW,6BAA6B;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA2BD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,WAAW,EACpB,EAAE,IAAS,EAAE,GAAE,6BAAkC,GAChD,WAAW,CAyBb"}
|
|
@@ -19,17 +19,37 @@ export const RESPONSIVE_BREAKPOINTS = ['lg', 'md', 'sm', 'xs', 'xxs'];
|
|
|
19
19
|
* and the SE resize handle could not widen a card that was already at the grid
|
|
20
20
|
* bound nor narrow one whose `minW` had been clamped up to `cols`.
|
|
21
21
|
*
|
|
22
|
-
* `md` and `sm` therefore mirror `lg
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* `md` and `sm` therefore mirror `lg`. So does `xs`, as of 2026-08-26 — the
|
|
23
|
+
* 2026-08-13 fix stopped ONE BREAKPOINT SHORT of the sessions D-75 was reported
|
|
24
|
+
* from, and the operator kept reporting it.
|
|
25
|
+
*
|
|
26
|
+
* MEASURED on production crm.crm7.app/dashboard, signed in, with a positive
|
|
27
|
+
* control in both directions at a SINGLE viewport (1024x1000) where the only
|
|
28
|
+
* variable is the sidebar:
|
|
29
|
+
*
|
|
30
|
+
* sidebar expanded -> container 664px -> `xs` -> the columns control was
|
|
31
|
+
* INERT: presets 2/4/12 each produced the identical
|
|
32
|
+
* single-column layout.
|
|
33
|
+
* sidebar collapsed -> container 872px -> `sm` -> the control ACTED: three
|
|
34
|
+
* presets, three distinct layouts.
|
|
35
|
+
*
|
|
36
|
+
* Same page, same viewport, same control. And in the inert case the control
|
|
37
|
+
* stayed fully interactive — it accepted the click and updated its own
|
|
38
|
+
* `aria-pressed`/`data-active` while nothing on screen moved.
|
|
39
|
+
*
|
|
40
|
+
* `xs` spans a 480-768px container. At 664px a two-column arrangement is ~330px
|
|
41
|
+
* a side, which is not the "unreadable sliver" the stacking rule was written to
|
|
42
|
+
* prevent; that rationale was about phones, and a 1024px laptop with a sidebar
|
|
43
|
+
* open is not a phone. Only `xxs` (< 480px container) genuinely is, so only
|
|
44
|
+
* `xxs` still stacks.
|
|
26
45
|
*/
|
|
27
|
-
export const MIRRORED_BREAKPOINTS = ['md', 'sm'];
|
|
46
|
+
export const MIRRORED_BREAKPOINTS = ['md', 'sm', 'xs'];
|
|
28
47
|
/**
|
|
29
48
|
* Breakpoints derived as a single full-width stack — narrow enough that a
|
|
30
|
-
* multi-column arrangement cannot be read.
|
|
49
|
+
* multi-column arrangement genuinely cannot be read. Below a 480px container
|
|
50
|
+
* even two columns are ~230px a side before margins, which is the sliver case.
|
|
31
51
|
*/
|
|
32
|
-
export const STACKED_BREAKPOINTS = ['
|
|
52
|
+
export const STACKED_BREAKPOINTS = ['xxs'];
|
|
33
53
|
/**
|
|
34
54
|
* Every breakpoint this module DERIVES from `lg`.
|
|
35
55
|
*
|
|
@@ -61,10 +81,11 @@ export function isCanonicalisableBreakpoint(breakpoint) {
|
|
|
61
81
|
/**
|
|
62
82
|
* Stack items into one full-width column, preserving reading order.
|
|
63
83
|
*
|
|
64
|
-
* `w: cols` is deliberate at the
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
84
|
+
* `w: cols` is deliberate at the breakpoint this is used for (`xxs`): the
|
|
85
|
+
* container is narrower than 480px, so a card occupies the whole grid whatever
|
|
86
|
+
* the column count. Do NOT reach for this at wider breakpoints — that was D-75,
|
|
87
|
+
* twice: once for `md`/`sm` in August 2026, and again for `xs`, which is where
|
|
88
|
+
* a 1024px laptop with an open sidebar actually lands.
|
|
68
89
|
*/
|
|
69
90
|
function stackToSingleColumn(items, cols) {
|
|
70
91
|
const sorted = [...items].sort((a, b) => (a.y !== b.y ? a.y - b.y : a.x - b.x));
|
|
@@ -85,10 +106,11 @@ function stackToSingleColumn(items, cols) {
|
|
|
85
106
|
* Ensure a GridLayouts object has entries for all responsive breakpoints
|
|
86
107
|
* (lg, md, sm, xs, xxs).
|
|
87
108
|
*
|
|
88
|
-
* - `md` and `
|
|
89
|
-
* every desktop and tablet container width (see
|
|
90
|
-
*
|
|
91
|
-
*
|
|
109
|
+
* - `md`, `sm` and `xs` mirror `lg` so the user's chosen column arrangement
|
|
110
|
+
* survives every desktop, laptop and tablet container width (see
|
|
111
|
+
* {@link MIRRORED_BREAKPOINTS}).
|
|
112
|
+
* - `xxs` is derived as a single-column stack so a phone viewport never
|
|
113
|
+
* squashes cards into unreadable slivers.
|
|
92
114
|
* - Consumer-supplied breakpoints are preserved verbatim. Supplying one opts
|
|
93
115
|
* that breakpoint OUT of tracking `lg`, including out of the columns slider —
|
|
94
116
|
* prefer not to.
|