@symbiote-native/react 0.4.0 → 2.0.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/README.md +32 -16
- package/build/components/activity-indicator-props.d.ts +4 -0
- package/build/components/activity-indicator-props.js +1 -0
- package/build/components/{button.d.ts → button-props.d.ts} +0 -2
- package/build/components/button-props.js +1 -0
- package/build/components/flat-list/index.js +2 -2
- package/build/components/image/image-props.d.ts +4 -0
- package/build/components/image/image-props.js +1 -0
- package/build/components/image-background-props.d.ts +9 -0
- package/build/components/image-background-props.js +1 -0
- package/build/components/input-accessory-view-props.d.ts +10 -0
- package/build/components/input-accessory-view-props.js +1 -0
- package/build/components/keyboard-avoiding-view/index.js +4 -4
- package/build/components/modal/index.js +3 -3
- package/build/components/pressable/{index.d.ts → pressable-props.d.ts} +4 -4
- package/build/components/pressable/pressable-props.js +1 -0
- package/build/components/{refresh-control/index.d.ts → refresh-control-props.d.ts} +3 -3
- package/build/components/refresh-control-props.js +1 -0
- package/build/components/safe-area-view-props.d.ts +11 -0
- package/build/components/safe-area-view-props.js +1 -0
- package/build/components/scroll-view/{shared.d.ts → scroll-view-props.d.ts} +4 -26
- package/build/components/scroll-view/scroll-view-props.js +1 -0
- package/build/components/switch/switch-props.d.ts +4 -0
- package/build/components/switch/switch-props.js +1 -0
- package/build/components/text-input/text-input-props.d.ts +4 -0
- package/build/components/text-input/text-input-props.js +1 -0
- package/build/components/touchable/touchable-props.d.ts +17 -0
- package/build/components/touchable/touchable-props.js +1 -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-without-feedback/touchable-without-feedback-props.d.ts +6 -0
- package/build/components/touchable-without-feedback/touchable-without-feedback-props.js +1 -0
- package/build/components/virtualized-list/index.js +83 -38
- package/build/components.d.ts +3 -4
- package/build/components.js +5 -17
- package/build/create-portal/index.js +1 -1
- package/build/create-tunnel/index.js +1 -1
- package/build/descriptor-to-react/index.js +1 -1
- package/build/host-config.d.ts +2 -2
- package/build/host-config.js +51 -10
- package/build/host-instance.js +1 -1
- package/build/index.d.ts +23 -27
- package/build/index.js +14 -14
- package/build/jsx-dev-runtime.d.ts +3 -0
- package/build/jsx-dev-runtime.js +10 -0
- package/build/jsx-namespace.type-check.d.ts +1 -0
- package/build/jsx-namespace.type-check.js +7 -0
- package/build/jsx-runtime.d.ts +62 -0
- package/build/jsx-runtime.js +1 -0
- package/build/modules/animated/create-animated-component.d.ts +2 -1
- package/build/modules/animated/create-animated-component.js +7 -1
- package/build/modules/animated/index.d.ts +0 -1
- package/build/modules/animated/index.js +16 -22
- package/build/modules/image/index.d.ts +3 -0
- package/build/modules/image/index.js +14 -0
- package/build/register.d.ts +1 -0
- package/build/register.js +15 -0
- package/build/render.js +2 -4
- package/metro-css-parser.cjs +2 -1
- package/package.json +28 -8
- package/build/components/activity-indicator/index.android.d.ts +0 -3
- package/build/components/activity-indicator/index.android.js +0 -17
- package/build/components/activity-indicator/index.d.ts +0 -1
- package/build/components/activity-indicator/index.ios.d.ts +0 -3
- package/build/components/activity-indicator/index.ios.js +0 -16
- package/build/components/activity-indicator/index.js +0 -4
- package/build/components/activity-indicator/shared.d.ts +0 -6
- package/build/components/activity-indicator/shared.js +0 -22
- package/build/components/button.js +0 -42
- package/build/components/image/index.d.ts +0 -9
- package/build/components/image/index.js +0 -28
- package/build/components/image-background/index.d.ts +0 -10
- package/build/components/image-background/index.js +0 -46
- package/build/components/input-accessory-view/index.d.ts +0 -11
- package/build/components/input-accessory-view/index.js +0 -19
- package/build/components/pressable/index.js +0 -100
- package/build/components/refresh-control/index.js +0 -21
- package/build/components/safe-area-view/index.d.ts +0 -11
- package/build/components/safe-area-view/index.js +0 -18
- package/build/components/scroll-view/index.android.d.ts +0 -3
- package/build/components/scroll-view/index.android.js +0 -61
- package/build/components/scroll-view/index.d.ts +0 -1
- package/build/components/scroll-view/index.ios.d.ts +0 -3
- package/build/components/scroll-view/index.ios.js +0 -29
- package/build/components/scroll-view/index.js +0 -4
- package/build/components/scroll-view/shared.js +0 -240
- package/build/components/scroll-view/sticky-header.d.ts +0 -18
- package/build/components/scroll-view/sticky-header.js +0 -227
- package/build/components/switch/index.android.d.ts +0 -3
- package/build/components/switch/index.android.js +0 -18
- package/build/components/switch/index.d.ts +0 -1
- package/build/components/switch/index.ios.d.ts +0 -3
- package/build/components/switch/index.ios.js +0 -16
- package/build/components/switch/index.js +0 -6
- package/build/components/switch/shared.d.ts +0 -9
- package/build/components/switch/shared.js +0 -60
- package/build/components/text-input/index.d.ts +0 -50
- package/build/components/text-input/index.js +0 -172
- package/build/components/touchable/index.d.ts +0 -22
- package/build/components/touchable/index.js +0 -165
- package/build/components/touchable-native-feedback/index.d.ts +0 -18
- package/build/components/touchable-native-feedback/index.js +0 -32
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// VirtualizedList: real windowing over the
|
|
1
|
+
// VirtualizedList: real windowing over the `scroll-view` TAG. Only the cells
|
|
2
2
|
// whose computed offset falls inside the visible window (plus a leading/trailing
|
|
3
3
|
// buffer) are rendered; everything above and below is collapsed into two spacer
|
|
4
4
|
// Views whose sizes sum to the off-screen extent, so the scroll thumb and total
|
|
@@ -14,14 +14,31 @@
|
|
|
14
14
|
// from a `commit` dispatched in a layout effect (before paint, so MVCP's shift lands without a
|
|
15
15
|
// visible jump). Lists have no Descriptor render fn — the cell content is React's own children.
|
|
16
16
|
//
|
|
17
|
-
// Imperative scrolling resolves to an offset in the reducer and rides the
|
|
18
|
-
// scrollTo command
|
|
19
|
-
//
|
|
17
|
+
// Imperative scrolling resolves to an offset in the reducer and rides the scroll node's native
|
|
18
|
+
// scrollTo command, animated by default. The `contentOffset` prop is only a fallback for the
|
|
19
|
+
// pre-mount window (the node not yet attached).
|
|
20
|
+
//
|
|
21
|
+
// WHAT IS STILL THIS COMPONENT'S, now that the scroll view is a tag and the engine owns its
|
|
22
|
+
// content node, its sticky seam and its RefreshControl placement — checked rather than assumed,
|
|
23
|
+
// because "the wrapper is gone" and "nothing is left" are different claims:
|
|
24
|
+
//
|
|
25
|
+
// the WINDOW `reduceList` decides which indices are in view, and this file is what
|
|
26
|
+
// turns that into elements. The output SHAPE is decided in JS from the
|
|
27
|
+
// app's own data through `renderItem` — the one disqualifier that no
|
|
28
|
+
// engine seam removes (`.claude/rules/host-primitive-tier.md`, tier 3).
|
|
29
|
+
// the CELL WRAPPERS a measuring `view` per cell with the inversion counter-flip, the two
|
|
30
|
+
// spacers, the header/footer/empty slots, the separator INSIDE the cell.
|
|
31
|
+
// the LIFECYCLE native events -> actions, effects run with React primitives (timers, a
|
|
32
|
+
// forced re-render, a layout effect for MVCP), one state cell.
|
|
33
|
+
// the HANDLE `buildScrollViewHandle` over the node a `ref` hands back, plus the list's
|
|
34
|
+
// own imperative surface on top of it.
|
|
35
|
+
//
|
|
36
|
+
// What is NOT: the content node, `contentContainerStyle`'s routing, where a RefreshControl goes
|
|
37
|
+
// per platform, and how a sticky header pins. The list names `sticky-header` on a cell and knows
|
|
38
|
+
// nothing else about it.
|
|
20
39
|
import { createElement, useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState, } from 'react';
|
|
21
40
|
import { dlog, } from '@symbiote-native/engine';
|
|
22
|
-
import { DEFAULT_END_REACHED_THRESHOLD, DEFAULT_INITIAL_NUM_TO_RENDER, DEFAULT_MAX_TO_RENDER_PER_BATCH, DEFAULT_START_REACHED_THRESHOLD, DEFAULT_UPDATE_CELLS_BATCHING_PERIOD, DEFAULT_WINDOW_SIZE, EMPTY_OFFSET, FIRST_INDEX, INVERTED_X_STYLE, INVERTED_Y_STYLE, buildListPlan, buildViewabilityPairs, createInitialListState, isSeparatorGapInRange, listEffectSignature, readLayoutLength, readLayoutOffset, readScrollOffset, reduceList, resolveItemKey, } from '@symbiote-native/components';
|
|
23
|
-
import { ScrollView, } from '../scroll-view';
|
|
24
|
-
import { RefreshControl } from '../refresh-control/index.js';
|
|
41
|
+
import { DEFAULT_END_REACHED_THRESHOLD, DEFAULT_INITIAL_NUM_TO_RENDER, DEFAULT_MAX_TO_RENDER_PER_BATCH, DEFAULT_START_REACHED_THRESHOLD, DEFAULT_UPDATE_CELLS_BATCHING_PERIOD, DEFAULT_WINDOW_SIZE, EMPTY_OFFSET, FIRST_INDEX, INVERTED_X_STYLE, INVERTED_Y_STYLE, buildListPlan, buildScrollViewHandle, buildViewabilityPairs, createInitialListState, isSeparatorGapInRange, listEffectSignature, readLayoutLength, readLayoutOffset, readScrollOffset, reduceList, resolveItemKey, } from '@symbiote-native/components';
|
|
25
42
|
function resolveElement(component) {
|
|
26
43
|
if (component === undefined)
|
|
27
44
|
return undefined;
|
|
@@ -101,7 +118,12 @@ export function VirtualizedList(props) {
|
|
|
101
118
|
// The offset we are imperatively driving native to (scrollTo* before the handle attaches). Pushed
|
|
102
119
|
// down as the ScrollView's contentOffset prop; fresh object identity each time. undefined = none.
|
|
103
120
|
const [commandedOffset, setCommandedOffset] = useState(undefined);
|
|
104
|
-
|
|
121
|
+
// The engine node of the scroll TAG. A `ref` on an intrinsic hands back the host instance, so
|
|
122
|
+
// there is no wrapper left to run a `useImperativeHandle` — `buildScrollViewHandle` is what turns
|
|
123
|
+
// the node into RN's scroll surface, and it is the same function every other adapter feeds from
|
|
124
|
+
// its own host-instance accessor. Lazy getter: the node is null until commit.
|
|
125
|
+
const scrollNodeRef = useRef(null);
|
|
126
|
+
const scrollHandle = useMemo(() => buildScrollViewHandle(() => scrollNodeRef.current), []);
|
|
105
127
|
// Pending minimumViewTime debounce timer / the incremental-fill timer (adapter owns the timers;
|
|
106
128
|
// the reducer only asks for a delay).
|
|
107
129
|
const viewableTimerRef = useRef(null);
|
|
@@ -117,9 +139,9 @@ export function VirtualizedList(props) {
|
|
|
117
139
|
const target = isHorizontal
|
|
118
140
|
? { x: clamped, y: EMPTY_OFFSET }
|
|
119
141
|
: { x: EMPTY_OFFSET, y: clamped };
|
|
120
|
-
if (
|
|
142
|
+
if (scrollNodeRef.current !== null) {
|
|
121
143
|
dlog(`VirtualizedList scrollTo offset=${clamped} animated=${animated} (horizontal=${isHorizontal})`);
|
|
122
|
-
|
|
144
|
+
scrollHandle.scrollTo({ x: target.x, y: target.y, animated });
|
|
123
145
|
return;
|
|
124
146
|
}
|
|
125
147
|
dlog(`VirtualizedList scrollTo offset=${clamped} pending-ref (horizontal=${isHorizontal})`);
|
|
@@ -289,18 +311,20 @@ export function VirtualizedList(props) {
|
|
|
289
311
|
dispatch({ kind: 'scroll-to-end', animated: params?.animated ?? true });
|
|
290
312
|
},
|
|
291
313
|
flashScrollIndicators: () => {
|
|
292
|
-
|
|
314
|
+
scrollHandle.flashScrollIndicators?.();
|
|
293
315
|
},
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
316
|
+
// Null until the tag commits, so these keep RN's "no scroll view yet" answer rather than
|
|
317
|
+
// handing back a handle that would silently no-op.
|
|
318
|
+
getNativeScrollRef: () => scrollNodeRef.current !== null ? scrollHandle : null,
|
|
319
|
+
getScrollableNode: () => scrollNodeRef.current !== null ? scrollHandle : null,
|
|
320
|
+
getScrollResponder: () => scrollNodeRef.current !== null ? scrollHandle : null,
|
|
321
|
+
getScrollNode: () => scrollNodeRef.current,
|
|
298
322
|
// Manual trigger for RN's recordInteraction: flip the interaction flag so
|
|
299
323
|
// waitForInteraction viewability configs start reporting.
|
|
300
324
|
recordInteraction: () => {
|
|
301
325
|
dispatch({ kind: 'record-interaction' });
|
|
302
326
|
},
|
|
303
|
-
}), [dispatch]);
|
|
327
|
+
}), [dispatch, scrollHandle]);
|
|
304
328
|
// After-commit pass: run the deferred effects (batch fill, edge-reached, viewability,
|
|
305
329
|
// initial-scroll, MVCP) in a LAYOUT effect so MVCP's shift lands before paint. Re-runs only when
|
|
306
330
|
// the windowing signature changed — the same dedup key every adapter shares.
|
|
@@ -328,15 +352,14 @@ export function VirtualizedList(props) {
|
|
|
328
352
|
const stickySet = stickyHeaderIndices !== undefined
|
|
329
353
|
? new Set(stickyHeaderIndices)
|
|
330
354
|
: undefined;
|
|
331
|
-
let renderedStickyIndices = [];
|
|
332
355
|
const header = resolveElement(ListHeaderComponent);
|
|
333
356
|
if (header !== undefined) {
|
|
334
|
-
children.push(createElement('
|
|
357
|
+
children.push(createElement('view', { key: 'list-header' }, header));
|
|
335
358
|
}
|
|
336
359
|
if (count === FIRST_INDEX) {
|
|
337
360
|
const empty = resolveElement(ListEmptyComponent);
|
|
338
361
|
if (empty !== undefined) {
|
|
339
|
-
children.push(createElement('
|
|
362
|
+
children.push(createElement('view', { key: 'list-empty' }, empty));
|
|
340
363
|
}
|
|
341
364
|
}
|
|
342
365
|
else {
|
|
@@ -352,9 +375,14 @@ export function VirtualizedList(props) {
|
|
|
352
375
|
stickyIndices: stickySet,
|
|
353
376
|
hasHeader: header !== undefined,
|
|
354
377
|
});
|
|
355
|
-
|
|
378
|
+
// `plan.stickyChildPositions` is deliberately NOT read. It was the input to the wrapper's own
|
|
379
|
+
// JS sticky pass, and the behavior honours `stickyHeaderIndices` by numbering the OWNER's paint
|
|
380
|
+
// children — which a windowed list cannot supply: it paints a header, a spacer and a slice, so
|
|
381
|
+
// data index 3 is almost never paint child 3, and the positions would have to be recomputed
|
|
382
|
+
// every time the window slides. The cells that should pin carry the `sticky-header` TAG
|
|
383
|
+
// instead, which pins by document order and survives windowing.
|
|
356
384
|
if (plan.leadingExtent > EMPTY_OFFSET) {
|
|
357
|
-
children.push(createElement('
|
|
385
|
+
children.push(createElement('view', {
|
|
358
386
|
key: 'spacer-leading',
|
|
359
387
|
style: horizontal
|
|
360
388
|
? { width: plan.leadingExtent }
|
|
@@ -374,7 +402,11 @@ export function VirtualizedList(props) {
|
|
|
374
402
|
index: forcedIndex,
|
|
375
403
|
separators: makeSeparators(forcedIndex),
|
|
376
404
|
});
|
|
377
|
-
children.push(createElement(
|
|
405
|
+
children.push(createElement(
|
|
406
|
+
// Sticky by construction — `forcedStickyCell` exists only for an index in `stickySet` —
|
|
407
|
+
// and the SAME tag the in-window branch below uses, so a cell crossing between the two
|
|
408
|
+
// keeps its element type as well as its key and never remounts.
|
|
409
|
+
'sticky-header', {
|
|
378
410
|
key: `cell-${plan.forcedStickyCell.key}`,
|
|
379
411
|
onLayout: makeCellMeasure(forcedIndex),
|
|
380
412
|
style: inverted
|
|
@@ -385,7 +417,7 @@ export function VirtualizedList(props) {
|
|
|
385
417
|
}, forcedCell));
|
|
386
418
|
}
|
|
387
419
|
if (plan.gapExtent > EMPTY_OFFSET) {
|
|
388
|
-
children.push(createElement('
|
|
420
|
+
children.push(createElement('view', {
|
|
389
421
|
key: 'spacer-gap',
|
|
390
422
|
style: horizontal
|
|
391
423
|
? { width: plan.gapExtent }
|
|
@@ -420,7 +452,13 @@ export function VirtualizedList(props) {
|
|
|
420
452
|
: undefined;
|
|
421
453
|
// Wrap each cell in a measuring View. When inverted, each cell carries the counter-flip so
|
|
422
454
|
// its content reads upright inside the flipped content container.
|
|
423
|
-
|
|
455
|
+
//
|
|
456
|
+
// A cell the app flagged sticky is wrapped in the `sticky-header` TAG instead — same
|
|
457
|
+
// position, same key, same `onLayout` (the behavior forwards it rather than replacing it),
|
|
458
|
+
// and the engine finds this scroll view by walking up. Nothing here computes a child index:
|
|
459
|
+
// the collision point comes from the owner's DOCUMENT order, which is the one form that
|
|
460
|
+
// survives windowing.
|
|
461
|
+
children.push(createElement(stickySet?.has(planCell.index) === true ? 'sticky-header' : 'view', {
|
|
424
462
|
key: `cell-${planCell.key}`,
|
|
425
463
|
onLayout: makeCellMeasure(planCell.index),
|
|
426
464
|
style: inverted
|
|
@@ -431,7 +469,7 @@ export function VirtualizedList(props) {
|
|
|
431
469
|
}, cell, separator));
|
|
432
470
|
}
|
|
433
471
|
if (plan.trailingExtent > EMPTY_OFFSET) {
|
|
434
|
-
children.push(createElement('
|
|
472
|
+
children.push(createElement('view', {
|
|
435
473
|
key: 'spacer-trailing',
|
|
436
474
|
style: horizontal
|
|
437
475
|
? { width: plan.trailingExtent }
|
|
@@ -441,7 +479,7 @@ export function VirtualizedList(props) {
|
|
|
441
479
|
}
|
|
442
480
|
const footer = resolveElement(ListFooterComponent);
|
|
443
481
|
if (footer !== undefined) {
|
|
444
|
-
children.push(createElement('
|
|
482
|
+
children.push(createElement('view', { key: 'list-footer' }, footer));
|
|
445
483
|
}
|
|
446
484
|
// A horizontal list pins the content container to the full row width so the row overflows for
|
|
447
485
|
// iOS to scroll. The inversion flip rides ONLY the outer ScrollView style and each cell, never
|
|
@@ -458,10 +496,13 @@ export function VirtualizedList(props) {
|
|
|
458
496
|
...accessibilityRest,
|
|
459
497
|
style: resolvedStyle,
|
|
460
498
|
contentContainerStyle: resolvedContentContainerStyle,
|
|
461
|
-
horizontal,
|
|
462
499
|
onScroll,
|
|
463
500
|
onLayout: onViewportLayout,
|
|
464
501
|
};
|
|
502
|
+
// `horizontal` is NOT in the bag: the axis is the TAG (`horizontal-scroll-view`), because Android
|
|
503
|
+
// scrolls the two axes with different native ViewManagers. The behavior's own fold deletes the
|
|
504
|
+
// prop and rewrites it from the tag, so passing it would be at best redundant and at worst a
|
|
505
|
+
// contradiction it has to warn about.
|
|
465
506
|
if (onScrollBeginDrag !== undefined)
|
|
466
507
|
scrollProps.onScrollBeginDrag = onScrollBeginDrag;
|
|
467
508
|
if (onScrollEndDrag !== undefined)
|
|
@@ -479,9 +520,6 @@ export function VirtualizedList(props) {
|
|
|
479
520
|
// A pending imperative/initial scroll rides down as contentOffset (fresh identity each push).
|
|
480
521
|
if (commandedOffset !== undefined)
|
|
481
522
|
scrollProps.contentOffset = commandedOffset;
|
|
482
|
-
// Headers in the window stick; an empty list leaves the prop off entirely.
|
|
483
|
-
if (renderedStickyIndices.length > 0)
|
|
484
|
-
scrollProps.stickyHeaderIndices = renderedStickyIndices;
|
|
485
523
|
// Forward maintainVisibleContentPosition to the native ScrollView so it anchors in-window cells.
|
|
486
524
|
// minIndexForVisible is bumped by 1 when a ListHeaderComponent occupies child 0.
|
|
487
525
|
if (maintainVisibleContentPosition !== undefined) {
|
|
@@ -491,16 +529,23 @@ export function VirtualizedList(props) {
|
|
|
491
529
|
(header !== undefined ? 1 : 0),
|
|
492
530
|
};
|
|
493
531
|
}
|
|
494
|
-
// Pull-to-refresh: when onRefresh is set,
|
|
495
|
-
//
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
532
|
+
// Pull-to-refresh: when onRefresh is set, the RefreshControl is an ordinary FIRST CHILD on both
|
|
533
|
+
// platforms rather than a prop. The scroll behavior CLAIMS it, so the engine keeps it beside the
|
|
534
|
+
// content view on iOS and inverts the tree on Android; everything after it lands in the content
|
|
535
|
+
// node the behavior built. refreshing is RN-required alongside onRefresh, default false.
|
|
536
|
+
const refreshControl = onRefresh !== undefined
|
|
537
|
+
? createElement('refresh-control', {
|
|
538
|
+
key: 'refresh-control',
|
|
499
539
|
refreshing: refreshing ?? false,
|
|
500
540
|
onRefresh,
|
|
501
541
|
progressViewOffset,
|
|
502
|
-
})
|
|
542
|
+
})
|
|
543
|
+
: undefined;
|
|
544
|
+
if (refreshControl !== undefined) {
|
|
545
|
+
dlog('VirtualizedList wiring RefreshControl (onRefresh provided)');
|
|
503
546
|
}
|
|
504
|
-
// The
|
|
505
|
-
|
|
547
|
+
// The scroll TAG, not a wrapper: the engine builds the content node, carries
|
|
548
|
+
// `contentContainerStyle` onto it and places the refresh control. `ref` hands back the engine
|
|
549
|
+
// node, which is what `buildScrollViewHandle` drives for the imperative scrolls.
|
|
550
|
+
return createElement(horizontal ? 'horizontal-scroll-view' : 'scroll-view', { ...scrollProps, ref: scrollNodeRef }, refreshControl, ...children);
|
|
506
551
|
}
|
package/build/components.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Ref, ReactNode } from 'react';
|
|
2
2
|
import type { ISymbioteEvent } from '@symbiote-native/engine';
|
|
3
3
|
import type { IHostInstance } from './host-instance';
|
|
4
|
-
import {
|
|
4
|
+
import type { IAccessibilityProps, IAriaProps } from '@symbiote-native/components';
|
|
5
5
|
import type { IResponderProps } from './utils/responder-props';
|
|
6
6
|
import type { IStyleProp, ITextStyle, IViewStyle } from './utils/styles';
|
|
7
7
|
export interface IViewProps extends IAccessibilityProps, IAriaProps, IResponderProps {
|
|
@@ -42,6 +42,7 @@ export interface ITextProps extends IAccessibilityProps, IAriaProps {
|
|
|
42
42
|
numberOfLines?: number;
|
|
43
43
|
ellipsizeMode?: 'head' | 'middle' | 'tail' | 'clip';
|
|
44
44
|
selectable?: boolean;
|
|
45
|
+
disabled?: boolean;
|
|
45
46
|
adjustsFontSizeToFit?: boolean;
|
|
46
47
|
minimumFontScale?: number;
|
|
47
48
|
allowFontScaling?: boolean;
|
|
@@ -50,5 +51,3 @@ export interface ITextProps extends IAccessibilityProps, IAriaProps {
|
|
|
50
51
|
ref?: Ref<IHostInstance>;
|
|
51
52
|
children?: ReactNode;
|
|
52
53
|
}
|
|
53
|
-
export declare const View: FC<IViewProps>;
|
|
54
|
-
export declare const Text: FC<ITextProps>;
|
package/build/components.js
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// view
|
|
5
|
-
|
|
6
|
-
import { resolveAccessibilityProps, resolveTextProps, } from '@symbiote-native/components';
|
|
7
|
-
// RN's modern `id` is just a W3C-named alias for `nativeID`: View.js copies it over
|
|
8
|
-
// (`processedProps.nativeID = id`), so `id` wins when both are set. We fold it here and
|
|
9
|
-
// blank the alias so a raw `id` never reaches Fabric (every non-function prop passes
|
|
10
|
-
// through to the slot otherwise).
|
|
11
|
-
function resolveId({ id, ...rest }) {
|
|
12
|
-
if (id === undefined)
|
|
13
|
-
return rest;
|
|
14
|
-
return { ...rest, nativeID: id };
|
|
15
|
-
}
|
|
16
|
-
export const View = props => createElement('symbiote-view', resolveAccessibilityProps(resolveId(props)));
|
|
17
|
-
export const Text = props => createElement('symbiote-text', resolveTextProps(resolveAccessibilityProps(props)));
|
|
1
|
+
// The public PROP TYPES for the two strict intrinsics, and nothing else. There is no component and
|
|
2
|
+
// no capitalized alias: an app writes `<view>` / `<text>`, React commits a host element directly,
|
|
3
|
+
// and `JSX.IntrinsicElements` (jsx-runtime.ts) is what supplies these types to it. The reconciler
|
|
4
|
+
// maps the tag through `descriptorFor` to a Fabric view name at commit.
|
|
5
|
+
export {};
|
|
@@ -14,7 +14,7 @@ import { isSymbioteNode, SymbioteSurface, } from '@symbiote-native/engine';
|
|
|
14
14
|
import reconciler from '../host-config.js';
|
|
15
15
|
export function createPortal(children, container, key) {
|
|
16
16
|
if (!(container instanceof SymbioteSurface) && !isSymbioteNode(container)) {
|
|
17
|
-
throw new Error('createPortal target must be an already-mounted host node (e.g. a ref to a rendered <
|
|
17
|
+
throw new Error('createPortal target must be an already-mounted host node (e.g. a ref to a rendered <view>) — got something else. Did you forget `.current`/`.value`, or pass a CSS-selector-style string?');
|
|
18
18
|
}
|
|
19
19
|
// @ts-expect-error @types/react-reconciler's ReactPortal (containerInfo/implementation) and
|
|
20
20
|
// react's own ReactPortal (type/props, a ReactElement) are different interfaces describing the
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx } from "@symbiote-native/react/jsx-runtime";
|
|
2
2
|
// createTunnel - the cross-surface answer to createPortal's same-surface-only scope. A real
|
|
3
3
|
// createPortal cannot reach across two separate reconciler roots (see
|
|
4
4
|
// github.com/facebook/react/issues/17147); the fix, same as pmndrs/tunnel-rat, is to not
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// The descriptor→element bridge. A render function in @symbiote-native/components returns a
|
|
2
2
|
// framework-agnostic `Descriptor` tree; this maps it onto React elements. The resulting
|
|
3
|
-
// host element (`
|
|
3
|
+
// host element (`view`, `activity-indicator`, …) flows on through the
|
|
4
4
|
// react-reconciler host config → engine → Fabric, exactly like a hand-written JSX host
|
|
5
5
|
// element.
|
|
6
6
|
import { createElement } from 'react';
|
package/build/host-config.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import createReconciler from 'react-reconciler';
|
|
2
2
|
import { SymbioteSurface, type ISymbioteNode } from '@symbiote-native/engine';
|
|
3
|
-
import { type IHostInstance } from './host-instance';
|
|
4
3
|
type IContainer = SymbioteSurface | ISymbioteNode;
|
|
5
4
|
export declare function withDiscretePriority(run: () => void): void;
|
|
6
|
-
declare const reconciler: createReconciler.Reconciler<IContainer, ISymbioteNode, ISymbioteNode, never, unknown,
|
|
5
|
+
declare const reconciler: createReconciler.Reconciler<IContainer, ISymbioteNode, ISymbioteNode, never, unknown, ISymbioteNode>;
|
|
6
|
+
export declare function flushExternalUpdate(run: () => void): void;
|
|
7
7
|
export default reconciler;
|
package/build/host-config.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// canary: a known-good driver exercising shared end to end.
|
|
5
5
|
import createReconciler from 'react-reconciler';
|
|
6
6
|
import { createContext } from 'react';
|
|
7
|
-
import { appendChild, createElement, createRawText, insertBefore, removeChild, routeProp, setNodeHidden, setText, SymbioteSurface, } from '@symbiote-native/engine';
|
|
7
|
+
import { appendChild, createElement, createRawText, insertBefore, removeChild, routeProp, setNodeComponent, setNodeHidden, setText, SymbioteSurface, } from '@symbiote-native/engine';
|
|
8
8
|
import { DefaultEventPriority, DiscreteEventPriority, NoEventPriority, } from './reconciler-constants.js';
|
|
9
9
|
import { toPublicInstance } from './host-instance.js';
|
|
10
10
|
// Intrinsic JSX type -> Fabric component name. The name table + resolver live once in
|
|
@@ -13,6 +13,14 @@ import { toPublicInstance } from './host-instance.js';
|
|
|
13
13
|
// Adding a primitive is one entry in each name table there, plus its thin
|
|
14
14
|
// component in components.ts: no host-config logic per primitive.
|
|
15
15
|
import { descriptorFor } from '@symbiote-native/components';
|
|
16
|
+
// A bare intrinsic tag has no wrapper to apply RN's per-primitive prop folds (id -> nativeID,
|
|
17
|
+
// Text's ellipsizeMode / allowFontScaling defaults), so the renderer is the layer that must.
|
|
18
|
+
// Shared with every other adapter, driven by the same HOST_PRIMITIVES spec.
|
|
19
|
+
import { foldHostBag } from '@symbiote-native/components/fold-host-bag';
|
|
20
|
+
// WHICH native view a primitive commits can depend on a prop (TextInput's `multiline`). A lowering
|
|
21
|
+
// transform decides that from source text; a bare tag has no transform, so the choice is made here,
|
|
22
|
+
// where the runtime value is known. Identity for every primitive that declares no alternative.
|
|
23
|
+
import { resolveIntrinsicTag } from '@symbiote-native/components/resolve-intrinsic';
|
|
16
24
|
// React-reserved prop keys that must never reach Fabric. `children` is the element
|
|
17
25
|
// tree (handled via appendChild). `ref`/`key` are React 19 plain props: the reconciler
|
|
18
26
|
// reads `props.ref` for commitAttachRef but does NOT strip it from the props it hands a
|
|
@@ -47,8 +55,9 @@ function isSurfaceContainer(container) {
|
|
|
47
55
|
return container instanceof SymbioteSurface;
|
|
48
56
|
}
|
|
49
57
|
let currentUpdatePriority = NoEventPriority;
|
|
50
|
-
// Run
|
|
51
|
-
//
|
|
58
|
+
// Run the callback at discrete priority. Native events and component-owned timers both enter
|
|
59
|
+
// React outside its render loop; callers pair this with flushExternalUpdate when the result must
|
|
60
|
+
// paint synchronously.
|
|
52
61
|
export function withDiscretePriority(run) {
|
|
53
62
|
const previous = currentUpdatePriority;
|
|
54
63
|
currentUpdatePriority = DiscreteEventPriority;
|
|
@@ -90,17 +99,35 @@ const reconciler = createReconciler({
|
|
|
90
99
|
},
|
|
91
100
|
shouldSetTextContent: () => false,
|
|
92
101
|
createInstance(type, props, _container, hostContext) {
|
|
93
|
-
|
|
102
|
+
// The INTRINSIC tag, kept in a binding rather than inlined, because it is needed twice: once
|
|
103
|
+
// to resolve the Fabric view name and once to hand the engine below. The host-behavior
|
|
104
|
+
// registry is keyed by TAG and never by Fabric name — `pressable` and a plain `View`
|
|
105
|
+
// both resolve to `RCTView`, so keying by the resolved name would put a press machine on every
|
|
106
|
+
// view in the app (`core/engine/src/host-behavior.ts`).
|
|
107
|
+
const tag = resolveIntrinsicTag(type, props);
|
|
108
|
+
const descriptor = descriptorFor(tag);
|
|
94
109
|
if (hostContext.isInsideText && !descriptor.isText) {
|
|
95
|
-
throw new Error(`<${type}> can't be nested inside <
|
|
110
|
+
throw new Error(`<${type}> can't be nested inside <text>`);
|
|
96
111
|
}
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
// The third argument is what makes a host behavior reachable AT ALL on this adapter. Dropping
|
|
113
|
+
// it degrades silently: `createElement`'s default is `tag = component`, so the lookup runs
|
|
114
|
+
// against `RCTView` / `RCTImageView`, matches nothing, and every behavior simply never
|
|
115
|
+
// attaches — no throw, no log, and no test goes red, because React ships no `register` entry
|
|
116
|
+
// today and so has never had a behavior to lose. That absence is exactly what hid this: the
|
|
117
|
+
// other four adapters all pass it (vue `renderer/index.ts`, svelte `dom-shim/element.ts`,
|
|
118
|
+
// solid `renderer.ts`, angular `renderer/index.ts`), and React is the one that did not.
|
|
119
|
+
//
|
|
120
|
+
// Inert on landing and deliberately so — nothing registers a behavior under a tag React emits.
|
|
121
|
+
// The `-managed` split is what keeps it inert once something does: React's TextInput and
|
|
122
|
+
// Switch wrappers emit `text-input-managed` / `switch-managed`, so a machine
|
|
123
|
+
// registered on the lowered tag cannot also attach to a wrapper-built node and run twice.
|
|
124
|
+
const node = createElement(descriptor.component, descriptor.isText, tag);
|
|
125
|
+
applyProps(node, foldHostBag(type, props));
|
|
99
126
|
return node;
|
|
100
127
|
},
|
|
101
128
|
createTextInstance(text, _container, hostContext) {
|
|
102
129
|
if (!hostContext.isInsideText) {
|
|
103
|
-
throw new Error(`Text string "${text}" must be rendered inside a <
|
|
130
|
+
throw new Error(`Text string "${text}" must be rendered inside a <text>`);
|
|
104
131
|
}
|
|
105
132
|
return createRawText(text);
|
|
106
133
|
},
|
|
@@ -127,8 +154,14 @@ const reconciler = createReconciler({
|
|
|
127
154
|
removeChild(container, child);
|
|
128
155
|
},
|
|
129
156
|
finalizeInitialChildren: () => false,
|
|
130
|
-
commitUpdate(node,
|
|
131
|
-
|
|
157
|
+
commitUpdate(node, type, oldProps, newProps) {
|
|
158
|
+
// A primitive whose native view depends on a prop (TextInput's `multiline`) can change view on
|
|
159
|
+
// an update. The node keeps its identity — an app's ref stays live — and the commit walk
|
|
160
|
+
// re-creates the Fabric node because its viewName no longer matches the committed one.
|
|
161
|
+
setNodeComponent(node, descriptorFor(resolveIntrinsicTag(type, newProps)).component);
|
|
162
|
+
// BOTH sides folded, or the diff compares a raw `id` against a folded `nativeID` and writes
|
|
163
|
+
// the alias twice while never clearing the raw key.
|
|
164
|
+
applyUpdate(node, foldHostBag(type, oldProps), foldHostBag(type, newProps));
|
|
132
165
|
},
|
|
133
166
|
commitTextUpdate(node, _oldText, newText) {
|
|
134
167
|
setText(node, newText);
|
|
@@ -174,4 +207,12 @@ const reconciler = createReconciler({
|
|
|
174
207
|
suspendInstance: () => { },
|
|
175
208
|
waitForCommitToBeReady: () => null,
|
|
176
209
|
});
|
|
210
|
+
// Native-event and timer callbacks both update React from outside the reconciler. Put the update
|
|
211
|
+
// on the discrete lane and synchronously commit it; otherwise a delayed Pressable transition can
|
|
212
|
+
// mutate state but remain visually stale until some unrelated later event flushes React work.
|
|
213
|
+
export function flushExternalUpdate(run) {
|
|
214
|
+
withDiscretePriority(run);
|
|
215
|
+
// @ts-expect-error flushSyncWork exists at runtime in react-reconciler 0.33
|
|
216
|
+
reconciler.flushSyncWork();
|
|
217
|
+
}
|
|
177
218
|
export default reconciler;
|
package/build/host-instance.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The public instance a host ref hands back, and the ref -> tag lookup. toPublicInstance and
|
|
2
2
|
// IHostInstance live in @symbiote-native/engine (every adapter inherits the same public instance);
|
|
3
3
|
// this module re-exports them so the React surface (findNodeHandle + IHostInstance, host-config's
|
|
4
|
-
//
|
|
4
|
+
// getPublicInstance) is unchanged. findNodeHandle stays React-specific: it is the
|
|
5
5
|
// RN-shaped "ref -> native tag" lookup over the engine's getNativeTag.
|
|
6
6
|
import { getNativeTag, isSymbioteNode, toPublicInstance, } from '@symbiote-native/engine';
|
|
7
7
|
export { toPublicInstance };
|
package/build/index.d.ts
CHANGED
|
@@ -1,37 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
import './register';
|
|
2
|
+
export type { ISymbioteIntrinsicTag } from './jsx-runtime';
|
|
2
3
|
export type { IViewProps, ITextProps } from './components';
|
|
3
4
|
export type { IAccessibilityProps, IAriaProps, IAccessibilityRole, IRole, IAccessibilityStateValue, IAccessibilityValue, IAccessibilityActionInfo, } from '@symbiote-native/components';
|
|
4
5
|
export type { IResponderProps } from './utils/responder-props';
|
|
5
|
-
export { Image
|
|
6
|
-
export
|
|
7
|
-
export {
|
|
8
|
-
export type {
|
|
9
|
-
export {
|
|
10
|
-
export type { IScrollViewProps, IScrollViewHandle, } from './components/scroll-view';
|
|
11
|
-
export {
|
|
12
|
-
export type {
|
|
13
|
-
export {
|
|
14
|
-
export type { IInputAccessoryViewProps } from './components/input-accessory-view';
|
|
6
|
+
export { Image } from './modules/image';
|
|
7
|
+
export { setImageSourceResolver } from '@symbiote-native/components';
|
|
8
|
+
export type { IImageProps } from './components/image/image-props';
|
|
9
|
+
export type { IImageSource, IImageSourceProp, IResizeMode, IImageSize, IImageCacheStatus, } from '@symbiote-native/components';
|
|
10
|
+
export type { IImageBackgroundProps } from './components/image-background-props';
|
|
11
|
+
export type { IScrollViewProps, IScrollViewHandle, } from './components/scroll-view/scroll-view-props';
|
|
12
|
+
export type { ITextInputProps } from './components/text-input/text-input-props';
|
|
13
|
+
export type { ITextInputHandle, ITextInputChangeEvent, } from '@symbiote-native/components';
|
|
14
|
+
export type { IInputAccessoryViewProps } from './components/input-accessory-view-props';
|
|
15
15
|
export { KeyboardAvoidingView } from './components/keyboard-avoiding-view';
|
|
16
16
|
export type { IKeyboardAvoidingViewProps, IKeyboardAvoidingBehavior, } from './components/keyboard-avoiding-view';
|
|
17
17
|
export { StatusBar } from './modules/status-bar';
|
|
18
18
|
export type { IStatusBarProps, IStatusBarStyle } from './modules/status-bar';
|
|
19
|
-
export {
|
|
20
|
-
export type {
|
|
21
|
-
export {
|
|
22
|
-
export type {
|
|
23
|
-
export {
|
|
24
|
-
export type { ISafeAreaViewProps } from './components/safe-area-view';
|
|
25
|
-
export { RefreshControl } from './components/refresh-control';
|
|
26
|
-
export type { IRefreshControlProps } from './components/refresh-control';
|
|
19
|
+
export type { ISwitchProps } from './components/switch/switch-props';
|
|
20
|
+
export type { ISwitchTrackColor, ISwitchChangeEvent, } from '@symbiote-native/components';
|
|
21
|
+
export type { IActivityIndicatorProps } from './components/activity-indicator-props';
|
|
22
|
+
export type { ISafeAreaViewProps } from './components/safe-area-view-props';
|
|
23
|
+
export type { IRefreshControlProps } from './components/refresh-control-props';
|
|
27
24
|
export { Modal } from './components/modal';
|
|
28
25
|
export type { IModalProps, IModalAnimationType, IModalPresentationStyle, IModalOrientation, } from './components/modal';
|
|
29
|
-
export {
|
|
30
|
-
export type {
|
|
31
|
-
export {
|
|
32
|
-
export type {
|
|
33
|
-
export { Button } from './components/button';
|
|
34
|
-
export type { IButtonProps } from './components/button';
|
|
26
|
+
export type { IPressableProps, IPressState, } from './components/pressable/pressable-props';
|
|
27
|
+
export type { ITouchableOpacityProps, ITouchableHighlightProps, } from './components/touchable/touchable-props';
|
|
28
|
+
export type { ITouchableWithoutFeedbackProps } from './components/touchable-without-feedback/touchable-without-feedback-props';
|
|
29
|
+
export type { IButtonProps } from './components/button-props';
|
|
35
30
|
export { FlatList } from './components/flat-list';
|
|
36
31
|
export type { IFlatListProps, IFlatListHandle } from './components/flat-list';
|
|
37
32
|
export { SectionList } from './components/section-list';
|
|
@@ -67,7 +62,8 @@ export { PanResponder } from '@symbiote-native/engine';
|
|
|
67
62
|
export type { IPanResponderGestureState, IPanResponderCallbacks, IGestureResponderHandlers, IPanResponderInstance, } from '@symbiote-native/engine';
|
|
68
63
|
export { InteractionManager } from '@symbiote-native/engine';
|
|
69
64
|
export type { IInteractionEvent, ISimpleTask, IPromiseTask, ITask, IHandle, } from '@symbiote-native/engine';
|
|
70
|
-
export { TouchableNativeFeedback } from '
|
|
71
|
-
export type {
|
|
65
|
+
export { TouchableNativeFeedback } from '@symbiote-native/components';
|
|
66
|
+
export type { INativeFeedbackBackground, IThemeAttrBackground, IRippleBackground, } from '@symbiote-native/components';
|
|
67
|
+
export type { ITouchableNativeFeedbackProps } from './components/touchable-native-feedback/touchable-native-feedback-props';
|
|
72
68
|
export type { ISymbioteEvent, ISymbioteNode, IRootTag, } from '@symbiote-native/engine';
|
|
73
69
|
export type { ICellLayout, ISeparatorProps, ISeparators, IModalOrientationChangeEvent, IPressableAndroidRippleConfig, IEnterKeyHint, IInputMode, ISubmitBehavior, ITextInputSelection, IImageStatics, } from '@symbiote-native/components';
|
package/build/index.js
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
// @symbiote-native/react: a react-reconciler host config (mutation mode) over
|
|
2
2
|
// @symbiote-native/engine. React is a known-good driver: it proves the native pipe
|
|
3
3
|
// and the shared clone-on-write engine before any non-React adapter has to.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
// Bare side-effect import, deliberately NOT a re-export and deliberately not beside one of the
|
|
5
|
+
// same specifier: it installs the engine's host behaviors, which is what makes a bare
|
|
6
|
+
// `<pressable>` / `<text-input>` / `<switch>` carry its machine. Any other shape is dropped by
|
|
7
|
+
// Metro's inlineRequires in a release build — see register.ts.
|
|
8
|
+
import './register.js';
|
|
9
|
+
// `Image` is a TAG — `<image>` — and the name now carries only RN's STATICS
|
|
10
|
+
// (`Image.getSize(...)`), an imperative API with no view. The wrapper's whole source/style
|
|
11
|
+
// translation runs on the tag as the engine's `registerImageBehavior`.
|
|
12
|
+
export { Image } from './modules/image/index.js';
|
|
13
|
+
export { setImageSourceResolver } from '@symbiote-native/components';
|
|
10
14
|
export { KeyboardAvoidingView } from './components/keyboard-avoiding-view/index.js';
|
|
11
15
|
export { StatusBar } from './modules/status-bar';
|
|
12
|
-
export { Switch } from './components/switch';
|
|
13
|
-
export { ActivityIndicator } from './components/activity-indicator';
|
|
14
|
-
export { SafeAreaView } from './components/safe-area-view/index.js';
|
|
15
|
-
export { RefreshControl } from './components/refresh-control/index.js';
|
|
16
16
|
export { Modal } from './components/modal/index.js';
|
|
17
|
-
export { Pressable } from './components/pressable/index.js';
|
|
18
|
-
export { TouchableOpacity, TouchableHighlight, TouchableWithoutFeedback, } from './components/touchable/index.js';
|
|
19
|
-
export { Button } from './components/button.js';
|
|
20
17
|
export { FlatList } from './components/flat-list/index.js';
|
|
21
18
|
export { SectionList } from './components/section-list/index.js';
|
|
22
19
|
export { VirtualizedSectionList } from './components/virtualized-section-list/index.js';
|
|
@@ -74,4 +71,7 @@ export { InteractionManager } from '@symbiote-native/engine';
|
|
|
74
71
|
// Android-only surface (the second-platform pass): a thin JS shim over an Android Fabric view,
|
|
75
72
|
// inert on iOS (no native view -> degrades to a plain container). The Android-only MODULES
|
|
76
73
|
// (ToastAndroid, PermissionsAndroid, BackHandler) sit in the engine block above.
|
|
77
|
-
|
|
74
|
+
// `TouchableNativeFeedback` is now RN's STATIC NAMESPACE, not a component: the element is the tag
|
|
75
|
+
// `<touchable-native-feedback>`, which commits no node of its own and clones onto its single child.
|
|
76
|
+
// `TouchableNativeFeedback.Ripple(…)` / `.SelectableBackground(…)` are unchanged.
|
|
77
|
+
export { TouchableNativeFeedback } from '@symbiote-native/components';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// The dev twin of `./jsx-runtime`, and it has to be its own file rather than an alias of it.
|
|
2
|
+
//
|
|
3
|
+
// TypeScript resolves the namespace from `<jsxImportSource>/jsx-dev-runtime` whenever `jsx` is
|
|
4
|
+
// `react-jsxdev`, and Babel's automatic runtime imports `jsxDEV` — not `jsx`/`jsxs` — from that
|
|
5
|
+
// same path in a development build. Solid points both subpaths at one file because its emitted
|
|
6
|
+
// runtime is empty either way; ours carries real factories, so the two entries export different
|
|
7
|
+
// names and pointing them at one file would leave a dev build importing a `jsxDEV` that is not
|
|
8
|
+
// there.
|
|
9
|
+
export { jsxDEV } from 'react/jsx-dev-runtime';
|
|
10
|
+
export { Fragment } from 'react/jsx-runtime';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const JSX_NAMESPACE_CHECK: number;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@symbiote-native/react/jsx-runtime";
|
|
2
|
+
const strictIntrinsicAcceptsItsOwnProp = (_jsx("view", { testID: "jsx-namespace-check" }));
|
|
3
|
+
const strictIntrinsicRejectsAnUnknownProp = (_jsx("view", { definitelyNotAViewProp: 1 }));
|
|
4
|
+
export const JSX_NAMESPACE_CHECK = [
|
|
5
|
+
strictIntrinsicAcceptsItsOwnProp,
|
|
6
|
+
strictIntrinsicRejectsAnUnknownProp,
|
|
7
|
+
].length;
|