@xenosystem/blocks 0.12.3 → 0.12.4

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.
@@ -1615,7 +1615,7 @@ declare function inspectorViewState(c: InspectorPanelController): InspectorViewS
1615
1615
  /** Apply a `ui` intent to the controller — the runtime's half of the contract. */
1616
1616
  declare function applyInspectorUi(c: InspectorPanelController, intent: InspectorUiIntent): void;
1617
1617
  declare const inspectorViewManifest: PanelManifest;
1618
- declare const BEHAVIOURS: {
1618
+ declare const BEHAVIOURS$1: {
1619
1619
  'edit/inspectorPanelView': (inputs: Record<string, unknown>) => InspectorViewState;
1620
1620
  };
1621
1621
  declare const INSPECTOR_DECLARATION: BlockDeclaration;
@@ -1983,7 +1983,14 @@ declare class HistoryPanelController {
1983
1983
  */
1984
1984
 
1985
1985
  /** Options for {@link createHistoryPanel}. */
1986
- type CreateHistoryPanelOptions = HistoryPanelControllerOptions;
1986
+ interface CreateHistoryPanelOptions extends HistoryPanelControllerOptions {
1987
+ /**
1988
+ * Draw the panel yourself — a host that mounts the block AS ITS DECLARATION renders
1989
+ * `HISTORY_DECLARATION` from `historyViewState(controller)` with `historyRuntimeComponents(controller)`
1990
+ * in its registry and applies `ui` intents with `applyHistoryUi`. Default: the code view.
1991
+ */
1992
+ render?: (root: HTMLElement, controller: HistoryPanelController) => () => void;
1993
+ }
1987
1994
  /**
1988
1995
  * Build the History panel module.
1989
1996
  *
@@ -2105,10 +2112,10 @@ declare function resolveIconName(kind: string | undefined, hostMap?: Record<stri
2105
2112
  * `useSyncExternalStore` and forwards interactions. No projection logic, no intent construction and
2106
2113
  * no virtualization math live here.
2107
2114
  *
2108
- * Rendered over the chrome family: a `Toolbar` of undo/redo/search/count/clear, an `InlineConfirm`
2109
- * for clearing, a `ScrollArea` the virtualizer measures, a `VirtualWindow` of `Row`s (the current
2110
- * row `selected`, the keyboard row `focused`, future entries `struck` — Photoshop's affordance),
2111
- * and a `StatusBar` for memory. The window math and the keyboard model stay in the controller.
2115
+ * Drawn from the SAME view state as `HISTORY_DECLARATION` (`historyViewState(controller)`) — the
2116
+ * declaration test holds the two byte-identical. The window math and the keyboard model stay in the
2117
+ * controller; the scroller (`HistoryScroller`) is the one runtime-bound unit: the element the
2118
+ * virtualizer measures, whose scrollTop the controller mirrors, the keys listen on.
2112
2119
  *
2113
2120
  * @module
2114
2121
  */
@@ -2118,6 +2125,109 @@ interface HistoryPanelViewProps {
2118
2125
  controller: HistoryPanelController;
2119
2126
  }
2120
2127
  declare function HistoryPanelView({ controller }: HistoryPanelViewProps): ReactElement;
2128
+ /**
2129
+ * The units the runtime registers for `HISTORY_DECLARATION`, bound to ITS controller: the scroller,
2130
+ * the cancel button, and the glyphs.
2131
+ */
2132
+ declare function historyRuntimeComponents(controller: HistoryPanelController): Record<string, React.ComponentType<any>>;
2133
+
2134
+ /**
2135
+ * The history panel AS A DECLARATION — the sixth block written the §8d way (auth gate, agent, account,
2136
+ * transport, inspector, history), and the first virtualized list.
2137
+ *
2138
+ * Presentation contract: input `view` (a {@link HistoryViewState} the runtime derives from the
2139
+ * controller on every draw — the window already computed, every row flag decided), output `ui`
2140
+ * (a {@link HistoryUiIntent}) applied by the runtime to the controller's own methods. The declaration
2141
+ * composes everything a reader sees: the toolbar, the inline confirmation, the pruned note, the
2142
+ * virtual window of rows, the empty state, the memory status bar.
2143
+ *
2144
+ * What a declaration cannot hold is the SCROLLER: the element the virtualizer measures, whose
2145
+ * `scrollTop` the controller mirrors, the keyboard model listens on. That is `history/Scroller`, a
2146
+ * unit the runtime registers bound to its controller ({@link historyRuntimeComponents}) — the same
2147
+ * shape as the inspector's cell. The rows inside it are data.
2148
+ */
2149
+
2150
+ interface HistoryViewRow {
2151
+ key: string;
2152
+ entryId: string | null;
2153
+ label: string;
2154
+ meta?: number;
2155
+ current: boolean;
2156
+ future: boolean;
2157
+ focused: boolean;
2158
+ jumpable: boolean;
2159
+ showIcon: boolean;
2160
+ hideIcon: boolean;
2161
+ iconName: string;
2162
+ pending: boolean;
2163
+ failed: boolean;
2164
+ showSource: boolean;
2165
+ sourceGlyph: string;
2166
+ sourceTitle: string;
2167
+ showCoalesced: boolean;
2168
+ coalescedText: string;
2169
+ coalescedTitle: string;
2170
+ showTime: boolean;
2171
+ time: string;
2172
+ height: number;
2173
+ cancelId?: string;
2174
+ }
2175
+ interface HistoryViewState {
2176
+ canUndo: boolean;
2177
+ canRedo: boolean;
2178
+ cannotUndo: boolean;
2179
+ cannotRedo: boolean;
2180
+ searchShown: boolean;
2181
+ filter: string;
2182
+ counter: string;
2183
+ clearAllowed: boolean;
2184
+ confirmingClear: boolean;
2185
+ pruned: boolean;
2186
+ totalHeight: number;
2187
+ offsetTop: number;
2188
+ rows: HistoryViewRow[];
2189
+ empty: boolean;
2190
+ hasMemory: boolean;
2191
+ memoryText: string;
2192
+ memoryDisk?: string;
2193
+ }
2194
+ type HistoryUiIntent = {
2195
+ kind: 'undo';
2196
+ } | {
2197
+ kind: 'redo';
2198
+ } | {
2199
+ kind: 'filter';
2200
+ value: string;
2201
+ } | {
2202
+ kind: 'requestClear';
2203
+ } | {
2204
+ kind: 'confirmClear';
2205
+ } | {
2206
+ kind: 'cancelClear';
2207
+ } | {
2208
+ kind: 'jump';
2209
+ entryId: string | null;
2210
+ } | {
2211
+ kind: 'hover';
2212
+ entryId: string | null;
2213
+ } | {
2214
+ kind: 'contextMenu';
2215
+ entryId: string | null;
2216
+ x: number;
2217
+ y: number;
2218
+ } | {
2219
+ kind: 'cancelPending';
2220
+ entryId?: string;
2221
+ };
2222
+ /** Derive the view state from the live controller — the runtime calls this on every draw. */
2223
+ declare function historyViewState(c: HistoryPanelController): HistoryViewState;
2224
+ /** Apply a `ui` intent to the controller — the runtime's half of the contract. */
2225
+ declare function applyHistoryUi(c: HistoryPanelController, intent: HistoryUiIntent): void;
2226
+ declare const historyViewManifest: PanelManifest;
2227
+ declare const BEHAVIOURS: {
2228
+ 'edit/historyPanelView': (inputs: Record<string, unknown>) => HistoryViewState;
2229
+ };
2230
+ declare const HISTORY_DECLARATION: BlockDeclaration;
2121
2231
 
2122
2232
  /**
2123
2233
  * Internal color math for `@xenosystem/blocks/edit`.
@@ -6617,4 +6727,4 @@ declare function TreeIcon({ name, size }: {
6617
6727
  size?: number;
6618
6728
  }): ReactNode;
6619
6729
 
6620
- export { type BlendModeGroup, type BlendModeOption, type Box, COLOR_SPACES, COMMENTS_PANEL_ID, CURVE_PANEL_ID, type ChannelId, ColorPanelController, type ColorPanelControllerOptions, type ColorPanelSerialized, ColorPanelView, type ColorPanelViewProps, type ColorSpace, type ColorStopSink, type ColorToken, CommentsController, type CommentsControllerOptions, type CommentsHostBridge, type CommentsPanelState, CommentsPanelView, type CommentsPanelViewProps, type CommentsRenderContext, type CommentsThreadView, type CommentsViewState, type ConnectRules, type ConnectVerdict, type CreateColorPanelOptions, type CreateCommentsPanelOptions, type CreateCurvePanelOptions, type CreateFindPanelOptions, type CreateHistoryPanelOptions, type CreateInspectorPanelOptions, type CreateLayersPanelOptions, type CreateNodeGraphPanelOptions, type CreateTreePanelOptions, type CreateViewportPanelOptions, CurveController, type CurveControllerOptions, type CurveDragKind, type CurveDragState, type CurveHostBridge, type CurvePanelState, CurvePanelView, type CurvePanelViewProps, type CurvePreview, type CurveRenderConfig, type CurveRenderContext, type CurveViewState, DEFAULT_BLEND_MODES, DEFAULT_CURVE_ZOOM, DEFAULT_GRAPH_ZOOM, DEFAULT_ICON_MAP, DEFAULT_ORIGINAL_LABEL, type DropInput, EASING_PRESETS, EDIT_SPACES, EMPTY_HISTORY, EMPTY_SCHEMA, EMPTY_TREE, EMPTY_TREE_SOURCE, FIND_PANEL_ID, FindController, type FindControllerOptions, type FindHostBridge, type FindPanelState, FindPanelView, type FindPanelViewProps, type FindRenderContext, type FindViewState, type FlatRow, type FlattenOptions, GENERIC_ICON, GraphController, type GraphControllerOptions, type GraphDragKind, type GraphDragState, type GraphHostBridge, type GraphPanelState, type GraphPreview, type GraphRenderConfig, type GraphRenderContext, type GraphViewState, type HistoryKeyEvent, HistoryPanelController, type HistoryPanelControllerOptions, type HistoryPanelSerialized, HistoryPanelView, type HistoryPanelViewProps, type ProjectOptions as HistoryProjectOptions, type HistoryRow, type Hsl, type Hsv, IMPLEMENTED_TREE_MODES, BEHAVIOURS as INSPECTOR_BEHAVIOURS, INSPECTOR_DECLARATION, type InspectorKeyEvent, InspectorPanelController, type InspectorPanelControllerOptions, type InspectorPanelSerialized, InspectorPanelView, type InspectorPanelViewProps, type ProjectOptions$1 as InspectorProjectOptions, type InspectorUiIntent, type InspectorViewField, type InspectorViewSection, type InspectorViewState, LAYER_COLUMNS, type LayerColumn, type LayersKeyEvent, LayersPanelController, type LayersPanelControllerOptions, type LayersPanelSerialized, LayersPanelView, type LayersPanelViewProps, MIXED, NODEGRAPH_PANEL_ID, NodeGraphPanelView, type NodeGraphPanelViewProps, type NumericConstraints, type OklchDisplay, type ParseResult, type ProjectedSection, type Rgba, type ScrubOptions, type SelectMods, TREE_PANEL_ID, type TangentEdit, Thumbnail, type ThumbnailProps, TreeController, type TreeControllerOptions, type TreeHostBridge, TreeIcon, type TreeKeyEvent, type TreePanelState, TreePanelView, type TreePanelViewProps, type TreeRenderContext, type TreeRow, type TreeViewState, VIEWPORT_PANEL_ID, VIEWPORT_SLOTS, VIEW_STATE_OPS, ViewportController, type ViewportControllerOptions, type ViewportHostBridge, type ViewportPanelState, ViewportPanelView, type ViewportPanelViewProps, type ViewportRenderContext, type ViewportViewState, type XenoAddMenuItem, type XenoAnchorState, type XenoColorValue, type XenoCommentAuthor, type XenoCommentFilter, type XenoCommentMessage, type XenoCommentOp, type XenoCommentReaction, type XenoCommentSort, type XenoCommentThread, type XenoCommitPolicy, type XenoContextMenuRequest, type XenoCurveChannel, type XenoCurveInterpolation, type XenoCurveKey, type XenoCurveKeyRef, type XenoCurveOp, type XenoCurvePoint, XenoCurveScale, type XenoCurveScaleGeometry, type XenoCurveScaleState, type XenoCurveSelection, type XenoCurveSet, type XenoCurveViewport, type XenoCurveZoom, type XenoEasingPreset, type XenoEdge, type XenoFieldAnim, type XenoFieldFocus, type XenoFieldOption, type XenoFieldToken, type XenoFieldType, type XenoFieldValue, type XenoFindMatch, type XenoFindNavigate, type XenoFindOptions, type XenoFindQuery, type XenoFindReplace, type XenoFindResults, type XenoFindStatus, type XenoGradient, type XenoGraph, type XenoGraphOp, XenoGraphScale, type XenoGraphScaleGeometry, type XenoGraphScaleState, type XenoGraphSelection, type XenoGraphViewport, type XenoGraphZoom, type XenoHistoryEntry, type XenoHistoryIntent, type XenoHistoryMemory, type XenoHistoryOrder, type XenoHistoryScope, type XenoHistorySnapshot, type XenoHistorySource, type XenoHistoryState, type XenoHistoryStatus, type XenoInspectorEdit, type XenoInspectorField, type XenoInspectorSchema, type XenoInspectorSection, type XenoInspectorTarget, type XenoInspectorToken, type XenoKeyframeKind, type XenoLayerAdornment, type XenoLayerCap, type XenoLayerKind, type XenoLayerNode, type XenoLayerOp, type XenoLayerTree, type XenoNavigateRequest, type XenoNode, XenoNodeIndex, type XenoPort, type XenoPortDirection, type XenoPortRef, type XenoSectionAction, type XenoTangent, type XenoTangentMode, type XenoTangentSide, type XenoThreadActivate, type XenoThumbnailRequest, type XenoThumbnailResponse, type XenoTreeAction, type XenoTreeBadge, type XenoTreeCaps, type XenoTreeChildState, type XenoTreeChildrenResponse, type XenoTreeError, type XenoTreeGlyph, type XenoTreeIcon, type XenoTreeInvalidate, type XenoTreeMode, type XenoTreeModifiers, type XenoTreeNode, type XenoTreeNodeKind, type XenoTreeOp, type XenoTreeReveal, type XenoTreeSource, type XenoTreeSourceKind, type XenoTreeSourceState, type XenoViewportClient, type XenoViewportKey, type XenoViewportPointer, type XenoViewportSlot, type XenoViewportStats, type XenoViewportSurface, allFields, allIds, anchorStateOf, appliedCount, applyInspectorUi, applyPrecision, applyTangentDrag, ariaSliderProps, boxesIntersect, canConnect, canRedo, canUndo, childStateOf, clamp, clampAlpha, clampTangent, collectDescendants, colorManifest, colorPanel, commentsManifest, commentsPanel, commitPolicyOf, componentsForSpace, computeSurfaceSize, constraintsOf, countIsMeaningful, createColorPanel, createCommentsPanel, createCurvePanel, createFindPanel, createHistoryPanel, createInspectorPanel, createLayersPanel, createNodeGraphPanel, createTreePanel, createViewportPanel, createsCycle, currentRowIndex, curveManifest, curvePanel, defaultIconFor, displayOrder, distanceToEdge, easeAt, easingPreset, edgeBounds, edgeKey, edgePath, edgesToReplace, edgesTouching, evaluateChannel, fieldMatches, findField, findManifest, findPanel, findPort, findSectionOf, fitToBounds, fitValueRange, flattenVisible, focusOrder, formatAge, formatNumeric, getAncestors, graphBounds, groupMatches, hasCap, hasDraggableTangents, hasTreeCap, hexFromHsv, highlightSegments, historyManifest, historyPanel, hslToRgb, hsvFromHex, hsvToRgb, inspectorManifest, inspectorPanel, inspectorRuntimeComponents, inspectorViewManifest, inspectorViewState, interpolateSegment, isAncestorOf, isAnimated, isCollapsed, isColorSpace, isContainer, isEmptyContainer, isFieldEditable, isFieldMixed, isJumpable, isKeyEditable, isLayerColumn, isMixedValue, isOrphaned, isTreeContainer, isValidHex, isViewStateOp, keyRefId, layersManifest, layersPanel, liveEdges, makeColorValue, matchesFilter, messagesOf, mirrorTangent, nodeBounds, nodegraphManifest, nodegraphPanel, normalizeColorInput, normalizeHistoryState, normalizeKindKey, normalizeNumeric, normalizeRanges, normalizeSchema, normalizeTree, nudgeValue, oklchToRgb, parseCssColor, parseHexColor, parseNumeric, passesFilter, patternError, portHasRoom, portRefId, positionToValue, projectRows, projectSections, rangeBetween, resolveDropTarget, resolveIconName, rgbToHex, rgbToHsl, rgbToHsv, rgbToOklch, rgbaToCssHex, roundRgb, rowIndexOf, rowIndexOfEntry, safeAddColorStop, safeAddColorStops, sameKey, sampleChannel, scrubValue, segmentsAround, solveBezierT, sortThreads, surfaceChanged, tangentsForMode, tangentsToControlPoints, toViewportCoords, totalCount, treeManifest, treePanel, usesLogScale, valueExtent, valueToPosition, valuesEqual, viewportManifest, viewportPanel, visibleEdges, walkTree, wheelZoomFactor, zoomAboutCursor, zoomTimeAboutCursor, zoomValueAboutCursor };
6730
+ export { type BlendModeGroup, type BlendModeOption, type Box, COLOR_SPACES, COMMENTS_PANEL_ID, CURVE_PANEL_ID, type ChannelId, ColorPanelController, type ColorPanelControllerOptions, type ColorPanelSerialized, ColorPanelView, type ColorPanelViewProps, type ColorSpace, type ColorStopSink, type ColorToken, CommentsController, type CommentsControllerOptions, type CommentsHostBridge, type CommentsPanelState, CommentsPanelView, type CommentsPanelViewProps, type CommentsRenderContext, type CommentsThreadView, type CommentsViewState, type ConnectRules, type ConnectVerdict, type CreateColorPanelOptions, type CreateCommentsPanelOptions, type CreateCurvePanelOptions, type CreateFindPanelOptions, type CreateHistoryPanelOptions, type CreateInspectorPanelOptions, type CreateLayersPanelOptions, type CreateNodeGraphPanelOptions, type CreateTreePanelOptions, type CreateViewportPanelOptions, CurveController, type CurveControllerOptions, type CurveDragKind, type CurveDragState, type CurveHostBridge, type CurvePanelState, CurvePanelView, type CurvePanelViewProps, type CurvePreview, type CurveRenderConfig, type CurveRenderContext, type CurveViewState, DEFAULT_BLEND_MODES, DEFAULT_CURVE_ZOOM, DEFAULT_GRAPH_ZOOM, DEFAULT_ICON_MAP, DEFAULT_ORIGINAL_LABEL, type DropInput, EASING_PRESETS, EDIT_SPACES, EMPTY_HISTORY, EMPTY_SCHEMA, EMPTY_TREE, EMPTY_TREE_SOURCE, FIND_PANEL_ID, FindController, type FindControllerOptions, type FindHostBridge, type FindPanelState, FindPanelView, type FindPanelViewProps, type FindRenderContext, type FindViewState, type FlatRow, type FlattenOptions, GENERIC_ICON, GraphController, type GraphControllerOptions, type GraphDragKind, type GraphDragState, type GraphHostBridge, type GraphPanelState, type GraphPreview, type GraphRenderConfig, type GraphRenderContext, type GraphViewState, BEHAVIOURS as HISTORY_BEHAVIOURS, HISTORY_DECLARATION, type HistoryKeyEvent, HistoryPanelController, type HistoryPanelControllerOptions, type HistoryPanelSerialized, HistoryPanelView, type HistoryPanelViewProps, type ProjectOptions as HistoryProjectOptions, type HistoryRow, type HistoryUiIntent, type HistoryViewRow, type HistoryViewState, type Hsl, type Hsv, IMPLEMENTED_TREE_MODES, BEHAVIOURS$1 as INSPECTOR_BEHAVIOURS, INSPECTOR_DECLARATION, type InspectorKeyEvent, InspectorPanelController, type InspectorPanelControllerOptions, type InspectorPanelSerialized, InspectorPanelView, type InspectorPanelViewProps, type ProjectOptions$1 as InspectorProjectOptions, type InspectorUiIntent, type InspectorViewField, type InspectorViewSection, type InspectorViewState, LAYER_COLUMNS, type LayerColumn, type LayersKeyEvent, LayersPanelController, type LayersPanelControllerOptions, type LayersPanelSerialized, LayersPanelView, type LayersPanelViewProps, MIXED, NODEGRAPH_PANEL_ID, NodeGraphPanelView, type NodeGraphPanelViewProps, type NumericConstraints, type OklchDisplay, type ParseResult, type ProjectedSection, type Rgba, type ScrubOptions, type SelectMods, TREE_PANEL_ID, type TangentEdit, Thumbnail, type ThumbnailProps, TreeController, type TreeControllerOptions, type TreeHostBridge, TreeIcon, type TreeKeyEvent, type TreePanelState, TreePanelView, type TreePanelViewProps, type TreeRenderContext, type TreeRow, type TreeViewState, VIEWPORT_PANEL_ID, VIEWPORT_SLOTS, VIEW_STATE_OPS, ViewportController, type ViewportControllerOptions, type ViewportHostBridge, type ViewportPanelState, ViewportPanelView, type ViewportPanelViewProps, type ViewportRenderContext, type ViewportViewState, type XenoAddMenuItem, type XenoAnchorState, type XenoColorValue, type XenoCommentAuthor, type XenoCommentFilter, type XenoCommentMessage, type XenoCommentOp, type XenoCommentReaction, type XenoCommentSort, type XenoCommentThread, type XenoCommitPolicy, type XenoContextMenuRequest, type XenoCurveChannel, type XenoCurveInterpolation, type XenoCurveKey, type XenoCurveKeyRef, type XenoCurveOp, type XenoCurvePoint, XenoCurveScale, type XenoCurveScaleGeometry, type XenoCurveScaleState, type XenoCurveSelection, type XenoCurveSet, type XenoCurveViewport, type XenoCurveZoom, type XenoEasingPreset, type XenoEdge, type XenoFieldAnim, type XenoFieldFocus, type XenoFieldOption, type XenoFieldToken, type XenoFieldType, type XenoFieldValue, type XenoFindMatch, type XenoFindNavigate, type XenoFindOptions, type XenoFindQuery, type XenoFindReplace, type XenoFindResults, type XenoFindStatus, type XenoGradient, type XenoGraph, type XenoGraphOp, XenoGraphScale, type XenoGraphScaleGeometry, type XenoGraphScaleState, type XenoGraphSelection, type XenoGraphViewport, type XenoGraphZoom, type XenoHistoryEntry, type XenoHistoryIntent, type XenoHistoryMemory, type XenoHistoryOrder, type XenoHistoryScope, type XenoHistorySnapshot, type XenoHistorySource, type XenoHistoryState, type XenoHistoryStatus, type XenoInspectorEdit, type XenoInspectorField, type XenoInspectorSchema, type XenoInspectorSection, type XenoInspectorTarget, type XenoInspectorToken, type XenoKeyframeKind, type XenoLayerAdornment, type XenoLayerCap, type XenoLayerKind, type XenoLayerNode, type XenoLayerOp, type XenoLayerTree, type XenoNavigateRequest, type XenoNode, XenoNodeIndex, type XenoPort, type XenoPortDirection, type XenoPortRef, type XenoSectionAction, type XenoTangent, type XenoTangentMode, type XenoTangentSide, type XenoThreadActivate, type XenoThumbnailRequest, type XenoThumbnailResponse, type XenoTreeAction, type XenoTreeBadge, type XenoTreeCaps, type XenoTreeChildState, type XenoTreeChildrenResponse, type XenoTreeError, type XenoTreeGlyph, type XenoTreeIcon, type XenoTreeInvalidate, type XenoTreeMode, type XenoTreeModifiers, type XenoTreeNode, type XenoTreeNodeKind, type XenoTreeOp, type XenoTreeReveal, type XenoTreeSource, type XenoTreeSourceKind, type XenoTreeSourceState, type XenoViewportClient, type XenoViewportKey, type XenoViewportPointer, type XenoViewportSlot, type XenoViewportStats, type XenoViewportSurface, allFields, allIds, anchorStateOf, appliedCount, applyHistoryUi, applyInspectorUi, applyPrecision, applyTangentDrag, ariaSliderProps, boxesIntersect, canConnect, canRedo, canUndo, childStateOf, clamp, clampAlpha, clampTangent, collectDescendants, colorManifest, colorPanel, commentsManifest, commentsPanel, commitPolicyOf, componentsForSpace, computeSurfaceSize, constraintsOf, countIsMeaningful, createColorPanel, createCommentsPanel, createCurvePanel, createFindPanel, createHistoryPanel, createInspectorPanel, createLayersPanel, createNodeGraphPanel, createTreePanel, createViewportPanel, createsCycle, currentRowIndex, curveManifest, curvePanel, defaultIconFor, displayOrder, distanceToEdge, easeAt, easingPreset, edgeBounds, edgeKey, edgePath, edgesToReplace, edgesTouching, evaluateChannel, fieldMatches, findField, findManifest, findPanel, findPort, findSectionOf, fitToBounds, fitValueRange, flattenVisible, focusOrder, formatAge, formatNumeric, getAncestors, graphBounds, groupMatches, hasCap, hasDraggableTangents, hasTreeCap, hexFromHsv, highlightSegments, historyManifest, historyPanel, historyRuntimeComponents, historyViewManifest, historyViewState, hslToRgb, hsvFromHex, hsvToRgb, inspectorManifest, inspectorPanel, inspectorRuntimeComponents, inspectorViewManifest, inspectorViewState, interpolateSegment, isAncestorOf, isAnimated, isCollapsed, isColorSpace, isContainer, isEmptyContainer, isFieldEditable, isFieldMixed, isJumpable, isKeyEditable, isLayerColumn, isMixedValue, isOrphaned, isTreeContainer, isValidHex, isViewStateOp, keyRefId, layersManifest, layersPanel, liveEdges, makeColorValue, matchesFilter, messagesOf, mirrorTangent, nodeBounds, nodegraphManifest, nodegraphPanel, normalizeColorInput, normalizeHistoryState, normalizeKindKey, normalizeNumeric, normalizeRanges, normalizeSchema, normalizeTree, nudgeValue, oklchToRgb, parseCssColor, parseHexColor, parseNumeric, passesFilter, patternError, portHasRoom, portRefId, positionToValue, projectRows, projectSections, rangeBetween, resolveDropTarget, resolveIconName, rgbToHex, rgbToHsl, rgbToHsv, rgbToOklch, rgbaToCssHex, roundRgb, rowIndexOf, rowIndexOfEntry, safeAddColorStop, safeAddColorStops, sameKey, sampleChannel, scrubValue, segmentsAround, solveBezierT, sortThreads, surfaceChanged, tangentsForMode, tangentsToControlPoints, toViewportCoords, totalCount, treeManifest, treePanel, usesLogScale, valueExtent, valueToPosition, valuesEqual, viewportManifest, viewportPanel, visibleEdges, walkTree, wheelZoomFactor, zoomAboutCursor, zoomTimeAboutCursor, zoomValueAboutCursor };
@@ -1871,8 +1871,8 @@ function constraintsOf(field) {
1871
1871
  scale: field.scale
1872
1872
  };
1873
1873
  }
1874
- function parseNumeric(text2) {
1875
- const trimmed = String(text2).trim();
1874
+ function parseNumeric(text3) {
1875
+ const trimmed = String(text3).trim();
1876
1876
  if (trimmed.length === 0) return { ok: false, reason: "empty" };
1877
1877
  const match = /^[+-]?(\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/.exec(trimmed);
1878
1878
  if (!match) return { ok: false, reason: "nan" };
@@ -1897,8 +1897,8 @@ function normalizeNumeric(value, c) {
1897
1897
  function formatNumeric(value, field) {
1898
1898
  if (!Number.isFinite(value)) return "";
1899
1899
  const precision = field.precision;
1900
- const text2 = typeof precision === "number" && Number.isFinite(precision) ? value.toFixed(Math.max(0, Math.floor(precision))) : String(value);
1901
- return field.unit ? `${text2}${field.unit}` : text2;
1900
+ const text3 = typeof precision === "number" && Number.isFinite(precision) ? value.toFixed(Math.max(0, Math.floor(precision))) : String(value);
1901
+ return field.unit ? `${text3}${field.unit}` : text3;
1902
1902
  }
1903
1903
  function usesLogScale(c) {
1904
1904
  return c.scale === "log" && typeof c.min === "number" && typeof c.max === "number" && c.min > 0 && c.max > c.min;
@@ -2232,44 +2232,44 @@ var InspectorPanelController = class {
2232
2232
  if (!field || !isFieldEditable(field)) return;
2233
2233
  const mixed = isFieldMixed(field);
2234
2234
  const value = this.getFieldValue(fieldId);
2235
- const text2 = mixed ? "" : field.type === "number" && typeof value === "number" ? formatNumeric(value, field) : value === void 0 || value === null ? "" : String(value);
2236
- this.drafts.set(fieldId, { text: text2, original: value });
2235
+ const text3 = mixed ? "" : field.type === "number" && typeof value === "number" ? formatNumeric(value, field) : value === void 0 || value === null ? "" : String(value);
2236
+ this.drafts.set(fieldId, { text: text3, original: value });
2237
2237
  this.focusedFieldId = fieldId;
2238
2238
  this.emitFieldFocus(fieldId);
2239
2239
  this.notify();
2240
2240
  }
2241
2241
  /** Update the draft text (typing). Emits nothing under the `blur` policy. */
2242
- setDraft(fieldId, text2) {
2242
+ setDraft(fieldId, text3) {
2243
2243
  const draft = this.drafts.get(fieldId);
2244
2244
  if (!draft) {
2245
- this.drafts.set(fieldId, { text: text2, original: this.getFieldValue(fieldId) });
2245
+ this.drafts.set(fieldId, { text: text3, original: this.getFieldValue(fieldId) });
2246
2246
  } else {
2247
- draft.text = text2;
2247
+ draft.text = text3;
2248
2248
  }
2249
2249
  const field = this.getField(fieldId);
2250
2250
  if (field && commitPolicyOf(field) === "live") {
2251
- const parsed = this.parseDraft(fieldId, text2);
2251
+ const parsed = this.parseDraft(fieldId, text3);
2252
2252
  if (parsed.ok) this.emitSet(fieldId, parsed.value);
2253
2253
  }
2254
2254
  this.notify();
2255
2255
  }
2256
2256
  /** Parse a draft string into a field-appropriate value. */
2257
- parseDraft(fieldId, text2) {
2257
+ parseDraft(fieldId, text3) {
2258
2258
  const field = this.getField(fieldId);
2259
2259
  if (!field) return { ok: false };
2260
2260
  if (field.type === "number") {
2261
- const parsed = parseNumeric(text2);
2261
+ const parsed = parseNumeric(text3);
2262
2262
  if (!parsed.ok) return { ok: false };
2263
2263
  return { ok: true, value: normalizeNumeric(parsed.value, constraintsOf(field)) };
2264
2264
  }
2265
2265
  if (field.type === "json") {
2266
2266
  try {
2267
- return { ok: true, value: JSON.parse(text2) };
2267
+ return { ok: true, value: JSON.parse(text3) };
2268
2268
  } catch {
2269
2269
  return { ok: false };
2270
2270
  }
2271
2271
  }
2272
- return { ok: true, value: text2 };
2272
+ return { ok: true, value: text3 };
2273
2273
  }
2274
2274
  /**
2275
2275
  * Commit the draft (Enter / blur). Invalid input reverts instead of committing garbage.
@@ -3244,7 +3244,7 @@ function NumberWidget({ field, controller, component }) {
3244
3244
  },
3245
3245
  [controller, editable, field.id, component]
3246
3246
  );
3247
- const text2 = component !== void 0 ? (() => {
3247
+ const text3 = component !== void 0 ? (() => {
3248
3248
  const raw = controller.getFieldValue(field.id);
3249
3249
  const v = Array.isArray(raw) ? raw[component] : void 0;
3250
3250
  return typeof v === "number" ? formatNumeric(v, field) : "";
@@ -3256,7 +3256,7 @@ function NumberWidget({ field, controller, component }) {
3256
3256
  Input2,
3257
3257
  {
3258
3258
  inputMode: "decimal",
3259
- value: text2,
3259
+ value: text3,
3260
3260
  placeholder: mixed ? controller.getMixedPlaceholder() : field.placeholder,
3261
3261
  mixed,
3262
3262
  readOnly: !editable,
@@ -3474,7 +3474,7 @@ function ActionGlyph({ glyph }) {
3474
3474
  return /* @__PURE__ */ jsx6("span", { "aria-hidden": true, children: glyph });
3475
3475
  }
3476
3476
  function SectionView({ section, controller }) {
3477
- const ui2 = (intent) => applyInspectorUi(controller, intent);
3477
+ const ui3 = (intent) => applyInspectorUi(controller, intent);
3478
3478
  const hasActions = section.actions.length > 0 || section.hasAddMenu;
3479
3479
  return /* @__PURE__ */ jsxs5(
3480
3480
  Section,
@@ -3483,13 +3483,13 @@ function SectionView({ section, controller }) {
3483
3483
  flush: true,
3484
3484
  collapsible: section.collapsible,
3485
3485
  collapsed: section.collapsed,
3486
- onCollapsedChange: () => ui2({ kind: "toggleSectionCollapsed", sectionId: section.id }),
3486
+ onCollapsedChange: () => ui3({ kind: "toggleSectionCollapsed", sectionId: section.id }),
3487
3487
  enabled: section.enabled,
3488
- onEnabledChange: () => ui2({ kind: "toggleSectionEnabled", sectionId: section.id }),
3488
+ onEnabledChange: () => ui3({ kind: "toggleSectionEnabled", sectionId: section.id }),
3489
3489
  badge: section.badge ? /* @__PURE__ */ jsx6(Badge2, { children: section.badge }) : null,
3490
3490
  actions: hasActions ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
3491
- section.actions.map((action) => /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(ActionGlyph, { glyph: action.glyph }), label: action.label, disabled: action.disabled, onClick: () => ui2({ kind: "runAction", sectionId: section.id, actionId: action.id }) }, action.id)),
3492
- section.hasAddMenu ? /* @__PURE__ */ jsx6(Select2, { size: "sm", placeholder: "\uFF0B", options: section.addOptions, value: "", label: section.addLabel, onChange: (id) => ui2({ kind: "addItem", sectionId: section.id, itemId: id }) }) : null
3491
+ section.actions.map((action) => /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(ActionGlyph, { glyph: action.glyph }), label: action.label, disabled: action.disabled, onClick: () => ui3({ kind: "runAction", sectionId: section.id, actionId: action.id }) }, action.id)),
3492
+ section.hasAddMenu ? /* @__PURE__ */ jsx6(Select2, { size: "sm", placeholder: "\uFF0B", options: section.addOptions, value: "", label: section.addLabel, onChange: (id) => ui3({ kind: "addItem", sectionId: section.id, itemId: id }) }) : null
3493
3493
  ] }) : null,
3494
3494
  children: [
3495
3495
  section.showEmptyHint ? /* @__PURE__ */ jsx6(Stack2, { pad: "inset", children: /* @__PURE__ */ jsx6(Text3, { role: "caption", children: section.emptyHint }) }) : null,
@@ -3499,7 +3499,7 @@ function SectionView({ section, controller }) {
3499
3499
  );
3500
3500
  }
3501
3501
  function FieldRow({ row, controller }) {
3502
- const ui2 = (intent) => applyInspectorUi(controller, intent);
3502
+ const ui3 = (intent) => applyInspectorUi(controller, intent);
3503
3503
  return /* @__PURE__ */ jsxs5(Fragment3, { children: [
3504
3504
  /* @__PURE__ */ jsxs5(
3505
3505
  Field,
@@ -3507,19 +3507,19 @@ function FieldRow({ row, controller }) {
3507
3507
  label: row.label,
3508
3508
  title: row.title,
3509
3509
  focused: row.focused,
3510
- onLabelClick: () => ui2({ kind: "focusField", fieldId: row.id }),
3511
- onContextMenu: (x, y) => ui2({ kind: "contextMenu", fieldId: row.id, x, y }),
3510
+ onLabelClick: () => ui3({ kind: "focusField", fieldId: row.id }),
3511
+ onContextMenu: (x, y) => ui3({ kind: "contextMenu", fieldId: row.id, x, y }),
3512
3512
  leading: row.showKeyframes ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
3513
- /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(StopwatchIcon, {}), label: "Toggle animation", active: row.animated, onClick: () => ui2({ kind: "keyframe", fieldId: row.id, op: "toggleAnim" }) }),
3514
- row.animated ? /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(PrevIcon, {}), label: "Previous keyframe", disabled: row.prevDisabled, onClick: () => ui2({ kind: "keyframe", fieldId: row.id, op: "prev" }) }) : null,
3515
- row.animated ? /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(DiamondIcon, { filled: row.onKeyframe }), label: row.keyframeLabel, onClick: () => ui2({ kind: "keyframe", fieldId: row.id, op: row.keyframeOp }) }) : null,
3516
- row.animated ? /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(NextIcon, {}), label: "Next keyframe", disabled: row.nextDisabled, onClick: () => ui2({ kind: "keyframe", fieldId: row.id, op: "next" }) }) : null
3513
+ /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(StopwatchIcon, {}), label: "Toggle animation", active: row.animated, onClick: () => ui3({ kind: "keyframe", fieldId: row.id, op: "toggleAnim" }) }),
3514
+ row.animated ? /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(PrevIcon, {}), label: "Previous keyframe", disabled: row.prevDisabled, onClick: () => ui3({ kind: "keyframe", fieldId: row.id, op: "prev" }) }) : null,
3515
+ row.animated ? /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(DiamondIcon, { filled: row.onKeyframe }), label: row.keyframeLabel, onClick: () => ui3({ kind: "keyframe", fieldId: row.id, op: row.keyframeOp }) }) : null,
3516
+ row.animated ? /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(NextIcon, {}), label: "Next keyframe", disabled: row.nextDisabled, onClick: () => ui3({ kind: "keyframe", fieldId: row.id, op: "next" }) }) : null
3517
3517
  ] }) : null,
3518
3518
  trailing: /* @__PURE__ */ jsxs5(Fragment3, { children: [
3519
- row.showEasing ? /* @__PURE__ */ jsx6(Select2, { size: "sm", options: row.easingOptions, value: row.easing, label: "Easing", onChange: (v) => ui2({ kind: "setEasing", fieldId: row.id, easing: v }) }) : null,
3519
+ row.showEasing ? /* @__PURE__ */ jsx6(Select2, { size: "sm", options: row.easingOptions, value: row.easing, label: "Easing", onChange: (v) => ui3({ kind: "setEasing", fieldId: row.id, easing: v }) }) : null,
3520
3520
  row.showKeyframes ? /* @__PURE__ */ jsx6(Badge2, { size: "sm", children: row.keyframeChip }) : null,
3521
- row.showToken ? /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(LinkIcon, {}), label: row.tokenActionLabel, active: row.bound, onClick: () => ui2({ kind: "bindToken", fieldId: row.id }) }) : null,
3522
- row.showReset ? /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(ResetIcon, {}), label: "Reset to default", onClick: () => ui2({ kind: "resetField", fieldId: row.id }) }) : null
3521
+ row.showToken ? /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(LinkIcon, {}), label: row.tokenActionLabel, active: row.bound, onClick: () => ui3({ kind: "bindToken", fieldId: row.id }) }) : null,
3522
+ row.showReset ? /* @__PURE__ */ jsx6(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx6(ResetIcon, {}), label: "Reset to default", onClick: () => ui3({ kind: "resetField", fieldId: row.id }) }) : null
3523
3523
  ] }),
3524
3524
  children: [
3525
3525
  row.bound ? /* @__PURE__ */ jsx6(Badge2, { title: row.tokenTitle, children: row.tokenLabel }) : null,
@@ -4539,6 +4539,231 @@ var HistoryPanelController = class {
4539
4539
 
4540
4540
  // src/edit/history/react/HistoryPanelView.tsx
4541
4541
  import { useCallback as useCallback4, useEffect as useEffect3, useRef as useRef4, useSyncExternalStore as useSyncExternalStore3 } from "react";
4542
+
4543
+ // src/edit/history/react/format.ts
4544
+ function formatTime(at) {
4545
+ const date = typeof at === "number" ? new Date(at) : new Date(at);
4546
+ if (Number.isNaN(date.getTime())) return typeof at === "string" ? at : "";
4547
+ return date.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit" });
4548
+ }
4549
+
4550
+ // src/edit/history/declaration.ts
4551
+ function historyViewState(c) {
4552
+ const rows = c.getRows();
4553
+ const window_ = c.getWindow();
4554
+ const rowHeight = c.getRowHeight();
4555
+ const memory = c.getMemory();
4556
+ const focused = c.getFocused();
4557
+ const showIcons = c.areIconsShown();
4558
+ const showSource = c.isSourceShown();
4559
+ const showTime = c.areTimestampsShown();
4560
+ const jumpAllowed = c.isJumpAllowed();
4561
+ return {
4562
+ canUndo: c.canUndo(),
4563
+ canRedo: c.canRedo(),
4564
+ cannotUndo: !c.canUndo(),
4565
+ cannotRedo: !c.canRedo(),
4566
+ searchShown: c.isSearchShown(),
4567
+ filter: c.getFilter(),
4568
+ counter: `${c.getAppliedCount()} / ${c.getTotalCount()}`,
4569
+ clearAllowed: c.isClearAllowed(),
4570
+ confirmingClear: c.isConfirmingClear(),
4571
+ pruned: c.isPruned(),
4572
+ totalHeight: window_.totalHeight,
4573
+ offsetTop: window_.offsetTop,
4574
+ rows: c.getWindowRows().map((row) => {
4575
+ const entry = row.entry;
4576
+ const pending = entry?.status === "pending";
4577
+ const source = entry?.source;
4578
+ return {
4579
+ key: row.entryId ?? "__original__",
4580
+ entryId: row.entryId,
4581
+ label: row.label,
4582
+ meta: row.kind === "entry" ? row.ordinal : void 0,
4583
+ current: row.current,
4584
+ future: row.future,
4585
+ focused: focused === row.entryId,
4586
+ jumpable: jumpAllowed && entry?.caps?.jumpable !== false,
4587
+ showIcon: showIcons,
4588
+ hideIcon: !showIcons,
4589
+ iconName: row.kind === "original" ? "original" : c.getIconName(entry?.kind),
4590
+ pending,
4591
+ failed: entry?.status === "failed",
4592
+ showSource: showSource && !!source && source !== "user",
4593
+ sourceGlyph: source === "agent" ? "AI" : "S",
4594
+ sourceTitle: `Source: ${source ?? ""}`,
4595
+ showCoalesced: !!entry?.coalesced && entry.coalesced > 1,
4596
+ coalescedText: `\xD7${entry?.coalesced ?? 0}`,
4597
+ coalescedTitle: `${entry?.coalesced ?? 0} actions coalesced`,
4598
+ showTime: showTime && entry?.at !== void 0,
4599
+ time: entry?.at !== void 0 ? formatTime(entry.at) : "",
4600
+ height: rowHeight,
4601
+ cancelId: pending ? entry?.id : void 0
4602
+ };
4603
+ }),
4604
+ empty: rows.length === 0,
4605
+ hasMemory: !!memory,
4606
+ memoryText: memory ? `${memory.usedMB.toFixed(1)} MB${memory.limitMB ? ` / ${memory.limitMB} MB` : ""}` : "",
4607
+ memoryDisk: memory?.onDiskCount !== void 0 ? `${memory.onDiskCount} on disk` : void 0
4608
+ };
4609
+ }
4610
+ function applyHistoryUi(c, intent) {
4611
+ switch (intent.kind) {
4612
+ case "undo":
4613
+ c.undo();
4614
+ break;
4615
+ case "redo":
4616
+ c.redo();
4617
+ break;
4618
+ case "filter":
4619
+ c.setFilter(intent.value);
4620
+ break;
4621
+ case "requestClear":
4622
+ c.requestClear();
4623
+ break;
4624
+ case "confirmClear":
4625
+ c.confirmClearNow();
4626
+ break;
4627
+ case "cancelClear":
4628
+ c.cancelClear();
4629
+ break;
4630
+ case "jump":
4631
+ c.jumpTo(intent.entryId);
4632
+ break;
4633
+ case "hover":
4634
+ c.setHovered(intent.entryId);
4635
+ break;
4636
+ case "contextMenu":
4637
+ c.requestContextMenu(intent.entryId, intent.x, intent.y);
4638
+ break;
4639
+ case "cancelPending":
4640
+ c.cancelPending(intent.entryId);
4641
+ break;
4642
+ }
4643
+ }
4644
+ var historyViewManifest = {
4645
+ id: historyManifest.id,
4646
+ version: "1.0.0",
4647
+ title: "History",
4648
+ category: "edit",
4649
+ layout: { slot: "side" },
4650
+ inputs: [{ id: "view", type: "object", label: "View state", description: "The HistoryViewState the runtime derives from the controller on every draw." }],
4651
+ outputs: [{ id: "ui", type: "object", label: "UI intent", description: "{ kind, entryId?, value?, x?, y? } \u2014 applied by the runtime to the controller." }],
4652
+ commands: []
4653
+ };
4654
+ var EMPTY2 = { canUndo: false, canRedo: false, cannotUndo: true, cannotRedo: true, searchShown: true, filter: "", counter: "0 / 0", clearAllowed: false, confirmingClear: false, pruned: false, totalHeight: 0, offsetTop: 0, rows: [], empty: true, hasMemory: false, memoryText: "" };
4655
+ var BEHAVIOURS2 = {
4656
+ "edit/historyPanelView": (inputs) => inputs.view ?? EMPTY2
4657
+ };
4658
+ var text2 = (b) => ({ component: "text", props: { text: b } });
4659
+ var ui2 = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
4660
+ var HISTORY_DECLARATION = {
4661
+ format: "xeno.block@1",
4662
+ manifest: historyViewManifest,
4663
+ behaviour: "edit/historyPanelView",
4664
+ composition: {
4665
+ component: "chrome/Column",
4666
+ props: { className: { value: "xeno-history-panel" } },
4667
+ children: [
4668
+ {
4669
+ component: "chrome/Toolbar",
4670
+ props: {
4671
+ left: {
4672
+ node: {
4673
+ component: "fragment",
4674
+ children: [
4675
+ { component: "chrome/IconButton", props: { size: { value: "sm" }, icon: { node: { component: "history/UndoIcon" } }, label: { value: "Undo" }, disabled: { input: "view.cannotUndo" } }, on: { onClick: ui2("undo") } },
4676
+ { component: "chrome/IconButton", props: { size: { value: "sm" }, icon: { node: { component: "history/RedoIcon" } }, label: { value: "Redo" }, disabled: { input: "view.cannotRedo" } }, on: { onClick: ui2("redo") } }
4677
+ ]
4678
+ }
4679
+ },
4680
+ right: {
4681
+ node: {
4682
+ component: "fragment",
4683
+ children: [
4684
+ { component: "chrome/Text", props: { role: { value: "number" } }, children: [text2({ input: "view.counter" })] },
4685
+ { component: "chrome/IconButton", when: { input: "view.clearAllowed" }, props: { size: { value: "sm" }, icon: { node: { component: "history/TrashIcon" } }, label: { value: "Clear history" } }, on: { onClick: ui2("requestClear") } }
4686
+ ]
4687
+ }
4688
+ }
4689
+ },
4690
+ children: [
4691
+ { component: "chrome/SearchField", when: { input: "view.searchShown" }, props: { value: { input: "view.filter" }, placeholder: { value: "Search history" }, label: { value: "Search history" } }, on: { onChange: ui2("filter", { value: { arg: "" } }) } }
4692
+ ]
4693
+ },
4694
+ {
4695
+ component: "chrome/InlineConfirm",
4696
+ when: { input: "view.confirmingClear" },
4697
+ props: { message: { value: "Clear all history?" }, label: { value: "Confirm clear history" }, confirmLabel: { value: "Clear" } },
4698
+ on: { onConfirm: ui2("confirmClear"), onCancel: ui2("cancelClear") }
4699
+ },
4700
+ { component: "chrome/Text", when: { input: "view.pruned" }, props: { role: { value: "caption" } }, children: [text2({ value: "Earlier history discarded (limit reached)" })] },
4701
+ {
4702
+ component: "history/Scroller",
4703
+ children: [
4704
+ {
4705
+ component: "chrome/RowList",
4706
+ props: { role: { value: "listbox" }, "aria-label": { value: "History" } },
4707
+ children: [
4708
+ {
4709
+ component: "chrome/VirtualWindow",
4710
+ props: { totalHeight: { input: "view.totalHeight" }, offsetTop: { input: "view.offsetTop" } },
4711
+ children: [
4712
+ {
4713
+ component: "chrome/Row",
4714
+ each: { input: "view.rows", key: "key" },
4715
+ props: {
4716
+ height: { item: "height" },
4717
+ selected: { item: "current" },
4718
+ focused: { item: "focused" },
4719
+ struck: { item: "future" },
4720
+ noIcon: { item: "hideIcon" },
4721
+ interactive: { item: "jumpable" },
4722
+ icon: { node: { component: "history/EntryIcon", props: { name: { item: "iconName" } } } },
4723
+ label: { item: "label" },
4724
+ meta: { item: "meta" },
4725
+ "data-history-row": { item: "key" },
4726
+ title: { item: "label" },
4727
+ trailing: {
4728
+ node: {
4729
+ component: "fragment",
4730
+ children: [
4731
+ { component: "history/PendingGlyph", when: { item: "pending" } },
4732
+ { component: "chrome/Badge", when: { item: "failed" }, props: { size: { value: "sm" }, tone: { value: "error" } }, children: [text2({ value: "failed" })] },
4733
+ { component: "chrome/Badge", when: { item: "showSource" }, props: { size: { value: "sm" }, title: { item: "sourceTitle" } }, children: [text2({ item: "sourceGlyph" })] },
4734
+ { component: "chrome/Badge", when: { item: "showCoalesced" }, props: { size: { value: "sm" }, title: { item: "coalescedTitle" } }, children: [text2({ item: "coalescedText" })] },
4735
+ { component: "chrome/Text", when: { item: "showTime" }, props: { role: { value: "meta" } }, children: [text2({ item: "time" })] },
4736
+ { component: "history/CancelButton", when: { item: "pending" }, props: { entryId: { item: "cancelId" } } }
4737
+ ]
4738
+ }
4739
+ }
4740
+ },
4741
+ on: {
4742
+ onClick: ui2("jump", { entryId: { item: "entryId" } }),
4743
+ onMouseEnter: ui2("hover", { entryId: { item: "entryId" } }),
4744
+ onContextMenuAt: ui2("contextMenu", { entryId: { item: "entryId" }, x: { arg: "" }, y: { arg: "", index: 1 } })
4745
+ }
4746
+ }
4747
+ ]
4748
+ }
4749
+ ]
4750
+ },
4751
+ { component: "chrome/EmptyState", when: { input: "view.empty" }, props: { title: { value: "No history" } } }
4752
+ ]
4753
+ },
4754
+ {
4755
+ component: "chrome/StatusBar",
4756
+ when: { input: "view.hasMemory" },
4757
+ props: {
4758
+ left: { node: { component: "chrome/Text", props: { role: { value: "number" } }, children: [text2({ input: "view.memoryText" })] } },
4759
+ right: { node: { component: "chrome/Text", when: { input: "view.memoryDisk" }, props: { role: { value: "meta" } }, children: [text2({ input: "view.memoryDisk" })] } }
4760
+ }
4761
+ }
4762
+ ]
4763
+ }
4764
+ };
4765
+
4766
+ // src/edit/history/react/HistoryPanelView.tsx
4542
4767
  import { Badge as Badge3, Column as Column3, EmptyState as EmptyState3, IconButton as IconButton4, InlineConfirm, RowList as RowList2, Row as Row2, ScrollArea as ScrollArea3, SearchField as SearchField3, StatusBar as StatusBar2, Text as Text4, Toolbar as Toolbar2, VirtualWindow as VirtualWindow2 } from "@xenosystem/components/chrome";
4543
4768
 
4544
4769
  // src/edit/history/react/icons.tsx
@@ -4640,12 +4865,34 @@ function HistoryPanelView({ controller }) {
4640
4865
  const subscribe = useCallback4((cb) => controller.subscribe(cb), [controller]);
4641
4866
  const getSnapshot = useCallback4(() => controller.getRevision(), [controller]);
4642
4867
  useSyncExternalStore3(subscribe, getSnapshot, getSnapshot);
4868
+ const view = historyViewState(controller);
4869
+ const ui3 = (intent) => applyHistoryUi(controller, intent);
4870
+ return /* @__PURE__ */ jsxs7(Column3, { className: "xeno-history-panel", children: [
4871
+ /* @__PURE__ */ jsx8(
4872
+ Toolbar2,
4873
+ {
4874
+ left: /* @__PURE__ */ jsxs7(Fragment4, { children: [
4875
+ /* @__PURE__ */ jsx8(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx8(UndoIcon, {}), label: "Undo", disabled: view.cannotUndo, onClick: () => ui3({ kind: "undo" }) }),
4876
+ /* @__PURE__ */ jsx8(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx8(RedoIcon, {}), label: "Redo", disabled: view.cannotRedo, onClick: () => ui3({ kind: "redo" }) })
4877
+ ] }),
4878
+ right: /* @__PURE__ */ jsxs7(Fragment4, { children: [
4879
+ /* @__PURE__ */ jsx8(Text4, { role: "number", children: view.counter }),
4880
+ view.clearAllowed ? /* @__PURE__ */ jsx8(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx8(TrashIcon, {}), label: "Clear history", onClick: () => ui3({ kind: "requestClear" }) }) : null
4881
+ ] }),
4882
+ children: view.searchShown ? /* @__PURE__ */ jsx8(SearchField3, { value: view.filter, onChange: (v) => ui3({ kind: "filter", value: v }), placeholder: "Search history", label: "Search history" }) : null
4883
+ }
4884
+ ),
4885
+ view.confirmingClear ? /* @__PURE__ */ jsx8(InlineConfirm, { message: "Clear all history?", label: "Confirm clear history", confirmLabel: "Clear", onConfirm: () => ui3({ kind: "confirmClear" }), onCancel: () => ui3({ kind: "cancelClear" }) }) : null,
4886
+ view.pruned ? /* @__PURE__ */ jsx8(Text4, { role: "caption", children: "Earlier history discarded (limit reached)" }) : null,
4887
+ /* @__PURE__ */ jsxs7(HistoryScroller, { controller, children: [
4888
+ /* @__PURE__ */ jsx8(RowList2, { role: "listbox", "aria-label": "History", children: /* @__PURE__ */ jsx8(VirtualWindow2, { totalHeight: view.totalHeight, offsetTop: view.offsetTop, children: view.rows.map((row) => /* @__PURE__ */ jsx8(HistoryRowView, { row, controller }, row.key)) }) }),
4889
+ view.empty ? /* @__PURE__ */ jsx8(EmptyState3, { title: "No history" }) : null
4890
+ ] }),
4891
+ view.hasMemory ? /* @__PURE__ */ jsx8(StatusBar2, { left: /* @__PURE__ */ jsx8(Text4, { role: "number", children: view.memoryText }), right: view.memoryDisk ? /* @__PURE__ */ jsx8(Text4, { role: "meta", children: view.memoryDisk }) : null }) : null
4892
+ ] });
4893
+ }
4894
+ function HistoryScroller({ controller, children }) {
4643
4895
  const scrollRef = useRef4(null);
4644
- const rows = controller.getRows();
4645
- const window_ = controller.getWindow();
4646
- const windowRows = controller.getWindowRows();
4647
- const rowHeight = controller.getRowHeight();
4648
- const memory = controller.getMemory();
4649
4896
  useEffect3(() => {
4650
4897
  const el = scrollRef.current;
4651
4898
  if (!el) return;
@@ -4665,18 +4912,10 @@ function HistoryPanelView({ controller }) {
4665
4912
  el.scrollTop = controller.getScrollTop();
4666
4913
  }
4667
4914
  });
4668
- const onScroll = useCallback4(
4669
- (e) => controller.setScrollTop(e.currentTarget.scrollTop),
4670
- [controller]
4671
- );
4915
+ const onScroll = useCallback4((e) => controller.setScrollTop(e.currentTarget.scrollTop), [controller]);
4672
4916
  const onKeyDown = useCallback4(
4673
4917
  (e) => {
4674
- const handled = controller.handleKey({
4675
- key: e.key,
4676
- ctrl: e.ctrlKey,
4677
- meta: e.metaKey,
4678
- shift: e.shiftKey
4679
- });
4918
+ const handled = controller.handleKey({ key: e.key, ctrl: e.ctrlKey, meta: e.metaKey, shift: e.shiftKey });
4680
4919
  if (handled) {
4681
4920
  e.preventDefault();
4682
4921
  e.stopPropagation();
@@ -4684,109 +4923,62 @@ function HistoryPanelView({ controller }) {
4684
4923
  },
4685
4924
  [controller]
4686
4925
  );
4687
- return /* @__PURE__ */ jsxs7(Column3, { className: "xeno-history-panel", children: [
4688
- /* @__PURE__ */ jsx8(
4689
- Toolbar2,
4690
- {
4691
- left: /* @__PURE__ */ jsxs7(Fragment4, { children: [
4692
- /* @__PURE__ */ jsx8(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx8(UndoIcon, {}), label: "Undo", disabled: !controller.canUndo(), onClick: () => controller.undo() }),
4693
- /* @__PURE__ */ jsx8(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx8(RedoIcon, {}), label: "Redo", disabled: !controller.canRedo(), onClick: () => controller.redo() })
4694
- ] }),
4695
- right: /* @__PURE__ */ jsxs7(Fragment4, { children: [
4696
- /* @__PURE__ */ jsxs7(Text4, { role: "number", children: [
4697
- controller.getAppliedCount(),
4698
- " / ",
4699
- controller.getTotalCount()
4700
- ] }),
4701
- controller.isClearAllowed() ? /* @__PURE__ */ jsx8(IconButton4, { size: "sm", icon: /* @__PURE__ */ jsx8(TrashIcon, {}), label: "Clear history", onClick: () => controller.requestClear() }) : null
4702
- ] }),
4703
- children: controller.isSearchShown() ? /* @__PURE__ */ jsx8(SearchField3, { value: controller.getFilter(), onChange: (v) => controller.setFilter(v), placeholder: "Search history", label: "Search history" }) : null
4704
- }
4705
- ),
4706
- controller.isConfirmingClear() ? /* @__PURE__ */ jsx8(InlineConfirm, { message: "Clear all history?", label: "Confirm clear history", confirmLabel: "Clear", onConfirm: () => controller.confirmClearNow(), onCancel: () => controller.cancelClear() }) : null,
4707
- controller.isPruned() ? /* @__PURE__ */ jsx8(Text4, { role: "caption", children: "Earlier history discarded (limit reached)" }) : null,
4708
- /* @__PURE__ */ jsxs7(ScrollArea3, { ref: scrollRef, onScroll, onKeyDown, onMouseLeave: () => controller.setHovered(null), tabIndex: 0, children: [
4709
- /* @__PURE__ */ jsx8(RowList2, { role: "listbox", "aria-label": "History", children: /* @__PURE__ */ jsx8(VirtualWindow2, { totalHeight: window_.totalHeight, offsetTop: window_.offsetTop, children: windowRows.map((row) => /* @__PURE__ */ jsx8(
4710
- HistoryRowView,
4711
- {
4712
- row,
4713
- controller,
4714
- rowHeight,
4715
- focused: controller.getFocused() === row.entryId
4716
- },
4717
- row.entryId ?? "__original__"
4718
- )) }) }),
4719
- rows.length === 0 ? /* @__PURE__ */ jsx8(EmptyState3, { title: "No history" }) : null
4720
- ] }),
4721
- memory ? /* @__PURE__ */ jsx8(
4722
- StatusBar2,
4723
- {
4724
- left: /* @__PURE__ */ jsxs7(Text4, { role: "number", children: [
4725
- memory.usedMB.toFixed(1),
4726
- " MB",
4727
- memory.limitMB ? ` / ${memory.limitMB} MB` : ""
4728
- ] }),
4729
- right: memory.onDiskCount !== void 0 ? /* @__PURE__ */ jsxs7(Text4, { role: "meta", children: [
4730
- memory.onDiskCount,
4731
- " on disk"
4732
- ] }) : null
4926
+ return /* @__PURE__ */ jsx8(ScrollArea3, { ref: scrollRef, onScroll, onKeyDown, onMouseLeave: () => controller.setHovered(null), tabIndex: 0, children });
4927
+ }
4928
+ function HistoryCancelButton({ entryId, controller }) {
4929
+ return /* @__PURE__ */ jsx8(
4930
+ IconButton4,
4931
+ {
4932
+ size: "sm",
4933
+ icon: /* @__PURE__ */ jsx8(XIcon2, {}),
4934
+ label: "Cancel operation",
4935
+ onClick: (e) => {
4936
+ e.stopPropagation();
4937
+ controller.cancelPending(entryId);
4733
4938
  }
4734
- ) : null
4735
- ] });
4939
+ }
4940
+ );
4736
4941
  }
4737
- function HistoryRowView({ row, controller, rowHeight, focused }) {
4738
- const entry = row.entry;
4739
- const pending = entry?.status === "pending";
4740
- const failed = entry?.status === "failed";
4741
- const jumpable = controller.isJumpAllowed() && entry?.caps?.jumpable !== false;
4942
+ function HistoryRowView({ row, controller }) {
4943
+ const ui3 = (intent) => applyHistoryUi(controller, intent);
4742
4944
  return /* @__PURE__ */ jsx8(
4743
4945
  Row2,
4744
4946
  {
4745
- height: rowHeight,
4947
+ height: row.height,
4746
4948
  selected: row.current,
4747
- focused,
4949
+ focused: row.focused,
4748
4950
  struck: row.future,
4749
- noIcon: !controller.areIconsShown(),
4750
- icon: /* @__PURE__ */ jsx8(EntryIcon, { name: row.kind === "original" ? "original" : controller.getIconName(entry?.kind) }),
4951
+ noIcon: row.hideIcon,
4952
+ interactive: row.jumpable,
4953
+ icon: /* @__PURE__ */ jsx8(EntryIcon, { name: row.iconName }),
4751
4954
  label: row.label,
4752
- meta: row.kind === "entry" ? row.ordinal : void 0,
4753
- "data-history-row": row.entryId ?? "__original__",
4754
- onClick: jumpable ? () => controller.jumpTo(row.entryId) : void 0,
4755
- onMouseEnter: () => controller.setHovered(row.entryId),
4756
- onContextMenu: (e) => {
4757
- e.preventDefault();
4758
- controller.requestContextMenu(row.entryId, e.clientX, e.clientY);
4759
- },
4955
+ meta: row.meta,
4956
+ "data-history-row": row.key,
4760
4957
  title: row.label,
4761
4958
  trailing: /* @__PURE__ */ jsxs7(Fragment4, { children: [
4762
- pending ? /* @__PURE__ */ jsx8(PendingGlyph, {}) : null,
4763
- failed ? /* @__PURE__ */ jsx8(Badge3, { size: "sm", tone: "error", children: "failed" }) : null,
4764
- controller.isSourceShown() && entry?.source && entry.source !== "user" ? /* @__PURE__ */ jsx8(Badge3, { size: "sm", title: `Source: ${entry.source}`, children: entry.source === "agent" ? "AI" : "S" }) : null,
4765
- entry?.coalesced && entry.coalesced > 1 ? /* @__PURE__ */ jsxs7(Badge3, { size: "sm", title: `${entry.coalesced} actions coalesced`, children: [
4766
- "\xD7",
4767
- entry.coalesced
4768
- ] }) : null,
4769
- controller.areTimestampsShown() && entry?.at !== void 0 ? /* @__PURE__ */ jsx8(Text4, { role: "meta", children: formatTime(entry.at) }) : null,
4770
- pending ? /* @__PURE__ */ jsx8(
4771
- IconButton4,
4772
- {
4773
- size: "sm",
4774
- icon: /* @__PURE__ */ jsx8(XIcon2, {}),
4775
- label: "Cancel operation",
4776
- onClick: (e) => {
4777
- e.stopPropagation();
4778
- controller.cancelPending(entry?.id);
4779
- }
4780
- }
4781
- ) : null
4782
- ] })
4959
+ row.pending ? /* @__PURE__ */ jsx8(PendingGlyph, {}) : null,
4960
+ row.failed ? /* @__PURE__ */ jsx8(Badge3, { size: "sm", tone: "error", children: "failed" }) : null,
4961
+ row.showSource ? /* @__PURE__ */ jsx8(Badge3, { size: "sm", title: row.sourceTitle, children: row.sourceGlyph }) : null,
4962
+ row.showCoalesced ? /* @__PURE__ */ jsx8(Badge3, { size: "sm", title: row.coalescedTitle, children: row.coalescedText }) : null,
4963
+ row.showTime ? /* @__PURE__ */ jsx8(Text4, { role: "meta", children: row.time }) : null,
4964
+ row.pending ? /* @__PURE__ */ jsx8(HistoryCancelButton, { entryId: row.cancelId, controller }) : null
4965
+ ] }),
4966
+ onClick: () => ui3({ kind: "jump", entryId: row.entryId }),
4967
+ onMouseEnter: () => ui3({ kind: "hover", entryId: row.entryId }),
4968
+ onContextMenuAt: (x, y) => ui3({ kind: "contextMenu", entryId: row.entryId, x, y })
4783
4969
  }
4784
4970
  );
4785
4971
  }
4786
- function formatTime(at) {
4787
- const date = typeof at === "number" ? new Date(at) : new Date(at);
4788
- if (Number.isNaN(date.getTime())) return typeof at === "string" ? at : "";
4789
- return date.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit" });
4972
+ function historyRuntimeComponents(controller) {
4973
+ return {
4974
+ "history/Scroller": ({ children }) => /* @__PURE__ */ jsx8(HistoryScroller, { controller, children }),
4975
+ "history/CancelButton": ({ entryId }) => /* @__PURE__ */ jsx8(HistoryCancelButton, { entryId, controller }),
4976
+ "history/EntryIcon": EntryIcon,
4977
+ "history/PendingGlyph": PendingGlyph,
4978
+ "history/UndoIcon": UndoIcon,
4979
+ "history/RedoIcon": RedoIcon,
4980
+ "history/TrashIcon": TrashIcon
4981
+ };
4790
4982
  }
4791
4983
 
4792
4984
  // src/edit/history/panel.ts
@@ -4794,11 +4986,20 @@ function createHistoryPanel(options = {}) {
4794
4986
  return {
4795
4987
  manifest: historyManifest,
4796
4988
  activate(host) {
4797
- const controller = new HistoryPanelController(host, options);
4989
+ const { render: customRender, ...controllerOptions } = options;
4990
+ const controller = new HistoryPanelController(host, controllerOptions);
4798
4991
  void controller.load();
4799
4992
  let root = null;
4993
+ let unrender = null;
4800
4994
  return {
4801
4995
  render(el) {
4996
+ if (customRender) {
4997
+ unrender = customRender(el, controller);
4998
+ return () => {
4999
+ unrender?.();
5000
+ unrender = null;
5001
+ };
5002
+ }
4802
5003
  root = createRoot3(el);
4803
5004
  root.render(createElement3(HistoryPanelView, { controller }));
4804
5005
  return () => {
@@ -4821,6 +5022,8 @@ function createHistoryPanel(options = {}) {
4821
5022
  dispose() {
4822
5023
  root?.unmount();
4823
5024
  root = null;
5025
+ unrender?.();
5026
+ unrender = null;
4824
5027
  controller.dispose();
4825
5028
  }
4826
5029
  };
@@ -8598,11 +8801,11 @@ var FindController = class {
8598
8801
  * @param text - The new query text.
8599
8802
  * @param immediate - Skip the debounce (a paste, or pressing Enter).
8600
8803
  */
8601
- setText(text2, immediate = false) {
8602
- if (text2 === this.text) return;
8603
- this.text = text2;
8804
+ setText(text3, immediate = false) {
8805
+ if (text3 === this.text) return;
8806
+ this.text = text3;
8604
8807
  this.index = -1;
8605
- if (text2 === "") {
8808
+ if (text3 === "") {
8606
8809
  this.clearResults("idle");
8607
8810
  this.emitQuery(true);
8608
8811
  return;
@@ -8630,8 +8833,8 @@ var FindController = class {
8630
8833
  this.notify();
8631
8834
  }
8632
8835
  /** The replacement text. Never emitted on its own — a replacement is not a search. */
8633
- setReplaceText(text2) {
8634
- this.replaceText = text2;
8836
+ setReplaceText(text3) {
8837
+ this.replaceText = text3;
8635
8838
  this.notify();
8636
8839
  }
8637
8840
  /** Show or hide the replace row. */
@@ -12267,12 +12470,12 @@ var TreeController = class {
12267
12470
  }
12268
12471
  if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
12269
12472
  const fresh = now - this.typeAhead.at > this.typeAheadMs;
12270
- const text2 = (fresh ? "" : this.typeAhead.text) + event.key.toLowerCase();
12271
- this.typeAhead = { text: text2, at: now };
12473
+ const text3 = (fresh ? "" : this.typeAhead.text) + event.key.toLowerCase();
12474
+ this.typeAhead = { text: text3, at: now };
12272
12475
  const from = fresh ? current : current + 1;
12273
12476
  for (let i = 0; i < rows.length; i += 1) {
12274
12477
  const candidate = rows[(from + i) % rows.length];
12275
- if (candidate.node.label.toLowerCase().startsWith(text2)) {
12478
+ if (candidate.node.label.toLowerCase().startsWith(text3)) {
12276
12479
  this.focusedId = candidate.id;
12277
12480
  this.select([candidate.id]);
12278
12481
  return true;
@@ -12298,9 +12501,9 @@ var TreeController = class {
12298
12501
  return true;
12299
12502
  }
12300
12503
  /** Update the rename draft. */
12301
- updateRenameDraft(text2) {
12504
+ updateRenameDraft(text3) {
12302
12505
  if (!this.renaming) return;
12303
- this.renaming = { ...this.renaming, draft: text2 };
12506
+ this.renaming = { ...this.renaming, draft: text3 };
12304
12507
  this.notify();
12305
12508
  }
12306
12509
  /**
@@ -13489,6 +13692,8 @@ export {
13489
13692
  FindPanelView,
13490
13693
  GENERIC_ICON,
13491
13694
  GraphController,
13695
+ BEHAVIOURS2 as HISTORY_BEHAVIOURS,
13696
+ HISTORY_DECLARATION,
13492
13697
  HistoryPanelController,
13493
13698
  HistoryPanelView,
13494
13699
  IMPLEMENTED_TREE_MODES,
@@ -13519,6 +13724,7 @@ export {
13519
13724
  allIds,
13520
13725
  anchorStateOf,
13521
13726
  appliedCount,
13727
+ applyHistoryUi,
13522
13728
  applyInspectorUi,
13523
13729
  applyPrecision,
13524
13730
  applyTangentDrag,
@@ -13588,6 +13794,9 @@ export {
13588
13794
  highlightSegments,
13589
13795
  historyManifest,
13590
13796
  historyPanel,
13797
+ historyRuntimeComponents,
13798
+ historyViewManifest,
13799
+ historyViewState,
13591
13800
  hslToRgb,
13592
13801
  hsvFromHex,
13593
13802
  hsvToRgb,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenosystem/blocks",
3
- "version": "0.12.3",
3
+ "version": "0.12.4",
4
4
  "description": "XENO Blocks — rung 3 of the front ladder: components composed into a contract-bearing unit (manifest: ports, intents, commands, agent surface), rendered by @xenosystem/workbench. ONE package, one subpath per family (/auth, /edit, /data, /time, /ops, /trust, /agent), one named export per block — XENO PACKAGE NAMING - STANDARD.md.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -60,7 +60,7 @@
60
60
  "peerDependencies": {
61
61
  "@duckdb/duckdb-wasm": ">=1.28.0",
62
62
  "@xenosystem/block-sdk": ">=0.3.3 <1",
63
- "@xenosystem/components": ">=0.16.0 <1",
63
+ "@xenosystem/components": ">=0.16.1 <1",
64
64
  "@xenosystem/data-core": "^0.1.0",
65
65
  "@xenosystem/elements-react": ">=0.0.1",
66
66
  "@xenosystem/time-core": "^0.1.0",
@@ -76,7 +76,7 @@
76
76
  "@types/react": "^19.0.0",
77
77
  "@types/react-dom": "^19.0.0",
78
78
  "@xenosystem/block-sdk": "^0.3.3",
79
- "@xenosystem/components": "^0.16.0",
79
+ "@xenosystem/components": "^0.16.1",
80
80
  "@xenosystem/data-core": "^0.1.0",
81
81
  "@xenosystem/elements-react": "0.0.1",
82
82
  "@xenosystem/time-core": "^0.1.0",