Skills/Editor Toolkit/Active Root Temporal Element

ef-active-root-temporal

Attributes

canvas
string

Canvas element ID or selector to bind to

Properties

activeRootTemporal
TemporalMixinInterface & HTMLElement | null

Currently active root temporal element

Displays the ID of the active root temporal element from a canvas.

Basic Usage

Show the active root temporal ID:

<ef-active-root-temporal canvas="my-canvas">None</ef-active-root-temporal>
<ef-canvas id="my-canvas">
<ef-timegroup id="scene-1">
<!-- Content -->
</ef-timegroup>
<ef-timegroup id="scene-2">
<!-- Content -->
</ef-timegroup>
</ef-canvas>

When you select an element in the canvas, the active root temporal ID displays.

Canvas Binding

Bind to a canvas by ID or selector:

By ID

<ef-active-root-temporal canvas="my-canvas"></ef-active-root-temporal>
<ef-canvas id="my-canvas"></ef-canvas>

By Selector

<ef-active-root-temporal canvas=".editor-canvas"></ef-active-root-temporal>
<ef-canvas class="editor-canvas"></ef-canvas>

Nearest Ancestor

Omit canvas attribute to use nearest ancestor:

<ef-canvas>
<ef-active-root-temporal></ef-active-root-temporal>
</ef-canvas>

Active Root Temporal

The active root temporal is the topmost timegroup containing the selected element:

<ef-canvas id="canvas">
<ef-timegroup id="root-1">
<ef-timegroup id="child-1">
<div id="element-1">Content</div>
</ef-timegroup>
</ef-timegroup>
</ef-canvas>

When element-1 is selected, active root temporal is root-1.

Display Content

Default Content

Show ID of active root temporal:

<ef-active-root-temporal canvas="canvas"></ef-active-root-temporal>
<!-- Displays: "root-1" when root-1 is active -->

Fallback Content

Provide fallback text for when no root is active:

<ef-active-root-temporal canvas="canvas">
No selection
</ef-active-root-temporal>
<!-- Displays: "No selection" when nothing is selected -->

Events

Listen for changes:

const canvas = document.querySelector('ef-canvas');
canvas.addEventListener('activeroottemporalchange', (e) => {
const { activeRootTemporal } = e.detail;
console.log('Active root:', activeRootTemporal?.id);
});

The canvas fires this event, not ef-active-root-temporal.

Use Cases

Timeline Scrubbing

Use active root temporal to determine which timeline to scrub:

const activeRootDisplay = document.querySelector('ef-active-root-temporal');
const canvas = document.querySelector('ef-canvas');
canvas.addEventListener('activeroottemporalchange', (e) => {
const rootTemporal = e.detail.activeRootTemporal;
if (rootTemporal) {
// Update scrubber to control this timegroup
scrubber.target = rootTemporal.id;
}
});

Playback Controls

Connect playback controls to active root:

const canvas = document.querySelector('ef-canvas');
const controls = document.querySelector('ef-controls');
canvas.addEventListener('activeroottemporalchange', (e) => {
if (e.detail.activeRootTemporal) {
controls.target = e.detail.activeRootTemporal.id;
}
});

Context Display

Show which composition is active:

<div class="toolbar">
<span class="label">Active Composition:</span>
<ef-active-root-temporal canvas="canvas" class="font-mono">
None
</ef-active-root-temporal>
</div>

Multiple Canvases

Use separate instances for multiple canvases:

<ef-active-root-temporal canvas="canvas-1">None</ef-active-root-temporal>
<ef-canvas id="canvas-1"></ef-canvas>
<ef-active-root-temporal canvas="canvas-2">None</ef-active-root-temporal>
<ef-canvas id="canvas-2"></ef-canvas>

Each instance tracks its own canvas independently.

Selection Behavior

Active root temporal updates when:

  • Element is selected in canvas
  • Selection changes to different element
  • Selection is cleared

Selection of nested elements always resolves to their root temporal ancestor.

Finding Root Temporal

The canvas walks up the DOM tree from selected element to find the topmost timegroup:

// Simplified algorithm
let current = selectedElement;
let rootTemporal = null;
while (current && current !== canvas) {
if (current.tagName === 'EF-TIMEGROUP') {
rootTemporal = current;
}
current = current.parentElement;
}
return rootTemporal;

Null State

When no element is selected or selected element has no root temporal ancestor:

const display = document.querySelector('ef-active-root-temporal');
console.log(display.activeRootTemporal); // null
// Text content shows fallback
console.log(display.textContent); // "None" (from slot content)

Temporal Mixin Interface

Active root temporal is typed as TemporalMixinInterface:

interface TemporalMixinInterface {
id: string;
durationMs: number;
currentTimeMs: number;
play(): void;
pause(): void;
// ... other temporal properties and methods
}

This ensures the element has timing capabilities.

Canvas Property

Access the bound canvas element:

const display = document.querySelector('ef-active-root-temporal');
// Canvas element reference (internal)
console.log(display.canvasElement); // EFCanvas instance

Styling

Style the display element:

ef-active-root-temporal {
display: inline-block;
font-family: monospace;
padding: 4px 8px;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 4px;
}

Reactive Updates

Display automatically updates when selection changes. No manual refresh needed.

Disconnection

When disconnected, the element:

  • Removes event listener from canvas
  • Clears active root temporal reference
  • Cleans up internal state

Initialization

On connection, the element:

  1. Finds canvas (by attribute, selector, or ancestor)
  2. Reads initial active root temporal
  3. Sets up event listener
  4. Updates display

Important Notes

  • Canvas attribute can be ID or CSS selector
  • Falls back to nearest ancestor canvas if not specified
  • Only displays root temporal elements (top-level timegroups)
  • Updates automatically - no manual refresh needed
  • Shows element ID, not a friendly name
  • Returns null when no root temporal is active