@blario/react-native 0.1.3 → 0.1.4

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 CHANGED
@@ -312,7 +312,7 @@ Wire envelope (mirrors the backend): `agent_command` / `request_dom_state` / `re
312
312
 
313
313
  | `action.type` | Fields | Target |
314
314
  | --- | --- | --- |
315
- | `click` | | `btn-N` (a switch toggles, an input is focused) |
315
+ | `click` | | `btn-N` (a switch toggles, an input is focused, a wheel picker's row scrolls to the center) |
316
316
  | `type` | `value`, `clear_first` (default true) | `inp-N` text input |
317
317
  | `check` | `checked` (omit to toggle) | `inp-N` switch |
318
318
  | `press_key` | `key` (`Enter` only) | `inp-N`, or the last input used |
@@ -322,7 +322,8 @@ Wire envelope (mirrors the backend): `agent_command` / `request_dom_state` / `re
322
322
  | `highlight` | `duration_ms` (default 3000) | any element |
323
323
 
324
324
  `click`, `type`, `check` and `highlight` scroll the target into view first. Elements that sit beyond their scroll
325
- viewport are listed with `offscreen=above|below|left|right` (at most 30, nearest first).
325
+ viewport are listed with `offscreen=above|below|left|right` (at most 30, nearest first). A wheel picker is a snapping
326
+ list (`snapToInterval` or `snapToOffsets`) of plain text rows: each row is a `btn-N`, and all of them stay listed.
326
327
 
327
328
  ## Develop
328
329
 
@@ -5,6 +5,8 @@ type ScrollAction = Extract<AgentAction, {
5
5
  type: 'scroll';
6
6
  }>;
7
7
  export declare function scrollContainer(target: ResolvedTarget, action: ScrollAction): Promise<HandlerResult>;
8
+ export declare function isInWheel(target: ResolvedTarget): boolean;
9
+ export declare function selectWheelOption(target: ResolvedTarget): Promise<HandlerResult>;
8
10
  export declare function scrollIntoView(target: ResolvedTarget, options?: {
9
11
  animated: boolean;
10
12
  }): Promise<HandlerResult>;
@@ -8,6 +8,7 @@ export interface Candidate {
8
8
  host: Fiber;
9
9
  ancestors: Fiber[];
10
10
  scrollContainers: Fiber[];
11
+ wheelOption?: boolean;
11
12
  }
12
13
  export interface TextBlock {
13
14
  host: Fiber;
@@ -7,9 +7,11 @@ export interface ScrollGeometry {
7
7
  horizontal: boolean;
8
8
  }
9
9
  export declare function isHorizontal(fiber: Fiber): boolean;
10
+ export declare function isWheel(fiber: Fiber): boolean;
10
11
  export declare function measureScrollGeometry(scrollFiber: Fiber): Promise<ScrollGeometry | null>;
11
12
  export declare function scrollOffsetOf(geometry: ScrollGeometry): number;
12
13
  export declare function maxScrollOffsetOf(geometry: ScrollGeometry): number;
13
14
  export declare function viewportExtentOf(geometry: ScrollGeometry): number;
15
+ export declare function offsetCentering(rect: Rect, geometry: ScrollGeometry): number;
14
16
  export declare function scrollDirectionsOf(geometry: ScrollGeometry): ScrollDirection[];
15
17
  export declare function describeScrollDirections(geometry: ScrollGeometry | null): string;
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "0.1.3";
1
+ export declare const SDK_VERSION = "0.1.4";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blario/react-native",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Blar agent SDK for React Native",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -6,6 +6,7 @@ import { buildPressEvent } from './events.ts';
6
6
  import { checkInteractable } from './interaction-guards.ts';
7
7
  import { failed, failedFromException, succeeded } from './result.ts';
8
8
  import type { ActionServices } from './services.ts';
9
+ import { isInWheel, selectWheelOption } from './scrolling.ts';
9
10
  import type { ResolvedTarget } from './target.ts';
10
11
  import type { HandlerResult } from './types.ts';
11
12
  import { toggleSwitch } from './switch.ts';
@@ -49,6 +50,6 @@ export async function click(target: ResolvedTarget, services: ActionServices): P
49
50
  case 'text_input':
50
51
  return focusInput(target, services);
51
52
  default:
52
- return pressButton(target);
53
+ return !isFunction(target.props.onPress) && isInWheel(target) ? selectWheelOption(target) : pressButton(target);
53
54
  }
54
55
  }
@@ -1,7 +1,7 @@
1
1
  import { measureHost } from '../host/measure.ts';
2
2
  import { type Band, scrollDeltaIntoBand } from '../host/rect.ts';
3
3
  import { scrollInstanceOf } from '../snapshot/classify.ts';
4
- import { maxScrollOffsetOf, measureScrollGeometry, scrollOffsetOf, type ScrollGeometry, viewportExtentOf } from '../snapshot/scroll.ts';
4
+ import { isWheel, maxScrollOffsetOf, measureScrollGeometry, offsetCentering, scrollOffsetOf, type ScrollGeometry, viewportExtentOf } from '../snapshot/scroll.ts';
5
5
  import { failed, failedFromException, succeeded } from './result.ts';
6
6
  import type { ResolvedTarget } from './target.ts';
7
7
  import type { AgentAction, HandlerResult } from './types.ts';
@@ -61,6 +61,28 @@ function nearestScrollAncestor(target: ResolvedTarget): ResolvedTarget['fiber']
61
61
  return null;
62
62
  }
63
63
 
64
+ export function isInWheel(target: ResolvedTarget): boolean {
65
+ const container = nearestScrollAncestor(target);
66
+ return container !== null && isWheel(container);
67
+ }
68
+
69
+ // The animated scroll ends in onMomentumScrollEnd, the event a wheel commits its value on, as a user's swipe does.
70
+ export async function selectWheelOption(target: ResolvedTarget): Promise<HandlerResult> {
71
+ const container = nearestScrollAncestor(target);
72
+ if (container === null || target.host === null) {
73
+ return failed('element_not_interactable', 'the option is not inside a wheel');
74
+ }
75
+ const [geometry, rect] = await Promise.all([measureScrollGeometry(container), measureHost(target.host)]);
76
+ if (geometry === null || rect === null) {
77
+ return failed('element_not_found', 'the option or its wheel could not be measured');
78
+ }
79
+ const next = offsetCentering(rect, geometry);
80
+ if (Math.abs(next - scrollOffsetOf(geometry)) < MOVEMENT_TOLERANCE) {
81
+ return succeeded('the option is already selected');
82
+ }
83
+ return applyOffset({ ...target, fiber: container }, geometry, next, true);
84
+ }
85
+
64
86
  function offsetDeltaToReveal(start: number, end: number, viewportStart: number, viewportEnd: number): number {
65
87
  const startShortfall = start - (viewportStart + VISIBLE_MARGIN);
66
88
  if (startShortfall < 0) {