@pyreon/core 0.11.4 → 0.11.6

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 (47) hide show
  1. package/README.md +2 -2
  2. package/lib/analysis/index.js.html +1 -1
  3. package/lib/index.js +33 -5
  4. package/lib/index.js.map +1 -1
  5. package/lib/jsx-dev-runtime.js.map +1 -1
  6. package/lib/jsx-runtime.js.map +1 -1
  7. package/lib/types/index.d.ts +145 -98
  8. package/lib/types/index.d.ts.map +1 -1
  9. package/lib/types/jsx-dev-runtime.d.ts +94 -94
  10. package/lib/types/jsx-runtime.d.ts +94 -94
  11. package/package.json +11 -11
  12. package/src/component.ts +2 -2
  13. package/src/context.ts +75 -4
  14. package/src/dynamic.ts +4 -4
  15. package/src/error-boundary.ts +10 -10
  16. package/src/for.ts +8 -2
  17. package/src/h.ts +4 -4
  18. package/src/index.ts +30 -27
  19. package/src/jsx-dev-runtime.ts +1 -1
  20. package/src/jsx-runtime.ts +108 -108
  21. package/src/lazy.ts +4 -4
  22. package/src/lifecycle.ts +6 -6
  23. package/src/portal.ts +2 -2
  24. package/src/show.ts +4 -4
  25. package/src/style.ts +51 -51
  26. package/src/suspense.ts +8 -8
  27. package/src/telemetry.ts +1 -1
  28. package/src/tests/component.test.ts +60 -60
  29. package/src/tests/context.test.ts +102 -102
  30. package/src/tests/core.test.ts +376 -376
  31. package/src/tests/cx.test.ts +34 -34
  32. package/src/tests/dynamic.test.ts +28 -28
  33. package/src/tests/error-boundary.test.ts +51 -51
  34. package/src/tests/for.test.ts +26 -26
  35. package/src/tests/h.test.ts +100 -100
  36. package/src/tests/jsx-compat.test.tsx +41 -41
  37. package/src/tests/lazy.test.ts +28 -28
  38. package/src/tests/lifecycle.test.ts +35 -35
  39. package/src/tests/map-array.test.ts +36 -36
  40. package/src/tests/portal.test.ts +21 -21
  41. package/src/tests/props-extended.test.ts +51 -51
  42. package/src/tests/props.test.ts +62 -62
  43. package/src/tests/ref.test.ts +20 -20
  44. package/src/tests/show.test.ts +94 -94
  45. package/src/tests/style.test.ts +101 -101
  46. package/src/tests/suspense.test.ts +44 -44
  47. package/src/tests/telemetry.test.ts +35 -35
@@ -1,49 +1,49 @@
1
- import { Fragment, h } from "../h"
2
- import { Suspense } from "../suspense"
3
- import type { ComponentFn, VNodeChild } from "../types"
1
+ import { Fragment, h } from '../h'
2
+ import { Suspense } from '../suspense'
3
+ import type { ComponentFn, VNodeChild } from '../types'
4
4
 
5
- describe("Suspense", () => {
6
- test("returns a Fragment VNode", () => {
5
+ describe('Suspense', () => {
6
+ test('returns a Fragment VNode', () => {
7
7
  const node = Suspense({
8
- fallback: h("div", null, "loading"),
9
- children: h("div", null, "content"),
8
+ fallback: h('div', null, 'loading'),
9
+ children: h('div', null, 'content'),
10
10
  })
11
11
  expect(node.type).toBe(Fragment)
12
12
  })
13
13
 
14
- test("Fragment contains a single reactive getter child", () => {
14
+ test('Fragment contains a single reactive getter child', () => {
15
15
  const node = Suspense({
16
- fallback: h("span", null, "loading"),
17
- children: h("div", null, "content"),
16
+ fallback: h('span', null, 'loading'),
17
+ children: h('div', null, 'content'),
18
18
  })
19
19
  expect(node.children).toHaveLength(1)
20
- expect(typeof node.children[0]).toBe("function")
20
+ expect(typeof node.children[0]).toBe('function')
21
21
  })
22
22
 
23
- test("renders children when not loading (plain VNode)", () => {
24
- const child = h("div", null, "loaded")
23
+ test('renders children when not loading (plain VNode)', () => {
24
+ const child = h('div', null, 'loaded')
25
25
  const node = Suspense({
26
- fallback: h("span", null, "loading"),
26
+ fallback: h('span', null, 'loading'),
27
27
  children: child,
28
28
  })
29
29
  const getter = node.children[0] as () => VNodeChild
30
30
  expect(getter()).toBe(child)
31
31
  })
32
32
 
33
- test("renders children when child type has no __loading", () => {
34
- const regularComp: ComponentFn = () => h("div", null)
33
+ test('renders children when child type has no __loading', () => {
34
+ const regularComp: ComponentFn = () => h('div', null)
35
35
  const child = h(regularComp, null)
36
36
  const node = Suspense({
37
- fallback: "loading",
37
+ fallback: 'loading',
38
38
  children: child,
39
39
  })
40
40
  const getter = node.children[0] as () => VNodeChild
41
41
  expect(getter()).toBe(child)
42
42
  })
43
43
 
44
- test("renders fallback when child __loading() is true", () => {
45
- const fallback = h("span", null, "loading...")
46
- const lazyFn = (() => h("div", null)) as unknown as ComponentFn & {
44
+ test('renders fallback when child __loading() is true', () => {
45
+ const fallback = h('span', null, 'loading...')
46
+ const lazyFn = (() => h('div', null)) as unknown as ComponentFn & {
47
47
  __loading: () => boolean
48
48
  }
49
49
  lazyFn.__loading = () => true
@@ -54,9 +54,9 @@ describe("Suspense", () => {
54
54
  expect(getter()).toBe(fallback)
55
55
  })
56
56
 
57
- test("renders children when __loading() is false", () => {
58
- const fallback = h("span", null, "loading...")
59
- const lazyFn = (() => h("div", null)) as unknown as ComponentFn & {
57
+ test('renders children when __loading() is false', () => {
58
+ const fallback = h('span', null, 'loading...')
59
+ const lazyFn = (() => h('div', null)) as unknown as ComponentFn & {
60
60
  __loading: () => boolean
61
61
  }
62
62
  lazyFn.__loading = () => false
@@ -67,19 +67,19 @@ describe("Suspense", () => {
67
67
  expect(getter()).toBe(child)
68
68
  })
69
69
 
70
- test("handles function children (reactive getter)", () => {
71
- const child = h("div", null, "content")
70
+ test('handles function children (reactive getter)', () => {
71
+ const child = h('div', null, 'content')
72
72
  const node = Suspense({
73
- fallback: h("span", null, "loading"),
73
+ fallback: h('span', null, 'loading'),
74
74
  children: () => child,
75
75
  })
76
76
  const getter = node.children[0] as () => VNodeChild
77
77
  expect(getter()).toBe(child)
78
78
  })
79
79
 
80
- test("evaluates function fallback", () => {
81
- const fbNode = h("div", null, "fb")
82
- const lazyFn = (() => h("div", null)) as unknown as ComponentFn & {
80
+ test('evaluates function fallback', () => {
81
+ const fbNode = h('div', null, 'fb')
82
+ const lazyFn = (() => h('div', null)) as unknown as ComponentFn & {
83
83
  __loading: () => boolean
84
84
  }
85
85
  lazyFn.__loading = () => true
@@ -90,44 +90,44 @@ describe("Suspense", () => {
90
90
  expect(getter()).toBe(fbNode)
91
91
  })
92
92
 
93
- test("handles null/undefined children", () => {
94
- const node = Suspense({ fallback: "loading" })
93
+ test('handles null/undefined children', () => {
94
+ const node = Suspense({ fallback: 'loading' })
95
95
  const getter = node.children[0] as () => VNodeChild
96
96
  // undefined children — not a VNode, not loading
97
97
  expect(getter()).toBeUndefined()
98
98
  })
99
99
 
100
- test("handles string children", () => {
101
- const node = Suspense({ fallback: "loading", children: "text content" })
100
+ test('handles string children', () => {
101
+ const node = Suspense({ fallback: 'loading', children: 'text content' })
102
102
  const getter = node.children[0] as () => VNodeChild
103
- expect(getter()).toBe("text content")
103
+ expect(getter()).toBe('text content')
104
104
  })
105
105
 
106
- test("handles array children (not loading)", () => {
107
- const children = [h("a", null), h("b", null)]
106
+ test('handles array children (not loading)', () => {
107
+ const children = [h('a', null), h('b', null)]
108
108
  const node = Suspense({
109
- fallback: "loading",
109
+ fallback: 'loading',
110
110
  children: children as unknown as VNodeChild,
111
111
  })
112
112
  const getter = node.children[0] as () => VNodeChild
113
113
  expect(getter()).toBe(children)
114
114
  })
115
115
 
116
- test("warns when fallback prop is missing", () => {
117
- const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {})
118
- Suspense({ fallback: undefined as unknown as VNodeChild, children: "x" })
119
- expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("<Suspense>"))
116
+ test('warns when fallback prop is missing', () => {
117
+ const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
118
+ Suspense({ fallback: undefined as unknown as VNodeChild, children: 'x' })
119
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('<Suspense>'))
120
120
  warnSpy.mockRestore()
121
121
  })
122
122
 
123
- test("transition from loading to loaded", () => {
123
+ test('transition from loading to loaded', () => {
124
124
  let isLoading = true
125
- const lazyFn = (() => h("div", null)) as unknown as ComponentFn & {
125
+ const lazyFn = (() => h('div', null)) as unknown as ComponentFn & {
126
126
  __loading: () => boolean
127
127
  }
128
128
  lazyFn.__loading = () => isLoading
129
129
  const child = h(lazyFn, null)
130
- const fallback = h("span", null, "loading")
130
+ const fallback = h('span', null, 'loading')
131
131
 
132
132
  const node = Suspense({ fallback, children: child })
133
133
  const getter = node.children[0] as () => VNodeChild
@@ -1,17 +1,17 @@
1
- import type { ErrorContext } from "../telemetry"
2
- import { registerErrorHandler, reportError } from "../telemetry"
1
+ import type { ErrorContext } from '../telemetry'
2
+ import { registerErrorHandler, reportError } from '../telemetry'
3
3
 
4
- describe("registerErrorHandler", () => {
5
- test("registers handler that receives error context", () => {
4
+ describe('registerErrorHandler', () => {
5
+ test('registers handler that receives error context', () => {
6
6
  const contexts: ErrorContext[] = []
7
7
  const unsub = registerErrorHandler((ctx) => {
8
8
  contexts.push(ctx)
9
9
  })
10
10
 
11
11
  const ctx: ErrorContext = {
12
- component: "TestComp",
13
- phase: "render",
14
- error: new Error("test"),
12
+ component: 'TestComp',
13
+ phase: 'render',
14
+ error: new Error('test'),
15
15
  timestamp: 1234567890,
16
16
  }
17
17
  reportError(ctx)
@@ -21,28 +21,28 @@ describe("registerErrorHandler", () => {
21
21
  unsub()
22
22
  })
23
23
 
24
- test("returns unregister function", () => {
24
+ test('returns unregister function', () => {
25
25
  let count = 0
26
26
  const unsub = registerErrorHandler(() => {
27
27
  count++
28
28
  })
29
29
 
30
- reportError({ component: "A", phase: "setup", error: "e1", timestamp: 0 })
30
+ reportError({ component: 'A', phase: 'setup', error: 'e1', timestamp: 0 })
31
31
  expect(count).toBe(1)
32
32
 
33
33
  unsub()
34
34
 
35
- reportError({ component: "B", phase: "render", error: "e2", timestamp: 0 })
35
+ reportError({ component: 'B', phase: 'render', error: 'e2', timestamp: 0 })
36
36
  expect(count).toBe(1) // not called after unregister
37
37
  })
38
38
 
39
- test("multiple handlers are all called", () => {
39
+ test('multiple handlers are all called', () => {
40
40
  let count = 0
41
41
  const unsub1 = registerErrorHandler(() => count++)
42
42
  const unsub2 = registerErrorHandler(() => count++)
43
43
  const unsub3 = registerErrorHandler(() => count++)
44
44
 
45
- reportError({ component: "X", phase: "mount", error: "err", timestamp: 0 })
45
+ reportError({ component: 'X', phase: 'mount', error: 'err', timestamp: 0 })
46
46
  expect(count).toBe(3)
47
47
 
48
48
  unsub1()
@@ -50,12 +50,12 @@ describe("registerErrorHandler", () => {
50
50
  unsub3()
51
51
  })
52
52
 
53
- test("handler errors are swallowed — subsequent handlers still called", () => {
53
+ test('handler errors are swallowed — subsequent handlers still called', () => {
54
54
  let secondCalled = false
55
55
  let thirdCalled = false
56
56
 
57
57
  const unsub1 = registerErrorHandler(() => {
58
- throw new Error("handler crash")
58
+ throw new Error('handler crash')
59
59
  })
60
60
  const unsub2 = registerErrorHandler(() => {
61
61
  secondCalled = true
@@ -66,7 +66,7 @@ describe("registerErrorHandler", () => {
66
66
 
67
67
  // Should not throw
68
68
  expect(() =>
69
- reportError({ component: "Y", phase: "unmount", error: "err", timestamp: 0 }),
69
+ reportError({ component: 'Y', phase: 'unmount', error: 'err', timestamp: 0 }),
70
70
  ).not.toThrow()
71
71
  expect(secondCalled).toBe(true)
72
72
  expect(thirdCalled).toBe(true)
@@ -76,64 +76,64 @@ describe("registerErrorHandler", () => {
76
76
  unsub3()
77
77
  })
78
78
 
79
- test("unregistering one handler does not affect others", () => {
79
+ test('unregistering one handler does not affect others', () => {
80
80
  const calls: string[] = []
81
- const unsub1 = registerErrorHandler(() => calls.push("a"))
82
- const unsub2 = registerErrorHandler(() => calls.push("b"))
83
- const unsub3 = registerErrorHandler(() => calls.push("c"))
81
+ const unsub1 = registerErrorHandler(() => calls.push('a'))
82
+ const unsub2 = registerErrorHandler(() => calls.push('b'))
83
+ const unsub3 = registerErrorHandler(() => calls.push('c'))
84
84
 
85
85
  unsub2() // remove middle handler
86
86
 
87
- reportError({ component: "Z", phase: "effect", error: "e", timestamp: 0 })
88
- expect(calls).toEqual(["a", "c"])
87
+ reportError({ component: 'Z', phase: 'effect', error: 'e', timestamp: 0 })
88
+ expect(calls).toEqual(['a', 'c'])
89
89
 
90
90
  unsub1()
91
91
  unsub3()
92
92
  })
93
93
  })
94
94
 
95
- describe("reportError", () => {
96
- test("no-op when no handlers registered", () => {
95
+ describe('reportError', () => {
96
+ test('no-op when no handlers registered', () => {
97
97
  // Should not throw
98
98
  expect(() =>
99
- reportError({ component: "None", phase: "setup", error: "err", timestamp: 0 }),
99
+ reportError({ component: 'None', phase: 'setup', error: 'err', timestamp: 0 }),
100
100
  ).not.toThrow()
101
101
  })
102
102
 
103
- test("passes full ErrorContext to handler", () => {
103
+ test('passes full ErrorContext to handler', () => {
104
104
  let received: ErrorContext | null = null
105
105
  const unsub = registerErrorHandler((ctx) => {
106
106
  received = ctx
107
107
  })
108
108
 
109
109
  const ctx: ErrorContext = {
110
- component: "MyComp",
111
- phase: "render",
112
- error: new Error("detail"),
110
+ component: 'MyComp',
111
+ phase: 'render',
112
+ error: new Error('detail'),
113
113
  timestamp: 999,
114
- props: { a: 1, b: "two" },
114
+ props: { a: 1, b: 'two' },
115
115
  }
116
116
  reportError(ctx)
117
117
 
118
118
  expect(received).not.toBeNull()
119
- expect(received!.component).toBe("MyComp")
120
- expect(received!.phase).toBe("render")
119
+ expect(received!.component).toBe('MyComp')
120
+ expect(received!.phase).toBe('render')
121
121
  expect(received!.error).toBeInstanceOf(Error)
122
122
  expect(received!.timestamp).toBe(999)
123
- expect(received!.props).toEqual({ a: 1, b: "two" })
123
+ expect(received!.props).toEqual({ a: 1, b: 'two' })
124
124
 
125
125
  unsub()
126
126
  })
127
127
 
128
- test("handles all phase types", () => {
129
- const phases: ErrorContext["phase"][] = ["setup", "render", "mount", "unmount", "effect"]
128
+ test('handles all phase types', () => {
129
+ const phases: ErrorContext['phase'][] = ['setup', 'render', 'mount', 'unmount', 'effect']
130
130
  const seen: string[] = []
131
131
  const unsub = registerErrorHandler((ctx) => {
132
132
  seen.push(ctx.phase)
133
133
  })
134
134
 
135
135
  for (const phase of phases) {
136
- reportError({ component: "X", phase, error: "e", timestamp: 0 })
136
+ reportError({ component: 'X', phase, error: 'e', timestamp: 0 })
137
137
  }
138
138
  expect(seen).toEqual(phases)
139
139