@luna_ui/luna 0.3.4 → 0.4.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 (182) hide show
  1. package/dist/cli.mjs +1264 -27
  2. package/dist/css/index.d.ts +194 -0
  3. package/dist/css/index.js +721 -0
  4. package/dist/css/runtime.d.ts +92 -0
  5. package/dist/css/runtime.js +179 -0
  6. package/dist/{index-CyEkcO3_.d.ts → index-CDWzWF-h.d.ts} +2 -2
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/jsx-dev-runtime.js +1 -1
  10. package/dist/jsx-runtime.d.ts +1 -1
  11. package/dist/jsx-runtime.js +1 -1
  12. package/dist/src-DEjrAhrg.js +1 -0
  13. package/dist/vite-plugin.d.ts +122 -0
  14. package/dist/vite-plugin.js +1518 -0
  15. package/package.json +16 -2
  16. package/src/css/extract.ts +798 -0
  17. package/src/css/index.ts +10 -0
  18. package/src/css/inject.ts +205 -0
  19. package/src/css/inline.ts +182 -0
  20. package/src/css/minify.ts +70 -0
  21. package/src/css/optimizer.ts +6 -0
  22. package/src/css/runtime.ts +344 -0
  23. package/src/css-optimizer/README.md +353 -0
  24. package/src/css-optimizer/cooccurrence.ts +100 -0
  25. package/src/css-optimizer/core.ts +263 -0
  26. package/src/css-optimizer/extractors.ts +243 -0
  27. package/src/css-optimizer/hash.ts +54 -0
  28. package/src/css-optimizer/index.ts +129 -0
  29. package/src/css-optimizer/merge.ts +109 -0
  30. package/src/css-optimizer/moonbit-analyzer.ts +210 -0
  31. package/src/css-optimizer/parser.ts +120 -0
  32. package/src/css-optimizer/pattern.ts +171 -0
  33. package/src/css-optimizer/transformers.ts +301 -0
  34. package/src/css-optimizer/types.ts +128 -0
  35. package/src/event-utils.ts +227 -0
  36. package/src/hydration/createHydrator.ts +62 -0
  37. package/src/hydration/delegate.ts +62 -0
  38. package/src/hydration/drag.ts +214 -0
  39. package/src/hydration/index.ts +12 -0
  40. package/src/hydration/keyboard.ts +64 -0
  41. package/src/hydration/toggle.ts +101 -0
  42. package/src/index.ts +890 -0
  43. package/src/jsx-dev-runtime.ts +2 -0
  44. package/src/jsx-runtime.ts +398 -0
  45. package/src/vite-plugin.ts +718 -0
  46. package/tests/__screenshots__/context.test.ts/Context-API-context-with-reactive-effects-context-value-accessible-in-effect-1.png +0 -0
  47. package/tests/__screenshots__/dom.test.ts/DOM-API-For-component--SolidJS-style--For-updates-when-signal-changes-1.png +0 -0
  48. package/tests/__screenshots__/dom.test.ts/DOM-API-Show-component--SolidJS-style--Show-accepts-children-as-function-1.png +0 -0
  49. package/tests/__screenshots__/dom.test.ts/DOM-API-Show-component--SolidJS-style--Show-toggles-visibility-1.png +0 -0
  50. package/tests/__screenshots__/dom.test.ts/DOM-API-createElement-createElement-with-dynamic-attribute-1.png +0 -0
  51. package/tests/__screenshots__/dom.test.ts/DOM-API-createElement-createElement-with-dynamic-style-1.png +0 -0
  52. package/tests/__screenshots__/dom.test.ts/DOM-API-createElementNs--SVG-support--createElementNs-with-dynamic-attribute-1.png +0 -0
  53. package/tests/__screenshots__/dom.test.ts/DOM-API-effect-with-DOM-effect-tracks-signal-changes-1.png +0 -0
  54. package/tests/__screenshots__/dom.test.ts/DOM-API-forEach--list-rendering--forEach-handles-clear-to-empty-1.png +0 -0
  55. package/tests/__screenshots__/dom.test.ts/DOM-API-forEach--list-rendering--forEach-handles-empty-array-1.png +0 -0
  56. package/tests/__screenshots__/dom.test.ts/DOM-API-forEach--list-rendering--forEach-removes-items-1.png +0 -0
  57. package/tests/__screenshots__/dom.test.ts/DOM-API-forEach--list-rendering--forEach-renders-initial-list-1.png +0 -0
  58. package/tests/__screenshots__/dom.test.ts/DOM-API-forEach--list-rendering--forEach-updates-when-items-change-1.png +0 -0
  59. package/tests/__screenshots__/dom.test.ts/DOM-API-forEach-with-SVG-elements-forEach-handles-empty-to-non-empty-transition-in-SVG-1.png +0 -0
  60. package/tests/__screenshots__/dom.test.ts/DOM-API-forEach-with-SVG-elements-forEach-handles-reordering-in-SVG-1.png +0 -0
  61. package/tests/__screenshots__/dom.test.ts/DOM-API-forEach-with-SVG-elements-forEach-updates-SVG-elements-when-signal-changes-1.png +0 -0
  62. package/tests/__screenshots__/dom.test.ts/DOM-API-forEach-with-SVG-elements-forEach-with-nested-SVG-groups-1.png +0 -0
  63. package/tests/__screenshots__/dom.test.ts/DOM-API-ref-callback--JSX-style--ref-callback-with-nested-elements-1.png +0 -0
  64. package/tests/__screenshots__/dom.test.ts/DOM-API-show--conditional-rendering--show-creates-a-node-1.png +0 -0
  65. package/tests/__screenshots__/dom.test.ts/DOM-API-show--conditional-rendering--show-with-false-condition-creates-placeholder-1.png +0 -0
  66. package/tests/__screenshots__/dom.test.ts/DOM-API-text-nodes-textDyn-creates-reactive-text-node-1.png +0 -0
  67. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-Complex-nested-scenario-forEach-renders-correctly-without-show--initial-items--1.png +0 -0
  68. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-Complex-nested-scenario-forEach-with-context-renders-correctly-without-show-1.png +0 -0
  69. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-Complex-nested-scenario-nested-components-with-context--forEach--and-show-1.png +0 -0
  70. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-Complex-nested-scenario-show-and-forEach-inherit-context-from-Owner--fixed--1.png +0 -0
  71. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-Complex-nested-scenario-show-and-forEach-work-together--context-uses-default--1.png +0 -0
  72. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-Context---ForEach-integration-forEach-items-can-access-context-1.png +0 -0
  73. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-ForEach-with-reactive-updates-forEach-renders-initial-list-1.png +0 -0
  74. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-ForEach-with-reactive-updates-forEach-updates-when-signal-changes-1.png +0 -0
  75. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-ForEach-with-reactive-updates-forEach-with-object-items-1.png +0 -0
  76. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-Show--conditional-rendering--show-hides-when-condition-is-false-1.png +0 -0
  77. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-Show--conditional-rendering--show-renders-when-condition-is-true-1.png +0 -0
  78. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-Show--conditional-rendering--show-toggles-from-false-to-true-1.png +0 -0
  79. package/tests/__screenshots__/integration.test.ts/Integration--Nested-Components-with-Context-Show--conditional-rendering--show-toggles-reactively-1.png +0 -0
  80. package/tests/__screenshots__/lifecycle.test.ts/onCleanup-in-Component-Body--Solid-js-style--event-listener-pattern--Solid-js-docs-example--1.png +0 -0
  81. package/tests/__screenshots__/lifecycle.test.ts/onCleanup-in-Component-Body--Solid-js-style--multiple-cleanups-in-component-body--LIFO-order--1.png +0 -0
  82. package/tests/__screenshots__/lifecycle.test.ts/onCleanup-in-Component-Body--Solid-js-style--onCleanup-in-component-body-runs-on-unmount-1.png +0 -0
  83. package/tests/__screenshots__/lifecycle.test.ts/onCleanup-in-Component-Body--Solid-js-style--onCleanup-works-with-For-loop-items--component-body-style--1.png +0 -0
  84. package/tests/__screenshots__/lifecycle.test.ts/onCleanup-in-Component-Body--Solid-js-style--timer-cleanup-pattern--Solid-js-style--1.png +0 -0
  85. package/tests/__screenshots__/lifecycle.test.ts/onCleanup-in-Effects-effect-cleanup-runs-before-re-run-1.png +0 -0
  86. package/tests/__screenshots__/preact-signals-comparison.test.ts/Bulk-Updates-large-list-update-1.png +0 -0
  87. package/tests/__screenshots__/preact-signals-comparison.test.ts/Bulk-Updates-nested-batch-operations-1.png +0 -0
  88. package/tests/__screenshots__/preact-signals-comparison.test.ts/Bulk-Updates-rapid-sequential-updates-1.png +0 -0
  89. package/tests/__screenshots__/preact-signals-comparison.test.ts/DOM-Rendering-Comparison---Conditional-Show-component---visible-1.png +0 -0
  90. package/tests/__screenshots__/preact-signals-comparison.test.ts/DOM-Rendering-Comparison---Conditional-show-hide-element---visible-1.png +0 -0
  91. package/tests/__screenshots__/preact-signals-comparison.test.ts/DOM-Rendering-Comparison---Fragments-fragment-with-list-1.png +0 -0
  92. package/tests/__screenshots__/preact-signals-comparison.test.ts/DOM-Rendering-Comparison---Fragments-nested-fragments-1.png +0 -0
  93. package/tests/__screenshots__/preact-signals-comparison.test.ts/DOM-Rendering-Comparison---Fragments-simple-fragment-1.png +0 -0
  94. package/tests/__screenshots__/preact-signals-comparison.test.ts/DOM-Rendering-Comparison---Reactive-Updates-conditional-toggle-updates-1.png +0 -0
  95. package/tests/__screenshots__/preact-signals-comparison.test.ts/DOM-Rendering-Comparison---Reactive-Updates-list-addition-updates-match-1.png +0 -0
  96. package/tests/__screenshots__/preact-signals-comparison.test.ts/DOM-Rendering-Comparison---Reactive-Updates-list-removal-updates-match-1.png +0 -0
  97. package/tests/__screenshots__/preact-signals-comparison.test.ts/DOM-Rendering-Comparison---Reactive-Updates-text-updates-match-1.png +0 -0
  98. package/tests/__screenshots__/preact-signals-comparison.test.ts/Dynamic-Attributes-Comparison-dynamic-className-updates-1.png +0 -0
  99. package/tests/__screenshots__/preact-signals-comparison.test.ts/Dynamic-Attributes-Comparison-dynamic-style-updates-1.png +0 -0
  100. package/tests/__screenshots__/preact-signals-comparison.test.ts/Dynamic-Attributes-Comparison-multiple-dynamic-attributes-1.png +0 -0
  101. package/tests/__screenshots__/preact-signals-comparison.test.ts/Edge-Cases-deeply-nested-conditionals-1.png +0 -0
  102. package/tests/__screenshots__/preact-signals-comparison.test.ts/Edge-Cases-list-transitions-from-empty-to-populated-1.png +0 -0
  103. package/tests/__screenshots__/preact-signals-comparison.test.ts/Edge-Cases-list-transitions-from-populated-to-empty-1.png +0 -0
  104. package/tests/__screenshots__/preact-signals-comparison.test.ts/Effect-Cleanup-Comparison-nested-effects-cleanup-order-1.png +0 -0
  105. package/tests/__screenshots__/preact-signals-comparison.test.ts/Effect-Cleanup-Comparison-nested-effects-with-inner-signal-change-1.png +0 -0
  106. package/tests/__screenshots__/preact-signals-comparison.test.ts/Effect-Cleanup-Comparison-onCleanup-is-called-when-effect-re-runs-1.png +0 -0
  107. package/tests/__screenshots__/preact-signals-comparison.test.ts/Effect-Cleanup-Comparison-onCleanup-with-resource-simulation-1.png +0 -0
  108. package/tests/__screenshots__/preact-signals-comparison.test.ts/Fragment-Comparison-with-Preact-Fragment-with-multiple-children--no-wrapper--1.png +0 -0
  109. package/tests/__screenshots__/preact-signals-comparison.test.ts/Fragment-Comparison-with-Preact-Fragment-with-no-children-1.png +0 -0
  110. package/tests/__screenshots__/preact-signals-comparison.test.ts/Fragment-Comparison-with-Preact-fragment-with-list-1.png +0 -0
  111. package/tests/__screenshots__/preact-signals-comparison.test.ts/Fragment-Comparison-with-Preact-nested-Fragments-work-correctly-1.png +0 -0
  112. package/tests/__screenshots__/preact-signals-comparison.test.ts/List-Reordering-complex-reordering-with-additions-and-removals-1.png +0 -0
  113. package/tests/__screenshots__/preact-signals-comparison.test.ts/List-Reordering-insert-in-middle-1.png +0 -0
  114. package/tests/__screenshots__/preact-signals-comparison.test.ts/List-Reordering-remove-from-middle-1.png +0 -0
  115. package/tests/__screenshots__/preact-signals-comparison.test.ts/List-Reordering-reverse-list-order-1.png +0 -0
  116. package/tests/__screenshots__/preact-signals-comparison.test.ts/List-Reordering-shuffle-list-1.png +0 -0
  117. package/tests/__screenshots__/preact-signals-comparison.test.ts/Luna-Conditional-Rendering-Show-component-renders-when-condition-is-true-1.png +0 -0
  118. package/tests/__screenshots__/preact-signals-comparison.test.ts/Luna-Conditional-Rendering-show-renders-content-when-initially-true-1.png +0 -0
  119. package/tests/__screenshots__/preact-signals-comparison.test.ts/Luna-Conditional-Rendering-show-toggles-visibility-dynamically-1.png +0 -0
  120. package/tests/__screenshots__/preact-signals-comparison.test.ts/Memo-Dependency-Chain-conditional-memo-dependencies-1.png +0 -0
  121. package/tests/__screenshots__/preact-signals-comparison.test.ts/Signal-Behavior-Comparison-basic-signal-get-set-produces-same-values-1.png +0 -0
  122. package/tests/__screenshots__/preact-signals-comparison.test.ts/Signal-Behavior-Comparison-batch-updates-produce-same-final-values-1.png +0 -0
  123. package/tests/__screenshots__/preact-signals-comparison.test.ts/Untrack-and-Peek-Behavior-peek-reads-value-without-tracking-1.png +0 -0
  124. package/tests/__screenshots__/preact-signals-comparison.test.ts/Untrack-and-Peek-Behavior-selective-tracking-with-untrack-1.png +0 -0
  125. package/tests/__screenshots__/preact-signals-comparison.test.ts/Untrack-and-Peek-Behavior-untrack-prevents-dependency-tracking-1.png +0 -0
  126. package/tests/__screenshots__/resource.test.ts/Resource-API--SolidJS-style--reactivity-accessor-is-reactive-1.png +0 -0
  127. package/tests/__screenshots__/resource.test.ts/Resource-API-AsyncState-helpers-stateError-returns-empty-string-for-non-failure-1.png +0 -0
  128. package/tests/__screenshots__/resource.test.ts/Resource-API-AsyncState-helpers-stateError-returns-undefined-for-non-failure-1.png +0 -0
  129. package/tests/__screenshots__/resource.test.ts/Resource-API-AsyncState-helpers-stateIsFailure-and-stateError-1.png +0 -0
  130. package/tests/__screenshots__/resource.test.ts/Resource-API-AsyncState-helpers-stateIsPending-1.png +0 -0
  131. package/tests/__screenshots__/resource.test.ts/Resource-API-AsyncState-helpers-stateIsSuccess-and-stateValue-1.png +0 -0
  132. package/tests/__screenshots__/resource.test.ts/Resource-API-AsyncState-helpers-stateValue-returns-undefined-for-non-success-1.png +0 -0
  133. package/tests/__screenshots__/resource.test.ts/Resource-API-createDeferred-reject-transitions-to-failure-1.png +0 -0
  134. package/tests/__screenshots__/resource.test.ts/Resource-API-createDeferred-resolve-transitions-to-success-1.png +0 -0
  135. package/tests/__screenshots__/resource.test.ts/Resource-API-createDeferred-returns-resource--resolve--and-reject-functions-1.png +0 -0
  136. package/tests/__screenshots__/resource.test.ts/Resource-API-createDeferred-starts-in-pending-state-1.png +0 -0
  137. package/tests/__screenshots__/resource.test.ts/Resource-API-createResource-async-resolve-works-1.png +0 -0
  138. package/tests/__screenshots__/resource.test.ts/Resource-API-createResource-starts-in-pending-state-1.png +0 -0
  139. package/tests/__screenshots__/resource.test.ts/Resource-API-createResource-transitions-to-failure-on-reject-1.png +0 -0
  140. package/tests/__screenshots__/resource.test.ts/Resource-API-createResource-transitions-to-success-on-resolve-1.png +0 -0
  141. package/tests/__screenshots__/resource.test.ts/Resource-API-integration-with-Promise-can-wrap-fetch-like-async-operations-1.png +0 -0
  142. package/tests/__screenshots__/resource.test.ts/Resource-API-integration-with-Promise-works-with-setTimeout-simulation-1.png +0 -0
  143. package/tests/__screenshots__/resource.test.ts/Resource-API-resourceGet-vs-resourcePeek-resourceGet-tracks-dependencies-1.png +0 -0
  144. package/tests/__screenshots__/resource.test.ts/Resource-API-resourceGet-vs-resourcePeek-resourcePeek-does-not-track-dependencies-1.png +0 -0
  145. package/tests/__screenshots__/resource.test.ts/Resource-API-resourceRefetch-refetch-resets-to-pending-and-re-runs-fetcher-1.png +0 -0
  146. package/tests/__screenshots__/solidjs-api.test.ts/Portal-component-Portal-renders-children-to-body-by-default-1.png +0 -0
  147. package/tests/__screenshots__/solidjs-api.test.ts/Portal-component-Portal-renders-to-selector-mount-target-1.png +0 -0
  148. package/tests/__screenshots__/solidjs-api.test.ts/SolidJS-API-compatibility-createEffect-tracks-dependencies-automatically-1.png +0 -0
  149. package/tests/__screenshots__/solidjs-api.test.ts/Switch-Match-component-Switch-with-accessor-condition-in-Match-1.png +0 -0
  150. package/tests/__screenshots__/solidjs-api.test.ts/Switch-Match-component-Switch-with-multiple-Match-components-1.png +0 -0
  151. package/tests/__screenshots__/solidjs-api.test.ts/Switch-Match-component-Switch-with-single-Match-and-fallback-1.png +0 -0
  152. package/tests/__screenshots__/solidjs-api.test.ts/Switch-Match-components-Switch-updates-DOM-when-signal-changes-1.png +0 -0
  153. package/tests/__screenshots__/solidjs-api.test.ts/on---utility-on-tracks-multiple-dependencies-1.png +0 -0
  154. package/tests/__screenshots__/solidjs-api.test.ts/on---utility-on-tracks-single-dependency-1.png +0 -0
  155. package/tests/__screenshots__/solidjs-api.test.ts/on---utility-on-with-defer-option-skips-initial-run-1.png +0 -0
  156. package/tests/__screenshots__/store.test.ts/createStore-Arrays-array-updates-work-1.png +0 -0
  157. package/tests/__screenshots__/store.test.ts/createStore-Reactivity-only-triggers-when-accessed-property-changes-1.png +0 -0
  158. package/tests/__screenshots__/store.test.ts/createStore-Reactivity-parent-path-change-notifies-child-accessors-1.png +0 -0
  159. package/tests/__screenshots__/store.test.ts/createStore-Reactivity-tracks-nested-property-access-1.png +0 -0
  160. package/tests/__screenshots__/store.test.ts/createStore-Reactivity-tracks-property-access-in-effects-1.png +0 -0
  161. package/tests/context.test.ts +118 -0
  162. package/tests/css-optimizer-extractors.test.ts +264 -0
  163. package/tests/css-optimizer-integration.test.ts +566 -0
  164. package/tests/css-optimizer-transformers.test.ts +301 -0
  165. package/tests/css-optimizer.test.ts +646 -0
  166. package/tests/css-runtime.bench.ts +442 -0
  167. package/tests/css-runtime.test.ts +342 -0
  168. package/tests/dom.test.ts +872 -0
  169. package/tests/integration.test.ts +405 -0
  170. package/tests/issue-5-for-infinite-loop.test.ts +516 -0
  171. package/tests/jsx-runtime.test.tsx +393 -0
  172. package/tests/lifecycle.test.ts +833 -0
  173. package/tests/move-before.bench.ts +304 -0
  174. package/tests/preact-signals-comparison.test.ts +1608 -0
  175. package/tests/resource.test.ts +160 -0
  176. package/tests/router.test.ts +117 -0
  177. package/tests/show-initial-mount-leak.test.tsx +182 -0
  178. package/tests/solidjs-api.test.ts +659 -0
  179. package/tests/static-perf.bench.ts +64 -0
  180. package/tests/store.test.ts +263 -0
  181. package/tests/tsx-syntax.test.tsx +404 -0
  182. package/dist/src-BDdxGwvq.js +0 -1
@@ -0,0 +1,2 @@
1
+ // JSX Dev Runtime - re-exports jsx-runtime for development mode
2
+ export { jsx, jsxs, Fragment, jsxDEV } from "./jsx-runtime";
@@ -0,0 +1,398 @@
1
+ // JSX Runtime for @luna_ui/luna
2
+ // Usage: Configure tsconfig.json with:
3
+ // "jsx": "react-jsx",
4
+ // "jsxImportSource": "@luna_ui/luna"
5
+
6
+ import { text, textDyn, createElement, Fragment as fragment } from "./index";
7
+
8
+ // Types for reactive attributes (can be static value or accessor function)
9
+ type MaybeAccessor<T> = T | (() => T);
10
+
11
+ // Common HTML attributes with reactive support
12
+ interface HTMLAttributes {
13
+ // Core attributes
14
+ id?: MaybeAccessor<string>;
15
+ className?: MaybeAccessor<string>;
16
+ class?: MaybeAccessor<string>;
17
+ style?: MaybeAccessor<string | Record<string, string | number>>;
18
+ title?: MaybeAccessor<string>;
19
+ tabIndex?: MaybeAccessor<number>;
20
+ hidden?: MaybeAccessor<boolean>;
21
+
22
+ // React-compatible innerHTML (use with caution)
23
+ // Static: dangerouslySetInnerHTML={{ __html: "<b>html</b>" }}
24
+ // Dynamic: dangerouslySetInnerHTML={() => ({ __html: htmlSignal() })}
25
+ dangerouslySetInnerHTML?: { __html: string } | (() => { __html: string });
26
+
27
+ // Form attributes
28
+ type?: MaybeAccessor<string>;
29
+ name?: MaybeAccessor<string>;
30
+ value?: MaybeAccessor<string | number>;
31
+ placeholder?: MaybeAccessor<string>;
32
+ disabled?: MaybeAccessor<boolean>;
33
+ checked?: MaybeAccessor<boolean>;
34
+ readonly?: MaybeAccessor<boolean>;
35
+ required?: MaybeAccessor<boolean>;
36
+ min?: MaybeAccessor<string | number>;
37
+ max?: MaybeAccessor<string | number>;
38
+ step?: MaybeAccessor<string | number>;
39
+ pattern?: MaybeAccessor<string>;
40
+
41
+ // Link/Media attributes
42
+ href?: MaybeAccessor<string>;
43
+ src?: MaybeAccessor<string>;
44
+ alt?: MaybeAccessor<string>;
45
+ target?: MaybeAccessor<string>;
46
+ rel?: MaybeAccessor<string>;
47
+
48
+ // ARIA attributes
49
+ role?: MaybeAccessor<string>;
50
+ "aria-label"?: MaybeAccessor<string>;
51
+ "aria-hidden"?: MaybeAccessor<boolean | "true" | "false">;
52
+ "aria-expanded"?: MaybeAccessor<boolean | "true" | "false">;
53
+ "aria-selected"?: MaybeAccessor<boolean | "true" | "false">;
54
+ "aria-disabled"?: MaybeAccessor<boolean | "true" | "false">;
55
+
56
+ // Data attributes
57
+ [key: `data-${string}`]: MaybeAccessor<string | number | boolean>;
58
+
59
+ // Event handlers
60
+ onClick?: (e: MouseEvent) => void;
61
+ onInput?: (e: Event) => void;
62
+ onChange?: (e: Event) => void;
63
+ onSubmit?: (e: Event) => void;
64
+ onKeyDown?: (e: KeyboardEvent) => void;
65
+ onKeyUp?: (e: KeyboardEvent) => void;
66
+ onKeyPress?: (e: KeyboardEvent) => void;
67
+ onFocus?: (e: FocusEvent) => void;
68
+ onBlur?: (e: FocusEvent) => void;
69
+ onMouseEnter?: (e: MouseEvent) => void;
70
+ onMouseLeave?: (e: MouseEvent) => void;
71
+ onMouseDown?: (e: MouseEvent) => void;
72
+ onMouseUp?: (e: MouseEvent) => void;
73
+ onMouseMove?: (e: MouseEvent) => void;
74
+ onTouchStart?: (e: TouchEvent) => void;
75
+ onTouchEnd?: (e: TouchEvent) => void;
76
+ onTouchMove?: (e: TouchEvent) => void;
77
+ onScroll?: (e: Event) => void;
78
+ onLoad?: (e: Event) => void;
79
+ onError?: (e: Event) => void;
80
+
81
+ // Ref callback
82
+ ref?: (el: HTMLElement) => void;
83
+
84
+ // Children
85
+ children?: JSX.Element | JSX.Element[] | string | number | (() => string | number);
86
+
87
+ // Allow any other attribute
88
+ [key: string]: unknown;
89
+ }
90
+
91
+ // Internal types for MoonBit interop
92
+ interface Attr {
93
+ _0: string;
94
+ _1: AttrValue;
95
+ }
96
+
97
+ interface AttrValue {
98
+ $tag: 0 | 1 | 2;
99
+ _0: unknown;
100
+ }
101
+
102
+ // Convert style object to CSS string
103
+ function styleToString(style: unknown): string {
104
+ if (typeof style === "string") return style;
105
+ if (typeof style !== "object" || style === null) return "";
106
+ return Object.entries(style)
107
+ .map(([key, value]) => {
108
+ // Convert camelCase to kebab-case
109
+ const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
110
+ return `${cssKey}: ${value}`;
111
+ })
112
+ .join("; ");
113
+ }
114
+
115
+ // Convert JSX props to createElement attrs format
116
+ function convertProps(props: Record<string, unknown> | null | undefined): Attr[] {
117
+ if (!props) return [];
118
+ const attrs: Attr[] = [];
119
+ for (const [key, value] of Object.entries(props)) {
120
+ if (key === "children") continue;
121
+
122
+ // Map JSX prop names to DOM attribute format
123
+ let attrName = key;
124
+ let attrValue: AttrValue;
125
+
126
+ // Handle className -> class
127
+ if (key === "className") {
128
+ attrName = "class";
129
+ }
130
+
131
+ // Handle dangerouslySetInnerHTML (React-compatible)
132
+ if (key === "dangerouslySetInnerHTML") {
133
+ if (typeof value === "function") {
134
+ // Dynamic innerHTML
135
+ const getter = value as () => { __html: string };
136
+ attrValue = { $tag: 1, _0: () => getter().__html }; // AttrValue.Dynamic
137
+ } else if (value && typeof value === "object" && "__html" in value) {
138
+ // Static innerHTML
139
+ attrValue = { $tag: 0, _0: (value as { __html: string }).__html }; // AttrValue.Static
140
+ } else {
141
+ continue; // Invalid format, skip
142
+ }
143
+ attrs.push({ _0: "__innerHTML", _1: attrValue });
144
+ continue;
145
+ }
146
+
147
+ // Handle style object -> CSS string
148
+ if (key === "style") {
149
+ if (typeof value === "function") {
150
+ // Dynamic style
151
+ const getter = value as () => unknown;
152
+ attrValue = { $tag: 1, _0: () => styleToString(getter()) }; // AttrValue.Dynamic
153
+ } else {
154
+ attrValue = { $tag: 0, _0: styleToString(value) }; // AttrValue.Static
155
+ }
156
+ attrs.push({ _0: attrName, _1: attrValue });
157
+ continue;
158
+ }
159
+
160
+ // Handle ref callback
161
+ if (key === "ref" && typeof value === "function") {
162
+ attrName = "__ref";
163
+ attrValue = { $tag: 2, _0: value }; // AttrValue.Handler
164
+ attrs.push({ _0: attrName, _1: attrValue });
165
+ continue;
166
+ }
167
+
168
+ // Handle event handlers (onClick -> click for addEventListener)
169
+ if (key.startsWith("on") && typeof value === "function") {
170
+ // Remove "on" prefix and lowercase first char: onClick -> click
171
+ attrName = key.slice(2).toLowerCase();
172
+ attrValue = { $tag: 2, _0: value }; // AttrValue.Handler
173
+ attrs.push({ _0: attrName, _1: attrValue });
174
+ continue;
175
+ }
176
+
177
+ // Handle dynamic values (functions)
178
+ // For reactive props, pass the accessor function directly: class={className}
179
+ if (typeof value === "function") {
180
+ attrValue = { $tag: 1, _0: value }; // AttrValue.Dynamic
181
+ } else {
182
+ attrValue = { $tag: 0, _0: String(value) }; // AttrValue.Static
183
+ }
184
+
185
+ attrs.push({ _0: attrName, _1: attrValue });
186
+ }
187
+ return attrs;
188
+ }
189
+
190
+ type Child = string | number | JSX.Element | (() => unknown) | Child[];
191
+
192
+ function convertChildren(children: unknown): unknown[] {
193
+ if (!children) return [];
194
+ let childArray: unknown[];
195
+ if (!Array.isArray(children)) {
196
+ childArray = [children];
197
+ } else {
198
+ childArray = children;
199
+ }
200
+ return childArray.flat().map((child) => {
201
+ if (typeof child === "string") {
202
+ return text(child);
203
+ }
204
+ if (typeof child === "number") {
205
+ return text(String(child));
206
+ }
207
+ // Handle functions:
208
+ // - No args (length === 0): signal accessor -> textDyn
209
+ // - With args (length > 0): render function -> pass through
210
+ if (typeof child === "function") {
211
+ if (child.length === 0) {
212
+ return textDyn(() => String(child()));
213
+ }
214
+ // Render function, pass through as-is
215
+ return child;
216
+ }
217
+ return child;
218
+ }).filter(Boolean);
219
+ }
220
+
221
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
222
+ type Component = (props: any) => JSX.Element;
223
+
224
+ // JSX factory function
225
+ export function jsx(type: string | Component, props: Record<string, unknown> | null): JSX.Element {
226
+ const { children, ...rest } = props || {};
227
+
228
+ // Function component - pass children as-is, don't convert
229
+ // This preserves functions like () => <Child /> for control flow components (Show, For, etc.)
230
+ if (typeof type === "function") {
231
+ return type({ ...rest, children });
232
+ }
233
+
234
+ // Element - convert children to DomNodes
235
+ if (typeof type === "string") {
236
+ const attrs = convertProps(rest);
237
+ const childNodes = convertChildren(children);
238
+ return createElement(type, attrs, childNodes) as JSX.Element;
239
+ }
240
+
241
+ throw new Error(`Invalid JSX type: ${type}`);
242
+ }
243
+
244
+ // jsxs is the same as jsx for our implementation
245
+ export const jsxs = jsx;
246
+
247
+ // Fragment wraps children in a DomNode fragment
248
+ export function Fragment({ children }: { children?: unknown }): unknown {
249
+ const childNodes = convertChildren(children);
250
+ // Use MoonBit's fragment function to create a proper DomNode fragment
251
+ return fragment(childNodes);
252
+ }
253
+
254
+ // Export jsxDEV for development mode
255
+ export const jsxDEV = jsx;
256
+
257
+ // Import LunaNode type from index
258
+ import type { LunaNode } from "./index";
259
+
260
+ // JSX namespace for TypeScript
261
+ export namespace JSX {
262
+ export type Element = LunaNode;
263
+ export interface IntrinsicElements {
264
+ // All HTML elements use HTMLAttributes with reactive support
265
+ a: HTMLAttributes;
266
+ abbr: HTMLAttributes;
267
+ address: HTMLAttributes;
268
+ area: HTMLAttributes;
269
+ article: HTMLAttributes;
270
+ aside: HTMLAttributes;
271
+ audio: HTMLAttributes;
272
+ b: HTMLAttributes;
273
+ base: HTMLAttributes;
274
+ bdi: HTMLAttributes;
275
+ bdo: HTMLAttributes;
276
+ blockquote: HTMLAttributes;
277
+ body: HTMLAttributes;
278
+ br: HTMLAttributes;
279
+ button: HTMLAttributes;
280
+ canvas: HTMLAttributes;
281
+ caption: HTMLAttributes;
282
+ cite: HTMLAttributes;
283
+ code: HTMLAttributes;
284
+ col: HTMLAttributes;
285
+ colgroup: HTMLAttributes;
286
+ data: HTMLAttributes;
287
+ datalist: HTMLAttributes;
288
+ dd: HTMLAttributes;
289
+ del: HTMLAttributes;
290
+ details: HTMLAttributes;
291
+ dfn: HTMLAttributes;
292
+ dialog: HTMLAttributes;
293
+ div: HTMLAttributes;
294
+ dl: HTMLAttributes;
295
+ dt: HTMLAttributes;
296
+ em: HTMLAttributes;
297
+ embed: HTMLAttributes;
298
+ fieldset: HTMLAttributes;
299
+ figcaption: HTMLAttributes;
300
+ figure: HTMLAttributes;
301
+ footer: HTMLAttributes;
302
+ form: HTMLAttributes;
303
+ h1: HTMLAttributes;
304
+ h2: HTMLAttributes;
305
+ h3: HTMLAttributes;
306
+ h4: HTMLAttributes;
307
+ h5: HTMLAttributes;
308
+ h6: HTMLAttributes;
309
+ head: HTMLAttributes;
310
+ header: HTMLAttributes;
311
+ hgroup: HTMLAttributes;
312
+ hr: HTMLAttributes;
313
+ html: HTMLAttributes;
314
+ i: HTMLAttributes;
315
+ iframe: HTMLAttributes;
316
+ img: HTMLAttributes;
317
+ input: HTMLAttributes;
318
+ ins: HTMLAttributes;
319
+ kbd: HTMLAttributes;
320
+ label: HTMLAttributes;
321
+ legend: HTMLAttributes;
322
+ li: HTMLAttributes;
323
+ link: HTMLAttributes;
324
+ main: HTMLAttributes;
325
+ map: HTMLAttributes;
326
+ mark: HTMLAttributes;
327
+ menu: HTMLAttributes;
328
+ meta: HTMLAttributes;
329
+ meter: HTMLAttributes;
330
+ nav: HTMLAttributes;
331
+ noscript: HTMLAttributes;
332
+ object: HTMLAttributes;
333
+ ol: HTMLAttributes;
334
+ optgroup: HTMLAttributes;
335
+ option: HTMLAttributes;
336
+ output: HTMLAttributes;
337
+ p: HTMLAttributes;
338
+ picture: HTMLAttributes;
339
+ pre: HTMLAttributes;
340
+ progress: HTMLAttributes;
341
+ q: HTMLAttributes;
342
+ rp: HTMLAttributes;
343
+ rt: HTMLAttributes;
344
+ ruby: HTMLAttributes;
345
+ s: HTMLAttributes;
346
+ samp: HTMLAttributes;
347
+ script: HTMLAttributes;
348
+ search: HTMLAttributes;
349
+ section: HTMLAttributes;
350
+ select: HTMLAttributes;
351
+ slot: HTMLAttributes;
352
+ small: HTMLAttributes;
353
+ source: HTMLAttributes;
354
+ span: HTMLAttributes;
355
+ strong: HTMLAttributes;
356
+ style: HTMLAttributes;
357
+ sub: HTMLAttributes;
358
+ summary: HTMLAttributes;
359
+ sup: HTMLAttributes;
360
+ table: HTMLAttributes;
361
+ tbody: HTMLAttributes;
362
+ td: HTMLAttributes;
363
+ template: HTMLAttributes;
364
+ textarea: HTMLAttributes;
365
+ tfoot: HTMLAttributes;
366
+ th: HTMLAttributes;
367
+ thead: HTMLAttributes;
368
+ time: HTMLAttributes;
369
+ title: HTMLAttributes;
370
+ tr: HTMLAttributes;
371
+ track: HTMLAttributes;
372
+ u: HTMLAttributes;
373
+ ul: HTMLAttributes;
374
+ var: HTMLAttributes;
375
+ video: HTMLAttributes;
376
+ wbr: HTMLAttributes;
377
+ // SVG elements
378
+ svg: HTMLAttributes;
379
+ path: HTMLAttributes;
380
+ circle: HTMLAttributes;
381
+ rect: HTMLAttributes;
382
+ line: HTMLAttributes;
383
+ polyline: HTMLAttributes;
384
+ polygon: HTMLAttributes;
385
+ ellipse: HTMLAttributes;
386
+ g: HTMLAttributes;
387
+ text: HTMLAttributes;
388
+ tspan: HTMLAttributes;
389
+ defs: HTMLAttributes;
390
+ use: HTMLAttributes;
391
+ image: HTMLAttributes;
392
+ // Allow any custom element
393
+ [key: string]: HTMLAttributes;
394
+ }
395
+ export interface ElementChildrenAttribute {
396
+ children: {};
397
+ }
398
+ }