@pyreon/runtime-dom 0.11.5 → 0.11.7

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,3 +1,3 @@
1
- import { GlobalRegistrator } from "@happy-dom/global-registrator"
1
+ import { GlobalRegistrator } from '@happy-dom/global-registrator'
2
2
 
3
3
  GlobalRegistrator.register()
@@ -1,38 +1,38 @@
1
- import { createContext, Fragment, h, provide, useContext } from "@pyreon/core"
2
- import { signal } from "@pyreon/reactivity"
3
- import { mount } from "@pyreon/runtime-dom"
4
- import { describe, expect, it } from "vitest"
1
+ import { createContext, Fragment, h, provide, useContext } from '@pyreon/core'
2
+ import { signal } from '@pyreon/reactivity'
3
+ import { mount } from '@pyreon/runtime-dom'
4
+ import { describe, expect, it } from 'vitest'
5
5
 
6
- const TestCtx = createContext("default")
6
+ const TestCtx = createContext('default')
7
7
 
8
- describe("context inheritance through reactive boundaries", () => {
9
- it("child inside reactive accessor inherits parent context", async () => {
8
+ describe('context inheritance through reactive boundaries', () => {
9
+ it('child inside reactive accessor inherits parent context', async () => {
10
10
  let childValue: string | undefined
11
11
 
12
12
  function Child() {
13
13
  childValue = useContext(TestCtx)
14
- return h("span", null, childValue)
14
+ return h('span', null, childValue)
15
15
  }
16
16
 
17
17
  function Parent() {
18
- provide(TestCtx, "from-parent")
18
+ provide(TestCtx, 'from-parent')
19
19
  const show = signal(false)
20
20
  setTimeout(() => show.set(true), 10)
21
21
  return () => (show() ? h(Child, null) : null)
22
22
  }
23
23
 
24
- const container = document.createElement("div")
24
+ const container = document.createElement('div')
25
25
  mount(h(Parent, null), container)
26
26
  await new Promise((r) => setTimeout(r, 50))
27
- expect(childValue).toBe("from-parent")
27
+ expect(childValue).toBe('from-parent')
28
28
  })
29
29
 
30
- it("deeply nested context survives through multiple reactive layers", async () => {
30
+ it('deeply nested context survives through multiple reactive layers', async () => {
31
31
  let innerValue: string | undefined
32
32
 
33
33
  function Inner() {
34
34
  innerValue = useContext(TestCtx)
35
- return h("span", null, innerValue)
35
+ return h('span', null, innerValue)
36
36
  }
37
37
 
38
38
  function Middle() {
@@ -42,16 +42,16 @@ describe("context inheritance through reactive boundaries", () => {
42
42
  }
43
43
 
44
44
  function Outer() {
45
- provide(TestCtx, "outer-value")
45
+ provide(TestCtx, 'outer-value')
46
46
  const show = signal(false)
47
47
  setTimeout(() => show.set(true), 5)
48
48
  return () => (show() ? h(Middle, null) : null)
49
49
  }
50
50
 
51
- const container = document.createElement("div")
51
+ const container = document.createElement('div')
52
52
  mount(h(Outer, null), container)
53
53
  await new Promise((r) => setTimeout(r, 100))
54
- expect(innerValue).toBe("outer-value")
54
+ expect(innerValue).toBe('outer-value')
55
55
  })
56
56
 
57
57
  it("sibling providers don't leak context to each other", async () => {
@@ -60,21 +60,21 @@ describe("context inheritance through reactive boundaries", () => {
60
60
 
61
61
  function ChildA() {
62
62
  childAValue = useContext(TestCtx)
63
- return h("span", null, childAValue)
63
+ return h('span', null, childAValue)
64
64
  }
65
65
 
66
66
  function ChildB() {
67
67
  childBValue = useContext(TestCtx)
68
- return h("span", null, childBValue)
68
+ return h('span', null, childBValue)
69
69
  }
70
70
 
71
71
  function ProviderA() {
72
- provide(TestCtx, "A")
72
+ provide(TestCtx, 'A')
73
73
  return h(ChildA, null)
74
74
  }
75
75
 
76
76
  function ProviderB() {
77
- provide(TestCtx, "B")
77
+ provide(TestCtx, 'B')
78
78
  return h(ChildB, null)
79
79
  }
80
80
 
@@ -82,26 +82,26 @@ describe("context inheritance through reactive boundaries", () => {
82
82
  return h(Fragment, null, h(ProviderA, null), h(ProviderB, null))
83
83
  }
84
84
 
85
- const container = document.createElement("div")
85
+ const container = document.createElement('div')
86
86
  mount(h(App, null), container)
87
87
  await new Promise((r) => setTimeout(r, 50))
88
88
 
89
- expect(childAValue).toBe("A")
90
- expect(childBValue).toBe("B")
89
+ expect(childAValue).toBe('A')
90
+ expect(childBValue).toBe('B')
91
91
  })
92
92
 
93
- it("Show toggle preserves context across hide/show cycle", async () => {
93
+ it('Show toggle preserves context across hide/show cycle', async () => {
94
94
  let childValue: string | undefined
95
95
  let mountCount = 0
96
96
 
97
97
  function Child() {
98
98
  mountCount++
99
99
  childValue = useContext(TestCtx)
100
- return h("span", null, childValue)
100
+ return h('span', null, childValue)
101
101
  }
102
102
 
103
103
  function Parent() {
104
- provide(TestCtx, "persistent")
104
+ provide(TestCtx, 'persistent')
105
105
  const show = signal(true)
106
106
 
107
107
  // Hide then show again
@@ -111,67 +111,67 @@ describe("context inheritance through reactive boundaries", () => {
111
111
  return () => (show() ? h(Child, null) : null)
112
112
  }
113
113
 
114
- const container = document.createElement("div")
114
+ const container = document.createElement('div')
115
115
  mount(h(Parent, null), container)
116
116
  await new Promise((r) => setTimeout(r, 100))
117
117
 
118
- expect(childValue).toBe("persistent")
118
+ expect(childValue).toBe('persistent')
119
119
  expect(mountCount).toBe(2) // mounted twice (initial + re-show)
120
120
  })
121
121
 
122
- it("reactive context getter updates JSX without re-running component", async () => {
123
- const ModeCtx = createContext<() => string>(() => "light")
122
+ it('reactive context getter updates JSX without re-running component', async () => {
123
+ const ModeCtx = createContext<() => string>(() => 'light')
124
124
  let renderCount = 0
125
125
 
126
126
  function Child() {
127
127
  const getMode = useContext(ModeCtx)
128
128
  renderCount++
129
129
  // Reading the getter inside a reactive accessor — updates when mode changes
130
- return h("span", null, () => getMode())
130
+ return h('span', null, () => getMode())
131
131
  }
132
132
 
133
133
  function Parent() {
134
- const mode = signal<string>("light")
134
+ const mode = signal<string>('light')
135
135
  provide(ModeCtx, () => mode())
136
- setTimeout(() => mode.set("dark"), 10)
136
+ setTimeout(() => mode.set('dark'), 10)
137
137
  return h(Child, null)
138
138
  }
139
139
 
140
- const container = document.createElement("div")
140
+ const container = document.createElement('div')
141
141
  mount(h(Parent, null), container)
142
142
 
143
- expect(container.textContent).toBe("light")
143
+ expect(container.textContent).toBe('light')
144
144
 
145
145
  await new Promise((r) => setTimeout(r, 50))
146
- expect(container.textContent).toBe("dark")
146
+ expect(container.textContent).toBe('dark')
147
147
  // Component setup ran once — JSX expression re-evaluated reactively
148
148
  expect(renderCount).toBe(1)
149
149
  })
150
150
 
151
- it("nested Show inside For with context", async () => {
152
- const ItemCtx = createContext("none")
151
+ it('nested Show inside For with context', async () => {
152
+ const ItemCtx = createContext('none')
153
153
  const collected: string[] = []
154
154
 
155
155
  function Item() {
156
156
  const val = useContext(ItemCtx)
157
157
  collected.push(val)
158
- return h("li", null, val)
158
+ return h('li', null, val)
159
159
  }
160
160
 
161
161
  function Parent() {
162
- provide(ItemCtx, "parent-provided")
162
+ provide(ItemCtx, 'parent-provided')
163
163
  const items = signal([1, 2, 3])
164
164
  const show = signal(false)
165
165
  setTimeout(() => show.set(true), 10)
166
166
 
167
- return () => (show() ? h("ul", null, ...items().map((i) => h(Item, { key: i }))) : null)
167
+ return () => (show() ? h('ul', null, ...items().map((i) => h(Item, { key: i }))) : null)
168
168
  }
169
169
 
170
- const container = document.createElement("div")
170
+ const container = document.createElement('div')
171
171
  mount(h(Parent, null), container)
172
172
  await new Promise((r) => setTimeout(r, 50))
173
173
 
174
174
  expect(collected.length).toBe(3)
175
- expect(collected.every((v) => v === "parent-provided")).toBe(true)
175
+ expect(collected.every((v) => v === 'parent-provided')).toBe(true)
176
176
  })
177
177
  })
@@ -1,123 +1,123 @@
1
- import { computed, signal } from "@pyreon/reactivity"
2
- import { _bindDirect, _bindText } from "../template"
1
+ import { computed, signal } from '@pyreon/reactivity'
2
+ import { _bindDirect, _bindText } from '../template'
3
3
 
4
4
  // ─── _bindText ──────────────────────────────────────────────────────────────
5
5
 
6
- describe("_bindText", () => {
7
- test("fast path: signal source sets text and updates reactively", () => {
8
- const s = signal("hello")
9
- const node = document.createTextNode("")
6
+ describe('_bindText', () => {
7
+ test('fast path: signal source sets text and updates reactively', () => {
8
+ const s = signal('hello')
9
+ const node = document.createTextNode('')
10
10
 
11
11
  const dispose = _bindText(s, node)
12
- expect(node.data).toBe("hello")
12
+ expect(node.data).toBe('hello')
13
13
 
14
- s.set("world")
15
- expect(node.data).toBe("world")
14
+ s.set('world')
15
+ expect(node.data).toBe('world')
16
16
 
17
17
  dispose()
18
18
  })
19
19
 
20
- test("fast path: computed source sets text and updates reactively", () => {
20
+ test('fast path: computed source sets text and updates reactively', () => {
21
21
  const s = signal(2)
22
22
  const doubled = computed(() => s() * 2)
23
- const node = document.createTextNode("")
23
+ const node = document.createTextNode('')
24
24
 
25
25
  const dispose = _bindText(doubled, node)
26
- expect(node.data).toBe("4")
26
+ expect(node.data).toBe('4')
27
27
 
28
28
  s.set(5)
29
- expect(node.data).toBe("10")
29
+ expect(node.data).toBe('10')
30
30
 
31
31
  dispose()
32
32
  })
33
33
 
34
- test("fallback: plain function source uses renderEffect", () => {
35
- const s = signal("initial")
34
+ test('fallback: plain function source uses renderEffect', () => {
35
+ const s = signal('initial')
36
36
  // Plain function — no .direct property
37
37
  const getter = () => s()
38
- const node = document.createTextNode("")
38
+ const node = document.createTextNode('')
39
39
 
40
40
  const dispose = _bindText(getter as unknown as Parameters<typeof _bindText>[0], node)
41
- expect(node.data).toBe("initial")
41
+ expect(node.data).toBe('initial')
42
42
 
43
- s.set("updated")
44
- expect(node.data).toBe("updated")
43
+ s.set('updated')
44
+ expect(node.data).toBe('updated')
45
45
 
46
46
  dispose()
47
47
  })
48
48
 
49
- test("disposal stops updates for signal source", () => {
50
- const s = signal("a")
51
- const node = document.createTextNode("")
49
+ test('disposal stops updates for signal source', () => {
50
+ const s = signal('a')
51
+ const node = document.createTextNode('')
52
52
 
53
53
  const dispose = _bindText(s, node)
54
- expect(node.data).toBe("a")
54
+ expect(node.data).toBe('a')
55
55
 
56
56
  dispose()
57
57
 
58
- s.set("b")
59
- expect(node.data).toBe("a")
58
+ s.set('b')
59
+ expect(node.data).toBe('a')
60
60
  })
61
61
 
62
- test("disposal stops updates for computed source", () => {
62
+ test('disposal stops updates for computed source', () => {
63
63
  const s = signal(1)
64
64
  const c = computed(() => s() + 10)
65
- const node = document.createTextNode("")
65
+ const node = document.createTextNode('')
66
66
 
67
67
  const dispose = _bindText(c, node)
68
- expect(node.data).toBe("11")
68
+ expect(node.data).toBe('11')
69
69
 
70
70
  dispose()
71
71
 
72
72
  s.set(2)
73
- expect(node.data).toBe("11")
73
+ expect(node.data).toBe('11')
74
74
  })
75
75
 
76
- test("disposal stops updates for plain function source", () => {
77
- const s = signal("x")
76
+ test('disposal stops updates for plain function source', () => {
77
+ const s = signal('x')
78
78
  const getter = () => s()
79
- const node = document.createTextNode("")
79
+ const node = document.createTextNode('')
80
80
 
81
81
  const dispose = _bindText(getter as unknown as Parameters<typeof _bindText>[0], node)
82
- expect(node.data).toBe("x")
82
+ expect(node.data).toBe('x')
83
83
 
84
84
  dispose()
85
85
 
86
- s.set("y")
87
- expect(node.data).toBe("x")
86
+ s.set('y')
87
+ expect(node.data).toBe('x')
88
88
  })
89
89
 
90
- test("null value renders as empty string", () => {
91
- const s = signal<string | null>("text")
92
- const node = document.createTextNode("")
90
+ test('null value renders as empty string', () => {
91
+ const s = signal<string | null>('text')
92
+ const node = document.createTextNode('')
93
93
 
94
94
  const dispose = _bindText(s, node)
95
- expect(node.data).toBe("text")
95
+ expect(node.data).toBe('text')
96
96
 
97
97
  s.set(null)
98
- expect(node.data).toBe("")
98
+ expect(node.data).toBe('')
99
99
 
100
100
  dispose()
101
101
  })
102
102
 
103
- test("false value renders as empty string", () => {
104
- const s = signal<string | false>("text")
105
- const node = document.createTextNode("")
103
+ test('false value renders as empty string', () => {
104
+ const s = signal<string | false>('text')
105
+ const node = document.createTextNode('')
106
106
 
107
107
  const dispose = _bindText(s, node)
108
108
  s.set(false)
109
- expect(node.data).toBe("")
109
+ expect(node.data).toBe('')
110
110
 
111
111
  dispose()
112
112
  })
113
113
 
114
- test("undefined value renders as empty string", () => {
115
- const s = signal<string | undefined>("text")
116
- const node = document.createTextNode("")
114
+ test('undefined value renders as empty string', () => {
115
+ const s = signal<string | undefined>('text')
116
+ const node = document.createTextNode('')
117
117
 
118
118
  const dispose = _bindText(s, node)
119
119
  s.set(undefined)
120
- expect(node.data).toBe("")
120
+ expect(node.data).toBe('')
121
121
 
122
122
  dispose()
123
123
  })
@@ -125,70 +125,70 @@ describe("_bindText", () => {
125
125
 
126
126
  // ─── _bindDirect ────────────────────────────────────────────────────────────
127
127
 
128
- describe("_bindDirect", () => {
129
- test("fast path: signal source calls updater immediately and on change", () => {
130
- const s = signal("red")
131
- const el = document.createElement("div")
128
+ describe('_bindDirect', () => {
129
+ test('fast path: signal source calls updater immediately and on change', () => {
130
+ const s = signal('red')
131
+ const el = document.createElement('div')
132
132
 
133
133
  const dispose = _bindDirect(s, (v) => {
134
134
  el.className = String(v)
135
135
  })
136
136
 
137
- expect(el.className).toBe("red")
137
+ expect(el.className).toBe('red')
138
138
 
139
- s.set("blue")
140
- expect(el.className).toBe("blue")
139
+ s.set('blue')
140
+ expect(el.className).toBe('blue')
141
141
 
142
142
  dispose()
143
143
  })
144
144
 
145
- test("fallback: plain function source uses renderEffect", () => {
145
+ test('fallback: plain function source uses renderEffect', () => {
146
146
  const s = signal(10)
147
147
  const getter = () => s()
148
- const el = document.createElement("div")
148
+ const el = document.createElement('div')
149
149
 
150
150
  const dispose = _bindDirect(getter as unknown as Parameters<typeof _bindDirect>[0], (v) => {
151
151
  el.style.width = `${v}px`
152
152
  })
153
153
 
154
- expect(el.style.width).toBe("10px")
154
+ expect(el.style.width).toBe('10px')
155
155
 
156
156
  s.set(20)
157
- expect(el.style.width).toBe("20px")
157
+ expect(el.style.width).toBe('20px')
158
158
 
159
159
  dispose()
160
160
  })
161
161
 
162
- test("disposal stops updates for signal source", () => {
163
- const s = signal("a")
164
- const el = document.createElement("div")
162
+ test('disposal stops updates for signal source', () => {
163
+ const s = signal('a')
164
+ const el = document.createElement('div')
165
165
 
166
166
  const dispose = _bindDirect(s, (v) => {
167
- el.setAttribute("data-val", String(v))
167
+ el.setAttribute('data-val', String(v))
168
168
  })
169
169
 
170
- expect(el.getAttribute("data-val")).toBe("a")
170
+ expect(el.getAttribute('data-val')).toBe('a')
171
171
 
172
172
  dispose()
173
173
 
174
- s.set("b")
175
- expect(el.getAttribute("data-val")).toBe("a")
174
+ s.set('b')
175
+ expect(el.getAttribute('data-val')).toBe('a')
176
176
  })
177
177
 
178
- test("disposal stops updates for plain function source", () => {
178
+ test('disposal stops updates for plain function source', () => {
179
179
  const s = signal(1)
180
180
  const getter = () => s()
181
- const el = document.createElement("div")
181
+ const el = document.createElement('div')
182
182
 
183
183
  const dispose = _bindDirect(getter as unknown as Parameters<typeof _bindDirect>[0], (v) => {
184
- el.setAttribute("data-num", String(v))
184
+ el.setAttribute('data-num', String(v))
185
185
  })
186
186
 
187
- expect(el.getAttribute("data-num")).toBe("1")
187
+ expect(el.getAttribute('data-num')).toBe('1')
188
188
 
189
189
  dispose()
190
190
 
191
191
  s.set(2)
192
- expect(el.getAttribute("data-num")).toBe("1")
192
+ expect(el.getAttribute('data-num')).toBe('1')
193
193
  })
194
194
  })