@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplatform.one/theme",
3
- "version": "7.81.0",
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.0",
76
- "@multiplatform.one/store": "^7.81.0",
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.0",
93
- "@multiplatform.one/test-utils": "7.81.0",
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 sheet's top
32
- * edge, 6pt down, drawn over the frame rather than floating on the scrim.
33
- * Spread on `Sheet.Handle`; the frame keeps `sheetGrabberClearance` clear.
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: 0,
44
- marginBottom: -11,
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
+ });
@@ -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 sheet's top
12
- * edge, 6pt down, drawn over the frame rather than floating on the scrim.
13
- * Spread on `Sheet.Handle`; the frame keeps `sheetGrabberClearance` clear.
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: 0;
24
- readonly marginBottom: -11;
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;;;;GAIG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;CAWf,CAAC;AAEX,kEAAkE;AAClE,eAAO,MAAM,qBAAqB,KAAK,CAAC;AA6DxC,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
+ {"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;AAGvD;;;;;;;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,2CA2GvB"}
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"}