@xenosystem/blocks 0.13.16 → 0.13.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/index.js +1 -1
- package/dist/edit/index.d.ts +345 -28
- package/dist/edit/index.js +815 -632
- package/dist/icons/index.js +1 -1
- package/dist/ops/index.js +1 -1
- package/dist/time/index.js +1 -1
- package/package.json +3 -3
- /package/dist/{chunk-PI5WOATA.js → chunk-7S2RKUAM.js} +0 -0
package/dist/edit/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ChevronGlyph,
|
|
3
2
|
CollapseGlyph,
|
|
4
3
|
DiamondIcon,
|
|
5
4
|
EntryIcon,
|
|
@@ -22,7 +21,7 @@ import {
|
|
|
22
21
|
VisibilityIcon,
|
|
23
22
|
XIcon,
|
|
24
23
|
XIcon2
|
|
25
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-7S2RKUAM.js";
|
|
26
25
|
import "../chunk-2KG3PWR4.js";
|
|
27
26
|
|
|
28
27
|
// src/edit/layers/panel.ts
|
|
@@ -1488,9 +1487,9 @@ function LayersPanelView({ controller }) {
|
|
|
1488
1487
|
const getSnapshot = useCallback(() => controller.getRevision(), [controller]);
|
|
1489
1488
|
useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
1490
1489
|
const view = layersViewState(controller);
|
|
1491
|
-
const
|
|
1490
|
+
const ui8 = (intent) => applyLayersUi(controller, intent);
|
|
1492
1491
|
return /* @__PURE__ */ jsxs(Column, { className: "xeno-layers-panel", children: [
|
|
1493
|
-
view.searchShown ? /* @__PURE__ */ jsx2(Toolbar, { children: /* @__PURE__ */ jsx2(SearchField, { value: view.filter, onChange: (v) =>
|
|
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,
|
|
1494
1493
|
/* @__PURE__ */ jsxs(LayersScroller, { controller, children: [
|
|
1495
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)) }) }),
|
|
1496
1495
|
view.empty ? /* @__PURE__ */ jsx2(EmptyState, { title: "No layers" }) : null
|
|
@@ -1603,7 +1602,7 @@ function LayersThumbnail({ thumbnailKey, size, controller }) {
|
|
|
1603
1602
|
return /* @__PURE__ */ jsx2(Thumbnail, { size, data: controller.getThumbnail(thumbnailKey) });
|
|
1604
1603
|
}
|
|
1605
1604
|
function LayerRow({ row: row2, thumbnailSize, controller }) {
|
|
1606
|
-
const
|
|
1605
|
+
const ui8 = (intent) => applyLayersUi(controller, intent);
|
|
1607
1606
|
return /* @__PURE__ */ jsx2(
|
|
1608
1607
|
Row,
|
|
1609
1608
|
{
|
|
@@ -1618,11 +1617,11 @@ function LayerRow({ row: row2, thumbnailSize, controller }) {
|
|
|
1618
1617
|
title: row2.title,
|
|
1619
1618
|
icon: row2.hasThumbnail ? /* @__PURE__ */ jsx2(LayersThumbnail, { thumbnailKey: row2.thumbnailKey, size: thumbnailSize, controller }) : /* @__PURE__ */ jsx2(KindGlyph, {}),
|
|
1620
1619
|
leading: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1621
|
-
row2.showVisibility ? /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(VisibilityIcon, { open: row2.visible }), label: row2.visibilityLabel, active: row2.visible, onClick: () =>
|
|
1622
|
-
row2.showLock ? /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(LockStateIcon, { locked: row2.locked }), label: row2.lockLabel, active: row2.locked, onClick: () =>
|
|
1623
|
-
row2.showSolo ? /* @__PURE__ */ jsx2(ChipToggle, { glyph: "S", label: "Solo", on: row2.solo, onChange: () =>
|
|
1624
|
-
row2.showMute ? /* @__PURE__ */ jsx2(ChipToggle, { glyph: "M", label: "Mute", on: row2.muted, onChange: () =>
|
|
1625
|
-
row2.showArm ? /* @__PURE__ */ jsx2(ChipToggle, { glyph: "R", label: "Arm", on: row2.armed, onChange: () =>
|
|
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,
|
|
1626
1625
|
row2.showColor ? /* @__PURE__ */ jsx2(ColorTag, { color: row2.colorLabel }) : null
|
|
1627
1626
|
] }),
|
|
1628
1627
|
label: row2.renaming ? /* @__PURE__ */ jsx2(LayersRenameField, { id: row2.id, controller }) : row2.name,
|
|
@@ -1630,9 +1629,9 @@ function LayerRow({ row: row2, thumbnailSize, controller }) {
|
|
|
1630
1629
|
row2.adornments.map((a) => /* @__PURE__ */ jsx2(Badge, { size: "sm", title: a.title, children: a.text }, a.key)),
|
|
1631
1630
|
row2.showOpacity ? /* @__PURE__ */ jsx2(Text, { role: "number", children: row2.opacity }) : null
|
|
1632
1631
|
] }),
|
|
1633
|
-
onExpandedChange: () =>
|
|
1634
|
-
onDoubleClick: () =>
|
|
1635
|
-
onContextMenuAt: (x, y) =>
|
|
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 })
|
|
1636
1635
|
}
|
|
1637
1636
|
);
|
|
1638
1637
|
}
|
|
@@ -2024,8 +2023,8 @@ function constraintsOf(field) {
|
|
|
2024
2023
|
scale: field.scale
|
|
2025
2024
|
};
|
|
2026
2025
|
}
|
|
2027
|
-
function parseNumeric(
|
|
2028
|
-
const trimmed = String(
|
|
2026
|
+
function parseNumeric(text8) {
|
|
2027
|
+
const trimmed = String(text8).trim();
|
|
2029
2028
|
if (trimmed.length === 0) return { ok: false, reason: "empty" };
|
|
2030
2029
|
const match = /^[+-]?(\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/.exec(trimmed);
|
|
2031
2030
|
if (!match) return { ok: false, reason: "nan" };
|
|
@@ -2050,8 +2049,8 @@ function normalizeNumeric(value, c) {
|
|
|
2050
2049
|
function formatNumeric(value, field) {
|
|
2051
2050
|
if (!Number.isFinite(value)) return "";
|
|
2052
2051
|
const precision = field.precision;
|
|
2053
|
-
const
|
|
2054
|
-
return field.unit ? `${
|
|
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;
|
|
2055
2054
|
}
|
|
2056
2055
|
function usesLogScale(c) {
|
|
2057
2056
|
return c.scale === "log" && typeof c.min === "number" && typeof c.max === "number" && c.min > 0 && c.max > c.min;
|
|
@@ -2385,44 +2384,44 @@ var InspectorPanelController = class {
|
|
|
2385
2384
|
if (!field || !isFieldEditable(field)) return;
|
|
2386
2385
|
const mixed = isFieldMixed(field);
|
|
2387
2386
|
const value = this.getFieldValue(fieldId);
|
|
2388
|
-
const
|
|
2389
|
-
this.drafts.set(fieldId, { text:
|
|
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 });
|
|
2390
2389
|
this.focusedFieldId = fieldId;
|
|
2391
2390
|
this.emitFieldFocus(fieldId);
|
|
2392
2391
|
this.notify();
|
|
2393
2392
|
}
|
|
2394
2393
|
/** Update the draft text (typing). Emits nothing under the `blur` policy. */
|
|
2395
|
-
setDraft(fieldId,
|
|
2394
|
+
setDraft(fieldId, text8) {
|
|
2396
2395
|
const draft = this.drafts.get(fieldId);
|
|
2397
2396
|
if (!draft) {
|
|
2398
|
-
this.drafts.set(fieldId, { text:
|
|
2397
|
+
this.drafts.set(fieldId, { text: text8, original: this.getFieldValue(fieldId) });
|
|
2399
2398
|
} else {
|
|
2400
|
-
draft.text =
|
|
2399
|
+
draft.text = text8;
|
|
2401
2400
|
}
|
|
2402
2401
|
const field = this.getField(fieldId);
|
|
2403
2402
|
if (field && commitPolicyOf(field) === "live") {
|
|
2404
|
-
const parsed = this.parseDraft(fieldId,
|
|
2403
|
+
const parsed = this.parseDraft(fieldId, text8);
|
|
2405
2404
|
if (parsed.ok) this.emitSet(fieldId, parsed.value);
|
|
2406
2405
|
}
|
|
2407
2406
|
this.notify();
|
|
2408
2407
|
}
|
|
2409
2408
|
/** Parse a draft string into a field-appropriate value. */
|
|
2410
|
-
parseDraft(fieldId,
|
|
2409
|
+
parseDraft(fieldId, text8) {
|
|
2411
2410
|
const field = this.getField(fieldId);
|
|
2412
2411
|
if (!field) return { ok: false };
|
|
2413
2412
|
if (field.type === "number") {
|
|
2414
|
-
const parsed = parseNumeric(
|
|
2413
|
+
const parsed = parseNumeric(text8);
|
|
2415
2414
|
if (!parsed.ok) return { ok: false };
|
|
2416
2415
|
return { ok: true, value: normalizeNumeric(parsed.value, constraintsOf(field)) };
|
|
2417
2416
|
}
|
|
2418
2417
|
if (field.type === "json") {
|
|
2419
2418
|
try {
|
|
2420
|
-
return { ok: true, value: JSON.parse(
|
|
2419
|
+
return { ok: true, value: JSON.parse(text8) };
|
|
2421
2420
|
} catch {
|
|
2422
2421
|
return { ok: false };
|
|
2423
2422
|
}
|
|
2424
2423
|
}
|
|
2425
|
-
return { ok: true, value:
|
|
2424
|
+
return { ok: true, value: text8 };
|
|
2426
2425
|
}
|
|
2427
2426
|
/**
|
|
2428
2427
|
* Commit the draft (Enter / blur). Invalid input reverts instead of committing garbage.
|
|
@@ -3348,7 +3347,7 @@ function NumberWidget({ field, controller, component }) {
|
|
|
3348
3347
|
},
|
|
3349
3348
|
[controller, editable, field.id, component]
|
|
3350
3349
|
);
|
|
3351
|
-
const
|
|
3350
|
+
const text8 = component !== void 0 ? (() => {
|
|
3352
3351
|
const raw = controller.getFieldValue(field.id);
|
|
3353
3352
|
const v = Array.isArray(raw) ? raw[component] : void 0;
|
|
3354
3353
|
return typeof v === "number" ? formatNumeric(v, field) : "";
|
|
@@ -3360,7 +3359,7 @@ function NumberWidget({ field, controller, component }) {
|
|
|
3360
3359
|
Input2,
|
|
3361
3360
|
{
|
|
3362
3361
|
inputMode: "decimal",
|
|
3363
|
-
value:
|
|
3362
|
+
value: text8,
|
|
3364
3363
|
placeholder: mixed ? controller.getMixedPlaceholder() : field.placeholder,
|
|
3365
3364
|
mixed,
|
|
3366
3365
|
readOnly: !editable,
|
|
@@ -3578,7 +3577,7 @@ function ActionGlyph({ glyph }) {
|
|
|
3578
3577
|
return /* @__PURE__ */ jsx4("span", { "aria-hidden": true, children: glyph });
|
|
3579
3578
|
}
|
|
3580
3579
|
function SectionView({ section, controller }) {
|
|
3581
|
-
const
|
|
3580
|
+
const ui8 = (intent) => applyInspectorUi(controller, intent);
|
|
3582
3581
|
const hasActions = section.actions.length > 0 || section.hasAddMenu;
|
|
3583
3582
|
return /* @__PURE__ */ jsxs3(
|
|
3584
3583
|
Section,
|
|
@@ -3587,13 +3586,13 @@ function SectionView({ section, controller }) {
|
|
|
3587
3586
|
flush: true,
|
|
3588
3587
|
collapsible: section.collapsible,
|
|
3589
3588
|
collapsed: section.collapsed,
|
|
3590
|
-
onCollapsedChange: () =>
|
|
3589
|
+
onCollapsedChange: () => ui8({ kind: "toggleSectionCollapsed", sectionId: section.id }),
|
|
3591
3590
|
enabled: section.enabled,
|
|
3592
|
-
onEnabledChange: () =>
|
|
3591
|
+
onEnabledChange: () => ui8({ kind: "toggleSectionEnabled", sectionId: section.id }),
|
|
3593
3592
|
badge: section.badge ? /* @__PURE__ */ jsx4(Badge2, { children: section.badge }) : null,
|
|
3594
3593
|
actions: hasActions ? /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3595
|
-
section.actions.map((action) => /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(ActionGlyph, { glyph: action.glyph }), label: action.label, disabled: action.disabled, onClick: () =>
|
|
3596
|
-
section.hasAddMenu ? /* @__PURE__ */ jsx4(Menu, { size: "sm", trigger: "\uFF0B", items: section.addItems, label: section.addLabel, align: "end", onSelect: (id) =>
|
|
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
|
|
3597
3596
|
] }) : null,
|
|
3598
3597
|
children: [
|
|
3599
3598
|
section.showEmptyHint ? /* @__PURE__ */ jsx4(Stack2, { pad: "inset", children: /* @__PURE__ */ jsx4(Text3, { role: "caption", children: section.emptyHint }) }) : null,
|
|
@@ -3603,7 +3602,7 @@ function SectionView({ section, controller }) {
|
|
|
3603
3602
|
);
|
|
3604
3603
|
}
|
|
3605
3604
|
function FieldRow({ row: row2, controller }) {
|
|
3606
|
-
const
|
|
3605
|
+
const ui8 = (intent) => applyInspectorUi(controller, intent);
|
|
3607
3606
|
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3608
3607
|
/* @__PURE__ */ jsxs3(
|
|
3609
3608
|
Field,
|
|
@@ -3611,19 +3610,19 @@ function FieldRow({ row: row2, controller }) {
|
|
|
3611
3610
|
label: row2.label,
|
|
3612
3611
|
title: row2.title,
|
|
3613
3612
|
focused: row2.focused,
|
|
3614
|
-
onLabelClick: () =>
|
|
3615
|
-
onContextMenu: (x, y) =>
|
|
3613
|
+
onLabelClick: () => ui8({ kind: "focusField", fieldId: row2.id }),
|
|
3614
|
+
onContextMenu: (x, y) => ui8({ kind: "contextMenu", fieldId: row2.id, x, y }),
|
|
3616
3615
|
leading: row2.showKeyframes ? /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3617
|
-
/* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(StopwatchIcon, {}), label: "Toggle animation", active: row2.animated, onClick: () =>
|
|
3618
|
-
row2.animated ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(PrevIcon, {}), label: "Previous keyframe", disabled: row2.prevDisabled, onClick: () =>
|
|
3619
|
-
row2.animated ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(DiamondIcon, { filled: row2.onKeyframe }), label: row2.keyframeLabel, onClick: () =>
|
|
3620
|
-
row2.animated ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(NextIcon, {}), label: "Next keyframe", disabled: row2.nextDisabled, onClick: () =>
|
|
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
|
|
3621
3620
|
] }) : null,
|
|
3622
3621
|
trailing: /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3623
|
-
row2.showEasing ? /* @__PURE__ */ jsx4(Select2, { size: "sm", options: row2.easingOptions, value: row2.easing, label: "Easing", onChange: (v) =>
|
|
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,
|
|
3624
3623
|
row2.showKeyframes ? /* @__PURE__ */ jsx4(Badge2, { size: "sm", children: row2.keyframeChip }) : null,
|
|
3625
|
-
row2.showToken ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(LinkIcon, {}), label: row2.tokenActionLabel, active: row2.bound, onClick: () =>
|
|
3626
|
-
row2.showReset ? /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(ResetIcon, {}), label: "Reset to default", onClick: () =>
|
|
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
|
|
3627
3626
|
] }),
|
|
3628
3627
|
children: [
|
|
3629
3628
|
row2.bound ? /* @__PURE__ */ jsx4(Badge2, { title: row2.tokenTitle, children: row2.tokenLabel }) : null,
|
|
@@ -4876,23 +4875,23 @@ function HistoryPanelView({ controller }) {
|
|
|
4876
4875
|
const getSnapshot = useCallback4(() => controller.getRevision(), [controller]);
|
|
4877
4876
|
useSyncExternalStore3(subscribe, getSnapshot, getSnapshot);
|
|
4878
4877
|
const view = historyViewState(controller);
|
|
4879
|
-
const
|
|
4878
|
+
const ui8 = (intent) => applyHistoryUi(controller, intent);
|
|
4880
4879
|
return /* @__PURE__ */ jsxs4(Column3, { className: "xeno-history-panel", children: [
|
|
4881
4880
|
/* @__PURE__ */ jsx5(
|
|
4882
4881
|
Toolbar2,
|
|
4883
4882
|
{
|
|
4884
4883
|
left: /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
4885
|
-
/* @__PURE__ */ jsx5(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx5(UndoIcon, {}), label: "Undo", disabled: !view.canUndo, onClick: () =>
|
|
4886
|
-
/* @__PURE__ */ jsx5(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx5(RedoIcon, {}), label: "Redo", disabled: !view.canRedo, onClick: () =>
|
|
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" }) })
|
|
4887
4886
|
] }),
|
|
4888
4887
|
right: /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
4889
4888
|
/* @__PURE__ */ jsx5(Text4, { role: "number", children: view.counter }),
|
|
4890
|
-
view.clearAllowed ? /* @__PURE__ */ jsx5(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx5(TrashIcon, {}), label: "Clear history", onClick: () =>
|
|
4889
|
+
view.clearAllowed ? /* @__PURE__ */ jsx5(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx5(TrashIcon, {}), label: "Clear history", onClick: () => ui8({ kind: "requestClear" }) }) : null
|
|
4891
4890
|
] }),
|
|
4892
|
-
children: view.searchShown ? /* @__PURE__ */ jsx5(SearchField3, { value: view.filter, onChange: (v) =>
|
|
4891
|
+
children: view.searchShown ? /* @__PURE__ */ jsx5(SearchField3, { value: view.filter, onChange: (v) => ui8({ kind: "filter", value: v }), placeholder: "Search history", label: "Search history" }) : null
|
|
4893
4892
|
}
|
|
4894
4893
|
),
|
|
4895
|
-
view.confirmingClear ? /* @__PURE__ */ jsx5(InlineConfirm, { message: "Clear all history?", label: "Confirm clear history", confirmLabel: "Clear", onConfirm: () =>
|
|
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,
|
|
4896
4895
|
view.pruned ? /* @__PURE__ */ jsx5(Text4, { role: "caption", children: "Earlier history discarded (limit reached)" }) : null,
|
|
4897
4896
|
/* @__PURE__ */ jsxs4(HistoryScroller, { controller, children: [
|
|
4898
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)) }) }),
|
|
@@ -4951,7 +4950,7 @@ function HistoryCancelButton({ entryId, controller }) {
|
|
|
4951
4950
|
);
|
|
4952
4951
|
}
|
|
4953
4952
|
function HistoryRowView({ row: row2, controller }) {
|
|
4954
|
-
const
|
|
4953
|
+
const ui8 = (intent) => applyHistoryUi(controller, intent);
|
|
4955
4954
|
return /* @__PURE__ */ jsx5(
|
|
4956
4955
|
Row2,
|
|
4957
4956
|
{
|
|
@@ -4974,9 +4973,9 @@ function HistoryRowView({ row: row2, controller }) {
|
|
|
4974
4973
|
row2.showTime ? /* @__PURE__ */ jsx5(Text4, { role: "meta", children: row2.time }) : null,
|
|
4975
4974
|
row2.pending ? /* @__PURE__ */ jsx5(HistoryCancelButton, { entryId: row2.cancelId, controller }) : null
|
|
4976
4975
|
] }),
|
|
4977
|
-
onClick: () =>
|
|
4978
|
-
onMouseEnter: () =>
|
|
4979
|
-
onContextMenuAt: (x, y) =>
|
|
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 })
|
|
4980
4979
|
}
|
|
4981
4980
|
);
|
|
4982
4981
|
}
|
|
@@ -6262,27 +6261,27 @@ function ColorPanelView({ controller }) {
|
|
|
6262
6261
|
const getSnapshot = useCallback5(() => controller.getRevision(), [controller]);
|
|
6263
6262
|
useSyncExternalStore4(subscribe, getSnapshot, getSnapshot);
|
|
6264
6263
|
const view = colorViewState(controller);
|
|
6265
|
-
const
|
|
6264
|
+
const ui8 = (intent) => applyColorUi(controller, intent);
|
|
6266
6265
|
return /* @__PURE__ */ jsx6(Column4, { className: "xeno-color-panel", children: /* @__PURE__ */ jsxs5(Stack3, { gap: 8, children: [
|
|
6267
6266
|
view.fgBg ? /* @__PURE__ */ jsxs5(Stack3, { direction: "row", pad: "none", children: [
|
|
6268
|
-
/* @__PURE__ */ jsx6(ColorChip, { color: view.hex, label: "Foreground", pressed: view.fgActive, onClick: () =>
|
|
6269
|
-
/* @__PURE__ */ jsx6(IconButton5, { size: "sm", icon: /* @__PURE__ */ jsx6(SwapIcon, {}), label: "Swap FG/BG (X)", onClick: () =>
|
|
6270
|
-
/* @__PURE__ */ jsx6(ColorChip, { color: null, label: "Background", pressed: view.bgActive, onClick: () =>
|
|
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" }) })
|
|
6271
6270
|
] }) : null,
|
|
6272
6271
|
/* @__PURE__ */ jsx6(ColorPicker, { controller }),
|
|
6273
6272
|
/* @__PURE__ */ jsxs5(Stack3, { direction: "row", pad: "none", gap: 4, children: [
|
|
6274
|
-
/* @__PURE__ */ jsx6(Select3, { size: "sm", label: "Color model", value: view.space, options: view.spaceOptions, onChange: (v) =>
|
|
6275
|
-
view.isHex ? /* @__PURE__ */ jsx6(Input3, { variant: "mono", label: "Hex", value: view.hex, onChange: (v) =>
|
|
6276
|
-
view.components.map((comp) => /* @__PURE__ */ jsx6(NumberInput, { caption: comp.label, value: comp.value, onChange: (n) =>
|
|
6277
|
-
view.alphaShown ? /* @__PURE__ */ jsx6(NumberInput, { caption: "A", label: "Alpha", min: 0, max: 100, value: view.alphaPercent, onChange: (n) =>
|
|
6278
|
-
/* @__PURE__ */ jsx6(IconButton5, { size: "sm", icon: /* @__PURE__ */ jsx6(EyedropperIcon, {}), label: "Pick from screen", onClick: () =>
|
|
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" }) })
|
|
6279
6278
|
] }),
|
|
6280
6279
|
view.hasTokens ? /* @__PURE__ */ jsx6(Field2, { label: "Token", htmlFor: "xeno-color-token", children: /* @__PURE__ */ jsxs5(Stack3, { direction: "row", pad: "none", gap: 4, children: [
|
|
6281
|
-
/* @__PURE__ */ jsx6(Select3, { size: "sm", label: "Bind token", value: view.boundTokenId, placeholder: "\u2014 raw \u2014", options: view.tokenOptions, onChange: (id) =>
|
|
6282
|
-
view.bound ? /* @__PURE__ */ jsx6(TextButton2, { onClick: () =>
|
|
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
|
|
6283
6282
|
] }) }) : null,
|
|
6284
|
-
/* @__PURE__ */ jsx6(Section2, { title: "Swatches", flush: true, actions: /* @__PURE__ */ jsx6(TextButton2, { onClick: () =>
|
|
6285
|
-
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: () =>
|
|
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
|
|
6286
6285
|
] }) });
|
|
6287
6286
|
}
|
|
6288
6287
|
function ColorPicker({ controller }) {
|
|
@@ -8944,11 +8943,11 @@ var FindController = class {
|
|
|
8944
8943
|
* @param text - The new query text.
|
|
8945
8944
|
* @param immediate - Skip the debounce (a paste, or pressing Enter).
|
|
8946
8945
|
*/
|
|
8947
|
-
setText(
|
|
8948
|
-
if (
|
|
8949
|
-
this.text =
|
|
8946
|
+
setText(text8, immediate = false) {
|
|
8947
|
+
if (text8 === this.text) return;
|
|
8948
|
+
this.text = text8;
|
|
8950
8949
|
this.index = -1;
|
|
8951
|
-
if (
|
|
8950
|
+
if (text8 === "") {
|
|
8952
8951
|
this.clearResults("idle");
|
|
8953
8952
|
this.emitQuery(true);
|
|
8954
8953
|
return;
|
|
@@ -8976,8 +8975,8 @@ var FindController = class {
|
|
|
8976
8975
|
this.notify();
|
|
8977
8976
|
}
|
|
8978
8977
|
/** The replacement text. Never emitted on its own — a replacement is not a search. */
|
|
8979
|
-
setReplaceText(
|
|
8980
|
-
this.replaceText =
|
|
8978
|
+
setReplaceText(text8) {
|
|
8979
|
+
this.replaceText = text8;
|
|
8981
8980
|
this.notify();
|
|
8982
8981
|
}
|
|
8983
8982
|
/** Show or hide the replace row. */
|
|
@@ -9626,7 +9625,7 @@ function findRuntimeComponents(controller) {
|
|
|
9626
9625
|
function FindPanelView({ controller, showResults, placeholder }) {
|
|
9627
9626
|
useSyncExternalStore7(controller.subscribe, controller.getState, controller.getState);
|
|
9628
9627
|
const view = findViewState(controller, { showResults, placeholder });
|
|
9629
|
-
const
|
|
9628
|
+
const ui8 = (intent) => applyFindUi(controller, intent);
|
|
9630
9629
|
const renderRow = (row2) => /* @__PURE__ */ jsx9(
|
|
9631
9630
|
Row3,
|
|
9632
9631
|
{
|
|
@@ -9634,8 +9633,8 @@ function FindPanelView({ controller, showResults, placeholder }) {
|
|
|
9634
9633
|
selected: row2.current,
|
|
9635
9634
|
meta: row2.location,
|
|
9636
9635
|
label: /* @__PURE__ */ jsx9(Highlight, { segments: row2.segments }),
|
|
9637
|
-
onClick: () =>
|
|
9638
|
-
onContextMenuAt: (x, y) =>
|
|
9636
|
+
onClick: () => ui8({ kind: "select", matchId: row2.id }),
|
|
9637
|
+
onContextMenuAt: (x, y) => ui8({ kind: "contextMenu", matchId: row2.id, x, y })
|
|
9639
9638
|
},
|
|
9640
9639
|
row2.id
|
|
9641
9640
|
);
|
|
@@ -9643,11 +9642,11 @@ function FindPanelView({ controller, showResults, placeholder }) {
|
|
|
9643
9642
|
/* @__PURE__ */ jsx9(
|
|
9644
9643
|
Toolbar4,
|
|
9645
9644
|
{
|
|
9646
|
-
left: /* @__PURE__ */ jsx9(SearchField4, { value: view.text, placeholder: view.placeholder, onChange: (value) =>
|
|
9645
|
+
left: /* @__PURE__ */ jsx9(SearchField4, { value: view.text, placeholder: view.placeholder, onChange: (value) => ui8({ kind: "text", value }) }),
|
|
9647
9646
|
right: /* @__PURE__ */ jsxs8(ToolbarGroup2, { end: true, children: [
|
|
9648
|
-
/* @__PURE__ */ jsx9(IconButton6, { label: "Match case", active: view.caseSensitive, icon: /* @__PURE__ */ jsx9(CaseIcon, { size: 12 }), onClick: () =>
|
|
9649
|
-
/* @__PURE__ */ jsx9(IconButton6, { label: "Whole word", active: view.wholeWord, icon: /* @__PURE__ */ jsx9(WordIcon, { size: 12 }), onClick: () =>
|
|
9650
|
-
/* @__PURE__ */ jsx9(IconButton6, { label: "Regular expression", active: view.regex, icon: /* @__PURE__ */ jsx9(RegexIcon, { size: 12 }), onClick: () =>
|
|
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" }) })
|
|
9651
9650
|
] })
|
|
9652
9651
|
}
|
|
9653
9652
|
),
|
|
@@ -9662,9 +9661,9 @@ function FindPanelView({ controller, showResults, placeholder }) {
|
|
|
9662
9661
|
view.countShown ? /* @__PURE__ */ jsx9(Text5, { role: "number", children: view.counter }) : null
|
|
9663
9662
|
] }),
|
|
9664
9663
|
right: /* @__PURE__ */ jsxs8(ToolbarGroup2, { end: true, children: [
|
|
9665
|
-
/* @__PURE__ */ jsx9(IconButton6, { label: "Previous match", disabled: !view.hasMatches, icon: /* @__PURE__ */ jsx9(Chevron, { direction: "up", size: 12 }), onClick: () =>
|
|
9666
|
-
/* @__PURE__ */ jsx9(IconButton6, { label: "Next match", disabled: !view.hasMatches, icon: /* @__PURE__ */ jsx9(Chevron, { direction: "down", size: 12 }), onClick: () =>
|
|
9667
|
-
/* @__PURE__ */ jsx9(TextButton3, { onClick: () =>
|
|
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 })
|
|
9668
9667
|
] })
|
|
9669
9668
|
}
|
|
9670
9669
|
),
|
|
@@ -9672,10 +9671,10 @@ function FindPanelView({ controller, showResults, placeholder }) {
|
|
|
9672
9671
|
view.replaceVisible ? /* @__PURE__ */ jsx9(
|
|
9673
9672
|
Toolbar4,
|
|
9674
9673
|
{
|
|
9675
|
-
left: /* @__PURE__ */ jsx9(SearchField4, { value: view.replaceText, placeholder: "Replace with", onChange: (value) =>
|
|
9674
|
+
left: /* @__PURE__ */ jsx9(SearchField4, { value: view.replaceText, placeholder: "Replace with", onChange: (value) => ui8({ kind: "replaceText", value }) }),
|
|
9676
9675
|
right: /* @__PURE__ */ jsxs8(ToolbarGroup2, { end: true, children: [
|
|
9677
|
-
/* @__PURE__ */ jsx9(TextButton3, { disabled: !view.canReplace, onClick: () =>
|
|
9678
|
-
/* @__PURE__ */ jsx9(TextButton3, { disabled: !view.canReplace, onClick: () =>
|
|
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 })
|
|
9679
9678
|
] })
|
|
9680
9679
|
}
|
|
9681
9680
|
) : null,
|
|
@@ -10333,279 +10332,290 @@ var commentsManifest = {
|
|
|
10333
10332
|
import { useSyncExternalStore as useSyncExternalStore8 } from "react";
|
|
10334
10333
|
import {
|
|
10335
10334
|
Badge as Badge6,
|
|
10335
|
+
Column as Column6,
|
|
10336
10336
|
EmptyState as EmptyState6,
|
|
10337
|
+
Input as Input4,
|
|
10338
|
+
Message,
|
|
10339
|
+
Note,
|
|
10340
|
+
Quote,
|
|
10337
10341
|
ScrollArea as ScrollArea5,
|
|
10338
10342
|
Section as Section4,
|
|
10339
10343
|
SegmentedControl as SegmentedControl2,
|
|
10344
|
+
Stack as Stack4,
|
|
10340
10345
|
StatusBar as StatusBar6,
|
|
10346
|
+
Text as Text6,
|
|
10347
|
+
TextArea as TextArea2,
|
|
10341
10348
|
TextButton as TextButton4,
|
|
10349
|
+
ThreadCard,
|
|
10342
10350
|
Toolbar as Toolbar5,
|
|
10343
10351
|
ToolbarGroup as ToolbarGroup3
|
|
10344
10352
|
} from "@xenosystem/components/chrome";
|
|
10345
|
-
|
|
10353
|
+
|
|
10354
|
+
// src/edit/comments/declaration.ts
|
|
10346
10355
|
var ANCHOR_BADGE = {
|
|
10347
10356
|
live: null,
|
|
10348
|
-
stale: {
|
|
10349
|
-
|
|
10350
|
-
|
|
10351
|
-
|
|
10352
|
-
|
|
10353
|
-
|
|
10354
|
-
|
|
10355
|
-
|
|
10356
|
-
|
|
10357
|
+
stale: { label: "edited", tone: "warning", title: "The content this comment is about has changed since it was written." },
|
|
10358
|
+
orphaned: { label: "content deleted", tone: "error", title: "The content this comment was about no longer exists. The comment is kept." }
|
|
10359
|
+
};
|
|
10360
|
+
function commentsViewState(c, options = {}) {
|
|
10361
|
+
const s = c.getState();
|
|
10362
|
+
const now = c.clock();
|
|
10363
|
+
const showResolved = options.showResolved ?? true;
|
|
10364
|
+
const allowReactions = options.allowReactions ?? false;
|
|
10365
|
+
const me = s.currentUser?.id ?? "";
|
|
10366
|
+
const thread = (v) => {
|
|
10367
|
+
const t = v.thread;
|
|
10368
|
+
const badge = ANCHOR_BADGE[v.anchorState];
|
|
10369
|
+
const replying = s.replyingTo === t.id;
|
|
10370
|
+
return {
|
|
10371
|
+
id: t.id,
|
|
10372
|
+
active: v.active,
|
|
10373
|
+
resolved: t.resolved === true,
|
|
10374
|
+
hasAnchorBadge: badge !== null,
|
|
10375
|
+
anchorLabel: badge?.label,
|
|
10376
|
+
anchorTone: badge?.tone ?? "neutral",
|
|
10377
|
+
anchorTitle: badge?.title,
|
|
10378
|
+
age: formatAge(t.createdAt, now),
|
|
10379
|
+
hasQuote: !!t.anchorLabel,
|
|
10380
|
+
quote: t.anchorLabel,
|
|
10381
|
+
orphaned: v.anchorState === "orphaned",
|
|
10382
|
+
messages: v.messages.map((m) => ({ id: m.id, author: m.authorName ?? m.authorId, age: formatAge(m.createdAt, now), edited: !!m.editedAt, body: m.body })),
|
|
10383
|
+
hasReactions: allowReactions && !!t.reactions?.length,
|
|
10384
|
+
reactions: allowReactions ? (t.reactions ?? []).map((r) => ({ threadId: t.id, emoji: r.emoji, label: `${r.emoji} ${r.userIds.length}`, mine: r.userIds.includes(me), reactTo: !r.userIds.includes(me) })) : [],
|
|
10385
|
+
replying,
|
|
10386
|
+
replyDraft: replying ? s.replyDraft : "",
|
|
10387
|
+
idle: !replying,
|
|
10388
|
+
resolveLabel: t.resolved ? "Reopen" : "Resolve",
|
|
10389
|
+
resolveTo: !t.resolved
|
|
10390
|
+
};
|
|
10391
|
+
};
|
|
10392
|
+
const open = s.threads.filter((v) => !v.thread.resolved).map(thread);
|
|
10393
|
+
const resolved = s.threads.filter((v) => v.thread.resolved).map(thread);
|
|
10394
|
+
const o = s.totals.orphaned;
|
|
10395
|
+
return {
|
|
10396
|
+
show: s.filter.show ?? "open",
|
|
10397
|
+
shows: [{ value: "open", label: "Open" }, { value: "resolved", label: "Resolved" }, { value: "all", label: "All" }],
|
|
10398
|
+
sort: s.sort,
|
|
10399
|
+
sorts: [{ value: "document", label: "Doc" }, { value: "newest", label: "New" }, { value: "oldest", label: "Old" }],
|
|
10400
|
+
orphanedNotice: o > 0 ? `${o} comment${o === 1 ? "" : "s"} lost the content${o === 1 ? " it was" : " they were"} about.` : void 0,
|
|
10401
|
+
orphanedHidden: o > 0 && s.filter.includeOrphaned === false,
|
|
10402
|
+
filteredEmpty: s.threads.length === 0 && s.filteredEmpty,
|
|
10403
|
+
filteredHint: `${s.totals.all} comment${s.totals.all === 1 ? "" : "s"} on this document.`,
|
|
10404
|
+
empty: s.threads.length === 0 && !s.filteredEmpty,
|
|
10405
|
+
emptyHint: options.emptyHint ?? "Select something and add a comment.",
|
|
10406
|
+
listed: s.threads.length > 0,
|
|
10407
|
+
open,
|
|
10408
|
+
hasResolved: showResolved && resolved.length > 0,
|
|
10409
|
+
resolvedTitle: `Resolved (${resolved.length})`,
|
|
10410
|
+
resolved: showResolved ? resolved : [],
|
|
10411
|
+
draft: s.draft,
|
|
10412
|
+
placeholder: s.activeAnchor === null ? "Select something in the document to comment on it" : "Add a comment\u2026",
|
|
10413
|
+
composerDisabled: s.activeAnchor === null,
|
|
10414
|
+
commentDisabled: s.activeAnchor === null || s.draft.trim() === "",
|
|
10415
|
+
countLabel: `${s.totals.open} open`,
|
|
10416
|
+
staleLabel: s.totals.stale > 0 ? `${s.totals.stale} edited` : void 0
|
|
10417
|
+
};
|
|
10418
|
+
}
|
|
10419
|
+
function applyCommentsUi(c, intent) {
|
|
10420
|
+
switch (intent.kind) {
|
|
10421
|
+
case "show":
|
|
10422
|
+
c.setFilter({ show: intent.show });
|
|
10423
|
+
break;
|
|
10424
|
+
case "sort":
|
|
10425
|
+
c.setSort(intent.sort);
|
|
10426
|
+
break;
|
|
10427
|
+
case "showOrphaned":
|
|
10428
|
+
c.setFilter({ includeOrphaned: true });
|
|
10429
|
+
break;
|
|
10430
|
+
case "activate":
|
|
10431
|
+
c.activate(intent.id);
|
|
10432
|
+
break;
|
|
10433
|
+
case "contextMenu":
|
|
10434
|
+
c.requestContextMenu(intent.id, intent.x, intent.y);
|
|
10435
|
+
break;
|
|
10436
|
+
case "react":
|
|
10437
|
+
c.react(intent.id, intent.emoji, intent.on);
|
|
10438
|
+
break;
|
|
10439
|
+
case "reply":
|
|
10440
|
+
c.reply(intent.id);
|
|
10441
|
+
break;
|
|
10442
|
+
case "replyDraft":
|
|
10443
|
+
c.setReplyDraft(intent.value);
|
|
10444
|
+
break;
|
|
10445
|
+
case "replyKey":
|
|
10446
|
+
if (intent.key === "Enter" && !intent.shift) c.reply(intent.id);
|
|
10447
|
+
else if (intent.key === "Escape") c.setReplyingTo(null);
|
|
10448
|
+
break;
|
|
10449
|
+
case "startReply":
|
|
10450
|
+
c.setReplyingTo(intent.id);
|
|
10451
|
+
break;
|
|
10452
|
+
case "resolve":
|
|
10453
|
+
c.resolve(intent.id, intent.resolved);
|
|
10454
|
+
break;
|
|
10455
|
+
case "remove":
|
|
10456
|
+
c.remove(intent.id);
|
|
10457
|
+
break;
|
|
10458
|
+
case "draft":
|
|
10459
|
+
c.setDraft(intent.value);
|
|
10460
|
+
break;
|
|
10461
|
+
case "draftKey":
|
|
10462
|
+
if (intent.key === "Enter" && (intent.ctrl || intent.meta)) c.create();
|
|
10463
|
+
break;
|
|
10464
|
+
case "create":
|
|
10465
|
+
c.create();
|
|
10466
|
+
break;
|
|
10357
10467
|
}
|
|
10468
|
+
}
|
|
10469
|
+
var commentsViewManifest = {
|
|
10470
|
+
id: commentsManifest.id,
|
|
10471
|
+
version: "1.0.0",
|
|
10472
|
+
title: "Comments",
|
|
10473
|
+
category: "edit",
|
|
10474
|
+
layout: { slot: "side" },
|
|
10475
|
+
inputs: [{ id: "view", type: "object", label: "View state", description: "The CommentsViewModel the runtime derives from the controller on every draw." }],
|
|
10476
|
+
outputs: [{ id: "ui", type: "object", label: "UI intent", description: "{ kind, \u2026 } \u2014 applied by the runtime to the controller." }],
|
|
10477
|
+
commands: []
|
|
10358
10478
|
};
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10363
|
-
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
|
|
10367
|
-
|
|
10368
|
-
|
|
10369
|
-
|
|
10370
|
-
|
|
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
|
|
10482
|
+
};
|
|
10483
|
+
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 } } });
|
|
10486
|
+
var threadCard = (input) => ({
|
|
10487
|
+
component: "chrome/ThreadCard",
|
|
10488
|
+
each: { input, key: "id" },
|
|
10489
|
+
props: { active: { item: "active" }, resolved: { item: "resolved" } },
|
|
10490
|
+
on: { onContextMenuAt: ui6("contextMenu", { id: { item: "id" }, x: { arg: "", index: 0 }, y: { arg: "", index: 1 } }) },
|
|
10491
|
+
children: [
|
|
10492
|
+
{
|
|
10493
|
+
component: "chrome/Stack",
|
|
10494
|
+
props: { direction: { value: "row" }, gap: { value: 4 }, pad: { value: "none" } },
|
|
10495
|
+
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" })] }
|
|
10499
|
+
]
|
|
10500
|
+
},
|
|
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" })] },
|
|
10371
10503
|
{
|
|
10372
|
-
|
|
10373
|
-
|
|
10374
|
-
|
|
10375
|
-
|
|
10376
|
-
|
|
10377
|
-
|
|
10504
|
+
component: "chrome/Stack",
|
|
10505
|
+
when: { item: "hasReactions" },
|
|
10506
|
+
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" })] }]
|
|
10508
|
+
},
|
|
10509
|
+
{
|
|
10510
|
+
component: "chrome/Stack",
|
|
10511
|
+
when: { item: "replying" },
|
|
10512
|
+
props: { direction: { value: "row" }, gap: { value: 4 }, pad: { value: "none" } },
|
|
10513
|
+
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" })] }
|
|
10516
|
+
]
|
|
10517
|
+
},
|
|
10518
|
+
{
|
|
10519
|
+
component: "chrome/Stack",
|
|
10520
|
+
when: { item: "idle" },
|
|
10521
|
+
props: { direction: { value: "row" }, gap: { value: 6 }, pad: { value: "none" } },
|
|
10522
|
+
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" })] }
|
|
10526
|
+
]
|
|
10527
|
+
}
|
|
10528
|
+
]
|
|
10529
|
+
});
|
|
10530
|
+
var COMMENTS_DECLARATION = {
|
|
10531
|
+
format: "xeno.block@1",
|
|
10532
|
+
manifest: commentsViewManifest,
|
|
10533
|
+
behaviour: "edit/commentsPanelView",
|
|
10534
|
+
composition: {
|
|
10535
|
+
component: "chrome/Column",
|
|
10536
|
+
children: [
|
|
10537
|
+
{
|
|
10538
|
+
component: "chrome/Toolbar",
|
|
10539
|
+
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: "" } }) } }] } }
|
|
10542
|
+
}
|
|
10378
10543
|
},
|
|
10379
|
-
|
|
10380
|
-
|
|
10381
|
-
|
|
10544
|
+
{
|
|
10545
|
+
component: "chrome/Note",
|
|
10546
|
+
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" })] }]
|
|
10382
10548
|
},
|
|
10383
|
-
|
|
10384
|
-
|
|
10385
|
-
|
|
10386
|
-
|
|
10387
|
-
|
|
10388
|
-
|
|
10389
|
-
|
|
10390
|
-
|
|
10391
|
-
|
|
10392
|
-
|
|
10393
|
-
|
|
10394
|
-
|
|
10395
|
-
|
|
10396
|
-
|
|
10397
|
-
|
|
10398
|
-
|
|
10399
|
-
|
|
10400
|
-
|
|
10401
|
-
|
|
10402
|
-
|
|
10403
|
-
|
|
10404
|
-
|
|
10405
|
-
|
|
10406
|
-
|
|
10407
|
-
|
|
10408
|
-
|
|
10409
|
-
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10413
|
-
|
|
10414
|
-
|
|
10415
|
-
|
|
10416
|
-
|
|
10417
|
-
|
|
10418
|
-
|
|
10419
|
-
|
|
10420
|
-
|
|
10421
|
-
|
|
10422
|
-
|
|
10423
|
-
|
|
10424
|
-
|
|
10425
|
-
|
|
10426
|
-
|
|
10427
|
-
|
|
10428
|
-
|
|
10429
|
-
|
|
10430
|
-
|
|
10431
|
-
reaction.userIds.length
|
|
10432
|
-
]
|
|
10433
|
-
},
|
|
10434
|
-
reaction.emoji
|
|
10435
|
-
)) }) : null,
|
|
10436
|
-
replying ? /* @__PURE__ */ jsxs9("div", { style: { display: "flex", gap: 4 }, children: [
|
|
10437
|
-
/* @__PURE__ */ jsx10(
|
|
10438
|
-
"input",
|
|
10439
|
-
{
|
|
10440
|
-
value: controller.getState().replyDraft,
|
|
10441
|
-
onChange: (event) => controller.setReplyDraft(event.target.value),
|
|
10442
|
-
onKeyDown: (event) => {
|
|
10443
|
-
if (event.key === "Enter" && !event.shiftKey) {
|
|
10444
|
-
event.preventDefault();
|
|
10445
|
-
controller.reply(thread.id);
|
|
10446
|
-
} else if (event.key === "Escape") {
|
|
10447
|
-
controller.setReplyingTo(null);
|
|
10448
|
-
}
|
|
10449
|
-
},
|
|
10450
|
-
placeholder: "Reply",
|
|
10451
|
-
autoFocus: true,
|
|
10452
|
-
style: {
|
|
10453
|
-
flex: 1,
|
|
10454
|
-
fontSize: 10,
|
|
10455
|
-
background: "var(--xeno-canvas)",
|
|
10456
|
-
border: "1px solid var(--xeno-border)",
|
|
10457
|
-
borderRadius: 2,
|
|
10458
|
-
padding: "2px 4px",
|
|
10459
|
-
color: "inherit",
|
|
10460
|
-
outline: "none"
|
|
10461
|
-
}
|
|
10462
|
-
}
|
|
10463
|
-
),
|
|
10464
|
-
/* @__PURE__ */ jsx10(TextButton4, { onClick: () => controller.reply(thread.id), children: "Send" })
|
|
10465
|
-
] }) : /* @__PURE__ */ jsxs9("div", { style: { display: "flex", gap: 6 }, children: [
|
|
10466
|
-
/* @__PURE__ */ jsx10(TextButton4, { onClick: () => controller.setReplyingTo(thread.id), children: "Reply" }),
|
|
10467
|
-
/* @__PURE__ */ jsx10(TextButton4, { onClick: () => controller.resolve(thread.id, !thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
|
|
10468
|
-
/* @__PURE__ */ jsx10(TextButton4, { onClick: () => controller.remove(thread.id), children: "Delete" })
|
|
10469
|
-
] })
|
|
10470
|
-
] })
|
|
10471
|
-
}
|
|
10472
|
-
);
|
|
10473
|
-
}
|
|
10474
|
-
function CommentsPanelView({
|
|
10475
|
-
controller,
|
|
10476
|
-
showResolved = true,
|
|
10477
|
-
allowReactions = false,
|
|
10478
|
-
emptyHint
|
|
10479
|
-
}) {
|
|
10480
|
-
const state = useSyncExternalStore8(controller.subscribe, controller.getState, controller.getState);
|
|
10481
|
-
const now = controller.clock();
|
|
10482
|
-
const open = state.threads.filter((t) => !t.thread.resolved);
|
|
10483
|
-
const resolved = state.threads.filter((t) => t.thread.resolved);
|
|
10484
|
-
return /* @__PURE__ */ jsxs9("div", { style: { display: "flex", flexDirection: "column", height: "100%", minHeight: 0 }, children: [
|
|
10549
|
+
{
|
|
10550
|
+
component: "chrome/ScrollArea",
|
|
10551
|
+
children: [
|
|
10552
|
+
{ component: "chrome/EmptyState", when: { input: "view.filteredEmpty" }, props: { title: { value: "Nothing matches this filter" }, hint: { input: "view.filteredHint" } } },
|
|
10553
|
+
{ component: "chrome/EmptyState", when: { input: "view.empty" }, props: { title: { value: "No comments" }, hint: { input: "view.emptyHint" } } },
|
|
10554
|
+
threadCard("view.open"),
|
|
10555
|
+
{ component: "chrome/Section", when: { input: "view.hasResolved" }, props: { title: { input: "view.resolvedTitle" }, flush: { value: true } }, children: [threadCard("view.resolved")] }
|
|
10556
|
+
]
|
|
10557
|
+
},
|
|
10558
|
+
{
|
|
10559
|
+
component: "chrome/Stack",
|
|
10560
|
+
props: { gap: { value: 2 }, pad: { value: "gutter" }, className: { value: "xeno-comments-composer" } },
|
|
10561
|
+
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" })] }] } } } }
|
|
10564
|
+
]
|
|
10565
|
+
},
|
|
10566
|
+
{ component: "chrome/StatusBar", props: { left: { input: "view.countLabel" }, right: { input: "view.staleLabel" } } }
|
|
10567
|
+
]
|
|
10568
|
+
}
|
|
10569
|
+
};
|
|
10570
|
+
|
|
10571
|
+
// src/edit/comments/react/CommentsPanelView.tsx
|
|
10572
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
10573
|
+
function CommentsPanelView({ controller, ...options }) {
|
|
10574
|
+
useSyncExternalStore8(controller.subscribe, controller.getState, controller.getState);
|
|
10575
|
+
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: [
|
|
10578
|
+
/* @__PURE__ */ jsxs9(Stack4, { direction: "row", gap: 4, pad: "none", children: [
|
|
10579
|
+
t.hasAnchorBadge ? /* @__PURE__ */ jsx10(Badge6, { tone: t.anchorTone, title: t.anchorTitle, children: t.anchorLabel }) : null,
|
|
10580
|
+
t.resolved ? /* @__PURE__ */ jsx10(Badge6, { children: "resolved" }) : null,
|
|
10581
|
+
/* @__PURE__ */ jsx10(Text6, { role: "caption", children: t.age })
|
|
10582
|
+
] }),
|
|
10583
|
+
t.hasQuote ? /* @__PURE__ */ jsx10(Quote, { orphaned: t.orphaned, onActivate: () => ui8({ kind: "activate", id: t.id }), children: t.quote }) : null,
|
|
10584
|
+
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,
|
|
10586
|
+
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" })
|
|
10589
|
+
] }) : null,
|
|
10590
|
+
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" })
|
|
10594
|
+
] }) : null
|
|
10595
|
+
] }, t.id);
|
|
10596
|
+
return /* @__PURE__ */ jsxs9(Column6, { children: [
|
|
10485
10597
|
/* @__PURE__ */ jsx10(
|
|
10486
10598
|
Toolbar5,
|
|
10487
10599
|
{
|
|
10488
|
-
left: /* @__PURE__ */ jsx10(
|
|
10489
|
-
|
|
10490
|
-
{
|
|
10491
|
-
label: "Show",
|
|
10492
|
-
value: state.filter.show ?? "open",
|
|
10493
|
-
onChange: (value) => controller.setFilter({ show: value }),
|
|
10494
|
-
options: [
|
|
10495
|
-
{ label: "Open", value: "open" },
|
|
10496
|
-
{ label: "Resolved", value: "resolved" },
|
|
10497
|
-
{ label: "All", value: "all" }
|
|
10498
|
-
]
|
|
10499
|
-
}
|
|
10500
|
-
),
|
|
10501
|
-
right: /* @__PURE__ */ jsx10(ToolbarGroup3, { end: true, children: /* @__PURE__ */ jsx10(
|
|
10502
|
-
SegmentedControl2,
|
|
10503
|
-
{
|
|
10504
|
-
label: "Sort",
|
|
10505
|
-
value: state.sort,
|
|
10506
|
-
onChange: (value) => controller.setSort(value),
|
|
10507
|
-
options: [
|
|
10508
|
-
{ label: "Doc", value: "document" },
|
|
10509
|
-
{ label: "New", value: "newest" },
|
|
10510
|
-
{ label: "Old", value: "oldest" }
|
|
10511
|
-
]
|
|
10512
|
-
}
|
|
10513
|
-
) })
|
|
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 }) }) })
|
|
10514
10602
|
}
|
|
10515
10603
|
),
|
|
10516
|
-
|
|
10517
|
-
|
|
10518
|
-
"
|
|
10519
|
-
state.totals.orphaned === 1 ? "" : "s",
|
|
10520
|
-
" lost the content",
|
|
10521
|
-
state.totals.orphaned === 1 ? " it was" : " they were",
|
|
10522
|
-
" about.",
|
|
10523
|
-
state.filter.includeOrphaned === false ? /* @__PURE__ */ jsx10(TextButton4, { onClick: () => controller.setFilter({ includeOrphaned: true }), children: "Show" }) : null
|
|
10604
|
+
view.orphanedNotice ? /* @__PURE__ */ jsxs9(Note, { children: [
|
|
10605
|
+
view.orphanedNotice,
|
|
10606
|
+
view.orphanedHidden ? /* @__PURE__ */ jsx10(TextButton4, { onClick: () => ui8({ kind: "showOrphaned" }), children: "Show" }) : null
|
|
10524
10607
|
] }) : null,
|
|
10525
|
-
/* @__PURE__ */
|
|
10526
|
-
|
|
10527
|
-
|
|
10528
|
-
|
|
10529
|
-
|
|
10530
|
-
{
|
|
10531
|
-
title: "Nothing matches this filter",
|
|
10532
|
-
hint: `${state.totals.all} comment${state.totals.all === 1 ? "" : "s"} on this document.`
|
|
10533
|
-
}
|
|
10534
|
-
)
|
|
10535
|
-
) : /* @__PURE__ */ jsx10(
|
|
10536
|
-
EmptyState6,
|
|
10537
|
-
{
|
|
10538
|
-
title: "No comments",
|
|
10539
|
-
hint: emptyHint ?? "Select something and add a comment."
|
|
10540
|
-
}
|
|
10541
|
-
) : /* @__PURE__ */ jsxs9(Fragment7, { children: [
|
|
10542
|
-
open.map((view) => /* @__PURE__ */ jsx10(
|
|
10543
|
-
ThreadCard,
|
|
10544
|
-
{
|
|
10545
|
-
view,
|
|
10546
|
-
controller,
|
|
10547
|
-
allowReactions,
|
|
10548
|
-
now
|
|
10549
|
-
},
|
|
10550
|
-
view.thread.id
|
|
10551
|
-
)),
|
|
10552
|
-
showResolved && resolved.length > 0 ? /* @__PURE__ */ jsx10(Section4, { title: `Resolved (${resolved.length})`, flush: true, children: resolved.map((view) => /* @__PURE__ */ jsx10(
|
|
10553
|
-
ThreadCard,
|
|
10554
|
-
{
|
|
10555
|
-
view,
|
|
10556
|
-
controller,
|
|
10557
|
-
allowReactions,
|
|
10558
|
-
now
|
|
10559
|
-
},
|
|
10560
|
-
view.thread.id
|
|
10561
|
-
)) }) : null
|
|
10562
|
-
] }) }),
|
|
10563
|
-
/* @__PURE__ */ jsxs9("div", { style: { borderTop: "1px solid var(--xeno-border-subtle)", padding: 6 }, children: [
|
|
10564
|
-
/* @__PURE__ */ jsx10(
|
|
10565
|
-
"textarea",
|
|
10566
|
-
{
|
|
10567
|
-
value: state.draft,
|
|
10568
|
-
onChange: (event) => controller.setDraft(event.target.value),
|
|
10569
|
-
onKeyDown: (event) => {
|
|
10570
|
-
if (event.key === "Enter" && (event.ctrlKey || event.metaKey)) {
|
|
10571
|
-
event.preventDefault();
|
|
10572
|
-
controller.create();
|
|
10573
|
-
}
|
|
10574
|
-
},
|
|
10575
|
-
placeholder: state.activeAnchor === null ? "Select something in the document to comment on it" : "Add a comment\u2026",
|
|
10576
|
-
disabled: state.activeAnchor === null,
|
|
10577
|
-
rows: 2,
|
|
10578
|
-
style: {
|
|
10579
|
-
width: "100%",
|
|
10580
|
-
fontSize: 11,
|
|
10581
|
-
background: "var(--xeno-canvas)",
|
|
10582
|
-
border: "1px solid var(--xeno-border)",
|
|
10583
|
-
borderRadius: 2,
|
|
10584
|
-
padding: 4,
|
|
10585
|
-
color: "inherit",
|
|
10586
|
-
outline: "none",
|
|
10587
|
-
resize: "none",
|
|
10588
|
-
opacity: state.activeAnchor === null ? 0.5 : 1
|
|
10589
|
-
}
|
|
10590
|
-
}
|
|
10591
|
-
),
|
|
10592
|
-
/* @__PURE__ */ jsx10("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 2 }, children: /* @__PURE__ */ jsx10(
|
|
10593
|
-
TextButton4,
|
|
10594
|
-
{
|
|
10595
|
-
strong: true,
|
|
10596
|
-
disabled: state.activeAnchor === null || state.draft.trim() === "",
|
|
10597
|
-
onClick: () => controller.create(),
|
|
10598
|
-
children: "Comment"
|
|
10599
|
-
}
|
|
10600
|
-
) })
|
|
10608
|
+
/* @__PURE__ */ jsxs9(ScrollArea5, { children: [
|
|
10609
|
+
view.filteredEmpty ? /* @__PURE__ */ jsx10(EmptyState6, { title: "Nothing matches this filter", hint: view.filteredHint }) : null,
|
|
10610
|
+
view.empty ? /* @__PURE__ */ jsx10(EmptyState6, { title: "No comments", hint: view.emptyHint }) : null,
|
|
10611
|
+
view.open.map(card),
|
|
10612
|
+
view.hasResolved ? /* @__PURE__ */ jsx10(Section4, { title: view.resolvedTitle, flush: true, children: view.resolved.map(card) }) : null
|
|
10601
10613
|
] }),
|
|
10602
|
-
/* @__PURE__ */
|
|
10603
|
-
|
|
10604
|
-
{
|
|
10605
|
-
|
|
10606
|
-
|
|
10607
|
-
}
|
|
10608
|
-
)
|
|
10614
|
+
/* @__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" }) }) })
|
|
10617
|
+
] }),
|
|
10618
|
+
/* @__PURE__ */ jsx10(StatusBar6, { left: view.countLabel, right: view.staleLabel })
|
|
10609
10619
|
] });
|
|
10610
10620
|
}
|
|
10611
10621
|
|
|
@@ -11773,7 +11783,7 @@ var nodegraphManifest = {
|
|
|
11773
11783
|
// src/edit/nodegraph/react/NodeGraphPanelView.tsx
|
|
11774
11784
|
import { useCallback as useCallback7, useEffect as useEffect7, useRef as useRef8, useSyncExternalStore as useSyncExternalStore9 } from "react";
|
|
11775
11785
|
import { EmptyState as EmptyState7, StatusBar as StatusBar7, Toolbar as Toolbar6, ToolbarGroup as ToolbarGroup4 } from "@xenosystem/components/chrome";
|
|
11776
|
-
import { Fragment as
|
|
11786
|
+
import { Fragment as Fragment7, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
11777
11787
|
var HEADER_H2 = 24;
|
|
11778
11788
|
var PORT_ROW_H2 = 18;
|
|
11779
11789
|
function NodeGraphPanelView({ controller }) {
|
|
@@ -11996,7 +12006,7 @@ function NodeRect({ node, selected, zoom }) {
|
|
|
11996
12006
|
children: node.title
|
|
11997
12007
|
}
|
|
11998
12008
|
),
|
|
11999
|
-
node.collapsed ? null : /* @__PURE__ */ jsxs10(
|
|
12009
|
+
node.collapsed ? null : /* @__PURE__ */ jsxs10(Fragment7, { children: [
|
|
12000
12010
|
node.inputs.map((port, i) => /* @__PURE__ */ jsx11(
|
|
12001
12011
|
Port,
|
|
12002
12012
|
{
|
|
@@ -12307,6 +12317,8 @@ var TreeController = class {
|
|
|
12307
12317
|
mode;
|
|
12308
12318
|
renaming = null;
|
|
12309
12319
|
drag = null;
|
|
12320
|
+
/** The scroller's measured viewport — the view state windows the rows from it (`tree/Scroller` reports it). */
|
|
12321
|
+
viewport = { height: 0, scrollTop: 0 };
|
|
12310
12322
|
/** Newest outstanding load request PER NODE. Anything else that arrives is stale. */
|
|
12311
12323
|
outstanding = /* @__PURE__ */ new Map();
|
|
12312
12324
|
/** Type-ahead buffer + the time it was last touched. */
|
|
@@ -12356,6 +12368,20 @@ var TreeController = class {
|
|
|
12356
12368
|
this.rowCache = null;
|
|
12357
12369
|
for (const listener of this.listeners) listener();
|
|
12358
12370
|
}
|
|
12371
|
+
/* ── Viewport ──────────────────────────────────────────────────────────── */
|
|
12372
|
+
/** The scroller reports its viewport; the view state windows the rows from it. */
|
|
12373
|
+
setViewport(height, scrollTop) {
|
|
12374
|
+
if (this.viewport.height === height && this.viewport.scrollTop === scrollTop) return;
|
|
12375
|
+
this.viewport = { height, scrollTop };
|
|
12376
|
+
this.notify();
|
|
12377
|
+
}
|
|
12378
|
+
getViewport() {
|
|
12379
|
+
return this.viewport;
|
|
12380
|
+
}
|
|
12381
|
+
/** The fixed row height the virtualizer and the drop resolver share. */
|
|
12382
|
+
getRowHeight() {
|
|
12383
|
+
return this.rowHeight;
|
|
12384
|
+
}
|
|
12359
12385
|
/* ── Rows ──────────────────────────────────────────────────────────────── */
|
|
12360
12386
|
/** The visible rows, flattened through the shared engine. */
|
|
12361
12387
|
rows() {
|
|
@@ -12729,12 +12755,12 @@ var TreeController = class {
|
|
|
12729
12755
|
}
|
|
12730
12756
|
if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
|
|
12731
12757
|
const fresh = now - this.typeAhead.at > this.typeAheadMs;
|
|
12732
|
-
const
|
|
12733
|
-
this.typeAhead = { text:
|
|
12758
|
+
const text8 = (fresh ? "" : this.typeAhead.text) + event.key.toLowerCase();
|
|
12759
|
+
this.typeAhead = { text: text8, at: now };
|
|
12734
12760
|
const from = fresh ? current : current + 1;
|
|
12735
12761
|
for (let i = 0; i < rows.length; i += 1) {
|
|
12736
12762
|
const candidate = rows[(from + i) % rows.length];
|
|
12737
|
-
if (candidate.node.label.toLowerCase().startsWith(
|
|
12763
|
+
if (candidate.node.label.toLowerCase().startsWith(text8)) {
|
|
12738
12764
|
this.focusedId = candidate.id;
|
|
12739
12765
|
this.select([candidate.id]);
|
|
12740
12766
|
return true;
|
|
@@ -12760,9 +12786,9 @@ var TreeController = class {
|
|
|
12760
12786
|
return true;
|
|
12761
12787
|
}
|
|
12762
12788
|
/** Update the rename draft. */
|
|
12763
|
-
updateRenameDraft(
|
|
12789
|
+
updateRenameDraft(text8) {
|
|
12764
12790
|
if (!this.renaming) return;
|
|
12765
|
-
this.renaming = { ...this.renaming, draft:
|
|
12791
|
+
this.renaming = { ...this.renaming, draft: text8 };
|
|
12766
12792
|
this.notify();
|
|
12767
12793
|
}
|
|
12768
12794
|
/**
|
|
@@ -13299,331 +13325,474 @@ var treeManifest = {
|
|
|
13299
13325
|
};
|
|
13300
13326
|
|
|
13301
13327
|
// src/edit/tree/react/TreePanelView.tsx
|
|
13302
|
-
import { useCallback as useCallback8, useEffect as useEffect8, useRef as useRef9,
|
|
13328
|
+
import { useCallback as useCallback8, useEffect as useEffect8, useRef as useRef9, useSyncExternalStore as useSyncExternalStore10 } from "react";
|
|
13303
13329
|
import {
|
|
13304
13330
|
Badge as Badge7,
|
|
13331
|
+
Column as Column7,
|
|
13305
13332
|
EmptyState as EmptyState8,
|
|
13306
13333
|
ErrorState,
|
|
13307
13334
|
IconButton as IconButton7,
|
|
13335
|
+
Input as Input5,
|
|
13308
13336
|
LoadingState,
|
|
13309
13337
|
Row as Row4,
|
|
13338
|
+
RowList as RowList4,
|
|
13310
13339
|
ScrollArea as ScrollArea6,
|
|
13311
13340
|
SearchField as SearchField5,
|
|
13312
13341
|
StatusBar as StatusBar8,
|
|
13342
|
+
Text as Text7,
|
|
13343
|
+
TextButton as TextButton5,
|
|
13313
13344
|
Toolbar as Toolbar7,
|
|
13314
|
-
ToolbarGroup as ToolbarGroup5
|
|
13345
|
+
ToolbarGroup as ToolbarGroup5,
|
|
13346
|
+
VirtualWindow as VirtualWindow3
|
|
13315
13347
|
} from "@xenosystem/components/chrome";
|
|
13348
|
+
|
|
13349
|
+
// src/edit/tree/declaration.ts
|
|
13316
13350
|
import { computeWindow as computeWindow3 } from "@xenosystem/tree-core";
|
|
13317
|
-
|
|
13318
|
-
function
|
|
13319
|
-
|
|
13320
|
-
|
|
13321
|
-
indentPx = 14,
|
|
13322
|
-
overscan = 6,
|
|
13323
|
-
showSearch = true,
|
|
13324
|
-
openOn = "double",
|
|
13325
|
-
columns,
|
|
13326
|
-
emptyHint
|
|
13327
|
-
}) {
|
|
13328
|
-
const state = useSyncExternalStore10(controller.subscribe, controller.getState, controller.getState);
|
|
13329
|
-
const scrollRef = useRef9(null);
|
|
13330
|
-
const [viewport, setViewport] = useState2({ height: 0, scrollTop: 0 });
|
|
13331
|
-
useEffect8(() => {
|
|
13332
|
-
const element = scrollRef.current;
|
|
13333
|
-
if (!element || typeof ResizeObserver === "undefined") return;
|
|
13334
|
-
const observer = new ResizeObserver(() => {
|
|
13335
|
-
setViewport((v) => ({ ...v, height: element.clientHeight }));
|
|
13336
|
-
});
|
|
13337
|
-
observer.observe(element);
|
|
13338
|
-
setViewport((v) => ({ ...v, height: element.clientHeight }));
|
|
13339
|
-
return () => observer.disconnect();
|
|
13340
|
-
}, []);
|
|
13341
|
-
const onScroll = useCallback8((event) => {
|
|
13342
|
-
const el = event.currentTarget;
|
|
13343
|
-
setViewport((v) => ({ ...v, scrollTop: el.scrollTop }));
|
|
13344
|
-
}, []);
|
|
13351
|
+
var iconHalf = (icon) => icon.kind === "text" ? { iconName: null, iconText: icon.value } : { iconName: icon.name, iconText: null };
|
|
13352
|
+
function treeViewState(c, options = {}) {
|
|
13353
|
+
const { overscan = 6, showSearch = true, columns, emptyHint } = options;
|
|
13354
|
+
const state = c.getState();
|
|
13345
13355
|
const source = state.source;
|
|
13346
13356
|
const sourceState = source?.sourceState ?? "idle";
|
|
13347
|
-
const
|
|
13348
|
-
|
|
13349
|
-
|
|
13357
|
+
const rowHeight = c.getRowHeight();
|
|
13358
|
+
const viewport = c.getViewport();
|
|
13359
|
+
const noSource = !source || sourceState === "idle";
|
|
13360
|
+
const loading = !noSource && sourceState === "loading" && state.rows.length === 0;
|
|
13361
|
+
const failed = !noSource && (sourceState === "error" || sourceState === "denied");
|
|
13362
|
+
const denied = sourceState === "denied";
|
|
13363
|
+
const bare = !noSource && !loading && !failed && state.rows.length === 0;
|
|
13364
|
+
const noMatches = bare && state.filter !== "";
|
|
13365
|
+
const emptyTree = bare && state.filter === "";
|
|
13366
|
+
const listShown = !noSource && !loading && !failed && state.rows.length > 0;
|
|
13367
|
+
const window_ = computeWindow3({
|
|
13368
|
+
scrollTop: viewport.scrollTop,
|
|
13369
|
+
viewportHeight: viewport.height || rowHeight * 24,
|
|
13370
|
+
rowHeight,
|
|
13371
|
+
rowCount: state.rows.length,
|
|
13372
|
+
overscan
|
|
13373
|
+
});
|
|
13374
|
+
const drag = state.drag;
|
|
13375
|
+
const renaming = state.renaming;
|
|
13376
|
+
const rows = listShown ? state.rows.slice(window_.startIndex, window_.endIndex).map((row2) => {
|
|
13377
|
+
const node = row2.node;
|
|
13378
|
+
const drop = drag?.targetId === row2.id ? drag : null;
|
|
13379
|
+
const error = node.error;
|
|
13380
|
+
const chipLoading = row2.container && row2.childState === "loading";
|
|
13381
|
+
const chipError = row2.container && !chipLoading && row2.childState === "error";
|
|
13382
|
+
const chipLoadMore = row2.container && !chipLoading && !chipError && !!node.hasMore && row2.expanded;
|
|
13383
|
+
const chipTruncated = row2.container && !chipLoading && !chipError && !chipLoadMore && node.truncatedAt !== void 0;
|
|
13384
|
+
const chipEmpty = row2.container && !chipLoading && !chipError && !chipLoadMore && !chipTruncated && row2.expanded && isEmptyContainer(node);
|
|
13385
|
+
return {
|
|
13386
|
+
id: row2.id,
|
|
13387
|
+
label: node.label,
|
|
13388
|
+
depth: row2.depth,
|
|
13389
|
+
level: row2.depth + 1,
|
|
13390
|
+
height: rowHeight,
|
|
13391
|
+
selected: state.selection.includes(row2.id),
|
|
13392
|
+
disabled: node.caps?.select === false,
|
|
13393
|
+
expanded: row2.container ? row2.expanded : void 0,
|
|
13394
|
+
dropHint: drop?.position ?? null,
|
|
13395
|
+
dropTitle: drop?.reason,
|
|
13396
|
+
renaming: renaming?.id === row2.id,
|
|
13397
|
+
draft: renaming?.id === row2.id ? renaming.draft : "",
|
|
13398
|
+
...iconHalf(node.icon ?? defaultIconFor(node.kind)),
|
|
13399
|
+
chipLoading,
|
|
13400
|
+
chipError,
|
|
13401
|
+
// The host's own sentence — never a regex over a message to guess the cause.
|
|
13402
|
+
chipErrorText: error?.code === "denied" ? "no access" : error?.code ?? "failed",
|
|
13403
|
+
chipLoadMore,
|
|
13404
|
+
chipTruncated,
|
|
13405
|
+
chipTruncatedText: `first ${node.truncatedAt ?? 0}`,
|
|
13406
|
+
chipEmpty,
|
|
13407
|
+
columns: (columns ?? []).map((key) => ({ key, text: node.columns?.[key] ?? "" })),
|
|
13408
|
+
glyphs: (node.glyphs ?? []).map((g) => ({ key: g.id, title: g.title, ...iconHalf(g.icon) })),
|
|
13409
|
+
badges: (node.badges ?? []).map((b) => ({ key: b.id, tone: b.tone, text: b.text })),
|
|
13410
|
+
actions: (node.actions ?? []).map((a) => ({ key: a.id, rowId: row2.id, actionId: a.id, label: a.label, disabled: !!a.disabled, ...iconHalf(a.icon) }))
|
|
13411
|
+
};
|
|
13412
|
+
}) : [];
|
|
13413
|
+
const count = state.rows.length;
|
|
13414
|
+
return {
|
|
13415
|
+
searchShown: showSearch,
|
|
13416
|
+
filter: state.filter,
|
|
13417
|
+
noSource,
|
|
13418
|
+
noSourceHint: emptyHint ?? "Connect a source to browse it.",
|
|
13419
|
+
loading,
|
|
13420
|
+
loadingLabel: source?.sourceMessage ?? "Loading\u2026",
|
|
13421
|
+
failed,
|
|
13422
|
+
failedTitle: denied ? "Access not granted" : "Could not read this source",
|
|
13423
|
+
// The HOST's sentence, verbatim. The panel never composes error prose.
|
|
13424
|
+
failedMessage: source?.sourceMessage,
|
|
13425
|
+
retryLabel: denied ? "Grant access" : "Retry",
|
|
13426
|
+
denied,
|
|
13427
|
+
noMatches,
|
|
13428
|
+
noMatchesHint: `Nothing matches \u201C${state.filter}\u201D.`,
|
|
13429
|
+
emptyTree,
|
|
13430
|
+
emptyHint: emptyHint ?? source?.sourceMessage ?? "This source has no items yet.",
|
|
13431
|
+
listShown,
|
|
13432
|
+
totalHeight: window_.totalHeight,
|
|
13433
|
+
offsetTop: window_.offsetTop,
|
|
13434
|
+
rows,
|
|
13435
|
+
countLabel: `${count} item${count === 1 ? "" : "s"}`,
|
|
13436
|
+
selectedLabel: state.selection.length > 0 ? `${state.selection.length} selected` : void 0
|
|
13437
|
+
};
|
|
13438
|
+
}
|
|
13439
|
+
function applyTreeUi(c, intent, options = {}) {
|
|
13440
|
+
switch (intent.kind) {
|
|
13441
|
+
case "filter":
|
|
13442
|
+
c.setFilter(intent.value);
|
|
13443
|
+
break;
|
|
13444
|
+
case "expandAll":
|
|
13445
|
+
c.expandAll();
|
|
13446
|
+
break;
|
|
13447
|
+
case "collapseAll":
|
|
13448
|
+
c.collapseAll();
|
|
13449
|
+
break;
|
|
13450
|
+
case "refresh":
|
|
13451
|
+
c.refresh();
|
|
13452
|
+
break;
|
|
13453
|
+
case "retry": {
|
|
13454
|
+
if (c.getState().source?.sourceState === "denied") c.requestConsent(void 0, "source denied");
|
|
13455
|
+
else c.refresh();
|
|
13456
|
+
break;
|
|
13350
13457
|
}
|
|
13351
|
-
|
|
13352
|
-
|
|
13458
|
+
case "toggleExpanded": {
|
|
13459
|
+
const row2 = c.getState().rows.find((r) => r.id === intent.id);
|
|
13460
|
+
if (row2) c.setExpanded(intent.id, !row2.expanded);
|
|
13461
|
+
break;
|
|
13353
13462
|
}
|
|
13354
|
-
|
|
13355
|
-
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
title: sourceState === "denied" ? "Access not granted" : "Could not read this source",
|
|
13359
|
-
message: source.sourceMessage,
|
|
13360
|
-
onRetry: sourceState === "denied" ? () => controller.requestConsent(void 0, "source denied") : () => controller.refresh(),
|
|
13361
|
-
retryLabel: sourceState === "denied" ? "Grant access" : "Retry"
|
|
13362
|
-
}
|
|
13363
|
-
);
|
|
13463
|
+
case "click": {
|
|
13464
|
+
c.select([intent.id], { toggle: !!intent.ctrlKey || !!intent.metaKey, range: !!intent.shiftKey });
|
|
13465
|
+
if ((options.openOn ?? "double") === "single") c.open(intent.id, { alt: !!intent.altKey });
|
|
13466
|
+
break;
|
|
13364
13467
|
}
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
|
|
13370
|
-
|
|
13371
|
-
|
|
13372
|
-
);
|
|
13468
|
+
case "doubleClick":
|
|
13469
|
+
if ((options.openOn ?? "double") === "double") c.open(intent.id);
|
|
13470
|
+
break;
|
|
13471
|
+
case "contextMenu": {
|
|
13472
|
+
const state = c.getState();
|
|
13473
|
+
c.requestContextMenu(state.selection.includes(intent.id) ? state.selection : [intent.id], intent.x, intent.y);
|
|
13474
|
+
break;
|
|
13373
13475
|
}
|
|
13374
|
-
|
|
13375
|
-
|
|
13376
|
-
|
|
13377
|
-
|
|
13378
|
-
|
|
13379
|
-
|
|
13380
|
-
|
|
13381
|
-
|
|
13382
|
-
|
|
13383
|
-
|
|
13476
|
+
case "loadMore":
|
|
13477
|
+
c.loadMore(intent.id);
|
|
13478
|
+
break;
|
|
13479
|
+
case "action":
|
|
13480
|
+
c.runAction(intent.id, intent.actionId);
|
|
13481
|
+
break;
|
|
13482
|
+
case "renameDraft":
|
|
13483
|
+
c.updateRenameDraft(intent.value);
|
|
13484
|
+
break;
|
|
13485
|
+
case "renameKey": {
|
|
13486
|
+
if (intent.key === "Enter") c.commitRename();
|
|
13487
|
+
else if (intent.key === "Escape") c.cancelRename();
|
|
13488
|
+
break;
|
|
13489
|
+
}
|
|
13490
|
+
case "commitRename":
|
|
13491
|
+
c.commitRename();
|
|
13492
|
+
break;
|
|
13493
|
+
}
|
|
13494
|
+
}
|
|
13495
|
+
var treeViewManifest = {
|
|
13496
|
+
id: treeManifest.id,
|
|
13497
|
+
version: "1.0.0",
|
|
13498
|
+
title: "Tree",
|
|
13499
|
+
category: "edit",
|
|
13500
|
+
layout: { slot: "side" },
|
|
13501
|
+
inputs: [{ id: "view", type: "object", label: "View state", description: "The TreeViewModel the runtime derives from the controller on every draw." }],
|
|
13502
|
+
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
|
+
commands: []
|
|
13504
|
+
};
|
|
13505
|
+
var EMPTY7 = {
|
|
13506
|
+
searchShown: true,
|
|
13507
|
+
filter: "",
|
|
13508
|
+
noSource: true,
|
|
13509
|
+
noSourceHint: "Connect a source to browse it.",
|
|
13510
|
+
loading: false,
|
|
13511
|
+
loadingLabel: "Loading\u2026",
|
|
13512
|
+
failed: false,
|
|
13513
|
+
failedTitle: "",
|
|
13514
|
+
retryLabel: "Retry",
|
|
13515
|
+
denied: false,
|
|
13516
|
+
noMatches: false,
|
|
13517
|
+
noMatchesHint: "",
|
|
13518
|
+
emptyTree: false,
|
|
13519
|
+
emptyHint: "",
|
|
13520
|
+
listShown: false,
|
|
13521
|
+
totalHeight: 0,
|
|
13522
|
+
offsetTop: 0,
|
|
13523
|
+
rows: [],
|
|
13524
|
+
countLabel: "0 items"
|
|
13525
|
+
};
|
|
13526
|
+
var BEHAVIOURS7 = {
|
|
13527
|
+
"edit/treePanelView": (inputs) => inputs.view ?? EMPTY7
|
|
13528
|
+
};
|
|
13529
|
+
var text7 = (b) => ({ component: "text", props: { text: b } });
|
|
13530
|
+
var ui7 = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
|
|
13531
|
+
var nodeIcon = () => ({
|
|
13532
|
+
component: "fragment",
|
|
13533
|
+
children: [
|
|
13534
|
+
{ 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" })] }
|
|
13536
|
+
]
|
|
13537
|
+
});
|
|
13538
|
+
var TREE_DECLARATION = {
|
|
13539
|
+
format: "xeno.block@1",
|
|
13540
|
+
manifest: treeViewManifest,
|
|
13541
|
+
behaviour: "edit/treePanelView",
|
|
13542
|
+
composition: {
|
|
13543
|
+
component: "chrome/Column",
|
|
13544
|
+
children: [
|
|
13384
13545
|
{
|
|
13385
|
-
|
|
13386
|
-
|
|
13387
|
-
|
|
13388
|
-
|
|
13389
|
-
|
|
13390
|
-
|
|
13391
|
-
|
|
13392
|
-
|
|
13393
|
-
|
|
13546
|
+
component: "chrome/Toolbar",
|
|
13547
|
+
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: "" } }) } } },
|
|
13549
|
+
right: {
|
|
13550
|
+
node: {
|
|
13551
|
+
component: "chrome/ToolbarGroup",
|
|
13552
|
+
props: { end: { value: true } },
|
|
13553
|
+
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") } }
|
|
13557
|
+
]
|
|
13558
|
+
}
|
|
13394
13559
|
}
|
|
13395
|
-
}
|
|
13396
|
-
|
|
13397
|
-
|
|
13560
|
+
}
|
|
13561
|
+
},
|
|
13562
|
+
{ component: "chrome/EmptyState", when: { input: "view.noSource" }, props: { title: { value: "No source" }, hint: { input: "view.noSourceHint" } } },
|
|
13563
|
+
{ 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") } },
|
|
13565
|
+
{ component: "chrome/EmptyState", when: { input: "view.noMatches" }, props: { title: { value: "No matches" }, hint: { input: "view.noMatchesHint" } } },
|
|
13566
|
+
{ component: "chrome/EmptyState", when: { input: "view.emptyTree" }, props: { title: { value: "Nothing here" }, hint: { input: "view.emptyHint" } } },
|
|
13567
|
+
{
|
|
13568
|
+
component: "tree/Scroller",
|
|
13569
|
+
when: { input: "view.listShown" },
|
|
13570
|
+
children: [
|
|
13398
13571
|
{
|
|
13399
|
-
|
|
13400
|
-
|
|
13401
|
-
|
|
13402
|
-
|
|
13403
|
-
|
|
13404
|
-
|
|
13405
|
-
|
|
13406
|
-
|
|
13407
|
-
|
|
13408
|
-
|
|
13572
|
+
component: "chrome/RowList",
|
|
13573
|
+
props: { role: { value: "tree" }, "aria-label": { value: "Tree" }, "aria-multiselectable": { value: true } },
|
|
13574
|
+
children: [
|
|
13575
|
+
{
|
|
13576
|
+
component: "chrome/VirtualWindow",
|
|
13577
|
+
props: { totalHeight: { input: "view.totalHeight" }, offsetTop: { input: "view.offsetTop" } },
|
|
13578
|
+
children: [
|
|
13579
|
+
{
|
|
13580
|
+
component: "chrome/Row",
|
|
13581
|
+
each: { input: "view.rows", key: "id" },
|
|
13582
|
+
props: {
|
|
13583
|
+
"data-tree-row": { item: "id" },
|
|
13584
|
+
"aria-level": { item: "level" },
|
|
13585
|
+
height: { item: "height" },
|
|
13586
|
+
depth: { item: "depth" },
|
|
13587
|
+
selected: { item: "selected" },
|
|
13588
|
+
disabled: { item: "disabled" },
|
|
13589
|
+
expanded: { item: "expanded" },
|
|
13590
|
+
dropHint: { item: "dropHint" },
|
|
13591
|
+
title: { item: "dropTitle" },
|
|
13592
|
+
icon: { node: nodeIcon() },
|
|
13593
|
+
label: {
|
|
13594
|
+
node: {
|
|
13595
|
+
component: "fragment",
|
|
13596
|
+
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" } }) } },
|
|
13598
|
+
{ component: "text", when: { not: { item: "renaming" } }, props: { text: { item: "label" } } }
|
|
13599
|
+
]
|
|
13600
|
+
}
|
|
13601
|
+
},
|
|
13602
|
+
meta: {
|
|
13603
|
+
node: {
|
|
13604
|
+
component: "fragment",
|
|
13605
|
+
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" })] }
|
|
13611
|
+
]
|
|
13612
|
+
}
|
|
13613
|
+
},
|
|
13614
|
+
trailing: {
|
|
13615
|
+
node: {
|
|
13616
|
+
component: "fragment",
|
|
13617
|
+
children: [
|
|
13618
|
+
{ component: "chrome/Text", each: { item: "columns", key: "key" }, props: { role: { value: "number" } }, children: [text7({ item: "text" })] },
|
|
13619
|
+
{ 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" } }) } }
|
|
13622
|
+
]
|
|
13623
|
+
}
|
|
13624
|
+
}
|
|
13625
|
+
},
|
|
13626
|
+
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 } })
|
|
13631
|
+
}
|
|
13632
|
+
}
|
|
13633
|
+
]
|
|
13634
|
+
}
|
|
13635
|
+
]
|
|
13636
|
+
}
|
|
13637
|
+
]
|
|
13638
|
+
},
|
|
13639
|
+
{
|
|
13640
|
+
component: "chrome/StatusBar",
|
|
13641
|
+
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" })] } }
|
|
13644
|
+
}
|
|
13409
13645
|
}
|
|
13410
|
-
|
|
13411
|
-
}
|
|
13412
|
-
|
|
13646
|
+
]
|
|
13647
|
+
}
|
|
13648
|
+
};
|
|
13649
|
+
|
|
13650
|
+
// src/edit/tree/react/TreePanelView.tsx
|
|
13651
|
+
import { Fragment as Fragment8, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
13652
|
+
var DRAG_THRESHOLD2 = 4;
|
|
13653
|
+
function TreePanelView({ controller, ...options }) {
|
|
13654
|
+
useSyncExternalStore10(controller.subscribe, controller.getState, controller.getState);
|
|
13655
|
+
const view = treeViewState(controller, options);
|
|
13656
|
+
const ui8 = (intent) => applyTreeUi(controller, intent, options);
|
|
13657
|
+
const icon = (name, textValue) => /* @__PURE__ */ jsxs11(Fragment8, { children: [
|
|
13658
|
+
name ? /* @__PURE__ */ jsx12(TreeIcon, { name }) : null,
|
|
13659
|
+
textValue ? /* @__PURE__ */ jsx12(Text7, { role: "caption", children: textValue }) : null
|
|
13660
|
+
] });
|
|
13661
|
+
const row2 = (r) => /* @__PURE__ */ jsx12(
|
|
13662
|
+
Row4,
|
|
13663
|
+
{
|
|
13664
|
+
"data-tree-row": r.id,
|
|
13665
|
+
"aria-level": r.level,
|
|
13666
|
+
height: r.height,
|
|
13667
|
+
depth: r.depth,
|
|
13668
|
+
selected: r.selected,
|
|
13669
|
+
disabled: r.disabled,
|
|
13670
|
+
expanded: r.expanded,
|
|
13671
|
+
dropHint: r.dropHint,
|
|
13672
|
+
title: r.dropTitle,
|
|
13673
|
+
icon: icon(r.iconName, r.iconText),
|
|
13674
|
+
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,
|
|
13676
|
+
!r.renaming ? r.label : null
|
|
13677
|
+
] }),
|
|
13678
|
+
meta: /* @__PURE__ */ jsxs11(Fragment8, { children: [
|
|
13679
|
+
r.chipLoading ? /* @__PURE__ */ jsx12(Text7, { role: "caption", children: "loading\u2026" }) : null,
|
|
13680
|
+
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,
|
|
13682
|
+
r.chipTruncated ? /* @__PURE__ */ jsx12(Badge7, { tone: "warning", children: r.chipTruncatedText }) : null,
|
|
13683
|
+
r.chipEmpty ? /* @__PURE__ */ jsx12(Text7, { role: "caption", children: "empty" }) : null
|
|
13684
|
+
] }),
|
|
13685
|
+
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)),
|
|
13688
|
+
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))
|
|
13690
|
+
] }),
|
|
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 })
|
|
13695
|
+
},
|
|
13696
|
+
r.id
|
|
13697
|
+
);
|
|
13698
|
+
return /* @__PURE__ */ jsxs11(Column7, { children: [
|
|
13413
13699
|
/* @__PURE__ */ jsx12(
|
|
13414
13700
|
Toolbar7,
|
|
13415
13701
|
{
|
|
13416
|
-
left:
|
|
13417
|
-
SearchField5,
|
|
13418
|
-
{
|
|
13419
|
-
value: state.filter,
|
|
13420
|
-
onChange: (term) => controller.setFilter(term),
|
|
13421
|
-
placeholder: "Filter\u2026"
|
|
13422
|
-
}
|
|
13423
|
-
) : void 0,
|
|
13702
|
+
left: view.searchShown ? /* @__PURE__ */ jsx12(SearchField5, { value: view.filter, placeholder: "Filter\u2026", onChange: (value) => ui8({ kind: "filter", value }) }) : null,
|
|
13424
13703
|
right: /* @__PURE__ */ jsxs11(ToolbarGroup5, { end: true, children: [
|
|
13425
|
-
/* @__PURE__ */ jsx12(IconButton7, { icon: /* @__PURE__ */ jsx12(ExpandGlyph, {}), label: "Expand all", onClick: () =>
|
|
13426
|
-
/* @__PURE__ */ jsx12(
|
|
13427
|
-
|
|
13428
|
-
{
|
|
13429
|
-
icon: /* @__PURE__ */ jsx12(CollapseGlyph, {}),
|
|
13430
|
-
label: "Collapse all",
|
|
13431
|
-
onClick: () => controller.collapseAll()
|
|
13432
|
-
}
|
|
13433
|
-
),
|
|
13434
|
-
/* @__PURE__ */ jsx12(IconButton7, { icon: /* @__PURE__ */ jsx12(RefreshGlyph, {}), label: "Refresh", onClick: () => controller.refresh() })
|
|
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" }) })
|
|
13435
13707
|
] })
|
|
13436
13708
|
}
|
|
13437
13709
|
),
|
|
13438
|
-
|
|
13439
|
-
/* @__PURE__ */ jsx12(
|
|
13440
|
-
|
|
13441
|
-
|
|
13442
|
-
|
|
13443
|
-
|
|
13444
|
-
|
|
13445
|
-
)
|
|
13710
|
+
view.noSource ? /* @__PURE__ */ jsx12(EmptyState8, { title: "No source", hint: view.noSourceHint }) : null,
|
|
13711
|
+
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,
|
|
13713
|
+
view.noMatches ? /* @__PURE__ */ jsx12(EmptyState8, { title: "No matches", hint: view.noMatchesHint }) : null,
|
|
13714
|
+
view.emptyTree ? /* @__PURE__ */ jsx12(EmptyState8, { title: "Nothing here", hint: view.emptyHint }) : null,
|
|
13715
|
+
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 })
|
|
13446
13717
|
] });
|
|
13447
13718
|
}
|
|
13448
|
-
function
|
|
13449
|
-
|
|
13450
|
-
|
|
13451
|
-
|
|
13452
|
-
|
|
13453
|
-
|
|
13454
|
-
|
|
13455
|
-
|
|
13456
|
-
|
|
13457
|
-
|
|
13458
|
-
|
|
13459
|
-
|
|
13460
|
-
|
|
13461
|
-
const
|
|
13462
|
-
|
|
13463
|
-
|
|
13464
|
-
|
|
13465
|
-
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
|
|
13474
|
-
|
|
13475
|
-
|
|
13476
|
-
|
|
13477
|
-
|
|
13478
|
-
|
|
13479
|
-
|
|
13480
|
-
|
|
13481
|
-
children: /* @__PURE__ */ jsx12(ChevronGlyph, { size: 9 })
|
|
13482
|
-
}
|
|
13483
|
-
) : (
|
|
13484
|
-
// A leaf still reserves the twisty column, so labels stay in ONE column across mixed rows.
|
|
13485
|
-
/* @__PURE__ */ jsx12("span", { style: { width: 12, flex: "0 0 auto" } })
|
|
13719
|
+
function TreeScroller({ controller, children }) {
|
|
13720
|
+
const scrollRef = useRef9(null);
|
|
13721
|
+
const pressRef = useRef9(null);
|
|
13722
|
+
useEffect8(() => {
|
|
13723
|
+
const el = scrollRef.current;
|
|
13724
|
+
if (!el) return;
|
|
13725
|
+
controller.setViewport(el.clientHeight, el.scrollTop);
|
|
13726
|
+
const RO = globalThis.ResizeObserver;
|
|
13727
|
+
if (!RO) return;
|
|
13728
|
+
const ro = new RO(() => controller.setViewport(el.clientHeight, el.scrollTop));
|
|
13729
|
+
ro.observe(el);
|
|
13730
|
+
return () => ro.disconnect();
|
|
13731
|
+
}, [controller]);
|
|
13732
|
+
const onScroll = useCallback8((e) => controller.setViewport(e.currentTarget.clientHeight, e.currentTarget.scrollTop), [controller]);
|
|
13733
|
+
const rowFromPoint = useCallback8((clientX, clientY) => {
|
|
13734
|
+
const el = document.elementFromPoint(clientX, clientY);
|
|
13735
|
+
const rowEl = el?.closest?.("[data-tree-row]");
|
|
13736
|
+
const id = rowEl?.getAttribute("data-tree-row");
|
|
13737
|
+
if (!rowEl || !id) return null;
|
|
13738
|
+
return { id, offsetY: clientY - rowEl.getBoundingClientRect().top };
|
|
13739
|
+
}, []);
|
|
13740
|
+
const onPointerDown = useCallback8(
|
|
13741
|
+
(e) => {
|
|
13742
|
+
if (e.button !== 0) return;
|
|
13743
|
+
const target = e.target;
|
|
13744
|
+
if (target?.closest?.("button,input")) return;
|
|
13745
|
+
const id = target?.closest?.("[data-tree-row]")?.getAttribute("data-tree-row");
|
|
13746
|
+
if (!id) return;
|
|
13747
|
+
const selection = controller.getState().selection;
|
|
13748
|
+
pressRef.current = { ids: selection.includes(id) ? selection : [id], x: e.clientX, y: e.clientY, dragging: false };
|
|
13749
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
13750
|
+
},
|
|
13751
|
+
[controller]
|
|
13486
13752
|
);
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
|
|
13499
|
-
|
|
13500
|
-
{
|
|
13501
|
-
role: "treeitem",
|
|
13502
|
-
"aria-expanded": row2.container ? row2.expanded : void 0,
|
|
13503
|
-
"aria-level": row2.depth + 1,
|
|
13504
|
-
selected,
|
|
13505
|
-
disabled: node.caps?.select === false,
|
|
13506
|
-
depth: 0,
|
|
13507
|
-
style: { height: rowHeight, paddingLeft: 6 + row2.depth * indentPx },
|
|
13508
|
-
onClick: (e) => {
|
|
13509
|
-
controller.select([row2.id], {
|
|
13510
|
-
toggle: e.ctrlKey || e.metaKey,
|
|
13511
|
-
range: e.shiftKey
|
|
13512
|
-
});
|
|
13513
|
-
if (openOn === "single") controller.open(row2.id, { alt: e.altKey });
|
|
13514
|
-
},
|
|
13515
|
-
onDoubleClick: () => {
|
|
13516
|
-
if (openOn === "double") controller.open(row2.id);
|
|
13517
|
-
},
|
|
13518
|
-
onContextMenu: (e) => {
|
|
13519
|
-
e.preventDefault();
|
|
13520
|
-
controller.requestContextMenu(selected ? state.selection : [row2.id], e.clientX, e.clientY);
|
|
13521
|
-
},
|
|
13522
|
-
onPointerDown: (e) => {
|
|
13523
|
-
if (e.button !== 0) return;
|
|
13524
|
-
controller.beginDrag(selected ? state.selection : [row2.id]);
|
|
13525
|
-
},
|
|
13526
|
-
onPointerMove: (e) => {
|
|
13527
|
-
if (!state.drag) return;
|
|
13528
|
-
const rect = e.currentTarget.getBoundingClientRect();
|
|
13529
|
-
controller.dragOver(row2.id, e.clientY - rect.top);
|
|
13530
|
-
},
|
|
13531
|
-
onPointerUp: () => {
|
|
13532
|
-
if (state.drag) controller.endDrag();
|
|
13533
|
-
},
|
|
13534
|
-
icon: /* @__PURE__ */ jsxs11(Fragment9, { children: [
|
|
13535
|
-
twisty,
|
|
13536
|
-
/* @__PURE__ */ jsx12(NodeIcon, { icon: node.icon ?? defaultIconFor(node.kind) })
|
|
13537
|
-
] }),
|
|
13538
|
-
label: renaming ? /* @__PURE__ */ jsx12(
|
|
13539
|
-
"input",
|
|
13540
|
-
{
|
|
13541
|
-
autoFocus: true,
|
|
13542
|
-
value: renaming.draft,
|
|
13543
|
-
onChange: (e) => controller.updateRenameDraft(e.target.value),
|
|
13544
|
-
onBlur: () => controller.commitRename(),
|
|
13545
|
-
onFocus: (e) => e.currentTarget.select(),
|
|
13546
|
-
onClick: (e) => e.stopPropagation(),
|
|
13547
|
-
onKeyDown: (e) => {
|
|
13548
|
-
e.stopPropagation();
|
|
13549
|
-
if (e.key === "Enter") controller.commitRename();
|
|
13550
|
-
else if (e.key === "Escape") controller.cancelRename();
|
|
13551
|
-
},
|
|
13552
|
-
style: {
|
|
13553
|
-
width: "100%",
|
|
13554
|
-
border: "none",
|
|
13555
|
-
outline: "none",
|
|
13556
|
-
background: "var(--xeno-canvas)",
|
|
13557
|
-
color: "inherit",
|
|
13558
|
-
font: "inherit",
|
|
13559
|
-
padding: 0
|
|
13560
|
-
}
|
|
13561
|
-
}
|
|
13562
|
-
) : node.label,
|
|
13563
|
-
meta: /* @__PURE__ */ jsx12(ChildStateChip, { row: row2, controller }),
|
|
13564
|
-
trailing: /* @__PURE__ */ jsxs11(Fragment9, { children: [
|
|
13565
|
-
columns?.map((columnId) => /* @__PURE__ */ jsx12("span", { style: { opacity: 0.7, fontVariantNumeric: "tabular-nums" }, children: node.columns?.[columnId] ?? "" }, columnId)),
|
|
13566
|
-
node.glyphs?.map((glyph) => /* @__PURE__ */ jsx12("span", { title: glyph.title, style: { display: "flex", opacity: 0.7 }, children: /* @__PURE__ */ jsx12(NodeIcon, { icon: glyph.icon }) }, glyph.id)),
|
|
13567
|
-
node.badges?.map((badge) => (
|
|
13568
|
-
// Opaque: the host formatted the text, the panel only places it.
|
|
13569
|
-
/* @__PURE__ */ jsx12(Badge7, { tone: badge.tone, className: badge.title ? void 0 : void 0, children: badge.text }, badge.id)
|
|
13570
|
-
)),
|
|
13571
|
-
node.actions?.map((action) => /* @__PURE__ */ jsx12(
|
|
13572
|
-
IconButton7,
|
|
13573
|
-
{
|
|
13574
|
-
size: "sm",
|
|
13575
|
-
icon: /* @__PURE__ */ jsx12(NodeIcon, { icon: action.icon }),
|
|
13576
|
-
label: action.label,
|
|
13577
|
-
disabled: action.disabled,
|
|
13578
|
-
onClick: () => controller.runAction(row2.id, action.id)
|
|
13579
|
-
},
|
|
13580
|
-
action.id
|
|
13581
|
-
))
|
|
13582
|
-
] })
|
|
13583
|
-
}
|
|
13584
|
-
)
|
|
13585
|
-
}
|
|
13753
|
+
const onPointerMove = useCallback8(
|
|
13754
|
+
(e) => {
|
|
13755
|
+
const press = pressRef.current;
|
|
13756
|
+
if (!press) return;
|
|
13757
|
+
if (!press.dragging) {
|
|
13758
|
+
if (Math.abs(e.clientX - press.x) + Math.abs(e.clientY - press.y) < DRAG_THRESHOLD2) return;
|
|
13759
|
+
press.dragging = true;
|
|
13760
|
+
controller.beginDrag(press.ids);
|
|
13761
|
+
}
|
|
13762
|
+
const hit = rowFromPoint(e.clientX, e.clientY);
|
|
13763
|
+
if (hit) controller.dragOver(hit.id, hit.offsetY);
|
|
13764
|
+
},
|
|
13765
|
+
[controller, rowFromPoint]
|
|
13586
13766
|
);
|
|
13587
|
-
|
|
13588
|
-
|
|
13589
|
-
|
|
13590
|
-
|
|
13591
|
-
|
|
13592
|
-
|
|
13593
|
-
|
|
13594
|
-
return /* @__PURE__ */ jsx12("span", { style: { opacity: 0.5, fontSize: 9 }, children: "loading\u2026" });
|
|
13595
|
-
}
|
|
13596
|
-
if (row2.childState === "error") {
|
|
13597
|
-
const error = row2.node.error;
|
|
13598
|
-
return /* @__PURE__ */ jsx12(Badge7, { tone: "error", children: error?.code === "denied" ? "no access" : error?.code ?? "failed" });
|
|
13599
|
-
}
|
|
13600
|
-
if (row2.node.hasMore && row2.expanded) {
|
|
13601
|
-
return /* @__PURE__ */ jsx12(
|
|
13602
|
-
"span",
|
|
13603
|
-
{
|
|
13604
|
-
role: "button",
|
|
13605
|
-
onClick: (e) => {
|
|
13606
|
-
e.stopPropagation();
|
|
13607
|
-
controller.loadMore(row2.id);
|
|
13608
|
-
},
|
|
13609
|
-
style: { cursor: "pointer", opacity: 0.7, fontSize: 9 },
|
|
13610
|
-
children: "load more\u2026"
|
|
13767
|
+
const onPointerUp = useCallback8(
|
|
13768
|
+
(e) => {
|
|
13769
|
+
const press = pressRef.current;
|
|
13770
|
+
pressRef.current = null;
|
|
13771
|
+
try {
|
|
13772
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
13773
|
+
} catch {
|
|
13611
13774
|
}
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
-
|
|
13620
|
-
|
|
13775
|
+
if (press?.dragging) controller.endDrag();
|
|
13776
|
+
},
|
|
13777
|
+
[controller]
|
|
13778
|
+
);
|
|
13779
|
+
const onKeyDown = useCallback8(
|
|
13780
|
+
(e) => {
|
|
13781
|
+
if (controller.getState().renaming) return;
|
|
13782
|
+
if (controller.handleKey({ key: e.key, shiftKey: e.shiftKey, ctrlKey: e.ctrlKey, metaKey: e.metaKey, altKey: e.altKey })) {
|
|
13783
|
+
e.preventDefault();
|
|
13784
|
+
e.stopPropagation();
|
|
13785
|
+
}
|
|
13786
|
+
},
|
|
13787
|
+
[controller]
|
|
13788
|
+
);
|
|
13789
|
+
return /* @__PURE__ */ jsx12(ScrollArea6, { ref: scrollRef, onScroll, onKeyDown, onPointerDown, onPointerMove, onPointerUp, tabIndex: 0, children });
|
|
13621
13790
|
}
|
|
13622
|
-
|
|
13623
|
-
|
|
13624
|
-
|
|
13625
|
-
|
|
13626
|
-
|
|
13791
|
+
var TREE_RUNTIME_UNITS = ["tree/Scroller"];
|
|
13792
|
+
function treeRuntimeComponents(controller) {
|
|
13793
|
+
return {
|
|
13794
|
+
"tree/Scroller": ({ children }) => /* @__PURE__ */ jsx12(TreeScroller, { controller, children })
|
|
13795
|
+
};
|
|
13627
13796
|
}
|
|
13628
13797
|
|
|
13629
13798
|
// src/edit/tree/panel.ts
|
|
@@ -13832,7 +14001,10 @@ export {
|
|
|
13832
14001
|
COLOR_DECLARATION,
|
|
13833
14002
|
COLOR_RUNTIME_UNITS,
|
|
13834
14003
|
COLOR_SPACES,
|
|
14004
|
+
BEHAVIOURS6 as COMMENTS_BEHAVIOURS,
|
|
14005
|
+
COMMENTS_DECLARATION,
|
|
13835
14006
|
COMMENTS_PANEL_ID,
|
|
14007
|
+
COMMENTS_RUNTIME_UNITS,
|
|
13836
14008
|
CURVE_PANEL_ID,
|
|
13837
14009
|
ColorPanelController,
|
|
13838
14010
|
ColorPanelView,
|
|
@@ -13881,11 +14053,15 @@ export {
|
|
|
13881
14053
|
NODEGRAPH_PANEL_ID,
|
|
13882
14054
|
NodeGraphPanelView,
|
|
13883
14055
|
SPACE_LABEL,
|
|
14056
|
+
BEHAVIOURS7 as TREE_BEHAVIOURS,
|
|
14057
|
+
TREE_DECLARATION,
|
|
13884
14058
|
TREE_PANEL_ID,
|
|
14059
|
+
TREE_RUNTIME_UNITS,
|
|
13885
14060
|
Thumbnail,
|
|
13886
14061
|
TreeController,
|
|
13887
14062
|
TreeIcon,
|
|
13888
14063
|
TreePanelView,
|
|
14064
|
+
TreeScroller,
|
|
13889
14065
|
VIEWPORT_PANEL_ID,
|
|
13890
14066
|
VIEWPORT_SLOTS,
|
|
13891
14067
|
VIEW_STATE_OPS,
|
|
@@ -13899,12 +14075,14 @@ export {
|
|
|
13899
14075
|
anchorStateOf,
|
|
13900
14076
|
appliedCount,
|
|
13901
14077
|
applyColorUi,
|
|
14078
|
+
applyCommentsUi,
|
|
13902
14079
|
applyFindUi,
|
|
13903
14080
|
applyHistoryUi,
|
|
13904
14081
|
applyInspectorUi,
|
|
13905
14082
|
applyLayersUi,
|
|
13906
14083
|
applyPrecision,
|
|
13907
14084
|
applyTangentDrag,
|
|
14085
|
+
applyTreeUi,
|
|
13908
14086
|
ariaSliderProps,
|
|
13909
14087
|
boxesIntersect,
|
|
13910
14088
|
canConnect,
|
|
@@ -13922,6 +14100,8 @@ export {
|
|
|
13922
14100
|
colorViewState,
|
|
13923
14101
|
commentsManifest,
|
|
13924
14102
|
commentsPanel,
|
|
14103
|
+
commentsViewManifest,
|
|
14104
|
+
commentsViewState,
|
|
13925
14105
|
commitPolicyOf,
|
|
13926
14106
|
componentsForSpace,
|
|
13927
14107
|
computeSurfaceSize,
|
|
@@ -14064,6 +14244,9 @@ export {
|
|
|
14064
14244
|
totalCount,
|
|
14065
14245
|
treeManifest,
|
|
14066
14246
|
treePanel,
|
|
14247
|
+
treeRuntimeComponents,
|
|
14248
|
+
treeViewManifest,
|
|
14249
|
+
treeViewState,
|
|
14067
14250
|
usesLogScale,
|
|
14068
14251
|
valueExtent,
|
|
14069
14252
|
valueToPosition,
|