@praxisjs/runtime 0.7.0 → 0.8.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 (138) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/children.d.ts.map +1 -1
  3. package/dist/children.js +2 -1
  4. package/dist/children.js.map +1 -1
  5. package/dist/component.d.ts +2 -3
  6. package/dist/component.d.ts.map +1 -1
  7. package/dist/component.js +133 -60
  8. package/dist/component.js.map +1 -1
  9. package/dist/context.d.ts +13 -0
  10. package/dist/context.d.ts.map +1 -1
  11. package/dist/context.js +24 -2
  12. package/dist/context.js.map +1 -1
  13. package/dist/dom/constants.d.ts +1 -1
  14. package/dist/dom/constants.d.ts.map +1 -1
  15. package/dist/dom/constants.js +24 -83
  16. package/dist/dom/constants.js.map +1 -1
  17. package/dist/dom/create.d.ts +1 -1
  18. package/dist/dom/create.d.ts.map +1 -1
  19. package/dist/dom/create.js +3 -3
  20. package/dist/dom/create.js.map +1 -1
  21. package/dist/dom/events.d.ts +29 -1
  22. package/dist/dom/events.d.ts.map +1 -1
  23. package/dist/dom/events.js +167 -17
  24. package/dist/dom/events.js.map +1 -1
  25. package/dist/dom/props.d.ts +4 -0
  26. package/dist/dom/props.d.ts.map +1 -1
  27. package/dist/dom/props.js +57 -8
  28. package/dist/dom/props.js.map +1 -1
  29. package/dist/dom/range.d.ts +4 -0
  30. package/dist/dom/range.d.ts.map +1 -0
  31. package/dist/dom/range.js +43 -0
  32. package/dist/dom/range.js.map +1 -0
  33. package/dist/dom/remove.d.ts.map +1 -1
  34. package/dist/dom/remove.js +2 -8
  35. package/dist/dom/remove.js.map +1 -1
  36. package/dist/element.d.ts.map +1 -1
  37. package/dist/element.js +7 -5
  38. package/dist/element.js.map +1 -1
  39. package/dist/hmr.d.ts +35 -0
  40. package/dist/hmr.d.ts.map +1 -0
  41. package/dist/hmr.js +85 -0
  42. package/dist/hmr.js.map +1 -0
  43. package/dist/hydration-context.d.ts +9 -1
  44. package/dist/hydration-context.d.ts.map +1 -1
  45. package/dist/hydration-context.js +34 -13
  46. package/dist/hydration-context.js.map +1 -1
  47. package/dist/hydration.d.ts.map +1 -1
  48. package/dist/hydration.js +4 -11
  49. package/dist/hydration.js.map +1 -1
  50. package/dist/index.d.ts +16 -5
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +31 -7
  53. package/dist/index.js.map +1 -1
  54. package/dist/list.d.ts +72 -0
  55. package/dist/list.d.ts.map +1 -0
  56. package/dist/list.js +786 -0
  57. package/dist/list.js.map +1 -0
  58. package/dist/portal.d.ts.map +1 -1
  59. package/dist/portal.js +3 -0
  60. package/dist/portal.js.map +1 -1
  61. package/dist/reactive.d.ts +2 -2
  62. package/dist/reactive.d.ts.map +1 -1
  63. package/dist/reactive.js +109 -34
  64. package/dist/reactive.js.map +1 -1
  65. package/dist/scope.d.ts +14 -4
  66. package/dist/scope.d.ts.map +1 -1
  67. package/dist/scope.js +55 -15
  68. package/dist/scope.js.map +1 -1
  69. package/dist/template.d.ts +48 -0
  70. package/dist/template.d.ts.map +1 -0
  71. package/dist/template.js +270 -0
  72. package/dist/template.js.map +1 -0
  73. package/package.json +15 -6
  74. package/src/children.ts +2 -1
  75. package/src/component.ts +135 -63
  76. package/src/context.ts +35 -4
  77. package/src/dom/constants.ts +25 -82
  78. package/src/dom/create.ts +3 -3
  79. package/src/dom/events.ts +188 -17
  80. package/src/dom/props.ts +66 -9
  81. package/src/dom/range.ts +45 -0
  82. package/src/dom/remove.ts +3 -7
  83. package/src/element.ts +8 -6
  84. package/src/hmr.ts +110 -0
  85. package/src/hydration-context.ts +34 -13
  86. package/src/hydration.ts +4 -9
  87. package/src/index.ts +54 -7
  88. package/src/list.ts +886 -0
  89. package/src/portal.ts +3 -0
  90. package/src/reactive.ts +147 -40
  91. package/src/scope.ts +63 -16
  92. package/src/template.ts +271 -0
  93. package/dist/__tests__/children.test.d.ts +0 -2
  94. package/dist/__tests__/children.test.d.ts.map +0 -1
  95. package/dist/__tests__/children.test.js +0 -241
  96. package/dist/__tests__/children.test.js.map +0 -1
  97. package/dist/__tests__/component.test.d.ts +0 -2
  98. package/dist/__tests__/component.test.d.ts.map +0 -1
  99. package/dist/__tests__/component.test.js +0 -331
  100. package/dist/__tests__/component.test.js.map +0 -1
  101. package/dist/__tests__/context.test.d.ts +0 -2
  102. package/dist/__tests__/context.test.d.ts.map +0 -1
  103. package/dist/__tests__/context.test.js +0 -111
  104. package/dist/__tests__/context.test.js.map +0 -1
  105. package/dist/__tests__/dom.test.d.ts +0 -2
  106. package/dist/__tests__/dom.test.d.ts.map +0 -1
  107. package/dist/__tests__/dom.test.js +0 -385
  108. package/dist/__tests__/dom.test.js.map +0 -1
  109. package/dist/__tests__/hydration.test.d.ts +0 -2
  110. package/dist/__tests__/hydration.test.d.ts.map +0 -1
  111. package/dist/__tests__/hydration.test.js +0 -299
  112. package/dist/__tests__/hydration.test.js.map +0 -1
  113. package/dist/__tests__/portal.test.d.ts +0 -2
  114. package/dist/__tests__/portal.test.d.ts.map +0 -1
  115. package/dist/__tests__/portal.test.js +0 -157
  116. package/dist/__tests__/portal.test.js.map +0 -1
  117. package/dist/__tests__/remove.test.d.ts +0 -2
  118. package/dist/__tests__/remove.test.d.ts.map +0 -1
  119. package/dist/__tests__/remove.test.js +0 -45
  120. package/dist/__tests__/remove.test.js.map +0 -1
  121. package/dist/__tests__/render.test.d.ts +0 -2
  122. package/dist/__tests__/render.test.d.ts.map +0 -1
  123. package/dist/__tests__/render.test.js +0 -97
  124. package/dist/__tests__/render.test.js.map +0 -1
  125. package/dist/__tests__/scope.test.d.ts +0 -2
  126. package/dist/__tests__/scope.test.d.ts.map +0 -1
  127. package/dist/__tests__/scope.test.js +0 -110
  128. package/dist/__tests__/scope.test.js.map +0 -1
  129. package/src/__tests__/children.test.ts +0 -276
  130. package/src/__tests__/component.test.ts +0 -363
  131. package/src/__tests__/context.test.ts +0 -128
  132. package/src/__tests__/dom.test.ts +0 -434
  133. package/src/__tests__/hydration.test.ts +0 -360
  134. package/src/__tests__/portal.test.ts +0 -177
  135. package/src/__tests__/remove.test.ts +0 -51
  136. package/src/__tests__/render.test.ts +0 -119
  137. package/src/__tests__/scope.test.ts +0 -120
  138. package/tsconfig.json +0 -8
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/dom/events.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAkBtC,wBAAgB,QAAQ,CACtB,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,KAAK,GACX,IAAI,CAIN"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/dom/events.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AA6BtC,wBAAgB,QAAQ,CACtB,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,aAAa,GAAG,mBAAmB,GAAG,IAAI,GAAG,SAAS,EAC/D,KAAK,EAAE,KAAK,GACX,IAAI,CAyBN;AAiBD,MAAM,WAAW,aAAa;IAC5B,0FAA0F;IAC1F,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,OAAO,EAAE,OAAO,CAAC;CAClB;AAWD,6FAA6F;AAC7F,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAY/D;AAiCD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,IAAI,CAO1D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAiB3H;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAerF"}
@@ -1,21 +1,171 @@
1
- import { batch } from "@praxisjs/core/internal";
2
- // One wrapper per handler keeps addEventListener's dedupe of an identical listener intact.
3
- const batchedHandlers = new WeakMap();
4
- // Handlers run inside batch() so several signal writes in one event flush their effects once,
5
- // instead of re-running the same reactive subtree after every write.
6
- function batched(handler) {
7
- let wrapper = batchedHandlers.get(handler);
8
- if (!wrapper) {
9
- wrapper = function (event) {
10
- batch(() => { handler.call(this, event); });
11
- };
12
- batchedHandlers.set(handler, wrapper);
13
- }
14
- return wrapper;
1
+ import { endBatch, startBatch } from "@praxisjs/core/internal";
2
+ import { EVENT_MAP } from "./constants";
3
+ const HANDLERS = Symbol("praxis.handlers");
4
+ // One shared listener per element and event type dispatches to the handlers stored on the
5
+ // element, so binding a handler allocates no wrapper. Handlers run inside a batch so several
6
+ // signal writes in one event flush their effects once.
7
+ function dispatch(event) {
8
+ const slot = this[HANDLERS]?.[event.type];
9
+ if (slot === undefined)
10
+ return;
11
+ startBatch();
12
+ try {
13
+ if (typeof slot === "function") {
14
+ slot.call(this, event);
15
+ }
16
+ else {
17
+ for (const handler of slot.slice())
18
+ handler.call(this, event);
19
+ }
20
+ }
21
+ finally {
22
+ endBatch();
23
+ }
15
24
  }
16
25
  export function addEvent(el, eventName, handler, scope) {
17
- const listener = batched(handler);
18
- el.addEventListener(eventName, listener);
19
- scope.add(() => { el.removeEventListener(eventName, listener); });
26
+ // Components forward optional handlers (`onSubmit={this.onSubmit}`) as-is, and addEventListener
27
+ // has always treated a missing listener as a no-op.
28
+ if (handler == null)
29
+ return;
30
+ if (typeof handler !== "function") {
31
+ el.addEventListener(eventName, handler);
32
+ scope.add(() => { el.removeEventListener(eventName, handler); });
33
+ return;
34
+ }
35
+ const host = el;
36
+ const handlers = (host[HANDLERS] ??= {});
37
+ const slot = handlers[eventName];
38
+ if (slot === undefined) {
39
+ // `in` tells a slot emptied by a disposed scope (listener still attached) from a new event type.
40
+ if (!(eventName in handlers))
41
+ el.addEventListener(eventName, dispatch);
42
+ handlers[eventName] = handler;
43
+ }
44
+ else if (typeof slot === "function") {
45
+ // Same as addEventListener: registering an identical listener twice is a no-op.
46
+ if (slot === handler)
47
+ return;
48
+ handlers[eventName] = [slot, handler];
49
+ }
50
+ else {
51
+ if (slot.includes(handler))
52
+ return;
53
+ slot.push(handler);
54
+ }
55
+ scope.listen(el, eventName, handler);
56
+ }
57
+ const OWNER = Symbol("praxis.owner");
58
+ const GENERATION = Symbol("praxis.generation");
59
+ // Every event prop maps to its own event type (EVENT_MAP has no two props for one type), so an
60
+ // entry is created once per prop and found by type when an event comes in.
61
+ const byType = new Map();
62
+ // Keyed by event prop name (`onClick`), so binding a handler costs one lookup. `null` marks a prop
63
+ // that is not an event.
64
+ const byProp = new Map();
65
+ const watched = [];
66
+ const roots = new Set();
67
+ /** The delegated event type an event prop binds, or null when `key` is not an event prop. */
68
+ export function delegatedProp(key) {
69
+ let entry = byProp.get(key);
70
+ if (entry === undefined) {
71
+ const type = EVENT_MAP.get(key);
72
+ entry = null;
73
+ if (type !== undefined) {
74
+ entry = { key, type, slot: Symbol(`praxis.on.${type}`), attached: Symbol(`praxis.attached.${type}`), watched: false };
75
+ byType.set(type, entry);
76
+ }
77
+ byProp.set(key, entry);
78
+ }
79
+ return entry;
80
+ }
81
+ function dispatchDelegated(event) {
82
+ const host = this;
83
+ const handler = host[byType.get(event.type).slot];
84
+ if (handler === undefined || host[OWNER].gen !== host[GENERATION])
85
+ return;
86
+ startBatch();
87
+ try {
88
+ handler.call(this, event);
89
+ }
90
+ finally {
91
+ endBatch();
92
+ }
93
+ }
94
+ function attachOnDemand(event) {
95
+ const { type, slot, attached } = byType.get(event.type);
96
+ for (const node of event.composedPath()) {
97
+ if (node === this)
98
+ return;
99
+ const host = node;
100
+ if (host[slot] !== undefined && host[attached] === undefined) {
101
+ host[attached] = true;
102
+ node.addEventListener(type, dispatchDelegated);
103
+ }
104
+ }
105
+ }
106
+ function watchType(entry) {
107
+ entry.watched = true;
108
+ watched.push(entry);
109
+ document.addEventListener(entry.type, attachOnDemand, true);
110
+ for (const root of roots)
111
+ root.addEventListener(entry.type, attachOnDemand, true);
112
+ }
113
+ /**
114
+ * Registers a render container (or portal target) whose subtree gets delegated handlers even while
115
+ * it is not in the document. Returns the function that unregisters it.
116
+ */
117
+ export function addEventRoot(root) {
118
+ roots.add(root);
119
+ for (const entry of watched)
120
+ root.addEventListener(entry.type, attachOnDemand, true);
121
+ return () => {
122
+ roots.delete(root);
123
+ for (const entry of watched)
124
+ root.removeEventListener(entry.type, attachOnDemand, true);
125
+ };
126
+ }
127
+ /**
128
+ * Binds `handler` for the event of `entry` (see delegatedProp) on `el` without attaching a
129
+ * listener now (see above). Falls back to addEvent when no render container is registered (an
130
+ * element mounted outside render()), when the element already has a delegated handler for this
131
+ * type, or when it was bound by another scope.
132
+ */
133
+ export function addDelegatedEvent(el, entry, handler, scope) {
134
+ if (handler == null)
135
+ return;
136
+ const host = el;
137
+ const key = entry.slot;
138
+ if (roots.size === 0 ||
139
+ typeof handler !== "function" ||
140
+ host[key] !== undefined ||
141
+ (host[OWNER] !== undefined && host[OWNER] !== scope)) {
142
+ addEvent(el, entry.type, handler, scope);
143
+ return;
144
+ }
145
+ if (!entry.watched)
146
+ watchType(entry);
147
+ host[key] = handler;
148
+ host[OWNER] = scope;
149
+ host[GENERATION] = scope.gen;
150
+ }
151
+ export function removeListener(el, eventName, handler) {
152
+ const handlers = el[HANDLERS];
153
+ const slot = handlers?.[eventName];
154
+ if (handlers === undefined || slot === undefined)
155
+ return;
156
+ if (typeof slot === "function") {
157
+ if (slot !== handler)
158
+ return;
159
+ // The shared listener stays registered: with an empty slot it does nothing, and leaving it
160
+ // saves a native call per handler when thousands of rows are disposed at once.
161
+ handlers[eventName] = undefined;
162
+ return;
163
+ }
164
+ const index = slot.indexOf(handler);
165
+ if (index === -1)
166
+ return;
167
+ slot.splice(index, 1);
168
+ if (slot.length === 1)
169
+ handlers[eventName] = slot[0];
20
170
  }
21
171
  //# sourceMappingURL=events.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/dom/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAIhD,2FAA2F;AAC3F,MAAM,eAAe,GAAG,IAAI,OAAO,EAAgC,CAAC;AAEpE,8FAA8F;AAC9F,qEAAqE;AACrE,SAAS,OAAO,CAAC,OAAsB;IACrC,IAAI,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,UAAyB,KAAK;YACtC,KAAK,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC,CAAC;QACF,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,QAAQ,CACtB,EAAW,EACX,SAAiB,EACjB,OAAsB,EACtB,KAAY;IAEZ,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACzC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC"}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/dom/events.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,7 @@
1
1
  import type { Scope } from "../scope";
2
+ export declare function hasWritableProperty(el: Element, key: string): boolean;
3
+ export declare function setProp(el: Element, key: string, value: unknown): void;
2
4
  export declare function applyProp(el: Element, key: string, value: unknown, scope: Scope): void;
5
+ /** A reactive `class` prop, bound like any other reactive prop but with no key dispatch per run. */
6
+ export declare function bindClass(el: Element, read: () => unknown, scope: Scope): void;
3
7
  //# sourceMappingURL=props.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../src/dom/props.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AA2FtC,wBAAgB,SAAS,CACvB,EAAE,EAAE,OAAO,EACX,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,KAAK,GACX,IAAI,CAwBN"}
1
+ {"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../src/dom/props.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAmEtC,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAgBrE;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAYtE;AAED,wBAAgB,SAAS,CACvB,EAAE,EAAE,OAAO,EACX,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,KAAK,GACX,IAAI,CAwBN;AA6CD,oGAAoG;AACpG,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAG9E"}
package/dist/dom/props.js CHANGED
@@ -5,7 +5,17 @@ function applyClass(el, value) {
5
5
  if (value === null || value === undefined) {
6
6
  el.removeAttribute("class");
7
7
  }
8
+ else if (el instanceof HTMLElement) {
9
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
10
+ const next = String(value);
11
+ // Reading is cheap; writing invalidates the element's style even when nothing changes, which
12
+ // is what a first binding run does on every element whose class starts empty.
13
+ if (el.className !== next)
14
+ el.className = next;
15
+ }
8
16
  else {
17
+ // SVG elements expose className as an SVGAnimatedString, so the attribute is the way in (as
18
+ // for any element of another kind, or of another window).
9
19
  // eslint-disable-next-line @typescript-eslint/no-base-to-string
10
20
  el.setAttribute("class", String(value));
11
21
  }
@@ -59,7 +69,7 @@ function lookupWritable(proto, key) {
59
69
  // must be excluded here or assignment below throws. The prototype walk is cached per
60
70
  // prototype because every element of a given tag repeats the same lookups; a property defined on
61
71
  // a prototype after its first lookup (e.g. a late polyfill) is therefore not picked up.
62
- function hasWritableProperty(el, key) {
72
+ export function hasWritableProperty(el, key) {
63
73
  const own = Object.getOwnPropertyDescriptor(el, key);
64
74
  if (own)
65
75
  return own.set !== undefined || own.writable === true;
@@ -76,7 +86,7 @@ function hasWritableProperty(el, key) {
76
86
  }
77
87
  return writable;
78
88
  }
79
- function setProp(el, key, value) {
89
+ export function setProp(el, key, value) {
80
90
  if (key === "class" || key === "className") {
81
91
  applyClass(el, value);
82
92
  }
@@ -99,19 +109,58 @@ export function applyProp(el, key, value, scope) {
99
109
  return;
100
110
  if (normalizedKey === "ref") {
101
111
  // untracked: a ref callback that reads a signal must not subscribe the enclosing reactive child
102
- untrack(() => { value(el); });
112
+ if (typeof value === "function")
113
+ untrack(() => { value(el); });
103
114
  return;
104
115
  }
105
- if (normalizedKey in EVENT_MAP) {
106
- addEvent(el, EVENT_MAP[normalizedKey], value, scope);
116
+ // Every event prop starts with "on": checking that first keeps other props off the map lookup.
117
+ const type = normalizedKey.startsWith("on") ? EVENT_MAP.get(normalizedKey) : undefined;
118
+ if (type !== undefined) {
119
+ addEvent(el, type, value, scope);
107
120
  return;
108
121
  }
109
122
  if (typeof value === "function") {
110
- scope.effect(() => {
111
- setProp(el, normalizedKey, value());
112
- });
123
+ bindProp(el, normalizedKey, value, scope);
113
124
  return;
114
125
  }
115
126
  setProp(el, normalizedKey, value);
116
127
  }
128
+ // State the user can change behind a binding's back (typing, toggling a <details>, the media
129
+ // controls, scrolling): always written, so a re-run puts the bound value back exactly as before.
130
+ const LIVE_PROPS = new Set([
131
+ "value", "checked", "selected", "indeterminate", "selectedIndex", "open",
132
+ "muted", "volume", "currentTime", "playbackRate", "scrollTop", "scrollLeft",
133
+ ]);
134
+ const UNSET = Symbol("unset");
135
+ // One function for every binding, reading its state from the effect: no closure per binding.
136
+ function runBinding() {
137
+ const binding = this.ctx;
138
+ const value = binding.read();
139
+ // A binding re-runs when anything it read changes; most re-runs produce the same primitive,
140
+ // and skipping that write saves a DOM call and the style or attribute work behind it.
141
+ if (value === binding.last && (typeof value !== "object" || value === null))
142
+ return;
143
+ binding.last = value;
144
+ setProp(binding.el, binding.key, value);
145
+ }
146
+ function runLiveBinding() {
147
+ const binding = this.ctx;
148
+ setProp(binding.el, binding.key, binding.read());
149
+ }
150
+ function bindProp(el, key, read, scope) {
151
+ scope.contextEffect(LIVE_PROPS.has(key) ? runLiveBinding : runBinding, { el, key, read, last: UNSET });
152
+ }
153
+ function runClassBinding() {
154
+ const binding = this.ctx;
155
+ const value = binding.read();
156
+ if (value === binding.last && (typeof value !== "object" || value === null))
157
+ return;
158
+ binding.last = value;
159
+ applyClass(binding.el, value);
160
+ }
161
+ /** A reactive `class` prop, bound like any other reactive prop but with no key dispatch per run. */
162
+ export function bindClass(el, read, scope) {
163
+ // Same record shape as bindProp's, so the effects of both kinds stay one shape.
164
+ scope.contextEffect(runClassBinding, { el, key: "class", read, last: UNSET });
165
+ }
117
166
  //# sourceMappingURL=props.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"props.js","sourceRoot":"","sources":["../../src/dom/props.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"props.js","sourceRoot":"","sources":["../../src/dom/props.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function moveNode(parent: Node, node: Node, ref: Node | null): void;
2
+ export declare function moveRange(parent: Node, first: Node, last: Node, ref: Node | null): void;
3
+ export declare function removeRange(parent: Node, first: Node, last: Node): void;
4
+ //# sourceMappingURL=range.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range.d.ts","sourceRoot":"","sources":["../../src/dom/range.ts"],"names":[],"mappings":"AAOA,wBAAgB,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAOzE;AAID,wBAAgB,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAYvF;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAYvE"}
@@ -0,0 +1,43 @@
1
+ // moveBefore() keeps focus, iframes, playing media and running CSS animations/transitions of the
2
+ // moved subtree, which a remove + insert resets. It only applies inside a connected tree (both nodes
3
+ // already share the parent here), so a detached parent such as a DocumentFragment uses insertBefore.
4
+ export function moveNode(parent, node, ref) {
5
+ const target = parent;
6
+ if (target.moveBefore !== undefined && target.isConnected) {
7
+ target.moveBefore(node, ref);
8
+ }
9
+ else {
10
+ parent.insertBefore(node, ref);
11
+ }
12
+ }
13
+ // Every node from `first` to `last` (inclusive) moves, not only the tracked ones, so anything a
14
+ // nested reactive child inserted between them after mount travels with them.
15
+ export function moveRange(parent, first, last, ref) {
16
+ if (first === last) {
17
+ moveNode(parent, first, ref);
18
+ return;
19
+ }
20
+ let node = first;
21
+ for (;;) {
22
+ const next = node.nextSibling;
23
+ moveNode(parent, node, ref);
24
+ if (node === last)
25
+ return;
26
+ node = next;
27
+ }
28
+ }
29
+ export function removeRange(parent, first, last) {
30
+ if (first === last) {
31
+ parent.removeChild(first);
32
+ return;
33
+ }
34
+ let node = first;
35
+ for (;;) {
36
+ const next = node.nextSibling;
37
+ parent.removeChild(node);
38
+ if (node === last)
39
+ return;
40
+ node = next;
41
+ }
42
+ }
43
+ //# sourceMappingURL=range.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range.js","sourceRoot":"","sources":["../../src/dom/range.ts"],"names":[],"mappings":"AAIA,iGAAiG;AACjG,qGAAqG;AACrG,qGAAqG;AACrG,MAAM,UAAU,QAAQ,CAAC,MAAY,EAAE,IAAU,EAAE,GAAgB;IACjE,MAAM,MAAM,GAAG,MAAuB,CAAC;IACvC,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QAC1D,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,gGAAgG;AAChG,6EAA6E;AAC7E,MAAM,UAAU,SAAS,CAAC,MAAY,EAAE,KAAW,EAAE,IAAU,EAAE,GAAgB;IAC/E,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,IAAI,IAAI,GAAS,KAAK,CAAC;IACvB,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,WAAmB,CAAC;QACtC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QAC5B,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QAC1B,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAY,EAAE,KAAW,EAAE,IAAU;IAC/D,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,OAAO;IACT,CAAC;IACD,IAAI,IAAI,GAAS,KAAK,CAAC;IACvB,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,WAAmB,CAAC;QACtC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QAC1B,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../src/dom/remove.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAiB/C"}
1
+ {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../src/dom/remove.ts"],"names":[],"mappings":"AAMA,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAW/C"}
@@ -1,3 +1,4 @@
1
+ import { removeRange } from "./range";
1
2
  // Replaces Range.deleteContents(): creating a Range per removal is several times slower than
2
3
  // walking the siblings, and unreachable Ranges stay registered with the document until collected.
3
4
  // Walking first → last (rather than only the tracked nodes) also removes anything a nested reactive
@@ -11,13 +12,6 @@ export function removeNodes(nodes) {
11
12
  node.parentNode?.removeChild(node);
12
13
  return;
13
14
  }
14
- let node = first;
15
- while (node) {
16
- const next = node.nextSibling;
17
- parent.removeChild(node);
18
- if (node === last)
19
- return;
20
- node = next;
21
- }
15
+ removeRange(parent, first, last);
22
16
  }
23
17
  //# sourceMappingURL=remove.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"remove.js","sourceRoot":"","sources":["../../src/dom/remove.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,kGAAkG;AAClG,oGAAoG;AACpG,kFAAkF;AAClF,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC;IAEhC,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;QAClD,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;QAC7D,OAAO;IACT,CAAC;IAED,IAAI,IAAI,GAAgB,KAAK,CAAC;IAC9B,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,IAAI,GAAgB,IAAI,CAAC,WAAW,CAAC;QAC3C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QAC1B,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"remove.js","sourceRoot":"","sources":["../../src/dom/remove.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,6FAA6F;AAC7F,kGAAkG;AAClG,oGAAoG;AACpG,kFAAkF;AAClF,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC;IAEhC,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;QAClD,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;QAC7D,OAAO;IACT,CAAC;IAED,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,EAAE,KAAK,GACX,WAAW,GAAG,UAAU,CAiB1B"}
1
+ {"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,EAAE,KAAK,GACX,WAAW,GAAG,UAAU,CAmB1B"}
package/dist/element.js CHANGED
@@ -1,21 +1,23 @@
1
1
  import { mountChildren } from "./children";
2
2
  import { createElement } from "./dom/create";
3
3
  import { applyProp } from "./dom/props";
4
- import { isRecording, recordProps } from "./hydration-context";
4
+ import { recording, recordProps } from "./hydration-context";
5
5
  export function mountElement(tag, props, scope) {
6
6
  const el = createElement(tag);
7
7
  // During a hydration build pass, retain (props, scope) so reconcile() can
8
8
  // replay them onto whichever real element it ends up keeping instead.
9
- if (isRecording())
9
+ if (recording)
10
10
  recordProps(el, props, scope);
11
+ // Children before props: a prop that depends on them (a <select>'s value picking one of its
12
+ // options, a ref reading the subtree) would otherwise run against an empty element.
13
+ if (props.children !== undefined) {
14
+ mountChildren(el, props.children, scope);
15
+ }
11
16
  for (const key in props) {
12
17
  if (key === "children")
13
18
  continue;
14
19
  applyProp(el, key, props[key], scope);
15
20
  }
16
- if (props.children !== undefined) {
17
- mountChildren(el, props.children, scope);
18
- }
19
21
  return el;
20
22
  }
21
23
  //# sourceMappingURL=element.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"element.js","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAI/D,MAAM,UAAU,YAAY,CAC1B,GAAW,EACX,KAA8B,EAC9B,KAAY;IAEZ,MAAM,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAE9B,0EAA0E;IAC1E,sEAAsE;IACtE,IAAI,WAAW,EAAE;QAAE,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAEjD,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,IAAI,GAAG,KAAK,UAAU;YAAE,SAAS;QACjC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACjC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"element.js","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAI7D,MAAM,UAAU,YAAY,CAC1B,GAAW,EACX,KAA8B,EAC9B,KAAY;IAEZ,MAAM,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAE9B,0EAA0E;IAC1E,sEAAsE;IACtE,IAAI,SAAS;QAAE,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAE7C,4FAA4F;IAC5F,oFAAoF;IACpF,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACjC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,IAAI,GAAG,KAAK,UAAU;YAAE,SAAS;QACjC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
package/dist/hmr.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ import { type ComponentConstructor } from "@praxisjs/shared/internal";
2
+ import type { Scope } from "./scope";
3
+ /** A mounted instance of a registered component: what it needs to be mounted again in place. */
4
+ export interface HotInstance {
5
+ ctor: ComponentConstructor;
6
+ props: Record<string, unknown>;
7
+ parentScope: Scope;
8
+ scope: Scope;
9
+ start: Comment;
10
+ end: Comment;
11
+ }
12
+ /** True once a component class was registered: mountComponent then tracks hot instances. */
13
+ export declare let hotEnabled: boolean;
14
+ /** Set by the component module, which owns mounting (kept out of here to avoid an import cycle). */
15
+ export declare function setHotRemount(fn: (hot: HotInstance, ctor: ComponentConstructor) => void): void;
16
+ /** The newest class registered under the id of `ctor`, or `ctor` itself. */
17
+ export declare function latestClass(ctor: ComponentConstructor): ComponentConstructor;
18
+ export declare function isHotClass(ctor: ComponentConstructor): boolean;
19
+ /** Records a mounted instance of a registered class until its scope is disposed. */
20
+ export declare function trackHotInstance(hot: HotInstance): void;
21
+ /**
22
+ * Registers `ctor` under `id`. Called by the code the Vite plugin appends to each module in
23
+ * development, every time the module runs. Mounted instances of a class registered before under
24
+ * the same id are mounted again with `ctor`, in one microtask for every class of the update, so a
25
+ * parent and its children edited together render once. Returns false for a class that is not a
26
+ * component, which is not registered.
27
+ */
28
+ export declare function registerHot(ctor: unknown, id: string): boolean;
29
+ /**
30
+ * Whether an updated module can replace its previous version in place: every export is a
31
+ * registered component class. Anything else (a helper, a constant, a store) may be held by the
32
+ * modules that import it, so the update has to reach them (Vite then re-runs or reloads them).
33
+ */
34
+ export declare function acceptsHotUpdate(module: Record<string, unknown> | undefined): boolean;
35
+ //# sourceMappingURL=hmr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEnF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AASrC,gGAAgG;AAChG,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,WAAW,EAAE,KAAK,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;CACd;AAOD,4FAA4F;AAC5F,eAAO,IAAI,UAAU,SAAQ,CAAC;AAS9B,oGAAoG;AACpG,wBAAgB,aAAa,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,oBAAoB,KAAK,IAAI,GAAG,IAAI,CAE9F;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,IAAI,EAAE,oBAAoB,GAAG,oBAAoB,CAG5E;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAE9D;AAED,oFAAoF;AACpF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAIvD;AAsBD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAa9D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,OAAO,CAIrF"}
package/dist/hmr.js ADDED
@@ -0,0 +1,85 @@
1
+ import { isComponent } from "@praxisjs/shared/internal";
2
+ /** True once a component class was registered: mountComponent then tracks hot instances. */
3
+ export let hotEnabled = false;
4
+ // A WeakMap, not a static property: a subclass would inherit a property and resolve to its base.
5
+ const ids = new WeakMap();
6
+ const records = new Map();
7
+ const stale = new Set();
8
+ let remount = null;
9
+ /** Set by the component module, which owns mounting (kept out of here to avoid an import cycle). */
10
+ export function setHotRemount(fn) {
11
+ remount = fn;
12
+ }
13
+ /** The newest class registered under the id of `ctor`, or `ctor` itself. */
14
+ export function latestClass(ctor) {
15
+ const id = ids.get(ctor);
16
+ return id === undefined ? ctor : records.get(id).current;
17
+ }
18
+ export function isHotClass(ctor) {
19
+ return ids.has(ctor);
20
+ }
21
+ /** Records a mounted instance of a registered class until its scope is disposed. */
22
+ export function trackHotInstance(hot) {
23
+ const record = records.get(ids.get(hot.ctor));
24
+ record.instances.add(hot);
25
+ hot.scope.add(() => { record.instances.delete(hot); });
26
+ }
27
+ function flush() {
28
+ const records = [...stale];
29
+ stale.clear();
30
+ let error;
31
+ let failed = false;
32
+ for (const record of records) {
33
+ for (const hot of [...record.instances]) {
34
+ // Gone with a parent remounted before it, or already mounted with the new class.
35
+ if (!record.instances.has(hot) || hot.ctor === record.current)
36
+ continue;
37
+ try {
38
+ remount(hot, record.current);
39
+ }
40
+ catch (e) {
41
+ if (!failed)
42
+ error = e;
43
+ failed = true;
44
+ }
45
+ }
46
+ }
47
+ if (failed)
48
+ throw error;
49
+ }
50
+ /**
51
+ * Registers `ctor` under `id`. Called by the code the Vite plugin appends to each module in
52
+ * development, every time the module runs. Mounted instances of a class registered before under
53
+ * the same id are mounted again with `ctor`, in one microtask for every class of the update, so a
54
+ * parent and its children edited together render once. Returns false for a class that is not a
55
+ * component, which is not registered.
56
+ */
57
+ export function registerHot(ctor, id) {
58
+ if (!isComponent(ctor))
59
+ return false;
60
+ hotEnabled = true;
61
+ ids.set(ctor, id);
62
+ const record = records.get(id);
63
+ if (record === undefined) {
64
+ records.set(id, { current: ctor, instances: new Set() });
65
+ }
66
+ else if (record.current !== ctor) {
67
+ record.current = ctor;
68
+ if (stale.size === 0)
69
+ queueMicrotask(flush);
70
+ stale.add(record);
71
+ }
72
+ return true;
73
+ }
74
+ /**
75
+ * Whether an updated module can replace its previous version in place: every export is a
76
+ * registered component class. Anything else (a helper, a constant, a store) may be held by the
77
+ * modules that import it, so the update has to reach them (Vite then re-runs or reloads them).
78
+ */
79
+ export function acceptsHotUpdate(module) {
80
+ if (module === undefined)
81
+ return false;
82
+ const values = Object.values(module);
83
+ return values.length > 0 && values.every((value) => typeof value === "function" && ids.has(value));
84
+ }
85
+ //# sourceMappingURL=hmr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmr.js","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"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"}