@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.
- package/LICENSE +21 -0
- package/README.md +161 -0
- package/build/bootstrap.d.ts +7 -0
- package/build/bootstrap.js +17 -0
- package/build/class-value.d.ts +6 -0
- package/build/class-value.js +81 -0
- package/build/components/RefreshControl.svelte +38 -0
- package/build/components/RefreshControl.svelte.d.ts +5 -0
- package/build/components/SafeAreaView.svelte +34 -0
- package/build/components/SafeAreaView.svelte.d.ts +5 -0
- package/build/components/Text.svelte +25 -0
- package/build/components/Text.svelte.d.ts +5 -0
- package/build/components/View.svelte +41 -0
- package/build/components/View.svelte.d.ts +5 -0
- package/build/components/activity-indicator/activity-indicator-platform.android.d.ts +3 -0
- package/build/components/activity-indicator/activity-indicator-platform.android.js +5 -0
- package/build/components/activity-indicator/activity-indicator-platform.d.ts +1 -0
- package/build/components/activity-indicator/activity-indicator-platform.ios.d.ts +3 -0
- package/build/components/activity-indicator/activity-indicator-platform.ios.js +6 -0
- package/build/components/activity-indicator/activity-indicator-platform.js +5 -0
- package/build/components/activity-indicator/activity-indicator-props.d.ts +5 -0
- package/build/components/activity-indicator/activity-indicator-props.js +1 -0
- package/build/components/activity-indicator/index.svelte +57 -0
- package/build/components/activity-indicator/index.svelte.d.ts +5 -0
- package/build/components/button-props.d.ts +5 -0
- package/build/components/button-props.js +1 -0
- package/build/components/button.svelte +71 -0
- package/build/components/button.svelte.d.ts +5 -0
- package/build/components/flat-list/flat-list-props.d.ts +10 -0
- package/build/components/flat-list/flat-list-props.js +1 -0
- package/build/components/flat-list/index.svelte +254 -0
- package/build/components/flat-list/index.svelte.d.ts +79 -0
- package/build/components/image/image-logic.d.ts +2 -0
- package/build/components/image/image-logic.js +125 -0
- package/build/components/image/image-props.d.ts +5 -0
- package/build/components/image/image-props.js +1 -0
- package/build/components/image/index.d.ts +3 -0
- package/build/components/image/index.js +10 -0
- package/build/components/image/index.svelte +66 -0
- package/build/components/image/index.svelte.d.ts +5 -0
- package/build/components/image-background/image-background-props.d.ts +10 -0
- package/build/components/image-background/image-background-props.js +1 -0
- package/build/components/image-background/index.svelte +81 -0
- package/build/components/image-background/index.svelte.d.ts +5 -0
- package/build/components/index.d.ts +50 -0
- package/build/components/index.js +24 -0
- package/build/components/input-accessory-view/index.svelte +48 -0
- package/build/components/input-accessory-view/index.svelte.d.ts +5 -0
- package/build/components/input-accessory-view/input-accessory-view-props.d.ts +11 -0
- package/build/components/input-accessory-view/input-accessory-view-props.js +1 -0
- package/build/components/keyboard-avoiding-view/index.svelte +135 -0
- package/build/components/keyboard-avoiding-view/index.svelte.d.ts +5 -0
- package/build/components/keyboard-avoiding-view/keyboard-avoiding-view-props.d.ts +15 -0
- package/build/components/keyboard-avoiding-view/keyboard-avoiding-view-props.js +1 -0
- package/build/components/modal/index.svelte +126 -0
- package/build/components/modal/index.svelte.d.ts +5 -0
- package/build/components/modal/modal-props.d.ts +24 -0
- package/build/components/modal/modal-props.js +1 -0
- package/build/components/pressable/index.svelte +160 -0
- package/build/components/pressable/index.svelte.d.ts +5 -0
- package/build/components/pressable/pressable-props.d.ts +27 -0
- package/build/components/pressable/pressable-props.js +1 -0
- package/build/components/refresh-control-props.d.ts +19 -0
- package/build/components/refresh-control-props.js +1 -0
- package/build/components/safe-area-view-props.d.ts +10 -0
- package/build/components/safe-area-view-props.js +1 -0
- package/build/components/scroll-view/index.svelte +298 -0
- package/build/components/scroll-view/index.svelte.d.ts +18 -0
- package/build/components/scroll-view/scroll-view-platform-types.d.ts +3 -0
- package/build/components/scroll-view/scroll-view-platform-types.js +1 -0
- package/build/components/scroll-view/scroll-view-platform.android.d.ts +3 -0
- package/build/components/scroll-view/scroll-view-platform.android.js +3 -0
- package/build/components/scroll-view/scroll-view-platform.d.ts +1 -0
- package/build/components/scroll-view/scroll-view-platform.ios.d.ts +3 -0
- package/build/components/scroll-view/scroll-view-platform.ios.js +3 -0
- package/build/components/scroll-view/scroll-view-platform.js +4 -0
- package/build/components/scroll-view/scroll-view-props.d.ts +78 -0
- package/build/components/scroll-view/scroll-view-props.js +1 -0
- package/build/components/scroll-view/scroll-view-sticky-context.d.ts +7 -0
- package/build/components/scroll-view/scroll-view-sticky-context.js +1 -0
- package/build/components/scroll-view/sticky-header-props.d.ts +10 -0
- package/build/components/scroll-view/sticky-header-props.js +1 -0
- package/build/components/scroll-view/sticky-header.svelte +254 -0
- package/build/components/scroll-view/sticky-header.svelte.d.ts +5 -0
- package/build/components/section-list/index.svelte +107 -0
- package/build/components/section-list/index.svelte.d.ts +57 -0
- package/build/components/section-list/section-list-props.d.ts +1 -0
- package/build/components/section-list/section-list-props.js +1 -0
- package/build/components/switch/index.svelte +123 -0
- package/build/components/switch/index.svelte.d.ts +5 -0
- package/build/components/switch/switch-platform-types.d.ts +5 -0
- package/build/components/switch/switch-platform-types.js +1 -0
- package/build/components/switch/switch-platform.android.d.ts +3 -0
- package/build/components/switch/switch-platform.android.js +8 -0
- package/build/components/switch/switch-platform.d.ts +1 -0
- package/build/components/switch/switch-platform.ios.d.ts +3 -0
- package/build/components/switch/switch-platform.ios.js +7 -0
- package/build/components/switch/switch-platform.js +5 -0
- package/build/components/switch/switch-props.d.ts +5 -0
- package/build/components/switch/switch-props.js +1 -0
- package/build/components/text-input/index.svelte +300 -0
- package/build/components/text-input/index.svelte.d.ts +12 -0
- package/build/components/text-input/text-input-props.d.ts +5 -0
- package/build/components/text-input/text-input-props.js +1 -0
- package/build/components/text-props.d.ts +23 -0
- package/build/components/text-props.js +1 -0
- package/build/components/touchable-base-props.d.ts +10 -0
- package/build/components/touchable-base-props.js +1 -0
- package/build/components/touchable-highlight/index.svelte +39 -0
- package/build/components/touchable-highlight/index.svelte.d.ts +5 -0
- package/build/components/touchable-highlight/touchable-highlight-props.d.ts +5 -0
- package/build/components/touchable-highlight/touchable-highlight-props.js +1 -0
- package/build/components/touchable-native-feedback/index.d.ts +9 -0
- package/build/components/touchable-native-feedback/index.js +14 -0
- package/build/components/touchable-native-feedback/touchable-native-feedback-props.d.ts +8 -0
- package/build/components/touchable-native-feedback/touchable-native-feedback-props.js +1 -0
- package/build/components/touchable-native-feedback/touchable-native-feedback.svelte +44 -0
- package/build/components/touchable-native-feedback/touchable-native-feedback.svelte.d.ts +5 -0
- package/build/components/touchable-opacity/index.svelte +124 -0
- package/build/components/touchable-opacity/index.svelte.d.ts +5 -0
- package/build/components/touchable-opacity/touchable-opacity-props.d.ts +5 -0
- package/build/components/touchable-opacity/touchable-opacity-props.js +1 -0
- package/build/components/touchable-without-feedback/index.svelte +19 -0
- package/build/components/touchable-without-feedback/index.svelte.d.ts +5 -0
- package/build/components/touchable-without-feedback/touchable-without-feedback-props.d.ts +2 -0
- package/build/components/touchable-without-feedback/touchable-without-feedback-props.js +1 -0
- package/build/components/view-props.d.ts +29 -0
- package/build/components/view-props.js +1 -0
- package/build/components/virtualized-list/index.svelte +702 -0
- package/build/components/virtualized-list/index.svelte.d.ts +79 -0
- package/build/components/virtualized-list/virtualized-list-props.d.ts +70 -0
- package/build/components/virtualized-list/virtualized-list-props.js +73 -0
- package/build/components/virtualized-section-list/index.svelte +206 -0
- package/build/components/virtualized-section-list/index.svelte.d.ts +57 -0
- package/build/components/virtualized-section-list/virtualized-section-list-props.d.ts +62 -0
- package/build/components/virtualized-section-list/virtualized-section-list-props.js +1 -0
- package/build/create-tunnel/index.d.ts +3 -0
- package/build/create-tunnel/index.js +3 -0
- package/build/create-tunnel/tunnel-in.svelte +24 -0
- package/build/create-tunnel/tunnel-in.svelte.d.ts +9 -0
- package/build/create-tunnel/tunnel-out.svelte +14 -0
- package/build/create-tunnel/tunnel-out.svelte.d.ts +7 -0
- package/build/create-tunnel/tunnel.d.ts +9 -0
- package/build/create-tunnel/tunnel.js +9 -0
- package/build/descriptor-to-svelte.d.ts +7 -0
- package/build/descriptor-to-svelte.js +104 -0
- package/build/dom-shim/comment.d.ts +9 -0
- package/build/dom-shim/comment.js +24 -0
- package/build/dom-shim/document-fragment.d.ts +8 -0
- package/build/dom-shim/document-fragment.js +23 -0
- package/build/dom-shim/document.d.ts +23 -0
- package/build/dom-shim/document.js +61 -0
- package/build/dom-shim/element.d.ts +22 -0
- package/build/dom-shim/element.js +130 -0
- package/build/dom-shim/index.d.ts +5 -0
- package/build/dom-shim/index.js +7 -0
- package/build/dom-shim/patch-globals.d.ts +2 -0
- package/build/dom-shim/patch-globals.js +94 -0
- package/build/dom-shim/shim-node.d.ts +30 -0
- package/build/dom-shim/shim-node.js +207 -0
- package/build/dom-shim/text.d.ts +14 -0
- package/build/dom-shim/text.js +97 -0
- package/build/host-instance.d.ts +5 -0
- package/build/host-instance.js +48 -0
- package/build/index.d.ts +28 -0
- package/build/index.js +77 -0
- package/build/modules/accessibility-info/index.android.d.ts +2 -0
- package/build/modules/accessibility-info/index.android.js +4 -0
- package/build/modules/accessibility-info/index.d.ts +1 -0
- package/build/modules/accessibility-info/index.ios.d.ts +2 -0
- package/build/modules/accessibility-info/index.ios.js +3 -0
- package/build/modules/accessibility-info/index.js +5 -0
- package/build/modules/animated/AnimatedImage.svelte +115 -0
- package/build/modules/animated/AnimatedImage.svelte.d.ts +5 -0
- package/build/modules/animated/AnimatedScrollView.svelte +92 -0
- package/build/modules/animated/AnimatedScrollView.svelte.d.ts +17 -0
- package/build/modules/animated/AnimatedText.svelte +58 -0
- package/build/modules/animated/AnimatedText.svelte.d.ts +5 -0
- package/build/modules/animated/AnimatedView.svelte +95 -0
- package/build/modules/animated/AnimatedView.svelte.d.ts +5 -0
- package/build/modules/animated/animated-component-props.d.ts +7 -0
- package/build/modules/animated/animated-component-props.js +1 -0
- package/build/modules/animated/index.d.ts +58 -0
- package/build/modules/animated/index.js +69 -0
- package/build/modules/app-registry/index.d.ts +7 -0
- package/build/modules/app-registry/index.js +28 -0
- package/build/modules/status-bar/index.d.ts +5 -0
- package/build/modules/status-bar/index.js +21 -0
- package/build/modules/status-bar/index.svelte +20 -0
- package/build/modules/status-bar/index.svelte.d.ts +4 -0
- package/build/native-view-bridge.d.ts +4 -0
- package/build/native-view-bridge.js +27 -0
- package/build/preprocessor/forbid-web-only-constructs.d.ts +8 -0
- package/build/preprocessor/forbid-web-only-constructs.js +204 -0
- package/build/preprocessor/scoped-styles.d.ts +10 -0
- package/build/preprocessor/scoped-styles.js +399 -0
- package/build/render.d.ts +7 -0
- package/build/render.js +46 -0
- package/build/root-element.d.ts +3 -0
- package/build/root-element.js +27 -0
- package/build/runes/attachments.d.ts +5 -0
- package/build/runes/attachments.js +73 -0
- package/build/runes/dimensions-value.d.ts +4 -0
- package/build/runes/dimensions-value.js +30 -0
- package/build/runes/media-query.d.ts +8 -0
- package/build/runes/media-query.js +38 -0
- package/build/runes/use-color-scheme.svelte.d.ts +4 -0
- package/build/runes/use-color-scheme.svelte.js +25 -0
- package/build/runes/use-window-dimensions.svelte.d.ts +4 -0
- package/build/runes/use-window-dimensions.svelte.js +43 -0
- package/build/runes/window.d.ts +6 -0
- package/build/runes/window.js +28 -0
- package/build/scope-token.d.ts +2 -0
- package/build/scope-token.js +33 -0
- package/build/style-scope.d.ts +1 -0
- package/build/style-scope.js +29 -0
- package/metro-css-parser.cjs +9 -0
- package/metro-svelte-transformer.cjs +156 -0
- 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,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,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 @@
|
|
|
1
|
+
export {};
|
|
@@ -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,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
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|