@signalsafe/tree-spec-editor 0.2.1 → 0.2.2

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.
Files changed (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +186 -59
  3. package/dist/index.d.ts +10 -2
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +5 -1
  6. package/dist/lib/PanelHeaderCollapseCarets.d.ts +1 -1
  7. package/dist/lib/PanelHeaderCollapseCarets.d.ts.map +1 -1
  8. package/dist/lib/buildDefaultToolbarSpec.d.ts +3 -79
  9. package/dist/lib/buildDefaultToolbarSpec.d.ts.map +1 -1
  10. package/dist/lib/buildDefaultToolbarSpec.js +9 -155
  11. package/dist/lib/panelNodeLink.d.ts +13 -0
  12. package/dist/lib/panelNodeLink.d.ts.map +1 -0
  13. package/dist/lib/panelNodeLink.js +12 -0
  14. package/dist/lib/selectionStyles.d.ts +9 -0
  15. package/dist/lib/selectionStyles.d.ts.map +1 -0
  16. package/dist/lib/selectionStyles.js +8 -0
  17. package/dist/lib/toolbar/defaultToolbarTypes.d.ts +89 -0
  18. package/dist/lib/toolbar/defaultToolbarTypes.d.ts.map +1 -0
  19. package/dist/lib/toolbar/defaultToolbarTypes.js +1 -0
  20. package/dist/lib/toolbar/toolbarSectionBuilders.d.ts +10 -0
  21. package/dist/lib/toolbar/toolbarSectionBuilders.d.ts.map +1 -0
  22. package/dist/lib/toolbar/toolbarSectionBuilders.js +153 -0
  23. package/dist/modals/AuditLogModal.d.ts +1 -1
  24. package/dist/modals/AuditLogModal.d.ts.map +1 -1
  25. package/dist/modals/AuditLogModal.js +1 -1
  26. package/dist/modals/DraftHistoryModal.d.ts +1 -1
  27. package/dist/modals/DraftHistoryModal.d.ts.map +1 -1
  28. package/dist/modals/DraftHistoryModal.js +1 -1
  29. package/dist/modals/PublishReviewModal.d.ts +1 -1
  30. package/dist/modals/PublishReviewModal.d.ts.map +1 -1
  31. package/dist/panels/AdvancedJsonPanel.d.ts +1 -1
  32. package/dist/panels/AdvancedJsonPanel.d.ts.map +1 -1
  33. package/dist/panels/AppearancePanel.d.ts +26 -0
  34. package/dist/panels/AppearancePanel.d.ts.map +1 -0
  35. package/dist/panels/AppearancePanel.js +76 -0
  36. package/dist/panels/ChoiceEdgeAppearanceFields.d.ts +10 -0
  37. package/dist/panels/ChoiceEdgeAppearanceFields.d.ts.map +1 -0
  38. package/dist/panels/ChoiceEdgeAppearanceFields.js +13 -0
  39. package/dist/panels/ChoiceTemplatesPanel.d.ts +27 -0
  40. package/dist/panels/ChoiceTemplatesPanel.d.ts.map +1 -0
  41. package/dist/panels/ChoiceTemplatesPanel.js +9 -0
  42. package/dist/panels/GraphEditorInfoPanel.d.ts +5 -2
  43. package/dist/panels/GraphEditorInfoPanel.d.ts.map +1 -1
  44. package/dist/panels/GraphEditorInfoPanel.js +6 -6
  45. package/dist/panels/InspectorPanel.d.ts +3 -78
  46. package/dist/panels/InspectorPanel.d.ts.map +1 -1
  47. package/dist/panels/InspectorPanel.js +20 -60
  48. package/dist/panels/IssuesPanel.d.ts +6 -2
  49. package/dist/panels/IssuesPanel.d.ts.map +1 -1
  50. package/dist/panels/IssuesPanel.js +15 -3
  51. package/dist/panels/NodesPanel.d.ts +3 -1
  52. package/dist/panels/NodesPanel.d.ts.map +1 -1
  53. package/dist/panels/NodesPanel.js +12 -6
  54. package/dist/panels/SelectedEdgePanel.d.ts +10 -3
  55. package/dist/panels/SelectedEdgePanel.d.ts.map +1 -1
  56. package/dist/panels/SelectedEdgePanel.js +5 -6
  57. package/dist/panels/ToolbarPanel.d.ts +1 -1
  58. package/dist/panels/ToolbarPanel.d.ts.map +1 -1
  59. package/dist/panels/ToolbarPanel.js +2 -4
  60. package/dist/panels/inspector/ChoiceEditorCard.d.ts +28 -0
  61. package/dist/panels/inspector/ChoiceEditorCard.d.ts.map +1 -0
  62. package/dist/panels/inspector/ChoiceEditorCard.js +36 -0
  63. package/dist/panels/inspector/ChoiceEditorList.d.ts +25 -0
  64. package/dist/panels/inspector/ChoiceEditorList.d.ts.map +1 -0
  65. package/dist/panels/inspector/ChoiceEditorList.js +10 -0
  66. package/dist/panels/inspector/NodeTypeField.d.ts +8 -0
  67. package/dist/panels/inspector/NodeTypeField.d.ts.map +1 -0
  68. package/dist/panels/inspector/NodeTypeField.js +12 -0
  69. package/dist/panels/inspector/RequiredNodeCard.d.ts +14 -0
  70. package/dist/panels/inspector/RequiredNodeCard.d.ts.map +1 -0
  71. package/dist/panels/inspector/RequiredNodeCard.js +16 -0
  72. package/dist/panels/inspector/choiceActionIconProps.d.ts +12 -0
  73. package/dist/panels/inspector/choiceActionIconProps.d.ts.map +1 -0
  74. package/dist/panels/inspector/choiceActionIconProps.js +26 -0
  75. package/dist/panels/inspector/types.d.ts +77 -0
  76. package/dist/panels/inspector/types.d.ts.map +1 -0
  77. package/dist/panels/inspector/types.js +11 -0
  78. package/package.json +83 -65
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SignalSafe Software
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -41,6 +41,35 @@ Tests live under `tests/panels/`, `tests/modals/`, plus `tests/index.test.ts` fo
41
41
  | Just the framework-agnostic helpers (CLI, server-side preview, Angular shell) | `@signalsafe/tree-spec-editor-core` |
42
42
  | Just the wire contract (validation, compile, lint) | `@signalsafe/tree-spec` |
43
43
 
44
+ ### Planned framework shells (separate packages)
45
+
46
+ | You want… | Import from |
47
+ |----------|-------------|
48
+ | React + Material panels/modals (reuse React Flow canvas) | `@signalsafe/tree-spec-editor-react-mui` (planned) + `-react` |
49
+ | Angular editor | `@signalsafe/tree-spec-editor-angular` (planned) + `-core` |
50
+ | Vue editor | `@signalsafe/tree-spec-editor-vue` (planned) + `-core` |
51
+
52
+ This package (`@signalsafe/tree-spec-editor`) **remains the Bootstrap reference shell** — it does not become Material, Angular, or Vue.
53
+
54
+ See [docs/ai/packages-editor-architecture.md](../../docs/ai/packages-editor-architecture.md).
55
+
56
+ ## Full-stack host import pattern
57
+
58
+ The reference host ([`ScenarioVersionGraphEditorPage`](../../frontend/shared/domains/content/ScenarioVersionGraphEditorPage.tsx)) imports from **three** packages:
59
+
60
+ ```tsx
61
+ // Bootstrap UI shell — panels, modals, toolbar, canvas default export
62
+ import TreeSpecGraphEditor, { AppearancePanel, buildDefaultToolbarSpec, … } from '@signalsafe/tree-spec-editor';
63
+
64
+ // Stateful orchestration hook (not re-exported from the shell barrel)
65
+ import { useTreeSpecEditor } from '@signalsafe/tree-spec-editor-react';
66
+
67
+ // Framework-agnostic helpers and constants (prefer over shell re-exports)
68
+ import { resolveDefaultEdgeType, GRAPH_SELECTION_KIND, computeTreeDiffSummary } from '@signalsafe/tree-spec-editor-core';
69
+ ```
70
+
71
+ ESLint nudges hosts to import listed framework-agnostic symbols from `-core` instead of the shell barrel.
72
+
44
73
  ## Happy Path
45
74
 
46
75
  The smallest useful integration is:
@@ -123,8 +152,14 @@ export function ExampleTreeSpecEditor(): JSX.Element {
123
152
  - `TreeSpecGraphEditor`: the default React editor component.
124
153
  - `IssuesPanel`, `NodesPanel`: presentational sidebar panels for issues and node search/selection.
125
154
  - `AdvancedJsonPanel`: presentational card chrome for displaying a host-owned JSON renderer (e.g. the compiled `tree_spec`).
126
- - `InspectorPanel`: right-rail node inspector (Type / Prompt / Choices with Label / Next / Outcome / Delete) with optional render-prop slots and overridable outcome options for project-specific extensions.
127
- - `SelectedEdgePanel`: compact read-only card showing the currently selected transition.
155
+ - `GraphEditorInfoPanel`: left-rail metadata card (scenario/version ids, draft/published badge, autosave status, validation timestamp, scenario-level default edge type).
156
+ - `InspectorPanel`: right-rail node inspector (Type / Prompt / Choices with Type / Label / Next / Outcome / reorder-delete icon actions) with optional render-prop slots, `onFocusChoice` for selection sync, and overridable outcome options.
157
+ - `AppearancePanel`: right-rail canvas-only styling for the selected node and/or the selected edge's source choice (node appearance + per-choice edge appearance in one panel).
158
+ - `ChoiceEdgeAppearanceFields`: embeddable per-choice edge styling fields (used by `AppearancePanel`; also exported for custom layouts).
159
+ - `ChoiceTemplatesPanel`: preset choice bundles for custom host layouts (**not wired** in the reference graph editor page; pair with `appendChoiceTemplate` from `-core`).
160
+ - `SelectedEdgePanel`: optional compact **read-only** card for a selected transition (for editing, use `AppearancePanel`).
161
+ - `LIST_SELECTION_CLASS`, `CANVAS_SELECTION_CLASS`, …: shared CSS class helpers for list/canvas selection highlighting.
162
+ - `buildDefaultToolbarSpec`: builds the default action toolbar (`+ Add`, Templates, layout, Undo/Redo, validate/history/audit/snapshot/clone, save/publish/preview) without status chrome — draft/autosave live in `GraphEditorInfoPanel`.
128
163
  - `PublishReviewModal`, `DraftHistoryModal`, `AuditLogModal`: presentational modals for the publish-review / draft-snapshot / audit-log authoring flows; all strings are overridable.
129
164
  - `ToolbarPanel`: data-driven toolbar that takes an `items: ToolbarItem[]` array (`button` / `dropdown` / `badge` / `text` / `custom` kinds) and renders Bootstrap chrome in a single flex wrapper.
130
165
  - `duplicateNode`, `deleteNode`, `computeTreeDiffSummary`, `applyTreeTemplate`: project-agnostic tree-operation helpers (clone a node, delete a node with cascade, summarize a structural diff, insert a reusable subgraph template).
@@ -445,19 +480,19 @@ export function CompiledTreeSpecPanel({ tree }: Props): JSX.Element {
445
480
 
446
481
  ### `InspectorPanel`
447
482
 
448
- The right-rail node inspector. When a node is selected, it renders two Bootstrap cards: **Required** (Type, Prompt, and `renderExtraNodeFields`) and **Choices** (list-group rows). The universal fields the package owns:
483
+ The right-rail node inspector. When a node is in context (selected directly, or as the source of a selected edge), it renders two Bootstrap cards: **Required** (Type, Prompt, and `renderExtraNodeFields`) and **Choices** (list-group rows). The universal fields the package owns:
449
484
 
450
- - **Type** `<select>` (with the package's `TREE_SPEC_NODE_TYPE_PRESETS` + custom-value input).
485
+ - **Type** `<select>` (with the package's `TREE_SPEC_NODE_TYPE_PRESETS` + custom-value input, or a host-supplied **choice type** catalog via `choiceTypes` / `onSetChoiceType`).
451
486
  - **Prompt** `<textarea>`.
452
- - **Choices** list with **Label**, **Next** (target-node `<select>`), and a **delete** control per choice.
453
- - **Outcome** `<select>` per choice — only shown when the choice targets `END_NODE_ID`. Default options are the canonical `TerminalOutcome` values from `@signalsafe/tree-spec` (`safe` / `at_risk` / `compromised`).
487
+ - **Choices** list with per-row **Type**, **Label**, **Next** (target-node `<select>`), **Outcome** (only when Next is `END_NODE_ID`), and **reorder / delete** icon actions styled like agGrid row actions (`action-icon`).
488
+ - Focusing any field in a choice row should call `onFocusChoice(choiceId)` so the canvas, nodes list, and choice highlight stay in sync (typical host: `selectChoice(nodeId, choiceId)`).
454
489
 
455
490
  For project-specific UI, `InspectorPanel` exposes **render-prop slots** so the package stays generic while hosts can extend it without forking. The package owns nothing app-specific.
456
491
 
457
492
  ```tsx
458
493
  import {
494
+ AppearancePanel,
459
495
  InspectorPanel,
460
- SelectedEdgePanel,
461
496
  type EditorNode,
462
497
  type EditorTree,
463
498
  type EditorTransition,
@@ -465,6 +500,7 @@ import {
465
500
 
466
501
  function RightRail({
467
502
  tree,
503
+ inspectorNode,
468
504
  selectedNode,
469
505
  selectedEdge,
470
506
  focusChoiceId,
@@ -472,10 +508,17 @@ function RightRail({
472
508
  onUpdateSelectedNode,
473
509
  onAddChoice,
474
510
  onDeleteChoice,
511
+ onMoveChoice,
512
+ onSetChoiceType,
475
513
  onSetChoiceTarget,
476
514
  onSetChoiceOutcome,
515
+ onFocusChoice,
516
+ onUpdateChoiceEdgeHints,
517
+ choiceTypes,
477
518
  }: {
478
519
  tree: EditorTree;
520
+ /** Node shown in Required/Choices — selected node or edge source node. */
521
+ inspectorNode: EditorNode | null;
479
522
  selectedNode: EditorNode | null;
480
523
  selectedEdge: EditorTransition | null;
481
524
  focusChoiceId: string | null;
@@ -483,29 +526,57 @@ function RightRail({
483
526
  onUpdateSelectedNode: (patch: Partial<EditorNode>) => void;
484
527
  onAddChoice: () => void;
485
528
  onDeleteChoice: (choiceId: string) => void;
529
+ onMoveChoice?: (choiceId: string, direction: 'up' | 'down') => void;
530
+ onSetChoiceType?: (choiceId: string, typeId: string, defaultLabel?: string) => void;
486
531
  onSetChoiceTarget: (choiceId: string, targetNodeId: string) => void;
487
532
  onSetChoiceOutcome: (choiceId: string, outcome: string) => void;
533
+ onFocusChoice?: (choiceId: string) => void;
534
+ onUpdateChoiceEdgeHints?: (
535
+ nodeId: string,
536
+ choiceId: string,
537
+ patch: Partial<import('@signalsafe/tree-spec-editor-core').ChoiceEdgeHints>,
538
+ ) => void;
539
+ choiceTypes?: ReadonlyArray<{ id: string; label: string }>;
488
540
  }) {
489
541
  return (
490
542
  <>
491
- <InspectorPanel
492
- tree={tree}
493
- selectedNode={selectedNode}
494
- focusChoiceId={focusChoiceId}
495
- isPublished={isPublished}
496
- onUpdateSelectedNode={onUpdateSelectedNode}
497
- onAddChoice={onAddChoice}
498
- onDeleteChoice={onDeleteChoice}
499
- onSetChoiceTarget={onSetChoiceTarget}
500
- onSetChoiceOutcome={onSetChoiceOutcome}
501
- renderExtraNodeFields={({ node, onUpdateNode }) => (
502
- <YourProjectNodeMetadataFields node={node} onChange={onUpdateNode} />
503
- )}
504
- renderExtraChoiceFields={({ choice, onUpdateNode }) => (
505
- <YourProjectChoiceMetadataFields choice={choice} onChange={onUpdateNode} />
506
- )}
507
- />
508
- <SelectedEdgePanel selectedEdge={selectedEdge} />
543
+ {inspectorNode ? (
544
+ <InspectorPanel
545
+ tree={tree}
546
+ selectedNode={inspectorNode}
547
+ focusChoiceId={focusChoiceId}
548
+ isPublished={isPublished}
549
+ onUpdateSelectedNode={onUpdateSelectedNode}
550
+ onAddChoice={onAddChoice}
551
+ onDeleteChoice={onDeleteChoice}
552
+ onMoveChoice={onMoveChoice}
553
+ onSetChoiceType={onSetChoiceType}
554
+ onSetChoiceTarget={onSetChoiceTarget}
555
+ onSetChoiceOutcome={onSetChoiceOutcome}
556
+ onFocusChoice={onFocusChoice}
557
+ choiceTypes={choiceTypes}
558
+ renderExtraNodeFields={({ node, onUpdateNode }) => (
559
+ <YourProjectNodeMetadataFields node={node} onChange={onUpdateNode} />
560
+ )}
561
+ renderExtraChoiceFields={({ choice, onUpdateNode }) => (
562
+ <YourProjectChoiceMetadataFields choice={choice} onChange={onUpdateNode} />
563
+ )}
564
+ />
565
+ ) : null}
566
+ {selectedNode || selectedEdge ? (
567
+ <AppearancePanel
568
+ tree={tree}
569
+ selectedNode={selectedNode}
570
+ selectedEdge={selectedEdge}
571
+ focusChoiceId={focusChoiceId}
572
+ isPublished={isPublished}
573
+ onUpdateSelectedNode={onUpdateSelectedNode}
574
+ onUpdateChoiceEdgeHints={onUpdateChoiceEdgeHints}
575
+ renderAppearanceFields={({ node, isPublished, onUpdateNode }) => (
576
+ <NodeAppearanceFields node={node} isPublished={isPublished} onUpdateNode={onUpdateNode} />
577
+ )}
578
+ />
579
+ ) : null}
509
580
  </>
510
581
  );
511
582
  }
@@ -515,6 +586,9 @@ function RightRail({
515
586
 
516
587
  - `outcomeOptions`: override the END-transition outcome `<select>` options (e.g. `[{ value: 'pass', label: 'Pass' }, { value: 'fail', label: 'Fail' }]`). Defaults to the canonical `TerminalOutcome` values exported as `DEFAULT_OUTCOME_OPTIONS`.
517
588
  - `hideOutcomeField`: hide the outcome `<select>` entirely (useful when the host manages outcomes via `renderExtraChoiceFields` or stores them outside the wire format).
589
+ - `choiceTypes` / `onSetChoiceType`: host-defined stable choice-type ids for the per-choice **Type** `<select>` (e.g. `verify`, `risky`, `bad`).
590
+ - `onMoveChoice`: when set, shows up/down icon actions to reorder choices within the node.
591
+ - `onFocusChoice`: invoked when the user focuses any control inside a choice card; use to sync canvas/node-list highlighting.
518
592
  - `renderExtraNodeFields({ tree, node, isPublished, onUpdateNode })`: render extra UI below the Prompt textarea, scoped to the currently-selected node. Use for project-specific node metadata (render hints, scoring, classification, etc.).
519
593
  - `renderExtraChoiceFields({ tree, node, choice, transition, isPublished, onUpdateNode })`: render extra UI below each choice card (after Next/Outcome). Use for project-specific per-choice metadata.
520
594
  - `onDeleteSelectedNode`: when set, shows a delete-node icon in the Required card header; wire to `useTreeSpecEditor().actions.deleteSelectedNode` (or equivalent). Disabled automatically when `isPublished` is true.
@@ -522,14 +596,53 @@ function RightRail({
522
596
  - `emptyStateText`: text shown when no node is selected (default `"Select a node to edit it."`).
523
597
  - `typeHelperText`: muted helper text under the Type field (default explains the open `type` string).
524
598
 
599
+ ### `GraphEditorInfoPanel`
600
+
601
+ Left-rail metadata card for the scenario version being edited. Shows scenario/version ids, name, created/updated timestamps, a **Draft** / **Published** badge, **autosave status**, last validation time, and (when wired) the scenario-level **default edge type** dropdown (`smoothstep` / `straight` / `step`).
602
+
603
+ Use this panel instead of duplicating draft/autosave badges in the top toolbar.
604
+
605
+ ### `AppearancePanel`
606
+
607
+ Right-rail panel for **canvas-only** styling. Combines:
608
+
609
+ - **Node appearance** (colors, width/height, text wrap, lock) when a node is selected and no choice/edge context is active — hosts inject fields via `renderAppearanceFields`.
610
+ - **Edge appearance** for the active choice when an edge is selected or a choice is focused — stroke color (default matches React Flow gray via `DEFAULT_CANVAS_EDGE_STROKE`), label visibility, and per-choice edge type override.
611
+
612
+ Scenario-level default edge routing lives in `GraphEditorInfoPanel`, not here.
613
+
614
+ Hosts typically pair node fields with a project-specific component (for example `NodeAppearanceFields` in `frontend/shared`):
615
+
616
+ ```tsx
617
+ import { AppearancePanel, InspectorPanel } from '@signalsafe/tree-spec-editor';
618
+ import NodeAppearanceFields from '../ui/components/NodeAppearanceFields';
619
+
620
+ <InspectorPanel /* Required + Choices; pass inspectorNode when edge-selected */ />
621
+ <AppearancePanel
622
+ tree={tree}
623
+ selectedNode={selectedNode}
624
+ selectedEdge={selectedEdge}
625
+ focusChoiceId={focusChoiceId}
626
+ isPublished={isPublished}
627
+ onUpdateSelectedNode={onUpdateSelectedNode}
628
+ onUpdateChoiceEdgeHints={updateChoiceEdgeHints}
629
+ renderAppearanceFields={({ node, isPublished, onUpdateNode }) => (
630
+ <NodeAppearanceFields node={node} isPublished={isPublished} onUpdateNode={onUpdateNode} />
631
+ )}
632
+ />
633
+ ```
634
+
635
+ Wire format details: [`@signalsafe/tree-spec` README](../tree-spec/README.md) — **Graph editor metadata**.
636
+
525
637
  ### `SelectedEdgePanel`
526
638
 
527
- The compact read-only card that surfaces the currently selected transition. Returns `null` when `selectedEdge` is `null`, so hosts can render it unconditionally.
639
+ Optional compact read-only card that surfaces the currently selected transition. Returns `null` when `selectedEdge` is `null`. **For editing**, prefer `AppearancePanel` + `InspectorPanel` (edge selection keeps the source node's choices visible and focuses the source choice). Keep `SelectedEdgePanel` only when you want a minimal read-only summary without the full appearance UI.
528
640
 
529
641
  `SelectedEdgePanel` accepts these optional props:
530
642
 
531
643
  - `title`: header title text (default `"Selected Edge"`).
532
- - `renderDetails(edge)`: replace the default `from · choice → to` line with a custom renderer.
644
+ - `onNodeSelect(nodeId)`: when set, the default details line renders **from** and **to** node ids as link buttons that invoke this callback (typical host: `setSelection({ kind: 'node', id })` plus `setFocusNodeId`).
645
+ - `renderDetails(edge, { onNodeSelect })`: replace the default `from · choice → to` line with a custom renderer.
533
646
 
534
647
  ## Modals
535
648
 
@@ -682,32 +795,52 @@ function AuditLogModalContainer({
682
795
 
683
796
  ## Toolbar
684
797
 
798
+ ### `buildDefaultToolbarSpec`
799
+
800
+ Builds the default TreeSpec editor toolbar item list from hook state, actions, and adapter capability flags. Includes **+ Add**, **Templates**, layout buttons, **Undo** / **Redo** (when `actions.undo` / `actions.redo` are wired), optional validate/history/audit/snapshot/clone actions, **Save draft**, **Publish**, and **Preview** — but **not** draft/autosave status chrome (use `GraphEditorInfoPanel` for that) and **not** a back link by default (use page breadcrumbs or pass optional `toolbarBackSlot` when you want a toolbar back control).
801
+
802
+ ```tsx
803
+ import { buildDefaultToolbarSpec, ToolbarPanel } from '@signalsafe/tree-spec-editor';
804
+
805
+ const items = buildDefaultToolbarSpec({
806
+ state: editor, // isPublished, canUndo, canRedo, saving, publishing, canPublish, hasTree, …
807
+ actions: {
808
+ ...editor.actions,
809
+ undo: () => editor.actions.undo(),
810
+ redo: () => editor.actions.redo(),
811
+ },
812
+ capabilities: {
813
+ canValidate: Boolean(adapter.validate),
814
+ canPublish: Boolean(adapter.publish),
815
+ // …
816
+ },
817
+ nodeTypes: [{ type: 'prompt' }, { type: 'email' }],
818
+ templates: [{ id: 'starter', label: 'Starter', spec: MY_TEMPLATE }],
819
+ preview: { onClick: openPreview, disabled: !versionId },
820
+ // toolbarBackSlot: { render: () => <Link to="/library">Back</Link> }, // optional — prefer breadcrumbs
821
+ showUndoRedo: true, // default; set false to hide Undo/Redo buttons
822
+ extraItems: [], // optional trailing ToolbarItem entries
823
+ });
824
+
825
+ <ToolbarPanel items={items} />;
826
+ ```
827
+
685
828
  ### `ToolbarPanel`
686
829
 
687
830
  A data-driven toolbar for editor pages. Hosts pass an `items: ToolbarItem[]`
688
831
  array; the package renders Bootstrap chrome (`Button`, `Dropdown`, badge,
689
- muted text) inside a single flex wrapper. All project-specific concerns —
690
- adapter capability gates, dropdown vocabularies, button labels, disabled
691
- rules, and router-aware links — stay in the host as closures inside each
692
- item.
832
+ muted text) inside a single flex wrapper. Project-specific concerns —
833
+ adapter capability gates, dropdown vocabularies, button labels, and disabled
834
+ rules — stay in the host as closures inside each item. Prefer
835
+ `buildDefaultToolbarSpec` for the standard action set.
693
836
 
694
837
  ```tsx
695
838
  import {
696
839
  ToolbarPanel,
697
840
  type ToolbarItem,
698
841
  } from '@signalsafe/tree-spec-editor';
699
- import { Link } from 'react-router-dom';
700
842
 
701
843
  const items: ToolbarItem[] = [
702
- {
703
- kind: 'custom',
704
- id: 'back',
705
- render: () => (
706
- <Link className="btn btn-outline-secondary" to="/scenarios">
707
- Back
708
- </Link>
709
- ),
710
- },
711
844
  {
712
845
  kind: 'dropdown',
713
846
  id: 'add',
@@ -716,14 +849,11 @@ const items: ToolbarItem[] = [
716
849
  entries: [
717
850
  { id: 'prompt', label: 'Prompt', onClick: () => addNode('prompt') },
718
851
  { id: 'email', label: 'Email', onClick: () => addNode('email') },
719
- { id: 'div', label: '', divider: true },
720
- { id: 'outcome', label: 'Outcome node', onClick: () => addNode('outcome') },
721
852
  ],
722
853
  },
723
- { kind: 'button', id: 'reset', label: 'Reset view', onClick: onReset, title: 'Reset view to fit graph' },
724
- { kind: 'button', id: 'save', label: saving ? 'Saving…' : 'Save Draft', variant: 'primary', onClick: onSave, disabled: saving },
725
- { kind: 'badge', id: 'status', label: isPublished ? 'Published (read-only)' : 'Draft', variant: isPublished ? 'success' : 'secondary' },
726
- { kind: 'text', id: 'autosave', content: autosaveLabel },
854
+ { kind: 'button', id: 'reset', label: 'Reset view', onClick: onReset },
855
+ { kind: 'button', id: 'save', label: saving ? 'Saving…' : 'Save draft', onClick: onSave, disabled: saving },
856
+ { kind: 'button', id: 'preview', label: 'Preview', onClick: onPreview },
727
857
  ];
728
858
 
729
859
  <ToolbarPanel items={items} />;
@@ -843,21 +973,12 @@ Small pure helpers for the parts of an editor page that aren't graph-shaped: the
843
973
 
844
974
  ### `getAutosaveStatusLabel(status)`
845
975
 
846
- Maps an `AutosaveStatus` (`'idle' | 'dirty' | 'saving' | 'saved'`) to a default toolbar label. Returns the empty string for `'idle'` so the toolbar can render nothing between editing sessions.
976
+ Maps an `AutosaveStatus` (`'idle' | 'dirty' | 'saving' | 'saved'`) to a default label. Returns the empty string for `'idle'`. The reference host page shows this in **`GraphEditorInfoPanel`**, not the top toolbar.
847
977
 
848
978
  ```tsx
849
- import {
850
- getAutosaveStatusLabel,
851
- ToolbarPanel,
852
- type AutosaveStatus,
853
- type ToolbarItem,
854
- } from '@signalsafe/tree-spec-editor';
979
+ import { getAutosaveStatusLabel } from '@signalsafe/tree-spec-editor';
855
980
 
856
- function buildToolbar(autosaveStatus: AutosaveStatus): ToolbarItem[] {
857
- return [
858
- { kind: 'text', id: 'autosave', content: getAutosaveStatusLabel(autosaveStatus) },
859
- ];
860
- }
981
+ const label = getAutosaveStatusLabel(autosaveStatus); // e.g. "Saved ✓"
861
982
  ```
862
983
 
863
984
  ### `getKeyboardShortcutAction(params)`
@@ -1026,3 +1147,9 @@ function addPromptNode(tree: EditorTree): EditorTree {
1026
1147
  - Import from the package root only.
1027
1148
  - Install `react`, `react-dom`, `reactflow`, and `react-bootstrap` in the consuming app, and load Bootstrap CSS as usual.
1028
1149
  - If you need wire-format compile/decompile helpers, use `@signalsafe/tree-spec`.
1150
+
1151
+ ## Repository
1152
+
1153
+ Standalone source and releases: [SignalSafeSoftware/tree-spec-editor](https://github.com/SignalSafeSoftware/tree-spec-editor).
1154
+
1155
+ Published as [`@signalsafe/tree-spec-editor`](https://www.npmjs.com/package/@signalsafe/tree-spec-editor) on npm.
package/dist/index.d.ts CHANGED
@@ -33,8 +33,15 @@ export { default as AdvancedJsonPanel } from './panels/AdvancedJsonPanel';
33
33
  export type { AdvancedJsonPanelProps } from './panels/AdvancedJsonPanel';
34
34
  export { default as InspectorPanel, DEFAULT_OUTCOME_OPTIONS } from './panels/InspectorPanel';
35
35
  export type { InspectorPanelProps, InspectorNodeRenderContext, InspectorChoiceRenderContext, } from './panels/InspectorPanel';
36
+ export { default as AppearancePanel } from './panels/AppearancePanel';
37
+ export type { AppearancePanelProps } from './panels/AppearancePanel';
36
38
  export { default as SelectedEdgePanel } from './panels/SelectedEdgePanel';
37
39
  export type { SelectedEdgePanelProps } from './panels/SelectedEdgePanel';
40
+ export { default as ChoiceTemplatesPanel } from './panels/ChoiceTemplatesPanel';
41
+ export type { ChoiceTemplatesPanelProps, ChoiceTemplateItem, ChoicePresetItem } from './panels/ChoiceTemplatesPanel';
42
+ export type { ChoiceTypeOption } from './panels/InspectorPanel';
43
+ export { default as ChoiceEdgeAppearanceFields } from './panels/ChoiceEdgeAppearanceFields';
44
+ export type { ChoiceEdgeAppearanceFieldsProps } from './panels/ChoiceEdgeAppearanceFields';
38
45
  export { default as PublishReviewModal } from './modals/PublishReviewModal';
39
46
  export type { PublishReviewModalProps } from './modals/PublishReviewModal';
40
47
  export { default as DraftHistoryModal } from './modals/DraftHistoryModal';
@@ -44,10 +51,11 @@ export type { AuditLogModalProps } from './modals/AuditLogModal';
44
51
  export { default as ToolbarPanel, TOOLBAR_ITEM_KIND } from './panels/ToolbarPanel';
45
52
  export type { ToolbarPanelProps, ToolbarItem, ToolbarItemKind, ToolbarButtonItem, ToolbarDropdownItem, ToolbarDropdownEntry, ToolbarBadgeItem, ToolbarTextItem, ToolbarCustomItem, } from './panels/ToolbarPanel';
46
53
  export { getIssueSeverityBadgeClass } from './lib/panelHelpers';
54
+ export { LIST_SELECTION_CLASS, CANVAS_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS, CANVAS_SELECTION_TEXT_CLASS } from './lib/selectionStyles';
47
55
  export { default as PanelHeaderCollapseCarets } from './lib/PanelHeaderCollapseCarets';
48
56
  export { buildDefaultToolbarSpec } from './lib/buildDefaultToolbarSpec';
49
57
  export type { BuildDefaultToolbarSpecOptions, DefaultToolbarActions, DefaultToolbarCapabilities, DefaultToolbarLabels, DefaultToolbarNodeType, DefaultToolbarState, DefaultToolbarTemplate, } from './lib/buildDefaultToolbarSpec';
50
- export { END_NODE_ID, GRAPH_SELECTION_KIND, safeUUID, getTransition, upsertTransition, deleteTransitionsForChoice, lintEditorTree, parsePydanticOutcomeErrors, shouldQueueInitialValidation, TREE_SPEC_NODE_TYPE_PRESETS, autoLayoutTree, getNextSpawnPosition, getAutosaveStatusLabel, AUTOSAVE_STATUS, getKeyboardShortcutAction, KEYBOARD_SHORTCUT_ACTION, applyTreeTemplate, computeTreeDiffSummary, deleteNode, duplicateNode, buildStableEntries, } from '@signalsafe/tree-spec-editor-core';
51
- export type { EditorChoice, EditorNode, EditorTransition, EditorTree, GraphEditorIssue, GraphSelection, GraphSelectionKind, ReactFlowEdgeChange, ReactFlowNodeChange, TreeSpecAuditEventItem, TreeSpecSnapshotItem, TreeSpecNodeTypePreset, AutosaveStatus, KeyboardShortcutAction, KeyboardShortcutParams, ApplyTreeTemplateOptions, TreeDiffSummary, TreeTemplateNodeSpec, TreeTemplateSpec, TreeTemplateTransitionSpec, } from '@signalsafe/tree-spec-editor-core';
58
+ export { END_NODE_ID, GRAPH_SELECTION_KIND, safeUUID, getTransition, upsertTransition, deleteTransitionsForChoice, lintEditorTree, parsePydanticOutcomeErrors, shouldQueueInitialValidation, TREE_SPEC_NODE_TYPE_PRESETS, autoLayoutTree, getNextSpawnPosition, needsInitialLayout, getThemeHints, getEditorHints, isNodeLocked, patchEditorHints, editorHintsToStyle, RENDER_HINTS_THEME_NS, RENDER_HINTS_EDITOR_NS, GRAPH_POSITION_KEY, getAutosaveStatusLabel, AUTOSAVE_STATUS, getKeyboardShortcutAction, KEYBOARD_SHORTCUT_ACTION, applyTreeTemplate, applyEditorConnectOnDrop, computeTreeDiffSummary, deleteNode, duplicateNode, buildStableEntries, } from '@signalsafe/tree-spec-editor-core';
59
+ export type { EditorChoice, EditorNode, EditorTransition, EditorTree, GraphEditorIssue, GraphSelection, GraphSelectionKind, ReactFlowEdgeChange, ReactFlowNodeChange, TreeSpecAuditEventItem, TreeSpecSnapshotItem, TreeSpecNodeTypePreset, AutosaveStatus, KeyboardShortcutAction, KeyboardShortcutParams, ApplyTreeTemplateOptions, TreeDiffSummary, TreeTemplateNodeSpec, TreeTemplateSpec, TreeTemplateTransitionSpec, ConnectOnDropOptions, NodeEditorHints, GraphPosition, } from '@signalsafe/tree-spec-editor-core';
52
60
  export type { TreeSpecIssue, TreeSpecWire } from '@signalsafe/tree-spec';
53
61
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -27,16 +27,20 @@ export { default as GraphEditorInfoPanel } from './panels/GraphEditorInfoPanel';
27
27
  export { default as NodesPanel } from './panels/NodesPanel';
28
28
  export { default as AdvancedJsonPanel } from './panels/AdvancedJsonPanel';
29
29
  export { default as InspectorPanel, DEFAULT_OUTCOME_OPTIONS } from './panels/InspectorPanel';
30
+ export { default as AppearancePanel } from './panels/AppearancePanel';
30
31
  export { default as SelectedEdgePanel } from './panels/SelectedEdgePanel';
32
+ export { default as ChoiceTemplatesPanel } from './panels/ChoiceTemplatesPanel';
33
+ export { default as ChoiceEdgeAppearanceFields } from './panels/ChoiceEdgeAppearanceFields';
31
34
  export { default as PublishReviewModal } from './modals/PublishReviewModal';
32
35
  export { default as DraftHistoryModal } from './modals/DraftHistoryModal';
33
36
  export { default as AuditLogModal } from './modals/AuditLogModal';
34
37
  export { default as ToolbarPanel, TOOLBAR_ITEM_KIND } from './panels/ToolbarPanel';
35
38
  export { getIssueSeverityBadgeClass } from './lib/panelHelpers';
39
+ export { LIST_SELECTION_CLASS, CANVAS_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS, CANVAS_SELECTION_TEXT_CLASS } from './lib/selectionStyles';
36
40
  export { default as PanelHeaderCollapseCarets } from './lib/PanelHeaderCollapseCarets';
37
41
  export { buildDefaultToolbarSpec } from './lib/buildDefaultToolbarSpec';
38
42
  /* ------------------------------------------------------------------------- */
39
43
  /* Framework-agnostic re-exports from @signalsafe/tree-spec-editor-core. */
40
44
  /* Hosts may consume these directly from `-core` to skip the React surface. */
41
45
  /* ------------------------------------------------------------------------- */
42
- export { END_NODE_ID, GRAPH_SELECTION_KIND, safeUUID, getTransition, upsertTransition, deleteTransitionsForChoice, lintEditorTree, parsePydanticOutcomeErrors, shouldQueueInitialValidation, TREE_SPEC_NODE_TYPE_PRESETS, autoLayoutTree, getNextSpawnPosition, getAutosaveStatusLabel, AUTOSAVE_STATUS, getKeyboardShortcutAction, KEYBOARD_SHORTCUT_ACTION, applyTreeTemplate, computeTreeDiffSummary, deleteNode, duplicateNode, buildStableEntries, } from '@signalsafe/tree-spec-editor-core';
46
+ export { END_NODE_ID, GRAPH_SELECTION_KIND, safeUUID, getTransition, upsertTransition, deleteTransitionsForChoice, lintEditorTree, parsePydanticOutcomeErrors, shouldQueueInitialValidation, TREE_SPEC_NODE_TYPE_PRESETS, autoLayoutTree, getNextSpawnPosition, needsInitialLayout, getThemeHints, getEditorHints, isNodeLocked, patchEditorHints, editorHintsToStyle, RENDER_HINTS_THEME_NS, RENDER_HINTS_EDITOR_NS, GRAPH_POSITION_KEY, getAutosaveStatusLabel, AUTOSAVE_STATUS, getKeyboardShortcutAction, KEYBOARD_SHORTCUT_ACTION, applyTreeTemplate, applyEditorConnectOnDrop, computeTreeDiffSummary, deleteNode, duplicateNode, buildStableEntries, } from '@signalsafe/tree-spec-editor-core';
@@ -3,5 +3,5 @@ export interface PanelHeaderCollapseCaretsProps {
3
3
  onToggle: () => void;
4
4
  }
5
5
  /** Collapse/expand carets for card panel headers. */
6
- export default function PanelHeaderCollapseCarets({ expanded, onToggle, }: Readonly<PanelHeaderCollapseCaretsProps>): import("react/jsx-runtime").JSX.Element;
6
+ export default function PanelHeaderCollapseCarets({ expanded, onToggle, }: Readonly<PanelHeaderCollapseCaretsProps>): import("react").JSX.Element;
7
7
  //# sourceMappingURL=PanelHeaderCollapseCarets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PanelHeaderCollapseCarets.d.ts","sourceRoot":"","sources":["../../src/lib/PanelHeaderCollapseCarets.tsx"],"names":[],"mappings":"AAAA,MAAM,WAAW,8BAA8B;IAC3C,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,qDAAqD;AACrD,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,EAC9C,QAAQ,EACR,QAAQ,GACX,EAAE,QAAQ,CAAC,8BAA8B,CAAC,2CAY1C"}
1
+ {"version":3,"file":"PanelHeaderCollapseCarets.d.ts","sourceRoot":"","sources":["../../src/lib/PanelHeaderCollapseCarets.tsx"],"names":[],"mappings":"AAAA,MAAM,WAAW,8BAA8B;IAC3C,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,qDAAqD;AACrD,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,EAC9C,QAAQ,EACR,QAAQ,GACX,EAAE,QAAQ,CAAC,8BAA8B,CAAC,+BAY1C"}
@@ -1,83 +1,7 @@
1
- import type { ReactNode } from 'react';
2
- import { type AutosaveStatus, type TreeTemplateSpec } from '@signalsafe/tree-spec-editor-core';
3
- import { type ToolbarItem } from '../panels/ToolbarPanel.js';
1
+ import type { ToolbarItem } from '../panels/ToolbarPanel.js';
2
+ import type { BuildDefaultToolbarSpecOptions } from './toolbar/defaultToolbarTypes.js';
4
3
  export { AUTOSAVE_STATUS } from '@signalsafe/tree-spec-editor-core';
5
- export interface DefaultToolbarCapabilities {
6
- canValidate?: boolean;
7
- canListSnapshots?: boolean;
8
- canListAudit?: boolean;
9
- canCreateSnapshot?: boolean;
10
- canCloneToDraft?: boolean;
11
- canPublish?: boolean;
12
- }
13
- export interface DefaultToolbarNodeType {
14
- type?: string;
15
- label?: string;
16
- divider?: boolean;
17
- id?: string;
18
- patch?: Record<string, unknown>;
19
- }
20
- export interface DefaultToolbarTemplate {
21
- id: string;
22
- label: string;
23
- spec: TreeTemplateSpec;
24
- }
25
- export interface DefaultToolbarLabels {
26
- add?: string;
27
- templates?: string;
28
- validate?: string;
29
- autoLayout?: string;
30
- resetView?: string;
31
- preview?: string;
32
- save?: string;
33
- publish?: string;
34
- history?: string;
35
- audit?: string;
36
- snapshot?: string;
37
- clone?: string;
38
- draftBadge?: string;
39
- publishedBadge?: string;
40
- }
41
- export interface DefaultToolbarState {
42
- isPublished: boolean;
43
- saving: boolean;
44
- publishing: boolean;
45
- creatingSnapshot: boolean;
46
- cloning: boolean;
47
- canPublish: boolean;
48
- hasTree: boolean;
49
- autosaveStatus: AutosaveStatus;
50
- }
51
- export interface DefaultToolbarActions {
52
- addNodeOfType: (type: string, patch?: Record<string, unknown>) => void;
53
- insertTemplate: (spec: TreeTemplateSpec) => void;
54
- triggerResetView: () => void;
55
- autoLayout: () => void;
56
- validate: () => void | Promise<void>;
57
- saveDraft: () => void | Promise<void>;
58
- setShowDraftHistory: (show: boolean) => void;
59
- setShowAudit: (show: boolean) => void;
60
- createSnapshot: () => void | Promise<void>;
61
- cloneToDraft: () => void | Promise<void>;
62
- setShowPublishModal: (show: boolean) => void;
63
- }
64
- export interface BuildDefaultToolbarSpecOptions {
65
- state: DefaultToolbarState;
66
- actions: DefaultToolbarActions;
67
- capabilities?: DefaultToolbarCapabilities;
68
- nodeTypes?: DefaultToolbarNodeType[];
69
- templates?: DefaultToolbarTemplate[];
70
- backSlot?: {
71
- id?: string;
72
- render: () => ReactNode;
73
- };
74
- preview?: {
75
- onClick: () => void;
76
- disabled?: boolean;
77
- };
78
- labels?: DefaultToolbarLabels;
79
- extraItems?: ToolbarItem[];
80
- }
4
+ export type { BuildDefaultToolbarSpecOptions, DefaultToolbarActions, DefaultToolbarBackSlot, DefaultToolbarCapabilities, DefaultToolbarLabels, DefaultToolbarNodeType, DefaultToolbarState, DefaultToolbarTemplate, } from './toolbar/defaultToolbarTypes.js';
81
5
  /** Build the default TreeSpec editor toolbar item list from state, actions, and capability flags. */
82
6
  export declare function buildDefaultToolbarSpec(options: BuildDefaultToolbarSpecOptions): ToolbarItem[];
83
7
  //# sourceMappingURL=buildDefaultToolbarSpec.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"buildDefaultToolbarSpec.d.ts","sourceRoot":"","sources":["../../src/lib/buildDefaultToolbarSpec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"buildDefaultToolbarSpec.d.ts","sourceRoot":"","sources":["../../src/lib/buildDefaultToolbarSpec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAW7D,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAEvF,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEpE,YAAY,EACR,8BAA8B,EAC9B,qBAAqB,EACrB,sBAAsB,EACtB,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,GACzB,MAAM,kCAAkC,CAAC;AAE1C,qGAAqG;AACrG,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,8BAA8B,GAAG,WAAW,EAAE,CA+B9F"}