@bsuite/page-builder 1.0.7 → 2.0.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.
@@ -55,8 +55,17 @@ const DEFAULT_GRID_PRIMITIVES = [
55
55
  */
56
56
  export function stripComments(source) {
57
57
  return source
58
- .replace(/\{\s*\/\*[\s\S]*?\*\/\s*\}/g, '') // {/* JSX comment */}
59
- .replace(/\/\*[\s\S]*?\*\//g, '') // /* block */
58
+ // {/* JSX comment */} — TEMPERED so the match cannot span a `*​/` it did
59
+ // not open. The naive lazy form `\{\s*\/\*[\s\S]*?\*\/\s*\}` backtracks
60
+ // past the comment's own terminator whenever the next character is not
61
+ // `}` — e.g. an ordinary block comment sitting at the head of an object
62
+ // literal — and then matches the NEXT `*​/}` anywhere later in the file,
63
+ // DELETING every line between. crm7 `src/pages/people/new/worker.tsx` lost
64
+ // 37 lines and two whole `<CanvasCard>` blocks to exactly that, which the
65
+ // UNKNOWN gate below caught as unbalanced tags. Code silently deleted
66
+ // before matching is a scanner that under-reports and calls it clean.
67
+ .replace(/\{\s*\/\*(?:(?!\*\/)[\s\S])*\*\/\s*\}/g, '')
68
+ .replace(/\/\*(?:(?!\*\/)[\s\S])*\*\//g, '') // /* block */
60
69
  .replace(/(^|[^:])\/\/[^\n]*/g, '$1'); // // line, but not http://
61
70
  }
62
71
  function tagPattern(tags) {
@@ -159,6 +168,293 @@ function extractWidgetEntries(source) {
159
168
  }
160
169
  return out;
161
170
  }
171
+ /* ==========================================================================
172
+ * V-C5 — NESTED CHROME
173
+ *
174
+ * `PageGridLayout` paints EVERY grid item as a card:
175
+ *
176
+ * h-full w-full rounded-3xl transition-all flex flex-col
177
+ * bg-card border border-border shadow-sm dark:shadow-[var(--glow-card,none)]
178
+ *
179
+ * When the slot's own content re-declares that surface — border + radius +
180
+ * background — the user sees 28px inside 24px and two 1px borders. V-C4
181
+ * (`glued-widget`) cannot see this: ONE card in ONE slot is not glue, and it
182
+ * is still a double frame. That is why 316 files across the estate render a
183
+ * card inside a card and every existing gate reads green.
184
+ * ========================================================================== */
185
+ /** Components that paint their own card chrome. */
186
+ const DEFAULT_NESTED_CHROME_TAGS = [
187
+ 'Card',
188
+ 'MagicCard',
189
+ 'GlassCard',
190
+ 'NeonCard',
191
+ 'StatCard',
192
+ 'SummaryCard',
193
+ 'ServiceCard',
194
+ 'CounterCard',
195
+ 'MetricCard',
196
+ 'InfoCard',
197
+ ];
198
+ /**
199
+ * Elements that are CONTROLS, not surfaces.
200
+ *
201
+ * A bordered, rounded, tinted `<button>` is a button. A `<Badge>` is a pill.
202
+ * Counting them as nested chrome is how a detector inflates: throughput's
203
+ * `Teams.tsx` carries `border … rounded … text-…` on a filter button, which is
204
+ * correct styling and not a second card. Chrome on a control is never the
205
+ * double-frame defect, so controls are excluded BY TAG rather than by tuning
206
+ * the class thresholds until the number looks right.
207
+ */
208
+ const CONTROL_TAGS = new Set([
209
+ 'button',
210
+ 'a',
211
+ 'input',
212
+ 'select',
213
+ 'textarea',
214
+ 'label',
215
+ 'summary',
216
+ 'Button',
217
+ 'Input',
218
+ 'Select',
219
+ 'SelectTrigger',
220
+ 'SelectContent',
221
+ 'Textarea',
222
+ 'Badge',
223
+ 'Avatar',
224
+ 'AvatarFallback',
225
+ 'Switch',
226
+ 'Checkbox',
227
+ 'Progress',
228
+ 'Slider',
229
+ 'Toggle',
230
+ 'ToggleGroup',
231
+ 'ToggleGroupItem',
232
+ 'TabsList',
233
+ 'TabsTrigger',
234
+ 'Skeleton',
235
+ 'Tooltip',
236
+ 'TooltipContent',
237
+ 'DropdownMenuContent',
238
+ 'PopoverContent',
239
+ ]);
240
+ const RADIUS_CLASS = /(?:^|[\s'"`])rounded(?:-[a-z0-9[\]().\-/]+)?(?=$|[\s'"`])/;
241
+ const BORDER_CLASS = /(?:^|[\s'"`])border(?:-[a-z0-9[\]().\-/]+)?(?=$|[\s'"`])/;
242
+ const BG_CLASS = /(?:^|[\s'"`])(?:bg-[a-z0-9[\]().\-/]+|glass-card|neon-card|card-surface)(?=$|[\s'"`])/;
243
+ /**
244
+ * Composite classes that are a WHOLE card surface on their own.
245
+ *
246
+ * BSU's `.glass-card` (business-suite-unified/src/index.css:760) declares
247
+ * `background-color` AND `border: 1px solid` AND a shadow. `glass-card
248
+ * rounded-xl` is therefore already border + radius + background — the full
249
+ * double frame — while carrying no `border-*` utility for a class matcher to
250
+ * find. Requiring three separate Tailwind utilities makes every composite-class
251
+ * card invisible; BSU `Government.tsx` is exactly that shape.
252
+ */
253
+ const COMPOSITE_CARD_CLASS = /(?:^|[\s'"`])(?:glass-card|neon-card|card-surface)(?=$|[\s'"`])/;
254
+ const RADIUS_STYLE = /\bborder-?[Rr]adius\b/;
255
+ const BORDER_STYLE = /\bborder(?:Color|Width|Style)?\s*:/;
256
+ const BG_STYLE = /\b(?:background|backgroundColor|backgroundImage)\s*:/;
257
+ /**
258
+ * Every opening tag in a JSX body, with its raw attribute text.
259
+ *
260
+ * Hand-rolled rather than regex-only because an attribute value can contain
261
+ * `>` inside a string, a template literal or a `{…}` expression — three of the
262
+ * five hand-rolled copies this module replaced were defeated by exactly that.
263
+ */
264
+ export function openingTags(body) {
265
+ const out = [];
266
+ for (let i = 0; i < body.length; i++) {
267
+ if (body[i] !== '<')
268
+ continue;
269
+ const nameMatch = /^<([A-Za-z][A-Za-z0-9._-]*)/.exec(body.slice(i, i + 64));
270
+ if (!nameMatch)
271
+ continue;
272
+ let j = i + nameMatch[0].length;
273
+ let depth = 0;
274
+ let quote = null;
275
+ let closed = false;
276
+ for (; j < body.length; j++) {
277
+ const c = body[j];
278
+ if (quote) {
279
+ if (c === quote && body[j - 1] !== '\\')
280
+ quote = null;
281
+ continue;
282
+ }
283
+ if (c === '"' || c === "'" || c === '`') {
284
+ quote = c;
285
+ continue;
286
+ }
287
+ if (c === '{')
288
+ depth++;
289
+ else if (c === '}')
290
+ depth--;
291
+ else if (c === '>' && depth === 0) {
292
+ closed = true;
293
+ break;
294
+ }
295
+ }
296
+ if (!closed)
297
+ continue;
298
+ out.push({ tag: nameMatch[1], attrs: body.slice(i + nameMatch[0].length, j) });
299
+ i = j;
300
+ }
301
+ return out;
302
+ }
303
+ /** Every className value on one element — string, template literal or `cn(...)`. */
304
+ function classValues(attrs) {
305
+ const out = [];
306
+ const re = /class(?:Name)?\s*=\s*(?:"([^"]*)"|'([^']*)'|\{([\s\S]*)\})/;
307
+ const m = re.exec(attrs);
308
+ if (!m)
309
+ return out;
310
+ if (m[1] !== undefined)
311
+ out.push(m[1]);
312
+ else if (m[2] !== undefined)
313
+ out.push(m[2]);
314
+ else if (m[3] !== undefined) {
315
+ // `{cn('a', cond && 'b')}` / `{`a ${x}`}` — take every literal inside.
316
+ const lit = /(?:"([^"]*)"|'([^']*)'|`([^`]*)`)/g;
317
+ let l;
318
+ while ((l = lit.exec(m[3])) !== null)
319
+ out.push(l[1] ?? l[2] ?? l[3] ?? '');
320
+ }
321
+ return out;
322
+ }
323
+ /** The raw text of an inline `style={{ … }}` attribute, if present. */
324
+ function styleValue(attrs) {
325
+ const i = attrs.indexOf('style');
326
+ if (i < 0)
327
+ return null;
328
+ const m = /style\s*=\s*\{/.exec(attrs.slice(i));
329
+ if (!m)
330
+ return null;
331
+ let depth = 0;
332
+ const start = i + m.index + m[0].length - 1;
333
+ for (let j = start; j < attrs.length; j++) {
334
+ if (attrs[j] === '{')
335
+ depth++;
336
+ else if (attrs[j] === '}') {
337
+ depth--;
338
+ if (depth === 0)
339
+ return attrs.slice(start, j + 1);
340
+ }
341
+ }
342
+ return null;
343
+ }
344
+ /**
345
+ * Does this element paint its OWN card chrome?
346
+ *
347
+ * Chrome means all three of border, radius and background, because that is
348
+ * exactly what `PageGridLayout` already paints on the slot. Two of the three is
349
+ * a tinted panel or a divider, not a second card — requiring all three is what
350
+ * separates BSU's `glass-card rounded-2xl border-primary/30` (a real double
351
+ * frame) from a `rounded-lg bg-muted` inline chip (not one).
352
+ *
353
+ * Chrome declared through `style={{ background, border, borderRadius }}` counts
354
+ * the same as chrome declared through classes. BSU's `Settings.tsx` is chrome
355
+ * entirely in inline style; a class-only detector calls that file clean, which
356
+ * is how a nested card hides from a gate that only reads Tailwind.
357
+ */
358
+ export function elementDeclaresCardChrome(el, chromeTags) {
359
+ if (chromeTags.has(el.tag))
360
+ return `<${el.tag}> paints its own card chrome`;
361
+ if (CONTROL_TAGS.has(el.tag))
362
+ return null;
363
+ for (const value of classValues(el.attrs)) {
364
+ const composite = COMPOSITE_CARD_CLASS.test(value);
365
+ const hasBorder = composite || BORDER_CLASS.test(value);
366
+ const hasBg = composite || BG_CLASS.test(value);
367
+ if (RADIUS_CLASS.test(value) && hasBorder && hasBg)
368
+ return `<${el.tag}> className declares border + radius + background ("${value.replace(/\s+/g, ' ').trim().slice(0, 80)}")`;
369
+ }
370
+ const style = styleValue(el.attrs);
371
+ if (style && RADIUS_STYLE.test(style) && BORDER_STYLE.test(style) && BG_STYLE.test(style))
372
+ return `<${el.tag}> inline style declares border + radius + background`;
373
+ // Mixed: radius as a class, border+background as inline style. BSU
374
+ // `Settings.tsx` is exactly this shape.
375
+ if (style) {
376
+ const classText = classValues(el.attrs).join(' ');
377
+ const composite = COMPOSITE_CARD_CLASS.test(classText);
378
+ const hasRadius = RADIUS_CLASS.test(classText) || RADIUS_STYLE.test(style);
379
+ const hasBorder = composite || BORDER_CLASS.test(classText) || BORDER_STYLE.test(style);
380
+ const hasBg = composite || BG_CLASS.test(classText) || BG_STYLE.test(style);
381
+ if (hasRadius && hasBorder && hasBg)
382
+ return `<${el.tag}> declares border + radius + background across className and inline style`;
383
+ }
384
+ return null;
385
+ }
386
+ /**
387
+ * Does this grid slot paint chrome of its OWN, post-inversion?
388
+ *
389
+ * Three ways to opt in, and all three have to be visible to the scanner or a
390
+ * re-chromed slot goes unnoticed: `itemChrome` on the grid component (whole
391
+ * app/page), `chrome: true` on the layout item, and `chrome` on the CanvasCard.
392
+ */
393
+ export function slotOptsIntoChrome(fileSource, slotBody) {
394
+ const openTag = /^<CanvasCard[\s\S]*?>/.exec(slotBody)?.[0] ?? '';
395
+ if (/\bchrome\s*(?:=\s*\{?\s*true\b|\}|[\s/>])/.test(openTag) &&
396
+ !/\bchrome\s*=\s*\{\s*false\s*\}/.test(openTag))
397
+ return true;
398
+ if (/\bitemChrome\b(?!\s*=\s*\{\s*false\s*\})/.test(fileSource))
399
+ return true;
400
+ if (/\bchrome\s*:\s*true\b/.test(fileSource))
401
+ return true;
402
+ return false;
403
+ }
404
+ /** The first nested-chrome element inside one grid slot, or null. */
405
+ export function findNestedChrome(slotBody, config) {
406
+ const chromeTags = new Set([
407
+ ...config.cardTags,
408
+ ...(config.nestedChromeTags ?? DEFAULT_NESTED_CHROME_TAGS),
409
+ ]);
410
+ // Skip the slot's own opening tag — `<CanvasCard>` is the grid item, not a
411
+ // child of it.
412
+ const inner = slotBody.replace(/^<CanvasCard[\s\S]*?>/, '');
413
+ for (const el of openingTags(inner)) {
414
+ const hit = elementDeclaresCardChrome(el, chromeTags);
415
+ if (hit)
416
+ return hit;
417
+ }
418
+ return null;
419
+ }
420
+ /**
421
+ * Can this file be parsed with confidence?
422
+ *
423
+ * Returns a reason when it CANNOT. Every `<CanvasCard` must pair with a
424
+ * `</CanvasCard>` the block regex can reach, and every `widgets={{` must close
425
+ * before EOF. A file that fails either is UNKNOWN — it is not reported clean,
426
+ * and it is not silently skipped. "Checked nothing" and "found nothing" do not
427
+ * share an exit code here.
428
+ */
429
+ export function parseConfidence(src) {
430
+ const opens = (src.match(/<CanvasCard[\s/>]/g) ?? []).length;
431
+ const selfClosing = (src.match(/<CanvasCard[^<>]*\/>/g) ?? []).length;
432
+ const closes = (src.match(/<\/CanvasCard>/g) ?? []).length;
433
+ if (opens - selfClosing !== closes)
434
+ return `unbalanced CanvasCard tags: ${opens} opening (${selfClosing} self-closing) vs ${closes} closing`;
435
+ const blocks = extractCanvasCardBlocks(src).length;
436
+ if (blocks !== closes)
437
+ return `CanvasCard block extraction recovered ${blocks} of ${closes} blocks (nested or dynamically composed CanvasCards)`;
438
+ const widgetStarts = (src.match(/widgets=\{\{/g) ?? []).length;
439
+ if (widgetStarts > 0) {
440
+ const re = /widgets=\{\{/g;
441
+ let m;
442
+ while ((m = re.exec(src)) !== null) {
443
+ let depth = 2;
444
+ let i = m.index + m[0].length;
445
+ while (i < src.length && depth > 0) {
446
+ if (src[i] === '{')
447
+ depth++;
448
+ else if (src[i] === '}')
449
+ depth--;
450
+ i++;
451
+ }
452
+ if (depth !== 0)
453
+ return 'widgets={{ … }} object literal never closes before EOF';
454
+ }
455
+ }
456
+ return null;
457
+ }
162
458
  function walk(dir, extensions, acc) {
163
459
  for (const entry of readdirSync(dir)) {
164
460
  if (entry === 'node_modules' || entry === 'dist' || entry === '.git')
@@ -177,6 +473,7 @@ export function scanCardSurfaces(config) {
177
473
  const findings = [];
178
474
  const files = [];
179
475
  const scanRootsResolved = [];
476
+ const unknownFiles = [];
180
477
  // D-92: assert the inputs were present BEFORE reporting any verdict. A
181
478
  // missing scan root must fail loudly, not produce a confident zero.
182
479
  for (const root of config.scanRoots) {
@@ -216,14 +513,53 @@ export function scanCardSurfaces(config) {
216
513
  }
217
514
  for (const file of files) {
218
515
  const rel = relative(config.projectRoot, file);
219
- const raw = readFileSync(file, 'utf8');
516
+ let raw;
517
+ try {
518
+ raw = readFileSync(file, 'utf8');
519
+ }
520
+ catch (err) {
521
+ // A file we could not READ is UNKNOWN, never clean.
522
+ unknownFiles.push(rel);
523
+ findings.push({
524
+ file: rel,
525
+ idiom: 'unparseable',
526
+ detail: `could not be read: ${err.message}`,
527
+ });
528
+ continue;
529
+ }
220
530
  const src = stripComments(raw);
531
+ // D-92 fail-closed: decide whether this file can be parsed with confidence
532
+ // BEFORE reporting any verdict about it. An UNKNOWN file is recorded as
533
+ // UNKNOWN and still scanned on a best-effort basis — what it must never do
534
+ // is contribute a silent "clean".
535
+ const unparseable = parseConfidence(src);
536
+ if (unparseable) {
537
+ unknownFiles.push(rel);
538
+ findings.push({ file: rel, idiom: 'unparseable', detail: unparseable });
539
+ }
221
540
  // --- glued widget: 2+ cards inside ONE grid slot -----------------------
222
541
  const slots = [
223
542
  ...extractCanvasCardBlocks(src).map((b, i) => ({ label: `CanvasCard#${i + 1}`, body: b })),
224
543
  ...extractWidgetEntries(src).map((e) => ({ label: `widgets.${e.key}`, body: e.body })),
225
544
  ];
545
+ let nestedChromeReported = false;
226
546
  for (const slot of slots) {
547
+ // --- V-C5 nested chrome: ONE card inside ONE slot is still a double
548
+ // frame, and V-C4 below cannot see it (it needs 2+).
549
+ const gridItemChromed = (config.gridItemPaintsChrome ?? true) || slotOptsIntoChrome(src, slot.body);
550
+ if (gridItemChromed && !nestedChromeReported && !config.nestedChromeExclusions?.[rel]) {
551
+ const chrome = findNestedChrome(slot.body, config);
552
+ if (chrome) {
553
+ nestedChromeReported = true;
554
+ findings.push({
555
+ file: rel,
556
+ idiom: 'nested-chrome',
557
+ detail: `${slot.label} ${chrome}. The grid item already paints ` +
558
+ `rounded-3xl + bg-card + border-border, so this renders a card inside a card — ` +
559
+ `mismatched corners and a doubled 1px edge.`,
560
+ });
561
+ }
562
+ }
227
563
  const n = countCardTags(slot.body, config);
228
564
  const mapped = hasMappedCards(slot.body, config);
229
565
  if (n > 1 || mapped) {
@@ -280,10 +616,23 @@ export function scanCardSurfaces(config) {
280
616
  ...Object.keys(config.gluedExclusions ?? {}).filter((f) => !hit.has(`glued-widget:${f}`) && !hit.has(`autoheight-optout:${f}`)),
281
617
  ...Object.keys(config.ungriddedExclusions ?? {}).filter((f) => !hit.has(`ungridded-multi-card:${f}`)),
282
618
  ];
619
+ const nestedChromeFiles = [
620
+ ...new Set(findings.filter((f) => f.idiom === 'nested-chrome').map((f) => f.file)),
621
+ ];
283
622
  const summary = `scanned ${files.length} files across ${scanRootsResolved.length} root(s) [${scanRootsResolved.join(', ')}] ` +
284
623
  `with cardTags [${config.cardTags.join(', ')}]` +
285
624
  `${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 };
625
+ `${findings.length} finding(s) incl. ${nestedChromeFiles.length} nested-chrome file(s); ` +
626
+ `${Object.keys(config.blindSpots ?? {}).length} declared blind spot(s); ` +
627
+ `${staleExclusions.length} stale exclusion(s); ` +
628
+ `${unknownFiles.length} UNKNOWN file(s) — an UNKNOWN is not a clean file.`;
629
+ return {
630
+ findings,
631
+ filesScanned: files.length,
632
+ scanRootsResolved,
633
+ staleExclusions,
634
+ unknownFiles,
635
+ nestedChromeFiles,
636
+ summary,
637
+ };
289
638
  }
@@ -1,3 +1,5 @@
1
- export { scanCardSurfaces, stripComments } from './cardSurfaceScanner.js';
1
+ export { scanCardSurfaces, stripComments, openingTags, elementDeclaresCardChrome, findNestedChrome, parseConfidence, slotOptsIntoChrome, } from './cardSurfaceScanner.js';
2
2
  export type { CardSurfaceScannerConfig, CardSurfaceScanResult, CardSurfaceFinding, CardSurfaceIdiom, } from './cardSurfaceScanner.js';
3
+ export { scanCardHeadings, jsxTags } from './cardHeadingScanner.js';
4
+ export type { CardHeadingScannerConfig, CardHeadingScanResult, CardHeadingFinding, } from './cardHeadingScanner.js';
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,GACnB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACpE,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,yBAAyB,CAAC"}
@@ -1 +1,2 @@
1
- export { scanCardSurfaces, stripComments } from './cardSurfaceScanner.js';
1
+ export { scanCardSurfaces, stripComments, openingTags, elementDeclaresCardChrome, findNestedChrome, parseConfidence, slotOptsIntoChrome, } from './cardSurfaceScanner.js';
2
+ export { scanCardHeadings, jsxTags } from './cardHeadingScanner.js';
package/dist/types.d.ts CHANGED
@@ -15,6 +15,17 @@ export interface GridLayoutItem extends LayoutItem {
15
15
  * operator-mandated capability. See the `activeLayouts` memo.
16
16
  */
17
17
  autoHeight?: boolean;
18
+ /**
19
+ * Paint THIS item as a card — border, radius, background, shadow.
20
+ *
21
+ * Undefined falls back to `PageGridLayout`'s `itemChrome`, which is FALSE.
22
+ * Up to 1.0.7 every grid item painted chrome unconditionally and there was
23
+ * no way to turn it off; 332 files across six apps render their own card
24
+ * inside it. Set this true on a slot whose content is BARE — a heading, a
25
+ * chart, a list with no surface of its own — and leave it alone everywhere
26
+ * the content already is a card.
27
+ */
28
+ chrome?: boolean;
18
29
  /**
19
30
  * True once the user has resized this item with the SE handle.
20
31
  *
@@ -147,6 +158,15 @@ export interface PageGridLayoutProps extends UsePageGridLayoutOptions {
147
158
  widgetMeta?: Record<string, WidgetMeta>;
148
159
  className?: string;
149
160
  isResizable?: boolean;
161
+ /**
162
+ * Paint every grid item as a card unless the item says otherwise.
163
+ *
164
+ * DEFAULT FALSE. This is the app-level migration lever for the 2.0.0 chrome
165
+ * inversion: an app that has not yet migrated its bare slots passes
166
+ * `itemChrome` and gets the pre-2.0.0 look back exactly, then flips slot by
167
+ * slot with `GridLayoutItem.chrome`. Per-item always wins.
168
+ */
169
+ itemChrome?: boolean;
150
170
  resizeHandles?: readonly ResizeHandleAxis[];
151
171
  /**
152
172
  * The signed-in caller's tenant. Threaded into every widget-factory call
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -27,10 +27,17 @@ export declare const PAGE_GRID_EDITING_EVENT = "bsuite-page-grid-editing";
27
27
  * was additionally polluted with frozen derived breakpoints, so all of them
28
28
  * reset once to the corrected defaults.
29
29
  *
30
+ * 1000 -> 2000 (2026-08-25, V-C5/G1): two more all-grids defaults changed in
31
+ * one release — the grid item no longer paints card chrome, and a `CanvasCard`
32
+ * that omits `w` is now half the grid rather than all of it. Every stored
33
+ * layout was written under the old width default, so a saved `w: 12` would
34
+ * fight the new default forever and the page would keep stacking. An epoch
35
+ * bump is the only lever that reaches every consumer at once.
36
+ *
30
37
  * Per-page `layoutVersion` bumps keep working on top; this only moves the
31
38
  * floor.
32
39
  */
33
- export declare const PACKAGE_LAYOUT_EPOCH = 1000;
40
+ export declare const PACKAGE_LAYOUT_EPOCH = 2000;
34
41
  export interface PageGridEditingEventDetail {
35
42
  pageKey: string;
36
43
  editing: boolean;
@@ -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,CA2sBpD"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;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,CA2sBpD"}
@@ -37,10 +37,17 @@ export const PAGE_GRID_EDITING_EVENT = 'bsuite-page-grid-editing';
37
37
  * was additionally polluted with frozen derived breakpoints, so all of them
38
38
  * reset once to the corrected defaults.
39
39
  *
40
+ * 1000 -> 2000 (2026-08-25, V-C5/G1): two more all-grids defaults changed in
41
+ * one release — the grid item no longer paints card chrome, and a `CanvasCard`
42
+ * that omits `w` is now half the grid rather than all of it. Every stored
43
+ * layout was written under the old width default, so a saved `w: 12` would
44
+ * fight the new default forever and the page would keep stacking. An epoch
45
+ * bump is the only lever that reaches every consumer at once.
46
+ *
40
47
  * Per-page `layoutVersion` bumps keep working on top; this only moves the
41
48
  * floor.
42
49
  */
43
- export const PACKAGE_LAYOUT_EPOCH = 1000;
50
+ export const PACKAGE_LAYOUT_EPOCH = 2000;
44
51
  /**
45
52
  * Default for `GridLayoutItem.autoHeight` when an item does not state one.
46
53
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsuite/page-builder",
3
- "version": "1.0.7",
3
+ "version": "2.0.0",
4
4
  "description": "Shared BSuite responsive page-builder grid and layout persistence primitives",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",