@multiplatform.one/theme 7.81.0 → 7.81.2
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/overlaySurfaces.tsx +14 -5
- package/src/theme/sheetGrabber.spec.ts +18 -0
- package/src/theme/theme.tsx +2 -0
- package/src/theme/touchManipulation.ts +27 -0
- package/types/theme/overlaySurfaces.d.ts +13 -5
- package/types/theme/overlaySurfaces.d.ts.map +1 -1
- package/types/theme/theme.d.ts.map +1 -1
- package/types/theme/touchManipulation.d.ts +12 -0
- package/types/theme/touchManipulation.d.ts.map +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/theme",
|
|
3
|
-
"version": "7.81.
|
|
3
|
+
"version": "7.81.2",
|
|
4
4
|
"description": "Tamagui theme system for multiplatform.one",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"multiplatform",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"access": "public"
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@multiplatform.one/platform": "^7.81.
|
|
76
|
-
"@multiplatform.one/store": "^7.81.
|
|
75
|
+
"@multiplatform.one/platform": "^7.81.2",
|
|
76
|
+
"@multiplatform.one/store": "^7.81.2",
|
|
77
77
|
"@tamagui/animations-react-native": "2.7.6",
|
|
78
78
|
"@tamagui/colors": "2.7.6",
|
|
79
79
|
"@tamagui/config": "2.7.6",
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@expo/prebuild-config": "55.0.18",
|
|
92
|
-
"@multiplatform.one/config": "7.81.
|
|
93
|
-
"@multiplatform.one/test-utils": "7.81.
|
|
92
|
+
"@multiplatform.one/config": "7.81.2",
|
|
93
|
+
"@multiplatform.one/test-utils": "7.81.2",
|
|
94
94
|
"@tamagui/animations-css": "2.7.6",
|
|
95
95
|
"@tamagui/animations-reanimated": "2.7.6",
|
|
96
96
|
"@tamagui/font-inter": "2.7.6",
|
|
@@ -28,9 +28,11 @@ import {
|
|
|
28
28
|
export const overlayScrim = "$shadow4" as const;
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
* A sheet's grabber (HIG, FZ-8557): a 36×5 capsule inside the
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* A sheet's grabber (HIG, FZ-8557, FZ-8648): a 36×5 capsule 5pt inside the
|
|
32
|
+
* sheet's top edge, drawn over the frame rather than floating on the scrim.
|
|
33
|
+
* Its margins net to no height, so it lands the same on a web `Sheet.Handle`
|
|
34
|
+
* laid out above the frame and on a native grab zone's first child. The one
|
|
35
|
+
* recipe for every sheet: spread it and set nothing else.
|
|
34
36
|
*/
|
|
35
37
|
export const sheetGrabber = {
|
|
36
38
|
width: 36,
|
|
@@ -40,14 +42,21 @@ export const sheetGrabber = {
|
|
|
40
42
|
opacity: 0.45,
|
|
41
43
|
alignSelf: "center",
|
|
42
44
|
marginHorizontal: 0,
|
|
43
|
-
marginTop:
|
|
44
|
-
marginBottom: -
|
|
45
|
+
marginTop: 5,
|
|
46
|
+
marginBottom: -10,
|
|
45
47
|
zIndex: 10,
|
|
46
48
|
} as const;
|
|
47
49
|
|
|
48
50
|
/** The top inset a sheet's content keeps clear of its grabber. */
|
|
49
51
|
export const sheetGrabberClearance = 16;
|
|
50
52
|
|
|
53
|
+
/** A native sheet's grab zone, the target around `sheetGrabber`. */
|
|
54
|
+
export const sheetGrabberZone = {
|
|
55
|
+
alignSelf: "stretch",
|
|
56
|
+
alignItems: "center",
|
|
57
|
+
height: 21,
|
|
58
|
+
} as const;
|
|
59
|
+
|
|
51
60
|
// ── Overlay frame focus (LC-71) ──────────────────────────────────────────
|
|
52
61
|
// Radix Dialog.Content / Primer Dialog are tabIndex=-1 and auto-focused on
|
|
53
62
|
// open. The frame is not a control: UA :focus-visible must not ring the
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { sheetGrabber, sheetGrabberClearance, sheetGrabberZone } from "./overlaySurfaces";
|
|
3
|
+
|
|
4
|
+
describe("sheetGrabber (FZ-8648)", () => {
|
|
5
|
+
it("is the HIG capsule, 36×5 and 5pt inside the sheet's top edge", () => {
|
|
6
|
+
expect(sheetGrabber).toMatchObject({ width: 36, height: 5, marginTop: 5, alignSelf: "center" });
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("takes no height, so it lands the same above a frame and inside a grab zone", () => {
|
|
10
|
+
expect(sheetGrabber.marginTop + sheetGrabber.height + sheetGrabber.marginBottom).toBe(0);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("clears a frame's content and fits its grab zone", () => {
|
|
14
|
+
const end = sheetGrabber.marginTop + sheetGrabber.height;
|
|
15
|
+
expect(sheetGrabberClearance).toBeGreaterThan(end);
|
|
16
|
+
expect(sheetGrabberZone.height).toBeGreaterThan(end);
|
|
17
|
+
});
|
|
18
|
+
});
|
package/src/theme/theme.tsx
CHANGED
|
@@ -19,6 +19,7 @@ import { defaultPreset } from "./presets";
|
|
|
19
19
|
import { ScaleStyles } from "./scale/ScaleStyles";
|
|
20
20
|
import { useActiveScale } from "./scale/useActiveScale";
|
|
21
21
|
import { type ThemeConfig, getPreset } from "./shared";
|
|
22
|
+
import { touchManipulationCss } from "./touchManipulation";
|
|
22
23
|
import { useSchemePreference } from "./useSchemePreference";
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -168,6 +169,7 @@ export function ThemeProvider<T extends CreateTamaguiProps>({
|
|
|
168
169
|
"::view-transition-old(root), ::view-transition-new(root) {",
|
|
169
170
|
" animation-duration: calc(var(--mp-transition) * 1);",
|
|
170
171
|
"}",
|
|
172
|
+
touchManipulationCss,
|
|
171
173
|
].join("\n");
|
|
172
174
|
document.head.appendChild(style);
|
|
173
175
|
}, []);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LC-196 TOUCH-MANIPULATION: every web pressable sets `touch-action:
|
|
3
|
+
* manipulation` so a tap fires without the double-tap-zoom wait, while pinch
|
|
4
|
+
* zoom stays on. ThemeProvider injects this once with its global styles.
|
|
5
|
+
* `:where()` keeps it at zero specificity so a drag surface that sets its own
|
|
6
|
+
* `touch-action: none` still wins. `button` sits outside it at element
|
|
7
|
+
* specificity because the Tamagui reset's `button { all: unset }` would
|
|
8
|
+
* otherwise put it back to `auto`; this sheet is appended after the reset.
|
|
9
|
+
*/
|
|
10
|
+
export const pressableSelectors = [
|
|
11
|
+
"a[href]",
|
|
12
|
+
"summary",
|
|
13
|
+
"label[for]",
|
|
14
|
+
'[role="button"]',
|
|
15
|
+
'[role="link"]',
|
|
16
|
+
'[role="tab"]',
|
|
17
|
+
'[role="menuitem"]',
|
|
18
|
+
'[role="menuitemradio"]',
|
|
19
|
+
'[role="menuitemcheckbox"]',
|
|
20
|
+
'[role="option"]',
|
|
21
|
+
'[role="switch"]',
|
|
22
|
+
'[role="checkbox"]',
|
|
23
|
+
'[role="radio"]',
|
|
24
|
+
'[tabindex="0"]',
|
|
25
|
+
] as const;
|
|
26
|
+
|
|
27
|
+
export const touchManipulationCss = `:where(${pressableSelectors.join(", ")}),\nbutton {\n touch-action: manipulation;\n}`;
|
|
@@ -8,9 +8,11 @@ import { type DialogContentProps as TamaguiDialogContentProps, type SizeTokens,
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const overlayScrim: "$shadow4";
|
|
10
10
|
/**
|
|
11
|
-
* A sheet's grabber (HIG, FZ-8557): a 36×5 capsule inside the
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* A sheet's grabber (HIG, FZ-8557, FZ-8648): a 36×5 capsule 5pt inside the
|
|
12
|
+
* sheet's top edge, drawn over the frame rather than floating on the scrim.
|
|
13
|
+
* Its margins net to no height, so it lands the same on a web `Sheet.Handle`
|
|
14
|
+
* laid out above the frame and on a native grab zone's first child. The one
|
|
15
|
+
* recipe for every sheet: spread it and set nothing else.
|
|
14
16
|
*/
|
|
15
17
|
export declare const sheetGrabber: {
|
|
16
18
|
readonly width: 36;
|
|
@@ -20,12 +22,18 @@ export declare const sheetGrabber: {
|
|
|
20
22
|
readonly opacity: 0.45;
|
|
21
23
|
readonly alignSelf: "center";
|
|
22
24
|
readonly marginHorizontal: 0;
|
|
23
|
-
readonly marginTop:
|
|
24
|
-
readonly marginBottom: -
|
|
25
|
+
readonly marginTop: 5;
|
|
26
|
+
readonly marginBottom: -10;
|
|
25
27
|
readonly zIndex: 10;
|
|
26
28
|
};
|
|
27
29
|
/** The top inset a sheet's content keeps clear of its grabber. */
|
|
28
30
|
export declare const sheetGrabberClearance = 16;
|
|
31
|
+
/** A native sheet's grab zone, the target around `sheetGrabber`. */
|
|
32
|
+
export declare const sheetGrabberZone: {
|
|
33
|
+
readonly alignSelf: "stretch";
|
|
34
|
+
readonly alignItems: "center";
|
|
35
|
+
readonly height: 21;
|
|
36
|
+
};
|
|
29
37
|
type OpenAutoFocus = (event: Event) => void;
|
|
30
38
|
/**
|
|
31
39
|
* The house open focus for a raw `Dialog.Content`, which `DialogContent` and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlaySurfaces.d.ts","sourceRoot":"","sources":["../../src/theme/overlaySurfaces.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAOL,KAAK,kBAAkB,IAAI,yBAAyB,EAEpD,KAAK,UAAU,EACf,KAAK,cAAc,EAEpB,MAAM,SAAS,CAAC;AAEjB;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAG,UAAmB,CAAC;AAEhD
|
|
1
|
+
{"version":3,"file":"overlaySurfaces.d.ts","sourceRoot":"","sources":["../../src/theme/overlaySurfaces.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAOL,KAAK,kBAAkB,IAAI,yBAAyB,EAEpD,KAAK,UAAU,EACf,KAAK,cAAc,EAEpB,MAAM,SAAS,CAAC;AAEjB;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAG,UAAmB,CAAC;AAEhD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;CAWf,CAAC;AAEX,kEAAkE;AAClE,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC,oEAAoE;AACpE,eAAO,MAAM,gBAAgB;;;;CAInB,CAAC;AA6DX,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAmC5C;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,eAAe,EAAE,EAAE;IAAE,eAAe,CAAC,EAAE,aAAa,CAAA;CAAE,GAAG,IAAI,CAG9F;AAID,MAAM,WAAW,wBAAwB;IACvC,4EAA4E;IAC5E,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,mDAE9B,CAAC;AAEH,wBAAgB,sBAAsB,IAAI,wBAAwB,CAEjE;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAQD,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,yBAAyB,EAAE,MAAM,CAAC,GAAG;IACzE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,aAAa;eAJb,SAAS;WACb,UAAU;kDAcjB,CAAC;AA8DH;;;;;;GAMG;AACH,eAAO,MAAM,aAAa;;;;;;;;eAEiB,SAAS;kDAelD,CAAC;AAOH,eAAO,MAAM,kBAAkB;eA5GlB,SAAS;WACb,UAAU;kDAqHlB,CAAC;AAgCF,eAAO,MAAM,kBAAkB;;;;;;;;eAEY,SAAS;kDAelD,CAAC;AAiBH,eAAO,MAAM,cAAc;eALd,SAAS;IACpB,iEAAiE;sBAC/C,aAAa;kDA0BhC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/theme/theme.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,kBAAkB,EAEvB,KAAK,oBAAoB,EAG1B,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAU/C,OAAO,EAAE,KAAK,WAAW,EAAa,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/theme/theme.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,kBAAkB,EAEvB,KAAK,oBAAoB,EAG1B,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAU/C,OAAO,EAAE,KAAK,WAAW,EAAa,MAAM,UAAU,CAAC;AAIvD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,IAAI,CAkB5D;AAMD,MAAM,WAAW,kBAAkB,CACjC,CAAC,SAAS,kBAAkB,GAAG,kBAAkB,CACjD,SAAQ,iBAAiB,CAAC,IAAI,CAAC,oBAAoB,EAAE,QAAQ,GAAG,cAAc,CAAC,CAAC;IAChF,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,UAAU,CAAC,cAAc,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;KAChE,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC;IAC3D,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAChC;AAkBD,wBAAgB,aAAa,CAAC,CAAC,SAAS,kBAAkB,EAAE,EAC1D,QAAQ,EACR,MAAM,EACN,WAAW,EACX,GAAG,YAAY,EAChB,EAAE,kBAAkB,CAAC,CAAC,CAAC,2CA4GvB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LC-196 TOUCH-MANIPULATION: every web pressable sets `touch-action:
|
|
3
|
+
* manipulation` so a tap fires without the double-tap-zoom wait, while pinch
|
|
4
|
+
* zoom stays on. ThemeProvider injects this once with its global styles.
|
|
5
|
+
* `:where()` keeps it at zero specificity so a drag surface that sets its own
|
|
6
|
+
* `touch-action: none` still wins. `button` sits outside it at element
|
|
7
|
+
* specificity because the Tamagui reset's `button { all: unset }` would
|
|
8
|
+
* otherwise put it back to `auto`; this sheet is appended after the reset.
|
|
9
|
+
*/
|
|
10
|
+
export declare const pressableSelectors: readonly ["a[href]", "summary", "label[for]", "[role=\"button\"]", "[role=\"link\"]", "[role=\"tab\"]", "[role=\"menuitem\"]", "[role=\"menuitemradio\"]", "[role=\"menuitemcheckbox\"]", "[role=\"option\"]", "[role=\"switch\"]", "[role=\"checkbox\"]", "[role=\"radio\"]", "[tabindex=\"0\"]"];
|
|
11
|
+
export declare const touchManipulationCss: string;
|
|
12
|
+
//# sourceMappingURL=touchManipulation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"touchManipulation.d.ts","sourceRoot":"","sources":["../../src/theme/touchManipulation.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,oSAerB,CAAC;AAEX,eAAO,MAAM,oBAAoB,QAA0F,CAAC"}
|