@xenosystem/blocks 0.13.22 → 0.13.23

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.
@@ -1487,9 +1487,9 @@ function LayersPanelView({ controller }) {
1487
1487
  const getSnapshot = useCallback(() => controller.getRevision(), [controller]);
1488
1488
  useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
1489
1489
  const view = layersViewState(controller);
1490
- const ui8 = (intent) => applyLayersUi(controller, intent);
1490
+ const ui9 = (intent) => applyLayersUi(controller, intent);
1491
1491
  return /* @__PURE__ */ jsxs(Column, { className: "xeno-layers-panel", children: [
1492
- view.searchShown ? /* @__PURE__ */ jsx2(Toolbar, { children: /* @__PURE__ */ jsx2(SearchField, { value: view.filter, onChange: (v) => ui8({ kind: "filter", value: v }), placeholder: "Search layers", label: "Search layers" }) }) : null,
1492
+ view.searchShown ? /* @__PURE__ */ jsx2(Toolbar, { children: /* @__PURE__ */ jsx2(SearchField, { value: view.filter, onChange: (v) => ui9({ kind: "filter", value: v }), placeholder: "Search layers", label: "Search layers" }) }) : null,
1493
1493
  /* @__PURE__ */ jsxs(LayersScroller, { controller, children: [
1494
1494
  /* @__PURE__ */ jsx2(RowList, { role: "tree", "aria-label": "Layers", children: /* @__PURE__ */ jsx2(VirtualWindow, { totalHeight: view.totalHeight, offsetTop: view.offsetTop, children: view.rows.map((row2) => /* @__PURE__ */ jsx2(LayerRow, { row: row2, thumbnailSize: view.thumbnailSize, controller }, row2.id)) }) }),
1495
1495
  view.empty ? /* @__PURE__ */ jsx2(EmptyState, { title: "No layers" }) : null
@@ -1602,7 +1602,7 @@ function LayersThumbnail({ thumbnailKey, size, controller }) {
1602
1602
  return /* @__PURE__ */ jsx2(Thumbnail, { size, data: controller.getThumbnail(thumbnailKey) });
1603
1603
  }
1604
1604
  function LayerRow({ row: row2, thumbnailSize, controller }) {
1605
- const ui8 = (intent) => applyLayersUi(controller, intent);
1605
+ const ui9 = (intent) => applyLayersUi(controller, intent);
1606
1606
  return /* @__PURE__ */ jsx2(
1607
1607
  Row,
1608
1608
  {
@@ -1617,11 +1617,11 @@ function LayerRow({ row: row2, thumbnailSize, controller }) {
1617
1617
  title: row2.title,
1618
1618
  icon: row2.hasThumbnail ? /* @__PURE__ */ jsx2(LayersThumbnail, { thumbnailKey: row2.thumbnailKey, size: thumbnailSize, controller }) : /* @__PURE__ */ jsx2(KindGlyph, {}),
1619
1619
  leading: /* @__PURE__ */ jsxs(Fragment, { children: [
1620
- row2.showVisibility ? /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(VisibilityIcon, { open: row2.visible }), label: row2.visibilityLabel, active: row2.visible, onClick: () => ui8({ kind: "toggleProp", id: row2.id, prop: "visible" }) }) : null,
1621
- row2.showLock ? /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(LockStateIcon, { locked: row2.locked }), label: row2.lockLabel, active: row2.locked, onClick: () => ui8({ kind: "toggleProp", id: row2.id, prop: "locked" }) }) : null,
1622
- row2.showSolo ? /* @__PURE__ */ jsx2(ChipToggle, { glyph: "S", label: "Solo", on: row2.solo, onChange: () => ui8({ kind: "toggleProp", id: row2.id, prop: "solo" }) }) : null,
1623
- row2.showMute ? /* @__PURE__ */ jsx2(ChipToggle, { glyph: "M", label: "Mute", on: row2.muted, onChange: () => ui8({ kind: "toggleProp", id: row2.id, prop: "muted" }) }) : null,
1624
- row2.showArm ? /* @__PURE__ */ jsx2(ChipToggle, { glyph: "R", label: "Arm", on: row2.armed, onChange: () => ui8({ kind: "toggleProp", id: row2.id, prop: "armed" }) }) : null,
1620
+ row2.showVisibility ? /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(VisibilityIcon, { open: row2.visible }), label: row2.visibilityLabel, active: row2.visible, onClick: () => ui9({ kind: "toggleProp", id: row2.id, prop: "visible" }) }) : null,
1621
+ row2.showLock ? /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(LockStateIcon, { locked: row2.locked }), label: row2.lockLabel, active: row2.locked, onClick: () => ui9({ kind: "toggleProp", id: row2.id, prop: "locked" }) }) : null,
1622
+ row2.showSolo ? /* @__PURE__ */ jsx2(ChipToggle, { glyph: "S", label: "Solo", on: row2.solo, onChange: () => ui9({ kind: "toggleProp", id: row2.id, prop: "solo" }) }) : null,
1623
+ row2.showMute ? /* @__PURE__ */ jsx2(ChipToggle, { glyph: "M", label: "Mute", on: row2.muted, onChange: () => ui9({ kind: "toggleProp", id: row2.id, prop: "muted" }) }) : null,
1624
+ row2.showArm ? /* @__PURE__ */ jsx2(ChipToggle, { glyph: "R", label: "Arm", on: row2.armed, onChange: () => ui9({ kind: "toggleProp", id: row2.id, prop: "armed" }) }) : null,
1625
1625
  row2.showColor ? /* @__PURE__ */ jsx2(ColorTag, { color: row2.colorLabel }) : null
1626
1626
  ] }),
1627
1627
  label: row2.renaming ? /* @__PURE__ */ jsx2(LayersRenameField, { id: row2.id, controller }) : row2.name,
@@ -1629,9 +1629,9 @@ function LayerRow({ row: row2, thumbnailSize, controller }) {
1629
1629
  row2.adornments.map((a) => /* @__PURE__ */ jsx2(Badge, { size: "sm", title: a.title, children: a.text }, a.key)),
1630
1630
  row2.showOpacity ? /* @__PURE__ */ jsx2(Text, { role: "number", children: row2.opacity }) : null
1631
1631
  ] }),
1632
- onExpandedChange: () => ui8({ kind: "toggleExpanded", id: row2.id }),
1633
- onDoubleClick: () => ui8({ kind: "beginRename", id: row2.id }),
1634
- onContextMenuAt: (x, y) => ui8({ kind: "contextMenu", id: row2.id, x, y })
1632
+ onExpandedChange: () => ui9({ kind: "toggleExpanded", id: row2.id }),
1633
+ onDoubleClick: () => ui9({ kind: "beginRename", id: row2.id }),
1634
+ onContextMenuAt: (x, y) => ui9({ kind: "contextMenu", id: row2.id, x, y })
1635
1635
  }
1636
1636
  );
1637
1637
  }
@@ -2023,8 +2023,8 @@ function constraintsOf(field) {
2023
2023
  scale: field.scale
2024
2024
  };
2025
2025
  }
2026
- function parseNumeric(text8) {
2027
- const trimmed = String(text8).trim();
2026
+ function parseNumeric(text9) {
2027
+ const trimmed = String(text9).trim();
2028
2028
  if (trimmed.length === 0) return { ok: false, reason: "empty" };
2029
2029
  const match = /^[+-]?(\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/.exec(trimmed);
2030
2030
  if (!match) return { ok: false, reason: "nan" };
@@ -2049,8 +2049,8 @@ function normalizeNumeric(value, c) {
2049
2049
  function formatNumeric(value, field) {
2050
2050
  if (!Number.isFinite(value)) return "";
2051
2051
  const precision = field.precision;
2052
- const text8 = typeof precision === "number" && Number.isFinite(precision) ? value.toFixed(Math.max(0, Math.floor(precision))) : String(value);
2053
- return field.unit ? `${text8}${field.unit}` : text8;
2052
+ const text9 = typeof precision === "number" && Number.isFinite(precision) ? value.toFixed(Math.max(0, Math.floor(precision))) : String(value);
2053
+ return field.unit ? `${text9}${field.unit}` : text9;
2054
2054
  }
2055
2055
  function usesLogScale(c) {
2056
2056
  return c.scale === "log" && typeof c.min === "number" && typeof c.max === "number" && c.min > 0 && c.max > c.min;
@@ -2384,44 +2384,44 @@ var InspectorPanelController = class {
2384
2384
  if (!field || !isFieldEditable(field)) return;
2385
2385
  const mixed = isFieldMixed(field);
2386
2386
  const value = this.getFieldValue(fieldId);
2387
- const text8 = mixed ? "" : field.type === "number" && typeof value === "number" ? formatNumeric(value, field) : value === void 0 || value === null ? "" : String(value);
2388
- this.drafts.set(fieldId, { text: text8, original: value });
2387
+ const text9 = mixed ? "" : field.type === "number" && typeof value === "number" ? formatNumeric(value, field) : value === void 0 || value === null ? "" : String(value);
2388
+ this.drafts.set(fieldId, { text: text9, original: value });
2389
2389
  this.focusedFieldId = fieldId;
2390
2390
  this.emitFieldFocus(fieldId);
2391
2391
  this.notify();
2392
2392
  }
2393
2393
  /** Update the draft text (typing). Emits nothing under the `blur` policy. */
2394
- setDraft(fieldId, text8) {
2394
+ setDraft(fieldId, text9) {
2395
2395
  const draft = this.drafts.get(fieldId);
2396
2396
  if (!draft) {
2397
- this.drafts.set(fieldId, { text: text8, original: this.getFieldValue(fieldId) });
2397
+ this.drafts.set(fieldId, { text: text9, original: this.getFieldValue(fieldId) });
2398
2398
  } else {
2399
- draft.text = text8;
2399
+ draft.text = text9;
2400
2400
  }
2401
2401
  const field = this.getField(fieldId);
2402
2402
  if (field && commitPolicyOf(field) === "live") {
2403
- const parsed = this.parseDraft(fieldId, text8);
2403
+ const parsed = this.parseDraft(fieldId, text9);
2404
2404
  if (parsed.ok) this.emitSet(fieldId, parsed.value);
2405
2405
  }
2406
2406
  this.notify();
2407
2407
  }
2408
2408
  /** Parse a draft string into a field-appropriate value. */
2409
- parseDraft(fieldId, text8) {
2409
+ parseDraft(fieldId, text9) {
2410
2410
  const field = this.getField(fieldId);
2411
2411
  if (!field) return { ok: false };
2412
2412
  if (field.type === "number") {
2413
- const parsed = parseNumeric(text8);
2413
+ const parsed = parseNumeric(text9);
2414
2414
  if (!parsed.ok) return { ok: false };
2415
2415
  return { ok: true, value: normalizeNumeric(parsed.value, constraintsOf(field)) };
2416
2416
  }
2417
2417
  if (field.type === "json") {
2418
2418
  try {
2419
- return { ok: true, value: JSON.parse(text8) };
2419
+ return { ok: true, value: JSON.parse(text9) };
2420
2420
  } catch {
2421
2421
  return { ok: false };
2422
2422
  }
2423
2423
  }
2424
- return { ok: true, value: text8 };
2424
+ return { ok: true, value: text9 };
2425
2425
  }
2426
2426
  /**
2427
2427
  * Commit the draft (Enter / blur). Invalid input reverts instead of committing garbage.
@@ -3347,7 +3347,7 @@ function NumberWidget({ field, controller, component }) {
3347
3347
  },
3348
3348
  [controller, editable, field.id, component]
3349
3349
  );
3350
- const text8 = component !== void 0 ? (() => {
3350
+ const text9 = component !== void 0 ? (() => {
3351
3351
  const raw = controller.getFieldValue(field.id);
3352
3352
  const v = Array.isArray(raw) ? raw[component] : void 0;
3353
3353
  return typeof v === "number" ? formatNumeric(v, field) : "";
@@ -3359,7 +3359,7 @@ function NumberWidget({ field, controller, component }) {
3359
3359
  Input2,
3360
3360
  {
3361
3361
  inputMode: "decimal",
3362
- value: text8,
3362
+ value: text9,
3363
3363
  placeholder: mixed ? controller.getMixedPlaceholder() : field.placeholder,
3364
3364
  mixed,
3365
3365
  readOnly: !editable,
@@ -3577,7 +3577,7 @@ function ActionGlyph({ glyph }) {
3577
3577
  return /* @__PURE__ */ jsx4("span", { "aria-hidden": true, children: glyph });
3578
3578
  }
3579
3579
  function SectionView({ section, controller }) {
3580
- const ui8 = (intent) => applyInspectorUi(controller, intent);
3580
+ const ui9 = (intent) => applyInspectorUi(controller, intent);
3581
3581
  const hasActions = section.actions.length > 0 || section.hasAddMenu;
3582
3582
  return /* @__PURE__ */ jsxs3(
3583
3583
  Section,
@@ -3586,13 +3586,13 @@ function SectionView({ section, controller }) {
3586
3586
  flush: true,
3587
3587
  collapsible: section.collapsible,
3588
3588
  collapsed: section.collapsed,
3589
- onCollapsedChange: () => ui8({ kind: "toggleSectionCollapsed", sectionId: section.id }),
3589
+ onCollapsedChange: () => ui9({ kind: "toggleSectionCollapsed", sectionId: section.id }),
3590
3590
  enabled: section.enabled,
3591
- onEnabledChange: () => ui8({ kind: "toggleSectionEnabled", sectionId: section.id }),
3591
+ onEnabledChange: () => ui9({ kind: "toggleSectionEnabled", sectionId: section.id }),
3592
3592
  badge: section.badge ? /* @__PURE__ */ jsx4(Badge2, { children: section.badge }) : null,
3593
3593
  actions: hasActions ? /* @__PURE__ */ jsxs3(Fragment3, { children: [
3594
- section.actions.map((action) => /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(ActionGlyph, { glyph: action.glyph }), label: action.label, disabled: action.disabled, onClick: () => ui8({ kind: "runAction", sectionId: section.id, actionId: action.id }) }, action.id)),
3595
- section.hasAddMenu ? /* @__PURE__ */ jsx4(Menu, { size: "sm", trigger: "\uFF0B", items: section.addItems, label: section.addLabel, align: "end", onSelect: (id) => ui8({ kind: "addItem", sectionId: section.id, itemId: id }) }) : null
3594
+ section.actions.map((action) => /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(ActionGlyph, { glyph: action.glyph }), label: action.label, disabled: action.disabled, onClick: () => ui9({ kind: "runAction", sectionId: section.id, actionId: action.id }) }, action.id)),
3595
+ section.hasAddMenu ? /* @__PURE__ */ jsx4(Menu, { size: "sm", trigger: "\uFF0B", items: section.addItems, label: section.addLabel, align: "end", onSelect: (id) => ui9({ kind: "addItem", sectionId: section.id, itemId: id }) }) : null
3596
3596
  ] }) : null,
3597
3597
  children: [
3598
3598
  section.showEmptyHint ? /* @__PURE__ */ jsx4(Stack2, { pad: "inset", children: /* @__PURE__ */ jsx4(Text3, { role: "caption", children: section.emptyHint }) }) : null,
@@ -3602,7 +3602,7 @@ function SectionView({ section, controller }) {
3602
3602
  );
3603
3603
  }
3604
3604
  function FieldRow({ row: row2, controller }) {
3605
- const ui8 = (intent) => applyInspectorUi(controller, intent);
3605
+ const ui9 = (intent) => applyInspectorUi(controller, intent);
3606
3606
  return /* @__PURE__ */ jsxs3(Fragment3, { children: [
3607
3607
  /* @__PURE__ */ jsxs3(
3608
3608
  Field,
@@ -3610,19 +3610,19 @@ function FieldRow({ row: row2, controller }) {
3610
3610
  label: row2.label,
3611
3611
  title: row2.title,
3612
3612
  focused: row2.focused,
3613
- onLabelClick: () => ui8({ kind: "focusField", fieldId: row2.id }),
3614
- onContextMenu: (x, y) => ui8({ kind: "contextMenu", fieldId: row2.id, x, y }),
3613
+ onLabelClick: () => ui9({ kind: "focusField", fieldId: row2.id }),
3614
+ onContextMenu: (x, y) => ui9({ kind: "contextMenu", fieldId: row2.id, x, y }),
3615
3615
  leading: row2.showKeyframes ? /* @__PURE__ */ jsxs3(Fragment3, { children: [
3616
- /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(StopwatchIcon, {}), label: "Toggle animation", active: row2.animated, onClick: () => ui8({ kind: "keyframe", fieldId: row2.id, op: "toggleAnim" }) }),
3617
- row2.animated ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(PrevIcon, {}), label: "Previous keyframe", disabled: row2.prevDisabled, onClick: () => ui8({ kind: "keyframe", fieldId: row2.id, op: "prev" }) }) : null,
3618
- row2.animated ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(DiamondIcon, { filled: row2.onKeyframe }), label: row2.keyframeLabel, onClick: () => ui8({ kind: "keyframe", fieldId: row2.id, op: row2.keyframeOp }) }) : null,
3619
- row2.animated ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(NextIcon, {}), label: "Next keyframe", disabled: row2.nextDisabled, onClick: () => ui8({ kind: "keyframe", fieldId: row2.id, op: "next" }) }) : null
3616
+ /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(StopwatchIcon, {}), label: "Toggle animation", active: row2.animated, onClick: () => ui9({ kind: "keyframe", fieldId: row2.id, op: "toggleAnim" }) }),
3617
+ row2.animated ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(PrevIcon, {}), label: "Previous keyframe", disabled: row2.prevDisabled, onClick: () => ui9({ kind: "keyframe", fieldId: row2.id, op: "prev" }) }) : null,
3618
+ row2.animated ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(DiamondIcon, { filled: row2.onKeyframe }), label: row2.keyframeLabel, onClick: () => ui9({ kind: "keyframe", fieldId: row2.id, op: row2.keyframeOp }) }) : null,
3619
+ row2.animated ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(NextIcon, {}), label: "Next keyframe", disabled: row2.nextDisabled, onClick: () => ui9({ kind: "keyframe", fieldId: row2.id, op: "next" }) }) : null
3620
3620
  ] }) : null,
3621
3621
  trailing: /* @__PURE__ */ jsxs3(Fragment3, { children: [
3622
- row2.showEasing ? /* @__PURE__ */ jsx4(Select2, { size: "sm", options: row2.easingOptions, value: row2.easing, label: "Easing", onChange: (v) => ui8({ kind: "setEasing", fieldId: row2.id, easing: v }) }) : null,
3622
+ row2.showEasing ? /* @__PURE__ */ jsx4(Select2, { size: "sm", options: row2.easingOptions, value: row2.easing, label: "Easing", onChange: (v) => ui9({ kind: "setEasing", fieldId: row2.id, easing: v }) }) : null,
3623
3623
  row2.showKeyframes ? /* @__PURE__ */ jsx4(Badge2, { size: "sm", children: row2.keyframeChip }) : null,
3624
- row2.showToken ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(LinkIcon, {}), label: row2.tokenActionLabel, active: row2.bound, onClick: () => ui8({ kind: "bindToken", fieldId: row2.id }) }) : null,
3625
- row2.showReset ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(ResetIcon, {}), label: "Reset to default", onClick: () => ui8({ kind: "resetField", fieldId: row2.id }) }) : null
3624
+ row2.showToken ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(LinkIcon, {}), label: row2.tokenActionLabel, active: row2.bound, onClick: () => ui9({ kind: "bindToken", fieldId: row2.id }) }) : null,
3625
+ row2.showReset ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(ResetIcon, {}), label: "Reset to default", onClick: () => ui9({ kind: "resetField", fieldId: row2.id }) }) : null
3626
3626
  ] }),
3627
3627
  children: [
3628
3628
  row2.bound ? /* @__PURE__ */ jsx4(Badge2, { title: row2.tokenTitle, children: row2.tokenLabel }) : null,
@@ -4875,23 +4875,23 @@ function HistoryPanelView({ controller }) {
4875
4875
  const getSnapshot = useCallback4(() => controller.getRevision(), [controller]);
4876
4876
  useSyncExternalStore3(subscribe, getSnapshot, getSnapshot);
4877
4877
  const view = historyViewState(controller);
4878
- const ui8 = (intent) => applyHistoryUi(controller, intent);
4878
+ const ui9 = (intent) => applyHistoryUi(controller, intent);
4879
4879
  return /* @__PURE__ */ jsxs4(Column3, { className: "xeno-history-panel", children: [
4880
4880
  /* @__PURE__ */ jsx5(
4881
4881
  Toolbar2,
4882
4882
  {
4883
4883
  left: /* @__PURE__ */ jsxs4(Fragment4, { children: [
4884
- /* @__PURE__ */ jsx5(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx5(UndoIcon, {}), label: "Undo", disabled: !view.canUndo, onClick: () => ui8({ kind: "undo" }) }),
4885
- /* @__PURE__ */ jsx5(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx5(RedoIcon, {}), label: "Redo", disabled: !view.canRedo, onClick: () => ui8({ kind: "redo" }) })
4884
+ /* @__PURE__ */ jsx5(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx5(UndoIcon, {}), label: "Undo", disabled: !view.canUndo, onClick: () => ui9({ kind: "undo" }) }),
4885
+ /* @__PURE__ */ jsx5(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx5(RedoIcon, {}), label: "Redo", disabled: !view.canRedo, onClick: () => ui9({ kind: "redo" }) })
4886
4886
  ] }),
4887
4887
  right: /* @__PURE__ */ jsxs4(Fragment4, { children: [
4888
4888
  /* @__PURE__ */ jsx5(Text4, { role: "number", children: view.counter }),
4889
- view.clearAllowed ? /* @__PURE__ */ jsx5(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx5(TrashIcon, {}), label: "Clear history", onClick: () => ui8({ kind: "requestClear" }) }) : null
4889
+ view.clearAllowed ? /* @__PURE__ */ jsx5(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx5(TrashIcon, {}), label: "Clear history", onClick: () => ui9({ kind: "requestClear" }) }) : null
4890
4890
  ] }),
4891
- children: view.searchShown ? /* @__PURE__ */ jsx5(SearchField3, { value: view.filter, onChange: (v) => ui8({ kind: "filter", value: v }), placeholder: "Search history", label: "Search history" }) : null
4891
+ children: view.searchShown ? /* @__PURE__ */ jsx5(SearchField3, { value: view.filter, onChange: (v) => ui9({ kind: "filter", value: v }), placeholder: "Search history", label: "Search history" }) : null
4892
4892
  }
4893
4893
  ),
4894
- view.confirmingClear ? /* @__PURE__ */ jsx5(InlineConfirm, { message: "Clear all history?", label: "Confirm clear history", confirmLabel: "Clear", onConfirm: () => ui8({ kind: "confirmClear" }), onCancel: () => ui8({ kind: "cancelClear" }) }) : null,
4894
+ view.confirmingClear ? /* @__PURE__ */ jsx5(InlineConfirm, { message: "Clear all history?", label: "Confirm clear history", confirmLabel: "Clear", onConfirm: () => ui9({ kind: "confirmClear" }), onCancel: () => ui9({ kind: "cancelClear" }) }) : null,
4895
4895
  view.pruned ? /* @__PURE__ */ jsx5(Text4, { role: "caption", children: "Earlier history discarded (limit reached)" }) : null,
4896
4896
  /* @__PURE__ */ jsxs4(HistoryScroller, { controller, children: [
4897
4897
  /* @__PURE__ */ jsx5(RowList2, { role: "listbox", "aria-label": "History", children: /* @__PURE__ */ jsx5(VirtualWindow2, { totalHeight: view.totalHeight, offsetTop: view.offsetTop, children: view.rows.map((row2) => /* @__PURE__ */ jsx5(HistoryRowView, { row: row2, controller }, row2.key)) }) }),
@@ -4950,7 +4950,7 @@ function HistoryCancelButton({ entryId, controller }) {
4950
4950
  );
4951
4951
  }
4952
4952
  function HistoryRowView({ row: row2, controller }) {
4953
- const ui8 = (intent) => applyHistoryUi(controller, intent);
4953
+ const ui9 = (intent) => applyHistoryUi(controller, intent);
4954
4954
  return /* @__PURE__ */ jsx5(
4955
4955
  Row2,
4956
4956
  {
@@ -4973,9 +4973,9 @@ function HistoryRowView({ row: row2, controller }) {
4973
4973
  row2.showTime ? /* @__PURE__ */ jsx5(Text4, { role: "meta", children: row2.time }) : null,
4974
4974
  row2.pending ? /* @__PURE__ */ jsx5(HistoryCancelButton, { entryId: row2.cancelId, controller }) : null
4975
4975
  ] }),
4976
- onClick: () => ui8({ kind: "jump", entryId: row2.entryId }),
4977
- onMouseEnter: () => ui8({ kind: "hover", entryId: row2.entryId }),
4978
- onContextMenuAt: (x, y) => ui8({ kind: "contextMenu", entryId: row2.entryId, x, y })
4976
+ onClick: () => ui9({ kind: "jump", entryId: row2.entryId }),
4977
+ onMouseEnter: () => ui9({ kind: "hover", entryId: row2.entryId }),
4978
+ onContextMenuAt: (x, y) => ui9({ kind: "contextMenu", entryId: row2.entryId, x, y })
4979
4979
  }
4980
4980
  );
4981
4981
  }
@@ -6261,27 +6261,27 @@ function ColorPanelView({ controller }) {
6261
6261
  const getSnapshot = useCallback5(() => controller.getRevision(), [controller]);
6262
6262
  useSyncExternalStore4(subscribe, getSnapshot, getSnapshot);
6263
6263
  const view = colorViewState(controller);
6264
- const ui8 = (intent) => applyColorUi(controller, intent);
6264
+ const ui9 = (intent) => applyColorUi(controller, intent);
6265
6265
  return /* @__PURE__ */ jsx6(Column4, { className: "xeno-color-panel", children: /* @__PURE__ */ jsxs5(Stack3, { gap: 8, children: [
6266
6266
  view.fgBg ? /* @__PURE__ */ jsxs5(Stack3, { direction: "row", pad: "none", children: [
6267
- /* @__PURE__ */ jsx6(ColorChip, { color: view.hex, label: "Foreground", pressed: view.fgActive, onClick: () => ui8({ kind: "setChannel", channel: "fg" }) }),
6268
- /* @__PURE__ */ jsx6(IconButton5, { size: "sm", icon: /* @__PURE__ */ jsx6(SwapIcon, {}), label: "Swap FG/BG (X)", onClick: () => ui8({ kind: "swapChannels" }) }),
6269
- /* @__PURE__ */ jsx6(ColorChip, { color: null, label: "Background", pressed: view.bgActive, onClick: () => ui8({ kind: "setChannel", channel: "bg" }) })
6267
+ /* @__PURE__ */ jsx6(ColorChip, { color: view.hex, label: "Foreground", pressed: view.fgActive, onClick: () => ui9({ kind: "setChannel", channel: "fg" }) }),
6268
+ /* @__PURE__ */ jsx6(IconButton5, { size: "sm", icon: /* @__PURE__ */ jsx6(SwapIcon, {}), label: "Swap FG/BG (X)", onClick: () => ui9({ kind: "swapChannels" }) }),
6269
+ /* @__PURE__ */ jsx6(ColorChip, { color: null, label: "Background", pressed: view.bgActive, onClick: () => ui9({ kind: "setChannel", channel: "bg" }) })
6270
6270
  ] }) : null,
6271
6271
  /* @__PURE__ */ jsx6(ColorPicker, { controller }),
6272
6272
  /* @__PURE__ */ jsxs5(Stack3, { direction: "row", pad: "none", gap: 4, children: [
6273
- /* @__PURE__ */ jsx6(Select3, { size: "sm", label: "Color model", value: view.space, options: view.spaceOptions, onChange: (v) => ui8({ kind: "setSpace", space: v }) }),
6274
- view.isHex ? /* @__PURE__ */ jsx6(Input3, { variant: "mono", label: "Hex", value: view.hex, onChange: (v) => ui8({ kind: "setHex", value: v }), disabled: view.bound }) : null,
6275
- view.components.map((comp) => /* @__PURE__ */ jsx6(NumberInput, { caption: comp.label, value: comp.value, onChange: (n) => ui8({ kind: "setComponent", index: comp.index, value: n }), disabled: view.bound }, comp.key)),
6276
- view.alphaShown ? /* @__PURE__ */ jsx6(NumberInput, { caption: "A", label: "Alpha", min: 0, max: 100, value: view.alphaPercent, onChange: (n) => ui8({ kind: "setAlpha", percent: n }), disabled: view.bound }) : null,
6277
- /* @__PURE__ */ jsx6(IconButton5, { size: "sm", icon: /* @__PURE__ */ jsx6(EyedropperIcon, {}), label: "Pick from screen", onClick: () => ui8({ kind: "eyedropper" }) })
6273
+ /* @__PURE__ */ jsx6(Select3, { size: "sm", label: "Color model", value: view.space, options: view.spaceOptions, onChange: (v) => ui9({ kind: "setSpace", space: v }) }),
6274
+ view.isHex ? /* @__PURE__ */ jsx6(Input3, { variant: "mono", label: "Hex", value: view.hex, onChange: (v) => ui9({ kind: "setHex", value: v }), disabled: view.bound }) : null,
6275
+ view.components.map((comp) => /* @__PURE__ */ jsx6(NumberInput, { caption: comp.label, value: comp.value, onChange: (n) => ui9({ kind: "setComponent", index: comp.index, value: n }), disabled: view.bound }, comp.key)),
6276
+ view.alphaShown ? /* @__PURE__ */ jsx6(NumberInput, { caption: "A", label: "Alpha", min: 0, max: 100, value: view.alphaPercent, onChange: (n) => ui9({ kind: "setAlpha", percent: n }), disabled: view.bound }) : null,
6277
+ /* @__PURE__ */ jsx6(IconButton5, { size: "sm", icon: /* @__PURE__ */ jsx6(EyedropperIcon, {}), label: "Pick from screen", onClick: () => ui9({ kind: "eyedropper" }) })
6278
6278
  ] }),
6279
6279
  view.hasTokens ? /* @__PURE__ */ jsx6(Field2, { label: "Token", htmlFor: "xeno-color-token", children: /* @__PURE__ */ jsxs5(Stack3, { direction: "row", pad: "none", gap: 4, children: [
6280
- /* @__PURE__ */ jsx6(Select3, { size: "sm", label: "Bind token", value: view.boundTokenId, placeholder: "\u2014 raw \u2014", options: view.tokenOptions, onChange: (id) => ui8({ kind: "bindToken", tokenId: id }) }),
6281
- view.bound ? /* @__PURE__ */ jsx6(TextButton2, { onClick: () => ui8({ kind: "unbindToken" }), children: "Unbind" }) : null
6280
+ /* @__PURE__ */ jsx6(Select3, { size: "sm", label: "Bind token", value: view.boundTokenId, placeholder: "\u2014 raw \u2014", options: view.tokenOptions, onChange: (id) => ui9({ kind: "bindToken", tokenId: id }) }),
6281
+ view.bound ? /* @__PURE__ */ jsx6(TextButton2, { onClick: () => ui9({ kind: "unbindToken" }), children: "Unbind" }) : null
6282
6282
  ] }) }) : null,
6283
- /* @__PURE__ */ jsx6(Section2, { title: "Swatches", flush: true, actions: /* @__PURE__ */ jsx6(TextButton2, { onClick: () => ui8({ kind: "addSwatch" }), children: "+ Save" }), children: /* @__PURE__ */ jsx6(SwatchGrid, { label: "Swatches", children: view.swatches.map((sw) => /* @__PURE__ */ jsx6(ColorChip, { size: "grid", color: sw.hex, label: sw.hex, onClick: () => ui8({ kind: "selectColor", hex: sw.hex }), onContextMenu: () => ui8({ kind: "removeSwatch", hex: sw.hex }) }, sw.key)) }) }),
6284
- view.hasRecent ? /* @__PURE__ */ jsx6(Section2, { title: "Recent", flush: true, children: /* @__PURE__ */ jsx6(SwatchGrid, { label: "Recent", children: view.recent.map((r) => /* @__PURE__ */ jsx6(ColorChip, { size: "grid", color: r.hex, label: r.hex, onClick: () => ui8({ kind: "selectColor", hex: r.hex }) }, r.key)) }) }) : null
6283
+ /* @__PURE__ */ jsx6(Section2, { title: "Swatches", flush: true, actions: /* @__PURE__ */ jsx6(TextButton2, { onClick: () => ui9({ kind: "addSwatch" }), children: "+ Save" }), children: /* @__PURE__ */ jsx6(SwatchGrid, { label: "Swatches", children: view.swatches.map((sw) => /* @__PURE__ */ jsx6(ColorChip, { size: "grid", color: sw.hex, label: sw.hex, onClick: () => ui9({ kind: "selectColor", hex: sw.hex }), onContextMenu: () => ui9({ kind: "removeSwatch", hex: sw.hex }) }, sw.key)) }) }),
6284
+ view.hasRecent ? /* @__PURE__ */ jsx6(Section2, { title: "Recent", flush: true, children: /* @__PURE__ */ jsx6(SwatchGrid, { label: "Recent", children: view.recent.map((r) => /* @__PURE__ */ jsx6(ColorChip, { size: "grid", color: r.hex, label: r.hex, onClick: () => ui9({ kind: "selectColor", hex: r.hex }) }, r.key)) }) }) : null
6285
6285
  ] }) });
6286
6286
  }
6287
6287
  function ColorPicker({ controller }) {
@@ -7696,11 +7696,128 @@ var curveManifest = {
7696
7696
 
7697
7697
  // src/edit/curve/react/CurvePanelView.tsx
7698
7698
  import { useCallback as useCallback6, useEffect as useEffect5, useRef as useRef6, useSyncExternalStore as useSyncExternalStore5 } from "react";
7699
- import { EmptyState as EmptyState4, StatusBar as StatusBar3, Toolbar as Toolbar3, ToolbarGroup } from "@xenosystem/components/chrome";
7699
+ import { Column as Column5, EmptyState as EmptyState4, StatusBar as StatusBar3, Text as Text5, TextButton as TextButton3, Toolbar as Toolbar3, ToolbarGroup } from "@xenosystem/components/chrome";
7700
+
7701
+ // src/edit/curve/declaration.ts
7700
7702
  import { formatTick } from "@xenosystem/time-core";
7703
+ var INTERPOLATIONS = ["linear", "bezier", "hold", "step"].map((mode) => ({ key: mode, mode, label: mode }));
7704
+ var TANGENT_MODES = ["aligned", "broken", "flat"].map((mode) => ({ key: mode, mode, label: mode }));
7705
+ var PRESETS = EASING_PRESETS.slice(0, 6).map((p) => ({ key: p.id, id: p.id, label: p.label }));
7706
+ function curveViewState(c, options = {}) {
7707
+ const { showPresets = true } = options;
7708
+ const state = c.getState();
7709
+ const channels = state.curves?.channels ?? [];
7710
+ return {
7711
+ interpolations: INTERPOLATIONS,
7712
+ tangentModes: TANGENT_MODES,
7713
+ presetsShown: showPresets,
7714
+ presets: PRESETS,
7715
+ empty: channels.length === 0,
7716
+ drawn: channels.length > 0,
7717
+ channelsLabel: `${channels.length} channel${channels.length === 1 ? "" : "s"}`,
7718
+ playheadLabel: state.playheadTick !== null ? formatTick(state.playheadTick, state.timebase) : ""
7719
+ };
7720
+ }
7721
+ function applyCurveUi(c, intent) {
7722
+ switch (intent.kind) {
7723
+ case "interpolation":
7724
+ c.setInterpolation(intent.mode);
7725
+ break;
7726
+ case "tangentMode":
7727
+ c.setTangentMode(intent.mode);
7728
+ break;
7729
+ case "fit":
7730
+ c.fitAll();
7731
+ break;
7732
+ case "preset":
7733
+ c.applyPreset(intent.id);
7734
+ break;
7735
+ }
7736
+ }
7737
+ var curveViewManifest = {
7738
+ id: curveManifest.id,
7739
+ version: "1.0.0",
7740
+ title: "Curve",
7741
+ category: "edit",
7742
+ layout: { slot: "bottom" },
7743
+ inputs: [{ id: "view", type: "object", label: "View state", description: "The CurveViewModel the runtime derives from the controller on every draw." }],
7744
+ outputs: [{ id: "ui", type: "object", label: "UI intent", description: "{ kind, mode?, id? } \u2014 applied by the runtime to the controller." }],
7745
+ commands: []
7746
+ };
7747
+ var EMPTY5 = { interpolations: INTERPOLATIONS, tangentModes: TANGENT_MODES, presetsShown: true, presets: PRESETS, empty: true, drawn: false, channelsLabel: "0 channels", playheadLabel: "" };
7748
+ var BEHAVIOURS5 = {
7749
+ "edit/curvePanelView": (inputs) => inputs.view ?? EMPTY5
7750
+ };
7751
+ var text5 = (b) => ({ component: "text", props: { text: b } });
7752
+ var ui5 = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
7753
+ var CURVE_DECLARATION = {
7754
+ format: "xeno.block@1",
7755
+ manifest: curveViewManifest,
7756
+ behaviour: "edit/curvePanelView",
7757
+ composition: {
7758
+ component: "chrome/Column",
7759
+ children: [
7760
+ {
7761
+ component: "chrome/Toolbar",
7762
+ props: {
7763
+ left: { node: { component: "chrome/ToolbarGroup", children: [{ component: "chrome/TextButton", each: { input: "view.interpolations", key: "key" }, children: [text5({ item: "label" })], on: { onClick: ui5("interpolation", { mode: { item: "mode" } }) } }] } },
7764
+ right: {
7765
+ node: {
7766
+ component: "chrome/ToolbarGroup",
7767
+ props: { end: { value: true } },
7768
+ children: [
7769
+ { component: "chrome/TextButton", each: { input: "view.tangentModes", key: "key" }, children: [text5({ item: "label" })], on: { onClick: ui5("tangentMode", { mode: { item: "mode" } }) } },
7770
+ { component: "chrome/TextButton", children: [text5({ value: "Fit" })], on: { onClick: ui5("fit") } }
7771
+ ]
7772
+ }
7773
+ }
7774
+ }
7775
+ },
7776
+ {
7777
+ component: "chrome/Toolbar",
7778
+ when: { input: "view.presetsShown" },
7779
+ props: {
7780
+ left: { node: { component: "chrome/ToolbarGroup", children: [{ component: "chrome/TextButton", each: { input: "view.presets", key: "key" }, children: [text5({ item: "label" })], on: { onClick: ui5("preset", { id: { item: "id" } }) } }] } }
7781
+ }
7782
+ },
7783
+ { component: "chrome/EmptyState", when: { input: "view.empty" }, props: { title: { value: "No curves" }, hint: { value: "Wire an animated property into this panel's input." } } },
7784
+ { component: "curve/Surface", when: { input: "view.drawn" } },
7785
+ {
7786
+ component: "chrome/StatusBar",
7787
+ props: {
7788
+ left: { node: { component: "chrome/Text", props: { role: { value: "number" } }, children: [text5({ input: "view.channelsLabel" })] } },
7789
+ right: { node: { component: "chrome/Text", props: { role: { value: "number" } }, children: [text5({ input: "view.playheadLabel" })] } }
7790
+ }
7791
+ }
7792
+ ]
7793
+ }
7794
+ };
7795
+
7796
+ // src/edit/curve/react/CurvePanelView.tsx
7701
7797
  import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
7702
7798
  var DASHES = ["none", "4 2", "1 2", "6 2 1 2"];
7703
- function CurvePanelView({ controller, showPresets = true }) {
7799
+ function CurvePanelView({ controller, ...options }) {
7800
+ useSyncExternalStore5(controller.subscribe, controller.getState, controller.getState);
7801
+ const view = curveViewState(controller, options);
7802
+ const ui9 = (intent) => applyCurveUi(controller, intent);
7803
+ return /* @__PURE__ */ jsxs6(Column5, { children: [
7804
+ /* @__PURE__ */ jsx7(
7805
+ Toolbar3,
7806
+ {
7807
+ left: /* @__PURE__ */ jsx7(ToolbarGroup, { children: view.interpolations.map((m) => /* @__PURE__ */ jsx7(TextButton3, { onClick: () => ui9({ kind: "interpolation", mode: m.mode }), children: m.label }, m.key)) }),
7808
+ right: /* @__PURE__ */ jsxs6(ToolbarGroup, { end: true, children: [
7809
+ view.tangentModes.map((m) => /* @__PURE__ */ jsx7(TextButton3, { onClick: () => ui9({ kind: "tangentMode", mode: m.mode }), children: m.label }, m.key)),
7810
+ /* @__PURE__ */ jsx7(TextButton3, { onClick: () => ui9({ kind: "fit" }), children: "Fit" })
7811
+ ] })
7812
+ }
7813
+ ),
7814
+ view.presetsShown ? /* @__PURE__ */ jsx7(Toolbar3, { left: /* @__PURE__ */ jsx7(ToolbarGroup, { children: view.presets.map((p) => /* @__PURE__ */ jsx7(TextButton3, { onClick: () => ui9({ kind: "preset", id: p.id }), children: p.label }, p.key)) }) }) : null,
7815
+ view.empty ? /* @__PURE__ */ jsx7(EmptyState4, { title: "No curves", hint: "Wire an animated property into this panel's input." }) : null,
7816
+ view.drawn ? /* @__PURE__ */ jsx7(CurveSurface, { controller }) : null,
7817
+ /* @__PURE__ */ jsx7(StatusBar3, { left: /* @__PURE__ */ jsx7(Text5, { role: "number", children: view.channelsLabel }), right: /* @__PURE__ */ jsx7(Text5, { role: "number", children: view.playheadLabel }) })
7818
+ ] });
7819
+ }
7820
+ function CurveSurface({ controller }) {
7704
7821
  const state = useSyncExternalStore5(controller.subscribe, controller.getState, controller.getState);
7705
7822
  const containerRef = useRef6(null);
7706
7823
  useEffect5(() => {
@@ -7777,154 +7894,119 @@ function CurvePanelView({ controller, showPresets = true }) {
7777
7894
  const preview = state.preview;
7778
7895
  const selected = new Set(state.selection.keys.map(keyRefId));
7779
7896
  const channels = state.curves?.channels ?? [];
7780
- return /* @__PURE__ */ jsxs6("div", { style: SHELL, children: [
7781
- /* @__PURE__ */ jsx7(
7782
- Toolbar3,
7783
- {
7784
- left: /* @__PURE__ */ jsx7(ToolbarGroup, { children: ["linear", "bezier", "hold", "step"].map((mode) => /* @__PURE__ */ jsx7("button", { type: "button", style: button(), onClick: () => controller.setInterpolation(mode), children: mode }, mode)) }),
7785
- right: /* @__PURE__ */ jsxs6(ToolbarGroup, { end: true, children: [
7786
- ["aligned", "broken", "flat"].map((mode) => /* @__PURE__ */ jsx7("button", { type: "button", style: button(), onClick: () => controller.setTangentMode(mode), children: mode }, mode)),
7787
- /* @__PURE__ */ jsx7("button", { type: "button", style: button(), onClick: () => controller.fitAll(), children: "Fit" })
7788
- ] })
7789
- }
7790
- ),
7791
- showPresets ? /* @__PURE__ */ jsx7(
7792
- Toolbar3,
7793
- {
7794
- left: /* @__PURE__ */ jsx7(ToolbarGroup, { children: EASING_PRESETS.slice(0, 6).map((preset) => /* @__PURE__ */ jsx7(
7795
- "button",
7796
- {
7797
- type: "button",
7798
- title: preset.label,
7799
- style: button(),
7800
- onClick: () => controller.applyPreset(preset.id),
7801
- children: preset.label
7802
- },
7803
- preset.id
7804
- )) })
7805
- }
7806
- ) : null,
7807
- channels.length === 0 ? /* @__PURE__ */ jsx7(EmptyState4, { title: "No curves", hint: "Wire an animated property into this panel's input." }) : /* @__PURE__ */ jsx7(
7808
- "div",
7809
- {
7810
- ref: containerRef,
7811
- tabIndex: 0,
7812
- role: "application",
7813
- "aria-label": "Curve editor",
7814
- style: SURFACE,
7815
- onWheel,
7816
- onPointerDown,
7817
- onPointerMove,
7818
- onPointerUp,
7819
- onPointerCancel: onPointerUp,
7820
- onKeyDown,
7821
- children: /* @__PURE__ */ jsxs6(
7822
- "svg",
7823
- {
7824
- "data-canvas": "curve-plot",
7825
- width: "100%",
7826
- height: "100%",
7827
- style: { position: "absolute", inset: 0, display: "block" },
7828
- children: [
7829
- /* @__PURE__ */ jsx7(
7830
- "line",
7831
- {
7832
- x1: scale.gutterPx,
7833
- y1: scale.rulerPx,
7834
- x2: scale.gutterPx,
7835
- y2: scale.heightPx,
7836
- stroke: "var(--xeno-control)"
7837
- }
7838
- ),
7839
- scale.minValue < 0 && scale.maxValue > 0 ? /* @__PURE__ */ jsx7(
7840
- "line",
7841
- {
7842
- x1: scale.gutterPx,
7843
- y1: scale.valueToY(0),
7844
- x2: scale.widthPx,
7845
- y2: scale.valueToY(0),
7846
- stroke: "var(--xeno-control)",
7847
- strokeDasharray: "2 3"
7848
- }
7849
- ) : null,
7850
- state.samples.map((series, index) => {
7851
- const channel = channels.find((c) => c.id === series.channelId);
7852
- if (!channel || series.points.length === 0) return null;
7853
- const d = series.points.map((p, i) => `${i === 0 ? "M" : "L"}${scale.tickToX(p.tick).toFixed(2)},${scale.valueToY(p.value).toFixed(2)}`).join(" ");
7854
- return /* @__PURE__ */ jsx7(
7855
- "path",
7856
- {
7857
- d,
7858
- fill: "none",
7859
- stroke: channel.color ?? "var(--xeno-text)",
7860
- strokeWidth: 1,
7861
- strokeDasharray: channel.color ? void 0 : DASHES[index % DASHES.length]
7862
- },
7863
- series.channelId
7864
- );
7865
- }),
7866
- channels.map(
7867
- (channel) => channel.visible === false ? null : channel.keys.map((key) => {
7868
- const ref = { channelId: channel.id, keyId: key.id };
7869
- const id = keyRefId(ref);
7870
- const shown = preview?.keys[id] ?? key;
7871
- const x = scale.tickToX(shown.tick);
7872
- const y = scale.valueToY(shown.value);
7873
- const isSelected = selected.has(id);
7874
- return /* @__PURE__ */ jsxs6("g", { children: [
7875
- isSelected ? /* @__PURE__ */ jsx7(Handles, { keyframe: key, x, y, scale }) : null,
7876
- /* @__PURE__ */ jsx7(
7877
- "rect",
7878
- {
7879
- x: x - 3,
7880
- y: y - 3,
7881
- width: 6,
7882
- height: 6,
7883
- transform: `rotate(45 ${x} ${y})`,
7884
- fill: isSelected ? "var(--xeno-text)" : "var(--xeno-active)",
7885
- stroke: "var(--xeno-elevated)",
7886
- strokeWidth: 0.5
7887
- }
7888
- )
7889
- ] }, id);
7890
- })
7891
- ),
7892
- preview?.marquee ? /* @__PURE__ */ jsx7(
7893
- "rect",
7894
- {
7895
- x: Math.min(scale.tickToX(preview.marquee.fromTick), scale.tickToX(preview.marquee.toTick)),
7896
- y: Math.min(scale.valueToY(preview.marquee.fromValue), scale.valueToY(preview.marquee.toValue)),
7897
- width: Math.abs(scale.tickToX(preview.marquee.toTick) - scale.tickToX(preview.marquee.fromTick)),
7898
- height: Math.abs(
7899
- scale.valueToY(preview.marquee.toValue) - scale.valueToY(preview.marquee.fromValue)
7900
- ),
7901
- fill: "var(--xeno-border-subtle)",
7902
- stroke: "var(--xeno-active)"
7903
- }
7904
- ) : null,
7905
- state.playheadTick !== null ? /* @__PURE__ */ jsx7(
7906
- "line",
7897
+ return /* @__PURE__ */ jsx7(
7898
+ "div",
7899
+ {
7900
+ ref: containerRef,
7901
+ tabIndex: 0,
7902
+ role: "application",
7903
+ "aria-label": "Curve editor",
7904
+ style: SURFACE,
7905
+ onWheel,
7906
+ onPointerDown,
7907
+ onPointerMove,
7908
+ onPointerUp,
7909
+ onPointerCancel: onPointerUp,
7910
+ onKeyDown,
7911
+ children: /* @__PURE__ */ jsxs6(
7912
+ "svg",
7913
+ {
7914
+ "data-canvas": "curve-plot",
7915
+ width: "100%",
7916
+ height: "100%",
7917
+ style: { position: "absolute", inset: 0, display: "block" },
7918
+ children: [
7919
+ /* @__PURE__ */ jsx7(
7920
+ "line",
7921
+ {
7922
+ x1: scale.gutterPx,
7923
+ y1: scale.rulerPx,
7924
+ x2: scale.gutterPx,
7925
+ y2: scale.heightPx,
7926
+ stroke: "var(--xeno-control)"
7927
+ }
7928
+ ),
7929
+ scale.minValue < 0 && scale.maxValue > 0 ? /* @__PURE__ */ jsx7(
7930
+ "line",
7931
+ {
7932
+ x1: scale.gutterPx,
7933
+ y1: scale.valueToY(0),
7934
+ x2: scale.widthPx,
7935
+ y2: scale.valueToY(0),
7936
+ stroke: "var(--xeno-control)",
7937
+ strokeDasharray: "2 3"
7938
+ }
7939
+ ) : null,
7940
+ state.samples.map((series, index) => {
7941
+ const channel = channels.find((c) => c.id === series.channelId);
7942
+ if (!channel || series.points.length === 0) return null;
7943
+ const d = series.points.map((p, i) => `${i === 0 ? "M" : "L"}${scale.tickToX(p.tick).toFixed(2)},${scale.valueToY(p.value).toFixed(2)}`).join(" ");
7944
+ return /* @__PURE__ */ jsx7(
7945
+ "path",
7907
7946
  {
7908
- x1: scale.tickToX(state.playheadTick),
7909
- y1: scale.rulerPx,
7910
- x2: scale.tickToX(state.playheadTick),
7911
- y2: scale.heightPx,
7912
- stroke: "var(--xeno-text)"
7913
- }
7914
- ) : null
7915
- ]
7916
- }
7917
- )
7918
- }
7919
- ),
7920
- /* @__PURE__ */ jsx7(
7921
- StatusBar3,
7922
- {
7923
- left: `${channels.length} channel${channels.length === 1 ? "" : "s"}`,
7924
- right: /* @__PURE__ */ jsx7("span", { className: "tabular-nums", children: state.playheadTick !== null ? formatTick(state.playheadTick, state.timebase) : "" })
7925
- }
7926
- )
7927
- ] });
7947
+ d,
7948
+ fill: "none",
7949
+ stroke: channel.color ?? "var(--xeno-text)",
7950
+ strokeWidth: 1,
7951
+ strokeDasharray: channel.color ? void 0 : DASHES[index % DASHES.length]
7952
+ },
7953
+ series.channelId
7954
+ );
7955
+ }),
7956
+ channels.map(
7957
+ (channel) => channel.visible === false ? null : channel.keys.map((key) => {
7958
+ const ref = { channelId: channel.id, keyId: key.id };
7959
+ const id = keyRefId(ref);
7960
+ const shown = preview?.keys[id] ?? key;
7961
+ const x = scale.tickToX(shown.tick);
7962
+ const y = scale.valueToY(shown.value);
7963
+ const isSelected = selected.has(id);
7964
+ return /* @__PURE__ */ jsxs6("g", { children: [
7965
+ isSelected ? /* @__PURE__ */ jsx7(Handles, { keyframe: key, x, y, scale }) : null,
7966
+ /* @__PURE__ */ jsx7(
7967
+ "rect",
7968
+ {
7969
+ x: x - 3,
7970
+ y: y - 3,
7971
+ width: 6,
7972
+ height: 6,
7973
+ transform: `rotate(45 ${x} ${y})`,
7974
+ fill: isSelected ? "var(--xeno-text)" : "var(--xeno-active)",
7975
+ stroke: "var(--xeno-elevated)",
7976
+ strokeWidth: 0.5
7977
+ }
7978
+ )
7979
+ ] }, id);
7980
+ })
7981
+ ),
7982
+ preview?.marquee ? /* @__PURE__ */ jsx7(
7983
+ "rect",
7984
+ {
7985
+ x: Math.min(scale.tickToX(preview.marquee.fromTick), scale.tickToX(preview.marquee.toTick)),
7986
+ y: Math.min(scale.valueToY(preview.marquee.fromValue), scale.valueToY(preview.marquee.toValue)),
7987
+ width: Math.abs(scale.tickToX(preview.marquee.toTick) - scale.tickToX(preview.marquee.fromTick)),
7988
+ height: Math.abs(
7989
+ scale.valueToY(preview.marquee.toValue) - scale.valueToY(preview.marquee.fromValue)
7990
+ ),
7991
+ fill: "var(--xeno-border-subtle)",
7992
+ stroke: "var(--xeno-active)"
7993
+ }
7994
+ ) : null,
7995
+ state.playheadTick !== null ? /* @__PURE__ */ jsx7(
7996
+ "line",
7997
+ {
7998
+ x1: scale.tickToX(state.playheadTick),
7999
+ y1: scale.rulerPx,
8000
+ x2: scale.tickToX(state.playheadTick),
8001
+ y2: scale.heightPx,
8002
+ stroke: "var(--xeno-text)"
8003
+ }
8004
+ ) : null
8005
+ ]
8006
+ }
8007
+ )
8008
+ }
8009
+ );
7928
8010
  }
7929
8011
  function Handles({
7930
8012
  keyframe,
@@ -7944,7 +8026,6 @@ function Handles({
7944
8026
  ] }, side);
7945
8027
  }) });
7946
8028
  }
7947
- var SHELL = { display: "flex", flexDirection: "column", height: "100%", minHeight: 0 };
7948
8029
  var SURFACE = {
7949
8030
  position: "relative",
7950
8031
  flex: 1,
@@ -7954,21 +8035,13 @@ var SURFACE = {
7954
8035
  userSelect: "none",
7955
8036
  touchAction: "none"
7956
8037
  };
7957
- function button() {
7958
- return {
7959
- height: 18,
7960
- padding: "0 6px",
7961
- fontSize: 10,
7962
- borderRadius: 2,
7963
- border: "1px solid var(--xeno-control)",
7964
- background: "transparent",
7965
- color: "var(--xeno-muted)",
7966
- cursor: "pointer"
7967
- };
8038
+ var CURVE_RUNTIME_UNITS = ["curve/Surface"];
8039
+ function curveRuntimeComponents(controller) {
8040
+ return { "curve/Surface": () => /* @__PURE__ */ jsx7(CurveSurface, { controller }) };
7968
8041
  }
7969
8042
 
7970
8043
  // src/edit/curve/panel.ts
7971
- var INTERPOLATIONS = [
8044
+ var INTERPOLATIONS2 = [
7972
8045
  "linear",
7973
8046
  "bezier",
7974
8047
  "hold",
@@ -7977,7 +8050,7 @@ var INTERPOLATIONS = [
7977
8050
  "ease-out",
7978
8051
  "ease-in-out"
7979
8052
  ];
7980
- var TANGENT_MODES = ["auto", "aligned", "broken", "flat", "linear"];
8053
+ var TANGENT_MODES2 = ["auto", "aligned", "broken", "flat", "linear"];
7981
8054
  function createCurvePanel(options = {}) {
7982
8055
  return {
7983
8056
  manifest: curveManifest,
@@ -8043,9 +8116,9 @@ function createCurvePanel(options = {}) {
8043
8116
  case "delete_selection":
8044
8117
  return controller.deleteSelection();
8045
8118
  case "set_interpolation":
8046
- return INTERPOLATIONS.includes(String(params.interpolation)) ? controller.setInterpolation(String(params.interpolation)) : null;
8119
+ return INTERPOLATIONS2.includes(String(params.interpolation)) ? controller.setInterpolation(String(params.interpolation)) : null;
8047
8120
  case "set_tangent_mode":
8048
- return TANGENT_MODES.includes(String(params.mode)) ? controller.setTangentMode(String(params.mode)) : null;
8121
+ return TANGENT_MODES2.includes(String(params.mode)) ? controller.setTangentMode(String(params.mode)) : null;
8049
8122
  case "apply_preset":
8050
8123
  return controller.applyPreset(String(params.preset));
8051
8124
  case "select_key":
@@ -8943,11 +9016,11 @@ var FindController = class {
8943
9016
  * @param text - The new query text.
8944
9017
  * @param immediate - Skip the debounce (a paste, or pressing Enter).
8945
9018
  */
8946
- setText(text8, immediate = false) {
8947
- if (text8 === this.text) return;
8948
- this.text = text8;
9019
+ setText(text9, immediate = false) {
9020
+ if (text9 === this.text) return;
9021
+ this.text = text9;
8949
9022
  this.index = -1;
8950
- if (text8 === "") {
9023
+ if (text9 === "") {
8951
9024
  this.clearResults("idle");
8952
9025
  this.emitQuery(true);
8953
9026
  return;
@@ -8975,8 +9048,8 @@ var FindController = class {
8975
9048
  this.notify();
8976
9049
  }
8977
9050
  /** The replacement text. Never emitted on its own — a replacement is not a search. */
8978
- setReplaceText(text8) {
8979
- this.replaceText = text8;
9051
+ setReplaceText(text9) {
9052
+ this.replaceText = text9;
8980
9053
  this.notify();
8981
9054
  }
8982
9055
  /** Show or hide the replace row. */
@@ -9341,7 +9414,7 @@ var findManifest = {
9341
9414
  import { useSyncExternalStore as useSyncExternalStore7 } from "react";
9342
9415
  import {
9343
9416
  Badge as Badge5,
9344
- Column as Column5,
9417
+ Column as Column6,
9345
9418
  EmptyState as EmptyState5,
9346
9419
  Highlight,
9347
9420
  IconButton as IconButton6,
@@ -9351,8 +9424,8 @@ import {
9351
9424
  SearchField as SearchField4,
9352
9425
  Section as Section3,
9353
9426
  StatusBar as StatusBar5,
9354
- Text as Text5,
9355
- TextButton as TextButton3,
9427
+ Text as Text6,
9428
+ TextButton as TextButton4,
9356
9429
  Toolbar as Toolbar4,
9357
9430
  ToolbarGroup as ToolbarGroup2
9358
9431
  } from "@xenosystem/components/chrome";
@@ -9450,7 +9523,7 @@ var findViewManifest = {
9450
9523
  outputs: [{ id: "ui", type: "object", label: "UI intent", description: "{ kind, value?, option?, matchId?, x?, y? } \u2014 applied by the runtime to the controller." }],
9451
9524
  commands: []
9452
9525
  };
9453
- var EMPTY5 = {
9526
+ var EMPTY6 = {
9454
9527
  text: "",
9455
9528
  hasText: false,
9456
9529
  placeholder: "Find",
@@ -9482,24 +9555,24 @@ var EMPTY5 = {
9482
9555
  rows: [],
9483
9556
  groups: []
9484
9557
  };
9485
- var BEHAVIOURS5 = {
9486
- "edit/findPanelView": (inputs) => inputs.view ?? EMPTY5
9558
+ var BEHAVIOURS6 = {
9559
+ "edit/findPanelView": (inputs) => inputs.view ?? EMPTY6
9487
9560
  };
9488
9561
  var FIND_RUNTIME_UNITS = ["find/Keys"];
9489
- var text5 = (b) => ({ component: "text", props: { text: b } });
9490
- var ui5 = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
9562
+ var text6 = (b) => ({ component: "text", props: { text: b } });
9563
+ var ui6 = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
9491
9564
  var option = (option2, icon, label) => ({
9492
9565
  component: "chrome/IconButton",
9493
9566
  props: { label: { value: label }, active: { input: `view.${option2}` }, icon: { node: { component: icon, props: { size: { value: 12 } } } } },
9494
- on: { onClick: ui5("option", { option: { value: option2 } }) }
9567
+ on: { onClick: ui6("option", { option: { value: option2 } }) }
9495
9568
  });
9496
9569
  var resultRow = {
9497
9570
  component: "chrome/Row",
9498
9571
  each: { item: "rows", key: "id" },
9499
9572
  props: { noIcon: { value: true }, selected: { item: "current" }, meta: { item: "location" }, label: { node: { component: "chrome/Highlight", props: { segments: { item: "segments" } } } } },
9500
9573
  on: {
9501
- onClick: ui5("select", { matchId: { item: "id" } }),
9502
- onContextMenuAt: ui5("contextMenu", { matchId: { item: "id" }, x: { arg: "", index: 0 }, y: { arg: "", index: 1 } })
9574
+ onClick: ui6("select", { matchId: { item: "id" } }),
9575
+ onContextMenuAt: ui6("contextMenu", { matchId: { item: "id" }, x: { arg: "", index: 0 }, y: { arg: "", index: 1 } })
9503
9576
  }
9504
9577
  };
9505
9578
  var flatRow = { ...resultRow, each: { input: "view.rows", key: "id" } };
@@ -9514,7 +9587,7 @@ var FIND_DECLARATION = {
9514
9587
  {
9515
9588
  component: "chrome/Toolbar",
9516
9589
  props: {
9517
- left: { node: { component: "chrome/SearchField", props: { value: { input: "view.text" }, placeholder: { input: "view.placeholder" } }, on: { onChange: ui5("text", { value: { arg: "" } }) } } },
9590
+ left: { node: { component: "chrome/SearchField", props: { value: { input: "view.text" }, placeholder: { input: "view.placeholder" } }, on: { onChange: ui6("text", { value: { arg: "" } }) } } },
9518
9591
  right: {
9519
9592
  node: {
9520
9593
  component: "chrome/ToolbarGroup",
@@ -9532,10 +9605,10 @@ var FIND_DECLARATION = {
9532
9605
  node: {
9533
9606
  component: "fragment",
9534
9607
  children: [
9535
- { component: "chrome/Badge", when: { input: "view.invalid" }, props: { tone: { value: "error" }, title: { input: "view.message" } }, children: [text5({ value: "invalid pattern" })] },
9536
- { component: "chrome/Badge", when: { input: "view.failed" }, props: { tone: { value: "error" }, title: { input: "view.message" } }, children: [text5({ value: "search failed" })] },
9537
- { component: "chrome/Badge", when: { input: "view.searchingBadge" }, children: [text5({ value: "searching\u2026" })] },
9538
- { component: "chrome/Text", when: { input: "view.countShown" }, props: { role: { value: "number" } }, children: [text5({ input: "view.counter" })] }
9608
+ { component: "chrome/Badge", when: { input: "view.invalid" }, props: { tone: { value: "error" }, title: { input: "view.message" } }, children: [text6({ value: "invalid pattern" })] },
9609
+ { component: "chrome/Badge", when: { input: "view.failed" }, props: { tone: { value: "error" }, title: { input: "view.message" } }, children: [text6({ value: "search failed" })] },
9610
+ { component: "chrome/Badge", when: { input: "view.searchingBadge" }, children: [text6({ value: "searching\u2026" })] },
9611
+ { component: "chrome/Text", when: { input: "view.countShown" }, props: { role: { value: "number" } }, children: [text6({ input: "view.counter" })] }
9539
9612
  ]
9540
9613
  }
9541
9614
  },
@@ -9544,27 +9617,27 @@ var FIND_DECLARATION = {
9544
9617
  component: "chrome/ToolbarGroup",
9545
9618
  props: { end: { value: true } },
9546
9619
  children: [
9547
- { component: "chrome/IconButton", props: { label: { value: "Previous match" }, disabled: { not: { input: "view.hasMatches" } }, icon: { node: { component: "icons/Chevron", props: { direction: { value: "up" }, size: { value: 12 } } } } }, on: { onClick: ui5("previous") } },
9548
- { component: "chrome/IconButton", props: { label: { value: "Next match" }, disabled: { not: { input: "view.hasMatches" } }, icon: { node: { component: "icons/Chevron", props: { direction: { value: "down" }, size: { value: 12 } } } } }, on: { onClick: ui5("next") } },
9549
- { component: "chrome/TextButton", on: { onClick: ui5("toggleReplace") }, children: [text5({ input: "view.replaceLabel" })] }
9620
+ { component: "chrome/IconButton", props: { label: { value: "Previous match" }, disabled: { not: { input: "view.hasMatches" } }, icon: { node: { component: "icons/Chevron", props: { direction: { value: "up" }, size: { value: 12 } } } } }, on: { onClick: ui6("previous") } },
9621
+ { component: "chrome/IconButton", props: { label: { value: "Next match" }, disabled: { not: { input: "view.hasMatches" } }, icon: { node: { component: "icons/Chevron", props: { direction: { value: "down" }, size: { value: 12 } } } } }, on: { onClick: ui6("next") } },
9622
+ { component: "chrome/TextButton", on: { onClick: ui6("toggleReplace") }, children: [text6({ input: "view.replaceLabel" })] }
9550
9623
  ]
9551
9624
  }
9552
9625
  }
9553
9626
  }
9554
9627
  },
9555
- { component: "chrome/Text", when: { input: "view.invalid" }, props: { role: { value: "caption" }, className: { value: "xeno-find-message" } }, children: [text5({ input: "view.message" })] },
9628
+ { component: "chrome/Text", when: { input: "view.invalid" }, props: { role: { value: "caption" }, className: { value: "xeno-find-message" } }, children: [text6({ input: "view.message" })] },
9556
9629
  {
9557
9630
  component: "chrome/Toolbar",
9558
9631
  when: { input: "view.replaceVisible" },
9559
9632
  props: {
9560
- left: { node: { component: "chrome/SearchField", props: { value: { input: "view.replaceText" }, placeholder: { value: "Replace with" } }, on: { onChange: ui5("replaceText", { value: { arg: "" } }) } } },
9633
+ left: { node: { component: "chrome/SearchField", props: { value: { input: "view.replaceText" }, placeholder: { value: "Replace with" } }, on: { onChange: ui6("replaceText", { value: { arg: "" } }) } } },
9561
9634
  right: {
9562
9635
  node: {
9563
9636
  component: "chrome/ToolbarGroup",
9564
9637
  props: { end: { value: true } },
9565
9638
  children: [
9566
- { component: "chrome/TextButton", props: { disabled: { not: { input: "view.canReplace" } } }, on: { onClick: ui5("replaceCurrent") }, children: [text5({ value: "Replace" })] },
9567
- { component: "chrome/TextButton", props: { disabled: { not: { input: "view.canReplace" } } }, on: { onClick: ui5("replaceAll") }, children: [text5({ input: "view.allLabel" })] }
9639
+ { component: "chrome/TextButton", props: { disabled: { not: { input: "view.canReplace" } } }, on: { onClick: ui6("replaceCurrent") }, children: [text6({ value: "Replace" })] },
9640
+ { component: "chrome/TextButton", props: { disabled: { not: { input: "view.canReplace" } } }, on: { onClick: ui6("replaceAll") }, children: [text6({ input: "view.allLabel" })] }
9568
9641
  ]
9569
9642
  }
9570
9643
  }
@@ -9586,7 +9659,7 @@ var FIND_DECLARATION = {
9586
9659
  {
9587
9660
  component: "chrome/Section",
9588
9661
  each: { input: "view.groups", key: "id" },
9589
- props: { title: { item: "label" }, flush: { value: true }, badge: { node: { component: "chrome/Badge", children: [text5({ item: "count" })] } } },
9662
+ props: { title: { item: "label" }, flush: { value: true }, badge: { node: { component: "chrome/Badge", children: [text6({ item: "count" })] } } },
9590
9663
  children: [{ component: "chrome/RowList", children: [resultRow] }]
9591
9664
  }
9592
9665
  ]
@@ -9615,7 +9688,7 @@ function FindKeys({ controller, children }) {
9615
9688
  controller.clear();
9616
9689
  }
9617
9690
  };
9618
- return /* @__PURE__ */ jsx9(Column5, { onKeyDown, children });
9691
+ return /* @__PURE__ */ jsx9(Column6, { onKeyDown, children });
9619
9692
  }
9620
9693
  function findRuntimeComponents(controller) {
9621
9694
  return {
@@ -9625,7 +9698,7 @@ function findRuntimeComponents(controller) {
9625
9698
  function FindPanelView({ controller, showResults, placeholder }) {
9626
9699
  useSyncExternalStore7(controller.subscribe, controller.getState, controller.getState);
9627
9700
  const view = findViewState(controller, { showResults, placeholder });
9628
- const ui8 = (intent) => applyFindUi(controller, intent);
9701
+ const ui9 = (intent) => applyFindUi(controller, intent);
9629
9702
  const renderRow = (row2) => /* @__PURE__ */ jsx9(
9630
9703
  Row3,
9631
9704
  {
@@ -9633,8 +9706,8 @@ function FindPanelView({ controller, showResults, placeholder }) {
9633
9706
  selected: row2.current,
9634
9707
  meta: row2.location,
9635
9708
  label: /* @__PURE__ */ jsx9(Highlight, { segments: row2.segments }),
9636
- onClick: () => ui8({ kind: "select", matchId: row2.id }),
9637
- onContextMenuAt: (x, y) => ui8({ kind: "contextMenu", matchId: row2.id, x, y })
9709
+ onClick: () => ui9({ kind: "select", matchId: row2.id }),
9710
+ onContextMenuAt: (x, y) => ui9({ kind: "contextMenu", matchId: row2.id, x, y })
9638
9711
  },
9639
9712
  row2.id
9640
9713
  );
@@ -9642,11 +9715,11 @@ function FindPanelView({ controller, showResults, placeholder }) {
9642
9715
  /* @__PURE__ */ jsx9(
9643
9716
  Toolbar4,
9644
9717
  {
9645
- left: /* @__PURE__ */ jsx9(SearchField4, { value: view.text, placeholder: view.placeholder, onChange: (value) => ui8({ kind: "text", value }) }),
9718
+ left: /* @__PURE__ */ jsx9(SearchField4, { value: view.text, placeholder: view.placeholder, onChange: (value) => ui9({ kind: "text", value }) }),
9646
9719
  right: /* @__PURE__ */ jsxs8(ToolbarGroup2, { end: true, children: [
9647
- /* @__PURE__ */ jsx9(IconButton6, { label: "Match case", active: view.caseSensitive, icon: /* @__PURE__ */ jsx9(CaseIcon, { size: 12 }), onClick: () => ui8({ kind: "option", option: "caseSensitive" }) }),
9648
- /* @__PURE__ */ jsx9(IconButton6, { label: "Whole word", active: view.wholeWord, icon: /* @__PURE__ */ jsx9(WordIcon, { size: 12 }), onClick: () => ui8({ kind: "option", option: "wholeWord" }) }),
9649
- /* @__PURE__ */ jsx9(IconButton6, { label: "Regular expression", active: view.regex, icon: /* @__PURE__ */ jsx9(RegexIcon, { size: 12 }), onClick: () => ui8({ kind: "option", option: "regex" }) })
9720
+ /* @__PURE__ */ jsx9(IconButton6, { label: "Match case", active: view.caseSensitive, icon: /* @__PURE__ */ jsx9(CaseIcon, { size: 12 }), onClick: () => ui9({ kind: "option", option: "caseSensitive" }) }),
9721
+ /* @__PURE__ */ jsx9(IconButton6, { label: "Whole word", active: view.wholeWord, icon: /* @__PURE__ */ jsx9(WordIcon, { size: 12 }), onClick: () => ui9({ kind: "option", option: "wholeWord" }) }),
9722
+ /* @__PURE__ */ jsx9(IconButton6, { label: "Regular expression", active: view.regex, icon: /* @__PURE__ */ jsx9(RegexIcon, { size: 12 }), onClick: () => ui9({ kind: "option", option: "regex" }) })
9650
9723
  ] })
9651
9724
  }
9652
9725
  ),
@@ -9658,23 +9731,23 @@ function FindPanelView({ controller, showResults, placeholder }) {
9658
9731
  view.invalid ? /* @__PURE__ */ jsx9(Badge5, { tone: "error", title: view.message ?? void 0, children: "invalid pattern" }) : null,
9659
9732
  view.failed ? /* @__PURE__ */ jsx9(Badge5, { tone: "error", title: view.message ?? void 0, children: "search failed" }) : null,
9660
9733
  view.searchingBadge ? /* @__PURE__ */ jsx9(Badge5, { children: "searching\u2026" }) : null,
9661
- view.countShown ? /* @__PURE__ */ jsx9(Text5, { role: "number", children: view.counter }) : null
9734
+ view.countShown ? /* @__PURE__ */ jsx9(Text6, { role: "number", children: view.counter }) : null
9662
9735
  ] }),
9663
9736
  right: /* @__PURE__ */ jsxs8(ToolbarGroup2, { end: true, children: [
9664
- /* @__PURE__ */ jsx9(IconButton6, { label: "Previous match", disabled: !view.hasMatches, icon: /* @__PURE__ */ jsx9(Chevron, { direction: "up", size: 12 }), onClick: () => ui8({ kind: "previous" }) }),
9665
- /* @__PURE__ */ jsx9(IconButton6, { label: "Next match", disabled: !view.hasMatches, icon: /* @__PURE__ */ jsx9(Chevron, { direction: "down", size: 12 }), onClick: () => ui8({ kind: "next" }) }),
9666
- /* @__PURE__ */ jsx9(TextButton3, { onClick: () => ui8({ kind: "toggleReplace" }), children: view.replaceLabel })
9737
+ /* @__PURE__ */ jsx9(IconButton6, { label: "Previous match", disabled: !view.hasMatches, icon: /* @__PURE__ */ jsx9(Chevron, { direction: "up", size: 12 }), onClick: () => ui9({ kind: "previous" }) }),
9738
+ /* @__PURE__ */ jsx9(IconButton6, { label: "Next match", disabled: !view.hasMatches, icon: /* @__PURE__ */ jsx9(Chevron, { direction: "down", size: 12 }), onClick: () => ui9({ kind: "next" }) }),
9739
+ /* @__PURE__ */ jsx9(TextButton4, { onClick: () => ui9({ kind: "toggleReplace" }), children: view.replaceLabel })
9667
9740
  ] })
9668
9741
  }
9669
9742
  ),
9670
- view.invalid ? /* @__PURE__ */ jsx9(Text5, { role: "caption", className: "xeno-find-message", children: view.message }) : null,
9743
+ view.invalid ? /* @__PURE__ */ jsx9(Text6, { role: "caption", className: "xeno-find-message", children: view.message }) : null,
9671
9744
  view.replaceVisible ? /* @__PURE__ */ jsx9(
9672
9745
  Toolbar4,
9673
9746
  {
9674
- left: /* @__PURE__ */ jsx9(SearchField4, { value: view.replaceText, placeholder: "Replace with", onChange: (value) => ui8({ kind: "replaceText", value }) }),
9747
+ left: /* @__PURE__ */ jsx9(SearchField4, { value: view.replaceText, placeholder: "Replace with", onChange: (value) => ui9({ kind: "replaceText", value }) }),
9675
9748
  right: /* @__PURE__ */ jsxs8(ToolbarGroup2, { end: true, children: [
9676
- /* @__PURE__ */ jsx9(TextButton3, { disabled: !view.canReplace, onClick: () => ui8({ kind: "replaceCurrent" }), children: "Replace" }),
9677
- /* @__PURE__ */ jsx9(TextButton3, { disabled: !view.canReplace, onClick: () => ui8({ kind: "replaceAll" }), children: view.allLabel })
9749
+ /* @__PURE__ */ jsx9(TextButton4, { disabled: !view.canReplace, onClick: () => ui9({ kind: "replaceCurrent" }), children: "Replace" }),
9750
+ /* @__PURE__ */ jsx9(TextButton4, { disabled: !view.canReplace, onClick: () => ui9({ kind: "replaceAll" }), children: view.allLabel })
9678
9751
  ] })
9679
9752
  }
9680
9753
  ) : null,
@@ -10332,7 +10405,7 @@ var commentsManifest = {
10332
10405
  import { useSyncExternalStore as useSyncExternalStore8 } from "react";
10333
10406
  import {
10334
10407
  Badge as Badge6,
10335
- Column as Column6,
10408
+ Column as Column7,
10336
10409
  EmptyState as EmptyState6,
10337
10410
  Input as Input4,
10338
10411
  Message,
@@ -10343,9 +10416,9 @@ import {
10343
10416
  SegmentedControl as SegmentedControl2,
10344
10417
  Stack as Stack4,
10345
10418
  StatusBar as StatusBar6,
10346
- Text as Text6,
10419
+ Text as Text7,
10347
10420
  TextArea as TextArea2,
10348
- TextButton as TextButton4,
10421
+ TextButton as TextButton5,
10349
10422
  ThreadCard,
10350
10423
  Toolbar as Toolbar5,
10351
10424
  ToolbarGroup as ToolbarGroup3
@@ -10476,43 +10549,43 @@ var commentsViewManifest = {
10476
10549
  outputs: [{ id: "ui", type: "object", label: "UI intent", description: "{ kind, \u2026 } \u2014 applied by the runtime to the controller." }],
10477
10550
  commands: []
10478
10551
  };
10479
- var EMPTY6 = { show: "open", shows: [], sort: "document", sorts: [], orphanedHidden: false, filteredEmpty: false, filteredHint: "", empty: true, emptyHint: "Select something and add a comment.", listed: false, open: [], hasResolved: false, resolvedTitle: "", resolved: [], draft: "", placeholder: "", composerDisabled: true, commentDisabled: true, countLabel: "0 open" };
10480
- var BEHAVIOURS6 = {
10481
- "edit/commentsPanelView": (inputs) => inputs.view ?? EMPTY6
10552
+ var EMPTY7 = { show: "open", shows: [], sort: "document", sorts: [], orphanedHidden: false, filteredEmpty: false, filteredHint: "", empty: true, emptyHint: "Select something and add a comment.", listed: false, open: [], hasResolved: false, resolvedTitle: "", resolved: [], draft: "", placeholder: "", composerDisabled: true, commentDisabled: true, countLabel: "0 open" };
10553
+ var BEHAVIOURS7 = {
10554
+ "edit/commentsPanelView": (inputs) => inputs.view ?? EMPTY7
10482
10555
  };
10483
10556
  var COMMENTS_RUNTIME_UNITS = [];
10484
- var text6 = (b) => ({ component: "text", props: { text: b } });
10485
- var ui6 = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
10557
+ var text7 = (b) => ({ component: "text", props: { text: b } });
10558
+ var ui7 = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
10486
10559
  var threadCard = (input) => ({
10487
10560
  component: "chrome/ThreadCard",
10488
10561
  each: { input, key: "id" },
10489
10562
  props: { active: { item: "active" }, resolved: { item: "resolved" } },
10490
- on: { onContextMenuAt: ui6("contextMenu", { id: { item: "id" }, x: { arg: "", index: 0 }, y: { arg: "", index: 1 } }) },
10563
+ on: { onContextMenuAt: ui7("contextMenu", { id: { item: "id" }, x: { arg: "", index: 0 }, y: { arg: "", index: 1 } }) },
10491
10564
  children: [
10492
10565
  {
10493
10566
  component: "chrome/Stack",
10494
10567
  props: { direction: { value: "row" }, gap: { value: 4 }, pad: { value: "none" } },
10495
10568
  children: [
10496
- { component: "chrome/Badge", when: { item: "hasAnchorBadge" }, props: { tone: { item: "anchorTone" }, title: { item: "anchorTitle" } }, children: [text6({ item: "anchorLabel" })] },
10497
- { component: "chrome/Badge", when: { item: "resolved" }, children: [text6({ value: "resolved" })] },
10498
- { component: "chrome/Text", props: { role: { value: "caption" } }, children: [text6({ item: "age" })] }
10569
+ { component: "chrome/Badge", when: { item: "hasAnchorBadge" }, props: { tone: { item: "anchorTone" }, title: { item: "anchorTitle" } }, children: [text7({ item: "anchorLabel" })] },
10570
+ { component: "chrome/Badge", when: { item: "resolved" }, children: [text7({ value: "resolved" })] },
10571
+ { component: "chrome/Text", props: { role: { value: "caption" } }, children: [text7({ item: "age" })] }
10499
10572
  ]
10500
10573
  },
10501
- { component: "chrome/Quote", when: { item: "hasQuote" }, props: { orphaned: { item: "orphaned" } }, on: { onActivate: ui6("activate", { id: { item: "id" } }) }, children: [text6({ item: "quote" })] },
10502
- { component: "chrome/Message", each: { item: "messages", key: "id" }, props: { author: { item: "author" }, age: { item: "age" }, edited: { item: "edited" } }, children: [text6({ item: "body" })] },
10574
+ { component: "chrome/Quote", when: { item: "hasQuote" }, props: { orphaned: { item: "orphaned" } }, on: { onActivate: ui7("activate", { id: { item: "id" } }) }, children: [text7({ item: "quote" })] },
10575
+ { component: "chrome/Message", each: { item: "messages", key: "id" }, props: { author: { item: "author" }, age: { item: "age" }, edited: { item: "edited" } }, children: [text7({ item: "body" })] },
10503
10576
  {
10504
10577
  component: "chrome/Stack",
10505
10578
  when: { item: "hasReactions" },
10506
10579
  props: { direction: { value: "row" }, gap: { value: 4 }, pad: { value: "none" } },
10507
- children: [{ component: "chrome/TextButton", each: { item: "reactions", key: "emoji" }, on: { onClick: ui6("react", { id: { item: "threadId" }, emoji: { item: "emoji" }, on: { item: "reactTo" } }) }, children: [text6({ item: "label" })] }]
10580
+ children: [{ component: "chrome/TextButton", each: { item: "reactions", key: "emoji" }, on: { onClick: ui7("react", { id: { item: "threadId" }, emoji: { item: "emoji" }, on: { item: "reactTo" } }) }, children: [text7({ item: "label" })] }]
10508
10581
  },
10509
10582
  {
10510
10583
  component: "chrome/Stack",
10511
10584
  when: { item: "replying" },
10512
10585
  props: { direction: { value: "row" }, gap: { value: 4 }, pad: { value: "none" } },
10513
10586
  children: [
10514
- { component: "chrome/Input", props: { value: { item: "replyDraft" }, placeholder: { value: "Reply" }, autoFocus: { value: true }, label: { value: "Reply" } }, on: { onChange: ui6("replyDraft", { value: { arg: "" } }), onKeyDown: ui6("replyKey", { id: { item: "id" }, key: { arg: "key" }, shift: { arg: "shiftKey" } }) } },
10515
- { component: "chrome/TextButton", on: { onClick: ui6("reply", { id: { item: "id" } }) }, children: [text6({ value: "Send" })] }
10587
+ { component: "chrome/Input", props: { value: { item: "replyDraft" }, placeholder: { value: "Reply" }, autoFocus: { value: true }, label: { value: "Reply" } }, on: { onChange: ui7("replyDraft", { value: { arg: "" } }), onKeyDown: ui7("replyKey", { id: { item: "id" }, key: { arg: "key" }, shift: { arg: "shiftKey" } }) } },
10588
+ { component: "chrome/TextButton", on: { onClick: ui7("reply", { id: { item: "id" } }) }, children: [text7({ value: "Send" })] }
10516
10589
  ]
10517
10590
  },
10518
10591
  {
@@ -10520,9 +10593,9 @@ var threadCard = (input) => ({
10520
10593
  when: { item: "idle" },
10521
10594
  props: { direction: { value: "row" }, gap: { value: 6 }, pad: { value: "none" } },
10522
10595
  children: [
10523
- { component: "chrome/TextButton", on: { onClick: ui6("startReply", { id: { item: "id" } }) }, children: [text6({ value: "Reply" })] },
10524
- { component: "chrome/TextButton", on: { onClick: ui6("resolve", { id: { item: "id" }, resolved: { item: "resolveTo" } }) }, children: [text6({ item: "resolveLabel" })] },
10525
- { component: "chrome/TextButton", on: { onClick: ui6("remove", { id: { item: "id" } }) }, children: [text6({ value: "Delete" })] }
10596
+ { component: "chrome/TextButton", on: { onClick: ui7("startReply", { id: { item: "id" } }) }, children: [text7({ value: "Reply" })] },
10597
+ { component: "chrome/TextButton", on: { onClick: ui7("resolve", { id: { item: "id" }, resolved: { item: "resolveTo" } }) }, children: [text7({ item: "resolveLabel" })] },
10598
+ { component: "chrome/TextButton", on: { onClick: ui7("remove", { id: { item: "id" } }) }, children: [text7({ value: "Delete" })] }
10526
10599
  ]
10527
10600
  }
10528
10601
  ]
@@ -10537,14 +10610,14 @@ var COMMENTS_DECLARATION = {
10537
10610
  {
10538
10611
  component: "chrome/Toolbar",
10539
10612
  props: {
10540
- left: { node: { component: "chrome/SegmentedControl", props: { label: { value: "Show" }, options: { input: "view.shows" }, value: { input: "view.show" } }, on: { onChange: ui6("show", { show: { arg: "" } }) } } },
10541
- right: { node: { component: "chrome/ToolbarGroup", props: { end: { value: true } }, children: [{ component: "chrome/SegmentedControl", props: { label: { value: "Sort" }, options: { input: "view.sorts" }, value: { input: "view.sort" } }, on: { onChange: ui6("sort", { sort: { arg: "" } }) } }] } }
10613
+ left: { node: { component: "chrome/SegmentedControl", props: { label: { value: "Show" }, options: { input: "view.shows" }, value: { input: "view.show" } }, on: { onChange: ui7("show", { show: { arg: "" } }) } } },
10614
+ right: { node: { component: "chrome/ToolbarGroup", props: { end: { value: true } }, children: [{ component: "chrome/SegmentedControl", props: { label: { value: "Sort" }, options: { input: "view.sorts" }, value: { input: "view.sort" } }, on: { onChange: ui7("sort", { sort: { arg: "" } }) } }] } }
10542
10615
  }
10543
10616
  },
10544
10617
  {
10545
10618
  component: "chrome/Note",
10546
10619
  when: { input: "view.orphanedNotice" },
10547
- children: [text6({ input: "view.orphanedNotice" }), { component: "chrome/TextButton", when: { input: "view.orphanedHidden" }, on: { onClick: ui6("showOrphaned") }, children: [text6({ value: "Show" })] }]
10620
+ children: [text7({ input: "view.orphanedNotice" }), { component: "chrome/TextButton", when: { input: "view.orphanedHidden" }, on: { onClick: ui7("showOrphaned") }, children: [text7({ value: "Show" })] }]
10548
10621
  },
10549
10622
  {
10550
10623
  component: "chrome/ScrollArea",
@@ -10559,8 +10632,8 @@ var COMMENTS_DECLARATION = {
10559
10632
  component: "chrome/Stack",
10560
10633
  props: { gap: { value: 2 }, pad: { value: "gutter" }, className: { value: "xeno-comments-composer" } },
10561
10634
  children: [
10562
- { component: "chrome/TextArea", props: { value: { input: "view.draft" }, placeholder: { input: "view.placeholder" }, disabled: { input: "view.composerDisabled" }, rows: { value: 2 }, label: { value: "New comment" } }, on: { onChange: ui6("draft", { value: { arg: "" } }), onKeyDown: ui6("draftKey", { key: { arg: "key" }, ctrl: { arg: "ctrlKey" }, meta: { arg: "metaKey" } }) } },
10563
- { component: "chrome/Toolbar", props: { divided: { value: false }, right: { node: { component: "chrome/ToolbarGroup", props: { end: { value: true } }, children: [{ component: "chrome/TextButton", props: { strong: { value: true }, disabled: { input: "view.commentDisabled" } }, on: { onClick: ui6("create") }, children: [text6({ value: "Comment" })] }] } } } }
10635
+ { component: "chrome/TextArea", props: { value: { input: "view.draft" }, placeholder: { input: "view.placeholder" }, disabled: { input: "view.composerDisabled" }, rows: { value: 2 }, label: { value: "New comment" } }, on: { onChange: ui7("draft", { value: { arg: "" } }), onKeyDown: ui7("draftKey", { key: { arg: "key" }, ctrl: { arg: "ctrlKey" }, meta: { arg: "metaKey" } }) } },
10636
+ { component: "chrome/Toolbar", props: { divided: { value: false }, right: { node: { component: "chrome/ToolbarGroup", props: { end: { value: true } }, children: [{ component: "chrome/TextButton", props: { strong: { value: true }, disabled: { input: "view.commentDisabled" } }, on: { onClick: ui7("create") }, children: [text7({ value: "Comment" })] }] } } } }
10564
10637
  ]
10565
10638
  },
10566
10639
  { component: "chrome/StatusBar", props: { left: { input: "view.countLabel" }, right: { input: "view.staleLabel" } } }
@@ -10573,37 +10646,37 @@ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
10573
10646
  function CommentsPanelView({ controller, ...options }) {
10574
10647
  useSyncExternalStore8(controller.subscribe, controller.getState, controller.getState);
10575
10648
  const view = commentsViewState(controller, options);
10576
- const ui8 = (intent) => applyCommentsUi(controller, intent);
10577
- const card = (t) => /* @__PURE__ */ jsxs9(ThreadCard, { active: t.active, resolved: t.resolved, onContextMenuAt: (x, y) => ui8({ kind: "contextMenu", id: t.id, x, y }), children: [
10649
+ const ui9 = (intent) => applyCommentsUi(controller, intent);
10650
+ const card = (t) => /* @__PURE__ */ jsxs9(ThreadCard, { active: t.active, resolved: t.resolved, onContextMenuAt: (x, y) => ui9({ kind: "contextMenu", id: t.id, x, y }), children: [
10578
10651
  /* @__PURE__ */ jsxs9(Stack4, { direction: "row", gap: 4, pad: "none", children: [
10579
10652
  t.hasAnchorBadge ? /* @__PURE__ */ jsx10(Badge6, { tone: t.anchorTone, title: t.anchorTitle, children: t.anchorLabel }) : null,
10580
10653
  t.resolved ? /* @__PURE__ */ jsx10(Badge6, { children: "resolved" }) : null,
10581
- /* @__PURE__ */ jsx10(Text6, { role: "caption", children: t.age })
10654
+ /* @__PURE__ */ jsx10(Text7, { role: "caption", children: t.age })
10582
10655
  ] }),
10583
- t.hasQuote ? /* @__PURE__ */ jsx10(Quote, { orphaned: t.orphaned, onActivate: () => ui8({ kind: "activate", id: t.id }), children: t.quote }) : null,
10656
+ t.hasQuote ? /* @__PURE__ */ jsx10(Quote, { orphaned: t.orphaned, onActivate: () => ui9({ kind: "activate", id: t.id }), children: t.quote }) : null,
10584
10657
  t.messages.map((m) => /* @__PURE__ */ jsx10(Message, { author: m.author, age: m.age, edited: m.edited, children: m.body }, m.id)),
10585
- t.hasReactions ? /* @__PURE__ */ jsx10(Stack4, { direction: "row", gap: 4, pad: "none", children: t.reactions.map((r) => /* @__PURE__ */ jsx10(TextButton4, { onClick: () => ui8({ kind: "react", id: r.threadId, emoji: r.emoji, on: r.reactTo }), children: r.label }, r.emoji)) }) : null,
10658
+ t.hasReactions ? /* @__PURE__ */ jsx10(Stack4, { direction: "row", gap: 4, pad: "none", children: t.reactions.map((r) => /* @__PURE__ */ jsx10(TextButton5, { onClick: () => ui9({ kind: "react", id: r.threadId, emoji: r.emoji, on: r.reactTo }), children: r.label }, r.emoji)) }) : null,
10586
10659
  t.replying ? /* @__PURE__ */ jsxs9(Stack4, { direction: "row", gap: 4, pad: "none", children: [
10587
- /* @__PURE__ */ jsx10(Input4, { value: t.replyDraft, placeholder: "Reply", autoFocus: true, label: "Reply", onChange: (value) => ui8({ kind: "replyDraft", value }), onKeyDown: (e) => ui8({ kind: "replyKey", id: t.id, key: e.key, shift: e.shiftKey }) }),
10588
- /* @__PURE__ */ jsx10(TextButton4, { onClick: () => ui8({ kind: "reply", id: t.id }), children: "Send" })
10660
+ /* @__PURE__ */ jsx10(Input4, { value: t.replyDraft, placeholder: "Reply", autoFocus: true, label: "Reply", onChange: (value) => ui9({ kind: "replyDraft", value }), onKeyDown: (e) => ui9({ kind: "replyKey", id: t.id, key: e.key, shift: e.shiftKey }) }),
10661
+ /* @__PURE__ */ jsx10(TextButton5, { onClick: () => ui9({ kind: "reply", id: t.id }), children: "Send" })
10589
10662
  ] }) : null,
10590
10663
  t.idle ? /* @__PURE__ */ jsxs9(Stack4, { direction: "row", gap: 6, pad: "none", children: [
10591
- /* @__PURE__ */ jsx10(TextButton4, { onClick: () => ui8({ kind: "startReply", id: t.id }), children: "Reply" }),
10592
- /* @__PURE__ */ jsx10(TextButton4, { onClick: () => ui8({ kind: "resolve", id: t.id, resolved: t.resolveTo }), children: t.resolveLabel }),
10593
- /* @__PURE__ */ jsx10(TextButton4, { onClick: () => ui8({ kind: "remove", id: t.id }), children: "Delete" })
10664
+ /* @__PURE__ */ jsx10(TextButton5, { onClick: () => ui9({ kind: "startReply", id: t.id }), children: "Reply" }),
10665
+ /* @__PURE__ */ jsx10(TextButton5, { onClick: () => ui9({ kind: "resolve", id: t.id, resolved: t.resolveTo }), children: t.resolveLabel }),
10666
+ /* @__PURE__ */ jsx10(TextButton5, { onClick: () => ui9({ kind: "remove", id: t.id }), children: "Delete" })
10594
10667
  ] }) : null
10595
10668
  ] }, t.id);
10596
- return /* @__PURE__ */ jsxs9(Column6, { children: [
10669
+ return /* @__PURE__ */ jsxs9(Column7, { children: [
10597
10670
  /* @__PURE__ */ jsx10(
10598
10671
  Toolbar5,
10599
10672
  {
10600
- left: /* @__PURE__ */ jsx10(SegmentedControl2, { label: "Show", options: view.shows, value: view.show, onChange: (show) => ui8({ kind: "show", show }) }),
10601
- right: /* @__PURE__ */ jsx10(ToolbarGroup3, { end: true, children: /* @__PURE__ */ jsx10(SegmentedControl2, { label: "Sort", options: view.sorts, value: view.sort, onChange: (sort) => ui8({ kind: "sort", sort }) }) })
10673
+ left: /* @__PURE__ */ jsx10(SegmentedControl2, { label: "Show", options: view.shows, value: view.show, onChange: (show) => ui9({ kind: "show", show }) }),
10674
+ right: /* @__PURE__ */ jsx10(ToolbarGroup3, { end: true, children: /* @__PURE__ */ jsx10(SegmentedControl2, { label: "Sort", options: view.sorts, value: view.sort, onChange: (sort) => ui9({ kind: "sort", sort }) }) })
10602
10675
  }
10603
10676
  ),
10604
10677
  view.orphanedNotice ? /* @__PURE__ */ jsxs9(Note, { children: [
10605
10678
  view.orphanedNotice,
10606
- view.orphanedHidden ? /* @__PURE__ */ jsx10(TextButton4, { onClick: () => ui8({ kind: "showOrphaned" }), children: "Show" }) : null
10679
+ view.orphanedHidden ? /* @__PURE__ */ jsx10(TextButton5, { onClick: () => ui9({ kind: "showOrphaned" }), children: "Show" }) : null
10607
10680
  ] }) : null,
10608
10681
  /* @__PURE__ */ jsxs9(ScrollArea5, { children: [
10609
10682
  view.filteredEmpty ? /* @__PURE__ */ jsx10(EmptyState6, { title: "Nothing matches this filter", hint: view.filteredHint }) : null,
@@ -10612,8 +10685,8 @@ function CommentsPanelView({ controller, ...options }) {
10612
10685
  view.hasResolved ? /* @__PURE__ */ jsx10(Section4, { title: view.resolvedTitle, flush: true, children: view.resolved.map(card) }) : null
10613
10686
  ] }),
10614
10687
  /* @__PURE__ */ jsxs9(Stack4, { gap: 2, pad: "gutter", className: "xeno-comments-composer", children: [
10615
- /* @__PURE__ */ jsx10(TextArea2, { value: view.draft, placeholder: view.placeholder, disabled: view.composerDisabled, rows: 2, label: "New comment", onChange: (value) => ui8({ kind: "draft", value }), onKeyDown: (e) => ui8({ kind: "draftKey", key: e.key, ctrl: e.ctrlKey, meta: e.metaKey }) }),
10616
- /* @__PURE__ */ jsx10(Toolbar5, { divided: false, right: /* @__PURE__ */ jsx10(ToolbarGroup3, { end: true, children: /* @__PURE__ */ jsx10(TextButton4, { strong: true, disabled: view.commentDisabled, onClick: () => ui8({ kind: "create" }), children: "Comment" }) }) })
10688
+ /* @__PURE__ */ jsx10(TextArea2, { value: view.draft, placeholder: view.placeholder, disabled: view.composerDisabled, rows: 2, label: "New comment", onChange: (value) => ui9({ kind: "draft", value }), onKeyDown: (e) => ui9({ kind: "draftKey", key: e.key, ctrl: e.ctrlKey, meta: e.metaKey }) }),
10689
+ /* @__PURE__ */ jsx10(Toolbar5, { divided: false, right: /* @__PURE__ */ jsx10(ToolbarGroup3, { end: true, children: /* @__PURE__ */ jsx10(TextButton5, { strong: true, disabled: view.commentDisabled, onClick: () => ui9({ kind: "create" }), children: "Comment" }) }) })
10617
10690
  ] }),
10618
10691
  /* @__PURE__ */ jsx10(StatusBar6, { left: view.countLabel, right: view.staleLabel })
10619
10692
  ] });
@@ -11862,13 +11935,13 @@ function NodeGraphPanelView({ controller }) {
11862
11935
  const selectedNodes = new Set(state.selection.nodeIds);
11863
11936
  const selectedEdges = new Set(state.selection.edgeIds);
11864
11937
  const total = state.graph?.nodes.length ?? 0;
11865
- return /* @__PURE__ */ jsxs10("div", { style: SHELL2, children: [
11938
+ return /* @__PURE__ */ jsxs10("div", { style: SHELL, children: [
11866
11939
  /* @__PURE__ */ jsx11(
11867
11940
  Toolbar6,
11868
11941
  {
11869
11942
  right: /* @__PURE__ */ jsxs10(ToolbarGroup4, { end: true, children: [
11870
- /* @__PURE__ */ jsx11("button", { type: "button", style: button2(), onClick: () => controller.fit(false), children: "Fit" }),
11871
- /* @__PURE__ */ jsx11("button", { type: "button", style: button2(), onClick: () => controller.fit(true), children: "Fit selection" })
11943
+ /* @__PURE__ */ jsx11("button", { type: "button", style: button(), onClick: () => controller.fit(false), children: "Fit" }),
11944
+ /* @__PURE__ */ jsx11("button", { type: "button", style: button(), onClick: () => controller.fit(true), children: "Fit selection" })
11872
11945
  ] })
11873
11946
  }
11874
11947
  ),
@@ -12066,7 +12139,7 @@ function Port({
12066
12139
  )
12067
12140
  ] });
12068
12141
  }
12069
- var SHELL2 = { display: "flex", flexDirection: "column", height: "100%", minHeight: 0 };
12142
+ var SHELL = { display: "flex", flexDirection: "column", height: "100%", minHeight: 0 };
12070
12143
  var SURFACE2 = {
12071
12144
  position: "relative",
12072
12145
  flex: 1,
@@ -12088,7 +12161,7 @@ var REASON = {
12088
12161
  color: "var(--xeno-text)",
12089
12162
  pointerEvents: "none"
12090
12163
  };
12091
- function button2() {
12164
+ function button() {
12092
12165
  return {
12093
12166
  height: 18,
12094
12167
  padding: "0 6px",
@@ -12755,12 +12828,12 @@ var TreeController = class {
12755
12828
  }
12756
12829
  if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
12757
12830
  const fresh = now - this.typeAhead.at > this.typeAheadMs;
12758
- const text8 = (fresh ? "" : this.typeAhead.text) + event.key.toLowerCase();
12759
- this.typeAhead = { text: text8, at: now };
12831
+ const text9 = (fresh ? "" : this.typeAhead.text) + event.key.toLowerCase();
12832
+ this.typeAhead = { text: text9, at: now };
12760
12833
  const from = fresh ? current : current + 1;
12761
12834
  for (let i = 0; i < rows.length; i += 1) {
12762
12835
  const candidate = rows[(from + i) % rows.length];
12763
- if (candidate.node.label.toLowerCase().startsWith(text8)) {
12836
+ if (candidate.node.label.toLowerCase().startsWith(text9)) {
12764
12837
  this.focusedId = candidate.id;
12765
12838
  this.select([candidate.id]);
12766
12839
  return true;
@@ -12786,9 +12859,9 @@ var TreeController = class {
12786
12859
  return true;
12787
12860
  }
12788
12861
  /** Update the rename draft. */
12789
- updateRenameDraft(text8) {
12862
+ updateRenameDraft(text9) {
12790
12863
  if (!this.renaming) return;
12791
- this.renaming = { ...this.renaming, draft: text8 };
12864
+ this.renaming = { ...this.renaming, draft: text9 };
12792
12865
  this.notify();
12793
12866
  }
12794
12867
  /**
@@ -13328,7 +13401,7 @@ var treeManifest = {
13328
13401
  import { useCallback as useCallback8, useEffect as useEffect8, useRef as useRef9, useSyncExternalStore as useSyncExternalStore10 } from "react";
13329
13402
  import {
13330
13403
  Badge as Badge7,
13331
- Column as Column7,
13404
+ Column as Column8,
13332
13405
  EmptyState as EmptyState8,
13333
13406
  ErrorState,
13334
13407
  IconButton as IconButton7,
@@ -13339,8 +13412,8 @@ import {
13339
13412
  ScrollArea as ScrollArea6,
13340
13413
  SearchField as SearchField5,
13341
13414
  StatusBar as StatusBar8,
13342
- Text as Text7,
13343
- TextButton as TextButton5,
13415
+ Text as Text8,
13416
+ TextButton as TextButton6,
13344
13417
  Toolbar as Toolbar7,
13345
13418
  ToolbarGroup as ToolbarGroup5,
13346
13419
  VirtualWindow as VirtualWindow3
@@ -13502,7 +13575,7 @@ var treeViewManifest = {
13502
13575
  outputs: [{ id: "ui", type: "object", label: "UI intent", description: "{ kind, id?, value?, key?, actionId?, x?, y?, ctrlKey?, metaKey?, shiftKey?, altKey? } \u2014 applied by the runtime to the controller." }],
13503
13576
  commands: []
13504
13577
  };
13505
- var EMPTY7 = {
13578
+ var EMPTY8 = {
13506
13579
  searchShown: true,
13507
13580
  filter: "",
13508
13581
  noSource: true,
@@ -13523,16 +13596,16 @@ var EMPTY7 = {
13523
13596
  rows: [],
13524
13597
  countLabel: "0 items"
13525
13598
  };
13526
- var BEHAVIOURS7 = {
13527
- "edit/treePanelView": (inputs) => inputs.view ?? EMPTY7
13599
+ var BEHAVIOURS8 = {
13600
+ "edit/treePanelView": (inputs) => inputs.view ?? EMPTY8
13528
13601
  };
13529
- var text7 = (b) => ({ component: "text", props: { text: b } });
13530
- var ui7 = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
13602
+ var text8 = (b) => ({ component: "text", props: { text: b } });
13603
+ var ui8 = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
13531
13604
  var nodeIcon = () => ({
13532
13605
  component: "fragment",
13533
13606
  children: [
13534
13607
  { component: "icons/TreeKind", when: { item: "iconName" }, props: { name: { item: "iconName" } } },
13535
- { component: "chrome/Text", when: { item: "iconText" }, props: { role: { value: "caption" } }, children: [text7({ item: "iconText" })] }
13608
+ { component: "chrome/Text", when: { item: "iconText" }, props: { role: { value: "caption" } }, children: [text8({ item: "iconText" })] }
13536
13609
  ]
13537
13610
  });
13538
13611
  var TREE_DECLARATION = {
@@ -13545,15 +13618,15 @@ var TREE_DECLARATION = {
13545
13618
  {
13546
13619
  component: "chrome/Toolbar",
13547
13620
  props: {
13548
- left: { node: { component: "chrome/SearchField", when: { input: "view.searchShown" }, props: { value: { input: "view.filter" }, placeholder: { value: "Filter\u2026" } }, on: { onChange: ui7("filter", { value: { arg: "" } }) } } },
13621
+ left: { node: { component: "chrome/SearchField", when: { input: "view.searchShown" }, props: { value: { input: "view.filter" }, placeholder: { value: "Filter\u2026" } }, on: { onChange: ui8("filter", { value: { arg: "" } }) } } },
13549
13622
  right: {
13550
13623
  node: {
13551
13624
  component: "chrome/ToolbarGroup",
13552
13625
  props: { end: { value: true } },
13553
13626
  children: [
13554
- { component: "chrome/IconButton", props: { icon: { node: { component: "icons/Expand" } }, label: { value: "Expand all" } }, on: { onClick: ui7("expandAll") } },
13555
- { component: "chrome/IconButton", props: { icon: { node: { component: "icons/Collapse" } }, label: { value: "Collapse all" } }, on: { onClick: ui7("collapseAll") } },
13556
- { component: "chrome/IconButton", props: { icon: { node: { component: "icons/Refresh" } }, label: { value: "Refresh" } }, on: { onClick: ui7("refresh") } }
13627
+ { component: "chrome/IconButton", props: { icon: { node: { component: "icons/Expand" } }, label: { value: "Expand all" } }, on: { onClick: ui8("expandAll") } },
13628
+ { component: "chrome/IconButton", props: { icon: { node: { component: "icons/Collapse" } }, label: { value: "Collapse all" } }, on: { onClick: ui8("collapseAll") } },
13629
+ { component: "chrome/IconButton", props: { icon: { node: { component: "icons/Refresh" } }, label: { value: "Refresh" } }, on: { onClick: ui8("refresh") } }
13557
13630
  ]
13558
13631
  }
13559
13632
  }
@@ -13561,7 +13634,7 @@ var TREE_DECLARATION = {
13561
13634
  },
13562
13635
  { component: "chrome/EmptyState", when: { input: "view.noSource" }, props: { title: { value: "No source" }, hint: { input: "view.noSourceHint" } } },
13563
13636
  { component: "chrome/LoadingState", when: { input: "view.loading" }, props: { label: { input: "view.loadingLabel" } } },
13564
- { component: "chrome/ErrorState", when: { input: "view.failed" }, props: { title: { input: "view.failedTitle" }, message: { input: "view.failedMessage" }, retryLabel: { input: "view.retryLabel" } }, on: { onRetry: ui7("retry") } },
13637
+ { component: "chrome/ErrorState", when: { input: "view.failed" }, props: { title: { input: "view.failedTitle" }, message: { input: "view.failedMessage" }, retryLabel: { input: "view.retryLabel" } }, on: { onRetry: ui8("retry") } },
13565
13638
  { component: "chrome/EmptyState", when: { input: "view.noMatches" }, props: { title: { value: "No matches" }, hint: { input: "view.noMatchesHint" } } },
13566
13639
  { component: "chrome/EmptyState", when: { input: "view.emptyTree" }, props: { title: { value: "Nothing here" }, hint: { input: "view.emptyHint" } } },
13567
13640
  {
@@ -13594,7 +13667,7 @@ var TREE_DECLARATION = {
13594
13667
  node: {
13595
13668
  component: "fragment",
13596
13669
  children: [
13597
- { component: "chrome/Input", when: { item: "renaming" }, props: { autoFocus: { value: true }, value: { item: "draft" }, label: { value: "Name" } }, on: { onChange: ui7("renameDraft", { value: { arg: "" } }), onBlur: ui7("commitRename"), onKeyDown: ui7("renameKey", { key: { arg: "key" } }) } },
13670
+ { component: "chrome/Input", when: { item: "renaming" }, props: { autoFocus: { value: true }, value: { item: "draft" }, label: { value: "Name" } }, on: { onChange: ui8("renameDraft", { value: { arg: "" } }), onBlur: ui8("commitRename"), onKeyDown: ui8("renameKey", { key: { arg: "key" } }) } },
13598
13671
  { component: "text", when: { not: { item: "renaming" } }, props: { text: { item: "label" } } }
13599
13672
  ]
13600
13673
  }
@@ -13603,11 +13676,11 @@ var TREE_DECLARATION = {
13603
13676
  node: {
13604
13677
  component: "fragment",
13605
13678
  children: [
13606
- { component: "chrome/Text", when: { item: "chipLoading" }, props: { role: { value: "caption" } }, children: [text7({ value: "loading\u2026" })] },
13607
- { component: "chrome/Badge", when: { item: "chipError" }, props: { tone: { value: "error" } }, children: [text7({ item: "chipErrorText" })] },
13608
- { component: "chrome/TextButton", when: { item: "chipLoadMore" }, children: [text7({ value: "load more\u2026" })], on: { onClick: ui7("loadMore", { id: { item: "id" } }) } },
13609
- { component: "chrome/Badge", when: { item: "chipTruncated" }, props: { tone: { value: "warning" } }, children: [text7({ item: "chipTruncatedText" })] },
13610
- { component: "chrome/Text", when: { item: "chipEmpty" }, props: { role: { value: "caption" } }, children: [text7({ value: "empty" })] }
13679
+ { component: "chrome/Text", when: { item: "chipLoading" }, props: { role: { value: "caption" } }, children: [text8({ value: "loading\u2026" })] },
13680
+ { component: "chrome/Badge", when: { item: "chipError" }, props: { tone: { value: "error" } }, children: [text8({ item: "chipErrorText" })] },
13681
+ { component: "chrome/TextButton", when: { item: "chipLoadMore" }, children: [text8({ value: "load more\u2026" })], on: { onClick: ui8("loadMore", { id: { item: "id" } }) } },
13682
+ { component: "chrome/Badge", when: { item: "chipTruncated" }, props: { tone: { value: "warning" } }, children: [text8({ item: "chipTruncatedText" })] },
13683
+ { component: "chrome/Text", when: { item: "chipEmpty" }, props: { role: { value: "caption" } }, children: [text8({ value: "empty" })] }
13611
13684
  ]
13612
13685
  }
13613
13686
  },
@@ -13615,19 +13688,19 @@ var TREE_DECLARATION = {
13615
13688
  node: {
13616
13689
  component: "fragment",
13617
13690
  children: [
13618
- { component: "chrome/Text", each: { item: "columns", key: "key" }, props: { role: { value: "number" } }, children: [text7({ item: "text" })] },
13691
+ { component: "chrome/Text", each: { item: "columns", key: "key" }, props: { role: { value: "number" } }, children: [text8({ item: "text" })] },
13619
13692
  { component: "chrome/Text", each: { item: "glyphs", key: "key" }, props: { role: { value: "meta" }, title: { item: "title" } }, children: [nodeIcon()] },
13620
- { component: "chrome/Badge", each: { item: "badges", key: "key" }, props: { tone: { item: "tone" } }, children: [text7({ item: "text" })] },
13621
- { component: "chrome/IconButton", each: { item: "actions", key: "key" }, props: { size: { value: "sm" }, icon: { node: nodeIcon() }, label: { item: "label" }, disabled: { item: "disabled" } }, on: { onClick: ui7("action", { id: { item: "rowId" }, actionId: { item: "actionId" } }) } }
13693
+ { component: "chrome/Badge", each: { item: "badges", key: "key" }, props: { tone: { item: "tone" } }, children: [text8({ item: "text" })] },
13694
+ { component: "chrome/IconButton", each: { item: "actions", key: "key" }, props: { size: { value: "sm" }, icon: { node: nodeIcon() }, label: { item: "label" }, disabled: { item: "disabled" } }, on: { onClick: ui8("action", { id: { item: "rowId" }, actionId: { item: "actionId" } }) } }
13622
13695
  ]
13623
13696
  }
13624
13697
  }
13625
13698
  },
13626
13699
  on: {
13627
- onExpandedChange: ui7("toggleExpanded", { id: { item: "id" } }),
13628
- onClick: ui7("click", { id: { item: "id" }, ctrlKey: { arg: "ctrlKey" }, metaKey: { arg: "metaKey" }, shiftKey: { arg: "shiftKey" }, altKey: { arg: "altKey" } }),
13629
- onDoubleClick: ui7("doubleClick", { id: { item: "id" } }),
13630
- onContextMenuAt: ui7("contextMenu", { id: { item: "id" }, x: { arg: "" }, y: { arg: "", index: 1 } })
13700
+ onExpandedChange: ui8("toggleExpanded", { id: { item: "id" } }),
13701
+ onClick: ui8("click", { id: { item: "id" }, ctrlKey: { arg: "ctrlKey" }, metaKey: { arg: "metaKey" }, shiftKey: { arg: "shiftKey" }, altKey: { arg: "altKey" } }),
13702
+ onDoubleClick: ui8("doubleClick", { id: { item: "id" } }),
13703
+ onContextMenuAt: ui8("contextMenu", { id: { item: "id" }, x: { arg: "" }, y: { arg: "", index: 1 } })
13631
13704
  }
13632
13705
  }
13633
13706
  ]
@@ -13639,8 +13712,8 @@ var TREE_DECLARATION = {
13639
13712
  {
13640
13713
  component: "chrome/StatusBar",
13641
13714
  props: {
13642
- left: { node: { component: "chrome/Text", props: { role: { value: "number" } }, children: [text7({ input: "view.countLabel" })] } },
13643
- right: { node: { component: "chrome/Text", when: { input: "view.selectedLabel" }, props: { role: { value: "meta" } }, children: [text7({ input: "view.selectedLabel" })] } }
13715
+ left: { node: { component: "chrome/Text", props: { role: { value: "number" } }, children: [text8({ input: "view.countLabel" })] } },
13716
+ right: { node: { component: "chrome/Text", when: { input: "view.selectedLabel" }, props: { role: { value: "meta" } }, children: [text8({ input: "view.selectedLabel" })] } }
13644
13717
  }
13645
13718
  }
13646
13719
  ]
@@ -13653,10 +13726,10 @@ var DRAG_THRESHOLD2 = 4;
13653
13726
  function TreePanelView({ controller, ...options }) {
13654
13727
  useSyncExternalStore10(controller.subscribe, controller.getState, controller.getState);
13655
13728
  const view = treeViewState(controller, options);
13656
- const ui8 = (intent) => applyTreeUi(controller, intent, options);
13729
+ const ui9 = (intent) => applyTreeUi(controller, intent, options);
13657
13730
  const icon = (name, textValue) => /* @__PURE__ */ jsxs11(Fragment8, { children: [
13658
13731
  name ? /* @__PURE__ */ jsx12(TreeIcon, { name }) : null,
13659
- textValue ? /* @__PURE__ */ jsx12(Text7, { role: "caption", children: textValue }) : null
13732
+ textValue ? /* @__PURE__ */ jsx12(Text8, { role: "caption", children: textValue }) : null
13660
13733
  ] });
13661
13734
  const row2 = (r) => /* @__PURE__ */ jsx12(
13662
13735
  Row4,
@@ -13672,48 +13745,48 @@ function TreePanelView({ controller, ...options }) {
13672
13745
  title: r.dropTitle,
13673
13746
  icon: icon(r.iconName, r.iconText),
13674
13747
  label: /* @__PURE__ */ jsxs11(Fragment8, { children: [
13675
- r.renaming ? /* @__PURE__ */ jsx12(Input5, { autoFocus: true, value: r.draft, label: "Name", onChange: (value) => ui8({ kind: "renameDraft", value }), onBlur: () => ui8({ kind: "commitRename" }), onKeyDown: (e) => ui8({ kind: "renameKey", key: e.key }) }) : null,
13748
+ r.renaming ? /* @__PURE__ */ jsx12(Input5, { autoFocus: true, value: r.draft, label: "Name", onChange: (value) => ui9({ kind: "renameDraft", value }), onBlur: () => ui9({ kind: "commitRename" }), onKeyDown: (e) => ui9({ kind: "renameKey", key: e.key }) }) : null,
13676
13749
  !r.renaming ? r.label : null
13677
13750
  ] }),
13678
13751
  meta: /* @__PURE__ */ jsxs11(Fragment8, { children: [
13679
- r.chipLoading ? /* @__PURE__ */ jsx12(Text7, { role: "caption", children: "loading\u2026" }) : null,
13752
+ r.chipLoading ? /* @__PURE__ */ jsx12(Text8, { role: "caption", children: "loading\u2026" }) : null,
13680
13753
  r.chipError ? /* @__PURE__ */ jsx12(Badge7, { tone: "error", children: r.chipErrorText }) : null,
13681
- r.chipLoadMore ? /* @__PURE__ */ jsx12(TextButton5, { onClick: () => ui8({ kind: "loadMore", id: r.id }), children: "load more\u2026" }) : null,
13754
+ r.chipLoadMore ? /* @__PURE__ */ jsx12(TextButton6, { onClick: () => ui9({ kind: "loadMore", id: r.id }), children: "load more\u2026" }) : null,
13682
13755
  r.chipTruncated ? /* @__PURE__ */ jsx12(Badge7, { tone: "warning", children: r.chipTruncatedText }) : null,
13683
- r.chipEmpty ? /* @__PURE__ */ jsx12(Text7, { role: "caption", children: "empty" }) : null
13756
+ r.chipEmpty ? /* @__PURE__ */ jsx12(Text8, { role: "caption", children: "empty" }) : null
13684
13757
  ] }),
13685
13758
  trailing: /* @__PURE__ */ jsxs11(Fragment8, { children: [
13686
- r.columns.map((c) => /* @__PURE__ */ jsx12(Text7, { role: "number", children: c.text }, c.key)),
13687
- r.glyphs.map((g) => /* @__PURE__ */ jsx12(Text7, { role: "meta", title: g.title, children: icon(g.iconName, g.iconText) }, g.key)),
13759
+ r.columns.map((c) => /* @__PURE__ */ jsx12(Text8, { role: "number", children: c.text }, c.key)),
13760
+ r.glyphs.map((g) => /* @__PURE__ */ jsx12(Text8, { role: "meta", title: g.title, children: icon(g.iconName, g.iconText) }, g.key)),
13688
13761
  r.badges.map((b) => /* @__PURE__ */ jsx12(Badge7, { tone: b.tone, children: b.text }, b.key)),
13689
- r.actions.map((a) => /* @__PURE__ */ jsx12(IconButton7, { size: "sm", icon: icon(a.iconName, a.iconText), label: a.label, disabled: a.disabled, onClick: () => ui8({ kind: "action", id: a.rowId, actionId: a.actionId }) }, a.key))
13762
+ r.actions.map((a) => /* @__PURE__ */ jsx12(IconButton7, { size: "sm", icon: icon(a.iconName, a.iconText), label: a.label, disabled: a.disabled, onClick: () => ui9({ kind: "action", id: a.rowId, actionId: a.actionId }) }, a.key))
13690
13763
  ] }),
13691
- onExpandedChange: () => ui8({ kind: "toggleExpanded", id: r.id }),
13692
- onClick: (e) => ui8({ kind: "click", id: r.id, ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey, altKey: e.altKey }),
13693
- onDoubleClick: () => ui8({ kind: "doubleClick", id: r.id }),
13694
- onContextMenuAt: (x, y) => ui8({ kind: "contextMenu", id: r.id, x, y })
13764
+ onExpandedChange: () => ui9({ kind: "toggleExpanded", id: r.id }),
13765
+ onClick: (e) => ui9({ kind: "click", id: r.id, ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey, altKey: e.altKey }),
13766
+ onDoubleClick: () => ui9({ kind: "doubleClick", id: r.id }),
13767
+ onContextMenuAt: (x, y) => ui9({ kind: "contextMenu", id: r.id, x, y })
13695
13768
  },
13696
13769
  r.id
13697
13770
  );
13698
- return /* @__PURE__ */ jsxs11(Column7, { children: [
13771
+ return /* @__PURE__ */ jsxs11(Column8, { children: [
13699
13772
  /* @__PURE__ */ jsx12(
13700
13773
  Toolbar7,
13701
13774
  {
13702
- left: view.searchShown ? /* @__PURE__ */ jsx12(SearchField5, { value: view.filter, placeholder: "Filter\u2026", onChange: (value) => ui8({ kind: "filter", value }) }) : null,
13775
+ left: view.searchShown ? /* @__PURE__ */ jsx12(SearchField5, { value: view.filter, placeholder: "Filter\u2026", onChange: (value) => ui9({ kind: "filter", value }) }) : null,
13703
13776
  right: /* @__PURE__ */ jsxs11(ToolbarGroup5, { end: true, children: [
13704
- /* @__PURE__ */ jsx12(IconButton7, { icon: /* @__PURE__ */ jsx12(ExpandGlyph, {}), label: "Expand all", onClick: () => ui8({ kind: "expandAll" }) }),
13705
- /* @__PURE__ */ jsx12(IconButton7, { icon: /* @__PURE__ */ jsx12(CollapseGlyph, {}), label: "Collapse all", onClick: () => ui8({ kind: "collapseAll" }) }),
13706
- /* @__PURE__ */ jsx12(IconButton7, { icon: /* @__PURE__ */ jsx12(RefreshGlyph, {}), label: "Refresh", onClick: () => ui8({ kind: "refresh" }) })
13777
+ /* @__PURE__ */ jsx12(IconButton7, { icon: /* @__PURE__ */ jsx12(ExpandGlyph, {}), label: "Expand all", onClick: () => ui9({ kind: "expandAll" }) }),
13778
+ /* @__PURE__ */ jsx12(IconButton7, { icon: /* @__PURE__ */ jsx12(CollapseGlyph, {}), label: "Collapse all", onClick: () => ui9({ kind: "collapseAll" }) }),
13779
+ /* @__PURE__ */ jsx12(IconButton7, { icon: /* @__PURE__ */ jsx12(RefreshGlyph, {}), label: "Refresh", onClick: () => ui9({ kind: "refresh" }) })
13707
13780
  ] })
13708
13781
  }
13709
13782
  ),
13710
13783
  view.noSource ? /* @__PURE__ */ jsx12(EmptyState8, { title: "No source", hint: view.noSourceHint }) : null,
13711
13784
  view.loading ? /* @__PURE__ */ jsx12(LoadingState, { label: view.loadingLabel }) : null,
13712
- view.failed ? /* @__PURE__ */ jsx12(ErrorState, { title: view.failedTitle, message: view.failedMessage, retryLabel: view.retryLabel, onRetry: () => ui8({ kind: "retry" }) }) : null,
13785
+ view.failed ? /* @__PURE__ */ jsx12(ErrorState, { title: view.failedTitle, message: view.failedMessage, retryLabel: view.retryLabel, onRetry: () => ui9({ kind: "retry" }) }) : null,
13713
13786
  view.noMatches ? /* @__PURE__ */ jsx12(EmptyState8, { title: "No matches", hint: view.noMatchesHint }) : null,
13714
13787
  view.emptyTree ? /* @__PURE__ */ jsx12(EmptyState8, { title: "Nothing here", hint: view.emptyHint }) : null,
13715
13788
  view.listShown ? /* @__PURE__ */ jsx12(TreeScroller, { controller, children: /* @__PURE__ */ jsx12(RowList4, { role: "tree", "aria-label": "Tree", "aria-multiselectable": true, children: /* @__PURE__ */ jsx12(VirtualWindow3, { totalHeight: view.totalHeight, offsetTop: view.offsetTop, children: view.rows.map(row2) }) }) }) : null,
13716
- /* @__PURE__ */ jsx12(StatusBar8, { left: /* @__PURE__ */ jsx12(Text7, { role: "number", children: view.countLabel }), right: view.selectedLabel ? /* @__PURE__ */ jsx12(Text7, { role: "meta", children: view.selectedLabel }) : null })
13789
+ /* @__PURE__ */ jsx12(StatusBar8, { left: /* @__PURE__ */ jsx12(Text8, { role: "number", children: view.countLabel }), right: view.selectedLabel ? /* @__PURE__ */ jsx12(Text8, { role: "meta", children: view.selectedLabel }) : null })
13717
13790
  ] });
13718
13791
  }
13719
13792
  function TreeScroller({ controller, children }) {
@@ -14001,17 +14074,21 @@ export {
14001
14074
  COLOR_DECLARATION,
14002
14075
  COLOR_RUNTIME_UNITS,
14003
14076
  COLOR_SPACES,
14004
- BEHAVIOURS6 as COMMENTS_BEHAVIOURS,
14077
+ BEHAVIOURS7 as COMMENTS_BEHAVIOURS,
14005
14078
  COMMENTS_DECLARATION,
14006
14079
  COMMENTS_PANEL_ID,
14007
14080
  COMMENTS_RUNTIME_UNITS,
14081
+ BEHAVIOURS5 as CURVE_BEHAVIOURS,
14082
+ CURVE_DECLARATION,
14008
14083
  CURVE_PANEL_ID,
14084
+ CURVE_RUNTIME_UNITS,
14009
14085
  ColorPanelController,
14010
14086
  ColorPanelView,
14011
14087
  CommentsController,
14012
14088
  CommentsPanelView,
14013
14089
  CurveController,
14014
14090
  CurvePanelView,
14091
+ CurveSurface,
14015
14092
  DEFAULT_BLEND_MODES,
14016
14093
  DEFAULT_CURVE_ZOOM,
14017
14094
  DEFAULT_GRAPH_ZOOM,
@@ -14023,7 +14100,7 @@ export {
14023
14100
  EMPTY_SCHEMA,
14024
14101
  EMPTY_TREE,
14025
14102
  EMPTY_TREE_SOURCE,
14026
- BEHAVIOURS5 as FIND_BEHAVIOURS,
14103
+ BEHAVIOURS6 as FIND_BEHAVIOURS,
14027
14104
  FIND_DECLARATION,
14028
14105
  FIND_PANEL_ID,
14029
14106
  FIND_RUNTIME_UNITS,
@@ -14053,7 +14130,7 @@ export {
14053
14130
  NODEGRAPH_PANEL_ID,
14054
14131
  NodeGraphPanelView,
14055
14132
  SPACE_LABEL,
14056
- BEHAVIOURS7 as TREE_BEHAVIOURS,
14133
+ BEHAVIOURS8 as TREE_BEHAVIOURS,
14057
14134
  TREE_DECLARATION,
14058
14135
  TREE_PANEL_ID,
14059
14136
  TREE_RUNTIME_UNITS,
@@ -14076,6 +14153,7 @@ export {
14076
14153
  appliedCount,
14077
14154
  applyColorUi,
14078
14155
  applyCommentsUi,
14156
+ applyCurveUi,
14079
14157
  applyFindUi,
14080
14158
  applyHistoryUi,
14081
14159
  applyInspectorUi,
@@ -14121,6 +14199,9 @@ export {
14121
14199
  currentRowIndex,
14122
14200
  curveManifest,
14123
14201
  curvePanel,
14202
+ curveRuntimeComponents,
14203
+ curveViewManifest,
14204
+ curveViewState,
14124
14205
  defaultIconFor,
14125
14206
  displayOrder,
14126
14207
  distanceToEdge,