@multiplatform.one/theme 7.4.0 → 7.5.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 +2 -1
- package/package.json +5 -5
- package/src/figma/figmaTokens.spec.ts +25 -21
- package/src/figma/figmaTokens.ts +2 -2
- package/src/font.ts +6 -19
- package/src/keyboardFocusRing.ts +12 -6
- package/src/theme/FontKnobStyles.tsx +5 -3
- package/src/theme/Tint.tsx +3 -2
- package/src/theme/animations/css.ts +14 -1
- package/src/theme/colorRules.spec.ts +233 -2
- package/src/theme/colorRules.ts +118 -0
- package/src/theme/cornerSmoothing.native.ts +39 -2
- package/src/theme/cornerSmoothing.spec.ts +213 -3
- package/src/theme/cornerSmoothing.ts +132 -10
- package/src/theme/createDefaultThemeConfig.spec.ts +107 -1
- package/src/theme/createDefaultThemeConfig.ts +27 -8
- package/src/theme/defaults/builderOptions.ts +23 -10
- package/src/theme/defaults/categoryFonts.ts +21 -0
- package/src/theme/defaults/fonts.spec.ts +93 -10
- package/src/theme/defaults/fonts.theme.spec.tsx +128 -0
- package/src/theme/defaults/fonts.ts +155 -27
- package/src/theme/defaults/index.ts +1 -0
- package/src/theme/devtools/ThemeDevtoolsPanel.tsx +0 -11
- package/src/theme/focusState.spec.ts +110 -1
- package/src/theme/focusState.ts +32 -7
- package/src/theme/fontCategoryStacks.ts +24 -0
- package/src/theme/fontKnobStyles.spec.ts +15 -2
- package/src/theme/glyphPaint.spec.ts +26 -0
- package/src/theme/glyphPaint.ts +46 -0
- package/src/theme/index.ts +3 -0
- package/src/theme/knobs.ts +18 -2
- package/src/theme/layoutTokens.spec.ts +3 -1
- package/src/theme/layoutTokens.ts +47 -4
- package/src/theme/mpo13Proof.spec.ts +3 -3
- package/src/theme/mpo19Proof.spec.ts +285 -0
- package/src/theme/presets.ts +1 -1
- package/src/theme/radiusClass.spec.ts +394 -0
- package/src/theme/radiusClass.ts +203 -4
- package/src/theme/radiusClassTable.generated.ts +121 -0
- package/src/theme/recipeInputs.ts +223 -36
- package/src/theme/recipes.ts +68 -4
- package/src/theme/resolveKnobs.spec.ts +139 -11
- package/src/theme/resolveKnobs.ts +190 -25
- package/src/theme/sizeLadder.spec.ts +84 -0
- package/src/theme/sizeRecipes.spec.ts +19 -6
- package/src/theme/sizeRecipes.ts +43 -13
- package/src/theme/theme.native.tsx +2 -0
- package/src/theme/theme.provider.spec.ts +9 -0
- package/src/theme/theme.tsx +6 -3
- package/src/theme/tint.spec.tsx +36 -35
- package/src/theme/useResolvedKnobs.ts +6 -3
- package/types/figma/figmaTokens.d.ts +1 -1
- package/types/figma/figmaTokens.d.ts.map +1 -1
- package/types/font.d.ts.map +1 -1
- package/types/keyboardFocusRing.d.ts +11 -5
- package/types/keyboardFocusRing.d.ts.map +1 -1
- package/types/theme/FontKnobStyles.d.ts +2 -1
- package/types/theme/FontKnobStyles.d.ts.map +1 -1
- package/types/theme/Tint.d.ts +2 -1
- package/types/theme/Tint.d.ts.map +1 -1
- package/types/theme/animations/css.d.ts +15 -2
- package/types/theme/animations/css.d.ts.map +1 -1
- package/types/theme/colorRules.d.ts +59 -1
- package/types/theme/colorRules.d.ts.map +1 -1
- package/types/theme/cornerSmoothing.d.ts +42 -20
- package/types/theme/cornerSmoothing.d.ts.map +1 -1
- package/types/theme/cornerSmoothing.native.d.ts +22 -2
- package/types/theme/cornerSmoothing.native.d.ts.map +1 -1
- package/types/theme/createDefaultThemeConfig.d.ts +21 -3
- package/types/theme/createDefaultThemeConfig.d.ts.map +1 -1
- package/types/theme/defaults/builderOptions.d.ts.map +1 -1
- package/types/theme/defaults/categoryFonts.d.ts +19 -0
- package/types/theme/defaults/categoryFonts.d.ts.map +1 -0
- package/types/theme/defaults/fonts.d.ts +135 -2
- package/types/theme/defaults/fonts.d.ts.map +1 -1
- package/types/theme/defaults/index.d.ts +1 -0
- package/types/theme/defaults/index.d.ts.map +1 -1
- package/types/theme/devtools/ThemeDevtoolsPanel.d.ts.map +1 -1
- package/types/theme/focusState.d.ts +32 -6
- package/types/theme/focusState.d.ts.map +1 -1
- package/types/theme/fontCategoryStacks.d.ts +11 -0
- package/types/theme/fontCategoryStacks.d.ts.map +1 -0
- package/types/theme/glyphPaint.d.ts +16 -0
- package/types/theme/glyphPaint.d.ts.map +1 -0
- package/types/theme/index.d.ts +3 -0
- package/types/theme/index.d.ts.map +1 -1
- package/types/theme/knobs.d.ts +10 -2
- package/types/theme/knobs.d.ts.map +1 -1
- package/types/theme/layoutTokens.d.ts +46 -4
- package/types/theme/layoutTokens.d.ts.map +1 -1
- package/types/theme/radiusClass.d.ts +96 -4
- package/types/theme/radiusClass.d.ts.map +1 -1
- package/types/theme/radiusClassTable.generated.d.ts +146 -0
- package/types/theme/radiusClassTable.generated.d.ts.map +1 -0
- package/types/theme/recipeInputs.d.ts +85 -14
- package/types/theme/recipeInputs.d.ts.map +1 -1
- package/types/theme/recipes.d.ts +78 -4
- package/types/theme/recipes.d.ts.map +1 -1
- package/types/theme/resolveKnobs.d.ts +12 -1
- package/types/theme/resolveKnobs.d.ts.map +1 -1
- package/types/theme/sizeRecipes.d.ts +27 -14
- package/types/theme/sizeRecipes.d.ts.map +1 -1
- package/types/theme/theme.d.ts.map +1 -1
- package/types/theme/theme.native.d.ts.map +1 -1
- package/types/theme/useResolvedKnobs.d.ts +2 -2
- package/types/theme/useResolvedKnobs.d.ts.map +1 -1
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
SIZE_RECIPE_COMPACT_RATIOS,
|
|
8
8
|
SIZE_RECIPE_HEIGHTS,
|
|
9
9
|
SIZE_RECIPE_HEIGHTS_TOUCH,
|
|
10
|
+
SIZE_RECIPE_RADII,
|
|
10
11
|
SIZE_RECIPE_RATIOS,
|
|
11
12
|
applyTouchFloor,
|
|
12
13
|
defaultRecipeInputs,
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
sizeRecipeIconVariants,
|
|
23
24
|
sizeRecipes,
|
|
24
25
|
sizeRecipeTypeVariants,
|
|
26
|
+
textFieldInset,
|
|
25
27
|
type SizeRecipe,
|
|
26
28
|
} from "./sizeRecipes";
|
|
27
29
|
|
|
@@ -75,10 +77,9 @@ describe("size recipes", () => {
|
|
|
75
77
|
}
|
|
76
78
|
});
|
|
77
79
|
|
|
78
|
-
it("static variants match
|
|
80
|
+
it("static variants match the generated table for every token", () => {
|
|
79
81
|
for (const token of RECIPE_KEYS) {
|
|
80
|
-
const recipe =
|
|
81
|
-
expect(sizeRecipes[token]).toEqual(recipe);
|
|
82
|
+
const recipe = sizeRecipes[token];
|
|
82
83
|
expect(sizeRecipeBoxVariants[token]).toEqual({
|
|
83
84
|
height: recipe.height,
|
|
84
85
|
paddingHorizontal: recipe.paddingHorizontal,
|
|
@@ -90,6 +91,7 @@ describe("size recipes", () => {
|
|
|
90
91
|
height: recipe.iconSize,
|
|
91
92
|
});
|
|
92
93
|
}
|
|
94
|
+
expect(sizeRecipeFromHeight(44)).toEqual(sizeRecipes.$4);
|
|
93
95
|
});
|
|
94
96
|
|
|
95
97
|
it("sizeRecipeForToken falls back to $4", () => {
|
|
@@ -230,7 +232,7 @@ describe("generateSizeRecipes (LC-70)", () => {
|
|
|
230
232
|
expect(generated.families.control.recipes.$4.height).toBe(44);
|
|
231
233
|
expect(generated.families.controlCompact.recipes.$4.height).toBe(44);
|
|
232
234
|
expect(generated.families.control.recipes.$4.paddingHorizontal).toBe(18);
|
|
233
|
-
expect(generated.families.controlCompact.recipes.$4.paddingHorizontal).toBe(
|
|
235
|
+
expect(generated.families.controlCompact.recipes.$4.paddingHorizontal).toBe(16);
|
|
234
236
|
expect(generated.families.controlCompact.recipes.$4.paddingHorizontal).toBeLessThan(
|
|
235
237
|
generated.families.control.recipes.$4.paddingHorizontal,
|
|
236
238
|
);
|
|
@@ -260,12 +262,23 @@ describe("generateSizeRecipes (LC-70)", () => {
|
|
|
260
262
|
expect(sizeRecipeTypeVariants).toBe(recipeFamilies.control.typeVariants);
|
|
261
263
|
expect(sizeRecipeIconVariants).toBe(recipeFamilies.control.iconVariants);
|
|
262
264
|
expect(SIZE_RECIPE_HEIGHTS).toBe(recipeFamilies.control.heights);
|
|
265
|
+
expect(SIZE_RECIPE_RADII).toBe(recipeFamilies.control.radii);
|
|
263
266
|
});
|
|
264
267
|
|
|
265
268
|
it("sizeRecipeEscape is identity", () => {
|
|
266
269
|
expect(sizeRecipeEscape(32)).toBe(32);
|
|
267
270
|
expect(sizeRecipeEscape("keep")).toBe("keep");
|
|
268
271
|
});
|
|
272
|
+
|
|
273
|
+
it("textFieldInset is min(padX, floor((height-fontSize)/2)) — $4 → 15 (LC-84)", () => {
|
|
274
|
+
expect(textFieldInset(sizeRecipes.$4)).toBe(15);
|
|
275
|
+
expect(textFieldInset({ height: 44, paddingHorizontal: 18, fontSize: 14 })).toBe(15);
|
|
276
|
+
expect(textFieldInset({ height: 32, paddingHorizontal: 12, fontSize: 14 })).toBe(9);
|
|
277
|
+
expect(textFieldInset({ height: 48, paddingHorizontal: 8, fontSize: 14 })).toBe(8);
|
|
278
|
+
expect(textFieldInset(sizeRecipes.$4)).toBeLessThanOrEqual(
|
|
279
|
+
Math.floor((sizeRecipes.$4.height - sizeRecipes.$4.fontSize) / 2),
|
|
280
|
+
);
|
|
281
|
+
});
|
|
269
282
|
});
|
|
270
283
|
|
|
271
284
|
describe("size recipe families", () => {
|
|
@@ -291,8 +304,8 @@ describe("size recipe families", () => {
|
|
|
291
304
|
expect(compact.boxVariants.$4.paddingHorizontal).toBeLessThan(
|
|
292
305
|
control.boxVariants.$4.paddingHorizontal,
|
|
293
306
|
);
|
|
294
|
-
expect(compact.boxVariants.$4.paddingHorizontal).toBe(
|
|
295
|
-
expect(compact.boxVariants.$4.gap).toBe(
|
|
307
|
+
expect(compact.boxVariants.$4.paddingHorizontal).toBe(16);
|
|
308
|
+
expect(compact.boxVariants.$4.gap).toBe(9);
|
|
296
309
|
expect(sizeRecipeForToken("$4", { family: "controlCompact" })).toEqual(compact.recipes.$4);
|
|
297
310
|
});
|
|
298
311
|
});
|
package/src/theme/sizeRecipes.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Coordinated control-size recipes (LC-
|
|
2
|
+
* Coordinated control-size recipes (LC-75 SIZE-RECIPE, LC-80 RECIPE-INPUTS).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The default ladder is the measured Tamagui v5 table in recipeInputs
|
|
5
|
+
* (padX / font / icon / radius per size token). Gap equals radius at
|
|
6
|
+
* every size and at every borderRadius knob stop (`applyRadiusStop`).
|
|
7
|
+
* A linear ratio is only the `{ baseHeight }` fallback — not a
|
|
8
|
+
* documented divergence (MPO-46 / R6).
|
|
7
9
|
*
|
|
8
10
|
* Tables are GENERATED from `defaultRecipeInputs` at module eval (Tamagui
|
|
9
11
|
* 2.0.0-rc.41 flattens `styled(View, { variants: { size: tables } })` when
|
|
@@ -13,25 +15,30 @@
|
|
|
13
15
|
* reserve it for non-enumerable values only. Do NOT put recipe tables on a
|
|
14
16
|
* `createStyledContext` primitive (`neverFlatten`).
|
|
15
17
|
*
|
|
16
|
-
* Reference md ($4 / $true): height 44, padX 18, font 14, icon 16,
|
|
17
|
-
* (the measured tamagui.dev $4 control — MPO-13).
|
|
18
|
+
* Reference md ($4 / $true): height 44, padX 18, font 14, icon 16, radius 9,
|
|
19
|
+
* gap 9 (the measured tamagui.dev $4 control — MPO-13 / MPO-19 X1/X2).
|
|
18
20
|
* `sizeToken` remains the recipe KEY (string "$4") so styled() variants
|
|
19
21
|
* can switch; it is not a height scalar.
|
|
20
22
|
*
|
|
21
|
-
* Families: `control`
|
|
22
|
-
* `
|
|
23
|
+
* Families: `control` reads `inputs.tokenTable`. `controlCompact` reads
|
|
24
|
+
* `compactTokenTable` at the SAME heights (Input padX, tighter type).
|
|
23
25
|
*
|
|
24
|
-
* On touch (LC-
|
|
25
|
-
* lift painted height to ≥ 44
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* On touch (LC-77), `applyTouchFloor` / `sizeRecipeForToken(token, { touch: true })`
|
|
27
|
+
* lift painted height to ≥ 44. Static `sizeRecipe*Variants` stay on the
|
|
28
|
+
* desktop table — runtime fragments carry the floor; consumers spread
|
|
29
|
+
* `knobProps.control` after `size`.
|
|
28
30
|
*/
|
|
29
31
|
|
|
30
32
|
export {
|
|
31
33
|
DEFAULT_SIZE_RECIPE_INPUTS,
|
|
34
|
+
SIZE_RECIPE_RADIUS_STOPS,
|
|
32
35
|
SIZE_RECIPE_TOKENS,
|
|
33
36
|
SIZE_TOKEN_EXPONENTS,
|
|
37
|
+
TAMAGUI_COMPACT_SIZE_TABLE,
|
|
38
|
+
TAMAGUI_CONTROL_SIZE_TABLE,
|
|
39
|
+
TAMAGUI_INPUT_PADX,
|
|
34
40
|
TOUCH_HEIGHT_FLOOR,
|
|
41
|
+
applyRadiusStop,
|
|
35
42
|
cloneSizeRecipeInputs,
|
|
36
43
|
createRecipeFamilies,
|
|
37
44
|
defaultRecipeInputs,
|
|
@@ -39,6 +46,7 @@ export {
|
|
|
39
46
|
generateSizeRecipeTables,
|
|
40
47
|
generateSizeRecipes,
|
|
41
48
|
mergeRecipeInputs,
|
|
49
|
+
recipeFromTokenChannels,
|
|
42
50
|
resolveSizeRecipeInputs,
|
|
43
51
|
} from "./recipeInputs";
|
|
44
52
|
export type {
|
|
@@ -52,13 +60,17 @@ export type {
|
|
|
52
60
|
SizeRecipeFamilyName,
|
|
53
61
|
SizeRecipeIconVariant,
|
|
54
62
|
SizeRecipeInputs,
|
|
63
|
+
SizeRecipeRadiusStop,
|
|
55
64
|
SizeRecipeRatios,
|
|
56
65
|
SizeRecipeTables,
|
|
57
66
|
SizeRecipeToken,
|
|
67
|
+
SizeRecipeTokenChannels,
|
|
68
|
+
SizeRecipeTokenTable,
|
|
58
69
|
SizeRecipeTypeVariant,
|
|
59
70
|
} from "./recipeInputs";
|
|
60
71
|
|
|
61
72
|
import {
|
|
73
|
+
cloneSizeRecipeInputs,
|
|
62
74
|
defaultRecipeInputs,
|
|
63
75
|
generateSizeRecipes,
|
|
64
76
|
sizeRecipeFromHeight as recipeFromHeight,
|
|
@@ -88,6 +100,7 @@ function adoptFamily(target: SizeRecipeFamily, source: SizeRecipeFamily): void {
|
|
|
88
100
|
replaceRecord(target.typeVariants, source.typeVariants);
|
|
89
101
|
replaceRecord(target.iconVariants, source.iconVariants);
|
|
90
102
|
replaceRecord(target.heightVariants, source.heightVariants);
|
|
103
|
+
replaceRecord(target.radii, source.radii);
|
|
91
104
|
}
|
|
92
105
|
|
|
93
106
|
const initial = generateSizeRecipes(defaultRecipeInputs);
|
|
@@ -106,6 +119,7 @@ export const sizeRecipeTypeVariants = recipeFamilies.control.typeVariants;
|
|
|
106
119
|
export const sizeRecipeIconVariants = recipeFamilies.control.iconVariants;
|
|
107
120
|
export const SIZE_RECIPE_HEIGHTS = recipeFamilies.control.heights;
|
|
108
121
|
export const SIZE_RECIPE_HEIGHTS_TOUCH = recipeFamilies.control.touchHeights;
|
|
122
|
+
export const SIZE_RECIPE_RADII = recipeFamilies.control.radii;
|
|
109
123
|
export const SIZE_RECIPE_RATIOS = recipeFamilies.control.ratios;
|
|
110
124
|
export const SIZE_RECIPE_COMPACT_RATIOS = recipeFamilies.controlCompact.ratios;
|
|
111
125
|
|
|
@@ -139,6 +153,7 @@ function adoptGenerated(next: GeneratedSizeRecipes): GeneratedSizeRecipes {
|
|
|
139
153
|
boxVariants: sizeRecipeBoxVariants,
|
|
140
154
|
typeVariants: sizeRecipeTypeVariants,
|
|
141
155
|
iconVariants: sizeRecipeIconVariants,
|
|
156
|
+
radii: SIZE_RECIPE_RADII,
|
|
142
157
|
families: recipeFamilies,
|
|
143
158
|
};
|
|
144
159
|
return current;
|
|
@@ -150,7 +165,7 @@ export function setSizeRecipeInputs(partial: Partial<RecipeInputs> = {}): Genera
|
|
|
150
165
|
}
|
|
151
166
|
|
|
152
167
|
export function getSizeRecipeInputs(): RecipeInputs {
|
|
153
|
-
return
|
|
168
|
+
return cloneSizeRecipeInputs(current.inputs);
|
|
154
169
|
}
|
|
155
170
|
|
|
156
171
|
export function getGeneratedSizeRecipes(): GeneratedSizeRecipes {
|
|
@@ -210,3 +225,18 @@ export function sizeRecipeForToken(
|
|
|
210
225
|
export function sizeRecipeEscape<T>(value: T): T {
|
|
211
226
|
return value;
|
|
212
227
|
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* LC-84 TEXT-INSET — optical vertical inset of a text field, never larger
|
|
231
|
+
* than the recipe padX. Extra horizontal space is legal only when an icon
|
|
232
|
+
* well occupies that side, not as empty-field padX.
|
|
233
|
+
*
|
|
234
|
+
* min(paddingHorizontal, floor((height − fontSize) / 2))
|
|
235
|
+
*
|
|
236
|
+
* `$4` (44 / 18 / 14) → 15. Button ladders keep recipe.paddingHorizontal (18).
|
|
237
|
+
*/
|
|
238
|
+
export function textFieldInset(
|
|
239
|
+
recipe: Pick<SizeRecipe, "height" | "paddingHorizontal" | "fontSize">,
|
|
240
|
+
): number {
|
|
241
|
+
return Math.min(recipe.paddingHorizontal, Math.floor((recipe.height - recipe.fontSize) / 2));
|
|
242
|
+
}
|
|
@@ -2,6 +2,7 @@ import { ToastProvider } from "@tamagui/toast";
|
|
|
2
2
|
import { useContext, useMemo } from "react";
|
|
3
3
|
import { type CreateTamaguiProps, TamaguiProvider, type TamaguiProviderProps } from "tamagui";
|
|
4
4
|
import type { PropsWithChildren } from "react";
|
|
5
|
+
import { CornerSmoothingStyles } from "./cornerSmoothing";
|
|
5
6
|
import { FontKnobStyles } from "./FontKnobStyles";
|
|
6
7
|
import { PresetContext, type PresetContextValue } from "./PresetContext";
|
|
7
8
|
import { defaultPreset } from "./presets";
|
|
@@ -61,6 +62,7 @@ function KnobBridge({ children }: PropsWithChildren) {
|
|
|
61
62
|
const tree = (
|
|
62
63
|
<>
|
|
63
64
|
<FontKnobStyles />
|
|
65
|
+
<CornerSmoothingStyles />
|
|
64
66
|
{children}
|
|
65
67
|
</>
|
|
66
68
|
);
|
|
@@ -15,6 +15,15 @@ describe("ThemeProvider knob injectors", () => {
|
|
|
15
15
|
expect(bridge).toContain("<FontKnobStyles");
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
+
it("mounts CornerSmoothingStyles inside KnobBridge so the squircle sheet is not tree-shaken", () => {
|
|
19
|
+
const src = readFileSync(join(here, "theme.tsx"), "utf8");
|
|
20
|
+
expect(src).toMatch(/import \{ CornerSmoothingStyles \} from "\.\/cornerSmoothing"/);
|
|
21
|
+
const bridge = src.slice(src.indexOf("function KnobBridge"));
|
|
22
|
+
expect(bridge).toContain("<CornerSmoothingStyles");
|
|
23
|
+
const native = readFileSync(join(here, "theme.native.tsx"), "utf8");
|
|
24
|
+
expect(native).toContain("<CornerSmoothingStyles");
|
|
25
|
+
});
|
|
26
|
+
|
|
18
27
|
it("does not invent a second knob store — cookies still feed PresetContext", () => {
|
|
19
28
|
const src = readFileSync(join(here, "theme.tsx"), "utf8");
|
|
20
29
|
expect(src).toContain("readPresetCookie");
|
package/src/theme/theme.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import { type CreateTamaguiProps, TamaguiProvider, type TamaguiProviderProps } f
|
|
|
5
5
|
import type { PropsWithChildren } from "react";
|
|
6
6
|
import { animationDurations } from "./animations/css";
|
|
7
7
|
import { getCookieWatchList, readOverridesCookie, readPresetCookie } from "./cookies";
|
|
8
|
+
import { CornerSmoothingStyles } from "./cornerSmoothing";
|
|
8
9
|
import { FontKnobStyles } from "./FontKnobStyles";
|
|
9
10
|
import { PresetContext, type PresetContextValue } from "./PresetContext";
|
|
10
11
|
import { defaultPreset } from "./presets";
|
|
@@ -157,9 +158,10 @@ export function ThemeProvider<T extends CreateTamaguiProps>({
|
|
|
157
158
|
* If an ancestor PresetContext already exists (e.g. from a Storybook decorator),
|
|
158
159
|
* the bridge is a pass-through to avoid overriding it.
|
|
159
160
|
*
|
|
160
|
-
* FontKnobStyles
|
|
161
|
-
*
|
|
162
|
-
*
|
|
161
|
+
* FontKnobStyles and CornerSmoothingStyles mount here (not only in
|
|
162
|
+
* Storybook CreatePreview) so heading/body fonts and the corner-shape
|
|
163
|
+
* stylesheet restyle every shipped app that uses ThemeProvider. Hairline
|
|
164
|
+
* still self-mounts on module load.
|
|
163
165
|
*/
|
|
164
166
|
function KnobBridge({ children }: PropsWithChildren) {
|
|
165
167
|
const existingCtx = useContext(PresetContext);
|
|
@@ -192,6 +194,7 @@ function KnobBridge({ children }: PropsWithChildren) {
|
|
|
192
194
|
const tree = (
|
|
193
195
|
<>
|
|
194
196
|
<FontKnobStyles />
|
|
197
|
+
<CornerSmoothingStyles />
|
|
195
198
|
{children}
|
|
196
199
|
</>
|
|
197
200
|
);
|
package/src/theme/tint.spec.tsx
CHANGED
|
@@ -13,12 +13,16 @@ import type { ThemeName } from "@tamagui/web";
|
|
|
13
13
|
import { PresetContext, type PresetContextValue } from "./PresetContext";
|
|
14
14
|
import type { Preset } from "./preset.types";
|
|
15
15
|
import { defaultKnobs } from "./knobs";
|
|
16
|
+
import { defaultPreset } from "./presets";
|
|
16
17
|
import { Tint, useTintDepth } from "./Tint";
|
|
17
18
|
|
|
18
19
|
// ---------------------------------------------------------------------------
|
|
19
20
|
// Helpers
|
|
20
21
|
// ---------------------------------------------------------------------------
|
|
21
22
|
|
|
23
|
+
/** Decorative nest family (R12) — the same four names as `defaultPreset.tints`. */
|
|
24
|
+
const FAMILY: ThemeName[] = ["orange", "blue", "purple", "pink"];
|
|
25
|
+
|
|
22
26
|
function makePreset(tints: ThemeName[]): Preset {
|
|
23
27
|
return {
|
|
24
28
|
theme: "light" as ThemeName,
|
|
@@ -42,71 +46,70 @@ function collectThemes(html: string): string[] {
|
|
|
42
46
|
return Array.from(html.matchAll(/data-tamagui-theme="([^"]+)"/g), (m) => m[1]);
|
|
43
47
|
}
|
|
44
48
|
|
|
49
|
+
function nestTints(
|
|
50
|
+
count: number,
|
|
51
|
+
innermost: ReactNode = createElement("span", null, "inner"),
|
|
52
|
+
): ReactNode {
|
|
53
|
+
let node: ReactNode = innermost;
|
|
54
|
+
for (let i = 0; i < count; i++) {
|
|
55
|
+
node = createElement(Tint, null, node);
|
|
56
|
+
}
|
|
57
|
+
return node;
|
|
58
|
+
}
|
|
59
|
+
|
|
45
60
|
// ---------------------------------------------------------------------------
|
|
46
61
|
// Tests
|
|
47
62
|
// ---------------------------------------------------------------------------
|
|
48
63
|
|
|
49
64
|
describe("Tint", () => {
|
|
50
|
-
it("
|
|
51
|
-
|
|
65
|
+
it("defaultPreset.tints is the four-name decorative family", () => {
|
|
66
|
+
expect(defaultPreset.tints).toEqual(FAMILY);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("selects tints[0] for a single <Tint> (depth 1)", () => {
|
|
52
70
|
const tree = wrapWithPreset(
|
|
53
|
-
|
|
71
|
+
FAMILY,
|
|
54
72
|
createElement(Tint, null, createElement("span", null, "hello")),
|
|
55
73
|
);
|
|
56
74
|
const html = renderToHtml(tree);
|
|
57
75
|
const themes = collectThemes(html);
|
|
58
|
-
// depth = 0 (parent) + 1 = 1 → tints[1 %
|
|
59
|
-
expect(themes).toEqual(["
|
|
76
|
+
// depth = 0 (parent) + 1 = 1 → tints[(1 - 1) % 4] = "orange"
|
|
77
|
+
expect(themes).toEqual(["orange"]);
|
|
60
78
|
});
|
|
61
79
|
|
|
62
80
|
it("increments depth correctly with nested <Tint>", () => {
|
|
63
|
-
const tints: ThemeName[] = ["red", "green", "blue"];
|
|
64
81
|
const tree = wrapWithPreset(
|
|
65
|
-
|
|
82
|
+
FAMILY,
|
|
66
83
|
createElement(Tint, null, createElement(Tint, null, createElement("span", null, "inner"))),
|
|
67
84
|
);
|
|
68
85
|
const html = renderToHtml(tree);
|
|
69
86
|
const themes = collectThemes(html);
|
|
70
|
-
// outer: depth=1 → tints[
|
|
71
|
-
expect(themes).toEqual(["
|
|
87
|
+
// outer: depth=1 → tints[0]="orange", inner: depth=2 → tints[1]="blue"
|
|
88
|
+
expect(themes).toEqual(["orange", "blue"]);
|
|
72
89
|
});
|
|
73
90
|
|
|
74
91
|
it("wraps via modulo when depth exceeds tints.length", () => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const tree = wrapWithPreset(
|
|
78
|
-
tints,
|
|
79
|
-
createElement(
|
|
80
|
-
Tint,
|
|
81
|
-
null,
|
|
82
|
-
createElement(
|
|
83
|
-
Tint,
|
|
84
|
-
null,
|
|
85
|
-
createElement(Tint, null, createElement(Tint, null, createElement("span", null, "deep"))),
|
|
86
|
-
),
|
|
87
|
-
),
|
|
88
|
-
);
|
|
92
|
+
// 5 nested Tints: depths 1..5 → indices 0,1,2,3,0 → orange,blue,purple,pink,orange
|
|
93
|
+
const tree = wrapWithPreset(FAMILY, nestTints(5, createElement("span", null, "deep")));
|
|
89
94
|
const html = renderToHtml(tree);
|
|
90
95
|
const themes = collectThemes(html);
|
|
91
|
-
expect(themes).toEqual(["
|
|
96
|
+
expect(themes).toEqual(["orange", "blue", "purple", "pink", "orange"]);
|
|
92
97
|
});
|
|
93
98
|
|
|
94
99
|
it("applies alt prop offset", () => {
|
|
95
|
-
|
|
96
|
-
// alt=2 at top level: depth = 0 + 1 + 2 = 3 → tints[3%3] = "red"
|
|
100
|
+
// alt=2 at top level: depth = 0 + 1 + 2 = 3 → tints[(3 - 1) % 4] = "purple"
|
|
97
101
|
const tree = wrapWithPreset(
|
|
98
|
-
|
|
102
|
+
FAMILY,
|
|
99
103
|
createElement(Tint, { alt: 2 }, createElement("span", null, "alt")),
|
|
100
104
|
);
|
|
101
105
|
const html = renderToHtml(tree);
|
|
102
106
|
const themes = collectThemes(html);
|
|
103
|
-
expect(themes).toEqual(["
|
|
107
|
+
expect(themes).toEqual(["purple"]);
|
|
104
108
|
});
|
|
105
109
|
|
|
106
110
|
it("skips Theme wrapper when disable is true", () => {
|
|
107
|
-
const tints: ThemeName[] = ["red", "green", "blue"];
|
|
108
111
|
const tree = wrapWithPreset(
|
|
109
|
-
|
|
112
|
+
FAMILY,
|
|
110
113
|
createElement(Tint, { disable: true }, createElement("span", null, "no theme")),
|
|
111
114
|
);
|
|
112
115
|
const html = renderToHtml(tree);
|
|
@@ -115,10 +118,9 @@ describe("Tint", () => {
|
|
|
115
118
|
});
|
|
116
119
|
|
|
117
120
|
it("still increments depth when disabled (so children see correct depth)", () => {
|
|
118
|
-
|
|
119
|
-
// disabled outer (depth=1, no theme wrap), inner (depth=2, wraps with tints[2%3]="blue")
|
|
121
|
+
// disabled outer (depth=1, no theme wrap), inner (depth=2, wraps with tints[1]="blue")
|
|
120
122
|
const tree = wrapWithPreset(
|
|
121
|
-
|
|
123
|
+
FAMILY,
|
|
122
124
|
createElement(
|
|
123
125
|
Tint,
|
|
124
126
|
{ disable: true },
|
|
@@ -163,14 +165,13 @@ describe("useTintDepth", () => {
|
|
|
163
165
|
});
|
|
164
166
|
|
|
165
167
|
it("returns current depth inside nested <Tint> components", () => {
|
|
166
|
-
const tints: ThemeName[] = ["red", "green", "blue"];
|
|
167
168
|
let capturedDepth = -1;
|
|
168
169
|
const Probe = () => {
|
|
169
170
|
capturedDepth = useTintDepth();
|
|
170
171
|
return createElement("span", null, "probe");
|
|
171
172
|
};
|
|
172
173
|
const tree = wrapWithPreset(
|
|
173
|
-
|
|
174
|
+
FAMILY,
|
|
174
175
|
createElement(Tint, null, createElement(Tint, null, createElement(Probe))),
|
|
175
176
|
);
|
|
176
177
|
renderToHtml(tree);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
|
2
|
-
import type
|
|
2
|
+
import { type SizeTokens, useThemeName } from "tamagui";
|
|
3
3
|
import { defaultKnobs, type Knobs } from "./knobs";
|
|
4
4
|
import type { IntentOverride } from "./preset.types";
|
|
5
5
|
import type { KnobPropsOverride, ResolvedKnobs } from "./recipes";
|
|
@@ -111,12 +111,14 @@ export const solidButtonIntents = new Set(["error", "warning", "success"]);
|
|
|
111
111
|
* 6. Apply density (space only; compact option wins when provided)
|
|
112
112
|
* 7. Re-clamp to Surface ceiling (compact option cannot exceed parent)
|
|
113
113
|
* 8. OS reduced-motion forces animation="none"
|
|
114
|
-
* 9. Call resolveKnobs(mergedKnobs, override) — override merges last
|
|
114
|
+
* 9. Call resolveKnobs(mergedKnobs, override, scheme) — override merges last
|
|
115
115
|
*/
|
|
116
116
|
export function useResolvedKnobs(options?: UseResolvedKnobsOptions): ResolvedKnobs {
|
|
117
117
|
const presetCtx = usePresetContext();
|
|
118
118
|
const contextIntent = useIntentContext();
|
|
119
119
|
const prefersReducedMotion = usePrefersReducedMotion();
|
|
120
|
+
const themeName = useThemeName() as string | undefined;
|
|
121
|
+
const scheme = themeName?.startsWith("dark") ? "dark" : "light";
|
|
120
122
|
const surfaceCtx = SurfaceContext.useStyledContext();
|
|
121
123
|
const surfaceSize = surfaceCtx?.size ?? "unset";
|
|
122
124
|
const surfaceDensity = surfaceCtx?.density ?? "unset";
|
|
@@ -186,7 +188,7 @@ export function useResolvedKnobs(options?: UseResolvedKnobsOptions): ResolvedKno
|
|
|
186
188
|
merged = { ...merged, animation: "none" };
|
|
187
189
|
}
|
|
188
190
|
|
|
189
|
-
const resolved = resolveKnobs(merged, override);
|
|
191
|
+
const resolved = resolveKnobs(merged, override, scheme);
|
|
190
192
|
|
|
191
193
|
if (intent && component === "Button" && solidButtonIntents.has(intent)) {
|
|
192
194
|
const labelColor = merged.fillStyle === "filled" ? "$color" : "$color11";
|
|
@@ -210,5 +212,6 @@ export function useResolvedKnobs(options?: UseResolvedKnobsOptions): ResolvedKno
|
|
|
210
212
|
prefersReducedMotion,
|
|
211
213
|
surfaceSize,
|
|
212
214
|
surfaceDensity,
|
|
215
|
+
scheme,
|
|
213
216
|
]);
|
|
214
217
|
}
|
|
@@ -65,7 +65,7 @@ export interface FigmaRadiusMode {
|
|
|
65
65
|
/** `Sizing` collection variable to alias (e.g. `radius-4`). */
|
|
66
66
|
figmaName: string;
|
|
67
67
|
px: number;
|
|
68
|
-
/** Outer/nested radius fragment (`knobProps.
|
|
68
|
+
/** Outer/nested radius fragment (`knobProps.borderRadiusNested`). */
|
|
69
69
|
outerToken: string;
|
|
70
70
|
outerFigmaName: string;
|
|
71
71
|
outerPx: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figmaTokens.d.ts","sourceRoot":"","sources":["../../src/figma/figmaTokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAQH,OAAO,EAAE,KAAK,KAAK,EAAgB,MAAM,gBAAgB,CAAC;AAK1D;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,gGAUpB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGzD,CAAC;AAEF,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAElE;AAID,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,
|
|
1
|
+
{"version":3,"file":"figmaTokens.d.ts","sourceRoot":"","sources":["../../src/figma/figmaTokens.ts"],"names":[],"mappings":"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"}
|
package/types/font.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"font.d.ts","sourceRoot":"","sources":["../src/font.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"font.d.ts","sourceRoot":"","sources":["../src/font.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAoBhD,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW,EACrD,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG;IAAE,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAA;CAAE,GACzC,CAAC,CAWH"}
|
|
@@ -23,15 +23,21 @@ export declare function ensureKeyboardModalityTracking(): void;
|
|
|
23
23
|
*/
|
|
24
24
|
export declare function wasKeyboardFocus(): boolean;
|
|
25
25
|
/**
|
|
26
|
-
* Standard manual ring props — the
|
|
27
|
-
* (2px solid `$outlineColor`,
|
|
28
|
-
*
|
|
26
|
+
* Standard manual ring props — the INSET ring geometry
|
|
27
|
+
* (`FOCUS_VISIBLE_RING_INSET`: 2px solid `$outlineColor`, offset −2), spread
|
|
28
|
+
* here so manually-painted rings can never drift from the theme contract.
|
|
29
|
+
* Manual painting exists for roving-focus / activedescendant composites
|
|
30
|
+
* (ToggleGroup segments inside a clipped Group, menu/listbox rows under a
|
|
31
|
+
* clipped overlay, table rows and cells) — items inside clipping ancestors,
|
|
32
|
+
* which is exactly the LC-71 §4 inset carve-out; an offset-0 band there
|
|
33
|
+
* would be severed by the clip. Standalone controls take the offset-0
|
|
34
|
+
* `FOCUS_VISIBLE_RING` via `focusVisibleStyle` / `ensureFocusVisibleRing()`.
|
|
29
35
|
*/
|
|
30
36
|
export declare const keyboardFocusRingProps: {
|
|
37
|
+
readonly outlineOffset: number;
|
|
31
38
|
readonly outlineWidth: number;
|
|
32
39
|
readonly outlineStyle: "solid";
|
|
33
40
|
readonly outlineColor: string;
|
|
34
|
-
readonly outlineOffset: number;
|
|
35
41
|
};
|
|
36
42
|
/**
|
|
37
43
|
* LC-71 RING-ANATOMY — CSS-synchronous ring on a composite's outer boundary.
|
|
@@ -41,7 +47,7 @@ export declare const keyboardFocusRingProps: {
|
|
|
41
47
|
* spawned the inner-Area ring cascade). Inner targets suppress their own
|
|
42
48
|
* outline so the box carries exactly one ring. Class: `mp-composite-ring`.
|
|
43
49
|
*/
|
|
44
|
-
export declare const compositeFocusRingCss = "/* LC-71: ring on the composite outer box; never on the inner field.\n Inset (\u22122px): these frames use overflow:hidden to clip children to radius,\n which severs an outer ring. Do NOT use :has(:focus-visible) on every\n descendant \u2014 that would ring the whole SearchInput when the clear \u2715 is\n focused (two focusables \u2192 two rings, chip-dismiss rule). */\n.mp-composite-ring:focus-visible,\n.mp-composite-ring:has(input:focus),\n.mp-composite-ring:has(textarea:focus),\n.mp-composite-ring:has(.mp-input-area:focus) {\n outline: 2px solid var(--outlineColor, var(--c-outlineColor, CanvasText));\n outline-offset: -2px;\n}\n.mp-composite-ring-deep:has(:focus-visible) {\n outline: 2px solid var(--outlineColor, var(--c-outlineColor, CanvasText));\n outline-offset: -2px;\n}\n.mp-composite-ring input,\n.mp-composite-ring textarea,\n.mp-composite-ring [contenteditable],\n.mp-input-area,\n.mp-input-area:focus,\n.mp-input-area:focus-visible {\n outline: none !important;\n box-shadow: none !important;\n}\n.mp-chip-dismiss:focus-visible {\n outline: none !important;\n}\n.mp-chip-dismiss:focus-visible .mp-chip-dismiss-ring {\n outline: 2px solid var(--outlineColor, var(--c-outlineColor, CanvasText));\n outline-offset:
|
|
50
|
+
export declare const compositeFocusRingCss = "/* LC-71: ring on the composite outer box; never on the inner field.\n Inset (\u22122px): these frames use overflow:hidden to clip children to radius,\n which severs an outer ring. Do NOT use :has(:focus-visible) on every\n descendant \u2014 that would ring the whole SearchInput when the clear \u2715 is\n focused (two focusables \u2192 two rings, chip-dismiss rule). */\n.mp-composite-ring:focus-visible,\n.mp-composite-ring:has(input:focus),\n.mp-composite-ring:has(textarea:focus),\n.mp-composite-ring:has(.mp-input-area:focus) {\n outline: 2px solid var(--outlineColor, var(--c-outlineColor, CanvasText));\n outline-offset: -2px;\n}\n.mp-composite-ring-deep:has(:focus-visible) {\n outline: 2px solid var(--outlineColor, var(--c-outlineColor, CanvasText));\n outline-offset: -2px;\n}\n.mp-composite-ring input,\n.mp-composite-ring textarea,\n.mp-composite-ring [contenteditable],\n.mp-input-area,\n.mp-input-area:focus,\n.mp-input-area:focus-visible {\n outline: none !important;\n box-shadow: none !important;\n}\n.mp-chip-dismiss:focus-visible {\n outline: none !important;\n}\n.mp-chip-dismiss:focus-visible .mp-chip-dismiss-ring {\n outline: 2px solid var(--outlineColor, var(--c-outlineColor, CanvasText));\n outline-offset: 0;\n}";
|
|
45
51
|
/** Idempotently mount the composite-boundary focus-ring stylesheet. */
|
|
46
52
|
export declare function ensureCompositeFocusRing(): void;
|
|
47
53
|
//# sourceMappingURL=keyboardFocusRing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboardFocusRing.d.ts","sourceRoot":"","sources":["../src/keyboardFocusRing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH;;;;GAIG;AACH,wBAAgB,8BAA8B,SAK7C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAG1C;AAID
|
|
1
|
+
{"version":3,"file":"keyboardFocusRing.d.ts","sourceRoot":"","sources":["../src/keyboardFocusRing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH;;;;GAIG;AACH,wBAAgB,8BAA8B,SAK7C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAG1C;AAID;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB;;;;;CAEzB,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,8uCA+BhC,CAAC;AAIH,uEAAuE;AACvE,wBAAgB,wBAAwB,IAAI,IAAI,CAO/C"}
|
|
@@ -21,7 +21,8 @@ export interface FontScopeTables {
|
|
|
21
21
|
/**
|
|
22
22
|
* Resolve the concrete font-family stack registered in the Tamagui config for
|
|
23
23
|
* a font category. Returns undefined when the category font is not registered
|
|
24
|
-
* (the caller then
|
|
24
|
+
* (the caller then uses `fontCategoryStacks` so the knob still writes
|
|
25
|
+
* `--f-family` — live SHC console had the style tag and skipped the family).
|
|
25
26
|
*/
|
|
26
27
|
export declare function getConfiguredFontFamily(category: FontCategory): string | undefined;
|
|
27
28
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FontKnobStyles.d.ts","sourceRoot":"","sources":["../../src/theme/FontKnobStyles.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FontKnobStyles.d.ts","sourceRoot":"","sources":["../../src/theme/FontKnobStyles.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAM5C;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CACtC,YAAY,EACZ;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,SAAS,GAAG,SAAS,CAAA;CAAE,CAgBxE,CAAC;AAqBF,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAelF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,eAAe,GAAG,SAAS,CAgC9F;AAkCD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,YAAY,EACzB,QAAQ,EAAE,YAAY,EACtB,aAAa,GAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,MAAM,GAAG,SAAmC,EACvF,aAAa,GAAE,CACb,KAAK,EAAE,SAAS,GAAG,MAAM,KACtB,eAAe,GAAG,SAAmC,GACzD,MAAM,CAkBR;AAED;;;;GAIG;AACH,wBAAgB,cAAc,SAgC7B"}
|
package/types/theme/Tint.d.ts
CHANGED
|
@@ -7,7 +7,8 @@ export interface TintProps extends PropsWithChildren {
|
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Depth-based tint component. Each nesting level increments the depth
|
|
10
|
-
* and selects a tint from the preset's tints array via
|
|
10
|
+
* and selects a tint from the preset's tints array via
|
|
11
|
+
* `tints[(depth - 1) % length]` so the first Tint is `tints[0]`.
|
|
11
12
|
*
|
|
12
13
|
* Applies a tint sub-theme based on nesting depth.
|
|
13
14
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tint.d.ts","sourceRoot":"","sources":["../../src/theme/Tint.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAA6B,MAAM,OAAO,CAAC;AAM1E,MAAM,WAAW,SAAU,SAAQ,iBAAiB;IAClD,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED
|
|
1
|
+
{"version":3,"file":"Tint.d.ts","sourceRoot":"","sources":["../../src/theme/Tint.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAA6B,MAAM,OAAO,CAAC;AAM1E,MAAM,WAAW,SAAU,SAAQ,iBAAiB;IAClD,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAO,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,2CAiBvE;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
|
|
@@ -1,8 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CSS driver's named durations.
|
|
3
|
+
*
|
|
4
|
+
* `bouncy`, `lazy`, `slow`, `medium` and `quick` are Tamagui's own names and
|
|
5
|
+
* carry Tamagui's own values — a shared name that means something different
|
|
6
|
+
* here is worse than no name, because every consumer reading `animation="medium"`
|
|
7
|
+
* against the upstream docs gets a different answer than the one it renders.
|
|
8
|
+
* MPO-19 X10: `medium` was `ease-in-out 250ms` against stock `ease-in 300ms`,
|
|
9
|
+
* with no improvement argument written down anywhere.
|
|
10
|
+
*
|
|
11
|
+
* `tooltip`, `snappy` and `gentle` are additive — names Tamagui does not use,
|
|
12
|
+
* so they are ours to set and are not a contradiction.
|
|
13
|
+
*/
|
|
1
14
|
export declare const animationConfig: {
|
|
2
15
|
readonly bouncy: "ease-in 200ms";
|
|
3
16
|
readonly lazy: "ease-in 600ms";
|
|
4
17
|
readonly slow: "ease-in 500ms";
|
|
5
|
-
readonly medium: "ease-in
|
|
18
|
+
readonly medium: "ease-in 300ms";
|
|
6
19
|
readonly quick: "ease-in 100ms";
|
|
7
20
|
readonly tooltip: "ease-in 400ms";
|
|
8
21
|
readonly snappy: "ease-out 80ms";
|
|
@@ -14,7 +27,7 @@ export declare const animations: import("@tamagui/web").AnimationDriver<{
|
|
|
14
27
|
readonly bouncy: "ease-in 200ms";
|
|
15
28
|
readonly lazy: "ease-in 600ms";
|
|
16
29
|
readonly slow: "ease-in 500ms";
|
|
17
|
-
readonly medium: "ease-in
|
|
30
|
+
readonly medium: "ease-in 300ms";
|
|
18
31
|
readonly quick: "ease-in 100ms";
|
|
19
32
|
readonly tooltip: "ease-in 400ms";
|
|
20
33
|
readonly snappy: "ease-out 80ms";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../../../src/theme/animations/css.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe;;;;;;;;;CASlB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,eAAe,CAAC;AACzD,eAAO,MAAM,cAAc,EAAmC,aAAa,EAAE,CAAC;AAC9E,eAAO,MAAM,UAAU;;;;;;;;;EAAoC,CAAC;AAO5D,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAE3B,CAAC"}
|
|
1
|
+
{"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../../../src/theme/animations/css.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe;;;;;;;;;CASlB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,eAAe,CAAC;AACzD,eAAO,MAAM,cAAc,EAAmC,aAAa,EAAE,CAAC;AAC9E,eAAO,MAAM,UAAU;;;;;;;;;EAAoC,CAAC;AAO5D,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAE3B,CAAC"}
|