@furystack/shades 11.1.0 → 12.0.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 (166) hide show
  1. package/CHANGELOG.md +291 -0
  2. package/README.md +13 -13
  3. package/esm/component-factory.spec.js +13 -5
  4. package/esm/component-factory.spec.js.map +1 -1
  5. package/esm/components/index.d.ts +4 -1
  6. package/esm/components/index.d.ts.map +1 -1
  7. package/esm/components/index.js +4 -1
  8. package/esm/components/index.js.map +1 -1
  9. package/esm/components/lazy-load.d.ts +2 -4
  10. package/esm/components/lazy-load.d.ts.map +1 -1
  11. package/esm/components/lazy-load.js +40 -24
  12. package/esm/components/lazy-load.js.map +1 -1
  13. package/esm/components/lazy-load.spec.js +57 -50
  14. package/esm/components/lazy-load.spec.js.map +1 -1
  15. package/esm/components/link-to-route.d.ts +2 -0
  16. package/esm/components/link-to-route.d.ts.map +1 -1
  17. package/esm/components/link-to-route.js +3 -2
  18. package/esm/components/link-to-route.js.map +1 -1
  19. package/esm/components/link-to-route.spec.js +13 -9
  20. package/esm/components/link-to-route.spec.js.map +1 -1
  21. package/esm/components/nested-route-link.d.ts +62 -0
  22. package/esm/components/nested-route-link.d.ts.map +1 -0
  23. package/esm/components/nested-route-link.js +66 -0
  24. package/esm/components/nested-route-link.js.map +1 -0
  25. package/esm/components/nested-route-link.spec.d.ts +2 -0
  26. package/esm/components/nested-route-link.spec.d.ts.map +1 -0
  27. package/esm/components/nested-route-link.spec.js +179 -0
  28. package/esm/components/nested-route-link.spec.js.map +1 -0
  29. package/esm/components/nested-route-types.d.ts +37 -0
  30. package/esm/components/nested-route-types.d.ts.map +1 -0
  31. package/esm/components/nested-route-types.js +2 -0
  32. package/esm/components/nested-route-types.js.map +1 -0
  33. package/esm/components/nested-router.d.ts +103 -0
  34. package/esm/components/nested-router.d.ts.map +1 -0
  35. package/esm/components/nested-router.js +178 -0
  36. package/esm/components/nested-router.js.map +1 -0
  37. package/esm/components/nested-router.spec.d.ts +2 -0
  38. package/esm/components/nested-router.spec.d.ts.map +1 -0
  39. package/esm/components/nested-router.spec.js +659 -0
  40. package/esm/components/nested-router.spec.js.map +1 -0
  41. package/esm/components/route-link.d.ts +4 -0
  42. package/esm/components/route-link.d.ts.map +1 -1
  43. package/esm/components/route-link.js +5 -5
  44. package/esm/components/route-link.js.map +1 -1
  45. package/esm/components/route-link.spec.js +16 -12
  46. package/esm/components/route-link.spec.js.map +1 -1
  47. package/esm/components/router.d.ts +20 -2
  48. package/esm/components/router.d.ts.map +1 -1
  49. package/esm/components/router.js +3 -0
  50. package/esm/components/router.js.map +1 -1
  51. package/esm/components/router.spec.js +75 -74
  52. package/esm/components/router.spec.js.map +1 -1
  53. package/esm/initialize.d.ts +11 -0
  54. package/esm/initialize.d.ts.map +1 -1
  55. package/esm/initialize.js +5 -0
  56. package/esm/initialize.js.map +1 -1
  57. package/esm/jsx.d.ts +83 -2
  58. package/esm/jsx.d.ts.map +1 -1
  59. package/esm/models/children-list.d.ts +5 -1
  60. package/esm/models/children-list.d.ts.map +1 -1
  61. package/esm/models/partial-element.d.ts +12 -2
  62. package/esm/models/partial-element.d.ts.map +1 -1
  63. package/esm/models/render-options.d.ts +89 -3
  64. package/esm/models/render-options.d.ts.map +1 -1
  65. package/esm/models/selection-state.d.ts +4 -0
  66. package/esm/models/selection-state.d.ts.map +1 -1
  67. package/esm/services/location-service.d.ts +11 -0
  68. package/esm/services/location-service.d.ts.map +1 -1
  69. package/esm/services/location-service.js +11 -0
  70. package/esm/services/location-service.js.map +1 -1
  71. package/esm/services/resource-manager.d.ts +24 -0
  72. package/esm/services/resource-manager.d.ts.map +1 -1
  73. package/esm/services/resource-manager.js +30 -0
  74. package/esm/services/resource-manager.js.map +1 -1
  75. package/esm/services/resource-manager.spec.js +93 -0
  76. package/esm/services/resource-manager.spec.js.map +1 -1
  77. package/esm/services/screen-service.d.ts +81 -4
  78. package/esm/services/screen-service.d.ts.map +1 -1
  79. package/esm/services/screen-service.js +75 -4
  80. package/esm/services/screen-service.js.map +1 -1
  81. package/esm/services/screen-service.spec.js +91 -7
  82. package/esm/services/screen-service.spec.js.map +1 -1
  83. package/esm/shade-component.d.ts +17 -4
  84. package/esm/shade-component.d.ts.map +1 -1
  85. package/esm/shade-component.js +67 -5
  86. package/esm/shade-component.js.map +1 -1
  87. package/esm/shade-host-props-ref.integration.spec.d.ts +2 -0
  88. package/esm/shade-host-props-ref.integration.spec.d.ts.map +1 -0
  89. package/esm/shade-host-props-ref.integration.spec.js +381 -0
  90. package/esm/shade-host-props-ref.integration.spec.js.map +1 -0
  91. package/esm/shade-resources.integration.spec.js +208 -39
  92. package/esm/shade-resources.integration.spec.js.map +1 -1
  93. package/esm/shade.d.ts +20 -17
  94. package/esm/shade.d.ts.map +1 -1
  95. package/esm/shade.js +172 -33
  96. package/esm/shade.js.map +1 -1
  97. package/esm/shade.spec.js +31 -30
  98. package/esm/shade.spec.js.map +1 -1
  99. package/esm/shades.integration.spec.js +135 -72
  100. package/esm/shades.integration.spec.js.map +1 -1
  101. package/esm/style-manager.d.ts +2 -2
  102. package/esm/style-manager.js +2 -2
  103. package/esm/svg-types.d.ts +389 -0
  104. package/esm/svg-types.d.ts.map +1 -0
  105. package/esm/svg-types.js +9 -0
  106. package/esm/svg-types.js.map +1 -0
  107. package/esm/svg.d.ts +15 -0
  108. package/esm/svg.d.ts.map +1 -0
  109. package/esm/svg.js +76 -0
  110. package/esm/svg.js.map +1 -0
  111. package/esm/svg.spec.d.ts +2 -0
  112. package/esm/svg.spec.d.ts.map +1 -0
  113. package/esm/svg.spec.js +80 -0
  114. package/esm/svg.spec.js.map +1 -0
  115. package/esm/vnode.d.ts +103 -0
  116. package/esm/vnode.d.ts.map +1 -0
  117. package/esm/vnode.integration.spec.d.ts +2 -0
  118. package/esm/vnode.integration.spec.d.ts.map +1 -0
  119. package/esm/vnode.integration.spec.js +494 -0
  120. package/esm/vnode.integration.spec.js.map +1 -0
  121. package/esm/vnode.js +453 -0
  122. package/esm/vnode.js.map +1 -0
  123. package/esm/vnode.spec.d.ts +2 -0
  124. package/esm/vnode.spec.d.ts.map +1 -0
  125. package/esm/vnode.spec.js +473 -0
  126. package/esm/vnode.spec.js.map +1 -0
  127. package/package.json +3 -3
  128. package/src/component-factory.spec.tsx +18 -5
  129. package/src/components/index.ts +4 -1
  130. package/src/components/lazy-load.spec.tsx +82 -75
  131. package/src/components/lazy-load.tsx +49 -27
  132. package/src/components/link-to-route.spec.tsx +25 -21
  133. package/src/components/link-to-route.tsx +4 -2
  134. package/src/components/nested-route-link.spec.tsx +303 -0
  135. package/src/components/nested-route-link.tsx +100 -0
  136. package/src/components/nested-route-types.ts +42 -0
  137. package/src/components/nested-router.spec.tsx +817 -0
  138. package/src/components/nested-router.tsx +256 -0
  139. package/src/components/route-link.spec.tsx +22 -18
  140. package/src/components/route-link.tsx +6 -5
  141. package/src/components/router.spec.tsx +109 -108
  142. package/src/components/router.tsx +15 -2
  143. package/src/initialize.ts +12 -0
  144. package/src/jsx.ts +129 -2
  145. package/src/models/children-list.ts +7 -1
  146. package/src/models/partial-element.ts +13 -2
  147. package/src/models/render-options.ts +90 -3
  148. package/src/models/selection-state.ts +4 -0
  149. package/src/services/location-service.tsx +11 -0
  150. package/src/services/resource-manager.spec.ts +116 -0
  151. package/src/services/resource-manager.ts +30 -0
  152. package/src/services/screen-service.spec.ts +109 -7
  153. package/src/services/screen-service.ts +81 -4
  154. package/src/shade-component.ts +72 -6
  155. package/src/shade-host-props-ref.integration.spec.tsx +460 -0
  156. package/src/shade-resources.integration.spec.tsx +276 -52
  157. package/src/shade.spec.tsx +40 -39
  158. package/src/shade.ts +186 -58
  159. package/src/shades.integration.spec.tsx +154 -80
  160. package/src/style-manager.ts +2 -2
  161. package/src/svg-types.ts +437 -0
  162. package/src/svg.spec.ts +89 -0
  163. package/src/svg.ts +78 -0
  164. package/src/vnode.integration.spec.tsx +657 -0
  165. package/src/vnode.spec.ts +579 -0
  166. package/src/vnode.ts +508 -0
@@ -1,9 +1,9 @@
1
1
  import { Injector } from '@furystack/inject';
2
- import { ObservableValue, sleepAsync } from '@furystack/utils';
2
+ import { ObservableValue, sleepAsync, usingAsync } from '@furystack/utils';
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
  import { initializeShadeRoot } from './initialize.js';
5
5
  import { createComponent } from './shade-component.js';
6
- import { Shade } from './shade.js';
6
+ import { flushUpdates, Shade } from './shade.js';
7
7
  describe('Shade Resources integration tests', () => {
8
8
  beforeEach(() => {
9
9
  document.body.innerHTML = '<div id="root"></div>';
@@ -12,45 +12,214 @@ describe('Shade Resources integration tests', () => {
12
12
  document.body.innerHTML = '';
13
13
  });
14
14
  it('Should update the component based on a custom observable value change', async () => {
15
- const injector = new Injector();
16
- const rootElement = document.getElementById('root');
17
- const renderCounter = vi.fn();
18
- const obs1 = new ObservableValue(0);
19
- const obs2 = new ObservableValue('a');
20
- const ExampleComponent = Shade({
21
- render: ({ useObservable }) => {
22
- const [value1] = useObservable('obs1', obs1);
23
- const [value2] = useObservable('obs2', obs2);
24
- renderCounter();
25
- return (createComponent("div", null,
26
- createComponent("div", { id: "val1" }, value1),
27
- createComponent("div", { id: "val2" }, value2)));
28
- },
29
- shadowDomName: 'shades-example-resource',
15
+ await usingAsync(new Injector(), async (injector) => {
16
+ const rootElement = document.getElementById('root');
17
+ const renderCounter = vi.fn();
18
+ const obs1 = new ObservableValue(0);
19
+ const obs2 = new ObservableValue('a');
20
+ const ExampleComponent = Shade({
21
+ render: ({ useObservable }) => {
22
+ const [value1] = useObservable('obs1', obs1);
23
+ const [value2] = useObservable('obs2', obs2);
24
+ renderCounter();
25
+ return (createComponent("div", null,
26
+ createComponent("div", { id: "val1" }, value1),
27
+ createComponent("div", { id: "val2" }, value2)));
28
+ },
29
+ shadowDomName: 'shades-example-resource',
30
+ });
31
+ expect(obs1.getObservers().length).toBe(0);
32
+ expect(obs2.getObservers().length).toBe(0);
33
+ initializeShadeRoot({
34
+ injector,
35
+ rootElement,
36
+ jsxElement: createComponent(ExampleComponent, null),
37
+ });
38
+ await flushUpdates();
39
+ expect(document.body.innerHTML).toBe('<div id="root"><shades-example-resource><div><div id="val1">0</div><div id="val2">a</div></div></shades-example-resource></div>');
40
+ expect(obs1.getObservers().length).toBe(1);
41
+ expect(obs2.getObservers().length).toBe(1);
42
+ expect(renderCounter).toBeCalledTimes(1);
43
+ obs1.setValue(1);
44
+ await flushUpdates();
45
+ expect(document.body.innerHTML).toBe('<div id="root"><shades-example-resource><div><div id="val1">1</div><div id="val2">a</div></div></shades-example-resource></div>');
46
+ expect(renderCounter).toBeCalledTimes(2);
47
+ obs2.setValue('b');
48
+ await flushUpdates();
49
+ expect(document.body.innerHTML).toBe('<div id="root"><shades-example-resource><div><div id="val1">1</div><div id="val2">b</div></div></shades-example-resource></div>');
50
+ const element = document.querySelector('shades-example-resource');
51
+ expect(element.getRenderCount()).toBe(3);
52
+ document.body.innerHTML = '';
53
+ await sleepAsync(10); // Cleanup can be async
54
+ expect(obs1.getObservers().length).toBe(0);
55
+ expect(obs2.getObservers().length).toBe(0);
56
+ expect(renderCounter).toBeCalledTimes(3);
30
57
  });
31
- expect(obs1.getObservers().length).toBe(0);
32
- expect(obs2.getObservers().length).toBe(0);
33
- initializeShadeRoot({
34
- injector,
35
- rootElement,
36
- jsxElement: createComponent(ExampleComponent, null),
58
+ });
59
+ it('Should NOT re-render the component when a custom onChange callback is provided', async () => {
60
+ await usingAsync(new Injector(), async (injector) => {
61
+ const rootElement = document.getElementById('root');
62
+ const renderCounter = vi.fn();
63
+ const customOnChange = vi.fn();
64
+ const obs = new ObservableValue(0);
65
+ const ExampleComponent = Shade({
66
+ render: ({ useObservable }) => {
67
+ const [value] = useObservable('obs', obs, { onChange: customOnChange });
68
+ renderCounter();
69
+ return createComponent("div", { id: "val" }, value);
70
+ },
71
+ shadowDomName: 'shades-example-custom-onchange',
72
+ });
73
+ initializeShadeRoot({
74
+ injector,
75
+ rootElement,
76
+ jsxElement: createComponent(ExampleComponent, null),
77
+ });
78
+ await flushUpdates();
79
+ const element = document.querySelector('shades-example-custom-onchange');
80
+ // Initial render
81
+ expect(element.getRenderCount()).toBe(1);
82
+ expect(renderCounter).toBeCalledTimes(1);
83
+ expect(customOnChange).toBeCalledTimes(0); // Not called until value changes
84
+ expect(document.getElementById('val')?.textContent).toBe('0');
85
+ // Change the observable value
86
+ obs.setValue(1);
87
+ // Custom onChange should be called
88
+ expect(customOnChange).toBeCalledTimes(1);
89
+ expect(customOnChange).toHaveBeenLastCalledWith(1);
90
+ // But component should NOT re-render
91
+ expect(element.getRenderCount()).toBe(1);
92
+ expect(renderCounter).toBeCalledTimes(1);
93
+ // DOM should still show old value since no re-render occurred
94
+ expect(document.getElementById('val')?.textContent).toBe('0');
95
+ // Change again to verify consistent behavior
96
+ obs.setValue(2);
97
+ expect(customOnChange).toBeCalledTimes(2);
98
+ expect(customOnChange).toHaveBeenLastCalledWith(2);
99
+ expect(element.getRenderCount()).toBe(1);
100
+ expect(renderCounter).toBeCalledTimes(1);
101
+ });
102
+ });
103
+ it('Should allow manual DOM updates in custom onChange callback without re-render', async () => {
104
+ await usingAsync(new Injector(), async (injector) => {
105
+ const rootElement = document.getElementById('root');
106
+ const renderCounter = vi.fn();
107
+ const obs = new ObservableValue(0);
108
+ const ExampleComponent = Shade({
109
+ render: ({ useObservable, useRef }) => {
110
+ const valRef = useRef('manualVal');
111
+ useObservable('obs', obs, {
112
+ onChange: (newValue) => {
113
+ if (valRef.current) {
114
+ valRef.current.textContent = String(newValue);
115
+ }
116
+ },
117
+ });
118
+ renderCounter();
119
+ return (createComponent("div", { ref: valRef, id: "manual-val" }, obs.getValue()));
120
+ },
121
+ shadowDomName: 'shades-example-manual-dom-update',
122
+ });
123
+ initializeShadeRoot({
124
+ injector,
125
+ rootElement,
126
+ jsxElement: createComponent(ExampleComponent, null),
127
+ });
128
+ await flushUpdates();
129
+ const element = document.querySelector('shades-example-manual-dom-update');
130
+ // Initial render
131
+ expect(element.getRenderCount()).toBe(1);
132
+ expect(renderCounter).toBeCalledTimes(1);
133
+ expect(document.getElementById('manual-val')?.textContent).toBe('0');
134
+ // Change the observable value
135
+ obs.setValue(42);
136
+ // Component should NOT re-render
137
+ expect(element.getRenderCount()).toBe(1);
138
+ expect(renderCounter).toBeCalledTimes(1);
139
+ // But DOM should be updated via the manual onChange callback
140
+ expect(document.getElementById('manual-val')?.textContent).toBe('42');
141
+ // Change again
142
+ obs.setValue(100);
143
+ expect(element.getRenderCount()).toBe(1);
144
+ expect(renderCounter).toBeCalledTimes(1);
145
+ expect(document.getElementById('manual-val')?.textContent).toBe('100');
146
+ });
147
+ });
148
+ it('Should batch multiple synchronous observable changes into a single render', async () => {
149
+ await usingAsync(new Injector(), async (injector) => {
150
+ const rootElement = document.getElementById('root');
151
+ const renderCounter = vi.fn();
152
+ const obs1 = new ObservableValue(0);
153
+ const obs2 = new ObservableValue('a');
154
+ const obs3 = new ObservableValue(false);
155
+ const ExampleComponent = Shade({
156
+ render: ({ useObservable }) => {
157
+ const [value1] = useObservable('obs1', obs1);
158
+ const [value2] = useObservable('obs2', obs2);
159
+ const [value3] = useObservable('obs3', obs3);
160
+ renderCounter();
161
+ return (createComponent("div", null,
162
+ createComponent("span", { id: "v1" }, value1),
163
+ createComponent("span", { id: "v2" }, value2),
164
+ createComponent("span", { id: "v3" }, String(value3))));
165
+ },
166
+ shadowDomName: 'shades-example-batching',
167
+ });
168
+ initializeShadeRoot({
169
+ injector,
170
+ rootElement,
171
+ jsxElement: createComponent(ExampleComponent, null),
172
+ });
173
+ await flushUpdates();
174
+ const element = document.querySelector('shades-example-batching');
175
+ expect(element.getRenderCount()).toBe(1);
176
+ expect(renderCounter).toBeCalledTimes(1);
177
+ // Change all three observables synchronously without awaiting in between
178
+ obs1.setValue(42);
179
+ obs2.setValue('z');
180
+ obs3.setValue(true);
181
+ // Before flushing, the DOM should still reflect the old values
182
+ expect(element.getRenderCount()).toBe(1);
183
+ await flushUpdates();
184
+ // After flushing, all changes should be reflected in a single render
185
+ expect(element.getRenderCount()).toBe(2);
186
+ expect(renderCounter).toBeCalledTimes(2);
187
+ expect(document.getElementById('v1')?.textContent).toBe('42');
188
+ expect(document.getElementById('v2')?.textContent).toBe('z');
189
+ expect(document.getElementById('v3')?.textContent).toBe('true');
190
+ });
191
+ });
192
+ it('Should batch multiple updateComponent() calls into a single render', async () => {
193
+ await usingAsync(new Injector(), async (injector) => {
194
+ const rootElement = document.getElementById('root');
195
+ const renderCounter = vi.fn();
196
+ const ExampleComponent = Shade({
197
+ render: () => {
198
+ renderCounter();
199
+ return createComponent("div", null, "content");
200
+ },
201
+ shadowDomName: 'shades-example-update-batching',
202
+ });
203
+ initializeShadeRoot({
204
+ injector,
205
+ rootElement,
206
+ jsxElement: createComponent(ExampleComponent, null),
207
+ });
208
+ await flushUpdates();
209
+ const element = document.querySelector('shades-example-update-batching');
210
+ expect(element.getRenderCount()).toBe(1);
211
+ expect(renderCounter).toBeCalledTimes(1);
212
+ // Call updateComponent multiple times synchronously
213
+ element.updateComponent();
214
+ element.updateComponent();
215
+ element.updateComponent();
216
+ // Before flushing, render count should still be 1
217
+ expect(element.getRenderCount()).toBe(1);
218
+ await flushUpdates();
219
+ // After flushing, only a single additional render should have occurred
220
+ expect(element.getRenderCount()).toBe(2);
221
+ expect(renderCounter).toBeCalledTimes(2);
37
222
  });
38
- expect(document.body.innerHTML).toBe('<div id="root"><shades-example-resource><div><div id="val1">0</div><div id="val2">a</div></div></shades-example-resource></div>');
39
- expect(obs1.getObservers().length).toBe(1);
40
- expect(obs2.getObservers().length).toBe(1);
41
- expect(renderCounter).toBeCalledTimes(1);
42
- obs1.setValue(1);
43
- expect(document.body.innerHTML).toBe('<div id="root"><shades-example-resource><div><div id="val1">1</div><div id="val2">a</div></div></shades-example-resource></div>');
44
- expect(renderCounter).toBeCalledTimes(2);
45
- obs2.setValue('b');
46
- expect(document.body.innerHTML).toBe('<div id="root"><shades-example-resource><div><div id="val1">1</div><div id="val2">b</div></div></shades-example-resource></div>');
47
- const element = document.querySelector('shades-example-resource');
48
- expect(element.getRenderCount()).toBe(3);
49
- document.body.innerHTML = '';
50
- await sleepAsync(10); // Cleanup can be async
51
- expect(obs1.getObservers().length).toBe(0);
52
- expect(obs2.getObservers().length).toBe(0);
53
- expect(renderCounter).toBeCalledTimes(3);
54
223
  });
55
224
  });
56
225
  //# sourceMappingURL=shade-resources.integration.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shade-resources.integration.spec.js","sourceRoot":"","sources":["../src/shade-resources.integration.spec.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shade-resources.integration.spec.js","sourceRoot":"","sources":["../src/shade-resources.integration.spec.tsx"],"names":[],"mappings":"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"}
package/esm/shade.d.ts CHANGED
@@ -2,25 +2,16 @@ import type { Constructable } from '@furystack/inject';
2
2
  import type { ChildrenList, CSSObject, PartialElement, RenderOptions } from './models/index.js';
3
3
  export type ShadeOptions<TProps, TElementBase extends HTMLElement> = {
4
4
  /**
5
- * Explicit shadow dom name. Will fall back to 'shade-{guid}' if not provided
5
+ * The custom element tag name used to register the component.
6
+ * Must follow the Custom Elements naming convention (lowercase, must contain a hyphen).
7
+ *
8
+ * @example 'my-button', 'shade-dialog', 'app-header'
6
9
  */
7
10
  shadowDomName: string;
8
11
  /**
9
12
  * Render hook, this method will be executed on each and every render.
10
13
  */
11
14
  render: (options: RenderOptions<TProps, TElementBase>) => JSX.Element | string | null;
12
- /**
13
- * Construct hook. Will be executed once when the element has been constructed and initialized
14
- */
15
- constructed?: (options: RenderOptions<TProps, TElementBase>) => void | undefined | (() => void) | Promise<void | undefined | (() => void)>;
16
- /**
17
- * Will be executed when the element is attached to the DOM.
18
- */
19
- onAttach?: (options: RenderOptions<TProps, TElementBase>) => void;
20
- /**
21
- * Will be executed when the element is detached from the DOM.
22
- */
23
- onDetach?: (options: RenderOptions<TProps, TElementBase>) => void;
24
15
  /**
25
16
  * Name of the HTML Element's base class. Needs to be defined if the elementBase is set. E.g.: 'div', 'button', 'input'
26
17
  */
@@ -30,18 +21,21 @@ export type ShadeOptions<TProps, TElementBase extends HTMLElement> = {
30
21
  */
31
22
  elementBase?: Constructable<TElementBase>;
32
23
  /**
33
- * A default style that will be applied to the element as inline styles.
34
- * Can be overridden by external styles on instances.
24
+ * Inline styles applied to each component instance.
25
+ * Use for per-instance dynamic overrides. Prefer `css` for component-level defaults.
35
26
  */
36
27
  style?: Partial<CSSStyleDeclaration>;
37
28
  /**
38
29
  * CSS styles injected as a stylesheet during component registration.
39
- * Supports pseudo-selectors (&:hover, &:active) and nested selectors (& .class).
40
- * Use this for component-level styling that doesn't need per-instance overrides.
30
+ * Supports pseudo-selectors (`&:hover`, `&:active`) and nested selectors (`& .class`).
31
+ *
32
+ * **Best practice:** Prefer `css` over `style` for component defaults -- styles are injected
33
+ * once per component type (better performance), and support pseudo-selectors and nesting.
41
34
  *
42
35
  * @example
43
36
  * ```typescript
44
37
  * css: {
38
+ * display: 'flex',
45
39
  * padding: '16px',
46
40
  * '&:hover': { backgroundColor: '#f0f0f0' },
47
41
  * '& .title': { fontWeight: 'bold' }
@@ -56,4 +50,13 @@ export type ShadeOptions<TProps, TElementBase extends HTMLElement> = {
56
50
  * @returns the JSX element
57
51
  */
58
52
  export declare const Shade: <TProps, TElementBase extends HTMLElement = HTMLElement>(o: ShadeOptions<TProps, TElementBase>) => (props: TProps & PartialElement<TElementBase>, children?: ChildrenList) => JSX.Element;
53
+ /**
54
+ * Flushes any pending microtask-based component updates.
55
+ * Useful in tests to wait for batched renders to complete before asserting DOM state.
56
+ *
57
+ * Note: this flushes one level of pending updates. If a render itself triggers new
58
+ * `updateComponent()` calls, an additional `await flushUpdates()` may be needed.
59
+ * @returns a promise that resolves after the current microtask queue has been processed
60
+ */
61
+ export declare const flushUpdates: () => Promise<void>;
59
62
  //# sourceMappingURL=shade.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shade.d.ts","sourceRoot":"","sources":["../src/shade.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGtD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAM/F,MAAM,MAAM,YAAY,CAAC,MAAM,EAAE,YAAY,SAAS,WAAW,IAAI;IACnE;;OAEG;IACH,aAAa,EAAE,MAAM,CAAA;IAErB;;OAEG;IACH,MAAM,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,KAAK,GAAG,CAAC,OAAO,GAAG,MAAM,GAAG,IAAI,CAAA;IAErF;;OAEG;IACH,WAAW,CAAC,EAAE,CACZ,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,KACzC,IAAI,GAAG,SAAS,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAA;IAE/E;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,KAAK,IAAI,CAAA;IAEjE;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,KAAK,IAAI,CAAA;IAEjE;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;IAEzC;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEpC;;;;;;;;;;;;;OAaG;IACH,GAAG,CAAC,EAAE,SAAS,CAAA;CAChB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,KAAK,GAAI,MAAM,EAAE,YAAY,SAAS,WAAW,GAAG,WAAW,EAC1E,GAAG,YAAY,CAAC,MAAM,EAAE,YAAY,CAAC,MAiO7B,OAAO,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,EAAE,WAAW,YAAY,KAgB9D,GAAG,CAAC,OAEpB,CAAA"}
1
+ {"version":3,"file":"shade.d.ts","sourceRoot":"","sources":["../src/shade.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGtD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAS/F,MAAM,MAAM,YAAY,CAAC,MAAM,EAAE,YAAY,SAAS,WAAW,IAAI;IACnE;;;;;OAKG;IACH,aAAa,EAAE,MAAM,CAAA;IAErB;;OAEG;IACH,MAAM,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,KAAK,GAAG,CAAC,OAAO,GAAG,MAAM,GAAG,IAAI,CAAA;IAErF;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;IAEzC;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAEpC;;;;;;;;;;;;;;;;OAgBG;IACH,GAAG,CAAC,EAAE,SAAS,CAAA;CAChB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,KAAK,GAAI,MAAM,EAAE,YAAY,SAAS,WAAW,GAAG,WAAW,EAC1E,GAAG,YAAY,CAAC,MAAM,EAAE,YAAY,CAAC,MA+V7B,OAAO,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,EAAE,WAAW,YAAY,KAgB9D,GAAG,CAAC,OAEpB,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,QAAO,OAAO,CAAC,IAAI,CAA4D,CAAA"}
package/esm/shade.js CHANGED
@@ -2,15 +2,16 @@ import { hasInjectorReference, Injector } from '@furystack/inject';
2
2
  import { ObservableValue } from '@furystack/utils';
3
3
  import { LocationService } from './services/location-service.js';
4
4
  import { ResourceManager } from './services/resource-manager.js';
5
- import { attachProps, attachStyles } from './shade-component.js';
5
+ import { attachProps, attachStyles, setRenderMode } from './shade-component.js';
6
6
  import { StyleManager } from './style-manager.js';
7
+ import { patchChildren, toVChildArray } from './vnode.js';
7
8
  /**
8
9
  * Factory method for creating Shade components
9
10
  * @param o The options object for component creation
10
11
  * @returns the JSX element
11
12
  */
12
13
  export const Shade = (o) => {
13
- // register shadow-dom element
14
+ // Register custom element
14
15
  const customElementName = o.shadowDomName;
15
16
  const existing = customElements.get(customElementName);
16
17
  if (!existing) {
@@ -28,14 +29,27 @@ export const Shade = (o) => {
28
29
  return this._renderCount;
29
30
  }
30
31
  resourceManager = new ResourceManager();
32
+ /**
33
+ * Host props collected during the current render pass via `useHostProps`.
34
+ * Applied to the host element after each render.
35
+ */
36
+ _pendingHostProps = [];
37
+ /**
38
+ * The host props that were applied in the previous render, used for diffing.
39
+ */
40
+ _prevHostProps = null;
41
+ /**
42
+ * Cached ref objects keyed by the user-provided key string.
43
+ */
44
+ _refs = new Map();
31
45
  connectedCallback() {
32
- o.onAttach?.(this.getRenderOptions());
33
- this.callConstructed();
46
+ this.updateComponent();
34
47
  }
35
48
  async disconnectedCallback() {
36
- o.onDetach?.(this.getRenderOptions());
49
+ this._refs.clear();
50
+ this._prevVTree = null;
51
+ this._prevHostProps = null;
37
52
  await this.resourceManager[Symbol.asyncDispose]();
38
- this.cleanup?.();
39
53
  }
40
54
  /**
41
55
  * Will be triggered when updating the external props object
@@ -61,8 +75,18 @@ export const Shade = (o) => {
61
75
  props: this.props,
62
76
  injector: this.injector,
63
77
  children: this.shadeChildren,
64
- element: this,
65
78
  renderCount: this._renderCount,
79
+ useHostProps: (hostProps) => {
80
+ this._pendingHostProps.push(hostProps);
81
+ },
82
+ useRef: (key) => {
83
+ const existingRef = this._refs.get(key);
84
+ if (existingRef)
85
+ return existingRef;
86
+ const refObject = { current: null };
87
+ this._refs.set(key, refObject);
88
+ return refObject;
89
+ },
66
90
  useObservable: (key, obesrvable, options) => {
67
91
  const onChange = options?.onChange || (() => this.updateComponent());
68
92
  return this.resourceManager.useObservable(key, obesrvable, onChange, options);
@@ -116,43 +140,149 @@ export const Shade = (o) => {
116
140
  };
117
141
  return renderOptions;
118
142
  };
143
+ _updateScheduled = false;
119
144
  /**
120
- * Updates the component in the DOM.
145
+ * The VChild array from the previous render, with `_el` references
146
+ * pointing to the real DOM nodes. Used to diff against the next render.
147
+ */
148
+ _prevVTree = null;
149
+ /**
150
+ * Schedules a component update via microtask. Multiple calls before the microtask
151
+ * runs are coalesced into a single render pass.
121
152
  */
122
153
  updateComponent() {
123
- const renderResult = this.render(this.getRenderOptions());
124
- if (renderResult === null || renderResult === undefined) {
125
- this.innerHTML = '';
126
- }
127
- if (typeof renderResult === 'string' || typeof renderResult === 'number') {
128
- this.innerHTML = renderResult;
154
+ if (!this._updateScheduled) {
155
+ this._updateScheduled = true;
156
+ queueMicrotask(() => {
157
+ this._updateScheduled = false;
158
+ this._performUpdate();
159
+ });
129
160
  }
130
- if (renderResult instanceof HTMLElement) {
131
- this.replaceChildren(renderResult);
161
+ }
162
+ _performUpdate() {
163
+ this._pendingHostProps = [];
164
+ let renderResult;
165
+ setRenderMode(true);
166
+ try {
167
+ renderResult = this.render(this.getRenderOptions());
132
168
  }
133
- if (renderResult instanceof DocumentFragment) {
134
- this.replaceChildren(renderResult);
169
+ finally {
170
+ setRenderMode(false);
135
171
  }
172
+ const newVTree = toVChildArray(renderResult);
173
+ patchChildren(this, this._prevVTree || [], newVTree);
174
+ this._prevVTree = newVTree;
175
+ this._applyHostProps();
136
176
  }
137
177
  /**
138
- * Finalize the component initialization after it gets the Props. Called by the framework internally
178
+ * Merges all pending host props from the render pass and applies them
179
+ * to the host element, diffing against the previously applied host props.
139
180
  */
140
- callConstructed() {
141
- this.updateComponent();
142
- const cleanupResult = o.constructed && o.constructed(this.getRenderOptions());
143
- if (cleanupResult instanceof Promise) {
144
- cleanupResult
145
- .then((cleanup) => (this.cleanup = cleanup))
146
- .catch(() => {
147
- /** */
148
- });
181
+ _applyHostProps() {
182
+ if (this._pendingHostProps.length === 0) {
183
+ if (this._prevHostProps) {
184
+ // All host props were removed — clean up
185
+ for (const key of Object.keys(this._prevHostProps)) {
186
+ if (key === 'style')
187
+ continue;
188
+ this.removeAttribute(key);
189
+ }
190
+ if (this._prevHostProps.style) {
191
+ for (const sk of Object.keys(this._prevHostProps.style)) {
192
+ if (sk.startsWith('--')) {
193
+ this.style.removeProperty(sk);
194
+ }
195
+ else {
196
+ ;
197
+ this.style[sk] = '';
198
+ }
199
+ }
200
+ }
201
+ this._prevHostProps = null;
202
+ }
203
+ return;
204
+ }
205
+ // Merge all pending host prop calls into a single object
206
+ const merged = {};
207
+ let mergedStyle;
208
+ for (const hp of this._pendingHostProps) {
209
+ for (const [key, value] of Object.entries(hp)) {
210
+ if (key === 'style' && typeof value === 'object' && value !== null) {
211
+ mergedStyle = { ...mergedStyle, ...value };
212
+ }
213
+ else {
214
+ merged[key] = value;
215
+ }
216
+ }
217
+ }
218
+ if (mergedStyle) {
219
+ merged.style = mergedStyle;
220
+ }
221
+ const oldHP = this._prevHostProps || {};
222
+ const newHP = merged;
223
+ // Remove attributes no longer present
224
+ for (const key of Object.keys(oldHP)) {
225
+ if (key === 'style')
226
+ continue;
227
+ if (!(key in newHP)) {
228
+ if (key.startsWith('on') && typeof oldHP[key] === 'function') {
229
+ ;
230
+ this[key] = null;
231
+ }
232
+ else {
233
+ this.removeAttribute(key);
234
+ }
235
+ }
149
236
  }
150
- else {
151
- // construct is not async
152
- this.cleanup = cleanupResult;
237
+ // Apply new/changed attributes
238
+ for (const [key, value] of Object.entries(newHP)) {
239
+ if (key === 'style')
240
+ continue;
241
+ if (oldHP[key] !== value) {
242
+ if (typeof value === 'function' || (typeof value === 'object' && value !== null)) {
243
+ ;
244
+ this[key] = value;
245
+ }
246
+ else if (value === null || value === undefined || value === false) {
247
+ if (key in this) {
248
+ ;
249
+ this[key] = undefined;
250
+ }
251
+ this.removeAttribute(key);
252
+ }
253
+ else {
254
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
255
+ this.setAttribute(key, String(value));
256
+ }
257
+ }
258
+ }
259
+ // Diff styles
260
+ const oldStyle = oldHP.style || {};
261
+ const newStyle = mergedStyle || {};
262
+ for (const sk of Object.keys(oldStyle)) {
263
+ if (!(sk in newStyle)) {
264
+ if (sk.startsWith('--')) {
265
+ this.style.removeProperty(sk);
266
+ }
267
+ else {
268
+ ;
269
+ this.style[sk] = '';
270
+ }
271
+ }
153
272
  }
273
+ for (const [sk, sv] of Object.entries(newStyle)) {
274
+ if (oldStyle[sk] !== sv) {
275
+ if (sk.startsWith('--')) {
276
+ this.style.setProperty(sk, sv);
277
+ }
278
+ else {
279
+ ;
280
+ this.style[sk] = sv;
281
+ }
282
+ }
283
+ }
284
+ this._prevHostProps = merged;
154
285
  }
155
- cleanup = undefined;
156
286
  _injector;
157
287
  getInjectorFromParent() {
158
288
  let parent = this.parentElement;
@@ -185,7 +315,7 @@ export const Shade = (o) => {
185
315
  }, o.elementBaseName ? { extends: o.elementBaseName } : undefined);
186
316
  }
187
317
  else {
188
- throw Error(`A custom shade with shadow DOM name '${o.shadowDomName}' has already been registered!`);
318
+ throw Error(`A custom shade with name '${o.shadowDomName}' has already been registered!`);
189
319
  }
190
320
  return (props, children) => {
191
321
  const ElementType = customElements.get(customElementName);
@@ -202,4 +332,13 @@ export const Shade = (o) => {
202
332
  return el;
203
333
  };
204
334
  };
335
+ /**
336
+ * Flushes any pending microtask-based component updates.
337
+ * Useful in tests to wait for batched renders to complete before asserting DOM state.
338
+ *
339
+ * Note: this flushes one level of pending updates. If a render itself triggers new
340
+ * `updateComponent()` calls, an additional `await flushUpdates()` may be needed.
341
+ * @returns a promise that resolves after the current microtask queue has been processed
342
+ */
343
+ export const flushUpdates = () => new Promise((resolve) => queueMicrotask(resolve));
205
344
  //# sourceMappingURL=shade.js.map