@yschimke/compose-design-map 1.53.0 → 1.54.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/README.md +17 -0
- package/design-map.mjs +89 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -156,6 +156,23 @@ one-to-one onto distinct device widths are a size axis and one of them can be pi
|
|
|
156
156
|
- the sizes the base did not take **fold under it as cells**, seeded `breakpoint=<dp>` and named
|
|
157
157
|
`<dp>dp`, so they are published rather than discarded.
|
|
158
158
|
|
|
159
|
+
A bare `breakpoint=<dp>` is a value no kit vocabulary contains, so such a cell resolves against
|
|
160
|
+
nothing — correctly, for the majority of kits, which draw every screen cell at one size and have no
|
|
161
|
+
size axis at all. Where a kit *does* publish screen size as a variant property, the component says
|
|
162
|
+
so:
|
|
163
|
+
|
|
164
|
+
```kotlin
|
|
165
|
+
@CatalogComponent(id = "Picker", breakpointKit = ["225=Larger Screen (BP)=Yes"])
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
and the 225dp cell is seeded `breakpoint=225` with `kitAxis`/`kitValue` attached, pairing with the
|
|
169
|
+
kit node the picture was always there for. It is a per-component declaration rather than a
|
|
170
|
+
per-run flag because it is a property of one component's kit set, not of the catalog; a size the
|
|
171
|
+
component never draws, or a malformed entry, keeps the bare seed and is reported unresolved rather
|
|
172
|
+
than mispaired. A breakpoint capture is the one kind of cell that cannot carry `@OverrideVariant
|
|
173
|
+
(kitAxis = …)` itself — it is not an annotation at all — which is why the mapping lives on the
|
|
174
|
+
component.
|
|
175
|
+
|
|
159
176
|
Two captures of the *same* width are still a mode, whatever devices they name: nothing orders them,
|
|
160
177
|
so they stay `ambiguousMode`. An `@OverrideVariant` cell rides the base breakpoint only — the
|
|
161
178
|
product of both axes would multiply the sheet by every size, and the base carries the matrix.
|
package/design-map.mjs
CHANGED
|
@@ -503,7 +503,61 @@ export function declarationMisses(preview) {
|
|
|
503
503
|
* this projection, which is why a FAB size axis read as unauthored while `FabSmall`/`FabMedium`/
|
|
504
504
|
* `FabLarge` sat in the catalog all along.
|
|
505
505
|
*/
|
|
506
|
-
|
|
506
|
+
/**
|
|
507
|
+
* The kit axis/value a component declares for a non-base breakpoint width, or `null`.
|
|
508
|
+
*
|
|
509
|
+
* [entries] are `@CatalogComponent.breakpointKit` strings, `"<widthDp>=<kitAxis>=<kitValue>"`. The
|
|
510
|
+
* `kitValue` half may itself contain `=` (a kit is free to name a cell `Size=Large`), so the split
|
|
511
|
+
* is on the FIRST TWO separators only — `String.split("=")` with a limit would drop the tail.
|
|
512
|
+
*
|
|
513
|
+
* A malformed entry, a non-numeric width or a width this component never renders yields `null`,
|
|
514
|
+
* which restores the bare `breakpoint=<width>` seed. That is the honest degradation — a mistyped
|
|
515
|
+
* mapping should cost the pairing, not silently pair the render against the wrong kit cell — but
|
|
516
|
+
* it must not be *silent*: degrading quietly leaves a typo indistinguishable from a deliberately
|
|
517
|
+
* undeclared mapping, and the only symptom is a generic pairing miss much further downstream. So
|
|
518
|
+
* a malformed entry is pushed onto [malformed] and reported as `diagnostics.invalidBreakpointKit`,
|
|
519
|
+
* the same way an unresolvable mode is reported rather than guessed at.
|
|
520
|
+
*
|
|
521
|
+
* "Malformed" is only about the entry's *shape*. An entry that is well-formed but names a width
|
|
522
|
+
* this particular capture is not — the common case, since one declaration serves every size — is
|
|
523
|
+
* not a fault and is not reported.
|
|
524
|
+
*/
|
|
525
|
+
export function breakpointKitNames(entries, widthDp, malformed = []) {
|
|
526
|
+
for (const entry of entries ?? []) {
|
|
527
|
+
if (typeof entry !== "string") {
|
|
528
|
+
malformed.push({ entry: String(entry), reason: "not a string" });
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
const firstEq = entry.indexOf("=");
|
|
532
|
+
const secondEq = firstEq < 0 ? -1 : entry.indexOf("=", firstEq + 1);
|
|
533
|
+
if (secondEq < 0) {
|
|
534
|
+
malformed.push({ entry, reason: "expected <widthDp>=<kitAxis>=<kitValue>" });
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
const rawWidth = entry.slice(0, firstEq).trim();
|
|
538
|
+
const width = Number(rawWidth);
|
|
539
|
+
if (rawWidth === "" || !Number.isFinite(width)) {
|
|
540
|
+
malformed.push({ entry, reason: `width '${rawWidth}' is not a number` });
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
const kitAxis = entry.slice(firstEq + 1, secondEq).trim();
|
|
544
|
+
const kitValue = entry.slice(secondEq + 1).trim();
|
|
545
|
+
if (!kitAxis || !kitValue) {
|
|
546
|
+
malformed.push({ entry, reason: "kitAxis and kitValue must both be non-empty" });
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
// Well-formed but for another size: not a fault, and the overwhelmingly common case.
|
|
550
|
+
if (width !== widthDp) continue;
|
|
551
|
+
return { kitAxis, kitValue };
|
|
552
|
+
}
|
|
553
|
+
return null;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
export function variantRendersByComponent(
|
|
557
|
+
previews,
|
|
558
|
+
selection = selectCaptures(previews),
|
|
559
|
+
invalidBreakpointKit = [],
|
|
560
|
+
) {
|
|
507
561
|
const byComponent = new Map();
|
|
508
562
|
for (const preview of previews) {
|
|
509
563
|
const catalog = preview.catalog;
|
|
@@ -535,7 +589,28 @@ export function variantRendersByComponent(previews, selection = selectCaptures(p
|
|
|
535
589
|
if (!isOverrideVariant && !isCatalogVariant) {
|
|
536
590
|
const widthDp = catalog.role === "COMPONENT" ? selection.breakpointOf(preview) : null;
|
|
537
591
|
if (widthDp === null) continue;
|
|
538
|
-
|
|
592
|
+
// `@CatalogComponent(breakpointKit = ["225=Larger Screen (BP)=Yes"])` says what this size
|
|
593
|
+
// MEANS to the kit. Without it the seed is a bare `breakpoint=225` — a value no kit
|
|
594
|
+
// vocabulary contains — and the resolver can only report "no counterpart for
|
|
595
|
+
// `breakpoint=225`", even where the kit publishes the very cells the render would pair with
|
|
596
|
+
// (issue #4827).
|
|
597
|
+
//
|
|
598
|
+
// Opt-in and per component, because most kits draw every screen cell at one size and have no
|
|
599
|
+
// size axis at all. Declaring nothing keeps the bare seed, so those captures stay honestly
|
|
600
|
+
// reported as renders with no kit counterpart rather than mispaired.
|
|
601
|
+
const malformed = [];
|
|
602
|
+
const kit = breakpointKitNames(catalog.breakpointKit, widthDp, malformed);
|
|
603
|
+
for (const bad of malformed) {
|
|
604
|
+
invalidBreakpointKit.push({ componentId: catalog.componentId, ...bad });
|
|
605
|
+
}
|
|
606
|
+
const seeds = [
|
|
607
|
+
{
|
|
608
|
+
key: "breakpoint",
|
|
609
|
+
raw: String(widthDp),
|
|
610
|
+
...(kit?.kitAxis ? { kitAxis: kit.kitAxis } : {}),
|
|
611
|
+
...(kit?.kitValue ? { kitValue: kit.kitValue } : {}),
|
|
612
|
+
},
|
|
613
|
+
];
|
|
539
614
|
const list = byComponent.get(catalog.componentId) ?? [];
|
|
540
615
|
list.push({ previewId: preview.id, name: `${widthDp}dp`, seeds });
|
|
541
616
|
byComponent.set(catalog.componentId, list);
|
|
@@ -587,7 +662,8 @@ export function variantRendersByComponent(previews, selection = selectCaptures(p
|
|
|
587
662
|
*/
|
|
588
663
|
export function projectDesignMap(previews, opts = {}) {
|
|
589
664
|
const selection = selectCaptures(previews, { baseBreakpointDp: opts.baseBreakpointDp });
|
|
590
|
-
const
|
|
665
|
+
const invalidBreakpointKit = [];
|
|
666
|
+
const variantRenders = variantRendersByComponent(previews, selection, invalidBreakpointKit);
|
|
591
667
|
|
|
592
668
|
const components = [];
|
|
593
669
|
const declarations = [];
|
|
@@ -752,6 +828,16 @@ export function projectDesignMap(previews, opts = {}) {
|
|
|
752
828
|
!referencelessSubjects.has(a.subject) &&
|
|
753
829
|
(!a.componentIds.length || a.componentIds.some((id) => !referencelessIds.has(id))),
|
|
754
830
|
),
|
|
831
|
+
// `@CatalogComponent(breakpointKit = …)` entries that do not parse. Reported rather than
|
|
832
|
+
// dropped: the degradation is to the bare `breakpoint=<dp>` seed, which is exactly what an
|
|
833
|
+
// undeclared component produces, so a typo would otherwise be invisible until someone
|
|
834
|
+
// wondered why a kit cell never paired. Deduplicated — one declaration is re-read once per
|
|
835
|
+
// non-base capture of the component, and the same typo is one fault, not four.
|
|
836
|
+
invalidBreakpointKit: [
|
|
837
|
+
...new Map(
|
|
838
|
+
invalidBreakpointKit.map((e) => [`${e.componentId}\u0000${e.entry}`, e]),
|
|
839
|
+
).values(),
|
|
840
|
+
],
|
|
755
841
|
variantRenders: declarations.reduce((n, d) => n + d.renders.length, 0),
|
|
756
842
|
withSet: components.filter((c) => c.refSet).length,
|
|
757
843
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yschimke/compose-design-map",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.54.0",
|
|
4
4
|
"description": "Project a compose-preview discovery manifest into design-parity's design-map.json, plus a sidecar of unresolved variant declarations. Dependency-free.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|