@editframe/elements 0.18.20-beta.0 → 0.18.21-beta.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.
@@ -187,7 +187,6 @@ export declare const deepGetElementsWithFrameTasks: (element: Element, elements?
187
187
  }>) => (HTMLElement & {
188
188
  frameTask: Task;
189
189
  })[];
190
- export declare const clearTemporalCacheForElement: (element: Element) => void;
191
190
  export declare const shallowGetTemporalElements: (element: Element, temporals?: TemporalMixinInterface[]) => TemporalMixinInterface[];
192
191
  export declare class OwnCurrentTimeController implements ReactiveController {
193
192
  private host;
@@ -15,21 +15,17 @@ const deepGetElementsWithFrameTasks = (element, elements = []) => {
15
15
  return elements;
16
16
  };
17
17
  let temporalCache;
18
- let modifiedElements = /* @__PURE__ */ new WeakSet();
19
18
  const resetTemporalCache = () => {
20
19
  temporalCache = /* @__PURE__ */ new Map();
21
- modifiedElements = /* @__PURE__ */ new WeakSet();
22
20
  if (typeof requestAnimationFrame !== "undefined") requestAnimationFrame(resetTemporalCache);
23
21
  };
24
22
  resetTemporalCache();
25
- const clearTemporalCacheForElement = (element) => {
26
- temporalCache.delete(element);
27
- modifiedElements.add(element);
28
- };
29
23
  const shallowGetTemporalElements = (element, temporals = []) => {
30
- temporals.length = 0;
24
+ const cachedResult = temporalCache.get(element);
25
+ if (cachedResult) return cachedResult;
31
26
  for (const child of element.children) if (isEFTemporal(child)) temporals.push(child);
32
27
  else shallowGetTemporalElements(child, temporals);
28
+ temporalCache.set(element, temporals);
33
29
  return temporals;
34
30
  };
35
31
  var OwnCurrentTimeController = class {
@@ -285,4 +281,4 @@ const EFTemporal = (superClass) => {
285
281
  Object.defineProperty(TemporalMixinClass.prototype, EF_TEMPORAL, { value: true });
286
282
  return TemporalMixinClass;
287
283
  };
288
- export { EFTemporal, clearTemporalCacheForElement, deepGetElementsWithFrameTasks, flushStartTimeMsCache, isEFTemporal, shallowGetTemporalElements, timegroupContext };
284
+ export { EFTemporal, deepGetElementsWithFrameTasks, flushStartTimeMsCache, isEFTemporal, shallowGetTemporalElements, timegroupContext };
@@ -53,7 +53,6 @@ let EFTimegroup = class EFTimegroup$1 extends EFTemporal(LitElement) {
53
53
  }
54
54
  #currentTime = 0;
55
55
  #resizeObserver;
56
- #childObserver;
57
56
  set currentTime(time) {
58
57
  const newTime = Math.max(0, Math.min(time, this.durationMs / 1e3));
59
58
  if (this.isRootTimegroup && this.isFrameUpdateInProgress) {
@@ -129,25 +128,6 @@ let EFTimegroup = class EFTimegroup$1 extends EFTemporal(LitElement) {
129
128
  });
130
129
  if (this.parentTimegroup) new TimegroupController(this.parentTimegroup, this);
131
130
  if (this.shouldWrapWithWorkbench()) this.wrapWithWorkbench();
132
- this.#childObserver = new MutationObserver((mutations) => {
133
- let shouldUpdate = false;
134
- for (const mutation of mutations) if (mutation.type === "childList") shouldUpdate = true;
135
- else if (mutation.type === "attributes") {
136
- if (mutation.attributeName === "duration" || mutation.attributeName === "mode") shouldUpdate = true;
137
- }
138
- if (shouldUpdate) {
139
- import("./EFTemporal.js").then(({ clearTemporalCacheForElement }) => {
140
- clearTemporalCacheForElement(this);
141
- });
142
- this.requestUpdate();
143
- }
144
- });
145
- this.#childObserver.observe(this, {
146
- childList: true,
147
- subtree: true,
148
- attributes: true,
149
- attributeFilter: ["duration", "mode"]
150
- });
151
131
  requestAnimationFrame(() => {
152
132
  this.updateAnimations();
153
133
  });
@@ -155,7 +135,6 @@ let EFTimegroup = class EFTimegroup$1 extends EFTemporal(LitElement) {
155
135
  disconnectedCallback() {
156
136
  super.disconnectedCallback();
157
137
  this.#resizeObserver?.disconnect();
158
- this.#childObserver?.disconnect();
159
138
  }
160
139
  get storageKey() {
161
140
  if (!this.id) throw new Error("Timegroup must have an id to use localStorage.");
@@ -4,7 +4,7 @@ declare class TestContext extends TestContext_base {
4
4
  }
5
5
  declare const TestContextElement_base: (new (...args: any[]) => import('./ContextMixin.js').ContextMixinInterface) & typeof LitElement;
6
6
  declare class TestContextElement extends TestContextElement_base {
7
- render(): import('../elements/EFTimegroup.js').EFTimegroup & Element;
7
+ render(): import('lit-html').TemplateResult<1>;
8
8
  }
9
9
  declare global {
10
10
  interface HTMLElementTagNameMap {
@@ -149,7 +149,7 @@ function ContextMixin(superClass) {
149
149
  if (newTimegroup !== this.targetTimegroup) {
150
150
  this.targetTimegroup = newTimegroup;
151
151
  shouldUpdate = true;
152
- }
152
+ } else if (mutation.target instanceof Element && (mutation.target.tagName === "EF-TIMEGROUP" || mutation.target.closest("ef-timegroup"))) shouldUpdate = true;
153
153
  } else if (mutation.type === "attributes") {
154
154
  if (mutation.attributeName === "duration" || mutation.attributeName === "mode" || mutation.target instanceof Element && (mutation.target.tagName === "EF-TIMEGROUP" || mutation.target.closest("ef-timegroup"))) shouldUpdate = true;
155
155
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@editframe/elements",
3
- "version": "0.18.20-beta.0",
3
+ "version": "0.18.21-beta.0",
4
4
  "description": "",
5
5
  "exports": {
6
6
  ".": {
@@ -27,7 +27,7 @@
27
27
  "license": "UNLICENSED",
28
28
  "dependencies": {
29
29
  "@bramus/style-observer": "^1.3.0",
30
- "@editframe/assets": "0.18.20-beta.0",
30
+ "@editframe/assets": "0.18.21-beta.0",
31
31
  "@lit/context": "^1.1.2",
32
32
  "@lit/task": "^1.0.1",
33
33
  "d3": "^7.9.0",
@@ -236,32 +236,22 @@ export const deepGetElementsWithFrameTasks = (
236
236
  };
237
237
 
238
238
  let temporalCache: Map<Element, TemporalMixinInterface[]>;
239
- let modifiedElements = new WeakSet<Element>();
240
-
241
239
  const resetTemporalCache = () => {
242
240
  temporalCache = new Map();
243
- modifiedElements = new WeakSet();
244
241
  if (typeof requestAnimationFrame !== "undefined") {
245
242
  requestAnimationFrame(resetTemporalCache);
246
243
  }
247
244
  };
248
245
  resetTemporalCache();
249
246
 
250
- export const clearTemporalCacheForElement = (element: Element) => {
251
- temporalCache.delete(element);
252
- modifiedElements.add(element);
253
- };
254
-
255
247
  export const shallowGetTemporalElements = (
256
248
  element: Element,
257
249
  temporals: TemporalMixinInterface[] = [],
258
250
  ) => {
259
- // Temporarily disable caching to ensure reactivity works correctly
260
- // TODO: Implement proper cache invalidation mechanism
261
-
262
- // Clear the temporals array to ensure fresh results
263
- temporals.length = 0;
264
-
251
+ const cachedResult = temporalCache.get(element);
252
+ if (cachedResult) {
253
+ return cachedResult;
254
+ }
265
255
  for (const child of element.children) {
266
256
  if (isEFTemporal(child)) {
267
257
  temporals.push(child);
@@ -269,7 +259,7 @@ export const shallowGetTemporalElements = (
269
259
  shallowGetTemporalElements(child, temporals);
270
260
  }
271
261
  }
272
-
262
+ temporalCache.set(element, temporals);
273
263
  return temporals;
274
264
  };
275
265
 
@@ -73,7 +73,6 @@ export class EFTimegroup extends EFTemporal(LitElement) {
73
73
  fit: "none" | "contain" | "cover" = "none";
74
74
 
75
75
  #resizeObserver?: ResizeObserver;
76
- #childObserver?: MutationObserver;
77
76
 
78
77
  @property({ type: Number, attribute: "currenttime" })
79
78
  set currentTime(time: number) {
@@ -186,44 +185,6 @@ export class EFTimegroup extends EFTemporal(LitElement) {
186
185
  this.wrapWithWorkbench();
187
186
  }
188
187
 
189
- // Set up observer to detect child changes that affect duration
190
- this.#childObserver = new MutationObserver((mutations) => {
191
- let shouldUpdate = false;
192
-
193
- for (const mutation of mutations) {
194
- if (mutation.type === "childList") {
195
- // Child added/removed - this affects duration for contain/sequence modes
196
- shouldUpdate = true;
197
- } else if (mutation.type === "attributes") {
198
- // Attribute changes that might affect duration
199
- if (
200
- mutation.attributeName === "duration" ||
201
- mutation.attributeName === "mode"
202
- ) {
203
- shouldUpdate = true;
204
- }
205
- }
206
- }
207
-
208
- if (shouldUpdate) {
209
- // Clear the temporal cache for this element to ensure childTemporals is up to date
210
- import("./EFTemporal.js").then(({ clearTemporalCacheForElement }) => {
211
- clearTemporalCacheForElement(this);
212
- });
213
-
214
- // Trigger an update to recalculate computed properties
215
- this.requestUpdate();
216
- }
217
- });
218
-
219
- // Observe this element for child changes
220
- this.#childObserver.observe(this, {
221
- childList: true,
222
- subtree: true,
223
- attributes: true,
224
- attributeFilter: ["duration", "mode"],
225
- });
226
-
227
188
  requestAnimationFrame(() => {
228
189
  this.updateAnimations();
229
190
  });
@@ -232,7 +193,6 @@ export class EFTimegroup extends EFTemporal(LitElement) {
232
193
  disconnectedCallback() {
233
194
  super.disconnectedCallback();
234
195
  this.#resizeObserver?.disconnect();
235
- this.#childObserver?.disconnect();
236
196
  }
237
197
 
238
198
  get storageKey() {
@@ -1,4 +1,4 @@
1
- import { LitElement } from "lit";
1
+ import { html, LitElement } from "lit";
2
2
  import { customElement } from "lit/decorators/custom-element.js";
3
3
  import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
4
4
 
@@ -13,7 +13,7 @@ class TestContext extends ContextMixin(LitElement) {}
13
13
  @customElement("test-context-reactivity")
14
14
  class TestContextElement extends ContextMixin(LitElement) {
15
15
  render() {
16
- return document.createElement("ef-timegroup");
16
+ return html`<slot></slot>`;
17
17
  }
18
18
  }
19
19
 
@@ -631,6 +631,9 @@ describe("ContextMixin", () => {
631
631
  await timegroup.updateComplete;
632
632
  await newChild.updateComplete;
633
633
 
634
+ // Wait for next animation frame to ensure temporal cache is cleared
635
+ await new Promise((resolve) => requestAnimationFrame(resolve));
636
+
634
637
  // Duration should now be 15s (the max of all children)
635
638
  expect(element.targetTimegroup?.durationMs).toBe(15000);
636
639
 
@@ -250,6 +250,13 @@ export function ContextMixin<T extends Constructor<LitElement>>(superClass: T) {
250
250
  if (newTimegroup !== this.targetTimegroup) {
251
251
  this.targetTimegroup = newTimegroup;
252
252
  shouldUpdate = true;
253
+ } else if (
254
+ mutation.target instanceof Element &&
255
+ (mutation.target.tagName === "EF-TIMEGROUP" ||
256
+ mutation.target.closest("ef-timegroup"))
257
+ ) {
258
+ // Handle childList changes within existing timegroups
259
+ shouldUpdate = true;
253
260
  }
254
261
  } else if (mutation.type === "attributes") {
255
262
  // Watch for attribute changes that might affect duration