@symbiote-native/vue 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 (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -0
  3. package/build/components/activity-indicator/index.android.d.ts +4 -0
  4. package/build/components/activity-indicator/index.android.js +10 -0
  5. package/build/components/activity-indicator/index.d.ts +1 -0
  6. package/build/components/activity-indicator/index.ios.d.ts +4 -0
  7. package/build/components/activity-indicator/index.ios.js +10 -0
  8. package/build/components/activity-indicator/index.js +4 -0
  9. package/build/components/activity-indicator/shared.d.ts +8 -0
  10. package/build/components/activity-indicator/shared.js +48 -0
  11. package/build/components/button.d.ts +14 -0
  12. package/build/components/button.js +59 -0
  13. package/build/components/drawer-layout-android/index.android.d.ts +8 -0
  14. package/build/components/drawer-layout-android/index.android.js +144 -0
  15. package/build/components/drawer-layout-android/index.d.ts +8 -0
  16. package/build/components/drawer-layout-android/index.js +36 -0
  17. package/build/components/drawer-layout-android/shared.d.ts +18 -0
  18. package/build/components/drawer-layout-android/shared.js +6 -0
  19. package/build/components/flat-list/index.d.ts +88 -0
  20. package/build/components/flat-list/index.js +189 -0
  21. package/build/components/image-background.d.ts +9 -0
  22. package/build/components/image-background.js +114 -0
  23. package/build/components/image.d.ts +9 -0
  24. package/build/components/image.js +99 -0
  25. package/build/components/input-accessory-view.d.ts +10 -0
  26. package/build/components/input-accessory-view.js +41 -0
  27. package/build/components/keyboard-avoiding-view.d.ts +18 -0
  28. package/build/components/keyboard-avoiding-view.js +121 -0
  29. package/build/components/modal.d.ts +29 -0
  30. package/build/components/modal.js +134 -0
  31. package/build/components/pressable.d.ts +58 -0
  32. package/build/components/pressable.js +221 -0
  33. package/build/components/refresh-control.d.ts +20 -0
  34. package/build/components/refresh-control.js +53 -0
  35. package/build/components/safe-area-view.d.ts +8 -0
  36. package/build/components/safe-area-view.js +33 -0
  37. package/build/components/scroll-view/index.android.d.ts +4 -0
  38. package/build/components/scroll-view/index.android.js +74 -0
  39. package/build/components/scroll-view/index.d.ts +1 -0
  40. package/build/components/scroll-view/index.ios.d.ts +4 -0
  41. package/build/components/scroll-view/index.ios.js +15 -0
  42. package/build/components/scroll-view/index.js +4 -0
  43. package/build/components/scroll-view/shared.d.ts +96 -0
  44. package/build/components/scroll-view/shared.js +297 -0
  45. package/build/components/scroll-view/sticky-header.d.ts +7 -0
  46. package/build/components/scroll-view/sticky-header.js +195 -0
  47. package/build/components/section-list/index.d.ts +39 -0
  48. package/build/components/section-list/index.js +77 -0
  49. package/build/components/switch/index.android.d.ts +12 -0
  50. package/build/components/switch/index.android.js +13 -0
  51. package/build/components/switch/index.d.ts +2 -0
  52. package/build/components/switch/index.ios.d.ts +12 -0
  53. package/build/components/switch/index.ios.js +11 -0
  54. package/build/components/switch/index.js +5 -0
  55. package/build/components/switch/shared.d.ts +23 -0
  56. package/build/components/switch/shared.js +129 -0
  57. package/build/components/text-input/index.d.ts +24 -0
  58. package/build/components/text-input/index.js +257 -0
  59. package/build/components/touchable-native-feedback.d.ts +24 -0
  60. package/build/components/touchable-native-feedback.js +75 -0
  61. package/build/components/touchable.d.ts +44 -0
  62. package/build/components/touchable.js +150 -0
  63. package/build/components/virtualized-list/index.d.ts +121 -0
  64. package/build/components/virtualized-list/index.js +687 -0
  65. package/build/components/virtualized-section-list/index.d.ts +96 -0
  66. package/build/components/virtualized-section-list/index.js +160 -0
  67. package/build/components.d.ts +51 -0
  68. package/build/components.js +26 -0
  69. package/build/composables/use-color-scheme.d.ts +3 -0
  70. package/build/composables/use-color-scheme.js +24 -0
  71. package/build/composables/use-window-dimensions.d.ts +3 -0
  72. package/build/composables/use-window-dimensions.js +34 -0
  73. package/build/create-tunnel.d.ts +9 -0
  74. package/build/create-tunnel.js +37 -0
  75. package/build/descriptor-to-vue.d.ts +3 -0
  76. package/build/descriptor-to-vue.js +14 -0
  77. package/build/host-instance/index.d.ts +2 -0
  78. package/build/host-instance/index.js +34 -0
  79. package/build/index.d.ts +67 -0
  80. package/build/index.js +90 -0
  81. package/build/modules/animated/create-animated-component.d.ts +4 -0
  82. package/build/modules/animated/create-animated-component.js +169 -0
  83. package/build/modules/animated/index.d.ts +55 -0
  84. package/build/modules/animated/index.js +66 -0
  85. package/build/modules/app-registry/index.d.ts +7 -0
  86. package/build/modules/app-registry/index.js +32 -0
  87. package/build/modules/status-bar.d.ts +17 -0
  88. package/build/modules/status-bar.js +65 -0
  89. package/build/render.d.ts +7 -0
  90. package/build/render.js +43 -0
  91. package/build/renderer.d.ts +4 -0
  92. package/build/renderer.js +129 -0
  93. package/build/runtime-helpers.d.ts +28 -0
  94. package/build/runtime-helpers.js +68 -0
  95. package/build/utils/component-helpers.d.ts +2 -0
  96. package/build/utils/component-helpers.js +13 -0
  97. package/build/utils/model-binding.d.ts +4 -0
  98. package/build/utils/model-binding.js +17 -0
  99. package/build/utils/normalize-attrs.d.ts +1 -0
  100. package/build/utils/normalize-attrs.js +30 -0
  101. package/build/utils/slots-to-render-props.d.ts +4 -0
  102. package/build/utils/slots-to-render-props.js +18 -0
  103. package/metro-css-parser.cjs +12 -0
  104. package/package.json +54 -0
@@ -0,0 +1,129 @@
1
+ // A Vue 3 custom renderer over @symbiote-native/engine. Each RendererOptions method maps onto
2
+ // the engine's tiny mutation API; the engine owns all Fabric clone-on-write, so Vue
3
+ // drives the exact same retained tree React does: the proof the core is framework-
4
+ // agnostic (M3 / R4).
5
+ import { createRenderer } from '@vue/runtime-core';
6
+ import { appendChild, createAnchor, createElement, createRawText, dlog, insertBefore, removeChild, routeProp, setText, toPublicInstance, RAW_TEXT_COMPONENT, SymbioteSurface, } from '@symbiote-native/engine';
7
+ import { descriptorFor } from '@symbiote-native/components';
8
+ function isSurface(parent) {
9
+ return parent instanceof SymbioteSurface;
10
+ }
11
+ function isRawText(node) {
12
+ return node.component === RAW_TEXT_COMPONENT;
13
+ }
14
+ // One renderer per mounted surface: the options close over the surface so every mutation
15
+ // can ask it to (microtask-coalesced) recommit. Vue has no resetAfterCommit; instead
16
+ // requestCommit() collapses a burst of insert/patchProp within one tick into a single
17
+ // completeRoot, exactly the seam the engine already exposes for reactive frameworks.
18
+ export function createSymbioteRenderer(surface) {
19
+ const options = {
20
+ createElement(type) {
21
+ const descriptor = descriptorFor(type);
22
+ const node = createElement(descriptor.component, descriptor.isText);
23
+ // Graft the imperative public-instance API (measure / setNativeProps / focus / …) onto
24
+ // the raw node so a template/function ref to a host element exposes it exactly like
25
+ // React's getPublicInstance. toPublicInstance mutates in place and returns the SAME node
26
+ // identity, so the engine commit mirror (keyed on the raw node) still resolves it — the
27
+ // ref must keep holding this raw node by identity (shallowRef), never a deep ref. See the
28
+ // vue-adapter-reactivity skill.
29
+ dlog(`vue createElement ${descriptor.component} -> public instance`);
30
+ return toPublicInstance(node);
31
+ },
32
+ createText(text) {
33
+ // Vue mounts Fragment boundaries (v-for / v-if lists / multi-root) as EMPTY text
34
+ // nodes via hostCreateText(''), NOT comments, then inserts them into the (usually
35
+ // non-Text) container. A raw text outside a <Text> is invalid in Fabric, so an empty
36
+ // text here is never real content; it's a positional anchor. Map it to an engine
37
+ // anchor (skipped by the commit walk, no native view), exactly like createComment.
38
+ // Non-empty text is genuine RCTRawText content and must live inside a <Text>.
39
+ return text === '' ? createAnchor() : createRawText(text);
40
+ },
41
+ // Fragment / v-if / v-for placeholder. A real retained node so insert/nextSibling/
42
+ // parentNode ordering stays correct, but the engine's commit walk skips it: no
43
+ // native view is ever created. (wolf-tui fakes a comment with an empty text node;
44
+ // here an empty RCTRawText would actually paint, so an anchor is the right call.)
45
+ createComment() {
46
+ return createAnchor();
47
+ },
48
+ setText(node, text) {
49
+ setText(node, text);
50
+ surface.requestCommit();
51
+ },
52
+ setElementText(el, text) {
53
+ if (isSurface(el))
54
+ return;
55
+ // An RCTText carries its string as a single raw-text child. Reuse a lone existing
56
+ // one to avoid churn; otherwise replace all children with a fresh raw-text node.
57
+ const [first] = el.children;
58
+ if (el.children.length === 1 && first !== undefined && isRawText(first)) {
59
+ setText(first, text);
60
+ }
61
+ else {
62
+ for (const child of el.children.slice())
63
+ removeChild(el, child);
64
+ appendChild(el, createRawText(text));
65
+ }
66
+ surface.requestCommit();
67
+ },
68
+ insert(child, parent, anchor) {
69
+ if (isRawText(child) && (isSurface(parent) || !parent.isText)) {
70
+ throw new Error(`Text string "${String(child.props.text)}" must be rendered inside a <Text>`);
71
+ }
72
+ if (isSurface(parent)) {
73
+ if (anchor)
74
+ parent.insertBefore(child, anchor);
75
+ else
76
+ parent.appendChild(child);
77
+ }
78
+ else if (anchor) {
79
+ insertBefore(parent, child, anchor);
80
+ }
81
+ else {
82
+ appendChild(parent, child);
83
+ }
84
+ surface.requestCommit();
85
+ },
86
+ remove(child) {
87
+ // A top-level node has no parent (it lives in surface.children); everything else
88
+ // detaches from its retained parent.
89
+ const parent = child.parent;
90
+ if (parent !== undefined)
91
+ removeChild(parent, child);
92
+ else
93
+ surface.removeChild(child);
94
+ surface.requestCommit();
95
+ },
96
+ parentNode(node) {
97
+ return node.parent ?? surface;
98
+ },
99
+ nextSibling(node) {
100
+ const siblings = node.parent !== undefined ? node.parent.children : surface.children;
101
+ const index = siblings.indexOf(node);
102
+ return index >= 0 ? (siblings[index + 1] ?? null) : null;
103
+ },
104
+ patchProp(el, key, _prev, next) {
105
+ if (isSurface(el))
106
+ return;
107
+ // routeProp makes the prop-vs-event decision from the node's ViewConfig (onPress on
108
+ // a View becomes a listener; onTintColor on a Switch stays a prop): identical to
109
+ // the React host config, so the whole event layer is shared. `class`/`style` merge
110
+ // (explicit :style always winning over class-derived style, regardless of which of
111
+ // Vue's two independent patchProp calls lands last) is centralized in routeProp too
112
+ // (core/engine/src/node.ts) — every adapter gets it, not just this one.
113
+ routeProp(el, key, next);
114
+ surface.requestCommit();
115
+ },
116
+ // RN has no querySelector / scope-id / innerHTML. The first two are inert; static
117
+ // hoisting is meaningless without a raw-HTML host, so insertStaticContent degrades to
118
+ // an empty anchor pair (logged, never painting) rather than crashing Vue's contract.
119
+ querySelector: () => null,
120
+ setScopeId: () => { },
121
+ insertStaticContent(_content, parent, anchor) {
122
+ dlog('vue insertStaticContent unsupported — degrading to empty anchor');
123
+ const node = createAnchor();
124
+ options.insert(node, parent, anchor ?? null);
125
+ return [node, node];
126
+ },
127
+ };
128
+ return createRenderer(options);
129
+ }
@@ -0,0 +1,28 @@
1
+ export * from '@vue/runtime-core';
2
+ import { type ObjectDirective } from '@vue/runtime-core';
3
+ import { type ISymbioteNode } from '@symbiote-native/engine';
4
+ export declare const vShow: ObjectDirective<ISymbioteNode, boolean>;
5
+ export declare const Teleport: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
6
+ to: {
7
+ type: null;
8
+ default: null;
9
+ };
10
+ disabled: {
11
+ type: BooleanConstructor;
12
+ default: boolean;
13
+ };
14
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
15
+ [key: string]: any;
16
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
17
+ to: {
18
+ type: null;
19
+ default: null;
20
+ };
21
+ disabled: {
22
+ type: BooleanConstructor;
23
+ default: boolean;
24
+ };
25
+ }>> & Readonly<{}>, {
26
+ disabled: boolean;
27
+ to: any;
28
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,68 @@
1
+ // Metro rewrites every compiled `from 'vue'` import to point HERE instead of at bare
2
+ // `@vue/runtime-core` (see examples/*/metro-vue-transformer.js). Most of the compiler's injected
3
+ // helpers (ref, computed, withDirectives, openBlock, …) already live in runtime-core untouched —
4
+ // re-exported below. But two Vue template directives compile to a runtime-helper import that
5
+ // ONLY exists in `@vue/runtime-dom` (vShow, vModelText, vModelCheckbox, vModelSelect), written
6
+ // directly against a real HTMLElement (el.style.display, el.value, addEventListener). We have no
7
+ // DOM, so those don't exist for us — rewriting straight to runtime-core leaves `v-show` either
8
+ // failing at import time or silently resolving to `undefined` (a no-op directive). This module is
9
+ // the interception point: it supplies our OWN implementation under the same export name, so the
10
+ // compiler's import keeps resolving and the directive actually does something.
11
+ //
12
+ // See the vue-adapter-directives skill for the full rationale and scope (what this does and does
13
+ // NOT cover — native-element v-model is a separate, out-of-scope case).
14
+ export * from '@vue/runtime-core';
15
+ import { defineComponent, h, Teleport as VueTeleport, } from '@vue/runtime-core';
16
+ import { isSymbioteNode, setNativeProps, whenCommitted, } from '@symbiote-native/engine';
17
+ // setNativeProps merges a partial `style` object onto the node's current one (never clobbering
18
+ // other declarative style fields) and re-commits via the node's OWN tracked rootTag — no
19
+ // SymbioteSurface reference needed here, which a directive hook has no access to anyway.
20
+ //
21
+ // whenCommitted, not a direct call: Vue's `mounted` hook fires synchronously during the patch
22
+ // pass, but this renderer coalesces the actual Fabric commit onto a microtask
23
+ // (surface.requestCommit()), so the node may have no committed tag yet — the same async-commit
24
+ // race TextInput's autoFocus guards against (see vue-adapter-reactivity). A bare setNativeProps
25
+ // here would silently no-op with no retry on the very first mount.
26
+ const pendingShowCommits = new WeakMap();
27
+ function applyShow(el, value) {
28
+ pendingShowCommits.get(el)?.();
29
+ const cancel = whenCommitted(el, () => setNativeProps(el, { style: { display: value ? undefined : 'none' } }));
30
+ pendingShowCommits.set(el, cancel);
31
+ }
32
+ export const vShow = {
33
+ mounted: (el, { value }) => applyShow(el, value),
34
+ updated: (el, { value }) => applyShow(el, value),
35
+ // Drop a still-pending first-commit wait if the element unmounts before it ever lands.
36
+ unmounted: el => pendingShowCommits.get(el)?.(),
37
+ };
38
+ // Teleport's `to` in the DOM world is usually a CSS-selector string ('body', '#modal-root'); we
39
+ // have no querySelector (renderer.ts stubs it to null, same as insertStaticContent), so `to` here
40
+ // must be an already-mounted host node — e.g. a ref to a persistent "overlay host" View rendered
41
+ // once near the app root — not a selector string. This wrapper shadows runtime-core's own
42
+ // `Teleport` (which the SFC compiler imports from 'vue' like vShow) purely to validate `to` BEFORE
43
+ // handing it to the real Teleport: a wrong value (string, plain object, an unrendered/reactive-
44
+ // wrapped node) throws immediately here instead of silently corrupting the retained tree deep
45
+ // inside insert/remove — the "don't let a dev accidentally break everything" case this exists for.
46
+ // Scope: same-surface targets only (see the React createPortal twin, create-portal.ts) — Vue's own
47
+ // Teleport internals (disabled toggling, move-on-update) work unmodified once `to` resolves to a
48
+ // real ISymbioteNode, since insert/remove/parentNode/nextSibling are already fully generic.
49
+ export const Teleport = defineComponent({
50
+ name: 'Teleport',
51
+ inheritAttrs: false,
52
+ props: {
53
+ to: { type: null, default: null },
54
+ disabled: { type: Boolean, default: false },
55
+ },
56
+ setup(props, { slots }) {
57
+ return () => {
58
+ const { to } = props;
59
+ if (typeof to === 'string') {
60
+ throw new Error(`Teleport target must be a host node ref, not a CSS-selector string ("${to}") — symbiote has no querySelector. Pass a ref to an already-rendered element instead (e.g. <View ref="overlayHost" />, then :to="overlayHost").`);
61
+ }
62
+ if (to != null && !isSymbioteNode(to)) {
63
+ throw new Error('Teleport target is not a real host node — did you forget `.value` on a ref, or pass something symbiote never rendered?');
64
+ }
65
+ return h(VueTeleport, { to, disabled: props.disabled }, slots);
66
+ };
67
+ },
68
+ });
@@ -0,0 +1,2 @@
1
+ import type { ObjectEmitsOptions, SetupContext, SlotsType } from '@vue/runtime-core';
2
+ export type ICtx<E extends ObjectEmitsOptions = ObjectEmitsOptions, S extends Record<string, any> = Record<string, any>, SS = SetupContext<E | {}, SlotsType<S>>> = SS;
@@ -0,0 +1,13 @@
1
+ // Generic-component typing helpers for the Vue adapter.
2
+ //
3
+ // Vue's `defineComponent` has no overload for a GENERIC setup function with separate runtime
4
+ // options, so a component generic over an item type (the list family) cannot type its emit payloads
5
+ // off that generic the normal way. The escape hatch (the symbiote port of pd-web-kit's pattern): a
6
+ // generic setup FUNCTION `<T,>(props: IProps<T>, ctx: ICtx<IEmits<T>>) => render`, plus the runtime
7
+ // options passed as a second arg cast through `as unknown as undefined` (the cast is sanctioned ONLY
8
+ // here — it is the only way to express a generic component in plain TS; see CLAUDE.md no-`as` rule).
9
+ //
10
+ // `ICtx` is a thin wrapper over Vue's SetupContext that lets the generic emits type E flow through,
11
+ // so `emit('viewableItemsChanged', info)` types `info` as `IViewableItemsChangedInfo<T>` and the
12
+ // consumer's `@viewable-items-changed` payload is `T`, never `unknown`.
13
+ export {};
@@ -0,0 +1,4 @@
1
+ export declare function resolveModelValue<T>(attrs: Record<string, unknown>, isValid: (value: unknown) => value is T): T | undefined;
2
+ type IModelUpdateEmit<T> = ((event: 'update:modelValue', value: T) => void) & ((event: 'update:value', value: T) => void);
3
+ export declare function emitModelUpdate<T>(emit: IModelUpdateEmit<T>, value: T): void;
4
+ export {};
@@ -0,0 +1,17 @@
1
+ // v-model support for controlled-value components (TextInput, Switch, Slider, …). Vue's bare
2
+ // `v-model="x"` compiles to prop `modelValue` + emit `update:modelValue`; named `v-model:value="x"`
3
+ // compiles to prop `value` + emit `update:value`. These are independent compiler targets, not
4
+ // alternatives, so a component accepts either input and fires both update events rather than
5
+ // picking one. The RN-parity `value` prop/emit pair is untouched either way. See the
6
+ // vue-adapter-events skill (Rule 6) for the read-every-site gotcha this exists to solve.
7
+ export function resolveModelValue(attrs, isValid) {
8
+ if (isValid(attrs.modelValue))
9
+ return attrs.modelValue;
10
+ if (isValid(attrs.value))
11
+ return attrs.value;
12
+ return undefined;
13
+ }
14
+ export function emitModelUpdate(emit, value) {
15
+ emit('update:modelValue', value);
16
+ emit('update:value', value);
17
+ }
@@ -0,0 +1 @@
1
+ export declare function normalizeVueAttrs(attrs: Record<string, unknown>): Record<string, unknown>;
@@ -0,0 +1,30 @@
1
+ // Vue does NOT camelCase $attrs: a template `:content-container-style` arrives in attrs keyed
2
+ // 'content-container-style', but symbiote's prop contract is RN-camelCase (contentContainerStyle)
3
+ // and idiomatic Vue templates use kebab-case. Reading `attrs.contentContainerStyle` then misses,
4
+ // so a consumed prop is silently dropped (lost padding) and a non-consumed one leaks to Fabric
5
+ // (Android `JS Functions are not convertible to dynamic` when a VNode-valued prop forwards). So
6
+ // every adapter component normalizes its incoming attrs kebab→camel at entry.
7
+ //
8
+ // Two prefixes MUST stay kebab: `aria-*` (resolveAccessibilityProps reads 'aria-label' literally)
9
+ // and `data-*`. Event keys are already `onXxx` (Vue folds `@value-change` → onValueChange, no
10
+ // dash) so they pass through untouched.
11
+ const KEBAB_SEGMENT = /-([a-z])/g;
12
+ function toCamel(key) {
13
+ return key.replace(KEBAB_SEGMENT, (_match, char) => char.toUpperCase());
14
+ }
15
+ export function normalizeVueAttrs(attrs) {
16
+ let changed = false;
17
+ const out = {};
18
+ for (const key of Object.keys(attrs)) {
19
+ if (key.includes('-') && !key.startsWith('aria-') && !key.startsWith('data-')) {
20
+ out[toCamel(key)] = attrs[key];
21
+ changed = true;
22
+ }
23
+ else {
24
+ out[key] = attrs[key];
25
+ }
26
+ }
27
+ // Return the original object when nothing converted (the already-camel / TSX path): avoids a
28
+ // per-render allocation and keeps attrs identity stable.
29
+ return changed ? out : attrs;
30
+ }
@@ -0,0 +1,4 @@
1
+ import { type Component, type VNode } from '@vue/runtime-core';
2
+ type ISlotFn<Props extends Record<string, unknown>> = (props: Props) => VNode[] | VNode;
3
+ export declare function componentFromSlot<Props extends Record<string, unknown>>(slot: ISlotFn<Props> | undefined): Component | undefined;
4
+ export {};
@@ -0,0 +1,18 @@
1
+ // Bridges Vue scoped slots to the render-function / render-component surface the shared list
2
+ // windowing layer (@symbiote-native/components) expects. The Vue-facing list API is slots
3
+ // (#item / #separator / #header / #footer / #empty / #sectionHeader / #sectionFooter /
4
+ // #sectionSeparator) — the idiomatic Vue surface; React's twin is the renderItem /
5
+ // ItemSeparatorComponent prop family. This is the ONE place that translation lives, so a list's
6
+ // own body reads a single source (its slots), never a renderItem prop. Vue-only lifecycle glue,
7
+ // so it belongs in the adapter (adapters_stay_thin): the shared windowing math is untouched.
8
+ import {} from '@vue/runtime-core';
9
+ // A component-style renderer (ItemSeparatorComponent / SectionSeparatorComponent) is invoked by the
10
+ // list as h(component, props). Expose the slot as a functional component so its scope props reach
11
+ // the slot body. The cell renderer (#item) and the scopeless chrome slots (#header / #footer /
12
+ // #empty) need no wrapper — a slot fn is already a valid render fn / functional component.
13
+ export function componentFromSlot(slot) {
14
+ if (slot === undefined)
15
+ return undefined;
16
+ const fromSlot = (props) => slot(props);
17
+ return fromSlot;
18
+ }
@@ -0,0 +1,12 @@
1
+ // Re-exports @symbiote-native/css-parser verbatim from INSIDE this package, so a consuming app's own
2
+ // require('@symbiote-native/vue/metro-css-parser') resolves css-parser relative to THIS file's
3
+ // location (adapters/vue/node_modules, where css-parser IS a real dependency — see
4
+ // package.json), not relative to the app's own node_modules, which does not and should not
5
+ // need to declare @symbiote-native/css-parser itself. Node resolves each require() relative to the
6
+ // requiring FILE's own location, so this indirection is what actually removes the extra install
7
+ // step, not pnpm hoisting (which does not propagate this transitively across workspace packages
8
+ // the way a flat classic node_modules would). .cjs, not .js: this package is "type": "module",
9
+ // and Metro's babelTransformerPath loading expects a require()-able module. Used by
10
+ // examples/vue-sfc/metro-vue-transformer.js for BOTH its inline <style> block compilation and
11
+ // standalone .css/.module.css file imports. See the symbiote-sfc-style-compiler skill.
12
+ module.exports = require('@symbiote-native/css-parser');
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@symbiote-native/vue",
3
+ "version": "0.1.0",
4
+ "description": "SymbioteJS's Vue adapter — a @vue/runtime-core createRenderer driving real native iOS/Android views through the same engine as the React adapter.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/OneEyed1366/symbiote-native.git",
8
+ "directory": "adapters/vue"
9
+ },
10
+ "homepage": "https://github.com/OneEyed1366/symbiote-native/tree/master/adapters/vue#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/OneEyed1366/symbiote-native/issues"
13
+ },
14
+ "author": "Andrey Prokopenko <psevdoproger@gmail.com>",
15
+ "type": "module",
16
+ "main": "./build/index.js",
17
+ "module": "./build/index.js",
18
+ "types": "./build/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./build/index.d.ts",
22
+ "default": "./build/index.js"
23
+ },
24
+ "./runtime-helpers": {
25
+ "types": "./build/runtime-helpers.d.ts",
26
+ "default": "./build/runtime-helpers.js"
27
+ },
28
+ "./metro-css-parser": "./metro-css-parser.cjs"
29
+ },
30
+ "files": [
31
+ "build",
32
+ "metro-css-parser.cjs"
33
+ ],
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "dependencies": {
38
+ "@vue/runtime-core": "^3.5.13",
39
+ "@symbiote-native/css-parser": "0.1.0",
40
+ "@symbiote-native/engine": "0.1.0",
41
+ "@symbiote-native/components": "0.1.0"
42
+ },
43
+ "peerDependencies": {
44
+ "vue": ">=3.5.0",
45
+ "react-native": ">=0.86"
46
+ },
47
+ "devDependencies": {
48
+ "@symbiote-native/test-utils": "0.0.0"
49
+ },
50
+ "scripts": {
51
+ "typecheck": "tsc --build",
52
+ "format": "prettier --write \"src/**/*.{ts,tsx}\""
53
+ }
54
+ }