@multiplatform.one/theme 7.2.2 → 7.4.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/package.json +5 -5
- package/src/theme/Surface.spec.tsx +1 -1
- package/src/theme/createDefaultThemeConfig.spec.ts +5 -5
- package/src/theme/index.ts +1 -0
- package/src/theme/layoutTokens.spec.ts +3 -2
- package/src/theme/layoutTokens.ts +22 -10
- package/src/theme/mpo13Proof.spec.ts +149 -0
- package/src/theme/recipeInputs.ts +70 -30
- package/src/theme/resolveKnobs.spec.ts +5 -5
- package/src/theme/sizeRecipes.spec.ts +44 -42
- package/src/theme/sizeRecipes.ts +19 -5
- package/src/theme/tileSizes.spec.ts +139 -0
- package/src/theme/tileSizes.ts +291 -0
- package/types/theme/index.d.ts +1 -0
- package/types/theme/index.d.ts.map +1 -1
- package/types/theme/layoutTokens.d.ts +22 -10
- package/types/theme/layoutTokens.d.ts.map +1 -1
- package/types/theme/recipeInputs.d.ts +14 -4
- package/types/theme/recipeInputs.d.ts.map +1 -1
- package/types/theme/sizeRecipes.d.ts +9 -1
- package/types/theme/sizeRecipes.d.ts.map +1 -1
- package/types/theme/tileSizes.d.ts +139 -0
- package/types/theme/tileSizes.d.ts.map +1 -0
package/src/theme/sizeRecipes.ts
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* reserve it for non-enumerable values only. Do NOT put recipe tables on a
|
|
14
14
|
* `createStyledContext` primitive (`neverFlatten`).
|
|
15
15
|
*
|
|
16
|
-
* Reference md ($4 / $true): height
|
|
16
|
+
* Reference md ($4 / $true): height 44, padX 18, font 14, icon 16, gap 9
|
|
17
|
+
* (the measured tamagui.dev $4 control — MPO-13).
|
|
17
18
|
* `sizeToken` remains the recipe KEY (string "$4") so styled() variants
|
|
18
19
|
* can switch; it is not a height scalar.
|
|
19
20
|
*
|
|
@@ -110,11 +111,27 @@ export const SIZE_RECIPE_COMPACT_RATIOS = recipeFamilies.controlCompact.ratios;
|
|
|
110
111
|
|
|
111
112
|
export const SIZE_RECIPE_FAMILY_NAMES = ["control", "controlCompact"] as const;
|
|
112
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Live tile-size ladder (MPO-31) — generated from `inputs.tile` over the
|
|
116
|
+
* measured defaults, adopted in place on `setSizeRecipeInputs` like every
|
|
117
|
+
* other live table. Never handwrite rungs; restyle through inputs.
|
|
118
|
+
*/
|
|
119
|
+
export const tileSizeLadder = initial.tiles;
|
|
120
|
+
|
|
121
|
+
export function getTileSizeLadder(): typeof tileSizeLadder {
|
|
122
|
+
return tileSizeLadder;
|
|
123
|
+
}
|
|
124
|
+
|
|
113
125
|
function adoptGenerated(next: GeneratedSizeRecipes): GeneratedSizeRecipes {
|
|
114
126
|
adoptFamily(recipeFamilies.control, next.families.control);
|
|
115
127
|
adoptFamily(recipeFamilies.controlCompact, next.families.controlCompact);
|
|
128
|
+
replaceRecord(
|
|
129
|
+
tileSizeLadder as unknown as Record<string, unknown>,
|
|
130
|
+
next.tiles as unknown as Record<string, unknown>,
|
|
131
|
+
);
|
|
116
132
|
current = {
|
|
117
133
|
...next,
|
|
134
|
+
tiles: tileSizeLadder,
|
|
118
135
|
heights: SIZE_RECIPE_HEIGHTS,
|
|
119
136
|
heightsTouch: SIZE_RECIPE_HEIGHTS_TOUCH,
|
|
120
137
|
recipes: sizeRecipes,
|
|
@@ -167,10 +184,7 @@ export function applyTouchFloor(
|
|
|
167
184
|
(key) => tables.heights[key] === recipe.height,
|
|
168
185
|
);
|
|
169
186
|
if (token && tables.recipesTouch[token]) return tables.recipesTouch[token];
|
|
170
|
-
return recipeFromHeight(
|
|
171
|
-
Math.max(recipe.height, tables.inputs.touchFloor),
|
|
172
|
-
tables.ratios,
|
|
173
|
-
);
|
|
187
|
+
return recipeFromHeight(Math.max(recipe.height, tables.inputs.touchFloor), tables.ratios);
|
|
174
188
|
}
|
|
175
189
|
|
|
176
190
|
export function sizeRecipeForToken(
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { generateSizeRecipes } from "./recipeInputs";
|
|
3
|
+
import { getSizeRecipeInputs, setSizeRecipeInputs, tileSizeLadder } from "./sizeRecipes";
|
|
4
|
+
import {
|
|
5
|
+
defaultTileSizeInputs,
|
|
6
|
+
generateTileSizeLadder,
|
|
7
|
+
mediaAspectRatios,
|
|
8
|
+
resolveMediaAspect,
|
|
9
|
+
resolveTileSizeInputs,
|
|
10
|
+
tileColumnsForWidth,
|
|
11
|
+
tileRungFlexProps,
|
|
12
|
+
tileSizeRungs,
|
|
13
|
+
} from "./tileSizes";
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
setSizeRecipeInputs();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("tile-size ladder (MPO-31 H1)", () => {
|
|
20
|
+
it("defaults to the measured consumer ladders, not invented numbers", () => {
|
|
21
|
+
const ladder = generateTileSizeLadder(resolveTileSizeInputs());
|
|
22
|
+
// sm..xl are Lookout's TILE_SIZES basis/max (identical to the SPA's
|
|
23
|
+
// TILE_MIN); xs is the launcher icon-plate minmax(104px,1fr) track.
|
|
24
|
+
expect(ladder.sm).toEqual({ minWidth: 220, maxWidth: 300 });
|
|
25
|
+
expect(ladder.md).toEqual({ minWidth: 320, maxWidth: 440 });
|
|
26
|
+
expect(ladder.lg).toEqual({ minWidth: 480, maxWidth: 720 });
|
|
27
|
+
expect(ladder.xl).toEqual({ minWidth: 720, maxWidth: 1400 });
|
|
28
|
+
expect(ladder.xs.minWidth).toBe(104);
|
|
29
|
+
// xs has no measured max; it derives from maxRatio (440/320).
|
|
30
|
+
expect(ladder.xs.maxWidth).toBe(Math.round(104 * defaultTileSizeInputs.maxRatio));
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("is a generated table: rungs are monotonic and max >= min on every rung", () => {
|
|
34
|
+
const ladder = generateTileSizeLadder(resolveTileSizeInputs());
|
|
35
|
+
for (let i = 0; i < tileSizeRungs.length; i++) {
|
|
36
|
+
const stop = ladder[tileSizeRungs[i]];
|
|
37
|
+
expect(stop.maxWidth).toBeGreaterThanOrEqual(stop.minWidth);
|
|
38
|
+
if (i > 0) {
|
|
39
|
+
expect(stop.minWidth).toBeGreaterThan(ladder[tileSizeRungs[i - 1]].minWidth);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("a bare baseWidth override regenerates the whole ladder geometrically", () => {
|
|
45
|
+
const inputs = resolveTileSizeInputs({ baseWidth: 280 });
|
|
46
|
+
// Scaling override drops the measured pins (the resolveSizeRecipeInputs contract).
|
|
47
|
+
expect(inputs.rungWidths).toBeUndefined();
|
|
48
|
+
expect(inputs.widthFactors).toBeUndefined();
|
|
49
|
+
expect(inputs.rungMaxWidths).toBeUndefined();
|
|
50
|
+
const ladder = generateTileSizeLadder(inputs);
|
|
51
|
+
expect(ladder.md.minWidth).toBe(280);
|
|
52
|
+
expect(ladder.lg.minWidth).toBe(Math.round(280 * 1.5));
|
|
53
|
+
expect(ladder.xl.minWidth).toBe(Math.round(280 * 1.5 ** 2));
|
|
54
|
+
expect(ladder.sm.minWidth).toBe(Math.round(280 / 1.5));
|
|
55
|
+
expect(ladder.xs.minWidth).toBe(Math.round(280 / 1.5 ** 2));
|
|
56
|
+
for (const rung of tileSizeRungs) {
|
|
57
|
+
expect(ladder[rung].maxWidth).toBe(
|
|
58
|
+
Math.round(ladder[rung].minWidth * defaultTileSizeInputs.maxRatio),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("explicit rungMaxWidths pin maxes; maxRatio covers the rest", () => {
|
|
64
|
+
const ladder = generateTileSizeLadder(
|
|
65
|
+
resolveTileSizeInputs({ baseWidth: 300, maxRatio: 2, rungMaxWidths: { md: 555 } }),
|
|
66
|
+
);
|
|
67
|
+
expect(ladder.md).toEqual({ minWidth: 300, maxWidth: 555 });
|
|
68
|
+
expect(ladder.lg.maxWidth).toBe(ladder.lg.minWidth * 2);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("tileRungFlexProps is the wrapping-flex tile fragment (the Lookout idiom)", () => {
|
|
72
|
+
const ladder = generateTileSizeLadder(resolveTileSizeInputs());
|
|
73
|
+
expect(tileRungFlexProps(ladder.md)).toEqual({
|
|
74
|
+
flexGrow: 1,
|
|
75
|
+
flexBasis: 320,
|
|
76
|
+
minWidth: 320,
|
|
77
|
+
maxWidth: 440,
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("tileColumnsForWidth derives fixed-column counts from the rung and the gutter", () => {
|
|
82
|
+
const ladder = generateTileSizeLadder(resolveTileSizeInputs());
|
|
83
|
+
// A 1024 window at md with a 12px gutter fits 3 columns.
|
|
84
|
+
expect(tileColumnsForWidth(1024, ladder.md, 12)).toBe(3);
|
|
85
|
+
// xs at the launcher's own 8px gutter reproduces the springboard split:
|
|
86
|
+
// 6 columns at the 700px wide-breakpoint, 4 in the phone band.
|
|
87
|
+
expect(tileColumnsForWidth(700, ladder.xs, 8)).toBe(6);
|
|
88
|
+
expect(tileColumnsForWidth(500, ladder.xs, 8)).toBe(4);
|
|
89
|
+
// Never fewer than one column.
|
|
90
|
+
expect(tileColumnsForWidth(80, ladder.md)).toBe(1);
|
|
91
|
+
expect(tileColumnsForWidth(0, ladder.md)).toBe(1);
|
|
92
|
+
expect(tileColumnsForWidth(Number.NaN, ladder.md)).toBe(1);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("rides recipeInputs: generateSizeRecipes carries tiles and setSizeRecipeInputs rewrites the live ladder in place", () => {
|
|
96
|
+
expect(generateSizeRecipes().tiles.md).toEqual({ minWidth: 320, maxWidth: 440 });
|
|
97
|
+
|
|
98
|
+
const live = tileSizeLadder;
|
|
99
|
+
expect(live.md.minWidth).toBe(320);
|
|
100
|
+
setSizeRecipeInputs({ tile: { baseWidth: 280 } });
|
|
101
|
+
// Same object identity (styled()-spread safety), new generated rows.
|
|
102
|
+
expect(tileSizeLadder).toBe(live);
|
|
103
|
+
expect(tileSizeLadder.md.minWidth).toBe(280);
|
|
104
|
+
expect(tileSizeLadder.lg.minWidth).toBe(420);
|
|
105
|
+
// The stored inputs round-trip through getSizeRecipeInputs.
|
|
106
|
+
expect(getSizeRecipeInputs().tile?.baseWidth).toBe(280);
|
|
107
|
+
|
|
108
|
+
setSizeRecipeInputs();
|
|
109
|
+
expect(tileSizeLadder.md).toEqual({ minWidth: 320, maxWidth: 440 });
|
|
110
|
+
expect(tileSizeLadder.sm).toEqual({ minWidth: 220, maxWidth: 300 });
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe("media aspect vocabulary (MPO-31 H2)", () => {
|
|
115
|
+
it("names resolve to their measured ratios", () => {
|
|
116
|
+
expect(resolveMediaAspect("square")).toBe(1);
|
|
117
|
+
expect(resolveMediaAspect("photo")).toBeCloseTo(4 / 3);
|
|
118
|
+
// The Lookout frame shape — desktop screen captures at 16:10.
|
|
119
|
+
expect(resolveMediaAspect("screen")).toBeCloseTo(1.6);
|
|
120
|
+
expect(resolveMediaAspect("video")).toBeCloseTo(16 / 9);
|
|
121
|
+
expect(resolveMediaAspect("portrait")).toBeCloseTo(3 / 4);
|
|
122
|
+
expect(Object.keys(mediaAspectRatios)).toEqual([
|
|
123
|
+
"square",
|
|
124
|
+
"photo",
|
|
125
|
+
"screen",
|
|
126
|
+
"video",
|
|
127
|
+
"portrait",
|
|
128
|
+
]);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("numbers pass through; nullish and junk fall back to square", () => {
|
|
132
|
+
expect(resolveMediaAspect(1.6)).toBe(1.6);
|
|
133
|
+
expect(resolveMediaAspect()).toBe(1);
|
|
134
|
+
expect(resolveMediaAspect(null)).toBe(1);
|
|
135
|
+
expect(resolveMediaAspect(0)).toBe(1);
|
|
136
|
+
expect(resolveMediaAspect(-2)).toBe(1);
|
|
137
|
+
expect(resolveMediaAspect(Number.POSITIVE_INFINITY)).toBe(1);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tile-size ladder + media-aspect vocabulary (MPO-31, design-system/12 D.3
|
|
3
|
+
* holes H1/H2).
|
|
4
|
+
*
|
|
5
|
+
* Every tile wall needs the same two decisions: HOW BIG is a tile (a small
|
|
6
|
+
* named ladder a person can pick from — the user-facing S/M/L/XL control)
|
|
7
|
+
* and WHAT SHAPE is its media (so the loading skeleton is the same shape as
|
|
8
|
+
* the image that replaces it). Before this module both were app-invented:
|
|
9
|
+
* the console's `launcherGeometry.ts` (03-our-surfaces.md DL-9) and
|
|
10
|
+
* Lookout's private `TILE_SIZES` were the same gap twice.
|
|
11
|
+
*
|
|
12
|
+
* Like the control-size recipes (LC-70 RECIPE-INPUTS), STORED INPUTS are the
|
|
13
|
+
* source of truth and the ladder table is DERIVED — never handwritten at a
|
|
14
|
+
* call site. The default rung values are the MEASURED ladders from the two
|
|
15
|
+
* real consumers, not invented numbers:
|
|
16
|
+
*
|
|
17
|
+
* | rung | minWidth | maxWidth | measured from |
|
|
18
|
+
* |------|----------|----------|------------------------------------------------|
|
|
19
|
+
* | xs | 104 | 143 | launcher icon-plate track `minmax(104px,1fr)` |
|
|
20
|
+
* | sm | 220 | 300 | Lookout `TILE_SIZES.s` / SPA `TILE_MIN.s` |
|
|
21
|
+
* | md | 320 | 440 | Lookout `TILE_SIZES.m` / SPA `TILE_MIN.m` |
|
|
22
|
+
* | lg | 480 | 720 | Lookout `TILE_SIZES.l` / SPA `TILE_MIN.l` |
|
|
23
|
+
* | xl | 720 | 1400 | Lookout `TILE_SIZES.xl` / SPA `TILE_MIN.xl` |
|
|
24
|
+
*
|
|
25
|
+
* `{ baseWidth: 280 }` (no rungWidths / widthFactors) regenerates the whole
|
|
26
|
+
* ladder geometrically from `baseWidth * stepRatio ** step`, the same
|
|
27
|
+
* override contract `resolveSizeRecipeInputs` gives `baseHeight`.
|
|
28
|
+
*
|
|
29
|
+
* OWNERSHIP (12-one-design.md Part B): the RUNGS are universal — generated
|
|
30
|
+
* here, restyled only through recipe inputs
|
|
31
|
+
* (`setSizeRecipeInputs({ tile })` / `createDefaultThemeConfig({ recipeInputs:
|
|
32
|
+
* { tile } })`). WHICH rung a surface shows is per-app (a prop, often
|
|
33
|
+
* persisted per user). Tile gutters stay on the space knob and tile rounding
|
|
34
|
+
* on the borderRadius knob — this module never emits a gap or a radius.
|
|
35
|
+
*
|
|
36
|
+
* DENSITY (LC-76): density moves SPACE only. A compact density steps the
|
|
37
|
+
* gutters between tiles (via the space knob) and must never re-rung the
|
|
38
|
+
* ladder — tile magnitude is content scale, not chrome scale, so nothing
|
|
39
|
+
* here reads the density knob.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
// ── Rungs ─────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
export const tileSizeRungs = ["xs", "sm", "md", "lg", "xl"] as const;
|
|
45
|
+
|
|
46
|
+
export type TileSizeRung = (typeof tileSizeRungs)[number];
|
|
47
|
+
|
|
48
|
+
/** One rung: the narrowest a tile may render, and the widest. */
|
|
49
|
+
export type TileSizeStop = {
|
|
50
|
+
minWidth: number;
|
|
51
|
+
maxWidth: number;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type TileSizeLadder = Record<TileSizeRung, TileSizeStop>;
|
|
55
|
+
|
|
56
|
+
// ── Inputs ────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
export type TileSizeInputs = {
|
|
59
|
+
/** Desktop px min-width of the `md` rung. */
|
|
60
|
+
baseWidth: number;
|
|
61
|
+
/** Rung-to-rung ratio when regenerating geometrically. */
|
|
62
|
+
stepRatio: number;
|
|
63
|
+
/** Exponent of each rung relative to `md` (0). */
|
|
64
|
+
rungSteps: Record<TileSizeRung, number>;
|
|
65
|
+
/**
|
|
66
|
+
* Absolute desktop px min-widths. When omitted, min-widths come from
|
|
67
|
+
* `baseWidth * stepRatio ** step` (or `widthFactors`).
|
|
68
|
+
*/
|
|
69
|
+
rungWidths?: Partial<Record<TileSizeRung, number>>;
|
|
70
|
+
/**
|
|
71
|
+
* Optional per-rung scale relative to `baseWidth`. Used only when
|
|
72
|
+
* `rungWidths` is omitted. Factors are `stepRatio ** exponent` otherwise.
|
|
73
|
+
*/
|
|
74
|
+
widthFactors?: Partial<Record<TileSizeRung, number>>;
|
|
75
|
+
/** maxWidth = minWidth * maxRatio for any rung `rungMaxWidths` does not pin. */
|
|
76
|
+
maxRatio: number;
|
|
77
|
+
/** Absolute desktop px max-widths (measured pins win over `maxRatio`). */
|
|
78
|
+
rungMaxWidths?: Partial<Record<TileSizeRung, number>>;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const tileSizeStepExponents: Record<TileSizeRung, number> = {
|
|
82
|
+
xs: -2,
|
|
83
|
+
sm: -1,
|
|
84
|
+
md: 0,
|
|
85
|
+
lg: 1,
|
|
86
|
+
xl: 2,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Measured min-widths: xs is the launcher/springboard icon-plate grid track
|
|
90
|
+
// (`minmax(104px,1fr)` — launcherGeometry.ts / traefik menu.go); sm..xl are
|
|
91
|
+
// Lookout's `TILE_SIZES` basis values, identical in the production SPA's
|
|
92
|
+
// `TILE_MIN` map. Kept explicit so adopting the ladder is a rendered no-op
|
|
93
|
+
// for both consumers.
|
|
94
|
+
const measuredRungWidths: Record<TileSizeRung, number> = {
|
|
95
|
+
xs: 104,
|
|
96
|
+
sm: 220,
|
|
97
|
+
md: 320,
|
|
98
|
+
lg: 480,
|
|
99
|
+
xl: 720,
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/** Lossless relative table: the measured 104/220/320/480/720 ramp at baseWidth 320. */
|
|
103
|
+
export const defaultWidthFactors: Record<TileSizeRung, number> = {
|
|
104
|
+
xs: 104 / 320,
|
|
105
|
+
sm: 220 / 320,
|
|
106
|
+
md: 1,
|
|
107
|
+
lg: 480 / 320,
|
|
108
|
+
xl: 720 / 320,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Measured max-widths (Lookout `TILE_SIZES` max). xl's 1.94x is the
|
|
112
|
+
// deliberate "one huge tile" rung; xs has no measured max (the launcher caps
|
|
113
|
+
// tiles by column count), so it derives from `maxRatio`.
|
|
114
|
+
const measuredRungMaxWidths: Partial<Record<TileSizeRung, number>> = {
|
|
115
|
+
sm: 300,
|
|
116
|
+
md: 440,
|
|
117
|
+
lg: 720,
|
|
118
|
+
xl: 1400,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export const defaultTileSizeInputs: TileSizeInputs = {
|
|
122
|
+
baseWidth: 320,
|
|
123
|
+
stepRatio: 1.5,
|
|
124
|
+
rungSteps: { ...tileSizeStepExponents },
|
|
125
|
+
rungWidths: { ...measuredRungWidths },
|
|
126
|
+
widthFactors: { ...defaultWidthFactors },
|
|
127
|
+
// Lookout md: 440/320. The measured sm (1.36) and lg (1.5) bracket it.
|
|
128
|
+
maxRatio: 440 / 320,
|
|
129
|
+
rungMaxWidths: { ...measuredRungMaxWidths },
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Deep copy that PRESERVES partiality: keys the caller never set stay
|
|
134
|
+
* unset, so a later `resolveTileSizeInputs` still sees them as defaults
|
|
135
|
+
* rather than explicit undefineds.
|
|
136
|
+
*/
|
|
137
|
+
export function cloneTileSizeInputs<T extends Partial<TileSizeInputs>>(inputs: T): T {
|
|
138
|
+
const clone = { ...inputs };
|
|
139
|
+
if (inputs.rungSteps) clone.rungSteps = { ...inputs.rungSteps };
|
|
140
|
+
if (inputs.rungWidths) clone.rungWidths = { ...inputs.rungWidths };
|
|
141
|
+
if (inputs.widthFactors) clone.widthFactors = { ...inputs.widthFactors };
|
|
142
|
+
if (inputs.rungMaxWidths) clone.rungMaxWidths = { ...inputs.rungMaxWidths };
|
|
143
|
+
return clone;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Fill defaults. `{ baseWidth: 280 }` (any scaling override without explicit
|
|
148
|
+
* tables) drops the measured rungWidths/widthFactors/rungMaxWidths so every
|
|
149
|
+
* rung regenerates from `stepRatio` — the `resolveSizeRecipeInputs` contract.
|
|
150
|
+
*/
|
|
151
|
+
export function resolveTileSizeInputs(partial: Partial<TileSizeInputs> = {}): TileSizeInputs {
|
|
152
|
+
const scalingOverride =
|
|
153
|
+
partial.baseWidth != null || partial.stepRatio != null || partial.rungSteps != null;
|
|
154
|
+
const hasRungWidths = Object.prototype.hasOwnProperty.call(partial, "rungWidths");
|
|
155
|
+
const hasWidthFactors = Object.prototype.hasOwnProperty.call(partial, "widthFactors");
|
|
156
|
+
const hasRungMaxWidths = Object.prototype.hasOwnProperty.call(partial, "rungMaxWidths");
|
|
157
|
+
|
|
158
|
+
const resolved: TileSizeInputs = {
|
|
159
|
+
baseWidth: partial.baseWidth ?? defaultTileSizeInputs.baseWidth,
|
|
160
|
+
stepRatio: partial.stepRatio ?? defaultTileSizeInputs.stepRatio,
|
|
161
|
+
rungSteps: { ...defaultTileSizeInputs.rungSteps, ...partial.rungSteps },
|
|
162
|
+
maxRatio: partial.maxRatio ?? defaultTileSizeInputs.maxRatio,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
if (hasRungWidths) {
|
|
166
|
+
resolved.rungWidths = partial.rungWidths ? { ...partial.rungWidths } : undefined;
|
|
167
|
+
if (hasWidthFactors) {
|
|
168
|
+
resolved.widthFactors = partial.widthFactors ? { ...partial.widthFactors } : undefined;
|
|
169
|
+
}
|
|
170
|
+
} else if (hasWidthFactors) {
|
|
171
|
+
resolved.widthFactors = partial.widthFactors ? { ...partial.widthFactors } : undefined;
|
|
172
|
+
} else if (!scalingOverride) {
|
|
173
|
+
resolved.rungWidths = { ...defaultTileSizeInputs.rungWidths };
|
|
174
|
+
resolved.widthFactors = { ...defaultTileSizeInputs.widthFactors };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (hasRungMaxWidths) {
|
|
178
|
+
resolved.rungMaxWidths = partial.rungMaxWidths ? { ...partial.rungMaxWidths } : undefined;
|
|
179
|
+
} else if (!scalingOverride && !hasRungWidths && !hasWidthFactors) {
|
|
180
|
+
resolved.rungMaxWidths = { ...defaultTileSizeInputs.rungMaxWidths };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return resolved;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ── Generation ────────────────────────────────────────────────
|
|
187
|
+
|
|
188
|
+
function clampWidth(value: number): number {
|
|
189
|
+
return Math.max(1, Math.round(value));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function minWidthForRung(rung: TileSizeRung, inputs: TileSizeInputs): number {
|
|
193
|
+
const explicitPx = inputs.rungWidths?.[rung];
|
|
194
|
+
if (explicitPx != null) return clampWidth(explicitPx);
|
|
195
|
+
const factor = inputs.widthFactors?.[rung];
|
|
196
|
+
if (factor != null) return clampWidth(inputs.baseWidth * factor);
|
|
197
|
+
const step = inputs.rungSteps[rung] ?? 0;
|
|
198
|
+
return clampWidth(inputs.baseWidth * inputs.stepRatio ** step);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Derive the full ladder from resolved inputs. Tables are generated, never handwritten. */
|
|
202
|
+
export function generateTileSizeLadder(inputs: TileSizeInputs): TileSizeLadder {
|
|
203
|
+
const ladder = {} as TileSizeLadder;
|
|
204
|
+
for (const rung of tileSizeRungs) {
|
|
205
|
+
const minWidth = minWidthForRung(rung, inputs);
|
|
206
|
+
const pinnedMax = inputs.rungMaxWidths?.[rung];
|
|
207
|
+
const maxWidth = Math.max(
|
|
208
|
+
minWidth,
|
|
209
|
+
pinnedMax != null ? clampWidth(pinnedMax) : clampWidth(minWidth * inputs.maxRatio),
|
|
210
|
+
);
|
|
211
|
+
ladder[rung] = { minWidth, maxWidth };
|
|
212
|
+
}
|
|
213
|
+
return ladder;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ── Consumption helpers ───────────────────────────────────────
|
|
217
|
+
|
|
218
|
+
export type TileRungFlexProps = {
|
|
219
|
+
flexGrow: number;
|
|
220
|
+
flexBasis: number;
|
|
221
|
+
minWidth: number;
|
|
222
|
+
maxWidth: number;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Style fragment for a tile in a wrapping flex wall (the Lookout idiom:
|
|
227
|
+
* tiles grow from `minWidth` and stop at `maxWidth`). Spread it on the tile
|
|
228
|
+
* surface; gutters stay on the container's space-knob gap.
|
|
229
|
+
*/
|
|
230
|
+
export function tileRungFlexProps(stop: TileSizeStop): TileRungFlexProps {
|
|
231
|
+
return {
|
|
232
|
+
flexGrow: 1,
|
|
233
|
+
flexBasis: stop.minWidth,
|
|
234
|
+
minWidth: stop.minWidth,
|
|
235
|
+
maxWidth: stop.maxWidth,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Column count for a fixed-column tile grid (the ImageGrid / springboard
|
|
241
|
+
* idiom): as many columns as fit at the rung's minWidth. `gutter` is the
|
|
242
|
+
* inter-column gap (the space knob's value), never baked into the rung.
|
|
243
|
+
*
|
|
244
|
+
* The count is min-driven on purpose: adding a column to honor `maxWidth`
|
|
245
|
+
* would, by construction of the fit, drop every cell below `minWidth`
|
|
246
|
+
* (`(fit+1)` cells at minWidth already overflow the width). `maxWidth`
|
|
247
|
+
* binds in the wrapping-flex idiom (`tileRungFlexProps`), where a tile can
|
|
248
|
+
* stop growing without forcing a new column.
|
|
249
|
+
*
|
|
250
|
+
* At the springboard's own numbers this reproduces the launcher's split:
|
|
251
|
+
* `xs` (104) with the 8px launcher gutter yields 6 columns at the 700px
|
|
252
|
+
* wide-breakpoint and 4 in the phone band.
|
|
253
|
+
*/
|
|
254
|
+
export function tileColumnsForWidth(width: number, stop: TileSizeStop, gutter = 0): number {
|
|
255
|
+
if (!Number.isFinite(width) || width <= 0) return 1;
|
|
256
|
+
return Math.max(1, Math.floor((width + gutter) / (stop.minWidth + gutter)));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// ── Media aspect (H2) ─────────────────────────────────────────
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Named media aspect ratios (width / height). A skeleton twin drawn at the
|
|
263
|
+
* wrong aspect produces the exact layout jump it exists to prevent
|
|
264
|
+
* (ImageGrid hardcoded 1; Lookout frames are 16:10).
|
|
265
|
+
*/
|
|
266
|
+
export const mediaAspectRatios = {
|
|
267
|
+
/** Album art, avatars, icon plates. */
|
|
268
|
+
square: 1,
|
|
269
|
+
/** Stills cameras, 4:3. */
|
|
270
|
+
photo: 4 / 3,
|
|
271
|
+
/** Desktop screen captures, 16:10 — the Lookout frame shape. */
|
|
272
|
+
screen: 16 / 10,
|
|
273
|
+
/** Video stills, 16:9. */
|
|
274
|
+
video: 16 / 9,
|
|
275
|
+
/** Portrait media, 3:4. */
|
|
276
|
+
portrait: 3 / 4,
|
|
277
|
+
} as const;
|
|
278
|
+
|
|
279
|
+
export type MediaAspectName = keyof typeof mediaAspectRatios;
|
|
280
|
+
|
|
281
|
+
/** A named aspect or an explicit width/height number. */
|
|
282
|
+
export type MediaAspect = MediaAspectName | number;
|
|
283
|
+
|
|
284
|
+
/** Resolve a name or number to a positive width/height ratio (default `square`). */
|
|
285
|
+
export function resolveMediaAspect(aspect?: MediaAspect | null): number {
|
|
286
|
+
if (typeof aspect === "number") {
|
|
287
|
+
return Number.isFinite(aspect) && aspect > 0 ? aspect : mediaAspectRatios.square;
|
|
288
|
+
}
|
|
289
|
+
if (aspect != null && aspect in mediaAspectRatios) return mediaAspectRatios[aspect];
|
|
290
|
+
return mediaAspectRatios.square;
|
|
291
|
+
}
|
package/types/theme/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,YAAY,EAAE,MAAM,IAAI,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACjF,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,YAAY,EAAE,MAAM,IAAI,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACjF,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAE5B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC"}
|
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
* Hybrid of shipped MP1 behavior + Material window-size naming:
|
|
11
11
|
* - **Names** follow Material (compact → xl).
|
|
12
12
|
* - **Numbers** prefer already-shipped thresholds:
|
|
13
|
-
* - `medium` @ 640 = Tamagui `$sm` / DeskShell narrow (Fluent sm)
|
|
14
|
-
*
|
|
13
|
+
* - `medium` @ 640 = Tamagui `$sm` / DeskShell narrow (Fluent sm) — and,
|
|
14
|
+
* since MPO-13, the overlay sheet↔float pivot (see OVERLAY_BREAKPOINT).
|
|
15
|
+
* - `expanded` @ 860 = pane-budget class only (~Material 840). No Tamagui
|
|
16
|
+
* counterpart; Tamagui has no pane system, so this stays additive.
|
|
15
17
|
* - `large` / `xl` = Tamagui `$lg` / `$xl`.
|
|
16
18
|
*
|
|
17
19
|
* Fluent (480/640/1024/1366/1920) and Material (600/840/1200/1600) stay in the
|
|
@@ -19,9 +21,9 @@
|
|
|
19
21
|
*
|
|
20
22
|
* | Class | Min px | Max panes (default) | Tamagui media | Notes |
|
|
21
23
|
* |-----------|--------|---------------------|---------------|--------------------------------|
|
|
22
|
-
* | compact | 0 | 1 | < `$sm` | phones; drawer nav
|
|
23
|
-
* | medium | 640 | 1 | `$sm` | DeskShell rail;
|
|
24
|
-
* | expanded | 860 | 2 | — (custom) |
|
|
24
|
+
* | compact | 0 | 1 | < `$sm` | phones; drawer nav; sheets |
|
|
25
|
+
* | medium | 640 | 1 | `$sm` | DeskShell rail; overlays float |
|
|
26
|
+
* | expanded | 860 | 2 | — (custom) | 2 panes |
|
|
25
27
|
* | large | 1024 | 2 | `$lg` | |
|
|
26
28
|
* | xl | 1280 | 2 | `$xl` | |
|
|
27
29
|
*
|
|
@@ -31,9 +33,13 @@
|
|
|
31
33
|
export type LayoutSizeClass = "compact" | "medium" | "expanded" | "large" | "xl";
|
|
32
34
|
/** Named min-widths. Prefer these over literals in layout code. */
|
|
33
35
|
export declare const layoutBreakpoints: {
|
|
34
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* End of compact / DeskShell narrow drawer threshold (Tamagui `$sm`).
|
|
38
|
+
* Also the overlay sheet↔float pivot and the DataTable card↔grid pivot —
|
|
39
|
+
* one idiom flip per viewport (MPO-13 C5).
|
|
40
|
+
*/
|
|
35
41
|
readonly medium: 640;
|
|
36
|
-
/** Two-pane
|
|
42
|
+
/** Two-pane budget threshold (~M3 expanded 840). Not an overlay pivot. */
|
|
37
43
|
readonly expanded: 860;
|
|
38
44
|
/** Tamagui `$lg`. */
|
|
39
45
|
readonly large: 1024;
|
|
@@ -42,10 +48,16 @@ export declare const layoutBreakpoints: {
|
|
|
42
48
|
};
|
|
43
49
|
export type LayoutBreakpointName = keyof typeof layoutBreakpoints;
|
|
44
50
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
51
|
+
* Overlay sheet↔float pivot for FloatingPanel / AdaptivePopup consumers.
|
|
52
|
+
*
|
|
53
|
+
* MPO-13 C5: was `layoutBreakpoints.expanded` (860, a custom threshold with
|
|
54
|
+
* no Tamagui counterpart), which split the system in two — at 700px a
|
|
55
|
+
* DataTable rendered its desktop grid while a Select in one of its cells
|
|
56
|
+
* opened as a bottom sheet. Overlays now pivot where the table does:
|
|
57
|
+
* `layoutBreakpoints.medium` (640, Tamagui v5 `$sm` — the same `media.sm`
|
|
58
|
+
* key DataTableRoot reads), so every surface flips idiom at one width.
|
|
47
59
|
*/
|
|
48
|
-
export declare const OVERLAY_BREAKPOINT:
|
|
60
|
+
export declare const OVERLAY_BREAKPOINT: 640;
|
|
49
61
|
/** DeskShell sidebar collapse — same value as `layoutBreakpoints.medium`. */
|
|
50
62
|
export declare const NARROW_BREAKPOINT: 640;
|
|
51
63
|
export declare const LAYOUT_SIZE_CLASS_ORDER: readonly LayoutSizeClass[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layoutTokens.d.ts","sourceRoot":"","sources":["../../src/theme/layoutTokens.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"layoutTokens.d.ts","sourceRoot":"","sources":["../../src/theme/layoutTokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AASH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,CAAC;AAEjF,mEAAmE;AACnE,eAAO,MAAM,iBAAiB;IAC5B;;;;OAIG;;IAEH,0EAA0E;;IAE1E,qBAAqB;;IAErB,qBAAqB;;CAEb,CAAC;AAEX,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,iBAAiB,CAAC;AAElE;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,KAA2B,CAAC;AAE3D,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB,KAA2B,CAAC;AAE1D,eAAO,MAAM,uBAAuB,EAAE,SAAS,eAAe,EAMpD,CAAC;AAEX,mEAAmE;AACnE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAMjE;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,SAAS,EAAE,eAAe,GAAG,CAAC,GAAG,CAAC,CAEjE;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,eAAe,GACvB,OAAO,CAET;AAQD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAiCpD;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,OAAO,CAItD;AAID,2DAA2D;AAC3D,eAAO,MAAM,gBAAgB,KAAK,CAAC;AACnC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,gFAAgF;AAChF,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE,MAAM,GAAG,MAAM,GAAG,IAAuB,GACjD,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAI3C;AAID,wFAAwF;AACxF,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,kEAAkE;AAClE,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,MAAyB,GAAG,gBAAgB,CAElF;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,yEAAyE;AACzE,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,GAAG,GAAE,MAAyB,GAC7B,aAAa,CAGf;AAID;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAIpC;;;GAGG;AACH,wBAAgB,eAAe,IAAI;IACjC,WAAW,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,aAAa,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAChC,CAMA"}
|
|
@@ -9,10 +9,13 @@
|
|
|
9
9
|
* Tamagui `createThemes` / theme-builder still emits COLOR palettes only.
|
|
10
10
|
* Do not stuff recipe keys into `getTheme()` / `themes`.
|
|
11
11
|
*
|
|
12
|
-
* DEFAULT uses `tokenHeights`
|
|
13
|
-
* ($4=
|
|
14
|
-
*
|
|
12
|
+
* DEFAULT uses `tokenHeights` pinned to the stock Tamagui `$size` scale as
|
|
13
|
+
* measured on tamagui.dev ($4=44, $3=36, $5=52, $6=64 — MPO-13 C1/C2: the
|
|
14
|
+
* recipe key and the raw token now agree). `{ baseHeight: 40 }` (no
|
|
15
|
+
* tokenHeights / sizeFactors) regenerates geometrically from
|
|
16
|
+
* `baseHeight * stepRatio ** step`.
|
|
15
17
|
*/
|
|
18
|
+
import { type TileSizeInputs, type TileSizeLadder } from "./tileSizes";
|
|
16
19
|
export declare const SIZE_RECIPE_TOKENS: readonly ["$1", "$1.5", "$2", "$2.5", "$3", "$3.5", "$4", "$true", "$5", "$6"];
|
|
17
20
|
export type SizeRecipeToken = (typeof SIZE_RECIPE_TOKENS)[number];
|
|
18
21
|
export type SizeRecipeFamilyName = "control" | "controlCompact";
|
|
@@ -39,6 +42,11 @@ export type SizeRecipeInputs = {
|
|
|
39
42
|
compactRatios: SizeRecipeRatios;
|
|
40
43
|
radiusPx: number;
|
|
41
44
|
touchFloor: number;
|
|
45
|
+
/**
|
|
46
|
+
* Tile-size ladder inputs (MPO-31). Merged over `defaultTileSizeInputs`;
|
|
47
|
+
* the ladder table derives from these the way every other table does.
|
|
48
|
+
*/
|
|
49
|
+
tile?: Partial<TileSizeInputs>;
|
|
42
50
|
};
|
|
43
51
|
/** @deprecated Use `SizeRecipeInputs`. */
|
|
44
52
|
export type RecipeInputs = SizeRecipeInputs;
|
|
@@ -89,9 +97,11 @@ export type GeneratedSizeRecipes = {
|
|
|
89
97
|
typeVariants: Record<string, SizeRecipeTypeVariant>;
|
|
90
98
|
iconVariants: Record<string, SizeRecipeIconVariant>;
|
|
91
99
|
families: RecipeFamilies;
|
|
100
|
+
/** Tile-size ladder (MPO-31) — derived from `inputs.tile` over the measured defaults. */
|
|
101
|
+
tiles: TileSizeLadder;
|
|
92
102
|
};
|
|
93
103
|
export declare const SIZE_TOKEN_EXPONENTS: Record<SizeRecipeToken, number>;
|
|
94
|
-
/** Lossless relative table:
|
|
104
|
+
/** Lossless relative table: the stock Tamagui 20/24/28/32/36/40/44/52/64 ramp at baseHeight 44. */
|
|
95
105
|
export declare const defaultSizeFactors: Record<SizeRecipeToken, number>;
|
|
96
106
|
export declare const DEFAULT_SIZE_RECIPE_INPUTS: SizeRecipeInputs;
|
|
97
107
|
export declare const defaultRecipeInputs: SizeRecipeInputs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recipeInputs.d.ts","sourceRoot":"","sources":["../../src/theme/recipeInputs.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"recipeInputs.d.ts","sourceRoot":"","sources":["../../src/theme/recipeInputs.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* reserve it for non-enumerable values only. Do NOT put recipe tables on a
|
|
14
14
|
* `createStyledContext` primitive (`neverFlatten`).
|
|
15
15
|
*
|
|
16
|
-
* Reference md ($4 / $true): height
|
|
16
|
+
* Reference md ($4 / $true): height 44, padX 18, font 14, icon 16, gap 9
|
|
17
|
+
* (the measured tamagui.dev $4 control — MPO-13).
|
|
17
18
|
* `sizeToken` remains the recipe KEY (string "$4") so styled() variants
|
|
18
19
|
* can switch; it is not a height scalar.
|
|
19
20
|
*
|
|
@@ -43,6 +44,13 @@ export declare const SIZE_RECIPE_HEIGHTS_TOUCH: Record<string, number>;
|
|
|
43
44
|
export declare const SIZE_RECIPE_RATIOS: import("./recipeInputs").SizeRecipeRatios;
|
|
44
45
|
export declare const SIZE_RECIPE_COMPACT_RATIOS: import("./recipeInputs").SizeRecipeRatios;
|
|
45
46
|
export declare const SIZE_RECIPE_FAMILY_NAMES: readonly ["control", "controlCompact"];
|
|
47
|
+
/**
|
|
48
|
+
* Live tile-size ladder (MPO-31) — generated from `inputs.tile` over the
|
|
49
|
+
* measured defaults, adopted in place on `setSizeRecipeInputs` like every
|
|
50
|
+
* other live table. Never handwrite rungs; restyle through inputs.
|
|
51
|
+
*/
|
|
52
|
+
export declare const tileSizeLadder: import("./tileSizes").TileSizeLadder;
|
|
53
|
+
export declare function getTileSizeLadder(): typeof tileSizeLadder;
|
|
46
54
|
/** Merge `partial` over defaultRecipeInputs (not the previous override) and rewrite live tables. */
|
|
47
55
|
export declare function setSizeRecipeInputs(partial?: Partial<RecipeInputs>): GeneratedSizeRecipes;
|
|
48
56
|
export declare function getSizeRecipeInputs(): RecipeInputs;
|