react-native-tapline 1.4.0 → 1.6.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.
Files changed (77) hide show
  1. package/TaplineNative.podspec +3 -1
  2. package/dist/actions.d.ts +75 -2
  3. package/dist/actions.js +333 -25
  4. package/dist/actions.js.map +1 -1
  5. package/dist/alerts.d.ts +2 -0
  6. package/dist/alerts.js +5 -0
  7. package/dist/alerts.js.map +1 -1
  8. package/dist/anim.d.ts +25 -0
  9. package/dist/anim.js +311 -0
  10. package/dist/anim.js.map +1 -0
  11. package/dist/appinfo.d.ts +12 -0
  12. package/dist/appinfo.js +78 -0
  13. package/dist/appinfo.js.map +1 -0
  14. package/dist/checks.d.ts +43 -1
  15. package/dist/checks.js +17 -5
  16. package/dist/checks.js.map +1 -1
  17. package/dist/client.d.ts +2 -0
  18. package/dist/client.js +28 -2
  19. package/dist/client.js.map +1 -1
  20. package/dist/commands.js +28 -0
  21. package/dist/commands.js.map +1 -1
  22. package/dist/glass.d.ts +3 -0
  23. package/dist/glass.js +81 -0
  24. package/dist/glass.js.map +1 -0
  25. package/dist/glassclip.d.ts +18 -0
  26. package/dist/glassclip.js +69 -0
  27. package/dist/glassclip.js.map +1 -0
  28. package/dist/guard.d.ts +17 -0
  29. package/dist/guard.js +44 -0
  30. package/dist/guard.js.map +1 -0
  31. package/dist/idle.d.ts +43 -0
  32. package/dist/idle.js +379 -0
  33. package/dist/idle.js.map +1 -0
  34. package/dist/index.d.ts +8 -0
  35. package/dist/index.js +6 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/inspect.d.ts +18 -1
  38. package/dist/inspect.js +48 -8
  39. package/dist/inspect.js.map +1 -1
  40. package/dist/loading.d.ts +17 -0
  41. package/dist/loading.js +96 -0
  42. package/dist/loading.js.map +1 -0
  43. package/dist/locale.js +1 -1
  44. package/dist/locale.js.map +1 -1
  45. package/dist/media.d.ts +71 -0
  46. package/dist/media.js +516 -0
  47. package/dist/media.js.map +1 -0
  48. package/dist/methods.js +14 -1
  49. package/dist/methods.js.map +1 -1
  50. package/dist/move.d.ts +40 -0
  51. package/dist/move.js +125 -0
  52. package/dist/move.js.map +1 -0
  53. package/dist/native.d.ts +5 -0
  54. package/dist/native.js.map +1 -1
  55. package/dist/network.d.ts +4 -0
  56. package/dist/network.js +49 -1
  57. package/dist/network.js.map +1 -1
  58. package/dist/place.d.ts +23 -0
  59. package/dist/place.js +66 -0
  60. package/dist/place.js.map +1 -0
  61. package/dist/placekey.d.ts +29 -0
  62. package/dist/placekey.js +134 -0
  63. package/dist/placekey.js.map +1 -0
  64. package/dist/routetree.d.ts +27 -0
  65. package/dist/routetree.js +216 -0
  66. package/dist/routetree.js.map +1 -0
  67. package/dist/types.d.ts +28 -2
  68. package/dist/types.js +5 -1
  69. package/dist/types.js.map +1 -1
  70. package/dist/uxcheck.d.ts +57 -0
  71. package/dist/uxcheck.js +222 -0
  72. package/dist/uxcheck.js.map +1 -0
  73. package/dist/wait.d.ts +5 -0
  74. package/dist/wait.js +34 -3
  75. package/dist/wait.js.map +1 -1
  76. package/ios/TaplineNativeModule.swift +61 -0
  77. package/package.json +1 -1
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.routePattern = routePattern;
4
+ exports.tabNameFromKey = tabNameFromKey;
5
+ exports.looksLikeValue = looksLikeValue;
6
+ exports.placeFrom = placeFrom;
7
+ exports.samePlace = samePlace;
8
+ const alerts_1 = require("./alerts");
9
+ const fiber_1 = require("./fiber");
10
+ const types_1 = require("./types");
11
+ /** Splits each route name on "/" so "trips/[id]" and ["trips","[id]"] agree (answer 12); empty pieces go. */
12
+ function routePattern(names) {
13
+ const out = [];
14
+ for (const name of names) {
15
+ for (const piece of name.split('/'))
16
+ if (piece !== '')
17
+ out.push(piece);
18
+ }
19
+ return out;
20
+ }
21
+ const SHEET_PRESENTATIONS = new Set(['formSheet', 'pageSheet', 'sheet']);
22
+ /** The deepest focused route, the last on ties (the same rule as `currentRoute`). */
23
+ function focusedRoute(routes) {
24
+ let best = null;
25
+ for (const route of routes) {
26
+ if (!route.focused)
27
+ continue;
28
+ if (best === null || route.chain.length >= best.chain.length)
29
+ best = route;
30
+ }
31
+ return best;
32
+ }
33
+ /**
34
+ * A native tab's route name from its `screenKey`. React Navigation keys are `<route name>-<21-character id>`, so the
35
+ * id is cut only when it is there; a key such as "home-tab" is a name with no id (and a name may hold a hyphen).
36
+ */
37
+ function tabNameFromKey(key) {
38
+ const match = /^(.+)-[A-Za-z0-9_-]{21}$/.exec(key);
39
+ return match?.[1] ?? key;
40
+ }
41
+ /** Whether `chain` starts with `prefix`. */
42
+ function startsWith(chain, prefix) {
43
+ return prefix.length <= chain.length && prefix.every((name, i) => chain[i] === name);
44
+ }
45
+ /** The root `testID` of a bare Modal's content, or undefined. */
46
+ function modalName(modal) {
47
+ const root = (0, fiber_1.firstHostChild)(modal);
48
+ const id = root ? (0, fiber_1.propsOf)(root).testID : undefined;
49
+ return typeof id === 'string' && id !== '' ? id : undefined;
50
+ }
51
+ /** `/` and `:` never appear in a layer name, so a key stays one piece. */
52
+ function plain(name) {
53
+ return name.replace(/[:/]/g, '_');
54
+ }
55
+ /**
56
+ * Whether a piece of a place looks like a value (an id, a number, a UUID, long hex) and not a name. A place holds
57
+ * patterns, never values (AGENT-TOOLS 1.13 §18.1). The host applies the same rule.
58
+ */
59
+ function looksLikeValue(piece) {
60
+ return (/^\d+$/.test(piece) ||
61
+ /\d{4,}/.test(piece) ||
62
+ /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i.test(piece) ||
63
+ /[0-9a-f]{16,}/i.test(piece));
64
+ }
65
+ /** A layer: its kind and, when the name isn't a value, its name. */
66
+ function layerOf(kind, name) {
67
+ return name === undefined || looksLikeValue(name) ? kind : `${kind}:${plain(name)}`;
68
+ }
69
+ /** Whether `fiber` lies inside `outer` (either copy of it). */
70
+ function inside(fiber, outer) {
71
+ for (let up = fiber.return; up; up = up.return) {
72
+ if (up === outer || up === outer.alternate)
73
+ return true;
74
+ }
75
+ return false;
76
+ }
77
+ /**
78
+ * Whether a bare Modal lies above a presented route: the Modal is inside that route's screen (opened from it) and the
79
+ * route is not inside the Modal. When the order can't be told, the route stays the layer, as before.
80
+ */
81
+ function modalAbove(modal, route) {
82
+ return route.fiber !== undefined && inside(modal, route.fiber) && !inside(route.fiber, modal);
83
+ }
84
+ function placeFrom(parts) {
85
+ const current = focusedRoute(parts.routes);
86
+ const chain = current ? current.chain : [];
87
+ const route = routePattern(chain);
88
+ // A route piece that looks like a value can't be a pattern: no route, and the host falls back to its signature.
89
+ const place = { route: route.some(looksLikeValue) ? [] : route };
90
+ const onPath = parts.routes.filter((route) => route.focused && startsWith(chain, route.chain));
91
+ // The selected tab: a tab navigator's selected route, else a native tab bar's selected tab (by its key, never its title).
92
+ for (const route of onPath) {
93
+ let type;
94
+ try {
95
+ const state = route.navigation.getState?.();
96
+ type = (0, types_1.isRecord)(state) ? state.type : undefined;
97
+ }
98
+ catch {
99
+ type = undefined;
100
+ }
101
+ if (type === 'tab') {
102
+ place.tab = route.name;
103
+ break;
104
+ }
105
+ }
106
+ if (place.tab === undefined) {
107
+ const selected = parts.tabs.find((tab) => tab.selected && tab.screenKey !== null);
108
+ if (selected?.screenKey)
109
+ place.tab = tabNameFromKey(selected.screenKey);
110
+ }
111
+ // What lies on top: an alert, else a modal or sheet (a navigation route's name, else a bare Modal's root testID).
112
+ if ((0, alerts_1.openAlerts)().length > 0) {
113
+ place.layer = 'alert';
114
+ }
115
+ else {
116
+ const presented = [...onPath].reverse().find((route) => route.presentation !== undefined);
117
+ if (presented?.presentation !== undefined && !(parts.modal && modalAbove(parts.modal, presented))) {
118
+ place.layer = layerOf(SHEET_PRESENTATIONS.has(presented.presentation) ? 'sheet' : 'modal', presented.name);
119
+ }
120
+ else if (parts.modal) {
121
+ place.layer = layerOf('modal', modalName(parts.modal));
122
+ }
123
+ }
124
+ if (place.tab !== undefined && looksLikeValue(place.tab))
125
+ delete place.tab;
126
+ return place;
127
+ }
128
+ /** Whether two places are the same key. */
129
+ function samePlace(a, b) {
130
+ if (a === null || b === null)
131
+ return a === b;
132
+ return a.tab === b.tab && a.layer === b.layer && a.route.length === b.route.length && a.route.every((name, i) => name === b.route[i]);
133
+ }
134
+ //# sourceMappingURL=placekey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placekey.js","sourceRoot":"","sources":["../src/placekey.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * AGENT-TOOLS 1.13 §18.1 ("Known before any visit"): the places an app has, listed from its own route tree. Expo Router's
3
+ * store is an internal API, so it is read behind a guard and any failure answers `source: "none"` (plan answer 21).
4
+ * Values of params never appear here, only their names.
5
+ */
6
+ export interface KnownPlace {
7
+ route: string[];
8
+ /** `<scheme>://<path>`, with `[id]` where a param goes; absent when the app has no scheme or the screen has no path. */
9
+ link?: string;
10
+ /** Param names such as "id"; values never. */
11
+ params: string[];
12
+ }
13
+ export interface KnownPlaces {
14
+ source: 'expo-router' | 'react-navigation' | 'none';
15
+ places: KnownPlace[];
16
+ }
17
+ /**
18
+ * The places in an Expo Router route tree (its `routeNode`): every leaf route, keyed by the layout and route names down to
19
+ * it. Exported for tests; the shape is read defensively, since it is Expo Router's own.
20
+ */
21
+ export declare function placesFromExpoTree(root: unknown, scheme: string | undefined): KnownPlace[];
22
+ /** A custom scheme beats an `https` prefix (the app opens from it directly); wildcard prefixes can't be used. */
23
+ export declare function pickPrefix(prefixes: unknown): string | undefined;
24
+ /** The places in a React Navigation `linking.config`: each leaf screen, keyed by the screen names down to it. Exported for tests. */
25
+ export declare function placesFromLinking(linking: unknown): KnownPlace[];
26
+ /** The `places` request: what the app's own route tree says it has, before any visit. Never throws. */
27
+ export declare function knownPlaces(): KnownPlaces;
@@ -0,0 +1,216 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.placesFromExpoTree = placesFromExpoTree;
4
+ exports.pickPrefix = pickPrefix;
5
+ exports.placesFromLinking = placesFromLinking;
6
+ exports.knownPlaces = knownPlaces;
7
+ const appinfo_1 = require("./appinfo");
8
+ const fiber_1 = require("./fiber");
9
+ const placekey_1 = require("./placekey");
10
+ const register_1 = require("./register");
11
+ const types_1 = require("./types");
12
+ /** Never go deeper than this: a route tree is a few levels; a cycle must not hang the app. */
13
+ const MAX_DEPTH = 12;
14
+ const MAX_PLACES = 500;
15
+ /* -------------------------------------------------------------------------- */
16
+ /* Expo Router */
17
+ /* -------------------------------------------------------------------------- */
18
+ const EXPO_PARAM = /^\[(?:\.\.\.)?([^\]]+)\]$/;
19
+ /** A group segment such as "(tabs)": part of the route key, not of the path. */
20
+ function isGroup(segment) {
21
+ return /^\(.*\)$/.test(segment);
22
+ }
23
+ /** Special files that aren't places a person navigates to: `+not-found`, `_sitemap` and the like. */
24
+ function isSpecial(name) {
25
+ return name.startsWith('+') || name.startsWith('_');
26
+ }
27
+ /**
28
+ * The places in an Expo Router route tree (its `routeNode`): every leaf route, keyed by the layout and route names down to
29
+ * it. Exported for tests; the shape is read defensively, since it is Expo Router's own.
30
+ */
31
+ function placesFromExpoTree(root, scheme) {
32
+ const places = [];
33
+ const visit = (node, names, depth) => {
34
+ if (!(0, types_1.isRecord)(node) || depth > MAX_DEPTH || places.length >= MAX_PLACES)
35
+ return;
36
+ const name = typeof node.route === 'string' ? node.route : '';
37
+ if (isSpecial(name) || node.type === 'api' || node.type === 'redirect' || node.type === 'rewrite')
38
+ return;
39
+ const here = name === '' ? names : [...names, name];
40
+ const children = Array.isArray(node.children) ? node.children : [];
41
+ if (children.length > 0) {
42
+ for (const child of children)
43
+ visit(child, here, depth + 1);
44
+ return;
45
+ }
46
+ if (node.type === 'layout' || here.length === 0)
47
+ return; // a layout with no screens is not a place
48
+ const route = (0, placekey_1.routePattern)(here);
49
+ const params = [];
50
+ for (const segment of route) {
51
+ const match = EXPO_PARAM.exec(segment);
52
+ if (match?.[1] !== undefined && !params.includes(match[1]))
53
+ params.push(match[1]);
54
+ }
55
+ const path = route.filter((segment) => !isGroup(segment) && segment !== 'index');
56
+ const place = { route, params };
57
+ if (scheme !== undefined)
58
+ place.link = `${scheme}://${path.join('/')}`;
59
+ places.push(place);
60
+ };
61
+ visit(root, [], 0);
62
+ return places;
63
+ }
64
+ /**
65
+ * Expo Router 58: the route tree is `routerConfig.routeNode`, the value of `RouterConfigContext`'s provider, which sits
66
+ * above the navigation container. Found through the fibers, the way the linking prop is.
67
+ */
68
+ function findRouterConfigNode() {
69
+ return findInFibers((props) => {
70
+ const value = props.value;
71
+ return (0, types_1.isRecord)(value) && (0, types_1.isRecord)(value.routeNode) && Array.isArray(value.routeNode.children) ? value.routeNode : undefined;
72
+ });
73
+ }
74
+ /** Expo Router 55: `routeNode` from its store, or null. Any failure (not installed, another version) is null. */
75
+ function expoStoreRouteNode() {
76
+ try {
77
+ // The `.js` matters: the package's exports map refuses an extensionless deep path.
78
+ const loaded = require('expo-router/build/global-state/router-store.js');
79
+ const store = (0, types_1.isRecord)(loaded) ? loaded.store : undefined;
80
+ if (!(0, types_1.isRecord)(store))
81
+ return null;
82
+ return store.routeNode ?? null;
83
+ }
84
+ catch {
85
+ return null;
86
+ }
87
+ }
88
+ /* -------------------------------------------------------------------------- */
89
+ /* React Navigation */
90
+ /* -------------------------------------------------------------------------- */
91
+ const NAVIGATION_PARAM = /^:([A-Za-z0-9_]+)\??$/;
92
+ /** A custom scheme beats an `https` prefix (the app opens from it directly); wildcard prefixes can't be used. */
93
+ function pickPrefix(prefixes) {
94
+ if (!Array.isArray(prefixes))
95
+ return undefined;
96
+ const usable = prefixes.filter((prefix) => typeof prefix === 'string' && prefix !== '' && !prefix.includes('*'));
97
+ const custom = usable.find((prefix) => !/^https?:/i.test(prefix));
98
+ return custom ?? usable[0];
99
+ }
100
+ /** `<prefix>/<path>`; a prefix that is only a scheme ("wayfare://") takes the path right after it. */
101
+ function linkFor(prefix, path) {
102
+ const scheme = /^([A-Za-z][A-Za-z0-9+.-]*):\/*$/.exec(prefix);
103
+ if (scheme)
104
+ return `${scheme[1]}://${path}`;
105
+ const base = prefix.replace(/\/+$/, '');
106
+ return path === '' ? base : `${base}/${path}`;
107
+ }
108
+ function joinPath(base, next, exact) {
109
+ const clean = next.replace(/^\/+|\/+$/g, '');
110
+ if (exact || base === '')
111
+ return clean;
112
+ return clean === '' ? base : `${base}/${clean}`;
113
+ }
114
+ /** The places in a React Navigation `linking.config`: each leaf screen, keyed by the screen names down to it. Exported for tests. */
115
+ function placesFromLinking(linking) {
116
+ if (!(0, types_1.isRecord)(linking) || !(0, types_1.isRecord)(linking.config))
117
+ return [];
118
+ const prefix = pickPrefix(linking.prefixes);
119
+ const places = [];
120
+ const visit = (screens, names, base, depth) => {
121
+ if (!(0, types_1.isRecord)(screens) || depth > MAX_DEPTH)
122
+ return;
123
+ for (const [name, entry] of Object.entries(screens)) {
124
+ if (places.length >= MAX_PLACES)
125
+ return;
126
+ const here = [...names, name];
127
+ let path = base;
128
+ let nestedScreens;
129
+ if (typeof entry === 'string') {
130
+ path = joinPath(base, entry, false);
131
+ }
132
+ else if ((0, types_1.isRecord)(entry)) {
133
+ if (typeof entry.path === 'string')
134
+ path = joinPath(base, entry.path, entry.exact === true);
135
+ nestedScreens = entry.screens;
136
+ }
137
+ if ((0, types_1.isRecord)(nestedScreens) && Object.keys(nestedScreens).length > 0) {
138
+ visit(nestedScreens, here, path, depth + 1);
139
+ continue;
140
+ }
141
+ const params = [];
142
+ for (const segment of path.split('/')) {
143
+ const match = NAVIGATION_PARAM.exec(segment);
144
+ if (match?.[1] !== undefined && !params.includes(match[1]))
145
+ params.push(match[1]);
146
+ }
147
+ const place = { route: (0, placekey_1.routePattern)(here), params };
148
+ // A path that is only the base prefix is the app's root; a screen with no path at all has no link.
149
+ const hasPath = typeof entry === 'string' || ((0, types_1.isRecord)(entry) && typeof entry.path === 'string');
150
+ if (prefix !== undefined && hasPath) {
151
+ place.link = linkFor(prefix, path.replace(/:([A-Za-z0-9_]+)\??/g, '[$1]'));
152
+ }
153
+ places.push(place);
154
+ }
155
+ };
156
+ visit(linking.config.screens, [], '', 0);
157
+ return places;
158
+ }
159
+ /** The first thing `pick` returns for a fiber's props, walking the tree from the root, child first; null when none. */
160
+ function findInFibers(pick) {
161
+ for (const root of (0, register_1.getRoots)()) {
162
+ const stack = root.current.child ? [root.current.child] : [];
163
+ let visited = 0;
164
+ for (let fiber = stack.pop(); fiber && visited < 5000; fiber = stack.pop()) {
165
+ visited += 1;
166
+ const found = pick((0, fiber_1.propsOf)(fiber));
167
+ if (found !== undefined)
168
+ return found;
169
+ if (fiber.sibling)
170
+ stack.push(fiber.sibling);
171
+ if (fiber.child)
172
+ stack.push(fiber.child);
173
+ }
174
+ }
175
+ return null;
176
+ }
177
+ /** The `linking` prop of the app's `NavigationContainer`, found through the fibers. */
178
+ function findLinking() {
179
+ return findInFibers((props) => ((0, types_1.isRecord)(props.linking) && (0, types_1.isRecord)(props.linking.config) ? props.linking : undefined));
180
+ }
181
+ /* -------------------------------------------------------------------------- */
182
+ /* The request */
183
+ /* -------------------------------------------------------------------------- */
184
+ /** The `places` request: what the app's own route tree says it has, before any visit. Never throws. */
185
+ function knownPlaces() {
186
+ try {
187
+ const scheme = (0, appinfo_1.appScheme)();
188
+ for (const read of [findRouterConfigNode, expoStoreRouteNode]) {
189
+ let node = null;
190
+ try {
191
+ node = read();
192
+ }
193
+ catch {
194
+ node = null; // an internal API that changed: try the next way
195
+ }
196
+ if (node === null)
197
+ continue;
198
+ const places = placesFromExpoTree(node, scheme);
199
+ if (places.length > 0)
200
+ return { source: 'expo-router', places };
201
+ }
202
+ }
203
+ catch {
204
+ // fall through
205
+ }
206
+ try {
207
+ const places = placesFromLinking(findLinking());
208
+ if (places.length > 0)
209
+ return { source: 'react-navigation', places };
210
+ }
211
+ catch {
212
+ // not a navigation app
213
+ }
214
+ return { source: 'none', places: [] };
215
+ }
216
+ //# sourceMappingURL=routetree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routetree.js","sourceRoot":"","sources":["../src/routetree.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /** Wire-protocol and shared types (see docs/PROTOCOL.md, version 1). */
2
2
  export declare const PROTOCOL_VERSION = 1;
3
- export type ErrorCode = 'not_found' | 'ambiguous' | 'not_actionable' | 'unsupported' | 'bad_params' | 'timeout' | 'internal';
3
+ export type ErrorCode = 'not_found' | 'ambiguous' | 'not_actionable' | 'unsupported' | 'bad_params' | 'timeout' | 'stale' | 'internal';
4
4
  export interface WireError {
5
5
  code: ErrorCode;
6
6
  message: string;
@@ -8,13 +8,22 @@ export interface WireError {
8
8
  refs?: string[];
9
9
  /** The candidates as elements (role, id, actions, frame), only for `ambiguous`. */
10
10
  candidates?: TaplineElement[];
11
+ /** Facts about a refusal that carry no text from the app (whether a field is secure, never its value). */
12
+ data?: {
13
+ secure: boolean;
14
+ };
11
15
  }
12
16
  /** An error that maps 1:1 onto a protocol error response. */
13
17
  export declare class TaplineError extends Error {
14
18
  readonly code: ErrorCode;
15
19
  readonly refs: string[] | undefined;
16
20
  readonly candidates: TaplineElement[] | undefined;
17
- constructor(code: ErrorCode, message: string, refs?: string[], candidates?: TaplineElement[]);
21
+ readonly data: {
22
+ secure: boolean;
23
+ } | undefined;
24
+ constructor(code: ErrorCode, message: string, refs?: string[], candidates?: TaplineElement[], data?: {
25
+ secure: boolean;
26
+ });
18
27
  toWire(): WireError;
19
28
  }
20
29
  export interface Frame {
@@ -45,6 +54,8 @@ export interface TaplineElement {
45
54
  selected: boolean;
46
55
  /** true / false / 'mixed' for checkable controls (Switch, checkbox role), else null. */
47
56
  checked: boolean | 'mixed' | null;
57
+ /** Inside a virtualized list's item: its text is content, so the host never saves it (AGENT-TOOLS 1.13 §18.2). */
58
+ row?: true;
48
59
  }
49
60
  export interface ScreenInfo {
50
61
  width: number;
@@ -107,6 +118,11 @@ export interface TreeResult {
107
118
  above: number;
108
119
  below: number;
109
120
  };
121
+ /** Only with `glass: true` (a journey in a user's eyes): whether a scroll view can really go further. Replaces the counts. */
122
+ glass?: {
123
+ moreAbove: boolean;
124
+ moreBelow: boolean;
125
+ };
110
126
  /** Open alerts (Alert.alert / Alert.prompt) the app showed, oldest first. */
111
127
  alerts?: TreeAlert[];
112
128
  /** Network requests still running (fetch / XMLHttpRequest) and the condition Tapline put on them; absent when neither. */
@@ -114,12 +130,22 @@ export interface TreeResult {
114
130
  inFlight?: number;
115
131
  condition?: 'offline' | '3g' | 'lossy';
116
132
  };
133
+ /** Present (as "fast") while the `animations` command has fast-forwarded animations. */
134
+ animations?: 'fast';
117
135
  /** True while the software keyboard is up; absent when it is down or isn't known. */
118
136
  keyboard?: true;
119
137
  /** The focused screen, when the app uses React Navigation (Expo Router included). */
120
138
  route?: RouteInfo;
121
139
  /** With `changes: true` and a previous tree: what changed since then. */
122
140
  changes?: TreeChanges;
141
+ /** Where the app is: route pattern, tab and layer, never params (AGENT-TOOLS 1.13 §18.1). Always present: `route` is empty without a router. */
142
+ place?: PlaceState;
143
+ }
144
+ /** A place as a route key: route patterns only, never a param's value or any screen text. */
145
+ export interface PlaceState {
146
+ route: string[];
147
+ tab?: string;
148
+ layer?: string;
123
149
  }
124
150
  export type Target = {
125
151
  ref: string;
package/dist/types.js CHANGED
@@ -9,12 +9,14 @@ class TaplineError extends Error {
9
9
  code;
10
10
  refs;
11
11
  candidates;
12
- constructor(code, message, refs, candidates) {
12
+ data;
13
+ constructor(code, message, refs, candidates, data) {
13
14
  super(message);
14
15
  this.name = 'TaplineError';
15
16
  this.code = code;
16
17
  this.refs = refs;
17
18
  this.candidates = candidates;
19
+ this.data = data;
18
20
  }
19
21
  toWire() {
20
22
  const wire = { code: this.code, message: this.message };
@@ -22,6 +24,8 @@ class TaplineError extends Error {
22
24
  wire.refs = this.refs;
23
25
  if (this.candidates)
24
26
  wire.candidates = this.candidates;
27
+ if (this.data)
28
+ wire.data = this.data;
25
29
  return wire;
26
30
  }
27
31
  }
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,wEAAwE;;;AA2LxE,4BAEC;AA3LY,QAAA,gBAAgB,GAAG,CAAC,CAAC;AAoBlC,6DAA6D;AAC7D,MAAa,YAAa,SAAQ,KAAK;IAC5B,IAAI,CAAY;IAChB,IAAI,CAAuB;IAC3B,UAAU,CAA+B;IAElD,YAAY,IAAe,EAAE,OAAe,EAAE,IAAe,EAAE,UAA6B;QAC1F,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,MAAM;QACJ,MAAM,IAAI,GAAc,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QACnE,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACrC,IAAI,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACvD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAnBD,oCAmBC;AAiJD,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,wEAAwE;;;AAgNxE,4BAEC;AAhNY,QAAA,gBAAgB,GAAG,CAAC,CAAC;AAuBlC,6DAA6D;AAC7D,MAAa,YAAa,SAAQ,KAAK;IAC5B,IAAI,CAAY;IAChB,IAAI,CAAuB;IAC3B,UAAU,CAA+B;IACzC,IAAI,CAAkC;IAE/C,YAAY,IAAe,EAAE,OAAe,EAAE,IAAe,EAAE,UAA6B,EAAE,IAA0B;QACtH,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,MAAM;QACJ,MAAM,IAAI,GAAc,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QACnE,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACrC,IAAI,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACvD,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAtBD,oCAsBC;AAgKD,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { type Entry } from './inspect';
2
+ import type { Frame } from './types';
3
+ /**
4
+ * `ux_check` (AGENT-TOOLS 1.12 §17.3): one screen against the basics, as facts. Each finding names the
5
+ * element it concerns and the basis it rests on: `measured`, `best practice: <rule>` or `house rule: <rule>`.
6
+ */
7
+ export type UxKind = 'choices' | 'main_action' | 'thumb_reach' | 'icon_only' | 'cut_off_text' | 'contrast' | 'target_size' | 'naming' | 'dead_end' | 'way_back';
8
+ export type UxCheckName = UxKind;
9
+ /** More competing choices than this on one screen is flagged (Hick's law). */
10
+ export declare const MAX_CHOICES = 7;
11
+ /** A phone at least this tall (points) has a top third out of the thumb's reach. */
12
+ export declare const TALL_SCREEN = 700;
13
+ /** The top-ranked action must be this many times as prominent as the next to count as clear. */
14
+ export declare const CLEAR_MARGIN = 1.5;
15
+ /** An action this far (points) from a message counts as near it. */
16
+ export declare const NEAR = 160;
17
+ export declare const BASIS_CHOICES = "best practice: Hick's law, more than 7 choices";
18
+ export declare const BASIS_MAIN = "best practice: one clear main action per screen";
19
+ export declare const BASIS_THUMB = "best practice: thumb zone, main actions belong in the lower part of a tall screen";
20
+ export declare const BASIS_ICON = "best practice: an icon-only button needs an accessibility label";
21
+ export declare const BASIS_NAMING = "best practice: name the same action the same way on every screen";
22
+ export declare const BASIS_DEAD_END = "best practice: an error or empty state says what to do next";
23
+ export declare const BASIS_WAY_BACK = "house rule: every screen has a way back";
24
+ /** An action seen on an earlier screen of the journey (the journey keeps these and hands them back). */
25
+ export interface UxAction {
26
+ label: string;
27
+ id?: string;
28
+ }
29
+ export interface UxFinding {
30
+ kind: UxKind;
31
+ /** The element, or null for the screen as a whole. */
32
+ entry: Entry | null;
33
+ frame: Frame | null;
34
+ problem: string;
35
+ basis: string;
36
+ }
37
+ export interface UxOptions {
38
+ /** `way_back` is a house rule: check that the screen has a visible way back. */
39
+ wayBack?: boolean;
40
+ /** Actions on earlier screens of the running journey; undefined when there is no journey. */
41
+ earlier?: readonly UxAction[];
42
+ /** A journey in a user's eyes (AGENT-TOOLS 1.12 §17.1): only what shows on the glass is checked. */
43
+ glass?: boolean;
44
+ }
45
+ export interface UxResult {
46
+ findings: UxFinding[];
47
+ checked: UxCheckName[];
48
+ /** Number of competing choices on the screen. */
49
+ choices: number;
50
+ /** The named actions on this screen, for the journey to keep as "earlier" for later screens. */
51
+ actions: UxAction[];
52
+ }
53
+ /** Names that are two names for one action: the same group of synonyms, but not the same words. */
54
+ export declare function sameActionDifferentName(a: string, b: string): boolean;
55
+ /** Text that reads like an error or an empty-state message. */
56
+ export declare function looksLikeMessage(text: string): boolean;
57
+ export declare function uxScreen(options?: UxOptions): Promise<UxResult>;