UNPKG

svelte-cross-frameworks

Version:
126 lines (118 loc) 3.65 kB
'use strict'; const React = require('react'); const Vue = require('vue'); function _interopNamespaceCompat(e) { if (e && typeof e === 'object' && 'default' in e) return e; const n = Object.create(null); if (e) { for (const k in e) { n[k] = e[k]; } } n.default = e; return n; } const React__namespace = /*#__PURE__*/_interopNamespaceCompat(React); const Vue__namespace = /*#__PURE__*/_interopNamespaceCompat(Vue); const conventionalEventHandlerPredicate = (maybeEventName) => { const match = maybeEventName.match(/^on([A-Z])(.*)/); if (match) { const [_, cap, ...resetEventName] = match; return cap.toLowerCase() + resetEventName.join(""); } return false; }; function extractEventMapFromProps(props, eventPredicate = conventionalEventHandlerPredicate) { return Object.keys(props).reduce( (registration, eventName) => { const predicated = eventPredicate(eventName); if (predicated && typeof predicated === "string") { registration.set(predicated, props[eventName]); } return registration; }, /* @__PURE__ */ new Map() ); } function createReactComponent(svelteComponent) { const ReactComponent = React__namespace.memo(React__namespace.forwardRef(function ReactComponent2(props, ref) { const targetRef = React__namespace.useRef(); const componentRef = React__namespace.useRef(); React__namespace.useImperativeHandle(ref, () => componentRef.current); const eventEntries = React__namespace.useMemo(() => Array.from(extractEventMapFromProps(props)), [props]); React__namespace.useEffect(() => { if (componentRef.current || !targetRef.current) { return; } componentRef.current = new svelteComponent({ target: targetRef.current, props }); return () => { componentRef.current?.$destroy?.(); componentRef.current = void 0; }; }, []); React__namespace.useEffect( () => { if (!componentRef.current) return; const offs = eventEntries.map(([eventName, handler]) => componentRef.current?.$on?.(eventName, handler)); return () => offs.forEach((off) => off?.()); }, [] ); React__namespace.useEffect(() => { componentRef.current?.$set?.(props); }, [props]); return React__namespace.createElement("div", { ref: targetRef }); })); ReactComponent.displayName = svelteComponent.name; return ReactComponent; } function createVueComponent(svelteComponent) { return Vue__namespace.defineComponent({ name: svelteComponent.name, data() { return { component: null, offs: [] }; }, computed: { eventEntries() { return Array.from(extractEventMapFromProps(this.$attrs)); } }, methods: { boundEvents() { this.offs = this.eventEntries.map(([eventName, handler]) => this.component?.$on?.(eventName, handler)); }, unboundEvents() { this.offs.forEach((off) => off?.()); } }, mounted() { if (!this.$refs.targetRef) { return; } this.component = new svelteComponent({ target: this.$refs.targetRef, props: this.$attrs }); }, unmounted() { this.unboundEvents(); this.component?.$destroy?.(); }, beforeUpdate() { this.unboundEvents(); }, updated() { this.component?.$set?.(this.$attrs); this.boundEvents(); }, render() { return Vue__namespace.h("div", { ref: "targetRef" }); } }); } exports.createReactComponent = createReactComponent; exports.createVueComponent = createVueComponent;