@zeus-js/output-react-wrapper 0.1.0-beta.3 → 0.1.0-beta.5

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.
@@ -1,10 +1,11 @@
1
1
  /**
2
- * output-react-wrapper v0.1.0-beta.3
2
+ * output-react-wrapper v0.1.0-beta.5
3
3
  * (c) 2026 baicie
4
4
  * Released under the MIT License.
5
5
  **/
6
6
  import { resolvePluginDts } from "@zeus-js/bundler-plugin";
7
7
  import { generateReactDts } from "@zeus-js/component-dts";
8
+ import { createComponent as createComponent$1 } from "@lit/react";
8
9
  //#region packages/web-c/output-react-wrapper/src/generateReactIndex.ts
9
10
  function generateReactIndex(components, options) {
10
11
  const lines = [];
@@ -16,211 +17,362 @@ function generateReactIndex(components, options) {
16
17
  return lines.join("\n");
17
18
  }
18
19
  //#endregion
19
- //#region packages/web-c/output-react-wrapper/src/naming.ts
20
- function toReactEventProp(eventName) {
21
- return "on" + eventName.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
22
- }
23
- //#endregion
24
20
  //#region packages/web-c/output-react-wrapper/src/generateReactWrapper.ts
25
21
  function generateReactWrapper(input) {
26
- const { mode = "minimal" } = input;
27
- if (mode === "minimal") return generateMinimalReactWrapper(input);
28
- return generateEventBridgeReactWrapper(input);
29
- }
30
- function createBindings(names, prefix) {
31
- return names.map((sourceName, index) => ({
32
- sourceName,
33
- localName: `${prefix}${index}`
34
- }));
35
- }
36
- function createEventBindings(eventNames) {
37
- return eventNames.map((eventName, index) => ({
38
- eventName,
39
- sourceName: toReactEventProp(eventName),
40
- localName: `eventHandler${index}`
41
- }));
42
- }
43
- function generateDestructuredBindings(bindings) {
44
- if (!bindings.length) return "";
45
- return bindings.map(({ sourceName, localName }) => {
46
- return `${JSON.stringify(sourceName)}: ${localName},`;
47
- }).join("\n ");
22
+ return input.mode === "runtime" ? generateRuntimeReactWrapper(input) : input.mode === "event-bridge" ? generateEventBridgeReactWrapper(input) : generateMinimalReactWrapper(input);
48
23
  }
49
24
  function generateMinimalReactWrapper(input) {
50
25
  const { component, namedSlots, wcModuleId } = input;
51
26
  const slotBindings = createBindings(getNamedSlots(component, namedSlots), "slotValue");
52
- const slotDestructure = slotBindings.length ? `\n ${generateDestructuredBindings(slotBindings)}` : "";
27
+ const omittedKeys = ["children", ...slotBindings.map(({ sourceName }) => sourceName)];
28
+ const slotAssignments = generatePropAssignments(slotBindings);
53
29
  const namedSlotLines = generateMinimalNamedSlots(slotBindings);
30
+ const childSetup = slotBindings.length ? `${namedSlotLines}
31
+ const childArgs = [];
32
+ pushAll(childArgs, slotNodes);
33
+ if (children != null) childArgs.push(children);` : "";
34
+ const render = slotBindings.length ? `React.createElement.apply(
35
+ React,
36
+ [${JSON.stringify(component.tag)}, rest].concat(childArgs),
37
+ )` : `React.createElement(${JSON.stringify(component.tag)}, rest, children)`;
54
38
  return `
55
39
  import * as React from 'react';
56
40
 
57
41
  import ${JSON.stringify(wcModuleId)};
58
42
 
43
+ const OMITTED_PROPS = new Set(${JSON.stringify(omittedKeys)});
44
+
59
45
  export const ${component.name} = React.forwardRef(
60
- function ${component.name}({
61
- children,${slotDestructure}
62
- ...rest
63
- } = {}, ref) {
64
- ${namedSlotLines}
65
- return React.createElement(
66
- ${JSON.stringify(component.tag)},
67
- {
68
- ...rest,
69
- ref,
70
- },
71
- ${namedSlotLines ? " ...slotNodes,\n" : ""} children,
72
- );
46
+ function ${component.name}(inputProps, ref) {
47
+ const props = inputProps || {};
48
+ const children = props.children;
49
+ ${slotAssignments}
50
+ const rest = omitProps(props);
51
+ rest.ref = ref;
52
+ ${childSetup}
53
+
54
+ return ${render};
73
55
  },
74
56
  );
57
+
58
+ function omitProps(source) {
59
+ const output = {};
60
+ for (const key in source) {
61
+ if (hasOwn(source, key) && !OMITTED_PROPS.has(key)) {
62
+ output[key] = source[key];
63
+ }
64
+ }
65
+ return output;
66
+ }
67
+
68
+ function hasOwn(source, key) {
69
+ return Object.prototype.hasOwnProperty.call(source, key);
70
+ }
71
+ ${slotBindings.length ? PUSH_ALL_HELPER : ""}
75
72
  `.trimStart();
76
73
  }
77
74
  function generateEventBridgeReactWrapper(input) {
78
75
  const { component, namedSlots, wcModuleId } = input;
79
76
  const propBindings = createBindings(Object.keys(component.props), "propValue");
80
- const eventBindings = createEventBindings(Object.keys(component.events));
77
+ const eventBindings = createEventBindings(component.events);
78
+ if (!propBindings.length && !eventBindings.length) return generateMinimalReactWrapper(input);
81
79
  const slotBindings = createBindings(getNamedSlots(component, namedSlots), "slotValue");
82
- const destructuredProps = generateDestructuredBindings([
80
+ const destructuredBindings = [
83
81
  ...propBindings,
84
82
  ...eventBindings,
85
83
  ...slotBindings
86
- ]);
84
+ ];
85
+ const omittedKeys = [
86
+ "children",
87
+ "className",
88
+ "style",
89
+ ...destructuredBindings.map(({ sourceName }) => sourceName)
90
+ ];
87
91
  return `
88
92
  import {
89
- createElement,
90
- cloneElement,
91
- Fragment,
92
- forwardRef,
93
- isValidElement,
94
- useEffect,
95
- useImperativeHandle,
96
- useRef,
93
+ ${[
94
+ "createElement",
95
+ ...slotBindings.length ? [
96
+ "cloneElement",
97
+ "Fragment",
98
+ "isValidElement"
99
+ ] : [],
100
+ "forwardRef",
101
+ ...propBindings.length || eventBindings.length ? ["useEffect"] : [],
102
+ "useImperativeHandle",
103
+ "useRef"
104
+ ].join(",\n ")},
97
105
  } from 'react';
98
106
 
99
107
  import ${JSON.stringify(wcModuleId)};
100
108
 
101
- export const ${component.name} = forwardRef(function ${component.name}(props, ref) {
102
- const {
103
- children,
104
- className,
105
- style,
106
- ${destructuredProps}
107
- ...rest
108
- } = props;
109
-
110
- const innerRef = useRef(null);
111
- const previousPropKeysRef = useRef(new Set());
112
-
113
- useImperativeHandle(ref, () => innerRef.current);
114
-
115
- ${generatePropSyncLines(propBindings)}
116
-
117
- ${generateEventEffects(eventBindings)}
109
+ const OMITTED_PROPS = new Set(${JSON.stringify(omittedKeys)});
110
+ ${eventBindings.length ? `const EVENT_NAMES = ${JSON.stringify(eventBindings.map((binding) => binding.eventName))};` : ""}
118
111
 
119
- const slotChildren = [];
112
+ export const ${component.name} = forwardRef(function ${component.name}(inputProps, ref) {
113
+ const props = inputProps || {};
114
+ const children = props.children;
115
+ const className = props.className;
116
+ const style = props.style;
117
+ ${generatePropAssignments(destructuredBindings)}
118
+ ${generatePropPresenceAssignments(propBindings)}
119
+ const rest = omitProps(props);
120
120
 
121
- ${generateNamedSlotRenderLines(slotBindings)}
121
+ const innerRef = useRef(null);
122
+ ${generatePropRefs(propBindings)}
123
+ ${generateEventRefs(eventBindings)}
124
+ useImperativeHandle(ref, () => innerRef.current, []);
122
125
 
123
- if (children != null) {
124
- slotChildren.push(children);
125
- }
126
+ ${generatePropSyncEffect(propBindings)}
127
+ ${generateEventEffect(eventBindings)}
128
+ ${generateChildrenSetup(slotBindings)}
129
+ rest.ref = innerRef;
130
+ rest.className = className;
131
+ rest.style = style;
126
132
 
127
- return createElement(
128
- ${JSON.stringify(component.tag)},
129
- {
130
- ...rest,
131
- ref: innerRef,
132
- className,
133
- style,
134
- },
135
- ...slotChildren,
136
- );
133
+ return ${generateReactRender(component.tag, slotBindings)};
137
134
  });
138
-
139
- function createNamedSlot(name, value) {
140
- if (value == null || value === false) return null;
141
-
142
- if (
143
- isValidElement(value) &&
144
- value.type !== Fragment
145
- ) {
146
- return cloneElement(value, { slot: name });
135
+ ${slotBindings.length ? NAMED_SLOT_HELPER : ""}
136
+ function omitProps(source) {
137
+ const output = {};
138
+ for (const key in source) {
139
+ if (hasOwn(source, key) && !OMITTED_PROPS.has(key)) {
140
+ output[key] = source[key];
141
+ }
147
142
  }
143
+ return output;
144
+ }
148
145
 
149
- return createElement(
150
- 'span',
151
- {
152
- slot: name,
153
- style: { display: 'contents' },
154
- },
155
- value,
156
- );
146
+ function hasOwn(source, key) {
147
+ return Object.prototype.hasOwnProperty.call(source, key);
157
148
  }
158
149
  `.trimStart();
159
150
  }
160
- function generatePropSyncLines(bindings) {
161
- if (!bindings.length) return "// no props";
162
- return `useEffect(() => {
151
+ function createBindings(names, prefix) {
152
+ return names.map((sourceName, index) => ({
153
+ sourceName,
154
+ localName: `${prefix}${index}`
155
+ }));
156
+ }
157
+ function createEventBindings(events) {
158
+ return Object.entries(events).map(([key, event], index) => {
159
+ var _event$key, _event$name, _event$reactName;
160
+ const sourceEventName = (_event$key = event.key) !== null && _event$key !== void 0 ? _event$key : key;
161
+ return {
162
+ eventName: (_event$name = event.name) !== null && _event$name !== void 0 ? _event$name : toKebabCase(sourceEventName),
163
+ sourceName: (_event$reactName = event.reactName) !== null && _event$reactName !== void 0 ? _event$reactName : toReactEventProp(sourceEventName),
164
+ localName: `eventHandler${index}`
165
+ };
166
+ });
167
+ }
168
+ function generatePropAssignments(bindings) {
169
+ return bindings.map(({ sourceName, localName }) => ` const ${localName} = props[${JSON.stringify(sourceName)}];`).join("\n");
170
+ }
171
+ function generatePropPresenceAssignments(bindings) {
172
+ return bindings.map(({ sourceName }, index) => ` const propPresent${index} = hasOwn(props, ${JSON.stringify(sourceName)});`).join("\n");
173
+ }
174
+ function generatePropRefs(bindings) {
175
+ if (!bindings.length) return "";
176
+ return ` const previousPropPresenceRef = useRef([]);
177
+ const previousPropValuesRef = useRef([]);`;
178
+ }
179
+ function generateEventRefs(bindings) {
180
+ if (!bindings.length) return "";
181
+ return ` const eventHandlersRef = useRef([]);
182
+ ${bindings.map(({ localName }, index) => ` eventHandlersRef.current[${index}] = ${localName};`).join("\n")}`;
183
+ }
184
+ function generatePropSyncEffect(bindings) {
185
+ if (!bindings.length) return "";
186
+ return ` useEffect(() => {
163
187
  const el = innerRef.current;
164
188
  if (!el) return;
165
189
 
166
- const previousPropKeys = previousPropKeysRef.current;
190
+ const previousPropPresence = previousPropPresenceRef.current;
191
+ const previousPropValues = previousPropValuesRef.current;
167
192
 
168
- ${bindings.map(({ sourceName, localName }) => {
193
+ ${bindings.map(({ sourceName, localName }, index) => {
169
194
  const key = JSON.stringify(sourceName);
170
- return `if (Object.prototype.hasOwnProperty.call(props, ${key})) {
171
- el[${key}] = ${localName};
172
- previousPropKeys.add(${key});
173
- } else if (previousPropKeys.has(${key})) {
195
+ return ` if (propPresent${index}) {
196
+ if (
197
+ !previousPropPresence[${index}] ||
198
+ !Object.is(previousPropValues[${index}], ${localName})
199
+ ) {
200
+ el[${key}] = ${localName};
201
+ previousPropValues[${index}] = ${localName};
202
+ }
203
+ previousPropPresence[${index}] = true;
204
+ } else if (previousPropPresence[${index}]) {
174
205
  el[${key}] = undefined;
175
- previousPropKeys.delete(${key});
206
+ previousPropPresence[${index}] = false;
207
+ previousPropValues[${index}] = undefined;
176
208
  }`;
177
- }).join("\n\n ")}
178
- }, [props, ${bindings.map((binding) => binding.localName).join(", ")}]);`;
209
+ }).join("\n\n")}
210
+ }, [${bindings.flatMap((binding, index) => [`propPresent${index}`, binding.localName]).join(", ")}]);
211
+ `;
179
212
  }
180
- function generateEventEffects(bindings) {
181
- return bindings.map(({ eventName, localName }) => {
182
- return `
183
- useEffect(() => {
213
+ function generateEventEffect(bindings) {
214
+ if (!bindings.length) return "";
215
+ return ` useEffect(() => {
184
216
  const el = innerRef.current;
185
- if (!el || !${localName}) return;
217
+ if (!el) return;
186
218
 
187
- const handler = event => {
188
- ${localName}(event);
189
- };
219
+ const listeners = EVENT_NAMES.map(
220
+ (_eventName, index) => event => {
221
+ const handler = eventHandlersRef.current[index];
222
+ if (handler) handler(event);
223
+ },
224
+ );
190
225
 
191
- el.addEventListener(${JSON.stringify(eventName)}, handler);
226
+ for (let index = 0; index < EVENT_NAMES.length; index += 1) {
227
+ el.addEventListener(EVENT_NAMES[index], listeners[index]);
228
+ }
192
229
 
193
230
  return () => {
194
- el.removeEventListener(${JSON.stringify(eventName)}, handler);
231
+ for (let index = 0; index < EVENT_NAMES.length; index += 1) {
232
+ el.removeEventListener(EVENT_NAMES[index], listeners[index]);
233
+ }
195
234
  };
196
- }, [${localName}]);
235
+ }, []);
197
236
  `;
198
- }).join("");
199
- }
200
- function getNamedSlots(component, namedSlots) {
201
- if (namedSlots === "none") return [];
202
- return Object.keys(component.slots).filter((name) => name !== "default");
203
237
  }
204
- function generateNamedSlotRenderLines(bindings) {
205
- return bindings.map(({ sourceName, localName }) => {
206
- return `
207
- {
238
+ function generateChildrenSetup(bindings) {
239
+ if (!bindings.length) return "";
240
+ return ` const slotChildren = [];
241
+ ${bindings.map(({ sourceName, localName }) => ` {
208
242
  const node = createNamedSlot(${JSON.stringify(sourceName)}, ${localName});
209
243
  if (node != null) slotChildren.push(node);
210
- }
244
+ }`).join("\n")}
245
+ if (children != null) slotChildren.push(children);
211
246
  `;
212
- }).join("");
247
+ }
248
+ function generateReactRender(tag, slotBindings) {
249
+ if (!slotBindings.length) return `createElement(${JSON.stringify(tag)}, rest, children)`;
250
+ return `createElement.apply(
251
+ null,
252
+ [${JSON.stringify(tag)}, rest].concat(slotChildren),
253
+ )`;
254
+ }
255
+ function getNamedSlots(component, namedSlots) {
256
+ return namedSlots === "none" ? [] : Object.keys(component.slots).filter((name) => name !== "default");
213
257
  }
214
258
  function generateMinimalNamedSlots(bindings) {
215
259
  if (!bindings.length) return "";
216
- return bindings.map(({ sourceName, localName }, index) => {
217
- return ` const ${`slotNode${index}`} = ${localName} != null && ${localName} !== false
260
+ return `${bindings.map(({ sourceName, localName }, index) => {
261
+ return ` const slotNode${index} = ${localName} != null && ${localName} !== false
218
262
  ? (React.isValidElement(${localName}) && ${localName}.type !== React.Fragment
219
263
  ? React.cloneElement(${localName}, { slot: ${JSON.stringify(sourceName)} })
220
264
  : React.createElement('span', { slot: ${JSON.stringify(sourceName)}, style: { display: 'contents' } }, ${localName}))
221
- : null;
265
+ : null;`;
266
+ }).join("\n")}
267
+ const slotNodes = [${bindings.map((_, index) => `slotNode${index}`).join(", ")}].filter(Boolean);`;
268
+ }
269
+ function toKebabCase(value) {
270
+ return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
271
+ }
272
+ function toReactEventProp(value) {
273
+ return `on${value.split("-").filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("")}`;
274
+ }
275
+ function generateRuntimeReactWrapper(input) {
276
+ const { component, namedSlots } = input;
277
+ const events = createRuntimeEventMap(component);
278
+ const slots = getNamedSlots(component, namedSlots);
279
+ return [
280
+ `import React from 'react'`,
281
+ `import { createComponent } from '@zeus-js/output-react-wrapper/runtime'`,
282
+ `import { defineCustomElement } from '../wc/loader.js'`,
283
+ ``,
284
+ `export const ${component.name} = createComponent({`,
285
+ ` react: React,`,
286
+ ` tagName: ${JSON.stringify(component.tag)},`,
287
+ ` defineCustomElement: () => defineCustomElement(${JSON.stringify(component.tag)}),`,
288
+ ` events: ${formatEventObject(events)},`,
289
+ ` slots: ${JSON.stringify(slots)},`,
290
+ ` displayName: ${JSON.stringify(component.name)},`,
291
+ `})`,
292
+ ``
293
+ ].join("\n");
294
+ }
295
+ function createRuntimeEventMap(component) {
296
+ const events = {};
297
+ for (const [key, event] of Object.entries(component.events)) {
298
+ var _event$key2, _event$name2, _event$reactName2;
299
+ const sourceEventName = (_event$key2 = event.key) !== null && _event$key2 !== void 0 ? _event$key2 : key;
300
+ const domEventName = (_event$name2 = event.name) !== null && _event$name2 !== void 0 ? _event$name2 : toKebabCase(sourceEventName);
301
+ const reactPropName = (_event$reactName2 = event.reactName) !== null && _event$reactName2 !== void 0 ? _event$reactName2 : toReactEventProp(sourceEventName);
302
+ events[reactPropName] = domEventName;
303
+ }
304
+ return events;
305
+ }
306
+ function formatEventObject(value) {
307
+ const entries = Object.entries(value);
308
+ if (!entries.length) return "{}";
309
+ return `{\n${entries.map(([key, item]) => ` ${JSON.stringify(key)}: ${JSON.stringify(item)}`).join(",\n")}\n }`;
310
+ }
311
+ const PUSH_ALL_HELPER = `
312
+ function pushAll(target, values) {
313
+ for (const value of values) target.push(value);
314
+ }
315
+ `;
316
+ const NAMED_SLOT_HELPER = `
317
+ function createNamedSlot(name, value) {
318
+ if (value == null || value === false) return null;
319
+
320
+ if (isValidElement(value) && value.type !== Fragment) {
321
+ return cloneElement(value, { slot: name });
322
+ }
323
+
324
+ return createElement(
325
+ 'span',
326
+ { slot: name, style: { display: 'contents' } },
327
+ value,
328
+ );
329
+ }
222
330
  `;
223
- }).join("") + "\n const slotNodes = [" + bindings.map((_, index) => `slotNode${index}`).join(", ") + "].filter(Boolean);\n";
331
+ //#endregion
332
+ //#region packages/web-c/output-react-wrapper/src/runtime/createComponent.ts
333
+ function createComponent(options) {
334
+ var _customElements$get;
335
+ const { defineCustomElement, react, tagName, transformTag, elementClass, events = {}, slots = [], displayName } = options;
336
+ const finalTagName = transformTag ? transformTag(tagName) : tagName;
337
+ defineCustomElement === null || defineCustomElement === void 0 || defineCustomElement();
338
+ const LitComponent = createComponent$1({
339
+ react,
340
+ tagName: finalTagName,
341
+ elementClass: elementClass !== null && elementClass !== void 0 ? elementClass : typeof customElements === "undefined" ? HTMLElement : (_customElements$get = customElements.get(finalTagName)) !== null && _customElements$get !== void 0 ? _customElements$get : HTMLElement,
342
+ events,
343
+ displayName
344
+ });
345
+ if (!slots.length) return LitComponent;
346
+ const slotSet = new Set(slots);
347
+ return react.forwardRef((inputProps, ref) => {
348
+ const rest = {};
349
+ const slottedChildren = [];
350
+ if (inputProps == null) {
351
+ rest.ref = ref;
352
+ return react.createElement(LitComponent, rest);
353
+ }
354
+ const props = inputProps;
355
+ for (const key in props) {
356
+ if (!Object.prototype.hasOwnProperty.call(props, key)) continue;
357
+ const value = props[key];
358
+ if (slotSet.has(key)) {
359
+ const child = createNamedSlot(react, key, value);
360
+ if (child != null) slottedChildren.push(child);
361
+ continue;
362
+ }
363
+ rest[key] = value;
364
+ }
365
+ rest.ref = ref;
366
+ if (props.children != null) slottedChildren.push(props.children);
367
+ return react.createElement(LitComponent, rest, ...slottedChildren);
368
+ });
369
+ }
370
+ function createNamedSlot(react, name, value) {
371
+ if (value == null || value === false) return null;
372
+ return react.createElement("span", {
373
+ slot: name,
374
+ style: { display: "contents" }
375
+ }, value);
224
376
  }
225
377
  //#endregion
226
378
  //#region packages/web-c/output-react-wrapper/src/index.ts
@@ -233,7 +385,7 @@ function reactWrapper(options = {}) {
233
385
  dts: (_options$dts = options.dts) !== null && _options$dts !== void 0 ? _options$dts : true,
234
386
  index: (_options$index = options.index) !== null && _options$index !== void 0 ? _options$index : true,
235
387
  namedSlots: (_options$namedSlots = options.namedSlots) !== null && _options$namedSlots !== void 0 ? _options$namedSlots : "props",
236
- wrapper: (_options$wrapper = options.wrapper) !== null && _options$wrapper !== void 0 ? _options$wrapper : "minimal"
388
+ wrapper: (_options$wrapper = options.wrapper) !== null && _options$wrapper !== void 0 ? _options$wrapper : "runtime"
237
389
  };
238
390
  return {
239
391
  name: "zeus-output-react-wrapper",
@@ -276,4 +428,4 @@ function reactWrapper(options = {}) {
276
428
  };
277
429
  }
278
430
  //#endregion
279
- export { reactWrapper as default };
431
+ export { createComponent, reactWrapper as default };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * output-react-wrapper v0.1.0-beta.5
3
+ * (c) 2026 baicie
4
+ * Released under the MIT License.
5
+ **/
6
+ Object.defineProperties(exports, {
7
+ __esModule: { value: true },
8
+ [Symbol.toStringTag]: { value: "Module" }
9
+ });
10
+ let _lit_react = require("@lit/react");
11
+ //#region packages/web-c/output-react-wrapper/src/runtime/createComponent.ts
12
+ function createComponent(options) {
13
+ var _customElements$get;
14
+ const { defineCustomElement, react, tagName, transformTag, elementClass, events = {}, slots = [], displayName } = options;
15
+ const finalTagName = transformTag ? transformTag(tagName) : tagName;
16
+ defineCustomElement === null || defineCustomElement === void 0 || defineCustomElement();
17
+ const LitComponent = (0, _lit_react.createComponent)({
18
+ react,
19
+ tagName: finalTagName,
20
+ elementClass: elementClass !== null && elementClass !== void 0 ? elementClass : typeof customElements === "undefined" ? HTMLElement : (_customElements$get = customElements.get(finalTagName)) !== null && _customElements$get !== void 0 ? _customElements$get : HTMLElement,
21
+ events,
22
+ displayName
23
+ });
24
+ if (!slots.length) return LitComponent;
25
+ const slotSet = new Set(slots);
26
+ return react.forwardRef((inputProps, ref) => {
27
+ const rest = {};
28
+ const slottedChildren = [];
29
+ if (inputProps == null) {
30
+ rest.ref = ref;
31
+ return react.createElement(LitComponent, rest);
32
+ }
33
+ const props = inputProps;
34
+ for (const key in props) {
35
+ if (!Object.prototype.hasOwnProperty.call(props, key)) continue;
36
+ const value = props[key];
37
+ if (slotSet.has(key)) {
38
+ const child = createNamedSlot(react, key, value);
39
+ if (child != null) slottedChildren.push(child);
40
+ continue;
41
+ }
42
+ rest[key] = value;
43
+ }
44
+ rest.ref = ref;
45
+ if (props.children != null) slottedChildren.push(props.children);
46
+ return react.createElement(LitComponent, rest, ...slottedChildren);
47
+ });
48
+ }
49
+ function createNamedSlot(react, name, value) {
50
+ if (value == null || value === false) return null;
51
+ return react.createElement("span", {
52
+ slot: name,
53
+ style: { display: "contents" }
54
+ }, value);
55
+ }
56
+ //#endregion
57
+ exports.createComponent = createComponent;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * output-react-wrapper v0.1.0-beta.5
3
+ * (c) 2026 baicie
4
+ * Released under the MIT License.
5
+ **/
6
+ Object.defineProperties(exports, {
7
+ __esModule: { value: true },
8
+ [Symbol.toStringTag]: { value: "Module" }
9
+ });
10
+ let _lit_react = require("@lit/react");
11
+ //#region packages/web-c/output-react-wrapper/src/runtime/createComponent.ts
12
+ function createComponent(options) {
13
+ var _customElements$get;
14
+ const { defineCustomElement, react, tagName, transformTag, elementClass, events = {}, slots = [], displayName } = options;
15
+ const finalTagName = transformTag ? transformTag(tagName) : tagName;
16
+ defineCustomElement === null || defineCustomElement === void 0 || defineCustomElement();
17
+ const LitComponent = (0, _lit_react.createComponent)({
18
+ react,
19
+ tagName: finalTagName,
20
+ elementClass: elementClass !== null && elementClass !== void 0 ? elementClass : typeof customElements === "undefined" ? HTMLElement : (_customElements$get = customElements.get(finalTagName)) !== null && _customElements$get !== void 0 ? _customElements$get : HTMLElement,
21
+ events,
22
+ displayName
23
+ });
24
+ if (!slots.length) return LitComponent;
25
+ const slotSet = new Set(slots);
26
+ return react.forwardRef((inputProps, ref) => {
27
+ const rest = {};
28
+ const slottedChildren = [];
29
+ if (inputProps == null) {
30
+ rest.ref = ref;
31
+ return react.createElement(LitComponent, rest);
32
+ }
33
+ const props = inputProps;
34
+ for (const key in props) {
35
+ if (!Object.prototype.hasOwnProperty.call(props, key)) continue;
36
+ const value = props[key];
37
+ if (slotSet.has(key)) {
38
+ const child = createNamedSlot(react, key, value);
39
+ if (child != null) slottedChildren.push(child);
40
+ continue;
41
+ }
42
+ rest[key] = value;
43
+ }
44
+ rest.ref = ref;
45
+ if (props.children != null) slottedChildren.push(props.children);
46
+ return react.createElement(LitComponent, rest, ...slottedChildren);
47
+ });
48
+ }
49
+ function createNamedSlot(react, name, value) {
50
+ if (value == null || value === false) return null;
51
+ return react.createElement("span", {
52
+ slot: name,
53
+ style: { display: "contents" }
54
+ }, value);
55
+ }
56
+ //#endregion
57
+ exports.createComponent = createComponent;
@@ -0,0 +1,39 @@
1
+ export type EventName<T extends Event = Event> = string & {
2
+ __eventType: T;
3
+ };
4
+ type EventNames = Record<string, EventName | string>;
5
+ type ElementProps<I extends HTMLElement> = Partial<Omit<I, keyof HTMLElement>>;
6
+ type ReactRef<I extends HTMLElement> = ((instance: I | null) => void) | {
7
+ current: I | null;
8
+ } | null;
9
+ export interface ReactModule {
10
+ createElement: (...args: unknown[]) => unknown;
11
+ forwardRef: (...args: unknown[]) => unknown;
12
+ }
13
+ type EventListeners<E extends EventNames> = {
14
+ [K in keyof E]?: E[K] extends EventName<infer T> ? (event: T) => void : (event: Event) => void;
15
+ };
16
+ type ComponentProps<I extends HTMLElement, E extends EventNames> = {
17
+ children?: unknown;
18
+ className?: string;
19
+ ref?: ReactRef<I>;
20
+ style?: unknown;
21
+ } & {
22
+ [key: string]: unknown;
23
+ } & EventListeners<E> & ElementProps<I>;
24
+ export type ZeusReactComponent<I extends HTMLElement, E extends EventNames = {}> = (props: ComponentProps<I, E>) => unknown;
25
+ export interface ZeusReactCreateComponentOptions<I extends HTMLElement, E extends EventNames> {
26
+ tagName: string;
27
+ react: ReactModule;
28
+ defineCustomElement?: () => void;
29
+ elementClass?: {
30
+ new (): I;
31
+ };
32
+ events?: E;
33
+ slots?: string[];
34
+ displayName?: string;
35
+ transformTag?: (tagName: string) => string;
36
+ }
37
+ export declare function createComponent<I extends HTMLElement, E extends EventNames = {}>(options: ZeusReactCreateComponentOptions<I, E>): ZeusReactComponent<I, E>;
38
+
39
+