@symbiote-native/svelte 0.1.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 (219) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +161 -0
  3. package/build/bootstrap.d.ts +7 -0
  4. package/build/bootstrap.js +17 -0
  5. package/build/class-value.d.ts +6 -0
  6. package/build/class-value.js +81 -0
  7. package/build/components/RefreshControl.svelte +38 -0
  8. package/build/components/RefreshControl.svelte.d.ts +5 -0
  9. package/build/components/SafeAreaView.svelte +34 -0
  10. package/build/components/SafeAreaView.svelte.d.ts +5 -0
  11. package/build/components/Text.svelte +25 -0
  12. package/build/components/Text.svelte.d.ts +5 -0
  13. package/build/components/View.svelte +41 -0
  14. package/build/components/View.svelte.d.ts +5 -0
  15. package/build/components/activity-indicator/activity-indicator-platform.android.d.ts +3 -0
  16. package/build/components/activity-indicator/activity-indicator-platform.android.js +5 -0
  17. package/build/components/activity-indicator/activity-indicator-platform.d.ts +1 -0
  18. package/build/components/activity-indicator/activity-indicator-platform.ios.d.ts +3 -0
  19. package/build/components/activity-indicator/activity-indicator-platform.ios.js +6 -0
  20. package/build/components/activity-indicator/activity-indicator-platform.js +5 -0
  21. package/build/components/activity-indicator/activity-indicator-props.d.ts +5 -0
  22. package/build/components/activity-indicator/activity-indicator-props.js +1 -0
  23. package/build/components/activity-indicator/index.svelte +57 -0
  24. package/build/components/activity-indicator/index.svelte.d.ts +5 -0
  25. package/build/components/button-props.d.ts +5 -0
  26. package/build/components/button-props.js +1 -0
  27. package/build/components/button.svelte +71 -0
  28. package/build/components/button.svelte.d.ts +5 -0
  29. package/build/components/flat-list/flat-list-props.d.ts +10 -0
  30. package/build/components/flat-list/flat-list-props.js +1 -0
  31. package/build/components/flat-list/index.svelte +254 -0
  32. package/build/components/flat-list/index.svelte.d.ts +79 -0
  33. package/build/components/image/image-logic.d.ts +2 -0
  34. package/build/components/image/image-logic.js +125 -0
  35. package/build/components/image/image-props.d.ts +5 -0
  36. package/build/components/image/image-props.js +1 -0
  37. package/build/components/image/index.d.ts +3 -0
  38. package/build/components/image/index.js +10 -0
  39. package/build/components/image/index.svelte +66 -0
  40. package/build/components/image/index.svelte.d.ts +5 -0
  41. package/build/components/image-background/image-background-props.d.ts +10 -0
  42. package/build/components/image-background/image-background-props.js +1 -0
  43. package/build/components/image-background/index.svelte +81 -0
  44. package/build/components/image-background/index.svelte.d.ts +5 -0
  45. package/build/components/index.d.ts +50 -0
  46. package/build/components/index.js +24 -0
  47. package/build/components/input-accessory-view/index.svelte +48 -0
  48. package/build/components/input-accessory-view/index.svelte.d.ts +5 -0
  49. package/build/components/input-accessory-view/input-accessory-view-props.d.ts +11 -0
  50. package/build/components/input-accessory-view/input-accessory-view-props.js +1 -0
  51. package/build/components/keyboard-avoiding-view/index.svelte +135 -0
  52. package/build/components/keyboard-avoiding-view/index.svelte.d.ts +5 -0
  53. package/build/components/keyboard-avoiding-view/keyboard-avoiding-view-props.d.ts +15 -0
  54. package/build/components/keyboard-avoiding-view/keyboard-avoiding-view-props.js +1 -0
  55. package/build/components/modal/index.svelte +126 -0
  56. package/build/components/modal/index.svelte.d.ts +5 -0
  57. package/build/components/modal/modal-props.d.ts +24 -0
  58. package/build/components/modal/modal-props.js +1 -0
  59. package/build/components/pressable/index.svelte +160 -0
  60. package/build/components/pressable/index.svelte.d.ts +5 -0
  61. package/build/components/pressable/pressable-props.d.ts +27 -0
  62. package/build/components/pressable/pressable-props.js +1 -0
  63. package/build/components/refresh-control-props.d.ts +19 -0
  64. package/build/components/refresh-control-props.js +1 -0
  65. package/build/components/safe-area-view-props.d.ts +10 -0
  66. package/build/components/safe-area-view-props.js +1 -0
  67. package/build/components/scroll-view/index.svelte +298 -0
  68. package/build/components/scroll-view/index.svelte.d.ts +18 -0
  69. package/build/components/scroll-view/scroll-view-platform-types.d.ts +3 -0
  70. package/build/components/scroll-view/scroll-view-platform-types.js +1 -0
  71. package/build/components/scroll-view/scroll-view-platform.android.d.ts +3 -0
  72. package/build/components/scroll-view/scroll-view-platform.android.js +3 -0
  73. package/build/components/scroll-view/scroll-view-platform.d.ts +1 -0
  74. package/build/components/scroll-view/scroll-view-platform.ios.d.ts +3 -0
  75. package/build/components/scroll-view/scroll-view-platform.ios.js +3 -0
  76. package/build/components/scroll-view/scroll-view-platform.js +4 -0
  77. package/build/components/scroll-view/scroll-view-props.d.ts +78 -0
  78. package/build/components/scroll-view/scroll-view-props.js +1 -0
  79. package/build/components/scroll-view/scroll-view-sticky-context.d.ts +7 -0
  80. package/build/components/scroll-view/scroll-view-sticky-context.js +1 -0
  81. package/build/components/scroll-view/sticky-header-props.d.ts +10 -0
  82. package/build/components/scroll-view/sticky-header-props.js +1 -0
  83. package/build/components/scroll-view/sticky-header.svelte +254 -0
  84. package/build/components/scroll-view/sticky-header.svelte.d.ts +5 -0
  85. package/build/components/section-list/index.svelte +107 -0
  86. package/build/components/section-list/index.svelte.d.ts +57 -0
  87. package/build/components/section-list/section-list-props.d.ts +1 -0
  88. package/build/components/section-list/section-list-props.js +1 -0
  89. package/build/components/switch/index.svelte +123 -0
  90. package/build/components/switch/index.svelte.d.ts +5 -0
  91. package/build/components/switch/switch-platform-types.d.ts +5 -0
  92. package/build/components/switch/switch-platform-types.js +1 -0
  93. package/build/components/switch/switch-platform.android.d.ts +3 -0
  94. package/build/components/switch/switch-platform.android.js +8 -0
  95. package/build/components/switch/switch-platform.d.ts +1 -0
  96. package/build/components/switch/switch-platform.ios.d.ts +3 -0
  97. package/build/components/switch/switch-platform.ios.js +7 -0
  98. package/build/components/switch/switch-platform.js +5 -0
  99. package/build/components/switch/switch-props.d.ts +5 -0
  100. package/build/components/switch/switch-props.js +1 -0
  101. package/build/components/text-input/index.svelte +300 -0
  102. package/build/components/text-input/index.svelte.d.ts +12 -0
  103. package/build/components/text-input/text-input-props.d.ts +5 -0
  104. package/build/components/text-input/text-input-props.js +1 -0
  105. package/build/components/text-props.d.ts +23 -0
  106. package/build/components/text-props.js +1 -0
  107. package/build/components/touchable-base-props.d.ts +10 -0
  108. package/build/components/touchable-base-props.js +1 -0
  109. package/build/components/touchable-highlight/index.svelte +39 -0
  110. package/build/components/touchable-highlight/index.svelte.d.ts +5 -0
  111. package/build/components/touchable-highlight/touchable-highlight-props.d.ts +5 -0
  112. package/build/components/touchable-highlight/touchable-highlight-props.js +1 -0
  113. package/build/components/touchable-native-feedback/index.d.ts +9 -0
  114. package/build/components/touchable-native-feedback/index.js +14 -0
  115. package/build/components/touchable-native-feedback/touchable-native-feedback-props.d.ts +8 -0
  116. package/build/components/touchable-native-feedback/touchable-native-feedback-props.js +1 -0
  117. package/build/components/touchable-native-feedback/touchable-native-feedback.svelte +44 -0
  118. package/build/components/touchable-native-feedback/touchable-native-feedback.svelte.d.ts +5 -0
  119. package/build/components/touchable-opacity/index.svelte +124 -0
  120. package/build/components/touchable-opacity/index.svelte.d.ts +5 -0
  121. package/build/components/touchable-opacity/touchable-opacity-props.d.ts +5 -0
  122. package/build/components/touchable-opacity/touchable-opacity-props.js +1 -0
  123. package/build/components/touchable-without-feedback/index.svelte +19 -0
  124. package/build/components/touchable-without-feedback/index.svelte.d.ts +5 -0
  125. package/build/components/touchable-without-feedback/touchable-without-feedback-props.d.ts +2 -0
  126. package/build/components/touchable-without-feedback/touchable-without-feedback-props.js +1 -0
  127. package/build/components/view-props.d.ts +29 -0
  128. package/build/components/view-props.js +1 -0
  129. package/build/components/virtualized-list/index.svelte +702 -0
  130. package/build/components/virtualized-list/index.svelte.d.ts +79 -0
  131. package/build/components/virtualized-list/virtualized-list-props.d.ts +70 -0
  132. package/build/components/virtualized-list/virtualized-list-props.js +73 -0
  133. package/build/components/virtualized-section-list/index.svelte +206 -0
  134. package/build/components/virtualized-section-list/index.svelte.d.ts +57 -0
  135. package/build/components/virtualized-section-list/virtualized-section-list-props.d.ts +62 -0
  136. package/build/components/virtualized-section-list/virtualized-section-list-props.js +1 -0
  137. package/build/create-tunnel/index.d.ts +3 -0
  138. package/build/create-tunnel/index.js +3 -0
  139. package/build/create-tunnel/tunnel-in.svelte +24 -0
  140. package/build/create-tunnel/tunnel-in.svelte.d.ts +9 -0
  141. package/build/create-tunnel/tunnel-out.svelte +14 -0
  142. package/build/create-tunnel/tunnel-out.svelte.d.ts +7 -0
  143. package/build/create-tunnel/tunnel.d.ts +9 -0
  144. package/build/create-tunnel/tunnel.js +9 -0
  145. package/build/descriptor-to-svelte.d.ts +7 -0
  146. package/build/descriptor-to-svelte.js +104 -0
  147. package/build/dom-shim/comment.d.ts +9 -0
  148. package/build/dom-shim/comment.js +24 -0
  149. package/build/dom-shim/document-fragment.d.ts +8 -0
  150. package/build/dom-shim/document-fragment.js +23 -0
  151. package/build/dom-shim/document.d.ts +23 -0
  152. package/build/dom-shim/document.js +61 -0
  153. package/build/dom-shim/element.d.ts +22 -0
  154. package/build/dom-shim/element.js +130 -0
  155. package/build/dom-shim/index.d.ts +5 -0
  156. package/build/dom-shim/index.js +7 -0
  157. package/build/dom-shim/patch-globals.d.ts +2 -0
  158. package/build/dom-shim/patch-globals.js +94 -0
  159. package/build/dom-shim/shim-node.d.ts +30 -0
  160. package/build/dom-shim/shim-node.js +207 -0
  161. package/build/dom-shim/text.d.ts +14 -0
  162. package/build/dom-shim/text.js +97 -0
  163. package/build/host-instance.d.ts +5 -0
  164. package/build/host-instance.js +48 -0
  165. package/build/index.d.ts +28 -0
  166. package/build/index.js +77 -0
  167. package/build/modules/accessibility-info/index.android.d.ts +2 -0
  168. package/build/modules/accessibility-info/index.android.js +4 -0
  169. package/build/modules/accessibility-info/index.d.ts +1 -0
  170. package/build/modules/accessibility-info/index.ios.d.ts +2 -0
  171. package/build/modules/accessibility-info/index.ios.js +3 -0
  172. package/build/modules/accessibility-info/index.js +5 -0
  173. package/build/modules/animated/AnimatedImage.svelte +115 -0
  174. package/build/modules/animated/AnimatedImage.svelte.d.ts +5 -0
  175. package/build/modules/animated/AnimatedScrollView.svelte +92 -0
  176. package/build/modules/animated/AnimatedScrollView.svelte.d.ts +17 -0
  177. package/build/modules/animated/AnimatedText.svelte +58 -0
  178. package/build/modules/animated/AnimatedText.svelte.d.ts +5 -0
  179. package/build/modules/animated/AnimatedView.svelte +95 -0
  180. package/build/modules/animated/AnimatedView.svelte.d.ts +5 -0
  181. package/build/modules/animated/animated-component-props.d.ts +7 -0
  182. package/build/modules/animated/animated-component-props.js +1 -0
  183. package/build/modules/animated/index.d.ts +58 -0
  184. package/build/modules/animated/index.js +69 -0
  185. package/build/modules/app-registry/index.d.ts +7 -0
  186. package/build/modules/app-registry/index.js +28 -0
  187. package/build/modules/status-bar/index.d.ts +5 -0
  188. package/build/modules/status-bar/index.js +21 -0
  189. package/build/modules/status-bar/index.svelte +20 -0
  190. package/build/modules/status-bar/index.svelte.d.ts +4 -0
  191. package/build/native-view-bridge.d.ts +4 -0
  192. package/build/native-view-bridge.js +27 -0
  193. package/build/preprocessor/forbid-web-only-constructs.d.ts +8 -0
  194. package/build/preprocessor/forbid-web-only-constructs.js +204 -0
  195. package/build/preprocessor/scoped-styles.d.ts +10 -0
  196. package/build/preprocessor/scoped-styles.js +399 -0
  197. package/build/render.d.ts +7 -0
  198. package/build/render.js +46 -0
  199. package/build/root-element.d.ts +3 -0
  200. package/build/root-element.js +27 -0
  201. package/build/runes/attachments.d.ts +5 -0
  202. package/build/runes/attachments.js +73 -0
  203. package/build/runes/dimensions-value.d.ts +4 -0
  204. package/build/runes/dimensions-value.js +30 -0
  205. package/build/runes/media-query.d.ts +8 -0
  206. package/build/runes/media-query.js +38 -0
  207. package/build/runes/use-color-scheme.svelte.d.ts +4 -0
  208. package/build/runes/use-color-scheme.svelte.js +25 -0
  209. package/build/runes/use-window-dimensions.svelte.d.ts +4 -0
  210. package/build/runes/use-window-dimensions.svelte.js +43 -0
  211. package/build/runes/window.d.ts +6 -0
  212. package/build/runes/window.js +28 -0
  213. package/build/scope-token.d.ts +2 -0
  214. package/build/scope-token.js +33 -0
  215. package/build/style-scope.d.ts +1 -0
  216. package/build/style-scope.js +29 -0
  217. package/metro-css-parser.cjs +9 -0
  218. package/metro-svelte-transformer.cjs +156 -0
  219. package/package.json +83 -0
@@ -0,0 +1,71 @@
1
+ <script lang="ts" module>
2
+ // Button: the minimal cross-platform button, rendered in RN's iOS shape (Button.js): a
3
+ // TouchableOpacity wrapping a Text. The base text style, the role constant, and the color fold
4
+ // (caller color tints the label; disabled greys it) are shared in
5
+ // @symbiote-native/components/view/render-button — this component only composes its
6
+ // TouchableOpacity + a raw `symbiote-text` host and forwards the native-only props, the Svelte
7
+ // twin of React's/Vue's Button.
8
+ import type { IButtonProps } from './button-props';
9
+
10
+ export type { IButtonProps };
11
+ </script>
12
+
13
+ <script lang="ts">
14
+ import { BUTTON_ACCESSIBILITY_ROLE, resolveButtonTextStyle } from '@symbiote-native/components';
15
+ import TouchableOpacity from './touchable-opacity/index.svelte';
16
+
17
+ let {
18
+ title,
19
+ onPress,
20
+ color,
21
+ disabled,
22
+ touchSoundDisabled,
23
+ testID,
24
+ hasTVPreferredFocus,
25
+ nextFocusDown,
26
+ nextFocusForward,
27
+ nextFocusLeft,
28
+ nextFocusRight,
29
+ nextFocusUp,
30
+ class: className,
31
+ ...accessibilityRest
32
+ }: IButtonProps = $props();
33
+
34
+ const textStyle = $derived(resolveButtonTextStyle(color, disabled));
35
+
36
+ // The native-only props TouchableOpacity does not type but forwards to Fabric (testID +
37
+ // TV-focus). Carried as a plain record (the pass-through idiom Image/React's Button use) so
38
+ // excess-property typing does not reject the native-only keys. TV-focus is inert on a phone.
39
+ const nativeForward = $derived.by(() => {
40
+ const forward: Record<string, unknown> = { testID };
41
+ if (hasTVPreferredFocus !== undefined) forward.hasTVPreferredFocus = hasTVPreferredFocus;
42
+ if (nextFocusDown !== undefined) forward.nextFocusDown = nextFocusDown;
43
+ if (nextFocusForward !== undefined) forward.nextFocusForward = nextFocusForward;
44
+ if (nextFocusLeft !== undefined) forward.nextFocusLeft = nextFocusLeft;
45
+ if (nextFocusRight !== undefined) forward.nextFocusRight = nextFocusRight;
46
+ if (nextFocusUp !== undefined) forward.nextFocusUp = nextFocusUp;
47
+ return forward;
48
+ });
49
+ </script>
50
+
51
+ <!--
52
+ RN's Button sets role=button, is accessible, and propagates the disabled accessibility state.
53
+ The caller's accessibility props pass through via {...accessibilityRest}, but Button's fixed
54
+ role/accessible/disabled-state win, applied after the spread. touchSoundDisabled maps to the
55
+ pressable's android_disableSound.
56
+ -->
57
+ <TouchableOpacity
58
+ {...accessibilityRest}
59
+ {...nativeForward}
60
+ {onPress}
61
+ {disabled}
62
+ class={className}
63
+ android_disableSound={touchSoundDisabled}
64
+ accessibilityRole={BUTTON_ACCESSIBILITY_ROLE}
65
+ accessible={true}
66
+ accessibilityState={{ disabled }}
67
+ >
68
+ {#snippet children()}
69
+ <symbiote-text p={{ style: textStyle }}>{title}</symbiote-text>
70
+ {/snippet}
71
+ </TouchableOpacity>
@@ -0,0 +1,5 @@
1
+ import type { IButtonProps } from './button-props';
2
+ export type { IButtonProps };
3
+ declare const Button: import("svelte").Component<IButtonProps, {}, "">;
4
+ type Button = ReturnType<typeof Button>;
5
+ export default Button;
@@ -0,0 +1,10 @@
1
+ import type { IStyleProp, IViewStyle } from '@symbiote-native/engine';
2
+ import type { IViewabilityConfigCallbackPair } from '@symbiote-native/components';
3
+ import type { IVirtualizedListHandle, IVirtualizedListProps } from '../virtualized-list/virtualized-list-props';
4
+ export type { IVirtualizedListHandle as IFlatListHandle };
5
+ export type IFlatListProps<ItemT> = Omit<IVirtualizedListProps<ItemT>, 'data' | 'getItem' | 'getItemCount' | 'viewabilityConfigCallbackPairs'> & {
6
+ data: readonly ItemT[];
7
+ numColumns?: number;
8
+ columnWrapperStyle?: IStyleProp<IViewStyle> | string;
9
+ viewabilityConfigCallbackPairs?: IViewabilityConfigCallbackPair<ItemT>[];
10
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,254 @@
1
+ <script lang="ts" module>
2
+ // FlatList: the convenience surface over VirtualizedList. Takes a plain `data` array and
3
+ // derives getItem/getItemCount; numColumns packs items into rows (a horizontal sub-View), so
4
+ // the virtualized stream is rows, not items (RN's FlatList). All windowing / viewability /
5
+ // batching / imperative scrolling are inherited from VirtualizedList; the data-shaping and the
6
+ // row/viewability/separator transforms are shared verbatim from @symbiote-native/components,
7
+ // exactly like the React/Vue FlatList over their own VirtualizedList.
8
+ import type { IFlatListProps, IFlatListHandle } from './flat-list-props';
9
+
10
+ export type { IFlatListProps, IFlatListHandle };
11
+ </script>
12
+
13
+ <script lang="ts" generics="ItemT">
14
+ import {
15
+ SINGLE_COLUMN,
16
+ chunkIntoRows,
17
+ expandRowViewability,
18
+ firstItemOfRow,
19
+ lastItemOfRow,
20
+ rowKeyExtractor,
21
+ type IRow,
22
+ type ISeparatorProps,
23
+ type ISeparators,
24
+ type IViewableItemsChangedInfo,
25
+ } from '@symbiote-native/components';
26
+ import { resolveClassName, type ISymbioteNode } from '@symbiote-native/engine';
27
+ import VirtualizedList from '../virtualized-list/index.svelte';
28
+ import { pickAccessibilityProps } from '../virtualized-list/virtualized-list-props';
29
+ import type { IVirtualizedListHandle, IScrollViewHandle } from '../virtualized-list/virtualized-list-props';
30
+ import type { IFlatListProps as IProps } from './flat-list-props';
31
+ import { pickAttachmentProps } from '../../runes/attachments';
32
+
33
+ let props: IProps<ItemT> = $props();
34
+
35
+ // $state.raw: the inner VirtualizedList component instance (its exports), held by identity —
36
+ // same concern as every other handle in this adapter (Switch's hostShim, VirtualizedList's own
37
+ // scrollHandle over its ShimElement).
38
+ let inner = $state.raw<IVirtualizedListHandle | null>(null);
39
+
40
+ const numColumns = $derived(typeof props.numColumns === 'number' ? props.numColumns : SINGLE_COLUMN);
41
+ const rows = $derived.by((): IRow<ItemT>[] =>
42
+ numColumns > SINGLE_COLUMN ? chunkIntoRows(props.data, numColumns) : [],
43
+ );
44
+
45
+ function getSingleItem(_source: unknown, index: number): ItemT {
46
+ return props.data[index];
47
+ }
48
+ function getSingleCount(): number {
49
+ return props.data.length;
50
+ }
51
+ function getRow(_source: unknown, index: number): IRow<ItemT> {
52
+ return rows[index];
53
+ }
54
+ function getRowCount(): number {
55
+ return rows.length;
56
+ }
57
+
58
+ function isStyleLike(value: unknown): boolean {
59
+ return Array.isArray(value) || (typeof value === 'object' && value !== null);
60
+ }
61
+
62
+ const rowStyle = $derived.by(() => [
63
+ { flexDirection: 'row' as const },
64
+ typeof props.columnWrapperStyle === 'string'
65
+ ? resolveClassName(props.columnWrapperStyle)
66
+ : isStyleLike(props.columnWrapperStyle)
67
+ ? props.columnWrapperStyle
68
+ : undefined,
69
+ ]);
70
+
71
+ // The divider between rows shows real items (last of the row above, first of the row below), so
72
+ // the user's `separator` snippet, typed on ItemT, sees items rather than the IRow wrapper.
73
+ function rowSeparatorProps(entryProps: ISeparatorProps<IRow<ItemT>>): ISeparatorProps<ItemT> {
74
+ return {
75
+ ...entryProps,
76
+ leadingItem: lastItemOfRow(entryProps.leadingItem),
77
+ trailingItem: firstItemOfRow(entryProps.trailingItem),
78
+ };
79
+ }
80
+
81
+ const rowOnViewableItemsChanged = $derived.by(() => {
82
+ const onChanged = props.onViewableItemsChanged;
83
+ if (onChanged === undefined) return undefined;
84
+ return (rowInfo: IViewableItemsChangedInfo<IRow<ItemT>>): void =>
85
+ onChanged(expandRowViewability(rowInfo, props.keyExtractor));
86
+ });
87
+ const rowViewabilityPairs = $derived(
88
+ props.viewabilityConfigCallbackPairs?.map(pair => ({
89
+ viewabilityConfig: pair.viewabilityConfig,
90
+ onViewableItemsChanged: (rowInfo: IViewableItemsChangedInfo<IRow<ItemT>>): void => {
91
+ pair.onViewableItemsChanged(expandRowViewability(rowInfo, props.keyExtractor));
92
+ },
93
+ })),
94
+ );
95
+
96
+ // Forwarded onto the inner VirtualizedList as a component-prop spread (not a raw attribute
97
+ // spread on a symbiote-* host tag — that stays banned, svelte-adapter-dom-shim skill §3g(c) —
98
+ // this lands on another compiled Svelte COMPONENT, an ordinary prop merge). Picked field-by-
99
+ // field by pickAccessibilityProps, same helper VirtualizedList's own host bag uses.
100
+ const accessibilityProps = $derived(pickAccessibilityProps(props));
101
+
102
+ // ---- imperative handle: delegate straight through to the inner VirtualizedList instance. ----
103
+ export function scrollToOffset(params: { offset: number; animated?: boolean }): void {
104
+ inner?.scrollToOffset(params);
105
+ }
106
+ export function scrollToIndex(params: {
107
+ index: number;
108
+ animated?: boolean;
109
+ viewOffset?: number;
110
+ viewPosition?: number;
111
+ }): void {
112
+ inner?.scrollToIndex(params);
113
+ }
114
+ export function scrollToItem(params: { item: unknown; animated?: boolean; viewPosition?: number }): void {
115
+ inner?.scrollToItem(params);
116
+ }
117
+ export function scrollToEnd(params?: { animated?: boolean }): void {
118
+ inner?.scrollToEnd(params);
119
+ }
120
+ export function flashScrollIndicators(): void {
121
+ inner?.flashScrollIndicators();
122
+ }
123
+ export function getNativeScrollRef(): IScrollViewHandle | null {
124
+ return inner?.getNativeScrollRef() ?? null;
125
+ }
126
+ export function getScrollableNode(): IScrollViewHandle | null {
127
+ return inner?.getScrollableNode() ?? null;
128
+ }
129
+ export function getScrollResponder(): IScrollViewHandle | null {
130
+ return inner?.getScrollResponder() ?? null;
131
+ }
132
+ export function getScrollNode(): ISymbioteNode | null {
133
+ return inner?.getScrollNode() ?? null;
134
+ }
135
+ export function recordInteraction(): void {
136
+ inner?.recordInteraction();
137
+ }
138
+
139
+ // `{@attach}` arrives as a symbol-keyed prop, which naming individual props below drops.
140
+ // Re-spread just those onto the inner list, which owns the real host node.
141
+ const attachments = $derived(pickAttachmentProps(props));
142
+ </script>
143
+
144
+ {#snippet rowItem({ item: row, index, separators }: { item: IRow<ItemT>; index: number; separators: ISeparators })}
145
+ <symbiote-view p={{ style: rowStyle }}>
146
+ {#each row.items as rowItem, column (props.keyExtractor ? props.keyExtractor(rowItem, row.startIndex + column) : String(row.startIndex + column))}
147
+ <symbiote-view p={{ style: { flex: 1 } }}>
148
+ {@render props.item({ item: rowItem, index: row.startIndex + column, separators })}
149
+ </symbiote-view>
150
+ {/each}
151
+ </symbiote-view>
152
+ {/snippet}
153
+
154
+ {#snippet rowSeparator(entryProps: ISeparatorProps<IRow<ItemT>>)}
155
+ {@render props.separator?.(rowSeparatorProps(entryProps))}
156
+ {/snippet}
157
+
158
+ {#if numColumns <= SINGLE_COLUMN}
159
+ <VirtualizedList
160
+ bind:this={inner}
161
+ {...accessibilityProps}
162
+ {...attachments}
163
+ data={props.data}
164
+ getItem={getSingleItem}
165
+ getItemCount={getSingleCount}
166
+ item={props.item}
167
+ separator={props.separator}
168
+ header={props.header}
169
+ footer={props.footer}
170
+ empty={props.empty}
171
+ keyExtractor={props.keyExtractor}
172
+ getItemLayout={props.getItemLayout}
173
+ horizontal={props.horizontal}
174
+ inverted={props.inverted}
175
+ extraData={props.extraData}
176
+ onEndReached={props.onEndReached}
177
+ onEndReachedThreshold={props.onEndReachedThreshold}
178
+ onStartReached={props.onStartReached}
179
+ onStartReachedThreshold={props.onStartReachedThreshold}
180
+ onRefresh={props.onRefresh}
181
+ refreshing={props.refreshing}
182
+ progressViewOffset={props.progressViewOffset}
183
+ onViewableItemsChanged={props.onViewableItemsChanged}
184
+ viewabilityConfig={props.viewabilityConfig}
185
+ viewabilityConfigCallbackPairs={props.viewabilityConfigCallbackPairs}
186
+ onScrollToIndexFailed={props.onScrollToIndexFailed}
187
+ initialNumToRender={props.initialNumToRender}
188
+ initialScrollIndex={props.initialScrollIndex}
189
+ maxToRenderPerBatch={props.maxToRenderPerBatch}
190
+ updateCellsBatchingPeriod={props.updateCellsBatchingPeriod}
191
+ windowSize={props.windowSize}
192
+ stickyHeaderIndices={props.stickyHeaderIndices}
193
+ maintainVisibleContentPosition={props.maintainVisibleContentPosition}
194
+ onScroll={props.onScroll}
195
+ onScrollBeginDrag={props.onScrollBeginDrag}
196
+ onScrollEndDrag={props.onScrollEndDrag}
197
+ onMomentumScrollBegin={props.onMomentumScrollBegin}
198
+ onMomentumScrollEnd={props.onMomentumScrollEnd}
199
+ scrollEventThrottle={props.scrollEventThrottle}
200
+ keyboardShouldPersistTaps={props.keyboardShouldPersistTaps}
201
+ keyboardDismissMode={props.keyboardDismissMode}
202
+ style={props.style}
203
+ contentContainerStyle={props.contentContainerStyle}
204
+ class={props.class}
205
+ />
206
+ {:else}
207
+ <VirtualizedList
208
+ bind:this={inner}
209
+ {...accessibilityProps}
210
+ {...attachments}
211
+ data={rows}
212
+ getItem={getRow}
213
+ getItemCount={getRowCount}
214
+ item={rowItem}
215
+ separator={props.separator ? rowSeparator : undefined}
216
+ header={props.header}
217
+ footer={props.footer}
218
+ empty={props.empty}
219
+ keyExtractor={rowKeyExtractor}
220
+ getItemLayout={props.getItemLayout}
221
+ horizontal={props.horizontal}
222
+ inverted={props.inverted}
223
+ extraData={props.extraData}
224
+ onEndReached={props.onEndReached}
225
+ onEndReachedThreshold={props.onEndReachedThreshold}
226
+ onStartReached={props.onStartReached}
227
+ onStartReachedThreshold={props.onStartReachedThreshold}
228
+ onRefresh={props.onRefresh}
229
+ refreshing={props.refreshing}
230
+ progressViewOffset={props.progressViewOffset}
231
+ onViewableItemsChanged={rowOnViewableItemsChanged}
232
+ viewabilityConfig={props.viewabilityConfig}
233
+ viewabilityConfigCallbackPairs={rowViewabilityPairs}
234
+ onScrollToIndexFailed={props.onScrollToIndexFailed}
235
+ initialNumToRender={props.initialNumToRender}
236
+ initialScrollIndex={props.initialScrollIndex}
237
+ maxToRenderPerBatch={props.maxToRenderPerBatch}
238
+ updateCellsBatchingPeriod={props.updateCellsBatchingPeriod}
239
+ windowSize={props.windowSize}
240
+ stickyHeaderIndices={props.stickyHeaderIndices}
241
+ maintainVisibleContentPosition={props.maintainVisibleContentPosition}
242
+ onScroll={props.onScroll}
243
+ onScrollBeginDrag={props.onScrollBeginDrag}
244
+ onScrollEndDrag={props.onScrollEndDrag}
245
+ onMomentumScrollBegin={props.onMomentumScrollBegin}
246
+ onMomentumScrollEnd={props.onMomentumScrollEnd}
247
+ scrollEventThrottle={props.scrollEventThrottle}
248
+ keyboardShouldPersistTaps={props.keyboardShouldPersistTaps}
249
+ keyboardDismissMode={props.keyboardDismissMode}
250
+ style={props.style}
251
+ contentContainerStyle={props.contentContainerStyle}
252
+ class={props.class}
253
+ />
254
+ {/if}
@@ -0,0 +1,79 @@
1
+ import type { IFlatListProps, IFlatListHandle } from './flat-list-props';
2
+ export type { IFlatListProps, IFlatListHandle };
3
+ import { type ISymbioteNode } from '@symbiote-native/engine';
4
+ import type { IScrollViewHandle } from '../virtualized-list/virtualized-list-props';
5
+ import type { IFlatListProps as IProps } from './flat-list-props';
6
+ declare function $$render<ItemT>(): {
7
+ props: IProps<ItemT>;
8
+ exports: {
9
+ scrollToOffset: (params: {
10
+ offset: number;
11
+ animated?: boolean;
12
+ }) => void;
13
+ scrollToIndex: (params: {
14
+ index: number;
15
+ animated?: boolean;
16
+ viewOffset?: number;
17
+ viewPosition?: number;
18
+ }) => void;
19
+ scrollToItem: (params: {
20
+ item: unknown;
21
+ animated?: boolean;
22
+ viewPosition?: number;
23
+ }) => void;
24
+ scrollToEnd: (params?: {
25
+ animated?: boolean;
26
+ }) => void;
27
+ flashScrollIndicators: () => void;
28
+ getNativeScrollRef: () => IScrollViewHandle | null;
29
+ getScrollableNode: () => IScrollViewHandle | null;
30
+ getScrollResponder: () => IScrollViewHandle | null;
31
+ getScrollNode: () => ISymbioteNode | null;
32
+ recordInteraction: () => void;
33
+ };
34
+ bindings: "";
35
+ slots: {};
36
+ events: {};
37
+ };
38
+ declare class __sveltets_Render<ItemT> {
39
+ props(): ReturnType<typeof $$render<ItemT>>['props'];
40
+ events(): ReturnType<typeof $$render<ItemT>>['events'];
41
+ slots(): ReturnType<typeof $$render<ItemT>>['slots'];
42
+ bindings(): "";
43
+ exports(): {
44
+ scrollToOffset: (params: {
45
+ offset: number;
46
+ animated?: boolean;
47
+ }) => void;
48
+ scrollToIndex: (params: {
49
+ index: number;
50
+ animated?: boolean;
51
+ viewOffset?: number;
52
+ viewPosition?: number;
53
+ }) => void;
54
+ scrollToItem: (params: {
55
+ item: unknown;
56
+ animated?: boolean;
57
+ viewPosition?: number;
58
+ }) => void;
59
+ scrollToEnd: (params?: {
60
+ animated?: boolean;
61
+ } | undefined) => void;
62
+ flashScrollIndicators: () => void;
63
+ getNativeScrollRef: () => IScrollViewHandle | null;
64
+ getScrollableNode: () => IScrollViewHandle | null;
65
+ getScrollResponder: () => IScrollViewHandle | null;
66
+ getScrollNode: () => ISymbioteNode | null;
67
+ recordInteraction: () => void;
68
+ };
69
+ }
70
+ interface $$IsomorphicComponent {
71
+ new <ItemT>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<ItemT>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<ItemT>['props']>, ReturnType<__sveltets_Render<ItemT>['events']>, ReturnType<__sveltets_Render<ItemT>['slots']>> & {
72
+ $$bindings?: ReturnType<__sveltets_Render<ItemT>['bindings']>;
73
+ } & ReturnType<__sveltets_Render<ItemT>['exports']>;
74
+ <ItemT>(internal: unknown, props: ReturnType<__sveltets_Render<ItemT>['props']> & {}): ReturnType<__sveltets_Render<ItemT>['exports']>;
75
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
76
+ }
77
+ declare const Index: $$IsomorphicComponent;
78
+ type Index<ItemT> = InstanceType<typeof Index<ItemT>>;
79
+ export default Index;
@@ -0,0 +1,2 @@
1
+ import type { IImageViewProps } from '@symbiote-native/components';
2
+ export declare function buildImageBag(view: IImageViewProps): Record<string, unknown>;
@@ -0,0 +1,125 @@
1
+ // Svelte-side duplicate of core/components/src/view/render-image/index.ts's private prop-mapping
2
+ // helpers (normalizeSource / headersFromAliases / expandSrcSet / readStyleString / readSourceUri /
3
+ // resolveSourceArray). None of them are exported — not even from that file — so per the
4
+ // svelte-adapter-dom-shim skill's §15 ("skip consuming a render-*.ts function's Descriptor output
5
+ // programmatically; hand-author the equivalent markup, reusing only EXPORTED pure helpers"), this
6
+ // module reproduces the mapping directly rather than calling renderImage() and reading its
7
+ // returned Descriptor's `.props`.
8
+ //
9
+ // GENUINE GAP (see the Svelte-components work report): these helpers should be exported from
10
+ // core/components/src/view/render-image/index.ts so no adapter needs this duplication. Until
11
+ // then, this file is kept byte-for-byte equivalent to that source and reuses every primitive that
12
+ // IS already exported (resolveImageSource, flattenStyle, dlog) — only the mid-level composition
13
+ // is duplicated.
14
+ import { dlog, flattenStyle, resolveImageSource, } from '@symbiote-native/engine';
15
+ function normalizeSource(source) {
16
+ const resolved = resolveImageSource(source);
17
+ const sources = Array.isArray(resolved) ? resolved : [resolved];
18
+ dlog(`Image source resolved to ${JSON.stringify(sources)}`);
19
+ return sources;
20
+ }
21
+ function headersFromAliases(view) {
22
+ const headers = {};
23
+ if (view.crossOrigin === 'use-credentials') {
24
+ headers['Access-Control-Allow-Credentials'] = 'true';
25
+ }
26
+ if (view.referrerPolicy !== undefined) {
27
+ headers['Referrer-Policy'] = view.referrerPolicy;
28
+ }
29
+ return headers;
30
+ }
31
+ function expandSrcSet(srcSet, view, headers) {
32
+ const sources = [];
33
+ let useSrcForDefaultScale = true;
34
+ for (const entry of srcSet.split(', ')) {
35
+ const [uri, xScale = '1x'] = entry.split(' ');
36
+ if (!xScale.endsWith('x')) {
37
+ dlog(`Image srcSet: unsupported scale token "${xScale}", skipping`);
38
+ continue;
39
+ }
40
+ const scale = parseInt(xScale.slice(0, -1), 10);
41
+ if (Number.isNaN(scale))
42
+ continue;
43
+ if (scale === 1)
44
+ useSrcForDefaultScale = false;
45
+ sources.push({ uri, scale, width: view.width, height: view.height, ...{ headers } });
46
+ }
47
+ if (useSrcForDefaultScale && view.src !== undefined) {
48
+ sources.push({
49
+ uri: view.src,
50
+ scale: 1,
51
+ width: view.width,
52
+ height: view.height,
53
+ ...{ headers },
54
+ });
55
+ }
56
+ if (sources.length === 0)
57
+ dlog('Image srcSet: produced no valid sources');
58
+ return sources;
59
+ }
60
+ function resolveSourceArray(view) {
61
+ const headers = headersFromAliases(view);
62
+ if (view.srcSet !== undefined) {
63
+ return expandSrcSet(view.srcSet, view, headers);
64
+ }
65
+ if (view.src !== undefined) {
66
+ return [{ uri: view.src, width: view.width, height: view.height, ...{ headers } }];
67
+ }
68
+ if (view.source === undefined) {
69
+ dlog('Image: no source / src / srcSet provided');
70
+ return [];
71
+ }
72
+ const sources = normalizeSource(view.source);
73
+ if (Object.keys(headers).length > 0 && sources.length === 1) {
74
+ const [only] = sources;
75
+ if (typeof only === 'object' && only !== null && typeof Reflect.get(only, 'uri') === 'string') {
76
+ return [{ ...only, headers }];
77
+ }
78
+ }
79
+ return sources;
80
+ }
81
+ function readStyleString(style, key) {
82
+ if (style === undefined)
83
+ return undefined;
84
+ const flat = flattenStyle(style);
85
+ const value = Object.hasOwn(flat, key) ? flat[key] : undefined;
86
+ return typeof value === 'string' ? value : undefined;
87
+ }
88
+ function readSourceUri(source) {
89
+ const [resolved] = normalizeSource(source);
90
+ if (typeof resolved === 'object' && resolved !== null) {
91
+ const uri = Reflect.get(resolved, 'uri');
92
+ if (typeof uri === 'string')
93
+ return uri;
94
+ }
95
+ return undefined;
96
+ }
97
+ // Builds the exact prop bag renderImage's `mapped` produces, minus the final `el()` wrap — the
98
+ // caller hands the result straight to `<symbiote-image p={bag}>`.
99
+ export function buildImageBag(view) {
100
+ // `width` / `height` aliases fold into style; explicit style keys win.
101
+ const foldedStyle = view.width === undefined && view.height === undefined
102
+ ? view.style
103
+ : [{ width: view.width, height: view.height }, view.style];
104
+ const mapped = {
105
+ ...view.passthrough,
106
+ style: foldedStyle,
107
+ source: resolveSourceArray(view),
108
+ resizeMode: view.resizeMode ?? readStyleString(view.style, 'resizeMode'),
109
+ tintColor: view.tintColor ?? readStyleString(view.style, 'tintColor'),
110
+ };
111
+ // `alt` is the accessibility text: it sets accessibilityLabel and marks the image accessible.
112
+ // An explicit accessibilityLabel (already folded into passthrough) still wins.
113
+ if (view.alt !== undefined) {
114
+ if (mapped.accessibilityLabel === undefined)
115
+ mapped.accessibilityLabel = view.alt;
116
+ mapped.accessible = true;
117
+ }
118
+ if (view.defaultSource !== undefined)
119
+ mapped.defaultSource = normalizeSource(view.defaultSource);
120
+ if (view.loadingIndicatorSource !== undefined) {
121
+ mapped.loadingIndicatorSrc = readSourceUri(view.loadingIndicatorSource);
122
+ }
123
+ dlog('Image -> RCTImageView');
124
+ return mapped;
125
+ }
@@ -0,0 +1,5 @@
1
+ import type { IImageProps as IImageBaseProps } from '@symbiote-native/components';
2
+ import type { ISvelteClassValue } from '../../class-value';
3
+ export type IImageProps = IImageBaseProps & {
4
+ class?: ISvelteClassValue;
5
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export type { IImageProps } from './image-props';
2
+ export type { IImageStatics } from '@symbiote-native/components';
3
+ export declare const Image: import("svelte").Component<import("./image-props").IImageProps, {}, ""> & import("@symbiote-native/engine").IImageStatics;
@@ -0,0 +1,10 @@
1
+ // Image statics (getSize / prefetch / queryCache / abortPrefetch / resolveAssetSource) attach onto
2
+ // the component value, mirroring RN's `Image.getSize` static surface — shared verbatim via
3
+ // @symbiote-native/engine's imageStatics, the same source React's and Vue's Image use. A `.svelte`
4
+ // file's own module type resolves through svelte's ambient `declare module '*.svelte'` fallback (a
5
+ // bare value export, not props-parameterized — see view-props.ts's header comment for the general
6
+ // reason), so the statics are attached here in a plain sibling `.ts` file rather than inside
7
+ // `index.svelte` itself.
8
+ import ImageComponent from './index.svelte';
9
+ import { imageStatics } from '@symbiote-native/components';
10
+ export const Image = Object.assign(ImageComponent, imageStatics);
@@ -0,0 +1,66 @@
1
+ <script lang="ts" module>
2
+ // Image: render-only (no state). Source resolution / width-height fold / resizeMode & tintColor
3
+ // style-read / alt->accessibility fold mirror core/components/src/view/render-image/index.ts's
4
+ // renderImage() exactly, via image-logic.ts's buildImageBag (see that file's header for why the
5
+ // logic is duplicated rather than the Descriptor consumed). renderImage always produces a
6
+ // SINGLE symbiote-image node, so the markup here is just that one host tag.
7
+ //
8
+ // Statics (getSize/prefetch/queryCache/…) are attached in the sibling `index.ts`, not here — a
9
+ // `.svelte` file's default export resolves through svelte's ambient module fallback (a bare
10
+ // value, not something `Object.assign` can usefully augment from inside the component itself).
11
+ import type { IImageProps } from './image-props';
12
+
13
+ export type { IImageProps };
14
+ </script>
15
+
16
+ <script lang="ts">
17
+ import { resolveAccessibilityProps } from '@symbiote-native/components';
18
+ import { buildImageBag } from './image-logic';
19
+ import { createAttachmentsSync } from '../../runes/attachments';
20
+ import type { ShimElement } from '../../dom-shim';
21
+
22
+ let {
23
+ source,
24
+ defaultSource,
25
+ loadingIndicatorSource,
26
+ style,
27
+ resizeMode,
28
+ tintColor,
29
+ src,
30
+ srcSet,
31
+ alt,
32
+ width,
33
+ height,
34
+ crossOrigin,
35
+ referrerPolicy,
36
+ ...passthrough
37
+ }: IImageProps = $props();
38
+
39
+ const bag = $derived(
40
+ buildImageBag({
41
+ source,
42
+ defaultSource,
43
+ loadingIndicatorSource,
44
+ style,
45
+ resizeMode,
46
+ tintColor,
47
+ src,
48
+ srcSet,
49
+ alt,
50
+ width,
51
+ height,
52
+ crossOrigin,
53
+ referrerPolicy,
54
+ passthrough: resolveAccessibilityProps(passthrough),
55
+ }),
56
+ );
57
+
58
+ // See View.svelte's note on `{@attach}`.
59
+ let hostShim = $state.raw<ShimElement | null>(null);
60
+ const syncAttachments = createAttachmentsSync();
61
+ $effect(() => {
62
+ syncAttachments(hostShim, passthrough);
63
+ });
64
+ </script>
65
+
66
+ <symbiote-image p={bag} bind:this={hostShim} />
@@ -0,0 +1,5 @@
1
+ import type { IImageProps } from './image-props';
2
+ export type { IImageProps };
3
+ declare const Index: import("svelte").Component<IImageProps, {}, "">;
4
+ type Index = ReturnType<typeof Index>;
5
+ export default Index;
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { IStyleProp, IViewStyle } from '@symbiote-native/engine';
3
+ import type { IImageProps } from '@symbiote-native/components';
4
+ import type { ISvelteClassValue } from '../../class-value';
5
+ export interface IImageBackgroundProps extends Omit<IImageProps, 'style'> {
6
+ style?: IStyleProp<IViewStyle>;
7
+ imageStyle?: IStyleProp<IViewStyle> | string;
8
+ class?: ISvelteClassValue;
9
+ children?: Snippet;
10
+ }