react-native-gtkx 0.2.0-alpha.1 → 0.2.0-alpha.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/README.md +11 -2
- package/dist/adw/widgets.generated.d.ts +4 -4
- package/dist/adw/widgets.generated.js +51 -51
- package/dist/adw/widgets.generated.js.map +1 -1
- package/dist/animated/create-animated.d.ts +2 -0
- package/dist/animated/create-animated.js +2 -0
- package/dist/animated/create-animated.js.map +1 -1
- package/dist/animated/index.d.ts +2 -0
- package/dist/animated/index.js +1 -0
- package/dist/animated/index.js.map +1 -1
- package/dist/animated/value-xy.d.ts +41 -0
- package/dist/animated/value-xy.js +90 -0
- package/dist/animated/value-xy.js.map +1 -0
- package/dist/animated/value.d.ts +9 -0
- package/dist/animated/value.js +30 -2
- package/dist/animated/value.js.map +1 -1
- package/dist/common/icon.d.ts +23 -0
- package/dist/common/icon.js +14 -0
- package/dist/common/icon.js.map +1 -0
- package/dist/common/index.d.ts +2 -0
- package/dist/common/index.js +2 -0
- package/dist/common/index.js.map +1 -1
- package/dist/common/list.d.ts +82 -0
- package/dist/common/list.js +166 -0
- package/dist/common/list.js.map +1 -0
- package/dist/common/widget.d.ts +1 -22
- package/dist/common/widget.js +75 -8
- package/dist/common/widget.js.map +1 -1
- package/dist/components/animated.d.ts +4 -2
- package/dist/components/animated.js +3 -1
- package/dist/components/animated.js.map +1 -1
- package/dist/components/app-registry.d.ts +26 -0
- package/dist/components/app-registry.js.map +1 -1
- package/dist/components/host-node.d.ts +7 -0
- package/dist/components/host-node.js +26 -1
- package/dist/components/host-node.js.map +1 -1
- package/dist/components/index.d.ts +6 -2
- package/dist/components/index.js +2 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/measure.d.ts +13 -0
- package/dist/components/measure.js +51 -0
- package/dist/components/measure.js.map +1 -0
- package/dist/components/modal.d.ts +1 -1
- package/dist/components/press-event.d.ts +28 -0
- package/dist/components/press-event.js +46 -0
- package/dist/components/press-event.js.map +1 -0
- package/dist/components/pressable.d.ts +2 -6
- package/dist/components/pressable.js +14 -8
- package/dist/components/pressable.js.map +1 -1
- package/dist/components/scroll-view.d.ts +4 -0
- package/dist/components/scroll-view.js +8 -2
- package/dist/components/scroll-view.js.map +1 -1
- package/dist/components/text-input.js +1 -1
- package/dist/components/text-input.js.map +1 -1
- package/dist/components/text.js +25 -1
- package/dist/components/text.js.map +1 -1
- package/dist/components/use-layout-child.js +17 -14
- package/dist/components/use-layout-child.js.map +1 -1
- package/dist/components/view.d.ts +9 -4
- package/dist/components/view.js +8 -2
- package/dist/components/view.js.map +1 -1
- package/dist/contracts.d.ts +19 -3
- package/dist/contracts.js.map +1 -1
- package/dist/gtk/index.d.ts +2 -1
- package/dist/gtk/index.js +8 -1
- package/dist/gtk/index.js.map +1 -1
- package/dist/gtk/widgets.generated.d.ts +14 -14
- package/dist/gtk/widgets.generated.js +101 -102
- package/dist/gtk/widgets.generated.js.map +1 -1
- package/dist/gtk/window-actions.d.ts +77 -0
- package/dist/gtk/window-actions.js +193 -0
- package/dist/gtk/window-actions.js.map +1 -0
- package/dist/gtkx/bridge/geometry.d.ts +15 -0
- package/dist/gtkx/bridge/geometry.js +38 -0
- package/dist/gtkx/bridge/geometry.js.map +1 -0
- package/dist/gtkx/bridge/index.d.ts +2 -0
- package/dist/gtkx/bridge/index.js +7 -2
- package/dist/gtkx/bridge/index.js.map +1 -1
- package/dist/gtkx/bridge/slot-portal.d.ts +12 -0
- package/dist/gtkx/bridge/slot-portal.js +17 -0
- package/dist/gtkx/bridge/slot-portal.js.map +1 -0
- package/dist/gtkx/bridge/svg-node.js +10 -54
- package/dist/gtkx/bridge/svg-node.js.map +1 -1
- package/dist/gtkx/bridge/use-signal.js +2 -2
- package/dist/gtkx/bridge/use-signal.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/data/generated.d.ts +99 -77
- package/dist/mcp/data/generated.js +107 -76
- package/dist/mcp/data/generated.js.map +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/navigation/sidebar.d.ts +31 -1
- package/dist/navigation/sidebar.js +12 -2
- package/dist/navigation/sidebar.js.map +1 -1
- package/dist/responder/system.d.ts +27 -0
- package/dist/responder/system.js +184 -0
- package/dist/responder/system.js.map +1 -0
- package/dist/responder/touch-history.d.ts +10 -0
- package/dist/responder/touch-history.js +78 -0
- package/dist/responder/touch-history.js.map +1 -0
- package/dist/responder/types.d.ts +63 -0
- package/dist/responder/types.js +29 -0
- package/dist/responder/types.js.map +1 -0
- package/dist/responder/use-responder.d.ts +12 -0
- package/dist/responder/use-responder.js +98 -0
- package/dist/responder/use-responder.js.map +1 -0
- package/dist/runner/host-dev.js +3 -1
- package/dist/runner/host-dev.js.map +1 -1
- package/dist/runner/host.js +5 -1
- package/dist/runner/host.js.map +1 -1
- package/dist/runner/index.js +1 -1
- package/dist/runner/index.js.map +1 -1
- package/dist/sea/gtkx-config-module.js +1 -1
- package/dist/sea/gtkx-config-module.js.map +1 -1
- package/dist/style/box-shadow.d.ts +7 -0
- package/dist/style/box-shadow.js +197 -0
- package/dist/style/box-shadow.js.map +1 -0
- package/dist/style/index.d.ts +2 -0
- package/dist/style/index.js +2 -0
- package/dist/style/index.js.map +1 -1
- package/dist/style/split-style.d.ts +5 -2
- package/dist/style/split-style.js +31 -3
- package/dist/style/split-style.js.map +1 -1
- package/dist/style/text-decoration.d.ts +15 -0
- package/dist/style/text-decoration.js +26 -0
- package/dist/style/text-decoration.js.map +1 -0
- package/dist/style/visual-css.js +37 -1
- package/dist/style/visual-css.js.map +1 -1
- package/dist/svg/gradient-geometry.js +2 -5
- package/dist/svg/gradient-geometry.js.map +1 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/vendor/react-native/pan-responder.d.ts +102 -0
- package/dist/vendor/react-native/pan-responder.js +196 -0
- package/dist/vendor/react-native/pan-responder.js.map +1 -0
- package/dist/vendor/react-native/touch-history-math.d.ts +18 -0
- package/dist/vendor/react-native/touch-history-math.js +102 -0
- package/dist/vendor/react-native/touch-history-math.js.map +1 -0
- package/dist/vite/index.js +1 -1
- package/dist/vite/index.js.map +1 -1
- package/dist/vitest/index.d.ts +1 -1
- package/dist/vitest/index.js.map +1 -1
- package/package.json +9 -9
package/dist/style/visual-css.js
CHANGED
|
@@ -5,12 +5,19 @@
|
|
|
5
5
|
// GTK4 CSS is not web CSS. What this generator relies on:
|
|
6
6
|
// - background-color, border-*, border-radius (incl. per-corner), opacity,
|
|
7
7
|
// color, font-*, letter-spacing: supported by GTK4;
|
|
8
|
+
// - box-shadow and outline-*: supported by GTK4, and used by Adwaita itself
|
|
9
|
+
// for the `.card`/`.boxed-list` frame and for every focus ring in the
|
|
10
|
+
// theme — which is why an app cannot reproduce the platform's own look
|
|
11
|
+
// without them. box-shadow is compiled by ./box-shadow.ts;
|
|
8
12
|
// - line-height: supported since GTK 4.6 (we target 4.20+);
|
|
9
13
|
// - text-align does NOT exist in GTK CSS — textAlign is applied by the Text
|
|
10
14
|
// component via widget properties (justify/xalign), so it is skipped here;
|
|
15
|
+
// - text-decoration does not exist for GTK widgets either: Pango carries it,
|
|
16
|
+
// and the Text component applies textDecorationLine as label attributes;
|
|
11
17
|
// - transform does NOT exist as a widget property in GTK4 CSS either: it is
|
|
12
18
|
// composed into a matrix by ./transform.ts and applied as the GskTransform
|
|
13
19
|
// of the child's allocation, so it is skipped here as well.
|
|
20
|
+
import { boxShadowToCss } from "./box-shadow";
|
|
14
21
|
import { parseColor } from "./colors";
|
|
15
22
|
import { warnOnce } from "./dev-warning";
|
|
16
23
|
const px = (value) => `${value}px`;
|
|
@@ -44,6 +51,12 @@ export const visualStyleToCss = (visual) => {
|
|
|
44
51
|
if (visual.opacity !== undefined) {
|
|
45
52
|
decls.push(`opacity: ${clamp01(visual.opacity)};`);
|
|
46
53
|
}
|
|
54
|
+
if (visual.boxShadow !== undefined) {
|
|
55
|
+
const shadow = boxShadowToCss(visual.boxShadow);
|
|
56
|
+
if (shadow !== null) {
|
|
57
|
+
decls.push(`box-shadow: ${shadow};`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
47
60
|
// GTK defaults border-style to none — width alone renders nothing. An
|
|
48
61
|
// explicit borderStyle wins (GTK4 CSS supports solid/dotted/dashed);
|
|
49
62
|
// otherwise any positive border width turns the border on with "solid".
|
|
@@ -107,6 +120,28 @@ export const visualStyleToCss = (visual) => {
|
|
|
107
120
|
if (visual.borderBottomLeftRadius !== undefined) {
|
|
108
121
|
decls.push(`border-bottom-left-radius: ${px(visual.borderBottomLeftRadius)};`);
|
|
109
122
|
}
|
|
123
|
+
// outline is a ring around the border box that takes no layout space, so
|
|
124
|
+
// unlike `border` it needs no Yoga involvement at all — GTK4 draws it from
|
|
125
|
+
// CSS exactly as the web does, which is how Adwaita itself paints every
|
|
126
|
+
// focus ring in the theme. GTK, like the web, defaults outline-style to
|
|
127
|
+
// `none`, so a width on its own would draw nothing; the same auto-solid
|
|
128
|
+
// rule the borders above use applies.
|
|
129
|
+
const hasVisibleOutlineWidth = visual.outlineWidth !== undefined && visual.outlineWidth > 0;
|
|
130
|
+
if (visual.outlineStyle !== undefined) {
|
|
131
|
+
decls.push(`outline-style: ${visual.outlineStyle};`);
|
|
132
|
+
}
|
|
133
|
+
else if (hasVisibleOutlineWidth) {
|
|
134
|
+
decls.push("outline-style: solid;");
|
|
135
|
+
}
|
|
136
|
+
if (visual.outlineWidth !== undefined) {
|
|
137
|
+
decls.push(`outline-width: ${px(visual.outlineWidth)};`);
|
|
138
|
+
}
|
|
139
|
+
if (visual.outlineColor !== undefined) {
|
|
140
|
+
pushColor(decls, "outline-color", visual.outlineColor, "outlineColor");
|
|
141
|
+
}
|
|
142
|
+
if (visual.outlineOffset !== undefined) {
|
|
143
|
+
decls.push(`outline-offset: ${px(visual.outlineOffset)};`);
|
|
144
|
+
}
|
|
110
145
|
if (visual.color !== undefined) {
|
|
111
146
|
pushColor(decls, "color", visual.color, "color");
|
|
112
147
|
}
|
|
@@ -128,7 +163,8 @@ export const visualStyleToCss = (visual) => {
|
|
|
128
163
|
if (visual.lineHeight !== undefined) {
|
|
129
164
|
decls.push(`line-height: ${px(visual.lineHeight)};`);
|
|
130
165
|
}
|
|
131
|
-
// visual.textAlign, visual.transform:
|
|
166
|
+
// visual.textAlign, visual.textDecorationLine, visual.transform:
|
|
167
|
+
// intentionally not CSS (see header).
|
|
132
168
|
return decls.join("\n");
|
|
133
169
|
};
|
|
134
170
|
//# sourceMappingURL=visual-css.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"visual-css.js","sourceRoot":"","sources":["../../src/style/visual-css.ts"],"names":[],"mappings":"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","sourcesContent":["// Compiles a VisualStyle into a GTK4 CSS declaration block (no selector).\n// Pure module — the resulting string is registered as a class through an\n// injected `css` function (see registry.ts / registry.gtkx.ts).\n//\n// GTK4 CSS is not web CSS. What this generator relies on:\n// - background-color, border-*, border-radius (incl. per-corner), opacity,\n// color, font-*, letter-spacing: supported by GTK4;\n// - line-height: supported since GTK 4.6 (we target 4.20+);\n// - text-align does NOT exist in GTK CSS — textAlign is applied by the Text\n// component via widget properties (justify/xalign), so it is skipped here;\n// - transform does NOT exist as a widget property in GTK4 CSS either: it is\n// composed into a matrix by ./transform.ts and applied as the GskTransform\n// of the child's allocation, so it is skipped here as well.\n\nimport type { VisualStyle } from \"../contracts\"\nimport { parseColor } from \"./colors\"\nimport { warnOnce } from \"./dev-warning\"\n\nconst px = (value: number): string => `${value}px`\n\nconst clamp01 = (value: number): number => Math.min(1, Math.max(0, value))\n\nconst pushColor = (\n declarations: string[],\n cssProperty: string,\n value: string,\n styleProperty: string,\n): void => {\n const parsed = parseColor(value)\n if (parsed === null) {\n warnOnce(\n `invalid-color:${styleProperty}:${value}`,\n `[react-native-gtkx] Invalid color ${JSON.stringify(value)} in \"${styleProperty}\" — declaration dropped`,\n )\n return\n }\n declarations.push(`${cssProperty}: ${parsed};`)\n}\n\nconst formatFontFamily = (family: string): string => {\n const trimmed = family.trim()\n if (/^(\".*\"|'.*')$/.test(trimmed)) {\n return trimmed\n }\n return /^[A-Za-z][\\w-]*$/.test(trimmed)\n ? trimmed\n : `\"${trimmed.replace(/\"/g, '\\\\\"')}\"`\n}\n\n/**\n * Renders a VisualStyle as GTK CSS declarations (one per line, stable\n * order). Returns \"\" when the style produces no CSS (e.g. transform-only).\n */\nexport const visualStyleToCss = (visual: VisualStyle): string => {\n const decls: string[] = []\n\n if (visual.backgroundColor !== undefined) {\n pushColor(\n decls,\n \"background-color\",\n visual.backgroundColor,\n \"backgroundColor\",\n )\n }\n if (visual.opacity !== undefined) {\n decls.push(`opacity: ${clamp01(visual.opacity)};`)\n }\n\n // GTK defaults border-style to none — width alone renders nothing. An\n // explicit borderStyle wins (GTK4 CSS supports solid/dotted/dashed);\n // otherwise any positive border width turns the border on with \"solid\".\n const hasVisibleBorderWidth = [\n visual.borderWidth,\n visual.borderTopWidth,\n visual.borderRightWidth,\n visual.borderBottomWidth,\n visual.borderLeftWidth,\n ].some((width) => width !== undefined && width > 0)\n if (visual.borderStyle !== undefined) {\n decls.push(`border-style: ${visual.borderStyle};`)\n } else if (hasVisibleBorderWidth) {\n decls.push(\"border-style: solid;\")\n }\n // Shorthands first, then per-side overrides so the sides win.\n if (visual.borderWidth !== undefined) {\n decls.push(`border-width: ${px(visual.borderWidth)};`)\n }\n if (visual.borderTopWidth !== undefined) {\n decls.push(`border-top-width: ${px(visual.borderTopWidth)};`)\n }\n if (visual.borderRightWidth !== undefined) {\n decls.push(`border-right-width: ${px(visual.borderRightWidth)};`)\n }\n if (visual.borderBottomWidth !== undefined) {\n decls.push(`border-bottom-width: ${px(visual.borderBottomWidth)};`)\n }\n if (visual.borderLeftWidth !== undefined) {\n decls.push(`border-left-width: ${px(visual.borderLeftWidth)};`)\n }\n if (visual.borderColor !== undefined) {\n pushColor(decls, \"border-color\", visual.borderColor, \"borderColor\")\n }\n if (visual.borderTopColor !== undefined) {\n pushColor(\n decls,\n \"border-top-color\",\n visual.borderTopColor,\n \"borderTopColor\",\n )\n }\n if (visual.borderRightColor !== undefined) {\n pushColor(\n decls,\n \"border-right-color\",\n visual.borderRightColor,\n \"borderRightColor\",\n )\n }\n if (visual.borderBottomColor !== undefined) {\n pushColor(\n decls,\n \"border-bottom-color\",\n visual.borderBottomColor,\n \"borderBottomColor\",\n )\n }\n if (visual.borderLeftColor !== undefined) {\n pushColor(\n decls,\n \"border-left-color\",\n visual.borderLeftColor,\n \"borderLeftColor\",\n )\n }\n if (visual.borderRadius !== undefined) {\n decls.push(`border-radius: ${px(visual.borderRadius)};`)\n }\n // Per-corner radii come after the shorthand so they override it.\n if (visual.borderTopLeftRadius !== undefined) {\n decls.push(`border-top-left-radius: ${px(visual.borderTopLeftRadius)};`)\n }\n if (visual.borderTopRightRadius !== undefined) {\n decls.push(`border-top-right-radius: ${px(visual.borderTopRightRadius)};`)\n }\n if (visual.borderBottomRightRadius !== undefined) {\n decls.push(\n `border-bottom-right-radius: ${px(visual.borderBottomRightRadius)};`,\n )\n }\n if (visual.borderBottomLeftRadius !== undefined) {\n decls.push(\n `border-bottom-left-radius: ${px(visual.borderBottomLeftRadius)};`,\n )\n }\n\n if (visual.color !== undefined) {\n pushColor(decls, \"color\", visual.color, \"color\")\n }\n if (visual.fontFamily !== undefined) {\n decls.push(`font-family: ${formatFontFamily(visual.fontFamily)};`)\n }\n if (visual.fontSize !== undefined) {\n decls.push(`font-size: ${px(visual.fontSize)};`)\n }\n if (visual.fontStyle !== undefined) {\n decls.push(`font-style: ${visual.fontStyle};`)\n }\n if (visual.fontWeight !== undefined) {\n decls.push(`font-weight: ${visual.fontWeight};`)\n }\n if (visual.letterSpacing !== undefined) {\n decls.push(`letter-spacing: ${px(visual.letterSpacing)};`)\n }\n if (visual.lineHeight !== undefined) {\n decls.push(`line-height: ${px(visual.lineHeight)};`)\n }\n\n // visual.textAlign, visual.transform: intentionally not CSS (see header).\n\n return decls.join(\"\\n\")\n}\n"]}
|
|
1
|
+
{"version":3,"file":"visual-css.js","sourceRoot":"","sources":["../../src/style/visual-css.ts"],"names":[],"mappings":"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","sourcesContent":["// Compiles a VisualStyle into a GTK4 CSS declaration block (no selector).\n// Pure module — the resulting string is registered as a class through an\n// injected `css` function (see registry.ts / registry.gtkx.ts).\n//\n// GTK4 CSS is not web CSS. What this generator relies on:\n// - background-color, border-*, border-radius (incl. per-corner), opacity,\n// color, font-*, letter-spacing: supported by GTK4;\n// - box-shadow and outline-*: supported by GTK4, and used by Adwaita itself\n// for the `.card`/`.boxed-list` frame and for every focus ring in the\n// theme — which is why an app cannot reproduce the platform's own look\n// without them. box-shadow is compiled by ./box-shadow.ts;\n// - line-height: supported since GTK 4.6 (we target 4.20+);\n// - text-align does NOT exist in GTK CSS — textAlign is applied by the Text\n// component via widget properties (justify/xalign), so it is skipped here;\n// - text-decoration does not exist for GTK widgets either: Pango carries it,\n// and the Text component applies textDecorationLine as label attributes;\n// - transform does NOT exist as a widget property in GTK4 CSS either: it is\n// composed into a matrix by ./transform.ts and applied as the GskTransform\n// of the child's allocation, so it is skipped here as well.\n\nimport type { VisualStyle } from \"../contracts\"\nimport { boxShadowToCss } from \"./box-shadow\"\nimport { parseColor } from \"./colors\"\nimport { warnOnce } from \"./dev-warning\"\n\nconst px = (value: number): string => `${value}px`\n\nconst clamp01 = (value: number): number => Math.min(1, Math.max(0, value))\n\nconst pushColor = (\n declarations: string[],\n cssProperty: string,\n value: string,\n styleProperty: string,\n): void => {\n const parsed = parseColor(value)\n if (parsed === null) {\n warnOnce(\n `invalid-color:${styleProperty}:${value}`,\n `[react-native-gtkx] Invalid color ${JSON.stringify(value)} in \"${styleProperty}\" — declaration dropped`,\n )\n return\n }\n declarations.push(`${cssProperty}: ${parsed};`)\n}\n\nconst formatFontFamily = (family: string): string => {\n const trimmed = family.trim()\n if (/^(\".*\"|'.*')$/.test(trimmed)) {\n return trimmed\n }\n return /^[A-Za-z][\\w-]*$/.test(trimmed)\n ? trimmed\n : `\"${trimmed.replace(/\"/g, '\\\\\"')}\"`\n}\n\n/**\n * Renders a VisualStyle as GTK CSS declarations (one per line, stable\n * order). Returns \"\" when the style produces no CSS (e.g. transform-only).\n */\nexport const visualStyleToCss = (visual: VisualStyle): string => {\n const decls: string[] = []\n\n if (visual.backgroundColor !== undefined) {\n pushColor(\n decls,\n \"background-color\",\n visual.backgroundColor,\n \"backgroundColor\",\n )\n }\n if (visual.opacity !== undefined) {\n decls.push(`opacity: ${clamp01(visual.opacity)};`)\n }\n if (visual.boxShadow !== undefined) {\n const shadow = boxShadowToCss(visual.boxShadow)\n if (shadow !== null) {\n decls.push(`box-shadow: ${shadow};`)\n }\n }\n\n // GTK defaults border-style to none — width alone renders nothing. An\n // explicit borderStyle wins (GTK4 CSS supports solid/dotted/dashed);\n // otherwise any positive border width turns the border on with \"solid\".\n const hasVisibleBorderWidth = [\n visual.borderWidth,\n visual.borderTopWidth,\n visual.borderRightWidth,\n visual.borderBottomWidth,\n visual.borderLeftWidth,\n ].some((width) => width !== undefined && width > 0)\n if (visual.borderStyle !== undefined) {\n decls.push(`border-style: ${visual.borderStyle};`)\n } else if (hasVisibleBorderWidth) {\n decls.push(\"border-style: solid;\")\n }\n // Shorthands first, then per-side overrides so the sides win.\n if (visual.borderWidth !== undefined) {\n decls.push(`border-width: ${px(visual.borderWidth)};`)\n }\n if (visual.borderTopWidth !== undefined) {\n decls.push(`border-top-width: ${px(visual.borderTopWidth)};`)\n }\n if (visual.borderRightWidth !== undefined) {\n decls.push(`border-right-width: ${px(visual.borderRightWidth)};`)\n }\n if (visual.borderBottomWidth !== undefined) {\n decls.push(`border-bottom-width: ${px(visual.borderBottomWidth)};`)\n }\n if (visual.borderLeftWidth !== undefined) {\n decls.push(`border-left-width: ${px(visual.borderLeftWidth)};`)\n }\n if (visual.borderColor !== undefined) {\n pushColor(decls, \"border-color\", visual.borderColor, \"borderColor\")\n }\n if (visual.borderTopColor !== undefined) {\n pushColor(\n decls,\n \"border-top-color\",\n visual.borderTopColor,\n \"borderTopColor\",\n )\n }\n if (visual.borderRightColor !== undefined) {\n pushColor(\n decls,\n \"border-right-color\",\n visual.borderRightColor,\n \"borderRightColor\",\n )\n }\n if (visual.borderBottomColor !== undefined) {\n pushColor(\n decls,\n \"border-bottom-color\",\n visual.borderBottomColor,\n \"borderBottomColor\",\n )\n }\n if (visual.borderLeftColor !== undefined) {\n pushColor(\n decls,\n \"border-left-color\",\n visual.borderLeftColor,\n \"borderLeftColor\",\n )\n }\n if (visual.borderRadius !== undefined) {\n decls.push(`border-radius: ${px(visual.borderRadius)};`)\n }\n // Per-corner radii come after the shorthand so they override it.\n if (visual.borderTopLeftRadius !== undefined) {\n decls.push(`border-top-left-radius: ${px(visual.borderTopLeftRadius)};`)\n }\n if (visual.borderTopRightRadius !== undefined) {\n decls.push(`border-top-right-radius: ${px(visual.borderTopRightRadius)};`)\n }\n if (visual.borderBottomRightRadius !== undefined) {\n decls.push(\n `border-bottom-right-radius: ${px(visual.borderBottomRightRadius)};`,\n )\n }\n if (visual.borderBottomLeftRadius !== undefined) {\n decls.push(\n `border-bottom-left-radius: ${px(visual.borderBottomLeftRadius)};`,\n )\n }\n\n // outline is a ring around the border box that takes no layout space, so\n // unlike `border` it needs no Yoga involvement at all — GTK4 draws it from\n // CSS exactly as the web does, which is how Adwaita itself paints every\n // focus ring in the theme. GTK, like the web, defaults outline-style to\n // `none`, so a width on its own would draw nothing; the same auto-solid\n // rule the borders above use applies.\n const hasVisibleOutlineWidth =\n visual.outlineWidth !== undefined && visual.outlineWidth > 0\n if (visual.outlineStyle !== undefined) {\n decls.push(`outline-style: ${visual.outlineStyle};`)\n } else if (hasVisibleOutlineWidth) {\n decls.push(\"outline-style: solid;\")\n }\n if (visual.outlineWidth !== undefined) {\n decls.push(`outline-width: ${px(visual.outlineWidth)};`)\n }\n if (visual.outlineColor !== undefined) {\n pushColor(decls, \"outline-color\", visual.outlineColor, \"outlineColor\")\n }\n if (visual.outlineOffset !== undefined) {\n decls.push(`outline-offset: ${px(visual.outlineOffset)};`)\n }\n\n if (visual.color !== undefined) {\n pushColor(decls, \"color\", visual.color, \"color\")\n }\n if (visual.fontFamily !== undefined) {\n decls.push(`font-family: ${formatFontFamily(visual.fontFamily)};`)\n }\n if (visual.fontSize !== undefined) {\n decls.push(`font-size: ${px(visual.fontSize)};`)\n }\n if (visual.fontStyle !== undefined) {\n decls.push(`font-style: ${visual.fontStyle};`)\n }\n if (visual.fontWeight !== undefined) {\n decls.push(`font-weight: ${visual.fontWeight};`)\n }\n if (visual.letterSpacing !== undefined) {\n decls.push(`letter-spacing: ${px(visual.letterSpacing)};`)\n }\n if (visual.lineHeight !== undefined) {\n decls.push(`line-height: ${px(visual.lineHeight)};`)\n }\n\n // visual.textAlign, visual.textDecorationLine, visual.transform:\n // intentionally not CSS (see header).\n\n return decls.join(\"\\n\")\n}\n"]}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
// Pure objectBoundingBox / userSpaceOnUse coordinate math for gradients — no
|
|
2
|
-
// gtkx imports, so it
|
|
3
|
-
//
|
|
4
|
-
// (see the WORKAROUND note by makeColorStop in gtkx/bridge/svg-node.ts).
|
|
5
|
-
// This is the part of gradient support that already works end to end today
|
|
6
|
-
// and will need no changes once that bug is fixed upstream.
|
|
2
|
+
// gtkx imports, so it is unit-testable off Linux; the bridge
|
|
3
|
+
// (gtkx/bridge/svg-node.ts) feeds the results to Gsk's gradient nodes.
|
|
7
4
|
export const resolveGradientPoint = (bounds, fractionX, fractionY, units) => units === "userSpaceOnUse"
|
|
8
5
|
? { x: fractionX, y: fractionY }
|
|
9
6
|
: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gradient-geometry.js","sourceRoot":"","sources":["../../src/svg/gradient-geometry.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,
|
|
1
|
+
{"version":3,"file":"gradient-geometry.js","sourceRoot":"","sources":["../../src/svg/gradient-geometry.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,6DAA6D;AAC7D,uEAAuE;AAUvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,MAAmB,EACnB,SAAiB,EACjB,SAAiB,EACjB,KAAoB,EACM,EAAE,CAC5B,KAAK,KAAK,gBAAgB;IACxB,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE;IAChC,CAAC,CAAC;QACE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,KAAK;QACtC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM;KACxC,CAAA;AAEP,yEAAyE;AACzE,wEAAwE;AACxE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,MAAmB,EACnB,CAAS,EACT,KAAoB,EACkB,EAAE,CACxC,KAAK,KAAK,gBAAgB;IACxB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;IAC5B,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA","sourcesContent":["// Pure objectBoundingBox / userSpaceOnUse coordinate math for gradients — no\n// gtkx imports, so it is unit-testable off Linux; the bridge\n// (gtkx/bridge/svg-node.ts) feeds the results to Gsk's gradient nodes.\n\nexport type BoundingBox = {\n x: number\n y: number\n width: number\n height: number\n}\nexport type GradientUnits = \"objectBoundingBox\" | \"userSpaceOnUse\"\n\nexport const resolveGradientPoint = (\n bounds: BoundingBox,\n fractionX: number,\n fractionY: number,\n units: GradientUnits,\n): { x: number; y: number } =>\n units === \"userSpaceOnUse\"\n ? { x: fractionX, y: fractionY }\n : {\n x: bounds.x + fractionX * bounds.width,\n y: bounds.y + fractionY * bounds.height,\n }\n\n// SVG only has one radial radius; objectBoundingBox stretches it into an\n// ellipse matching the shape's own aspect ratio (what browsers do too).\nexport const resolveGradientRadius = (\n bounds: BoundingBox,\n r: number,\n units: GradientUnits,\n): { hradius: number; vradius: number } =>\n units === \"userSpaceOnUse\"\n ? { hradius: r, vradius: r }\n : { hradius: r * bounds.width, vradius: r * bounds.height }\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAOlD,2EAA2E;AAC3E,0EAA0E;AAC1E,6EAA6E;AAC7E,2EAA2E;AAC3E,4EAA4E;AAC5E,iDAAiD;AACjD,cAAc,eAAe,CAAA;AA2B7B,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAmC,EACnC,OAAkC;IAIlC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAA;IAChD,MAAM,IAAI,GAAG,MAAM,UAAU,CAC3B,QAAoC,EACpC,OAAmC,CACpC,CAAA;IACD,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAA;AAC5B,CAAC","sourcesContent":["import { render, renderHook } from \"@gtkx/testing\"\nimport type {\n RenderHookOptions,\n RenderHookResult,\n RenderResult,\n} from \"@gtkx/testing\"\n\n// react-native-gtkx/testing — @gtkx/testing's queries, render, renderHook,\n// fireEvent and userEvent already operate on the real GTK widget tree our\n// RN components render into, so `getByText` on a `Text` or `userEvent.click`\n// on a `Pressable` already work with no RN-flavoured wrapper: this subpath\n// re-exports that surface as-is, one import source for a consumer, plus the\n// one genuinely repeated workaround (see below).\nexport * from \"@gtkx/testing\"\n\n//
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAOlD,2EAA2E;AAC3E,0EAA0E;AAC1E,6EAA6E;AAC7E,2EAA2E;AAC3E,4EAA4E;AAC5E,iDAAiD;AACjD,cAAc,eAAe,CAAA;AA2B7B,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAmC,EACnC,OAAkC;IAIlC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAA;IAChD,MAAM,IAAI,GAAG,MAAM,UAAU,CAC3B,QAAoC,EACpC,OAAmC,CACpC,CAAA;IACD,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAA;AAC5B,CAAC","sourcesContent":["import { render, renderHook } from \"@gtkx/testing\"\nimport type {\n RenderHookOptions,\n RenderHookResult,\n RenderResult,\n} from \"@gtkx/testing\"\n\n// react-native-gtkx/testing — @gtkx/testing's queries, render, renderHook,\n// fireEvent and userEvent already operate on the real GTK widget tree our\n// RN components render into, so `getByText` on a `Text` or `userEvent.click`\n// on a `Pressable` already work with no RN-flavoured wrapper: this subpath\n// re-exports that surface as-is, one import source for a consumer, plus the\n// one genuinely repeated workaround (see below).\nexport * from \"@gtkx/testing\"\n\n// RC3-WORKAROUND(renderhook-no-window): see docs/gtkx-rc3-notes.md\n// @gtkx/testing's renderHook() always mounts its test component into a bare\n// Gtk.Box, so a hook that reads the active toplevel (useWindowDimensions,\n// anything through Gtk.Window.getToplevels()) has nothing to read. render()\n// always creates and presents a harness window when no container is given,\n// regardless of what it renders — rendering null is enough to get one.\n\n/**\n * Like `renderHook`, but first creates and presents a harness window (via\n * `render(null)`), so window-dependent hooks have a toplevel to read.\n * Cleanup is automatic — @gtkx/testing tears down every active render\n * (including the harness window) after each test.\n */\nexport function renderHookWithWindow<Result>(\n callback: () => Result,\n options?: RenderHookOptions<undefined>,\n): Promise<\n RenderHookResult<Result, undefined> & { window: RenderResult[\"container\"] }\n>\nexport function renderHookWithWindow<Result, Props>(\n callback: (props: Props) => Result,\n options: RenderHookOptions<Props>,\n): Promise<\n RenderHookResult<Result, Props> & { window: RenderResult[\"container\"] }\n>\nexport async function renderHookWithWindow<Result, Props>(\n callback: (props?: Props) => Result,\n options?: RenderHookOptions<Props>,\n): Promise<\n RenderHookResult<Result, Props> & { window: RenderResult[\"container\"] }\n> {\n const { container: window } = await render(null)\n const hook = await renderHook(\n callback as (props: Props) => Result,\n options as RenderHookOptions<Props>,\n )\n return { ...hook, window }\n}\n"]}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { GestureResponderEvent } from "../../responder/types";
|
|
8
|
+
export type PanResponderGestureState = {
|
|
9
|
+
/** ID of the gestureState - persisted as long as there's a touch on screen */
|
|
10
|
+
stateID: number;
|
|
11
|
+
/** the latest screen coordinates of the recently-moved touch */
|
|
12
|
+
moveX: number;
|
|
13
|
+
/** the latest screen coordinates of the recently-moved touch */
|
|
14
|
+
moveY: number;
|
|
15
|
+
/** the screen coordinates of the responder grant */
|
|
16
|
+
x0: number;
|
|
17
|
+
/** the screen coordinates of the responder grant */
|
|
18
|
+
y0: number;
|
|
19
|
+
/** accumulated distance of the gesture since the touch started */
|
|
20
|
+
dx: number;
|
|
21
|
+
/** accumulated distance of the gesture since the touch started */
|
|
22
|
+
dy: number;
|
|
23
|
+
/** current velocity of the gesture */
|
|
24
|
+
vx: number;
|
|
25
|
+
/** current velocity of the gesture */
|
|
26
|
+
vy: number;
|
|
27
|
+
/** Number of touches currently on screen */
|
|
28
|
+
numberActiveTouches: number;
|
|
29
|
+
/** All `gestureState` accounts for timeStamps up until this value */
|
|
30
|
+
_accountsForMovesUpTo: number;
|
|
31
|
+
};
|
|
32
|
+
type ActiveCallback = (event: GestureResponderEvent, gestureState: PanResponderGestureState) => boolean;
|
|
33
|
+
type PassiveCallback = (event: GestureResponderEvent, gestureState: PanResponderGestureState) => unknown;
|
|
34
|
+
export type GestureResponderHandlerMethods = {
|
|
35
|
+
onMoveShouldSetResponder: (event: GestureResponderEvent) => boolean;
|
|
36
|
+
onMoveShouldSetResponderCapture: (event: GestureResponderEvent) => boolean;
|
|
37
|
+
onResponderEnd: (event: GestureResponderEvent) => void;
|
|
38
|
+
onResponderGrant: (event: GestureResponderEvent) => boolean;
|
|
39
|
+
onResponderMove: (event: GestureResponderEvent) => void;
|
|
40
|
+
onResponderReject: (event: GestureResponderEvent) => void;
|
|
41
|
+
onResponderRelease: (event: GestureResponderEvent) => void;
|
|
42
|
+
onResponderStart: (event: GestureResponderEvent) => void;
|
|
43
|
+
onResponderTerminate: (event: GestureResponderEvent) => void;
|
|
44
|
+
onResponderTerminationRequest: (event: GestureResponderEvent) => boolean;
|
|
45
|
+
onStartShouldSetResponder: (event: GestureResponderEvent) => boolean;
|
|
46
|
+
onStartShouldSetResponderCapture: (event: GestureResponderEvent) => boolean;
|
|
47
|
+
};
|
|
48
|
+
export type PanResponderCallbacks = Readonly<{
|
|
49
|
+
onMoveShouldSetPanResponder?: ActiveCallback;
|
|
50
|
+
onMoveShouldSetPanResponderCapture?: ActiveCallback;
|
|
51
|
+
onStartShouldSetPanResponder?: ActiveCallback;
|
|
52
|
+
onStartShouldSetPanResponderCapture?: ActiveCallback;
|
|
53
|
+
onPanResponderGrant?: PassiveCallback;
|
|
54
|
+
onPanResponderMove?: PassiveCallback;
|
|
55
|
+
onPanResponderRelease?: PassiveCallback;
|
|
56
|
+
onPanResponderTerminate?: PassiveCallback;
|
|
57
|
+
onPanResponderReject?: PassiveCallback;
|
|
58
|
+
onPanResponderStart?: PassiveCallback;
|
|
59
|
+
onPanResponderEnd?: PassiveCallback;
|
|
60
|
+
onPanResponderTerminationRequest?: ActiveCallback;
|
|
61
|
+
onShouldBlockNativeResponder?: ActiveCallback;
|
|
62
|
+
}>;
|
|
63
|
+
declare const PanResponder: {
|
|
64
|
+
_initializeGestureState(gestureState: PanResponderGestureState): void;
|
|
65
|
+
/**
|
|
66
|
+
* This is nuanced and is necessary. It is incorrect to continuously take all
|
|
67
|
+
* active *and* recently moved touches, find the centroid, and track how that
|
|
68
|
+
* result changes over time. Instead, we must take all recently moved
|
|
69
|
+
* touches, and calculate how the centroid has changed just for those
|
|
70
|
+
* recently moved touches, and append that change to an accumulator. This is
|
|
71
|
+
* to (at least) handle the case where the user is moving three fingers, and
|
|
72
|
+
* then one of the fingers stops but the other two continue.
|
|
73
|
+
*
|
|
74
|
+
* This is very different than taking all of the recently moved touches and
|
|
75
|
+
* storing their centroid as `dx/dy`. For correctness, we must *accumulate
|
|
76
|
+
* changes* in the centroid of recently moved touches.
|
|
77
|
+
*
|
|
78
|
+
* There is also some nuance with how we handle multiple moved touches in a
|
|
79
|
+
* single event. With the way `ReactNativeEventEmitter` dispatches touches as
|
|
80
|
+
* individual events, multiple touches generate two 'move' events, each of
|
|
81
|
+
* them triggering `onResponderMove`. But with the way `PanResponder` works,
|
|
82
|
+
* all of the gesture inference is performed on the first dispatch, since it
|
|
83
|
+
* looks at all of the touches (even the ones for which there hasn't been a
|
|
84
|
+
* native dispatch yet). Therefore, `PanResponder` does not call
|
|
85
|
+
* `onResponderMove` passed the first dispatch. This diverges from the
|
|
86
|
+
* typical responder callback pattern (without using `PanResponder`), but
|
|
87
|
+
* avoids more dispatches than necessary.
|
|
88
|
+
*/
|
|
89
|
+
_updateGestureStateOnMove(gestureState: PanResponderGestureState, touchHistory: GestureResponderEvent["touchHistory"]): void;
|
|
90
|
+
/**
|
|
91
|
+
* @param config Enhanced versions of all of the responder callbacks that
|
|
92
|
+
* provide not only the typical `ResponderSyntheticEvent`, but also the
|
|
93
|
+
* `PanResponder` gesture state. Simply replace the word `Responder` with
|
|
94
|
+
* `PanResponder` in each of the typical `onResponder*` callbacks.
|
|
95
|
+
*/
|
|
96
|
+
create(config: PanResponderCallbacks): {
|
|
97
|
+
getInteractionHandle: () => number | null;
|
|
98
|
+
panHandlers: GestureResponderHandlerMethods;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
export type PanResponderInstance = ReturnType<(typeof PanResponder)["create"]>;
|
|
102
|
+
export default PanResponder;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import TouchHistoryMath from "./touch-history-math";
|
|
8
|
+
const currentCentroidXOfTouchesChangedAfter = TouchHistoryMath.currentCentroidXOfTouchesChangedAfter;
|
|
9
|
+
const currentCentroidYOfTouchesChangedAfter = TouchHistoryMath.currentCentroidYOfTouchesChangedAfter;
|
|
10
|
+
const previousCentroidXOfTouchesChangedAfter = TouchHistoryMath.previousCentroidXOfTouchesChangedAfter;
|
|
11
|
+
const previousCentroidYOfTouchesChangedAfter = TouchHistoryMath.previousCentroidYOfTouchesChangedAfter;
|
|
12
|
+
const currentCentroidX = TouchHistoryMath.currentCentroidX;
|
|
13
|
+
const currentCentroidY = TouchHistoryMath.currentCentroidY;
|
|
14
|
+
const PanResponder = {
|
|
15
|
+
_initializeGestureState(gestureState) {
|
|
16
|
+
gestureState.moveX = 0;
|
|
17
|
+
gestureState.moveY = 0;
|
|
18
|
+
gestureState.x0 = 0;
|
|
19
|
+
gestureState.y0 = 0;
|
|
20
|
+
gestureState.dx = 0;
|
|
21
|
+
gestureState.dy = 0;
|
|
22
|
+
gestureState.vx = 0;
|
|
23
|
+
gestureState.vy = 0;
|
|
24
|
+
gestureState.numberActiveTouches = 0;
|
|
25
|
+
// All `gestureState` accounts for timeStamps up until:
|
|
26
|
+
gestureState._accountsForMovesUpTo = 0;
|
|
27
|
+
},
|
|
28
|
+
/**
|
|
29
|
+
* This is nuanced and is necessary. It is incorrect to continuously take all
|
|
30
|
+
* active *and* recently moved touches, find the centroid, and track how that
|
|
31
|
+
* result changes over time. Instead, we must take all recently moved
|
|
32
|
+
* touches, and calculate how the centroid has changed just for those
|
|
33
|
+
* recently moved touches, and append that change to an accumulator. This is
|
|
34
|
+
* to (at least) handle the case where the user is moving three fingers, and
|
|
35
|
+
* then one of the fingers stops but the other two continue.
|
|
36
|
+
*
|
|
37
|
+
* This is very different than taking all of the recently moved touches and
|
|
38
|
+
* storing their centroid as `dx/dy`. For correctness, we must *accumulate
|
|
39
|
+
* changes* in the centroid of recently moved touches.
|
|
40
|
+
*
|
|
41
|
+
* There is also some nuance with how we handle multiple moved touches in a
|
|
42
|
+
* single event. With the way `ReactNativeEventEmitter` dispatches touches as
|
|
43
|
+
* individual events, multiple touches generate two 'move' events, each of
|
|
44
|
+
* them triggering `onResponderMove`. But with the way `PanResponder` works,
|
|
45
|
+
* all of the gesture inference is performed on the first dispatch, since it
|
|
46
|
+
* looks at all of the touches (even the ones for which there hasn't been a
|
|
47
|
+
* native dispatch yet). Therefore, `PanResponder` does not call
|
|
48
|
+
* `onResponderMove` passed the first dispatch. This diverges from the
|
|
49
|
+
* typical responder callback pattern (without using `PanResponder`), but
|
|
50
|
+
* avoids more dispatches than necessary.
|
|
51
|
+
*/
|
|
52
|
+
_updateGestureStateOnMove(gestureState, touchHistory) {
|
|
53
|
+
gestureState.numberActiveTouches = touchHistory.numberActiveTouches;
|
|
54
|
+
gestureState.moveX = currentCentroidXOfTouchesChangedAfter(touchHistory, gestureState._accountsForMovesUpTo);
|
|
55
|
+
gestureState.moveY = currentCentroidYOfTouchesChangedAfter(touchHistory, gestureState._accountsForMovesUpTo);
|
|
56
|
+
const movedAfter = gestureState._accountsForMovesUpTo;
|
|
57
|
+
const prevX = previousCentroidXOfTouchesChangedAfter(touchHistory, movedAfter);
|
|
58
|
+
const x = currentCentroidXOfTouchesChangedAfter(touchHistory, movedAfter);
|
|
59
|
+
const prevY = previousCentroidYOfTouchesChangedAfter(touchHistory, movedAfter);
|
|
60
|
+
const y = currentCentroidYOfTouchesChangedAfter(touchHistory, movedAfter);
|
|
61
|
+
const nextDX = gestureState.dx + (x - prevX);
|
|
62
|
+
const nextDY = gestureState.dy + (y - prevY);
|
|
63
|
+
// TODO: This must be filtered intelligently.
|
|
64
|
+
const dt = touchHistory.mostRecentTimeStamp - gestureState._accountsForMovesUpTo;
|
|
65
|
+
gestureState.vx = (nextDX - gestureState.dx) / dt;
|
|
66
|
+
gestureState.vy = (nextDY - gestureState.dy) / dt;
|
|
67
|
+
gestureState.dx = nextDX;
|
|
68
|
+
gestureState.dy = nextDY;
|
|
69
|
+
gestureState._accountsForMovesUpTo = touchHistory.mostRecentTimeStamp;
|
|
70
|
+
},
|
|
71
|
+
/**
|
|
72
|
+
* @param config Enhanced versions of all of the responder callbacks that
|
|
73
|
+
* provide not only the typical `ResponderSyntheticEvent`, but also the
|
|
74
|
+
* `PanResponder` gesture state. Simply replace the word `Responder` with
|
|
75
|
+
* `PanResponder` in each of the typical `onResponder*` callbacks.
|
|
76
|
+
*/
|
|
77
|
+
create(config) {
|
|
78
|
+
const gestureState = {
|
|
79
|
+
// Useful for debugging
|
|
80
|
+
stateID: Math.random(),
|
|
81
|
+
moveX: 0,
|
|
82
|
+
moveY: 0,
|
|
83
|
+
x0: 0,
|
|
84
|
+
y0: 0,
|
|
85
|
+
dx: 0,
|
|
86
|
+
dy: 0,
|
|
87
|
+
vx: 0,
|
|
88
|
+
vy: 0,
|
|
89
|
+
numberActiveTouches: 0,
|
|
90
|
+
_accountsForMovesUpTo: 0,
|
|
91
|
+
};
|
|
92
|
+
const panHandlers = {
|
|
93
|
+
onStartShouldSetResponder(event) {
|
|
94
|
+
return config.onStartShouldSetPanResponder == null
|
|
95
|
+
? false
|
|
96
|
+
: config.onStartShouldSetPanResponder(event, gestureState);
|
|
97
|
+
},
|
|
98
|
+
onMoveShouldSetResponder(event) {
|
|
99
|
+
return config.onMoveShouldSetPanResponder == null
|
|
100
|
+
? false
|
|
101
|
+
: config.onMoveShouldSetPanResponder(event, gestureState);
|
|
102
|
+
},
|
|
103
|
+
onStartShouldSetResponderCapture(event) {
|
|
104
|
+
// TODO: Actually, we should reinitialize the state any time
|
|
105
|
+
// touches.length increases from 0 active to > 0 active.
|
|
106
|
+
if (event.nativeEvent.touches.length === 1) {
|
|
107
|
+
PanResponder._initializeGestureState(gestureState);
|
|
108
|
+
}
|
|
109
|
+
gestureState.numberActiveTouches =
|
|
110
|
+
event.touchHistory.numberActiveTouches;
|
|
111
|
+
return config.onStartShouldSetPanResponderCapture != null
|
|
112
|
+
? config.onStartShouldSetPanResponderCapture(event, gestureState)
|
|
113
|
+
: false;
|
|
114
|
+
},
|
|
115
|
+
onMoveShouldSetResponderCapture(event) {
|
|
116
|
+
const touchHistory = event.touchHistory;
|
|
117
|
+
// Responder system incorrectly dispatches should* to current responder
|
|
118
|
+
// Filter out any touch moves past the first one - we would have
|
|
119
|
+
// already processed multi-touch geometry during the first event.
|
|
120
|
+
if (gestureState._accountsForMovesUpTo ===
|
|
121
|
+
touchHistory.mostRecentTimeStamp) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
PanResponder._updateGestureStateOnMove(gestureState, touchHistory);
|
|
125
|
+
return config.onMoveShouldSetPanResponderCapture
|
|
126
|
+
? config.onMoveShouldSetPanResponderCapture(event, gestureState)
|
|
127
|
+
: false;
|
|
128
|
+
},
|
|
129
|
+
onResponderGrant(event) {
|
|
130
|
+
gestureState.x0 = currentCentroidX(event.touchHistory);
|
|
131
|
+
gestureState.y0 = currentCentroidY(event.touchHistory);
|
|
132
|
+
gestureState.dx = 0;
|
|
133
|
+
gestureState.dy = 0;
|
|
134
|
+
if (config.onPanResponderGrant) {
|
|
135
|
+
config.onPanResponderGrant(event, gestureState);
|
|
136
|
+
}
|
|
137
|
+
// TODO: t7467124 investigate if this can be removed
|
|
138
|
+
return config.onShouldBlockNativeResponder == null
|
|
139
|
+
? true
|
|
140
|
+
: config.onShouldBlockNativeResponder(event, gestureState);
|
|
141
|
+
},
|
|
142
|
+
onResponderReject(event) {
|
|
143
|
+
config.onPanResponderReject?.call(undefined, event, gestureState);
|
|
144
|
+
},
|
|
145
|
+
onResponderRelease(event) {
|
|
146
|
+
config.onPanResponderRelease?.call(undefined, event, gestureState);
|
|
147
|
+
PanResponder._initializeGestureState(gestureState);
|
|
148
|
+
},
|
|
149
|
+
onResponderStart(event) {
|
|
150
|
+
const touchHistory = event.touchHistory;
|
|
151
|
+
gestureState.numberActiveTouches = touchHistory.numberActiveTouches;
|
|
152
|
+
if (config.onPanResponderStart) {
|
|
153
|
+
config.onPanResponderStart(event, gestureState);
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
onResponderMove(event) {
|
|
157
|
+
const touchHistory = event.touchHistory;
|
|
158
|
+
// Guard against the dispatch of two touch moves when there are two
|
|
159
|
+
// simultaneously changed touches.
|
|
160
|
+
if (gestureState._accountsForMovesUpTo ===
|
|
161
|
+
touchHistory.mostRecentTimeStamp) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
// Filter out any touch moves past the first one - we would have
|
|
165
|
+
// already processed multi-touch geometry during the first event.
|
|
166
|
+
PanResponder._updateGestureStateOnMove(gestureState, touchHistory);
|
|
167
|
+
if (config.onPanResponderMove) {
|
|
168
|
+
config.onPanResponderMove(event, gestureState);
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
onResponderEnd(event) {
|
|
172
|
+
const touchHistory = event.touchHistory;
|
|
173
|
+
gestureState.numberActiveTouches = touchHistory.numberActiveTouches;
|
|
174
|
+
config.onPanResponderEnd?.call(undefined, event, gestureState);
|
|
175
|
+
},
|
|
176
|
+
onResponderTerminate(event) {
|
|
177
|
+
config.onPanResponderTerminate?.call(undefined, event, gestureState);
|
|
178
|
+
PanResponder._initializeGestureState(gestureState);
|
|
179
|
+
},
|
|
180
|
+
onResponderTerminationRequest(event) {
|
|
181
|
+
return config.onPanResponderTerminationRequest == null
|
|
182
|
+
? true
|
|
183
|
+
: config.onPanResponderTerminationRequest(event, gestureState);
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
return {
|
|
187
|
+
panHandlers,
|
|
188
|
+
getInteractionHandle() {
|
|
189
|
+
// TODO: Deprecate and delete this method.
|
|
190
|
+
return null;
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
export default PanResponder;
|
|
196
|
+
//# sourceMappingURL=pan-responder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pan-responder.js","sourceRoot":"","sources":["../../../src/vendor/react-native/pan-responder.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// VENDORED from react-native (MIT), Libraries/Interaction/PanResponder.js.\n//\n// react-native-web re-exports Meta's file directly and it works untouched,\n// because RNW reproduces the touchHistory structure PanResponder expects. We\n// reproduce the same structure (src/responder/touch-history.ts), so the\n// algorithm below is upstream's, unmodified in substance.\n//\n// We cannot re-export it the way RNW does: upstream ships Flow, and this\n// package is one tsc emit. So it is transliterated, and ONLY transliterated:\n// - Flow annotations to TypeScript (`?number` to `number | null`,\n// inexact object types to plain ones, `Readonly<{}>` kept as-is);\n// - `GestureResponderEvent` imported from our responder types instead of\n// RN's CoreEventTypes;\n// - `require` to `import`.\n//\n// The logic is deliberately untouched, comments included — especially the\n// clustered multi-touch accumulation in _updateGestureStateOnMove, which is\n// the part with no obvious specification and the reason vendoring beats\n// reimplementing.\nimport type { GestureResponderEvent } from \"../../responder/types\"\nimport TouchHistoryMath from \"./touch-history-math\"\n\nconst currentCentroidXOfTouchesChangedAfter =\n TouchHistoryMath.currentCentroidXOfTouchesChangedAfter\nconst currentCentroidYOfTouchesChangedAfter =\n TouchHistoryMath.currentCentroidYOfTouchesChangedAfter\nconst previousCentroidXOfTouchesChangedAfter =\n TouchHistoryMath.previousCentroidXOfTouchesChangedAfter\nconst previousCentroidYOfTouchesChangedAfter =\n TouchHistoryMath.previousCentroidYOfTouchesChangedAfter\nconst currentCentroidX = TouchHistoryMath.currentCentroidX\nconst currentCentroidY = TouchHistoryMath.currentCentroidY\n\nexport type PanResponderGestureState = {\n /** ID of the gestureState - persisted as long as there's a touch on screen */\n stateID: number\n /** the latest screen coordinates of the recently-moved touch */\n moveX: number\n /** the latest screen coordinates of the recently-moved touch */\n moveY: number\n /** the screen coordinates of the responder grant */\n x0: number\n /** the screen coordinates of the responder grant */\n y0: number\n /** accumulated distance of the gesture since the touch started */\n dx: number\n /** accumulated distance of the gesture since the touch started */\n dy: number\n /** current velocity of the gesture */\n vx: number\n /** current velocity of the gesture */\n vy: number\n /** Number of touches currently on screen */\n numberActiveTouches: number\n /** All `gestureState` accounts for timeStamps up until this value */\n _accountsForMovesUpTo: number\n}\n\ntype ActiveCallback = (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n) => boolean\n\ntype PassiveCallback = (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n) => unknown\n\nexport type GestureResponderHandlerMethods = {\n onMoveShouldSetResponder: (event: GestureResponderEvent) => boolean\n onMoveShouldSetResponderCapture: (event: GestureResponderEvent) => boolean\n onResponderEnd: (event: GestureResponderEvent) => void\n onResponderGrant: (event: GestureResponderEvent) => boolean\n onResponderMove: (event: GestureResponderEvent) => void\n onResponderReject: (event: GestureResponderEvent) => void\n onResponderRelease: (event: GestureResponderEvent) => void\n onResponderStart: (event: GestureResponderEvent) => void\n onResponderTerminate: (event: GestureResponderEvent) => void\n onResponderTerminationRequest: (event: GestureResponderEvent) => boolean\n onStartShouldSetResponder: (event: GestureResponderEvent) => boolean\n onStartShouldSetResponderCapture: (event: GestureResponderEvent) => boolean\n}\n\nexport type PanResponderCallbacks = Readonly<{\n onMoveShouldSetPanResponder?: ActiveCallback\n onMoveShouldSetPanResponderCapture?: ActiveCallback\n onStartShouldSetPanResponder?: ActiveCallback\n onStartShouldSetPanResponderCapture?: ActiveCallback\n onPanResponderGrant?: PassiveCallback\n onPanResponderMove?: PassiveCallback\n onPanResponderRelease?: PassiveCallback\n onPanResponderTerminate?: PassiveCallback\n onPanResponderReject?: PassiveCallback\n onPanResponderStart?: PassiveCallback\n onPanResponderEnd?: PassiveCallback\n onPanResponderTerminationRequest?: ActiveCallback\n onShouldBlockNativeResponder?: ActiveCallback\n}>\n\nconst PanResponder = {\n _initializeGestureState(gestureState: PanResponderGestureState): void {\n gestureState.moveX = 0\n gestureState.moveY = 0\n gestureState.x0 = 0\n gestureState.y0 = 0\n gestureState.dx = 0\n gestureState.dy = 0\n gestureState.vx = 0\n gestureState.vy = 0\n gestureState.numberActiveTouches = 0\n // All `gestureState` accounts for timeStamps up until:\n gestureState._accountsForMovesUpTo = 0\n },\n\n /**\n * This is nuanced and is necessary. It is incorrect to continuously take all\n * active *and* recently moved touches, find the centroid, and track how that\n * result changes over time. Instead, we must take all recently moved\n * touches, and calculate how the centroid has changed just for those\n * recently moved touches, and append that change to an accumulator. This is\n * to (at least) handle the case where the user is moving three fingers, and\n * then one of the fingers stops but the other two continue.\n *\n * This is very different than taking all of the recently moved touches and\n * storing their centroid as `dx/dy`. For correctness, we must *accumulate\n * changes* in the centroid of recently moved touches.\n *\n * There is also some nuance with how we handle multiple moved touches in a\n * single event. With the way `ReactNativeEventEmitter` dispatches touches as\n * individual events, multiple touches generate two 'move' events, each of\n * them triggering `onResponderMove`. But with the way `PanResponder` works,\n * all of the gesture inference is performed on the first dispatch, since it\n * looks at all of the touches (even the ones for which there hasn't been a\n * native dispatch yet). Therefore, `PanResponder` does not call\n * `onResponderMove` passed the first dispatch. This diverges from the\n * typical responder callback pattern (without using `PanResponder`), but\n * avoids more dispatches than necessary.\n */\n _updateGestureStateOnMove(\n gestureState: PanResponderGestureState,\n touchHistory: GestureResponderEvent[\"touchHistory\"],\n ): void {\n gestureState.numberActiveTouches = touchHistory.numberActiveTouches\n gestureState.moveX = currentCentroidXOfTouchesChangedAfter(\n touchHistory,\n gestureState._accountsForMovesUpTo,\n )\n gestureState.moveY = currentCentroidYOfTouchesChangedAfter(\n touchHistory,\n gestureState._accountsForMovesUpTo,\n )\n const movedAfter = gestureState._accountsForMovesUpTo\n const prevX = previousCentroidXOfTouchesChangedAfter(\n touchHistory,\n movedAfter,\n )\n const x = currentCentroidXOfTouchesChangedAfter(touchHistory, movedAfter)\n const prevY = previousCentroidYOfTouchesChangedAfter(\n touchHistory,\n movedAfter,\n )\n const y = currentCentroidYOfTouchesChangedAfter(touchHistory, movedAfter)\n const nextDX = gestureState.dx + (x - prevX)\n const nextDY = gestureState.dy + (y - prevY)\n\n // TODO: This must be filtered intelligently.\n const dt =\n touchHistory.mostRecentTimeStamp - gestureState._accountsForMovesUpTo\n gestureState.vx = (nextDX - gestureState.dx) / dt\n gestureState.vy = (nextDY - gestureState.dy) / dt\n\n gestureState.dx = nextDX\n gestureState.dy = nextDY\n gestureState._accountsForMovesUpTo = touchHistory.mostRecentTimeStamp\n },\n\n /**\n * @param config Enhanced versions of all of the responder callbacks that\n * provide not only the typical `ResponderSyntheticEvent`, but also the\n * `PanResponder` gesture state. Simply replace the word `Responder` with\n * `PanResponder` in each of the typical `onResponder*` callbacks.\n */\n create(config: PanResponderCallbacks): {\n getInteractionHandle: () => number | null\n panHandlers: GestureResponderHandlerMethods\n } {\n const gestureState: PanResponderGestureState = {\n // Useful for debugging\n stateID: Math.random(),\n moveX: 0,\n moveY: 0,\n x0: 0,\n y0: 0,\n dx: 0,\n dy: 0,\n vx: 0,\n vy: 0,\n numberActiveTouches: 0,\n _accountsForMovesUpTo: 0,\n }\n const panHandlers: GestureResponderHandlerMethods = {\n onStartShouldSetResponder(event: GestureResponderEvent): boolean {\n return config.onStartShouldSetPanResponder == null\n ? false\n : config.onStartShouldSetPanResponder(event, gestureState)\n },\n onMoveShouldSetResponder(event: GestureResponderEvent): boolean {\n return config.onMoveShouldSetPanResponder == null\n ? false\n : config.onMoveShouldSetPanResponder(event, gestureState)\n },\n onStartShouldSetResponderCapture(event: GestureResponderEvent): boolean {\n // TODO: Actually, we should reinitialize the state any time\n // touches.length increases from 0 active to > 0 active.\n if (event.nativeEvent.touches.length === 1) {\n PanResponder._initializeGestureState(gestureState)\n }\n gestureState.numberActiveTouches =\n event.touchHistory.numberActiveTouches\n return config.onStartShouldSetPanResponderCapture != null\n ? config.onStartShouldSetPanResponderCapture(event, gestureState)\n : false\n },\n\n onMoveShouldSetResponderCapture(event: GestureResponderEvent): boolean {\n const touchHistory = event.touchHistory\n // Responder system incorrectly dispatches should* to current responder\n // Filter out any touch moves past the first one - we would have\n // already processed multi-touch geometry during the first event.\n if (\n gestureState._accountsForMovesUpTo ===\n touchHistory.mostRecentTimeStamp\n ) {\n return false\n }\n PanResponder._updateGestureStateOnMove(gestureState, touchHistory)\n return config.onMoveShouldSetPanResponderCapture\n ? config.onMoveShouldSetPanResponderCapture(event, gestureState)\n : false\n },\n\n onResponderGrant(event: GestureResponderEvent): boolean {\n gestureState.x0 = currentCentroidX(event.touchHistory)\n gestureState.y0 = currentCentroidY(event.touchHistory)\n gestureState.dx = 0\n gestureState.dy = 0\n if (config.onPanResponderGrant) {\n config.onPanResponderGrant(event, gestureState)\n }\n // TODO: t7467124 investigate if this can be removed\n return config.onShouldBlockNativeResponder == null\n ? true\n : config.onShouldBlockNativeResponder(event, gestureState)\n },\n\n onResponderReject(event: GestureResponderEvent): void {\n config.onPanResponderReject?.call(undefined, event, gestureState)\n },\n\n onResponderRelease(event: GestureResponderEvent): void {\n config.onPanResponderRelease?.call(undefined, event, gestureState)\n PanResponder._initializeGestureState(gestureState)\n },\n\n onResponderStart(event: GestureResponderEvent): void {\n const touchHistory = event.touchHistory\n gestureState.numberActiveTouches = touchHistory.numberActiveTouches\n if (config.onPanResponderStart) {\n config.onPanResponderStart(event, gestureState)\n }\n },\n\n onResponderMove(event: GestureResponderEvent): void {\n const touchHistory = event.touchHistory\n // Guard against the dispatch of two touch moves when there are two\n // simultaneously changed touches.\n if (\n gestureState._accountsForMovesUpTo ===\n touchHistory.mostRecentTimeStamp\n ) {\n return\n }\n // Filter out any touch moves past the first one - we would have\n // already processed multi-touch geometry during the first event.\n PanResponder._updateGestureStateOnMove(gestureState, touchHistory)\n if (config.onPanResponderMove) {\n config.onPanResponderMove(event, gestureState)\n }\n },\n\n onResponderEnd(event: GestureResponderEvent): void {\n const touchHistory = event.touchHistory\n gestureState.numberActiveTouches = touchHistory.numberActiveTouches\n config.onPanResponderEnd?.call(undefined, event, gestureState)\n },\n\n onResponderTerminate(event: GestureResponderEvent): void {\n config.onPanResponderTerminate?.call(undefined, event, gestureState)\n PanResponder._initializeGestureState(gestureState)\n },\n\n onResponderTerminationRequest(event: GestureResponderEvent): boolean {\n return config.onPanResponderTerminationRequest == null\n ? true\n : config.onPanResponderTerminationRequest(event, gestureState)\n },\n }\n return {\n panHandlers,\n getInteractionHandle(): number | null {\n // TODO: Deprecate and delete this method.\n return null\n },\n }\n },\n}\n\nexport type PanResponderInstance = ReturnType<(typeof PanResponder)[\"create\"]>\n\nexport default PanResponder\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { TouchHistory } from "../../responder/types";
|
|
8
|
+
declare const TouchHistoryMath: {
|
|
9
|
+
centroidDimension: (touchHistory: TouchHistory, touchesChangedAfter: number, isXAxis: boolean, ofCurrent: boolean) => number;
|
|
10
|
+
currentCentroidXOfTouchesChangedAfter(touchHistory: TouchHistory, touchesChangedAfter: number): number;
|
|
11
|
+
currentCentroidYOfTouchesChangedAfter(touchHistory: TouchHistory, touchesChangedAfter: number): number;
|
|
12
|
+
previousCentroidXOfTouchesChangedAfter(touchHistory: TouchHistory, touchesChangedAfter: number): number;
|
|
13
|
+
previousCentroidYOfTouchesChangedAfter(touchHistory: TouchHistory, touchesChangedAfter: number): number;
|
|
14
|
+
currentCentroidX(touchHistory: TouchHistory): number;
|
|
15
|
+
currentCentroidY(touchHistory: TouchHistory): number;
|
|
16
|
+
noCentroid: number;
|
|
17
|
+
};
|
|
18
|
+
export default TouchHistoryMath;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
const noCentroid = -1;
|
|
8
|
+
/**
|
|
9
|
+
* This code is optimized and not intended to look beautiful. This allows
|
|
10
|
+
* computing of touch centroids that have moved after `touchesChangedAfter`
|
|
11
|
+
* timeStamp. You can compute the current centroid involving all touches
|
|
12
|
+
* moves after `touchesChangedAfter`, or you can compute the previous
|
|
13
|
+
* centroid of all touches that were moved after `touchesChangedAfter`.
|
|
14
|
+
*
|
|
15
|
+
* @param touchHistory Standard Responder touch track data.
|
|
16
|
+
* @param touchesChangedAfter timeStamp after which moved touches are
|
|
17
|
+
* considered "actively moving" - not just "active".
|
|
18
|
+
* @param isXAxis Consider `x` dimension vs. `y` dimension.
|
|
19
|
+
* @param ofCurrent Compute current centroid for actively moving touches vs.
|
|
20
|
+
* previous centroid of now actively moving touches.
|
|
21
|
+
* @return value of centroid in specified dimension.
|
|
22
|
+
*/
|
|
23
|
+
const centroidDimension = (touchHistory, touchesChangedAfter, isXAxis, ofCurrent) => {
|
|
24
|
+
const touchBank = touchHistory.touchBank;
|
|
25
|
+
let total = 0;
|
|
26
|
+
let count = 0;
|
|
27
|
+
const oneTouchData = touchHistory.numberActiveTouches === 1
|
|
28
|
+
? touchHistory.touchBank[touchHistory.indexOfSingleActiveTouch]
|
|
29
|
+
: null;
|
|
30
|
+
if (oneTouchData !== null && oneTouchData !== undefined) {
|
|
31
|
+
if (oneTouchData.touchActive &&
|
|
32
|
+
oneTouchData.currentTimeStamp > touchesChangedAfter) {
|
|
33
|
+
total +=
|
|
34
|
+
ofCurrent && isXAxis
|
|
35
|
+
? oneTouchData.currentPageX
|
|
36
|
+
: ofCurrent && !isXAxis
|
|
37
|
+
? oneTouchData.currentPageY
|
|
38
|
+
: !ofCurrent && isXAxis
|
|
39
|
+
? oneTouchData.previousPageX
|
|
40
|
+
: oneTouchData.previousPageY;
|
|
41
|
+
count = 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
for (let i = 0; i < touchBank.length; i++) {
|
|
46
|
+
const touchTrack = touchBank[i];
|
|
47
|
+
if (touchTrack !== null &&
|
|
48
|
+
touchTrack !== undefined &&
|
|
49
|
+
touchTrack.touchActive &&
|
|
50
|
+
touchTrack.currentTimeStamp >= touchesChangedAfter) {
|
|
51
|
+
let toAdd; // Yuck, program temporarily in invalid state.
|
|
52
|
+
if (ofCurrent && isXAxis) {
|
|
53
|
+
toAdd = touchTrack.currentPageX;
|
|
54
|
+
}
|
|
55
|
+
else if (ofCurrent && !isXAxis) {
|
|
56
|
+
toAdd = touchTrack.currentPageY;
|
|
57
|
+
}
|
|
58
|
+
else if (!ofCurrent && isXAxis) {
|
|
59
|
+
toAdd = touchTrack.previousPageX;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
toAdd = touchTrack.previousPageY;
|
|
63
|
+
}
|
|
64
|
+
total += toAdd;
|
|
65
|
+
count++;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return count > 0 ? total / count : noCentroid;
|
|
70
|
+
};
|
|
71
|
+
const TouchHistoryMath = {
|
|
72
|
+
centroidDimension,
|
|
73
|
+
currentCentroidXOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
|
|
74
|
+
return centroidDimension(touchHistory, touchesChangedAfter, true, // isXAxis
|
|
75
|
+
true);
|
|
76
|
+
},
|
|
77
|
+
currentCentroidYOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
|
|
78
|
+
return centroidDimension(touchHistory, touchesChangedAfter, false, // isXAxis
|
|
79
|
+
true);
|
|
80
|
+
},
|
|
81
|
+
previousCentroidXOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
|
|
82
|
+
return centroidDimension(touchHistory, touchesChangedAfter, true, // isXAxis
|
|
83
|
+
false);
|
|
84
|
+
},
|
|
85
|
+
previousCentroidYOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
|
|
86
|
+
return centroidDimension(touchHistory, touchesChangedAfter, false, // isXAxis
|
|
87
|
+
false);
|
|
88
|
+
},
|
|
89
|
+
currentCentroidX(touchHistory) {
|
|
90
|
+
return centroidDimension(touchHistory, 0, // touchesChangedAfter
|
|
91
|
+
true, // isXAxis
|
|
92
|
+
true);
|
|
93
|
+
},
|
|
94
|
+
currentCentroidY(touchHistory) {
|
|
95
|
+
return centroidDimension(touchHistory, 0, // touchesChangedAfter
|
|
96
|
+
false, // isXAxis
|
|
97
|
+
true);
|
|
98
|
+
},
|
|
99
|
+
noCentroid,
|
|
100
|
+
};
|
|
101
|
+
export default TouchHistoryMath;
|
|
102
|
+
//# sourceMappingURL=touch-history-math.js.map
|