@domql/element 3.3.7 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/children.js CHANGED
@@ -16,13 +16,19 @@ import {
16
16
  matchesComponentNaming
17
17
  } from '@domql/utils'
18
18
 
19
- const shallowChildrenEqual = (a, b) => {
19
+ const deepChildrenEqual = (a, b) => {
20
20
  if (a === b) return true
21
21
  if (!a || !b) return false
22
+ const typeA = typeof a
23
+ const typeB = typeof b
24
+ // Functions in children data are structural definitions (event handlers,
25
+ // conditions) that get new references each call but are logically equal
26
+ if (typeA === 'function' && typeB === 'function') return true
27
+ if (typeA !== typeB) return false
22
28
  if (isArray(a) && isArray(b)) {
23
29
  if (a.length !== b.length) return false
24
30
  for (let i = 0; i < a.length; i++) {
25
- if (a[i] !== b[i]) return false
31
+ if (!deepChildrenEqual(a[i], b[i])) return false
26
32
  }
27
33
  return true
28
34
  }
@@ -32,7 +38,7 @@ const shallowChildrenEqual = (a, b) => {
32
38
  if (keysA.length !== keysB.length) return false
33
39
  for (let i = 0; i < keysA.length; i++) {
34
40
  const key = keysA[i]
35
- if (a[key] !== b[key]) return false
41
+ if (!deepChildrenEqual(a[key], b[key])) return false
36
42
  }
37
43
  return true
38
44
  }
@@ -95,7 +101,7 @@ export function setChildren (param, element, opts) {
95
101
 
96
102
  let cloned
97
103
  if (ref.__childrenCache) {
98
- if (shallowChildrenEqual(children, ref.__childrenCache)) {
104
+ if (deepChildrenEqual(children, ref.__childrenCache)) {
99
105
  ref.__noChildrenDifference = true
100
106
  } else {
101
107
  cloned = deepClone(children)
@@ -105,6 +111,8 @@ export function setChildren (param, element, opts) {
105
111
  } else {
106
112
  cloned = deepClone(children)
107
113
  ref.__childrenCache = cloned
114
+ // First evaluation during update - no cache to compare against, so don't
115
+ // assume children match. State-dependent children may have changed since creation.
108
116
  }
109
117
 
110
118
  if (isObject(children) || isArray(children)) {
@@ -23,13 +23,17 @@ __export(children_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(children_exports);
25
25
  var import_utils = require("@domql/utils");
26
- const shallowChildrenEqual = (a, b) => {
26
+ const deepChildrenEqual = (a, b) => {
27
27
  if (a === b) return true;
28
28
  if (!a || !b) return false;
29
+ const typeA = typeof a;
30
+ const typeB = typeof b;
31
+ if (typeA === "function" && typeB === "function") return true;
32
+ if (typeA !== typeB) return false;
29
33
  if ((0, import_utils.isArray)(a) && (0, import_utils.isArray)(b)) {
30
34
  if (a.length !== b.length) return false;
31
35
  for (let i = 0; i < a.length; i++) {
32
- if (a[i] !== b[i]) return false;
36
+ if (!deepChildrenEqual(a[i], b[i])) return false;
33
37
  }
34
38
  return true;
35
39
  }
@@ -39,7 +43,7 @@ const shallowChildrenEqual = (a, b) => {
39
43
  if (keysA.length !== keysB.length) return false;
40
44
  for (let i = 0; i < keysA.length; i++) {
41
45
  const key = keysA[i];
42
- if (a[key] !== b[key]) return false;
46
+ if (!deepChildrenEqual(a[key], b[key])) return false;
43
47
  }
44
48
  return true;
45
49
  }
@@ -91,7 +95,7 @@ function setChildren(param, element, opts) {
91
95
  }
92
96
  let cloned;
93
97
  if (ref.__childrenCache) {
94
- if (shallowChildrenEqual(children, ref.__childrenCache)) {
98
+ if (deepChildrenEqual(children, ref.__childrenCache)) {
95
99
  ref.__noChildrenDifference = true;
96
100
  } else {
97
101
  cloned = (0, import_utils.deepClone)(children);
@@ -87,6 +87,7 @@ const update = function(params = {}, opts) {
87
87
  const hasBeforeUpdate = element.on?.beforeUpdate || element.props?.onBeforeUpdate;
88
88
  if (hasBeforeUpdate) {
89
89
  const simulate = { ...params, ...element };
90
+ Object.setPrototypeOf(simulate, Object.getPrototypeOf(element));
90
91
  const beforeUpdateReturns = (0, import_event.triggerEventOnUpdate)(
91
92
  "beforeUpdate",
92
93
  params,
@@ -145,12 +146,15 @@ const update = function(params = {}, opts) {
145
146
  options.onEachUpdate(param, element, element.state, element.context);
146
147
  }
147
148
  const childParams = params[param];
148
- if (childParams === void 0 && !options.isForced) continue;
149
- const childUpdateCall = () => update.call(prop, childParams, {
150
- ...options,
151
- currentSnapshot: snapshotOnCallee,
152
- calleeElement
153
- });
149
+ if (childParams === void 0 && !options.isForced) {
150
+ if (options.onlyUpdate) {
151
+ if (param !== options.onlyUpdate) continue;
152
+ } else if (!options.updateByState) {
153
+ continue;
154
+ }
155
+ }
156
+ const childOptions = options.onlyUpdate && param === options.onlyUpdate ? { ...options, onlyUpdate: void 0, currentSnapshot: snapshotOnCallee, calleeElement } : { ...options, currentSnapshot: snapshotOnCallee, calleeElement };
157
+ const childUpdateCall = () => update.call(prop, childParams, childOptions);
154
158
  if (lazyLoad) {
155
159
  import_utils.window.requestAnimationFrame(() => {
156
160
  childUpdateCall();
@@ -164,7 +168,7 @@ const update = function(params = {}, opts) {
164
168
  if (!preventContentUpdate) {
165
169
  const contentKey = ref.contentElementKey || "content";
166
170
  const existingContent = element[contentKey];
167
- const childrenProp = params.children || element.children;
171
+ const childrenProp = options.updateByState ? params.children || (ref.__exec?.children ? element.children : void 0) : params.children || element.children;
168
172
  if (childrenProp) {
169
173
  const content = (0, import_children.default)(childrenProp, element, opts);
170
174
  if (content && !ref.__noChildrenDifference) {
@@ -202,7 +206,7 @@ const update = function(params = {}, opts) {
202
206
  } else contentUpdateCall();
203
207
  } else {
204
208
  const content = element.children || params.content;
205
- if (content) {
209
+ if (content && !options.updateByState) {
206
210
  (0, import_set.setContent)(content, element, options);
207
211
  }
208
212
  }
@@ -13,13 +13,17 @@ import {
13
13
  isString,
14
14
  matchesComponentNaming
15
15
  } from "@domql/utils";
16
- const shallowChildrenEqual = (a, b) => {
16
+ const deepChildrenEqual = (a, b) => {
17
17
  if (a === b) return true;
18
18
  if (!a || !b) return false;
19
+ const typeA = typeof a;
20
+ const typeB = typeof b;
21
+ if (typeA === "function" && typeB === "function") return true;
22
+ if (typeA !== typeB) return false;
19
23
  if (isArray(a) && isArray(b)) {
20
24
  if (a.length !== b.length) return false;
21
25
  for (let i = 0; i < a.length; i++) {
22
- if (a[i] !== b[i]) return false;
26
+ if (!deepChildrenEqual(a[i], b[i])) return false;
23
27
  }
24
28
  return true;
25
29
  }
@@ -29,7 +33,7 @@ const shallowChildrenEqual = (a, b) => {
29
33
  if (keysA.length !== keysB.length) return false;
30
34
  for (let i = 0; i < keysA.length; i++) {
31
35
  const key = keysA[i];
32
- if (a[key] !== b[key]) return false;
36
+ if (!deepChildrenEqual(a[key], b[key])) return false;
33
37
  }
34
38
  return true;
35
39
  }
@@ -81,7 +85,7 @@ function setChildren(param, element, opts) {
81
85
  }
82
86
  let cloned;
83
87
  if (ref.__childrenCache) {
84
- if (shallowChildrenEqual(children, ref.__childrenCache)) {
88
+ if (deepChildrenEqual(children, ref.__childrenCache)) {
85
89
  ref.__noChildrenDifference = true;
86
90
  } else {
87
91
  cloned = deepClone(children);
@@ -74,6 +74,7 @@ const update = function(params = {}, opts) {
74
74
  const hasBeforeUpdate = element.on?.beforeUpdate || element.props?.onBeforeUpdate;
75
75
  if (hasBeforeUpdate) {
76
76
  const simulate = { ...params, ...element };
77
+ Object.setPrototypeOf(simulate, Object.getPrototypeOf(element));
77
78
  const beforeUpdateReturns = triggerEventOnUpdate(
78
79
  "beforeUpdate",
79
80
  params,
@@ -132,12 +133,15 @@ const update = function(params = {}, opts) {
132
133
  options.onEachUpdate(param, element, element.state, element.context);
133
134
  }
134
135
  const childParams = params[param];
135
- if (childParams === void 0 && !options.isForced) continue;
136
- const childUpdateCall = () => update.call(prop, childParams, {
137
- ...options,
138
- currentSnapshot: snapshotOnCallee,
139
- calleeElement
140
- });
136
+ if (childParams === void 0 && !options.isForced) {
137
+ if (options.onlyUpdate) {
138
+ if (param !== options.onlyUpdate) continue;
139
+ } else if (!options.updateByState) {
140
+ continue;
141
+ }
142
+ }
143
+ const childOptions = options.onlyUpdate && param === options.onlyUpdate ? { ...options, onlyUpdate: void 0, currentSnapshot: snapshotOnCallee, calleeElement } : { ...options, currentSnapshot: snapshotOnCallee, calleeElement };
144
+ const childUpdateCall = () => update.call(prop, childParams, childOptions);
141
145
  if (lazyLoad) {
142
146
  window.requestAnimationFrame(() => {
143
147
  childUpdateCall();
@@ -151,7 +155,7 @@ const update = function(params = {}, opts) {
151
155
  if (!preventContentUpdate) {
152
156
  const contentKey = ref.contentElementKey || "content";
153
157
  const existingContent = element[contentKey];
154
- const childrenProp = params.children || element.children;
158
+ const childrenProp = options.updateByState ? params.children || (ref.__exec?.children ? element.children : void 0) : params.children || element.children;
155
159
  if (childrenProp) {
156
160
  const content = setChildren(childrenProp, element, opts);
157
161
  if (content && !ref.__noChildrenDifference) {
@@ -189,7 +193,7 @@ const update = function(params = {}, opts) {
189
193
  } else contentUpdateCall();
190
194
  } else {
191
195
  const content = element.children || params.content;
192
- if (content) {
196
+ if (content && !options.updateByState) {
193
197
  setContent(content, element, options);
194
198
  }
195
199
  }
@@ -2640,13 +2640,17 @@ ${element}` : "";
2640
2640
  };
2641
2641
 
2642
2642
  // children.js
2643
- var shallowChildrenEqual = (a, b) => {
2643
+ var deepChildrenEqual = (a, b) => {
2644
2644
  if (a === b) return true;
2645
2645
  if (!a || !b) return false;
2646
+ const typeA = typeof a;
2647
+ const typeB = typeof b;
2648
+ if (typeA === "function" && typeB === "function") return true;
2649
+ if (typeA !== typeB) return false;
2646
2650
  if (isArray(a) && isArray(b)) {
2647
2651
  if (a.length !== b.length) return false;
2648
2652
  for (let i = 0; i < a.length; i++) {
2649
- if (a[i] !== b[i]) return false;
2653
+ if (!deepChildrenEqual(a[i], b[i])) return false;
2650
2654
  }
2651
2655
  return true;
2652
2656
  }
@@ -2656,7 +2660,7 @@ ${element}` : "";
2656
2660
  if (keysA.length !== keysB.length) return false;
2657
2661
  for (let i = 0; i < keysA.length; i++) {
2658
2662
  const key = keysA[i];
2659
- if (a[key] !== b[key]) return false;
2663
+ if (!deepChildrenEqual(a[key], b[key])) return false;
2660
2664
  }
2661
2665
  return true;
2662
2666
  }
@@ -2708,7 +2712,7 @@ ${element}` : "";
2708
2712
  }
2709
2713
  let cloned;
2710
2714
  if (ref.__childrenCache) {
2711
- if (shallowChildrenEqual(children, ref.__childrenCache)) {
2715
+ if (deepChildrenEqual(children, ref.__childrenCache)) {
2712
2716
  ref.__noChildrenDifference = true;
2713
2717
  } else {
2714
2718
  cloned = deepClone(children);
@@ -3326,6 +3330,7 @@ ${element}` : "";
3326
3330
  const hasBeforeUpdate = element.on?.beforeUpdate || element.props?.onBeforeUpdate;
3327
3331
  if (hasBeforeUpdate) {
3328
3332
  const simulate = { ...params, ...element };
3333
+ Object.setPrototypeOf(simulate, Object.getPrototypeOf(element));
3329
3334
  const beforeUpdateReturns = triggerEventOnUpdate(
3330
3335
  "beforeUpdate",
3331
3336
  params,
@@ -3384,12 +3389,15 @@ ${element}` : "";
3384
3389
  options.onEachUpdate(param, element, element.state, element.context);
3385
3390
  }
3386
3391
  const childParams = params[param];
3387
- if (childParams === void 0 && !options.isForced) continue;
3388
- const childUpdateCall = () => update2.call(prop, childParams, {
3389
- ...options,
3390
- currentSnapshot: snapshotOnCallee,
3391
- calleeElement
3392
- });
3392
+ if (childParams === void 0 && !options.isForced) {
3393
+ if (options.onlyUpdate) {
3394
+ if (param !== options.onlyUpdate) continue;
3395
+ } else if (!options.updateByState) {
3396
+ continue;
3397
+ }
3398
+ }
3399
+ const childOptions = options.onlyUpdate && param === options.onlyUpdate ? { ...options, onlyUpdate: void 0, currentSnapshot: snapshotOnCallee, calleeElement } : { ...options, currentSnapshot: snapshotOnCallee, calleeElement };
3400
+ const childUpdateCall = () => update2.call(prop, childParams, childOptions);
3393
3401
  if (lazyLoad) {
3394
3402
  window2.requestAnimationFrame(() => {
3395
3403
  childUpdateCall();
@@ -3403,7 +3411,7 @@ ${element}` : "";
3403
3411
  if (!preventContentUpdate) {
3404
3412
  const contentKey = ref.contentElementKey || "content";
3405
3413
  const existingContent = element[contentKey];
3406
- const childrenProp = params.children || element.children;
3414
+ const childrenProp = options.updateByState ? params.children || (ref.__exec?.children ? element.children : void 0) : params.children || element.children;
3407
3415
  if (childrenProp) {
3408
3416
  const content = children_default(childrenProp, element, opts);
3409
3417
  if (content && !ref.__noChildrenDifference) {
@@ -3441,7 +3449,7 @@ ${element}` : "";
3441
3449
  } else contentUpdateCall();
3442
3450
  } else {
3443
3451
  const content = element.children || params.content;
3444
- if (content) {
3452
+ if (content && !options.updateByState) {
3445
3453
  setContent(content, element, options);
3446
3454
  }
3447
3455
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@domql/element",
3
- "version": "3.3.7",
3
+ "version": "3.4.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "module": "./dist/esm/index.js",
@@ -47,10 +47,10 @@
47
47
  "build:iife": "cross-env NODE_ENV=$NODE_ENV esbuild index.js --bundle --target=es2020 --format=iife --global-name=DomqlElement --outfile=dist/iife/index.js --define:process.env.NODE_ENV=process.env.NODE_ENV"
48
48
  },
49
49
  "dependencies": {
50
- "@domql/report": "^3.3.7",
51
- "@domql/state": "^3.3.7",
52
- "@domql/utils": "^3.3.7",
53
- "attrs-in-props": "^3.3.7"
50
+ "@domql/report": "^3.4.1",
51
+ "@domql/state": "^3.4.1",
52
+ "@domql/utils": "^3.4.1",
53
+ "attrs-in-props": "^3.4.1"
54
54
  },
55
55
  "gitHead": "9fc1b79b41cdc725ca6b24aec64920a599634681",
56
56
  "devDependencies": {
package/update.js CHANGED
@@ -99,6 +99,7 @@ export const update = function (params = {}, opts) {
99
99
  const hasBeforeUpdate = element.on?.beforeUpdate || element.props?.onBeforeUpdate
100
100
  if (hasBeforeUpdate) {
101
101
  const simulate = { ...params, ...element }
102
+ Object.setPrototypeOf(simulate, Object.getPrototypeOf(element))
102
103
  const beforeUpdateReturns = triggerEventOnUpdate(
103
104
  'beforeUpdate',
104
105
  params,
@@ -195,14 +196,21 @@ export const update = function (params = {}, opts) {
195
196
  }
196
197
 
197
198
  const childParams = params[param]
198
- if (childParams === undefined && !options.isForced) continue
199
+ if (childParams === undefined && !options.isForced) {
200
+ if (options.onlyUpdate) {
201
+ if (param !== options.onlyUpdate) continue
202
+ } else if (!options.updateByState) {
203
+ continue
204
+ }
205
+ }
206
+
207
+ // Once we reach the onlyUpdate target, clear it so its children update normally
208
+ const childOptions = options.onlyUpdate && param === options.onlyUpdate
209
+ ? { ...options, onlyUpdate: undefined, currentSnapshot: snapshotOnCallee, calleeElement }
210
+ : { ...options, currentSnapshot: snapshotOnCallee, calleeElement }
199
211
 
200
212
  const childUpdateCall = () =>
201
- update.call(prop, childParams, {
202
- ...options,
203
- currentSnapshot: snapshotOnCallee,
204
- calleeElement
205
- })
213
+ update.call(prop, childParams, childOptions)
206
214
 
207
215
  if (lazyLoad) {
208
216
  window.requestAnimationFrame(() => {
@@ -218,12 +226,16 @@ export const update = function (params = {}, opts) {
218
226
  }
219
227
 
220
228
  if (!preventContentUpdate) {
221
- // Update existing content element if it's a live DOMQL element
222
229
  const contentKey = ref.contentElementKey || 'content'
223
230
  const existingContent = element[contentKey]
224
231
 
225
- // Re-evaluate children if the element has a children property
226
- const childrenProp = params.children || element.children
232
+ // During state-triggered cascading updates (updateByState), skip static
233
+ // children but still re-process dynamic children (originally functions, already
234
+ // re-evaluated by throughUpdatedExec). Check ref.__exec.children to detect these.
235
+ const childrenProp = options.updateByState
236
+ ? (params.children || (ref.__exec?.children ? element.children : undefined))
237
+ : (params.children || element.children)
238
+
227
239
  if (childrenProp) {
228
240
  const content = setChildren(childrenProp, element, opts)
229
241
  if (content && !ref.__noChildrenDifference) {
@@ -265,7 +277,7 @@ export const update = function (params = {}, opts) {
265
277
  } else contentUpdateCall()
266
278
  } else {
267
279
  const content = element.children || params.content
268
- if (content) {
280
+ if (content && !options.updateByState) {
269
281
  setContent(content, element, options)
270
282
  }
271
283
  }