craft-native 0.0.204 → 0.0.206

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/dist/cli.js CHANGED
@@ -3424,7 +3424,7 @@ function pinCraftNativeDependency(packagePath, craftVersion) {
3424
3424
  `);
3425
3425
  }
3426
3426
  // package.json
3427
- var version = "0.0.204";
3427
+ var version = "0.0.206";
3428
3428
 
3429
3429
  // bin/cli.ts
3430
3430
  var spawnedFrom = process6.env[CRAFT_CLI_SPAWN_MARKER];
@@ -86,7 +86,13 @@ export interface LayoutStyle {
86
86
  /** Overflow */
87
87
  overflow?: 'visible' | 'hidden' | 'scroll';
88
88
  /** Display */
89
- display?: 'flex' | 'none';
89
+ display?: 'flex' | 'none' | 'grid';
90
+ /** Equal-width grid track count or CSS-shaped `repeat(N, 1fr)` tracks. */
91
+ gridTemplateColumns?: number | string;
92
+ /** Legacy numeric alias for the grid track count. */
93
+ gridColumns?: number;
94
+ /** Intrinsic or fixed height for automatically-created grid rows. */
95
+ gridAutoRows?: number | string;
90
96
  }
91
97
  /**
92
98
  * Spacing style properties.
@@ -166,6 +172,14 @@ export interface ColorStyle {
166
172
  backgroundColor?: string;
167
173
  /** Opacity */
168
174
  opacity?: number;
175
+ /** Linear-gradient direction used by native hosts. */
176
+ gradientDirection?: 'to-t' | 'to-tr' | 'to-r' | 'to-br' | 'to-b' | 'to-bl' | 'to-l' | 'to-tl';
177
+ /** Linear-gradient start color. */
178
+ gradientFrom?: string;
179
+ /** Optional linear-gradient middle stop. */
180
+ gradientVia?: string;
181
+ /** Linear-gradient end color. */
182
+ gradientTo?: string;
169
183
  }
170
184
  /**
171
185
  * Shadow style properties.
@@ -265,7 +279,7 @@ export type TextStyle = ViewStyle & TextStyleProps;
265
279
  */
266
280
  export interface ImageStyleProps {
267
281
  /** Resize mode */
268
- resizeMode?: 'cover' | 'contain' | 'stretch' | 'repeat' | 'center';
282
+ resizeMode?: 'cover' | 'contain' | 'stretch' | 'center';
269
283
  /** Tint color */
270
284
  tintColor?: string;
271
285
  }
@@ -290,7 +304,9 @@ export interface BaseProps {
290
304
  /** Accessibility state exposed to assistive technologies */
291
305
  accessibilityState?: AccessibilityState;
292
306
  /** Accessibility role */
293
- accessibilityRole?: 'none' | 'button' | 'link' | 'image' | 'text' | 'header' | 'search' | 'menu';
307
+ accessibilityRole?: 'none' | 'button' | 'link' | 'image' | 'text' | 'header' | 'search' | 'adjustable' | 'menu' | 'summary' | 'alert' | 'checkbox' | 'combobox' | 'menuitem' | 'progressbar' | 'radio' | 'tablist' | 'radiogroup' | 'list' | 'menubar' | 'spinbutton' | 'switch' | 'tab' | 'timer' | 'toolbar' | 'scrollbar';
308
+ /** Matches a view across an animated state change. */
309
+ transitionID?: string;
294
310
  /** Children elements */
295
311
  children?: any;
296
312
  }
@@ -307,12 +323,12 @@ export interface ViewProps extends BaseProps {
307
323
  style?: ViewStyle | ViewStyle[];
308
324
  /** Press handler */
309
325
  onPress?: () => void;
326
+ /** DOM-compatible press alias accepted by native hosts. */
327
+ onClick?: () => void;
310
328
  /** Long press handler */
311
329
  onLongPress?: () => void;
312
330
  /** Layout change handler */
313
331
  onLayout?: (event: LayoutEvent) => void;
314
- /** Pointer events behavior */
315
- pointerEvents?: 'auto' | 'none' | 'box-none' | 'box-only';
316
332
  }
317
333
  /** Safe-area container props used by native iOS and Android screens. */
318
334
  export interface SafeAreaViewProps extends ViewProps {
@@ -324,6 +340,17 @@ export interface KeyboardAvoidingViewProps extends ViewProps {
324
340
  behavior?: 'height' | 'position' | 'padding';
325
341
  keyboardVerticalOffset?: number;
326
342
  }
343
+ /** Native status-bar appearance for the current screen. */
344
+ export interface StatusBarProps extends BaseProps {
345
+ barStyle?: 'default' | 'light-content' | 'dark-content';
346
+ hidden?: boolean;
347
+ }
348
+ /** Pull-to-refresh control consumed by a parent ScrollView or FlatList. */
349
+ export interface RefreshControlProps extends BaseProps {
350
+ refreshing?: boolean;
351
+ onRefresh?: () => void;
352
+ tintColor?: string;
353
+ }
327
354
  /**
328
355
  * Text component props.
329
356
  */
@@ -334,8 +361,6 @@ export interface TextProps extends BaseProps {
334
361
  numberOfLines?: number;
335
362
  /** Ellipsize mode */
336
363
  ellipsizeMode?: 'head' | 'middle' | 'tail' | 'clip';
337
- /** Selectable text */
338
- selectable?: boolean;
339
364
  /** Press handler */
340
365
  onPress?: () => void;
341
366
  /** Long press handler */
@@ -345,6 +370,7 @@ export interface TextProps extends BaseProps {
345
370
  export interface ButtonProps extends BaseProps {
346
371
  title?: string;
347
372
  onPress?: () => void;
373
+ onClick?: () => void;
348
374
  disabled?: boolean;
349
375
  color?: string;
350
376
  }
@@ -369,10 +395,8 @@ export interface TouchableHighlightProps extends ViewProps {
369
395
  */
370
396
  export type ImageSource = {
371
397
  uri: string;
372
- width?: number;
373
- height?: number;
374
398
  headers?: Record<string, string>;
375
- } | number;
399
+ };
376
400
  /**
377
401
  * Image component props.
378
402
  */
@@ -382,7 +406,7 @@ export interface ImageProps extends BaseProps {
382
406
  /** Style object or array */
383
407
  style?: ImageStyle | ImageStyle[];
384
408
  /** Resize mode */
385
- resizeMode?: 'cover' | 'contain' | 'stretch' | 'repeat' | 'center';
409
+ resizeMode?: 'cover' | 'contain' | 'stretch' | 'center';
386
410
  /** Load start handler */
387
411
  onLoadStart?: () => void;
388
412
  /** Load handler */
@@ -393,10 +417,6 @@ export interface ImageProps extends BaseProps {
393
417
  onError?: (error: Error) => void;
394
418
  /** Default source while loading */
395
419
  defaultSource?: ImageSource;
396
- /** Blur radius */
397
- blurRadius?: number;
398
- /** Fade duration (ms) */
399
- fadeDuration?: number;
400
420
  /** Alt text for accessibility */
401
421
  alt?: string;
402
422
  }
@@ -453,12 +473,15 @@ export interface MapRegion {
453
473
  }
454
474
  export interface MapProps extends BaseProps {
455
475
  region?: MapRegion;
476
+ /** Initial camera region; applied once, then controlled by subsequent props. */
477
+ initialRegion?: MapRegion;
456
478
  fitToBounds?: boolean;
457
479
  showsUserLocation?: boolean;
458
480
  scrollEnabled?: boolean;
459
481
  zoomEnabled?: boolean;
460
482
  rotateEnabled?: boolean;
461
- mapType?: 'standard' | 'satellite' | 'hybrid' | 'terrain';
483
+ /** Map styles implemented consistently by the maintained iOS and Android hosts. */
484
+ mapType?: 'standard' | 'satellite' | 'hybrid';
462
485
  onMarkerPress?: (event: {
463
486
  nativeEvent: {
464
487
  id: string;
@@ -486,7 +509,60 @@ export interface MapMarkerProps extends BaseProps {
486
509
  }) => void;
487
510
  }
488
511
  export interface ImageBackgroundProps extends ImageProps {
489
- imageStyle?: ImageStyle | ImageStyle[];
512
+ }
513
+ /** Shared paint and accessibility props for DOM-free native SVG nodes. */
514
+ export interface SvgPaintProps extends BaseProps {
515
+ style?: ViewStyle | ViewStyle[];
516
+ fill?: string;
517
+ stroke?: string;
518
+ strokeWidth?: number;
519
+ strokeDasharray?: number[] | string;
520
+ strokeDashoffset?: number;
521
+ strokeLinecap?: 'butt' | 'round' | 'square';
522
+ strokeLinejoin?: 'miter' | 'round' | 'bevel';
523
+ strokeMiterlimit?: number;
524
+ strokeOpacity?: number;
525
+ fillOpacity?: number;
526
+ fillRule?: 'nonzero' | 'evenodd';
527
+ vectorEffect?: 'none' | 'non-scaling-stroke';
528
+ color?: string;
529
+ opacity?: number;
530
+ /** Font weight inherited by descendant native SVG text. */
531
+ fontWeight?: string | number;
532
+ }
533
+ /** Root native SVG drawing surface. */
534
+ export interface SvgProps extends SvgPaintProps {
535
+ viewBox?: [number, number, number, number] | string;
536
+ preserveAspectRatio?: string;
537
+ }
538
+ /** Native SVG group inheriting paint from its parent. */
539
+ export interface GProps extends SvgPaintProps {
540
+ }
541
+ /** Shared generated geometry prop for native SVG shape nodes. */
542
+ export interface SvgShapeProps extends SvgPaintProps {
543
+ geometry?: number[];
544
+ }
545
+ export interface PathProps extends SvgShapeProps {
546
+ }
547
+ export interface LineProps extends SvgShapeProps {
548
+ }
549
+ export interface RectProps extends SvgShapeProps {
550
+ }
551
+ export interface CircleProps extends SvgShapeProps {
552
+ }
553
+ export interface EllipseProps extends SvgShapeProps {
554
+ }
555
+ export interface PolylineProps extends SvgShapeProps {
556
+ }
557
+ export interface PolygonProps extends SvgShapeProps {
558
+ }
559
+ /** Native SVG text painted in the root viewBox. */
560
+ export interface SvgTextProps extends SvgPaintProps {
561
+ x?: number;
562
+ y?: number;
563
+ fontSize?: number;
564
+ textAnchor?: 'start' | 'middle' | 'end' | string;
565
+ dominantBaseline?: string;
490
566
  }
491
567
  /**
492
568
  * ScrollView component props.
@@ -524,8 +600,18 @@ export interface ScrollViewProps extends ViewProps {
524
600
  keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
525
601
  /** Keyboard should persist taps */
526
602
  keyboardShouldPersistTaps?: 'always' | 'never' | 'handled';
527
- /** Refresh control component */
528
- refreshControl?: any;
603
+ /** Keep indexed vertical children pinned while scrolling. */
604
+ stickyHeaderIndices?: number[];
605
+ /** Scroll a child into view when this target changes. */
606
+ scrollTarget?: string | {
607
+ id: string;
608
+ animated?: boolean;
609
+ key?: string;
610
+ } | null;
611
+ /** Render content in reverse order along the scroll axis. */
612
+ inverted?: boolean;
613
+ /** Controlled native pull-to-refresh component. */
614
+ refreshControl?: RefreshControlProps;
529
615
  }
530
616
  /**
531
617
  * Pressable component props.
@@ -537,28 +623,6 @@ export interface PressableProps extends ViewProps {
537
623
  onPressIn?: () => void;
538
624
  /** Press out handler */
539
625
  onPressOut?: () => void;
540
- /** Hit slop for touch area */
541
- hitSlop?: number | {
542
- top?: number;
543
- right?: number;
544
- bottom?: number;
545
- left?: number;
546
- };
547
- /** Press retention offset */
548
- pressRetentionOffset?: number | {
549
- top?: number;
550
- right?: number;
551
- bottom?: number;
552
- left?: number;
553
- };
554
- /** Android ripple effect */
555
- android_ripple?: {
556
- color?: string;
557
- borderless?: boolean;
558
- radius?: number;
559
- };
560
- /** Delay for long press */
561
- delayLongPress?: number;
562
626
  }
563
627
  /**
564
628
  * TextInput component props.
@@ -586,6 +650,10 @@ export interface TextInputProps extends BaseProps {
586
650
  autoFocus?: boolean;
587
651
  /** Secure text entry (password) */
588
652
  secureTextEntry?: boolean;
653
+ /** Platform autofill content type (for example `username` or `oneTimeCode`). */
654
+ textContentType?: string;
655
+ /** HTML-style autofill hint (for example `current-password`). */
656
+ autoComplete?: string;
589
657
  /** Multi-line input */
590
658
  multiline?: boolean;
591
659
  /** Number of lines for multiline */
@@ -598,6 +666,8 @@ export interface TextInputProps extends BaseProps {
598
666
  selectionColor?: string;
599
667
  /** Change text handler */
600
668
  onChangeText?: (text: string) => void;
669
+ /** DOM-compatible change alias accepted by native hosts. */
670
+ onChange?: (text: string) => void;
601
671
  /** Focus handler */
602
672
  onFocus?: () => void;
603
673
  /** Blur handler */
@@ -607,11 +677,13 @@ export interface TextInputProps extends BaseProps {
607
677
  /** End editing handler */
608
678
  onEndEditing?: () => void;
609
679
  }
610
- export type KeyboardType = 'default' | 'email-address' | 'numeric' | 'phone-pad' | 'number-pad' | 'decimal-pad' | 'url' | 'web-search' | 'visible-password' | 'ascii-capable' | 'numbers-and-punctuation' | 'name-phone-pad' | 'twitter';
680
+ export type KeyboardType = 'default' | 'email-address' | 'numeric' | 'phone-pad' | 'number-pad' | 'decimal-pad' | 'url' | 'web-search' | 'visible-password';
611
681
  export type ReturnKeyType = 'done' | 'go' | 'next' | 'search' | 'send' | 'join' | 'route' | 'continue' | 'emergency-call' | 'default';
612
682
  export interface SwitchProps extends BaseProps {
683
+ /** Controlled boolean state; malformed native bridge values stay off. */
613
684
  value?: boolean;
614
685
  onValueChange?: (value: boolean) => void;
686
+ onChange?: (value: boolean) => void;
615
687
  disabled?: boolean;
616
688
  trackColor?: {
617
689
  false?: string;
@@ -621,11 +693,13 @@ export interface SwitchProps extends BaseProps {
621
693
  ios_backgroundColor?: string;
622
694
  }
623
695
  export interface CheckboxProps extends BaseProps {
696
+ /** Controlled boolean state; malformed native bridge values stay off. */
624
697
  value?: boolean;
625
698
  checked?: boolean;
626
699
  indeterminate?: boolean;
627
700
  label?: string;
628
701
  onValueChange?: (value: boolean) => void;
702
+ onChange?: (value: boolean) => void;
629
703
  disabled?: boolean;
630
704
  color?: string;
631
705
  }
@@ -635,6 +709,7 @@ export interface SliderProps extends BaseProps {
635
709
  maximumValue?: number;
636
710
  step?: number;
637
711
  onValueChange?: (value: number) => void;
712
+ onChange?: (value: number) => void;
638
713
  onSlidingComplete?: (value: number) => void;
639
714
  disabled?: boolean;
640
715
  minimumTrackTintColor?: string;
@@ -643,12 +718,15 @@ export interface SliderProps extends BaseProps {
643
718
  }
644
719
  export interface PickerOption {
645
720
  label: string;
721
+ /** String or finite number; other bridge values are ignored by native hosts. */
646
722
  value: string | number;
647
723
  }
648
724
  export interface PickerProps extends BaseProps {
649
- items: PickerOption[];
725
+ /** Typed options; child options remain supported when omitted. */
726
+ items?: PickerOption[];
650
727
  selectedValue?: string | number;
651
728
  onValueChange?: (value: string | number, index: number) => void;
729
+ onChange?: (value: string | number, index: number) => void;
652
730
  disabled?: boolean;
653
731
  }
654
732
  export interface DatePickerChange {
@@ -662,8 +740,8 @@ export interface DatePickerProps extends BaseProps {
662
740
  minimumDate?: string | number;
663
741
  maximumDate?: string | number;
664
742
  minuteInterval?: number;
665
- display?: 'compact' | 'inline' | 'wheels';
666
743
  onValueChange?: (event: DatePickerChange) => void;
744
+ onChange?: (event: DatePickerChange) => void;
667
745
  disabled?: boolean;
668
746
  }
669
747
  export interface ActivityIndicatorProps extends BaseProps {
@@ -685,28 +763,8 @@ export interface FlatListProps<T> extends ScrollViewProps {
685
763
  }) => any;
686
764
  /** Key extractor function */
687
765
  keyExtractor?: (item: T, index: number) => string;
688
- /** Item separator component */
689
- ItemSeparatorComponent?: any;
690
- /** List header component */
691
- ListHeaderComponent?: any;
692
- /** List footer component */
693
- ListFooterComponent?: any;
694
- /** Empty list component */
695
- ListEmptyComponent?: any;
696
766
  /** Number of columns */
697
767
  numColumns?: number;
698
- /** Initial number to render */
699
- initialNumToRender?: number;
700
- /** Max to render per batch */
701
- maxToRenderPerBatch?: number;
702
- /** Window size */
703
- windowSize?: number;
704
- /** Get item layout for optimization */
705
- getItemLayout?: (data: T[] | null, index: number) => {
706
- length: number;
707
- offset: number;
708
- index: number;
709
- };
710
768
  /** End reached handler */
711
769
  onEndReached?: () => void;
712
770
  /** End reached threshold */
@@ -722,16 +780,6 @@ export interface SectionListSection<T> {
722
780
  title?: string;
723
781
  }
724
782
  export interface SectionListProps<T> extends ScrollViewProps {
725
- sections: SectionListSection<T>[];
726
- renderItem: (info: {
727
- item: T;
728
- index: number;
729
- section: SectionListSection<T>;
730
- }) => any;
731
- renderSectionHeader?: (info: {
732
- section: SectionListSection<T>;
733
- }) => any;
734
- keyExtractor?: (item: T, index: number) => string;
735
783
  }
736
784
  export interface ModalProps extends BaseProps {
737
785
  visible?: boolean;
package/dist/index.cjs CHANGED
@@ -309,7 +309,7 @@ function craftBinaryNotFoundMessage(triedPath) {
309
309
  `);
310
310
  }
311
311
  // package.json
312
- var version = "0.0.204";
312
+ var version = "0.0.206";
313
313
 
314
314
  // src/sdk-version.ts
315
315
  var SDK_VERSION = version;
package/dist/index.d.cts CHANGED
@@ -30,7 +30,7 @@ export * from './utils/index.js';
30
30
  export * from './api/index.js';
31
31
  export * as components from './components/index.js';
32
32
  export { createTahoeSidebar, createArcSidebar, createOrbStackSidebar, sidebarItem, sidebarSection, sidebarSeparator, tahoeStyle, arcStyle, orbstackStyle, createSplitView, SplitViewInstance, createFileBrowser, FileBrowserInstance, createOutlineView, OutlineViewInstance, createTableView, TableViewInstance, showQuickLook, hideQuickLook, canQuickLook, showColorPicker, showFontPicker, showDatePicker, createProgress, ProgressInstance, setToolbar, updateToolbarItem, setToolbarVisible, setTouchBar, updateTouchBarItem, StyleSheet, Animated, } from './components/index.js';
33
- export type { ContextMenuItem, SidebarStyle, SidebarPosition, SidebarHeaderConfig, SidebarFooterConfig, SidebarEventType, SidebarEventMap, SidebarEventHandler, ComponentProps, ComponentInstance, SplitViewOrientation, SplitViewDividerStyle, SplitViewConfig, FileBrowserConfig, FileBrowserSelection, OutlineItem, OutlineViewConfig, TableRow, TableViewConfig, QuickLookConfig, ColorPickerConfig, FontPickerConfig, FontResult, DatePickerConfig, ProgressConfig, ToolbarItem, ToolbarConfig, TouchBarConfig, FlexStyle, LayoutStyle, SpacingStyle, BorderStyle, ColorStyle, ShadowStyle, TransformStyle, ViewStyle, TextStyleProps, TextStyle, ImageStyleProps, ImageStyle, BaseProps, ViewProps, SafeAreaViewProps, KeyboardAvoidingViewProps, TextProps, ButtonProps, LinkProps, TouchableOpacityProps, TouchableHighlightProps, ImageSource, ImageProps, ImageBackgroundProps, IconProps, VideoProps, MapRegion, MapProps, MapPolylineProps, MapMarkerProps, ScrollViewProps, PressableProps, TextInputProps, KeyboardType, ReturnKeyType, SwitchProps, CheckboxProps, SliderProps, PickerOption, PickerProps, DatePickerChange, DatePickerProps, ActivityIndicatorProps, FlatListProps, SectionListSection, SectionListProps, ModalProps, LayoutEvent, ScrollEvent, } from './components/index.js';
33
+ export type { ContextMenuItem, SidebarStyle, SidebarPosition, SidebarHeaderConfig, SidebarFooterConfig, SidebarEventType, SidebarEventMap, SidebarEventHandler, ComponentProps, ComponentInstance, SplitViewOrientation, SplitViewDividerStyle, SplitViewConfig, FileBrowserConfig, FileBrowserSelection, OutlineItem, OutlineViewConfig, TableRow, TableViewConfig, QuickLookConfig, ColorPickerConfig, FontPickerConfig, FontResult, DatePickerConfig, ProgressConfig, ToolbarItem, ToolbarConfig, TouchBarConfig, FlexStyle, LayoutStyle, SpacingStyle, BorderStyle, ColorStyle, ShadowStyle, TransformStyle, ViewStyle, TextStyleProps, TextStyle, ImageStyleProps, ImageStyle, BaseProps, ViewProps, SafeAreaViewProps, KeyboardAvoidingViewProps, StatusBarProps, RefreshControlProps, TextProps, ButtonProps, LinkProps, TouchableOpacityProps, TouchableHighlightProps, ImageSource, ImageProps, ImageBackgroundProps, SvgPaintProps, SvgProps, GProps, SvgShapeProps, PathProps, LineProps, RectProps, CircleProps, EllipseProps, PolylineProps, PolygonProps, SvgTextProps, IconProps, VideoProps, MapRegion, MapProps, MapPolylineProps, MapMarkerProps, ScrollViewProps, PressableProps, TextInputProps, KeyboardType, ReturnKeyType, SwitchProps, CheckboxProps, SliderProps, PickerOption, PickerProps, DatePickerChange, DatePickerProps, ActivityIndicatorProps, FlatListProps, SectionListSection, SectionListProps, ModalProps, LayoutEvent, ScrollEvent, } from './components/index.js';
34
34
  export * from './styles/headwind.js';
35
35
  export * from './styles/index.js';
36
36
  export * from './optimizations/index.js';
package/dist/index.d.ts CHANGED
@@ -30,7 +30,7 @@ export * from './utils/index.js';
30
30
  export * from './api/index.js';
31
31
  export * as components from './components/index.js';
32
32
  export { createTahoeSidebar, createArcSidebar, createOrbStackSidebar, sidebarItem, sidebarSection, sidebarSeparator, tahoeStyle, arcStyle, orbstackStyle, createSplitView, SplitViewInstance, createFileBrowser, FileBrowserInstance, createOutlineView, OutlineViewInstance, createTableView, TableViewInstance, showQuickLook, hideQuickLook, canQuickLook, showColorPicker, showFontPicker, showDatePicker, createProgress, ProgressInstance, setToolbar, updateToolbarItem, setToolbarVisible, setTouchBar, updateTouchBarItem, StyleSheet, Animated, } from './components/index.js';
33
- export type { ContextMenuItem, SidebarStyle, SidebarPosition, SidebarHeaderConfig, SidebarFooterConfig, SidebarEventType, SidebarEventMap, SidebarEventHandler, ComponentProps, ComponentInstance, SplitViewOrientation, SplitViewDividerStyle, SplitViewConfig, FileBrowserConfig, FileBrowserSelection, OutlineItem, OutlineViewConfig, TableRow, TableViewConfig, QuickLookConfig, ColorPickerConfig, FontPickerConfig, FontResult, DatePickerConfig, ProgressConfig, ToolbarItem, ToolbarConfig, TouchBarConfig, FlexStyle, LayoutStyle, SpacingStyle, BorderStyle, ColorStyle, ShadowStyle, TransformStyle, ViewStyle, TextStyleProps, TextStyle, ImageStyleProps, ImageStyle, BaseProps, ViewProps, SafeAreaViewProps, KeyboardAvoidingViewProps, TextProps, ButtonProps, LinkProps, TouchableOpacityProps, TouchableHighlightProps, ImageSource, ImageProps, ImageBackgroundProps, IconProps, VideoProps, MapRegion, MapProps, MapPolylineProps, MapMarkerProps, ScrollViewProps, PressableProps, TextInputProps, KeyboardType, ReturnKeyType, SwitchProps, CheckboxProps, SliderProps, PickerOption, PickerProps, DatePickerChange, DatePickerProps, ActivityIndicatorProps, FlatListProps, SectionListSection, SectionListProps, ModalProps, LayoutEvent, ScrollEvent, } from './components/index.js';
33
+ export type { ContextMenuItem, SidebarStyle, SidebarPosition, SidebarHeaderConfig, SidebarFooterConfig, SidebarEventType, SidebarEventMap, SidebarEventHandler, ComponentProps, ComponentInstance, SplitViewOrientation, SplitViewDividerStyle, SplitViewConfig, FileBrowserConfig, FileBrowserSelection, OutlineItem, OutlineViewConfig, TableRow, TableViewConfig, QuickLookConfig, ColorPickerConfig, FontPickerConfig, FontResult, DatePickerConfig, ProgressConfig, ToolbarItem, ToolbarConfig, TouchBarConfig, FlexStyle, LayoutStyle, SpacingStyle, BorderStyle, ColorStyle, ShadowStyle, TransformStyle, ViewStyle, TextStyleProps, TextStyle, ImageStyleProps, ImageStyle, BaseProps, ViewProps, SafeAreaViewProps, KeyboardAvoidingViewProps, StatusBarProps, RefreshControlProps, TextProps, ButtonProps, LinkProps, TouchableOpacityProps, TouchableHighlightProps, ImageSource, ImageProps, ImageBackgroundProps, SvgPaintProps, SvgProps, GProps, SvgShapeProps, PathProps, LineProps, RectProps, CircleProps, EllipseProps, PolylineProps, PolygonProps, SvgTextProps, IconProps, VideoProps, MapRegion, MapProps, MapPolylineProps, MapMarkerProps, ScrollViewProps, PressableProps, TextInputProps, KeyboardType, ReturnKeyType, SwitchProps, CheckboxProps, SliderProps, PickerOption, PickerProps, DatePickerChange, DatePickerProps, ActivityIndicatorProps, FlatListProps, SectionListSection, SectionListProps, ModalProps, LayoutEvent, ScrollEvent, } from './components/index.js';
34
34
  export * from './styles/headwind.js';
35
35
  export * from './styles/index.js';
36
36
  export * from './optimizations/index.js';
package/dist/index.js CHANGED
@@ -57,7 +57,7 @@ function craftBinaryNotFoundMessage(triedPath) {
57
57
  `);
58
58
  }
59
59
  // package.json
60
- var version = "0.0.204";
60
+ var version = "0.0.206";
61
61
 
62
62
  // src/sdk-version.ts
63
63
  var SDK_VERSION = version;
@@ -102,6 +102,17 @@ function initSimulatorDriver(options) {
102
102
  if (previous !== content)
103
103
  writeFileSync(path, content);
104
104
  }
105
+ const script = join2(output, "UITests/journey.txt");
106
+ if (options.script === undefined)
107
+ rmSync(script, { force: true });
108
+ else {
109
+ let previous;
110
+ try {
111
+ previous = readFileSync(script, "utf8");
112
+ } catch {}
113
+ if (previous !== options.script)
114
+ writeFileSync(script, options.script);
115
+ }
105
116
  }
106
117
  function serializeSimulatorSteps(steps) {
107
118
  const number = (value) => {
@@ -7,11 +7,13 @@ export interface SimulatorDriverOptions {
7
7
  deploymentTarget?: string;
8
8
  controlUrl?: string;
9
9
  tabs?: readonly string[];
10
+ /** Bundle a wire-protocol journey and save native XCTest attachments. No control server is needed on physical devices. */
11
+ script?: string;
10
12
  }
11
13
  /** Generate the reusable XCUITest shell from package templates. No app-owned Swift. */
12
14
  export declare function initSimulatorDriver(options: SimulatorDriverOptions): void;
13
15
  export type SimulatorStep = {
14
- command: 'launch' | 'activate' | 'terminate' | 'home' | 'back' | 'return' | 'unlabelled';
16
+ command: 'launch' | 'activate' | 'terminate' | 'home' | 'back' | 'return' | 'unlabelled' | 'notifications';
15
17
  } | {
16
18
  command: 'background' | 'wait';
17
19
  seconds: number;
@@ -45,14 +47,14 @@ export type SimulatorStep = {
45
47
  id: string;
46
48
  text: string;
47
49
  } | {
48
- command: 'expect' | 'expectexact' | 'expectid';
50
+ command: 'expect' | 'expectexact' | 'expectid' | 'systemexpect';
49
51
  text: string;
50
52
  seconds?: number;
51
53
  } | {
52
- command: 'tap' | 'tapif' | 'tapid' | 'tapexact' | 'type' | 'absent' | 'absentid' | 'selected' | 'tab' | 'scrollto' | 'dismiss' | 'log';
54
+ command: 'tap' | 'tapif' | 'tapid' | 'tapexact' | 'type' | 'absent' | 'absentid' | 'selected' | 'tab' | 'scrollto' | 'dismiss' | 'log' | 'systemtap' | 'systemabsent';
53
55
  text: string;
54
56
  } | {
55
- command: 'shot' | 'tree' | 'audit' | 'exec';
57
+ command: 'shot' | 'tree' | 'audit' | 'exec' | 'systemtree';
56
58
  name: string;
57
59
  } | {
58
60
  command: 'openurl';
@@ -146,8 +146,10 @@ struct CraftHybridRoutes {
146
146
  let scheme = (url.scheme ?? "").lowercased()
147
147
  guard scheme == "http" || scheme == "https",
148
148
  let host = url.host?.lowercased(), !host.isEmpty,
149
- let siteHost = site?.host?.lowercased() else { return false }
150
- return host == siteHost
149
+ let siteScheme = site?.scheme?.lowercased(), scheme == siteScheme,
150
+ let siteHost = site?.host?.lowercased(), host == siteHost,
151
+ url.port == site?.port else { return false }
152
+ return true
151
153
  }
152
154
 
153
155
  /// Where a path no native screen draws opens in an app with no web view:
@@ -979,6 +981,17 @@ final class CraftHybridWebSlot: UIViewController {
979
981
  /// ready. This belongs to the incoming slot, beyond the push animation.
980
982
  private(set) var waitingPageSnapshot: UIView?
981
983
 
984
+ /// A canceled tab swipe may leave this slot hidden after the page has
985
+ /// already reported its destination. Reconcile that route before the
986
+ /// WebView is adopted again, so the slot cannot stay transparent forever.
987
+ @discardableResult
988
+ func markArrivedIfNeeded(_ currentPath: String?) -> Bool {
989
+ guard awaitingPage, let currentPath,
990
+ CraftHybridRoutes.normalize(currentPath) == CraftHybridRoutes.normalize(path) else { return false }
991
+ awaitingPage = false
992
+ return true
993
+ }
994
+
982
995
  func keepPageVisible(_ snapshot: UIView) {
983
996
  waitingPageSnapshot?.removeFromSuperview()
984
997
  snapshot.frame = view.bounds
@@ -1392,7 +1405,7 @@ final class CraftHybridController: UIViewController, UINavigationControllerDeleg
1392
1405
 
1393
1406
  /// The entry for a path: its native screen, or a web entry.
1394
1407
  private func entry(for path: String, isTabRoot: Bool, depth: Int?, params extra: [String: Any] = [:]) -> UIViewController {
1395
- if let match = hybrid.routes.match(path) {
1408
+ if hybrid.isEnabled, let match = hybrid.routes.match(path) {
1396
1409
  var params = self.params(for: path, match)
1397
1410
  extra.forEach { params[$0.key] = $0.value }
1398
1411
  let screen = CraftNativeScreenController(config: config, routeName: match.screen, routeParams: params)
@@ -1441,6 +1454,7 @@ final class CraftHybridController: UIViewController, UINavigationControllerDeleg
1441
1454
  func adoptWeb(into slot: CraftHybridWebSlot, allowHiddenStack: Bool = false) {
1442
1455
  guard let webHost,
1443
1456
  allowHiddenStack || slot.navigationController === visibleStack || visibleStack == nil else { return }
1457
+ slot.markArrivedIfNeeded(hybrid.pagePath)
1444
1458
  attachWeb()
1445
1459
  moveWeb(to: slot, in: slot.view)
1446
1460
  webHost.view.alpha = slot.awaitingPage ? 0 : 1
@@ -158,6 +158,8 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
158
158
  private var refreshHandler: (() -> Void)?
159
159
  private let keyboardTapGesture = UITapGestureRecognizer()
160
160
  private var keyboardShouldPersistTaps = "never"
161
+ private var scrollTargetKey: String?
162
+ private var pendingScrollTarget: (id: String, animated: Bool, attempts: Int)?
161
163
 
162
164
  init() {
163
165
  let layout = CraftNativeFlatListLayout()
@@ -271,6 +273,37 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
271
273
  updateItemEstimate()
272
274
  super.layoutSubviews()
273
275
  craftApplyCornerRadius()
276
+ scrollToPendingTarget()
277
+ }
278
+
279
+ /// Scroll to a virtualized row identified by its native testID, id, or key.
280
+ /// The row need not be mounted yet; the data snapshot is enough to find its
281
+ /// index, and UIKit will mount it as part of the scroll.
282
+ func setScrollTarget(_ value: Any?) {
283
+ var id: String?
284
+ var animated = true
285
+ if let text = value as? String {
286
+ id = text
287
+ } else if let target = value as? [String: Any] {
288
+ id = target["id"] as? String
289
+ animated = target["animated"] as? Bool ?? true
290
+ }
291
+ guard let id, !id.isEmpty else {
292
+ scrollTargetKey = nil
293
+ pendingScrollTarget = nil
294
+ return
295
+ }
296
+ let key: String
297
+ if let target = value as? [String: Any],
298
+ let data = try? JSONSerialization.data(withJSONObject: target, options: [.sortedKeys]) {
299
+ key = String(decoding: data, as: UTF8.self)
300
+ } else {
301
+ key = id
302
+ }
303
+ guard key != scrollTargetKey else { return }
304
+ scrollTargetKey = key
305
+ pendingScrollTarget = (id, animated, 0)
306
+ scrollToPendingTarget()
274
307
  }
275
308
 
276
309
  func setContentContainerStyle(_ raw: [String: Any]?) {
@@ -315,6 +348,10 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
315
348
  }
316
349
  }
317
350
 
351
+ func setRefreshAppearance(_ props: [String: Any]) {
352
+ nativeRefreshControl.tintColor = (props["tintColor"] as? String).flatMap { UIColor(hex: $0) }
353
+ }
354
+
318
355
  @objc private func refreshTriggered() {
319
356
  refreshHandler?()
320
357
  DispatchQueue.main.async { [weak self] in
@@ -473,6 +510,8 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
473
510
  onMomentumScrollBegin = nil
474
511
  onMomentumScrollEnd = nil
475
512
  pendingThemeRefresh = false
513
+ scrollTargetKey = nil
514
+ pendingScrollTarget = nil
476
515
  }
477
516
 
478
517
  func refreshThemeDefaults() {
@@ -543,10 +582,39 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
543
582
  self.refreshThemeDefaults()
544
583
  return
545
584
  }
585
+ self.scrollToPendingTarget()
546
586
  self.evaluateEndReached()
547
587
  }
548
588
  }
549
589
 
590
+ private func targetIndex(for id: String) -> Int? {
591
+ items.firstIndex { item in
592
+ let props = item.node["props"] as? [String: Any] ?? [:]
593
+ return [props["testID"], props["id"], item.node["id"], item.identity]
594
+ .compactMap { $0 as? String }
595
+ .contains(id)
596
+ }
597
+ }
598
+
599
+ private func scrollToPendingTarget() {
600
+ guard let target = pendingScrollTarget else { return }
601
+ guard let index = targetIndex(for: target.id), index < numberOfItems(inSection: 0) else {
602
+ if target.attempts >= 4 {
603
+ // A diffable snapshot may still be applying. Keep the target
604
+ // for finishApplyingSnapshot(), but discard an invalid target
605
+ // once the list is otherwise idle.
606
+ if !isApplyingSnapshot { pendingScrollTarget = nil }
607
+ return
608
+ }
609
+ pendingScrollTarget = (target.id, target.animated, target.attempts + 1)
610
+ DispatchQueue.main.async { [weak self] in self?.scrollToPendingTarget() }
611
+ return
612
+ }
613
+ pendingScrollTarget = nil
614
+ let position: UICollectionView.ScrollPosition = flowLayout.scrollDirection == .horizontal ? .left : .top
615
+ scrollToItem(at: IndexPath(item: index, section: 0), at: position, animated: target.animated)
616
+ }
617
+
550
618
  private func clamped(_ offset: CGPoint) -> CGPoint {
551
619
  CGPoint(
552
620
  x: min(max(-adjustedContentInset.left, offset.x), max(-adjustedContentInset.left, contentSize.width - bounds.width + adjustedContentInset.right)),