@bsuite/page-builder 0.7.0 → 0.9.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.
- package/dist/CanvasCard.d.ts +52 -0
- package/dist/CanvasCard.d.ts.map +1 -0
- package/dist/CanvasCard.js +18 -0
- package/dist/DraggableCardPage.d.ts +118 -0
- package/dist/DraggableCardPage.d.ts.map +1 -0
- package/dist/DraggableCardPage.js +110 -0
- package/dist/PageGridLayout.d.ts +1 -1
- package/dist/PageGridLayout.d.ts.map +1 -1
- package/dist/PageGridLayout.js +102 -19
- package/dist/buildResponsiveLayouts.d.ts +61 -4
- package/dist/buildResponsiveLayouts.d.ts.map +1 -1
- package/dist/buildResponsiveLayouts.js +77 -5
- package/dist/canvasCardLayout.d.ts +62 -0
- package/dist/canvasCardLayout.d.ts.map +1 -0
- package/dist/canvasCardLayout.js +120 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/scanner/cardSurfaceScanner.d.ts +120 -0
- package/dist/scanner/cardSurfaceScanner.d.ts.map +1 -0
- package/dist/scanner/cardSurfaceScanner.js +289 -0
- package/dist/scanner/index.d.ts +3 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +1 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/usePageGridLayout.d.ts +22 -1
- package/dist/usePageGridLayout.d.ts.map +1 -1
- package/dist/usePageGridLayout.js +197 -66
- package/package.json +8 -3
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The card-surface contract scanner — ONE implementation, shipped from the
|
|
3
|
+
* package, replacing five divergent hand-rolled copies.
|
|
4
|
+
*
|
|
5
|
+
* Why this exists
|
|
6
|
+
* ---------------
|
|
7
|
+
* crm7 wrote a card-unglue contract test. BSU, conduit, throughput and braden
|
|
8
|
+
* each PORTED it, and each silently dropped checks during the port. The
|
|
9
|
+
* divergence was not cosmetic:
|
|
10
|
+
*
|
|
11
|
+
* - `findUngriddedMultiCard` — the check crm7's own comment calls "the actual
|
|
12
|
+
* root cause of the operator's platform-wide complaint" — was ABSENT from
|
|
13
|
+
* BSU, throughput and braden, and present only in a narrowed form in
|
|
14
|
+
* conduit. In throughput and braden it was absent structurally: their glue
|
|
15
|
+
* scan is gated on the file containing `CanvasCard` at all, so a page with
|
|
16
|
+
* two cards and no grid primitive is invisible by construction.
|
|
17
|
+
* - conduit's header documents THREE card idioms and its regexes detect TWO.
|
|
18
|
+
* The third (`rounded-lg border p-4` section panels) has no detector, which
|
|
19
|
+
* is how five known-glued conduit pages pass as an empty ledger.
|
|
20
|
+
* - BSU's scan only walks files containing the literal string
|
|
21
|
+
* `PageGridLayout`, so every BSU page that never adopted the grid is
|
|
22
|
+
* structurally invisible to BSU's own gate.
|
|
23
|
+
*
|
|
24
|
+
* A gate that cannot tell "checked nothing" from "found nothing" is not a gate
|
|
25
|
+
* (D-92). This module therefore ASSERTS ITS INPUTS: it fails closed if a scan
|
|
26
|
+
* root is missing or matches zero files, and it reports how it reached its
|
|
27
|
+
* verdict rather than only the verdict.
|
|
28
|
+
*
|
|
29
|
+
* What stays per-app
|
|
30
|
+
* ------------------
|
|
31
|
+
* Scan roots, card vocabulary, class-based surface patterns, and the exclusion
|
|
32
|
+
* ledgers. Those are operational truth about a specific app. Everything else —
|
|
33
|
+
* the detection logic — lives here so it can only be fixed once.
|
|
34
|
+
*
|
|
35
|
+
* Node-only: this module touches the filesystem and is exported from
|
|
36
|
+
* `@bsuite/page-builder/scanner`, NOT from the package root, so it never
|
|
37
|
+
* reaches a browser bundle.
|
|
38
|
+
*/
|
|
39
|
+
import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
|
|
40
|
+
import { join, relative, sep } from 'node:path';
|
|
41
|
+
const DEFAULT_GRID_PRIMITIVES = [
|
|
42
|
+
'CanvasCard',
|
|
43
|
+
'DraggableCardPage',
|
|
44
|
+
'PageGridLayout',
|
|
45
|
+
'usePageGridLayout',
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Strip block comments, line comments and JSX comments before matching.
|
|
49
|
+
*
|
|
50
|
+
* Three of the five hand-rolled copies matched against raw file content, which
|
|
51
|
+
* produced two opposite errors at once: a commented-out `<Card/><Card/>`
|
|
52
|
+
* example false-POSITIVES as glue, and a file that merely MENTIONS
|
|
53
|
+
* `CanvasCard` in a TODO comment false-NEGATIVES as "already gridded" and is
|
|
54
|
+
* skipped entirely. Stripping first fixes both.
|
|
55
|
+
*/
|
|
56
|
+
export function stripComments(source) {
|
|
57
|
+
return source
|
|
58
|
+
.replace(/\{\s*\/\*[\s\S]*?\*\/\s*\}/g, '') // {/* JSX comment */}
|
|
59
|
+
.replace(/\/\*[\s\S]*?\*\//g, '') // /* block */
|
|
60
|
+
.replace(/(^|[^:])\/\/[^\n]*/g, '$1'); // // line, but not http://
|
|
61
|
+
}
|
|
62
|
+
function tagPattern(tags) {
|
|
63
|
+
// `[\s/>]` not `[\s>]`: `<Card/>` with no space before the slash was missed
|
|
64
|
+
// by three of the five copies. The trailing alternation keeps `<Card>` and
|
|
65
|
+
// `<Card ...>` matching too.
|
|
66
|
+
return new RegExp(`<(${tags.join('|')})[\\s/>]`, 'g');
|
|
67
|
+
}
|
|
68
|
+
function countCardTags(source, config) {
|
|
69
|
+
let count = (source.match(tagPattern(config.cardTags)) ?? []).length;
|
|
70
|
+
for (const re of config.classSurfaces ?? []) {
|
|
71
|
+
const global = new RegExp(re.source, re.flags.includes('g') ? re.flags : re.flags + 'g');
|
|
72
|
+
count += (source.match(global) ?? []).length;
|
|
73
|
+
}
|
|
74
|
+
return count;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Does this source render cards from a `.map()`?
|
|
78
|
+
*
|
|
79
|
+
* The non-greedy `[\s\S]*?` form is deliberate. Three copies used
|
|
80
|
+
* `\.map\s*\([^)]*\)\s*=>` which requires a PARENTHESISED parameter, so
|
|
81
|
+
* `items.map(item => <Card/>)` — a bare param with an expression body — was
|
|
82
|
+
* missed. That gap is currently dormant across the estate but it is a landmine,
|
|
83
|
+
* not a theoretical concern.
|
|
84
|
+
*/
|
|
85
|
+
function hasMappedCards(source, config) {
|
|
86
|
+
const tags = config.cardTags.join('|');
|
|
87
|
+
if (new RegExp(`\\.map\\s*\\([\\s\\S]*?=>\\s*\\(?\\s*<(${tags})[\\s/>]`).test(source) ||
|
|
88
|
+
new RegExp(`\\.map\\s*\\([\\s\\S]*?\\{[\\s\\S]*?return\\s*\\(?\\s*<(${tags})[\\s/>]`).test(source))
|
|
89
|
+
return true;
|
|
90
|
+
// A mapped CLASS surface is still a mapped card.
|
|
91
|
+
//
|
|
92
|
+
// This was missed on the first pass: the tag alternation above is built from
|
|
93
|
+
// `cardTags` only, so `.map(api => <div className="glass-card">…)` produced N
|
|
94
|
+
// cards inside one grid slot and read as clean. BSU's `Government.tsx#apis`
|
|
95
|
+
// is exactly that shape, and only its hand-maintained ledger knew — which is
|
|
96
|
+
// the failure mode this whole module exists to end. `countCardTags` already
|
|
97
|
+
// counts class surfaces; the mapped check has to as well or the two disagree.
|
|
98
|
+
for (const re of config.classSurfaces ?? []) {
|
|
99
|
+
const src = re.source;
|
|
100
|
+
if (new RegExp(`\\.map\\s*\\([\\s\\S]*?=>\\s*\\(?\\s*<[^>]*?${src}`).test(source) ||
|
|
101
|
+
new RegExp(`\\.map\\s*\\([\\s\\S]*?\\{[\\s\\S]*?return\\s*\\(?\\s*<[^>]*?${src}`).test(source))
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
/** Extract the body of every `<CanvasCard …> … </CanvasCard>` block. */
|
|
107
|
+
function extractCanvasCardBlocks(source) {
|
|
108
|
+
const blocks = [];
|
|
109
|
+
const re = /<CanvasCard[\s>][\s\S]*?<\/CanvasCard>/g;
|
|
110
|
+
let m;
|
|
111
|
+
while ((m = re.exec(source)) !== null)
|
|
112
|
+
blocks.push(m[0]);
|
|
113
|
+
return blocks;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Extract each value of an inline `widgets={{ key: <jsx/> }}` object literal.
|
|
117
|
+
* Brace-balanced rather than regex-terminated, because a widget body contains
|
|
118
|
+
* arbitrary nested JSX and braces.
|
|
119
|
+
*/
|
|
120
|
+
function extractWidgetEntries(source) {
|
|
121
|
+
const out = [];
|
|
122
|
+
const start = /widgets=\{\{/g;
|
|
123
|
+
let m;
|
|
124
|
+
while ((m = start.exec(source)) !== null) {
|
|
125
|
+
let depth = 2;
|
|
126
|
+
let i = m.index + m[0].length;
|
|
127
|
+
const objStart = i;
|
|
128
|
+
while (i < source.length && depth > 0) {
|
|
129
|
+
if (source[i] === '{')
|
|
130
|
+
depth++;
|
|
131
|
+
else if (source[i] === '}')
|
|
132
|
+
depth--;
|
|
133
|
+
i++;
|
|
134
|
+
}
|
|
135
|
+
const obj = source.slice(objStart, i - 2);
|
|
136
|
+
// Split top-level `key:` entries at depth 0.
|
|
137
|
+
let d = 0;
|
|
138
|
+
let keyStart = 0;
|
|
139
|
+
let currentKey = null;
|
|
140
|
+
let bodyStart = 0;
|
|
141
|
+
for (let j = 0; j < obj.length; j++) {
|
|
142
|
+
const c = obj[j];
|
|
143
|
+
if (c === '{' || c === '(' || c === '[')
|
|
144
|
+
d++;
|
|
145
|
+
else if (c === '}' || c === ')' || c === ']')
|
|
146
|
+
d--;
|
|
147
|
+
else if (c === ':' && d === 0 && currentKey === null) {
|
|
148
|
+
currentKey = obj.slice(keyStart, j).trim().replace(/['"]/g, '');
|
|
149
|
+
bodyStart = j + 1;
|
|
150
|
+
}
|
|
151
|
+
else if (c === ',' && d === 0 && currentKey !== null) {
|
|
152
|
+
out.push({ key: currentKey, body: obj.slice(bodyStart, j) });
|
|
153
|
+
currentKey = null;
|
|
154
|
+
keyStart = j + 1;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (currentKey !== null)
|
|
158
|
+
out.push({ key: currentKey, body: obj.slice(bodyStart) });
|
|
159
|
+
}
|
|
160
|
+
return out;
|
|
161
|
+
}
|
|
162
|
+
function walk(dir, extensions, acc) {
|
|
163
|
+
for (const entry of readdirSync(dir)) {
|
|
164
|
+
if (entry === 'node_modules' || entry === 'dist' || entry === '.git')
|
|
165
|
+
continue;
|
|
166
|
+
const full = join(dir, entry);
|
|
167
|
+
const st = statSync(full);
|
|
168
|
+
if (st.isDirectory())
|
|
169
|
+
walk(full, extensions, acc);
|
|
170
|
+
else if (extensions.some((e) => entry.endsWith(e)) && !/\.(test|spec)\./.test(entry))
|
|
171
|
+
acc.push(full);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
export function scanCardSurfaces(config) {
|
|
175
|
+
const extensions = config.extensions ?? ['.tsx'];
|
|
176
|
+
const gridPrimitives = config.gridPrimitives ?? DEFAULT_GRID_PRIMITIVES;
|
|
177
|
+
const findings = [];
|
|
178
|
+
const files = [];
|
|
179
|
+
const scanRootsResolved = [];
|
|
180
|
+
// D-92: assert the inputs were present BEFORE reporting any verdict. A
|
|
181
|
+
// missing scan root must fail loudly, not produce a confident zero.
|
|
182
|
+
for (const root of config.scanRoots) {
|
|
183
|
+
const abs = join(config.projectRoot, root);
|
|
184
|
+
if (!existsSync(abs))
|
|
185
|
+
throw new Error(`[cardSurfaceScanner] scan root "${root}" does not exist at ${abs}. ` +
|
|
186
|
+
`A scanner that silently skips a missing root reports a false pass, which is worse than a failure.`);
|
|
187
|
+
const before = files.length;
|
|
188
|
+
walk(abs, extensions, files);
|
|
189
|
+
if (files.length === before)
|
|
190
|
+
throw new Error(`[cardSurfaceScanner] scan root "${root}" matched ZERO files with extensions ${extensions.join(', ')}. ` +
|
|
191
|
+
`Refusing to report a verdict from an empty scan.`);
|
|
192
|
+
scanRootsResolved.push(root);
|
|
193
|
+
}
|
|
194
|
+
// Retired single-widget primitives must not exist and must not be imported.
|
|
195
|
+
for (const retired of config.retiredPrimitivePaths ?? []) {
|
|
196
|
+
const abs = join(config.projectRoot, retired);
|
|
197
|
+
if (existsSync(abs))
|
|
198
|
+
findings.push({
|
|
199
|
+
file: retired,
|
|
200
|
+
idiom: 'retired-primitive',
|
|
201
|
+
detail: `${retired} still exists. It builds ONE grid item for the whole page, so every card on it ` +
|
|
202
|
+
`moves as a single block — the exact defect this contract exists to prevent.`,
|
|
203
|
+
});
|
|
204
|
+
const base = retired.split(sep).pop()?.replace(/\.tsx?$/, '');
|
|
205
|
+
if (base) {
|
|
206
|
+
for (const file of files) {
|
|
207
|
+
const src = stripComments(readFileSync(file, 'utf8'));
|
|
208
|
+
if (new RegExp(`\\b${base}\\b`).test(src) && !file.endsWith(retired))
|
|
209
|
+
findings.push({
|
|
210
|
+
file: relative(config.projectRoot, file),
|
|
211
|
+
idiom: 'retired-primitive',
|
|
212
|
+
detail: `imports or references the retired primitive ${base}`,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
for (const file of files) {
|
|
218
|
+
const rel = relative(config.projectRoot, file);
|
|
219
|
+
const raw = readFileSync(file, 'utf8');
|
|
220
|
+
const src = stripComments(raw);
|
|
221
|
+
// --- glued widget: 2+ cards inside ONE grid slot -----------------------
|
|
222
|
+
const slots = [
|
|
223
|
+
...extractCanvasCardBlocks(src).map((b, i) => ({ label: `CanvasCard#${i + 1}`, body: b })),
|
|
224
|
+
...extractWidgetEntries(src).map((e) => ({ label: `widgets.${e.key}`, body: e.body })),
|
|
225
|
+
];
|
|
226
|
+
for (const slot of slots) {
|
|
227
|
+
const n = countCardTags(slot.body, config);
|
|
228
|
+
const mapped = hasMappedCards(slot.body, config);
|
|
229
|
+
if (n > 1 || mapped) {
|
|
230
|
+
if (config.gluedExclusions?.[rel])
|
|
231
|
+
continue;
|
|
232
|
+
findings.push({
|
|
233
|
+
file: rel,
|
|
234
|
+
idiom: 'glued-widget',
|
|
235
|
+
cardCount: n,
|
|
236
|
+
detail: `${slot.label} packs ${mapped ? 'a .map() of cards' : `${n} card-like components`} into one grid slot. ` +
|
|
237
|
+
`Dragging any one of them moves them all.`,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// --- ungridded multi-card: the check three of five ports DROPPED -------
|
|
242
|
+
// Gate on the COMMENT-STRIPPED source so a TODO mentioning CanvasCard does
|
|
243
|
+
// not mask a page that never actually reaches the grid.
|
|
244
|
+
const usesGrid = gridPrimitives.some((p) => new RegExp(`\\b${p}\\b`).test(src));
|
|
245
|
+
if (!usesGrid) {
|
|
246
|
+
const n = countCardTags(src, config);
|
|
247
|
+
if (n > 1 && !config.ungriddedExclusions?.[rel]) {
|
|
248
|
+
findings.push({
|
|
249
|
+
file: rel,
|
|
250
|
+
idiom: 'ungridded-multi-card',
|
|
251
|
+
cardCount: n,
|
|
252
|
+
detail: `renders ${n} card-like surfaces and never reaches a grid primitive, so none of them is draggable at all. ` +
|
|
253
|
+
`This is the idiom crm7's scanner calls "the actual root cause of the operator's platform-wide complaint".`,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// --- autoHeight opt-out + clip invariant -------------------------------
|
|
258
|
+
const optOut = /autoHeight\s*[:=]\s*\{?\s*false/g;
|
|
259
|
+
if (optOut.test(src) && !(config.autoHeightEscapeHatch?.test(src) ?? false)) {
|
|
260
|
+
findings.push({
|
|
261
|
+
file: rel,
|
|
262
|
+
idiom: 'autoheight-optout',
|
|
263
|
+
detail: `opts out of autoHeight. That is reserved for genuinely virtualized/windowed lists that own their own scroll; ` +
|
|
264
|
+
`an ordinary table must expand so every row is visible.`,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
// A card that opts out AND seeds h<=2 (64px) cannot show its content.
|
|
268
|
+
if (/autoHeight\s*[:=]\s*\{?\s*false/.test(src) && /\bh=\{?[12]\}?/.test(src)) {
|
|
269
|
+
findings.push({
|
|
270
|
+
file: rel,
|
|
271
|
+
idiom: 'clipped-card',
|
|
272
|
+
detail: `autoHeight={false} with h<=2 (<=64px) — the card is guaranteed to clip its content.`,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// Stale ledger entries: a claim that is no longer true is a claim that will
|
|
277
|
+
// be trusted next time. An exclusions ledger is a claim, not a fact.
|
|
278
|
+
const hit = new Set(findings.map((f) => `${f.idiom}:${f.file}`));
|
|
279
|
+
const staleExclusions = [
|
|
280
|
+
...Object.keys(config.gluedExclusions ?? {}).filter((f) => !hit.has(`glued-widget:${f}`) && !hit.has(`autoheight-optout:${f}`)),
|
|
281
|
+
...Object.keys(config.ungriddedExclusions ?? {}).filter((f) => !hit.has(`ungridded-multi-card:${f}`)),
|
|
282
|
+
];
|
|
283
|
+
const summary = `scanned ${files.length} files across ${scanRootsResolved.length} root(s) [${scanRootsResolved.join(', ')}] ` +
|
|
284
|
+
`with cardTags [${config.cardTags.join(', ')}]` +
|
|
285
|
+
`${config.classSurfaces?.length ? ` + ${config.classSurfaces.length} class surface pattern(s)` : ''}; ` +
|
|
286
|
+
`${findings.length} finding(s); ${Object.keys(config.blindSpots ?? {}).length} declared blind spot(s); ` +
|
|
287
|
+
`${staleExclusions.length} stale exclusion(s).`;
|
|
288
|
+
return { findings, filesScanned: files.length, scanRootsResolved, staleExclusions, summary };
|
|
289
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC1E,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { scanCardSurfaces, stripComments } from './cardSurfaceScanner.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -34,6 +34,14 @@ export interface UsePageGridLayoutOptions {
|
|
|
34
34
|
canEditPage?: boolean;
|
|
35
35
|
editorEventNames?: readonly string[];
|
|
36
36
|
preferenceAdapter?: PageGridPreferenceFactory;
|
|
37
|
+
/**
|
|
38
|
+
* Value used for `GridLayoutItem.autoHeight` on any item that does not state
|
|
39
|
+
* one. Defaults to `true` — cards grow to fit their content rather than
|
|
40
|
+
* clipping it behind an inner scrollbar (D-76). Pass `false` for a surface
|
|
41
|
+
* whose items own their own scroll (a virtualized list); an individual item
|
|
42
|
+
* can always opt out with an explicit `autoHeight: false`.
|
|
43
|
+
*/
|
|
44
|
+
defaultAutoHeight?: boolean;
|
|
37
45
|
}
|
|
38
46
|
export interface WidgetMeta {
|
|
39
47
|
label: string;
|
|
@@ -162,6 +170,14 @@ export interface UsePageGridLayoutResult {
|
|
|
162
170
|
activeCompactor: Compactor;
|
|
163
171
|
onLayoutChange: (_layout: unknown, layouts: unknown) => void;
|
|
164
172
|
handleColumnChange: (newCols: number) => void;
|
|
173
|
+
/**
|
|
174
|
+
* Wire to `<Responsive onBreakpointChange>`. The hook needs to know which
|
|
175
|
+
* breakpoint react-grid-layout is rendering so a gesture is written back to
|
|
176
|
+
* the breakpoint that owns it — see `canonicaliseLayoutForPersist`. Without
|
|
177
|
+
* this the hook assumes `lg`, and every edit made at a narrower container
|
|
178
|
+
* width lands in a derived breakpoint that is then discarded (D-75).
|
|
179
|
+
*/
|
|
180
|
+
handleBreakpointChange: (breakpoint: string) => void;
|
|
165
181
|
handleCompact: () => void;
|
|
166
182
|
handleReset: () => void;
|
|
167
183
|
addWidget: (widgetKey: string, initialSize?: Partial<Pick<GridLayoutItem, 'w' | 'h' | 'minW' | 'minH'>>) => void;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEjF,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,cAAc,EAAE,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC;IACpD,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,EACxC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,CAAC,KACR,yBAAyB,CAAC,CAAC,CAAC,CAAC;AAElC,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,WAAW,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEjF,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,cAAc,EAAE,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC;IACpD,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,EACxC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,CAAC,KACR,yBAAyB,CAAC,CAAC,CAAC,CAAC;AAElC,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,WAAW,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,yBAAyB,CAAC;IAC9C;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,WAAW,CAAC,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACxE;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,0BAA2B,SAAQ,kBAAkB;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAYD;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,wBAAwB;IACvC,6EAA6E;IAC7E,cAAc,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gCAAiC,SAAQ,wBAAwB;IAChF,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,mBAAmB,GAAG,SAAS,wBAAwB,EAAE,CAAC;AAEtE,MAAM,WAAW,mBAAoB,SAAQ,wBAAwB;IACnE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC5C;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,yBAAyB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9E,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACtF;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,+BAA+B,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpD,wBAAwB,CAAC,EAAE,CAAC,OAAO,EAAE,gCAAgC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC1F,4BAA4B,CAAC,EAAE,CAAC,OAAO,EAAE,wBAAwB,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAClG;;;;;OAKG;IACH,4BAA4B,CAAC,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,CAAC;CAC3E;AAED,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,WAAW,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,eAAe,EAAE,SAAS,CAAC;IAC3B,cAAc,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7D,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C;;;;;;OAMG;IACH,sBAAsB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,EAAE,CACT,SAAS,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC,KACrE,IAAI,CAAC;IACV,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC;IAClE,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C;;;;;;;;;;OAUG;IACH,mBAAmB,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IACpE;0CACsC;IACtC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,mBAAmB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACnE,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAClD,cAAc,EAAE,MAAM,CAAC;CACxB"}
|
|
@@ -10,9 +10,30 @@ export declare const DEFAULT_EDITOR_EVENT_NAMES: readonly ["bsuite-open-page-edi
|
|
|
10
10
|
* launchers scope by page if they handle multiple grids on one screen.
|
|
11
11
|
*/
|
|
12
12
|
export declare const PAGE_GRID_EDITING_EVENT = "bsuite-page-grid-editing";
|
|
13
|
+
/**
|
|
14
|
+
* Package-wide layout epoch, added to EVERY consumer's `layoutVersion`.
|
|
15
|
+
*
|
|
16
|
+
* When a default that governs all grids changes, a saved layout produced under
|
|
17
|
+
* the old default has to be invalidated — and there is no way to reach ~330
|
|
18
|
+
* call sites across six apps to hand-bump each one. crm7's `DraggableCardPage`
|
|
19
|
+
* already solved this locally with its own `LAYOUT_EPOCH`; this is the same
|
|
20
|
+
* lever one level down, so it also covers the raw `PageGridLayout` consumers
|
|
21
|
+
* (Dashboard, Billing, GTO, Analytics, the throughput and braden pages) that
|
|
22
|
+
* no app-level epoch can see.
|
|
23
|
+
*
|
|
24
|
+
* 0 -> 1000 (2026-08-13, D-75/D-76): two all-grids defaults changed in the same
|
|
25
|
+
* release — `autoHeight` now defaults to true for raw consumers, and md/sm no
|
|
26
|
+
* longer collapse to a full-width stack. Every stored layout predates both and
|
|
27
|
+
* was additionally polluted with frozen derived breakpoints, so all of them
|
|
28
|
+
* reset once to the corrected defaults.
|
|
29
|
+
*
|
|
30
|
+
* Per-page `layoutVersion` bumps keep working on top; this only moves the
|
|
31
|
+
* floor.
|
|
32
|
+
*/
|
|
33
|
+
export declare const PACKAGE_LAYOUT_EPOCH = 1000;
|
|
13
34
|
export interface PageGridEditingEventDetail {
|
|
14
35
|
pageKey: string;
|
|
15
36
|
editing: boolean;
|
|
16
37
|
}
|
|
17
|
-
export declare function usePageGridLayout({ pageKey, defaultLayouts, defaultCols, layoutVersion, canEditPage, editorEventNames, preferenceAdapter, }: UsePageGridLayoutOptions): UsePageGridLayoutResult;
|
|
38
|
+
export declare function usePageGridLayout({ pageKey, defaultLayouts, defaultCols, layoutVersion, canEditPage, editorEventNames, preferenceAdapter, defaultAutoHeight, }: UsePageGridLayoutOptions): UsePageGridLayoutResult;
|
|
18
39
|
//# sourceMappingURL=usePageGridLayout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePageGridLayout.d.ts","sourceRoot":"","sources":["../src/usePageGridLayout.ts"],"names":[],"mappings":"
|
|
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,CAkmBpD"}
|