@pyreon/core 0.3.1 → 0.5.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/package.json +2 -2
- package/src/jsx-runtime.ts +17 -2
- package/src/tests/jsx-compat.test.tsx +86 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Core component model and lifecycle for Pyreon",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"prepublishOnly": "bun run build"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@pyreon/reactivity": "^0.
|
|
52
|
+
"@pyreon/reactivity": "^0.5.0"
|
|
53
53
|
},
|
|
54
54
|
"publishConfig": {
|
|
55
55
|
"access": "public"
|
package/src/jsx-runtime.ts
CHANGED
|
@@ -92,8 +92,8 @@ interface PyreonHTMLAttributes {
|
|
|
92
92
|
"aria-rowcount"?: number
|
|
93
93
|
"aria-rowindex"?: number
|
|
94
94
|
"aria-rowspan"?: number
|
|
95
|
-
// DOM lifecycle ref
|
|
96
|
-
ref?: { current: unknown }
|
|
95
|
+
// DOM lifecycle ref — object ref or callback ref
|
|
96
|
+
ref?: { current: unknown } | ((el: Element) => void)
|
|
97
97
|
// Key for list reconciliation
|
|
98
98
|
key?: string | number
|
|
99
99
|
// innerHTML
|
|
@@ -425,6 +425,21 @@ interface SvgAttributes extends PyreonHTMLAttributes {
|
|
|
425
425
|
|
|
426
426
|
declare global {
|
|
427
427
|
namespace JSX {
|
|
428
|
+
/** The type that JSX expressions evaluate to */
|
|
429
|
+
type Element = import("./types").VNode
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Valid JSX tag types — intrinsic strings + component functions.
|
|
433
|
+
* Components may return VNode, null, strings, functions (reactive getters), etc.
|
|
434
|
+
* (TS 5.1+ feature)
|
|
435
|
+
*/
|
|
436
|
+
type ElementType = keyof IntrinsicElements | ((props: any) => import("./types").VNodeChild)
|
|
437
|
+
|
|
438
|
+
/** Tells TS which prop name carries children in component calls */
|
|
439
|
+
interface ElementChildrenAttribute {
|
|
440
|
+
children: {}
|
|
441
|
+
}
|
|
442
|
+
|
|
428
443
|
interface IntrinsicElements {
|
|
429
444
|
// Document structure
|
|
430
445
|
html: PyreonHTMLAttributes
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSX type compatibility test — verifies all JSX patterns produce correct VNodes.
|
|
3
|
+
* Uses h() directly since core's vitest config doesn't have JSX transform.
|
|
4
|
+
* TypeScript already validates JSX types via typecheck (tsc --noEmit).
|
|
5
|
+
*/
|
|
6
|
+
import { createRef, Fragment, h } from "../index"
|
|
7
|
+
|
|
8
|
+
describe("JSX type compat (via h)", () => {
|
|
9
|
+
test("basic element", () => {
|
|
10
|
+
const el = h("div", { class: "hello" }, "world")
|
|
11
|
+
expect(el.type).toBe("div")
|
|
12
|
+
expect(el.props.class).toBe("hello")
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test("callback ref", () => {
|
|
16
|
+
let captured: Element | null = null
|
|
17
|
+
const el = h(
|
|
18
|
+
"div",
|
|
19
|
+
{
|
|
20
|
+
ref: (e: Element) => {
|
|
21
|
+
captured = e
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
"test",
|
|
25
|
+
)
|
|
26
|
+
expect(typeof el.props.ref).toBe("function")
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test("object ref", () => {
|
|
30
|
+
const myRef = createRef<HTMLDivElement>()
|
|
31
|
+
const el = h("div", { ref: myRef }, "test")
|
|
32
|
+
expect(el.props.ref).toBe(myRef)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test("reactive class prop", () => {
|
|
36
|
+
const el = h("span", { class: () => "active" }, "hello")
|
|
37
|
+
expect(typeof el.props.class).toBe("function")
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test("input with typed props", () => {
|
|
41
|
+
const el = h("input", { type: "text", value: "test" })
|
|
42
|
+
expect(el.type).toBe("input")
|
|
43
|
+
expect(el.props.type).toBe("text")
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test("component with children", () => {
|
|
47
|
+
const MyComp = (props: { name: string; children?: unknown }) => {
|
|
48
|
+
return h("div", null, String(props.name))
|
|
49
|
+
}
|
|
50
|
+
const el = h(MyComp, { name: "test" }, "child")
|
|
51
|
+
expect(typeof el.type).toBe("function")
|
|
52
|
+
expect(el.props.name).toBe("test")
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test("fragment", () => {
|
|
56
|
+
const el = h(Fragment, null, "fragment")
|
|
57
|
+
expect(el.type).toBe(Fragment)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test("event handler", () => {
|
|
61
|
+
const handler = vi.fn()
|
|
62
|
+
const el = h("button", { onClick: handler }, "click")
|
|
63
|
+
expect(el.props.onClick).toBe(handler)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test("style as object", () => {
|
|
67
|
+
const el = h("div", { style: { color: "red" } }, "styled")
|
|
68
|
+
expect(el.props.style).toEqual({ color: "red" })
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test("data attributes", () => {
|
|
72
|
+
const el = h("div", { "data-testid": "foo" }, "test")
|
|
73
|
+
expect(el.props["data-testid"]).toBe("foo")
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
test("aria attributes", () => {
|
|
77
|
+
const el = h("div", { "aria-label": "close", role: "button" })
|
|
78
|
+
expect(el.props["aria-label"]).toBe("close")
|
|
79
|
+
expect(el.props.role).toBe("button")
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
test("key prop", () => {
|
|
83
|
+
const el = h("li", { key: "item-1" }, "item")
|
|
84
|
+
expect(el.key).toBe("item-1")
|
|
85
|
+
})
|
|
86
|
+
})
|