@signalsafe/tree-spec-editor 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,20 +1,70 @@
1
1
  # `@signalsafe/tree-spec-editor`
2
2
 
3
- React graph editor for authoring `TreeSpec` content.
3
+ React **Bootstrap UI shell** for authoring TreeSpec graphs: canvas (from `@signalsafe/tree-spec-editor-react`), sidebar panels, modals, and toolbar helpers.
4
4
 
5
- This package gives you a ready-to-embed editor component plus a small set of editor helpers. It is focused on graph editing only: nodes, choices, transitions, selection, layout, and validation hints.
5
+ | | |
6
+ |---|---|
7
+ | **npm** | `@signalsafe/tree-spec-editor` |
8
+ | **GitHub** | [SignalSafeSoftware/tree-spec-editor](https://github.com/SignalSafeSoftware/tree-spec-editor) |
9
+ | **Peer deps** | `react`, `react-dom`, `reactflow`, `react-bootstrap` |
10
+
11
+ ## What this package does
12
+
13
+ - Ships a ready-to-embed **graph editor UI** (`TreeSpecGraphEditor` re-export, panels, modals, toolbar).
14
+ - Re-exports selected **editor-core helpers** and types for one-stop imports in Bootstrap hosts.
15
+
16
+ ## What this package does not do
17
+
18
+ - Routing, REST/GraphQL clients, or authentication — your host app loads/saves drafts and enforces permissions.
19
+ - Wire compile/publish without your adapter — use `useTreeSpecEditor` from `@signalsafe/tree-spec-editor-react` with a host adapter.
20
+ - React Flow CSS by itself — the canvas lives in `-editor-react`; **consumers may need** `import 'reactflow/dist/style.css'` in the app entry (see `@signalsafe/tree-spec-editor-react` README). This package keeps `sideEffects: false` because it does not import CSS directly.
21
+
22
+ ## Package stack
23
+
24
+ | Layer | Package |
25
+ |---|---|
26
+ | Wire | `@signalsafe/tree-spec` |
27
+ | Editor model | `@signalsafe/tree-spec-editor-core` |
28
+ | React Flow canvas | `@signalsafe/tree-spec-editor-react` |
29
+ | **Bootstrap shell (this package)** | `@signalsafe/tree-spec-editor` |
6
30
 
7
31
  ## Install
8
32
 
9
33
  ```bash
10
- npm install @signalsafe/tree-spec-editor react react-dom reactflow react-bootstrap
34
+ npm install @signalsafe/tree-spec-editor @signalsafe/tree-spec-editor-react @signalsafe/tree-spec-editor-core @signalsafe/tree-spec react react-dom reactflow react-bootstrap bootstrap
35
+ ```
36
+
37
+ Load Bootstrap CSS in your app. Import React Flow CSS as documented in `@signalsafe/tree-spec-editor-react`.
38
+
39
+ ## Development
40
+
41
+ `yarn build` uses `tsconfig.build.json` and resolves `@signalsafe/*` from `node_modules`. Ecosystem sibling `paths` in `tsconfig.json` apply to local typecheck/tests only.
42
+
43
+ ```bash
44
+ yarn install
45
+ yarn build
46
+ yarn test
47
+ yarn typecheck
11
48
  ```
12
49
 
13
- The package ships React components that use `react-bootstrap` primitives (cards, buttons, form controls). The consuming app must install `react-bootstrap@^2.10.0` and load Bootstrap CSS in the usual way.
50
+ ## Security
51
+
52
+ See [SECURITY.md](./SECURITY.md). Host applications must enforce authorization, validate TreeSpec server-side, and control publish permissions.
53
+
54
+ ## Changelog and releases
55
+
56
+ - [CHANGELOG.md](./CHANGELOG.md)
57
+ - [RELEASING.md](./RELEASING.md)
58
+
59
+ ---
60
+
61
+ ## Detailed component reference
62
+
63
+ The sections below document panels, modals, toolbar items, and integration patterns. Import from **`@signalsafe/tree-spec-editor`** package root only (no subpath exports).
14
64
 
15
65
  ## Source layout (maintainers)
16
66
 
17
- Published consumers import only the package root (`@signalsafe/tree-spec-editor`). This package is the **React + Bootstrap UI shell** in the layered editor stack:
67
+ Published consumers import only the package root. Layer stack:
18
68
 
19
69
  | Layer | Package | Owns |
20
70
  |-------|---------|------|
@@ -30,7 +80,7 @@ Published consumers import only the package root (`@signalsafe/tree-spec-editor`
30
80
  | `src/lib/panelHelpers.ts` | `getIssueSeverityBadgeClass` (Bootstrap-flavored — Material / Angular shells ship their own equivalent) |
31
81
  | `src/index.ts` | Public barrel — **do not** import from subpaths in apps. Re-exports the canvas from `@signalsafe/tree-spec-editor-react` and the framework-agnostic surface from `@signalsafe/tree-spec-editor-core` |
32
82
 
33
- Tests live under `tests/panels/`, `tests/modals/`, plus `tests/index.test.ts` for the barrel. The canvas test lives in **`packages/tree-spec-editor-react/tests/`** and the framework-agnostic helper tests live in **`packages/tree-spec-editor-core/tests/`**.
83
+ Tests live under `tests/panels/`, `tests/modals/`, and `tests/index.test.ts` in this repo. Canvas tests live in **`tree-spec-editor-react`**; core helper tests live in **`tree-spec-editor-core`**.
34
84
 
35
85
  ## Choosing the right package
36
86
 
@@ -51,11 +101,11 @@ Tests live under `tests/panels/`, `tests/modals/`, plus `tests/index.test.ts` fo
51
101
 
52
102
  This package (`@signalsafe/tree-spec-editor`) **remains the Bootstrap reference shell** — it does not become Material, Angular, or Vue.
53
103
 
54
- See [docs/ai/packages-editor-architecture.md](../../docs/ai/packages-editor-architecture.md).
104
+ See package READMEs in the [`tree-spec-editor-core`](https://github.com/SignalSafeSoftware/tree-spec-editor-core) and [`tree-spec-editor-react`](https://github.com/SignalSafeSoftware/tree-spec-editor-react) repos for layer rules.
55
105
 
56
- ## Full-stack host import pattern
106
+ ## Host import pattern
57
107
 
58
- The reference host ([`ScenarioVersionGraphEditorPage`](../../frontend/shared/domains/content/ScenarioVersionGraphEditorPage.tsx)) imports from **three** packages:
108
+ Typical host apps import from **three** packages:
59
109
 
60
110
  ```tsx
61
111
  // Bootstrap UI shell — panels, modals, toolbar, canvas default export
@@ -78,9 +128,9 @@ The smallest useful integration is:
78
128
  2. Render `TreeSpecGraphEditor`.
79
129
  3. Replace the state value in `onChange`.
80
130
 
81
- The screenshot below was captured from the exact example tree in this section.
131
+ The example below uses a minimal in-memory tree (screenshot assets are not bundled in the npm package).
82
132
 
83
- ![Happy path editor example](https://raw.githubusercontent.com/denverprogrammer/DeliveryPlus/main/packages/tree-spec-editor/docs/tree-spec-editor-happy-path.png)
133
+ <!-- Screenshot: add your own capture when integrating the editor in your app -->
84
134
 
85
135
  ```tsx
86
136
  import { useState, type JSX } from 'react';
@@ -179,9 +229,9 @@ export function ExampleTreeSpecEditor(): JSX.Element {
179
229
 
180
230
  Pass `issues` when you want the editor to highlight problem nodes and edges.
181
231
 
182
- The screenshot below was captured from the exact example tree in this section.
232
+ The example below demonstrates validation highlighting (screenshot assets are not bundled in the npm package).
183
233
 
184
- ![Validation issues example](https://raw.githubusercontent.com/denverprogrammer/DeliveryPlus/main/packages/tree-spec-editor/docs/tree-spec-editor-issues.png)
234
+ <!-- Screenshot: add your own capture when integrating the editor in your app -->
185
235
 
186
236
  ```tsx
187
237
  import { useMemo, useState, type JSX } from 'react';
@@ -611,7 +661,7 @@ Right-rail panel for **canvas-only** styling. Combines:
611
661
 
612
662
  Scenario-level default edge routing lives in `GraphEditorInfoPanel`, not here.
613
663
 
614
- Hosts typically pair node fields with a project-specific component (for example `NodeAppearanceFields` in `frontend/shared`):
664
+ Hosts typically pair node fields with a project-specific component:
615
665
 
616
666
  ```tsx
617
667
  import { AppearancePanel, InspectorPanel } from '@signalsafe/tree-spec-editor';
@@ -0,0 +1,14 @@
1
+ # Standalone export
2
+
3
+ This tree was generated by `scripts/export-standalone-npm-package.sh tree-spec-editor` from the DeliveryPlus monorepo.
4
+
5
+ ```bash
6
+ git init
7
+ git branch -M main
8
+ git add .
9
+ git commit -m "Sync tree-spec-editor from DeliveryPlus"
10
+ git remote add origin git@github.com:SignalSafeSoftware/tree-spec-editor.git
11
+ git push -u origin main
12
+ ```
13
+
14
+ See `RELEASING.md` for npm publish steps.
package/dist/index.d.ts CHANGED
@@ -23,38 +23,38 @@
23
23
  */
24
24
  export { default } from '@signalsafe/tree-spec-editor-react';
25
25
  export type { TreeSpecGraphEditorProps, GraphEditorVersionInfo } from '@signalsafe/tree-spec-editor-react';
26
- export { default as IssuesPanel } from './panels/IssuesPanel';
27
- export type { IssuesPanelProps } from './panels/IssuesPanel';
28
- export { default as GraphEditorInfoPanel } from './panels/GraphEditorInfoPanel';
29
- export type { GraphEditorInfoPanelProps } from './panels/GraphEditorInfoPanel';
30
- export { default as NodesPanel } from './panels/NodesPanel';
31
- export type { NodesPanelProps } from './panels/NodesPanel';
32
- export { default as AdvancedJsonPanel } from './panels/AdvancedJsonPanel';
33
- export type { AdvancedJsonPanelProps } from './panels/AdvancedJsonPanel';
34
- export { default as InspectorPanel, DEFAULT_OUTCOME_OPTIONS } from './panels/InspectorPanel';
35
- export type { InspectorPanelProps, InspectorNodeRenderContext, InspectorChoiceRenderContext, } from './panels/InspectorPanel';
36
- export { default as AppearancePanel } from './panels/AppearancePanel';
37
- export type { AppearancePanelProps } from './panels/AppearancePanel';
38
- export { default as SelectedEdgePanel } from './panels/SelectedEdgePanel';
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';
45
- export { default as PublishReviewModal } from './modals/PublishReviewModal';
46
- export type { PublishReviewModalProps } from './modals/PublishReviewModal';
47
- export { default as DraftHistoryModal } from './modals/DraftHistoryModal';
48
- export type { DraftHistoryModalProps } from './modals/DraftHistoryModal';
49
- export { default as AuditLogModal } from './modals/AuditLogModal';
50
- export type { AuditLogModalProps } from './modals/AuditLogModal';
51
- export { default as ToolbarPanel, TOOLBAR_ITEM_KIND } from './panels/ToolbarPanel';
52
- export type { ToolbarPanelProps, ToolbarItem, ToolbarItemKind, ToolbarButtonItem, ToolbarDropdownItem, ToolbarDropdownEntry, ToolbarBadgeItem, ToolbarTextItem, ToolbarCustomItem, } from './panels/ToolbarPanel';
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';
55
- export { default as PanelHeaderCollapseCarets } from './lib/PanelHeaderCollapseCarets';
56
- export { buildDefaultToolbarSpec } from './lib/buildDefaultToolbarSpec';
57
- export type { BuildDefaultToolbarSpecOptions, DefaultToolbarActions, DefaultToolbarCapabilities, DefaultToolbarLabels, DefaultToolbarNodeType, DefaultToolbarState, DefaultToolbarTemplate, } from './lib/buildDefaultToolbarSpec';
26
+ export { default as IssuesPanel } from './panels/IssuesPanel.js';
27
+ export type { IssuesPanelProps } from './panels/IssuesPanel.js';
28
+ export { default as GraphEditorInfoPanel } from './panels/GraphEditorInfoPanel.js';
29
+ export type { GraphEditorInfoPanelProps } from './panels/GraphEditorInfoPanel.js';
30
+ export { default as NodesPanel } from './panels/NodesPanel.js';
31
+ export type { NodesPanelProps } from './panels/NodesPanel.js';
32
+ export { default as AdvancedJsonPanel } from './panels/AdvancedJsonPanel.js';
33
+ export type { AdvancedJsonPanelProps } from './panels/AdvancedJsonPanel.js';
34
+ export { default as InspectorPanel, DEFAULT_OUTCOME_OPTIONS } from './panels/InspectorPanel.js';
35
+ export type { InspectorPanelProps, InspectorNodeRenderContext, InspectorChoiceRenderContext, } from './panels/InspectorPanel.js';
36
+ export { default as AppearancePanel } from './panels/AppearancePanel.js';
37
+ export type { AppearancePanelProps } from './panels/AppearancePanel.js';
38
+ export { default as SelectedEdgePanel } from './panels/SelectedEdgePanel.js';
39
+ export type { SelectedEdgePanelProps } from './panels/SelectedEdgePanel.js';
40
+ export { default as ChoiceTemplatesPanel } from './panels/ChoiceTemplatesPanel.js';
41
+ export type { ChoiceTemplatesPanelProps, ChoiceTemplateItem, ChoicePresetItem } from './panels/ChoiceTemplatesPanel.js';
42
+ export type { ChoiceTypeOption } from './panels/InspectorPanel.js';
43
+ export { default as ChoiceEdgeAppearanceFields } from './panels/ChoiceEdgeAppearanceFields.js';
44
+ export type { ChoiceEdgeAppearanceFieldsProps } from './panels/ChoiceEdgeAppearanceFields.js';
45
+ export { default as PublishReviewModal } from './modals/PublishReviewModal.js';
46
+ export type { PublishReviewModalProps } from './modals/PublishReviewModal.js';
47
+ export { default as DraftHistoryModal } from './modals/DraftHistoryModal.js';
48
+ export type { DraftHistoryModalProps } from './modals/DraftHistoryModal.js';
49
+ export { default as AuditLogModal } from './modals/AuditLogModal.js';
50
+ export type { AuditLogModalProps } from './modals/AuditLogModal.js';
51
+ export { default as ToolbarPanel, TOOLBAR_ITEM_KIND } from './panels/ToolbarPanel.js';
52
+ export type { ToolbarPanelProps, ToolbarItem, ToolbarItemKind, ToolbarButtonItem, ToolbarDropdownItem, ToolbarDropdownEntry, ToolbarBadgeItem, ToolbarTextItem, ToolbarCustomItem, } from './panels/ToolbarPanel.js';
53
+ export { getIssueSeverityBadgeClass } from './lib/panelHelpers.js';
54
+ export { LIST_SELECTION_CLASS, CANVAS_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS, CANVAS_SELECTION_TEXT_CLASS } from './lib/selectionStyles.js';
55
+ export { default as PanelHeaderCollapseCarets } from './lib/PanelHeaderCollapseCarets.js';
56
+ export { buildDefaultToolbarSpec } from './lib/buildDefaultToolbarSpec.js';
57
+ export type { BuildDefaultToolbarSpecOptions, DefaultToolbarActions, DefaultToolbarCapabilities, DefaultToolbarLabels, DefaultToolbarNodeType, DefaultToolbarState, DefaultToolbarTemplate, } from './lib/buildDefaultToolbarSpec.js';
58
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
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';
60
60
  export type { TreeSpecIssue, TreeSpecWire } from '@signalsafe/tree-spec';
package/dist/index.js CHANGED
@@ -22,23 +22,23 @@
22
22
  * - `lib/` — UI-flavored helpers (Bootstrap severity badge classes)
23
23
  */
24
24
  export { default } from '@signalsafe/tree-spec-editor-react';
25
- export { default as IssuesPanel } from './panels/IssuesPanel';
26
- export { default as GraphEditorInfoPanel } from './panels/GraphEditorInfoPanel';
27
- export { default as NodesPanel } from './panels/NodesPanel';
28
- export { default as AdvancedJsonPanel } from './panels/AdvancedJsonPanel';
29
- export { default as InspectorPanel, DEFAULT_OUTCOME_OPTIONS } from './panels/InspectorPanel';
30
- export { default as AppearancePanel } from './panels/AppearancePanel';
31
- export { default as SelectedEdgePanel } from './panels/SelectedEdgePanel';
32
- export { default as ChoiceTemplatesPanel } from './panels/ChoiceTemplatesPanel';
33
- export { default as ChoiceEdgeAppearanceFields } from './panels/ChoiceEdgeAppearanceFields';
34
- export { default as PublishReviewModal } from './modals/PublishReviewModal';
35
- export { default as DraftHistoryModal } from './modals/DraftHistoryModal';
36
- export { default as AuditLogModal } from './modals/AuditLogModal';
37
- export { default as ToolbarPanel, TOOLBAR_ITEM_KIND } from './panels/ToolbarPanel';
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';
40
- export { default as PanelHeaderCollapseCarets } from './lib/PanelHeaderCollapseCarets';
41
- export { buildDefaultToolbarSpec } from './lib/buildDefaultToolbarSpec';
25
+ export { default as IssuesPanel } from './panels/IssuesPanel.js';
26
+ export { default as GraphEditorInfoPanel } from './panels/GraphEditorInfoPanel.js';
27
+ export { default as NodesPanel } from './panels/NodesPanel.js';
28
+ export { default as AdvancedJsonPanel } from './panels/AdvancedJsonPanel.js';
29
+ export { default as InspectorPanel, DEFAULT_OUTCOME_OPTIONS } from './panels/InspectorPanel.js';
30
+ export { default as AppearancePanel } from './panels/AppearancePanel.js';
31
+ export { default as SelectedEdgePanel } from './panels/SelectedEdgePanel.js';
32
+ export { default as ChoiceTemplatesPanel } from './panels/ChoiceTemplatesPanel.js';
33
+ export { default as ChoiceEdgeAppearanceFields } from './panels/ChoiceEdgeAppearanceFields.js';
34
+ export { default as PublishReviewModal } from './modals/PublishReviewModal.js';
35
+ export { default as DraftHistoryModal } from './modals/DraftHistoryModal.js';
36
+ export { default as AuditLogModal } from './modals/AuditLogModal.js';
37
+ export { default as ToolbarPanel, TOOLBAR_ITEM_KIND } from './panels/ToolbarPanel.js';
38
+ export { getIssueSeverityBadgeClass } from './lib/panelHelpers.js';
39
+ export { LIST_SELECTION_CLASS, CANVAS_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS, CANVAS_SELECTION_TEXT_CLASS } from './lib/selectionStyles.js';
40
+ export { default as PanelHeaderCollapseCarets } from './lib/PanelHeaderCollapseCarets.js';
41
+ export { buildDefaultToolbarSpec } from './lib/buildDefaultToolbarSpec.js';
42
42
  /* ------------------------------------------------------------------------- */
43
43
  /* Framework-agnostic re-exports from @signalsafe/tree-spec-editor-core. */
44
44
  /* Hosts may consume these directly from `-core` to skip the React surface. */
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
3
  import { Button } from 'react-bootstrap';
4
- import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets';
4
+ import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
5
5
  const DEFAULT_TITLE = 'Advanced JSON (read-only)';
6
6
  export default function AdvancedJsonPanel({ children, title = DEFAULT_TITLE, subtitle, onExpandAll, onCollapseAll, expandAllLabel = 'Expand all', collapseAllLabel = 'Compress all', className, }) {
7
7
  const [expanded, setExpanded] = useState(true);
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import type { ReactNode } from 'react';
6
6
  import { type ChoiceEdgeHints, type EditorNode, type EditorTransition, type EditorTree } from '@signalsafe/tree-spec-editor-core';
7
- import type { InspectorNodeRenderContext } from './InspectorPanel';
7
+ import type { InspectorNodeRenderContext } from './InspectorPanel.js';
8
8
  export interface AppearancePanelProps {
9
9
  tree: EditorTree;
10
10
  selectedNode: EditorNode | null;
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
3
  import { getTransition, } from '@signalsafe/tree-spec-editor-core';
4
- import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets';
5
- import { PanelNodeLink } from '../lib/panelNodeLink';
6
- import ChoiceEdgeAppearanceFields from './ChoiceEdgeAppearanceFields';
4
+ import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
5
+ import { PanelNodeLink } from '../lib/panelNodeLink.js';
6
+ import ChoiceEdgeAppearanceFields from './ChoiceEdgeAppearanceFields.js';
7
7
  function resolveActiveChoiceId(choices, selectedEdge, focusChoiceId) {
8
8
  if (selectedEdge)
9
9
  return selectedEdge.fromChoiceId;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
3
  import { Button, Card } from 'react-bootstrap';
4
- import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets';
4
+ import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
5
5
  export default function ChoiceTemplatesPanel({ templates, selectedNodeId, isPublished = false, onApplyTemplate, }) {
6
6
  const [expanded, setExpanded] = useState(true);
7
7
  const disabled = isPublished || !selectedNodeId;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
3
  import { Badge, Form, Table } from 'react-bootstrap';
4
- import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets';
4
+ import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
5
5
  import { EDITOR_EDGE_TYPE_OPTIONS, getAutosaveStatusLabel, } from '@signalsafe/tree-spec-editor-core';
6
6
  function defaultFormatTimestamp(iso) {
7
7
  return new Date(iso).toLocaleString();
@@ -1,4 +1,4 @@
1
- import { type InspectorPanelProps } from './inspector/types';
2
- export { DEFAULT_OUTCOME_OPTIONS, type ChoiceTypeOption, type InspectorChoiceRenderContext, type InspectorNodeRenderContext, type InspectorPanelProps, } from './inspector/types';
1
+ import { type InspectorPanelProps } from './inspector/types.js';
2
+ export { DEFAULT_OUTCOME_OPTIONS, type ChoiceTypeOption, type InspectorChoiceRenderContext, type InspectorNodeRenderContext, type InspectorPanelProps, } from './inspector/types.js';
3
3
  export default function InspectorPanel({ tree, selectedNode, focusChoiceId, isPublished, onUpdateSelectedNode, onAddChoice, onDeleteChoice, onMoveChoice, onSetChoiceTarget, onSetChoiceOutcome, outcomeOptions, hideOutcomeField, renderExtraNodeFields, renderExtraChoiceFields, choiceTypes, onSetChoiceType, title, emptyStateText, typeHelperText, onDeleteSelectedNode, onFocusChoice, }: Readonly<InspectorPanelProps>): import("react").JSX.Element;
4
4
  //# sourceMappingURL=InspectorPanel.d.ts.map
@@ -14,10 +14,10 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
14
14
  * - `renderExtraChoiceFields`: render additional UI below each choice card.
15
15
  * - `choiceTypes` / `onSetChoiceType`: host-defined choice type catalog (stable ids).
16
16
  */
17
- import ChoiceEditorList from './inspector/ChoiceEditorList';
18
- import RequiredNodeCard from './inspector/RequiredNodeCard';
19
- import { DEFAULT_OUTCOME_OPTIONS, DEFAULT_TYPE_HELPER_TEXT, } from './inspector/types';
20
- export { DEFAULT_OUTCOME_OPTIONS, } from './inspector/types';
17
+ import ChoiceEditorList from './inspector/ChoiceEditorList.js';
18
+ import RequiredNodeCard from './inspector/RequiredNodeCard.js';
19
+ import { DEFAULT_OUTCOME_OPTIONS, DEFAULT_TYPE_HELPER_TEXT, } from './inspector/types.js';
20
+ export { DEFAULT_OUTCOME_OPTIONS, } from './inspector/types.js';
21
21
  export default function InspectorPanel({ tree, selectedNode, focusChoiceId = null, isPublished = false, onUpdateSelectedNode, onAddChoice, onDeleteChoice, onMoveChoice, onSetChoiceTarget, onSetChoiceOutcome, outcomeOptions = DEFAULT_OUTCOME_OPTIONS, hideOutcomeField = false, renderExtraNodeFields, renderExtraChoiceFields, choiceTypes, onSetChoiceType, title = 'Required', emptyStateText = 'Select a node to edit it.', typeHelperText = DEFAULT_TYPE_HELPER_TEXT, onDeleteSelectedNode, onFocusChoice, }) {
22
22
  return (_jsx("div", { children: selectedNode ? (_jsxs(_Fragment, { children: [_jsx(RequiredNodeCard, { tree: tree, selectedNode: selectedNode, isPublished: isPublished, title: title, typeHelperText: typeHelperText, onUpdateSelectedNode: onUpdateSelectedNode, onDeleteSelectedNode: onDeleteSelectedNode, renderExtraNodeFields: renderExtraNodeFields }), _jsx(ChoiceEditorList, { tree: tree, selectedNode: selectedNode, focusChoiceId: focusChoiceId, isPublished: isPublished, onAddChoice: onAddChoice, onUpdateSelectedNode: onUpdateSelectedNode, onDeleteChoice: onDeleteChoice, onMoveChoice: onMoveChoice, onSetChoiceTarget: onSetChoiceTarget, onSetChoiceOutcome: onSetChoiceOutcome, outcomeOptions: outcomeOptions, hideOutcomeField: hideOutcomeField, renderExtraChoiceFields: renderExtraChoiceFields, choiceTypes: choiceTypes, onSetChoiceType: onSetChoiceType, onFocusChoice: onFocusChoice })] })) : (_jsx("div", { className: "text-muted", children: _jsx("em", { children: emptyStateText }) })) }));
23
23
  }
@@ -2,9 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { useMemo, useState } from 'react';
3
3
  import { Form } from 'react-bootstrap';
4
4
  import { buildStableEntries, GRAPH_SELECTION_KIND, } from '@signalsafe/tree-spec-editor-core';
5
- import { getIssueSeverityBadgeClass } from '../lib/panelHelpers';
6
- import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets';
7
- import { LIST_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS } from '../lib/selectionStyles';
5
+ import { getIssueSeverityBadgeClass } from '../lib/panelHelpers.js';
6
+ import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
7
+ import { LIST_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS } from '../lib/selectionStyles.js';
8
8
  function defaultFormatTimestamp(iso) {
9
9
  return new Date(iso).toLocaleString();
10
10
  }
@@ -2,8 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
3
  import { Form } from 'react-bootstrap';
4
4
  import { GRAPH_SELECTION_KIND, TREE_SPEC_NODE_TYPE_PRESETS, } from '@signalsafe/tree-spec-editor-core';
5
- import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets';
6
- import { LIST_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS } from '../lib/selectionStyles';
5
+ import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
6
+ import { LIST_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS } from '../lib/selectionStyles.js';
7
7
  const DEFAULT_TIP_TEXT = 'Tip: connect choices by dragging the blue dots. Shortcuts: \u2318S save, \u2318\u21E7V validate, \u2318D duplicate, Del delete.';
8
8
  const TYPE_SORT_ORDER = new Map(TREE_SPEC_NODE_TYPE_PRESETS.map((t, i) => [t, i]));
9
9
  function choiceLine(n) {
@@ -6,9 +6,9 @@
6
6
  */
7
7
  import type { ReactNode } from 'react';
8
8
  import type { EditorTransition } from '@signalsafe/tree-spec-editor-core';
9
- import { type PanelNodeLinkContext } from '../lib/panelNodeLink';
9
+ import { type PanelNodeLinkContext } from '../lib/panelNodeLink.js';
10
10
  export type SelectedEdgeDetailsContext = PanelNodeLinkContext;
11
- export { PanelNodeLink } from '../lib/panelNodeLink';
11
+ export { PanelNodeLink } from '../lib/panelNodeLink.js';
12
12
  export interface SelectedEdgePanelProps {
13
13
  selectedEdge: EditorTransition | null;
14
14
  /** Select a node when its id is clicked in the default details line. */
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { renderDefaultEdgeBreadcrumb } from '../lib/panelNodeLink';
3
- export { PanelNodeLink } from '../lib/panelNodeLink';
2
+ import { renderDefaultEdgeBreadcrumb } from '../lib/panelNodeLink.js';
3
+ export { PanelNodeLink } from '../lib/panelNodeLink.js';
4
4
  export default function SelectedEdgePanel({ selectedEdge, onNodeSelect, title = 'Selected Edge', renderDetails = renderDefaultEdgeBreadcrumb, }) {
5
5
  if (!selectedEdge)
6
6
  return null;
@@ -1,6 +1,6 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import { type EditorChoice, type EditorNode, type EditorTree } from '@signalsafe/tree-spec-editor-core';
3
- import type { ChoiceTypeOption, InspectorChoiceRenderContext } from './types';
3
+ import type { ChoiceTypeOption, InspectorChoiceRenderContext } from './types.js';
4
4
  export default function ChoiceEditorCard({ choice, tree, selectedNode, focusChoiceId, isPublished, canMoveUp, canMoveDown, usedChoiceTypeIds, onUpdateSelectedNode, onDeleteChoice, onMoveChoice, onSetChoiceTarget, onSetChoiceOutcome, onSetChoiceType, choiceTypes, outcomeOptions, hideOutcomeField, renderExtraChoiceFields, onFocusChoice, }: Readonly<{
5
5
  choice: EditorChoice;
6
6
  tree: EditorTree;
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Form } from 'react-bootstrap';
3
3
  import { END_NODE_ID, getTransition, } from '@signalsafe/tree-spec-editor-core';
4
- import { LIST_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS } from '../../lib/selectionStyles';
5
- import { choiceActionIconProps } from './choiceActionIconProps';
4
+ import { LIST_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS } from '../../lib/selectionStyles.js';
5
+ import { choiceActionIconProps } from './choiceActionIconProps.js';
6
6
  export default function ChoiceEditorCard({ choice, tree, selectedNode, focusChoiceId, isPublished, canMoveUp, canMoveDown, usedChoiceTypeIds, onUpdateSelectedNode, onDeleteChoice, onMoveChoice, onSetChoiceTarget, onSetChoiceOutcome, onSetChoiceType, choiceTypes, outcomeOptions, hideOutcomeField, renderExtraChoiceFields, onFocusChoice, }) {
7
7
  const transition = getTransition(tree, selectedNode.id, choice.id);
8
8
  const targetNodeId = transition?.toNodeId ?? '';
@@ -1,6 +1,6 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { EditorNode, EditorTree } from '@signalsafe/tree-spec-editor-core';
3
- import type { ChoiceTypeOption, InspectorChoiceRenderContext } from './types';
3
+ import type { ChoiceTypeOption, InspectorChoiceRenderContext } from './types.js';
4
4
  export default function ChoiceEditorList({ tree, selectedNode, focusChoiceId, isPublished, onAddChoice, onUpdateSelectedNode, onDeleteChoice, onMoveChoice, onSetChoiceTarget, onSetChoiceOutcome, onSetChoiceType, choiceTypes, outcomeOptions, hideOutcomeField, renderExtraChoiceFields, onFocusChoice, }: Readonly<{
5
5
  tree: EditorTree;
6
6
  selectedNode: EditorNode;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
- import PanelHeaderCollapseCarets from '../../lib/PanelHeaderCollapseCarets';
4
- import ChoiceEditorCard from './ChoiceEditorCard';
3
+ import PanelHeaderCollapseCarets from '../../lib/PanelHeaderCollapseCarets.js';
4
+ import ChoiceEditorCard from './ChoiceEditorCard.js';
5
5
  export default function ChoiceEditorList({ tree, selectedNode, focusChoiceId, isPublished, onAddChoice, onUpdateSelectedNode, onDeleteChoice, onMoveChoice, onSetChoiceTarget, onSetChoiceOutcome, onSetChoiceType, choiceTypes, outcomeOptions, hideOutcomeField, renderExtraChoiceFields, onFocusChoice, }) {
6
6
  const choices = selectedNode.choices ?? [];
7
7
  const [choicesExpanded, setChoicesExpanded] = useState(true);
@@ -1,6 +1,6 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { EditorNode, EditorTree } from '@signalsafe/tree-spec-editor-core';
3
- import type { InspectorNodeRenderContext } from './types';
3
+ import type { InspectorNodeRenderContext } from './types.js';
4
4
  export default function RequiredNodeCard({ tree, selectedNode, isPublished, title, typeHelperText, onUpdateSelectedNode, onDeleteSelectedNode, renderExtraNodeFields, }: Readonly<{
5
5
  tree: EditorTree;
6
6
  selectedNode: EditorNode;
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
3
  import { Form } from 'react-bootstrap';
4
- import PanelHeaderCollapseCarets from '../../lib/PanelHeaderCollapseCarets';
5
- import NodeTypeField from './NodeTypeField';
4
+ import PanelHeaderCollapseCarets from '../../lib/PanelHeaderCollapseCarets.js';
5
+ import NodeTypeField from './NodeTypeField.js';
6
6
  export default function RequiredNodeCard({ tree, selectedNode, isPublished, title, typeHelperText, onUpdateSelectedNode, onDeleteSelectedNode, renderExtraNodeFields, }) {
7
7
  const [requiredExpanded, setRequiredExpanded] = useState(true);
8
8
  return (_jsxs("div", { className: "card", children: [_jsxs("div", { className: "card-header bg-body-secondary py-2 px-2 d-flex justify-content-between align-items-center gap-2", children: [_jsxs("div", { className: "d-flex align-items-center min-w-0", children: [_jsx("span", { className: "fw-semibold", children: title }), _jsx(PanelHeaderCollapseCarets, { expanded: requiredExpanded, onToggle: () => setRequiredExpanded((v) => !v) })] }), onDeleteSelectedNode ? (_jsx("button", { type: "button", className: "btn p-0 border-0 bg-transparent flex-shrink-0", "aria-label": "Delete node", title: "Delete node", disabled: isPublished, onClick: onDeleteSelectedNode, children: _jsx("i", { className: `bi bi-trash action-icon cursor-pointer${isPublished ? ' text-secondary opacity-50' : ' text-danger'}`, "aria-hidden": true }) })) : null] }), _jsxs("div", { className: `card-body${requiredExpanded ? '' : ' d-none'}`, "aria-hidden": !requiredExpanded, children: [_jsx(NodeTypeField, { selectedNode: selectedNode, isPublished: isPublished, onUpdateSelectedNode: onUpdateSelectedNode, typeHelperText: typeHelperText }), _jsxs(Form.Group, { className: "mb-2", children: [_jsx(Form.Label, { children: "Prompt" }), _jsx(Form.Control, { as: "textarea", rows: 4, value: selectedNode.prompt, onChange: (e) => onUpdateSelectedNode({ prompt: e.target.value }) })] }), renderExtraNodeFields
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signalsafe/tree-spec-editor",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "description": "Reusable TreeSpec graph editor (React Flow) and authoring helpers (no API or routing).",
6
6
  "license": "MIT",
@@ -41,6 +41,7 @@
41
41
  "engines": {
42
42
  "node": ">=18"
43
43
  },
44
+ "packageManager": "yarn@1.22.22",
44
45
  "publishConfig": {
45
46
  "access": "public"
46
47
  },
@@ -56,15 +57,16 @@
56
57
  "pack:check": "node ../../scripts/check-package-tarball.mjs --tgz \"../../dist/reusable-npm/signalsafe-tree-spec-editor-$npm_package_version.tgz\" --expect package/dist/index.js --expect package/dist/index.d.ts --expect package/package.json --expect package/README.md",
57
58
  "smoke:external": "node ../../scripts/smoke-tree-spec-editor-external-consumer.mjs",
58
59
  "smoke:published": "node ../../scripts/smoke-tree-spec-editor-external-consumer.mjs --source registry",
60
+ "smoke:package": "node scripts/smoke-package.mjs",
59
61
  "prepublishOnly": "npm run build",
60
62
  "prepare": "npm run build",
61
63
  "test": "vitest run",
62
64
  "test:monorepo": "cd ../../frontend && yarn vitest run --config vitest.tree-spec-editor.config.ts"
63
65
  },
64
66
  "dependencies": {
65
- "@signalsafe/tree-spec": "^0.3.1",
66
- "@signalsafe/tree-spec-editor-core": "^0.1.2",
67
- "@signalsafe/tree-spec-editor-react": "^0.1.2"
67
+ "@signalsafe/tree-spec": "^0.3.2",
68
+ "@signalsafe/tree-spec-editor-core": "^0.1.3",
69
+ "@signalsafe/tree-spec-editor-react": "^0.1.3"
68
70
  },
69
71
  "peerDependencies": {
70
72
  "react": "^18.0.0",
@@ -82,6 +84,7 @@
82
84
  "react-test-renderer": "^18.3.1",
83
85
  "reactflow": "^11.11.4",
84
86
  "typescript": "^5.4.2",
87
+ "@vitest/coverage-v8": "^3.2.4",
85
88
  "vitest": "^3.2.4"
86
89
  }
87
90
  }