@signalsafe/tree-spec-editor 0.1.2 → 0.2.1

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 (56) hide show
  1. package/README.md +657 -2
  2. package/dist/index.d.ts +48 -7
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +39 -5
  5. package/dist/lib/PanelHeaderCollapseCarets.d.ts +7 -0
  6. package/dist/lib/PanelHeaderCollapseCarets.d.ts.map +1 -0
  7. package/dist/lib/PanelHeaderCollapseCarets.js +5 -0
  8. package/dist/lib/buildDefaultToolbarSpec.d.ts +83 -0
  9. package/dist/lib/buildDefaultToolbarSpec.d.ts.map +1 -0
  10. package/dist/lib/buildDefaultToolbarSpec.js +167 -0
  11. package/dist/lib/panelHelpers.d.ts +3 -0
  12. package/dist/lib/panelHelpers.d.ts.map +1 -0
  13. package/dist/lib/panelHelpers.js +14 -0
  14. package/dist/modals/AuditLogModal.d.ts +21 -0
  15. package/dist/modals/AuditLogModal.d.ts.map +1 -0
  16. package/dist/modals/AuditLogModal.js +23 -0
  17. package/dist/modals/DraftHistoryModal.d.ts +34 -0
  18. package/dist/modals/DraftHistoryModal.d.ts.map +1 -0
  19. package/dist/modals/DraftHistoryModal.js +27 -0
  20. package/dist/modals/PublishReviewModal.d.ts +37 -0
  21. package/dist/modals/PublishReviewModal.d.ts.map +1 -0
  22. package/dist/modals/PublishReviewModal.js +25 -0
  23. package/dist/panels/AdvancedJsonPanel.d.ts +27 -0
  24. package/dist/panels/AdvancedJsonPanel.d.ts.map +1 -0
  25. package/dist/panels/AdvancedJsonPanel.js +11 -0
  26. package/dist/panels/GraphEditorInfoPanel.d.ts +20 -0
  27. package/dist/panels/GraphEditorInfoPanel.d.ts.map +1 -0
  28. package/dist/panels/GraphEditorInfoPanel.js +25 -0
  29. package/dist/panels/InspectorPanel.d.ts +79 -0
  30. package/dist/panels/InspectorPanel.d.ts.map +1 -0
  31. package/dist/panels/InspectorPanel.js +63 -0
  32. package/dist/panels/IssuesPanel.d.ts +33 -0
  33. package/dist/panels/IssuesPanel.d.ts.map +1 -0
  34. package/dist/panels/IssuesPanel.js +41 -0
  35. package/dist/panels/NodesPanel.d.ts +28 -0
  36. package/dist/panels/NodesPanel.d.ts.map +1 -0
  37. package/dist/panels/NodesPanel.js +48 -0
  38. package/dist/panels/SelectedEdgePanel.d.ts +18 -0
  39. package/dist/panels/SelectedEdgePanel.d.ts.map +1 -0
  40. package/dist/panels/SelectedEdgePanel.js +9 -0
  41. package/dist/panels/ToolbarPanel.d.ts +88 -0
  42. package/dist/panels/ToolbarPanel.d.ts.map +1 -0
  43. package/dist/panels/ToolbarPanel.js +59 -0
  44. package/package.json +7 -3
  45. package/dist/TreeSpecGraphEditor.d.ts +0 -16
  46. package/dist/TreeSpecGraphEditor.d.ts.map +0 -1
  47. package/dist/TreeSpecGraphEditor.js +0 -272
  48. package/dist/editorHelpers.d.ts +0 -16
  49. package/dist/editorHelpers.d.ts.map +0 -1
  50. package/dist/editorHelpers.js +0 -67
  51. package/dist/model.d.ts +0 -23
  52. package/dist/model.d.ts.map +0 -1
  53. package/dist/model.js +0 -1
  54. package/dist/treeLayout.d.ts +0 -11
  55. package/dist/treeLayout.d.ts.map +0 -1
  56. package/dist/treeLayout.js +0 -63
package/dist/index.d.ts CHANGED
@@ -1,12 +1,53 @@
1
1
  /**
2
2
  * @packageDocumentation
3
- * TreeSpec graph editor (React Flow) and authoring helpers. No API, routing, or simulator runtime.
3
+ * React + Bootstrap implementation of the TreeSpec graph editor.
4
+ *
5
+ * Layered architecture:
6
+ * - `@signalsafe/tree-spec` — wire contract (pure TS, no UI).
7
+ * - `@signalsafe/tree-spec-editor-core` — framework-agnostic model, helpers,
8
+ * and constants (no React, no DOM).
9
+ * - `@signalsafe/tree-spec-editor-react` — headless React: React Flow canvas
10
+ * (no UI library).
11
+ * - **`@signalsafe/tree-spec-editor`** (this package) — React + Bootstrap shell:
12
+ * sidebar panels, modals, toolbar, and the Bootstrap severity badge helper.
13
+ *
14
+ * The framework-agnostic surface from `-core` and the canvas from `-react`
15
+ * are re-exported from this barrel for consumer convenience. Hosts targeting
16
+ * alternative UI libraries (e.g. Material) should consume `-react` plus their
17
+ * own UI shell instead.
18
+ *
19
+ * Source layout:
20
+ * - `panels/` — sidebar / toolbar / inspector presentational components
21
+ * - `modals/` — authoring-flow dialogs
22
+ * - `lib/` — UI-flavored helpers (Bootstrap severity badge classes)
4
23
  */
5
- export { default } from './TreeSpecGraphEditor';
6
- export type { TreeSpecGraphEditorProps } from './TreeSpecGraphEditor';
7
- export { END_NODE_ID } from './model';
8
- export type { EditorChoice, EditorNode, EditorTransition, EditorTree, GraphEditorIssue, GraphSelection, ReactFlowEdgeChange, ReactFlowNodeChange, } from './model';
9
- export { safeUUID, getTransition, upsertTransition, deleteTransitionsForChoice, lintEditorTree, parsePydanticOutcomeErrors, TREE_SPEC_NODE_TYPE_PRESETS, } from './editorHelpers';
10
- export { autoLayoutTree, getNextSpawnPosition } from './treeLayout';
24
+ export { default } from '@signalsafe/tree-spec-editor-react';
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 SelectedEdgePanel } from './panels/SelectedEdgePanel';
37
+ export type { SelectedEdgePanelProps } from './panels/SelectedEdgePanel';
38
+ export { default as PublishReviewModal } from './modals/PublishReviewModal';
39
+ export type { PublishReviewModalProps } from './modals/PublishReviewModal';
40
+ export { default as DraftHistoryModal } from './modals/DraftHistoryModal';
41
+ export type { DraftHistoryModalProps } from './modals/DraftHistoryModal';
42
+ export { default as AuditLogModal } from './modals/AuditLogModal';
43
+ export type { AuditLogModalProps } from './modals/AuditLogModal';
44
+ export { default as ToolbarPanel, TOOLBAR_ITEM_KIND } from './panels/ToolbarPanel';
45
+ export type { ToolbarPanelProps, ToolbarItem, ToolbarItemKind, ToolbarButtonItem, ToolbarDropdownItem, ToolbarDropdownEntry, ToolbarBadgeItem, ToolbarTextItem, ToolbarCustomItem, } from './panels/ToolbarPanel';
46
+ export { getIssueSeverityBadgeClass } from './lib/panelHelpers';
47
+ export { default as PanelHeaderCollapseCarets } from './lib/PanelHeaderCollapseCarets';
48
+ export { buildDefaultToolbarSpec } from './lib/buildDefaultToolbarSpec';
49
+ 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';
11
52
  export type { TreeSpecIssue, TreeSpecWire } from '@signalsafe/tree-spec';
12
53
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,YAAY,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,YAAY,EACR,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,SAAS,CAAC;AAEjB,OAAO,EACH,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,0BAA0B,EAC1B,cAAc,EACd,0BAA0B,EAC1B,2BAA2B,GAC9B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAE7D,YAAY,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAE3G,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAChF,YAAY,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,YAAY,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC7F,YAAY,EACR,mBAAmB,EACnB,0BAA0B,EAC1B,4BAA4B,GAC/B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,YAAY,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,YAAY,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,YAAY,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACnF,YAAY,EACR,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GACpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAEvF,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,YAAY,EACR,8BAA8B,EAC9B,qBAAqB,EACrB,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,GACzB,MAAM,+BAA+B,CAAC;AAOvC,OAAO,EACH,WAAW,EACX,oBAAoB,EACpB,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,0BAA0B,EAC1B,cAAc,EACd,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,EAC3B,cAAc,EACd,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,yBAAyB,EACzB,wBAAwB,EACxB,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,aAAa,EACb,kBAAkB,GACrB,MAAM,mCAAmC,CAAC;AAE3C,YAAY,EACR,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,0BAA0B,GAC7B,MAAM,mCAAmC,CAAC;AAE3C,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,42 @@
1
1
  /**
2
2
  * @packageDocumentation
3
- * TreeSpec graph editor (React Flow) and authoring helpers. No API, routing, or simulator runtime.
3
+ * React + Bootstrap implementation of the TreeSpec graph editor.
4
+ *
5
+ * Layered architecture:
6
+ * - `@signalsafe/tree-spec` — wire contract (pure TS, no UI).
7
+ * - `@signalsafe/tree-spec-editor-core` — framework-agnostic model, helpers,
8
+ * and constants (no React, no DOM).
9
+ * - `@signalsafe/tree-spec-editor-react` — headless React: React Flow canvas
10
+ * (no UI library).
11
+ * - **`@signalsafe/tree-spec-editor`** (this package) — React + Bootstrap shell:
12
+ * sidebar panels, modals, toolbar, and the Bootstrap severity badge helper.
13
+ *
14
+ * The framework-agnostic surface from `-core` and the canvas from `-react`
15
+ * are re-exported from this barrel for consumer convenience. Hosts targeting
16
+ * alternative UI libraries (e.g. Material) should consume `-react` plus their
17
+ * own UI shell instead.
18
+ *
19
+ * Source layout:
20
+ * - `panels/` — sidebar / toolbar / inspector presentational components
21
+ * - `modals/` — authoring-flow dialogs
22
+ * - `lib/` — UI-flavored helpers (Bootstrap severity badge classes)
4
23
  */
5
- export { default } from './TreeSpecGraphEditor';
6
- export { END_NODE_ID } from './model';
7
- export { safeUUID, getTransition, upsertTransition, deleteTransitionsForChoice, lintEditorTree, parsePydanticOutcomeErrors, TREE_SPEC_NODE_TYPE_PRESETS, } from './editorHelpers';
8
- export { autoLayoutTree, getNextSpawnPosition } from './treeLayout';
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 SelectedEdgePanel } from './panels/SelectedEdgePanel';
31
+ export { default as PublishReviewModal } from './modals/PublishReviewModal';
32
+ export { default as DraftHistoryModal } from './modals/DraftHistoryModal';
33
+ export { default as AuditLogModal } from './modals/AuditLogModal';
34
+ export { default as ToolbarPanel, TOOLBAR_ITEM_KIND } from './panels/ToolbarPanel';
35
+ export { getIssueSeverityBadgeClass } from './lib/panelHelpers';
36
+ export { default as PanelHeaderCollapseCarets } from './lib/PanelHeaderCollapseCarets';
37
+ export { buildDefaultToolbarSpec } from './lib/buildDefaultToolbarSpec';
38
+ /* ------------------------------------------------------------------------- */
39
+ /* Framework-agnostic re-exports from @signalsafe/tree-spec-editor-core. */
40
+ /* Hosts may consume these directly from `-core` to skip the React surface. */
41
+ /* ------------------------------------------------------------------------- */
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';
@@ -0,0 +1,7 @@
1
+ export interface PanelHeaderCollapseCaretsProps {
2
+ expanded: boolean;
3
+ onToggle: () => void;
4
+ }
5
+ /** Collapse/expand carets for card panel headers. */
6
+ export default function PanelHeaderCollapseCarets({ expanded, onToggle, }: Readonly<PanelHeaderCollapseCaretsProps>): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=PanelHeaderCollapseCarets.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /** Collapse/expand carets for card panel headers. */
3
+ export default function PanelHeaderCollapseCarets({ expanded, onToggle, }) {
4
+ return (_jsx("button", { type: "button", className: "btn btn-sm btn-link text-body-secondary p-0 ms-1", "aria-expanded": expanded, "aria-label": expanded ? 'Collapse panel' : 'Expand panel', onClick: onToggle, children: _jsx("i", { className: `bi bi-caret-${expanded ? 'up' : 'down'}`, "aria-hidden": true }) }));
5
+ }
@@ -0,0 +1,83 @@
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';
4
+ 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
+ }
81
+ /** Build the default TreeSpec editor toolbar item list from state, actions, and capability flags. */
82
+ export declare function buildDefaultToolbarSpec(options: BuildDefaultToolbarSpecOptions): ToolbarItem[];
83
+ //# sourceMappingURL=buildDefaultToolbarSpec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildDefaultToolbarSpec.d.ts","sourceRoot":"","sources":["../../src/lib/buildDefaultToolbarSpec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,167 @@
1
+ import { getAutosaveStatusLabel, } from '@signalsafe/tree-spec-editor-core';
2
+ import { TOOLBAR_ITEM_KIND } from '../panels/ToolbarPanel.js';
3
+ export { AUTOSAVE_STATUS } from '@signalsafe/tree-spec-editor-core';
4
+ function appendBackSlot(items, backSlot) {
5
+ items.push({
6
+ kind: TOOLBAR_ITEM_KIND.CUSTOM,
7
+ id: backSlot.id ?? 'back',
8
+ render: backSlot.render,
9
+ });
10
+ }
11
+ function appendAddDropdown(items, nodeTypes, actions, labels, isPublished) {
12
+ const addEntries = nodeTypes.map((entry, index) => {
13
+ if (entry.divider) {
14
+ return { id: entry.id ?? `divider-${index}`, label: '', divider: true };
15
+ }
16
+ const type = entry.type ?? 'prompt';
17
+ return {
18
+ id: entry.id ?? `add-${type}`,
19
+ label: entry.label ?? type,
20
+ onClick: () => actions.addNodeOfType(type, entry.patch),
21
+ };
22
+ });
23
+ if (addEntries.length === 0)
24
+ return;
25
+ items.push({
26
+ kind: TOOLBAR_ITEM_KIND.DROPDOWN,
27
+ id: 'add',
28
+ label: labels.add ?? '+ Add',
29
+ disabled: isPublished,
30
+ entries: addEntries,
31
+ });
32
+ }
33
+ function appendTemplatesDropdown(items, templates, actions, labels, isPublished) {
34
+ if (templates.length === 0)
35
+ return;
36
+ items.push({
37
+ kind: TOOLBAR_ITEM_KIND.DROPDOWN,
38
+ id: 'templates',
39
+ label: labels.templates ?? 'Templates',
40
+ disabled: isPublished,
41
+ entries: templates.map((t) => ({
42
+ id: t.id,
43
+ label: t.label,
44
+ onClick: () => actions.insertTemplate(t.spec),
45
+ })),
46
+ });
47
+ }
48
+ function appendLayoutButtons(items, state, actions, labels) {
49
+ const { isPublished, hasTree } = state;
50
+ items.push({
51
+ kind: TOOLBAR_ITEM_KIND.BUTTON,
52
+ id: 'reset-view',
53
+ label: labels.resetView ?? 'Reset view',
54
+ disabled: !hasTree,
55
+ onClick: () => actions.triggerResetView(),
56
+ }, {
57
+ kind: TOOLBAR_ITEM_KIND.BUTTON,
58
+ id: 'auto-layout',
59
+ label: labels.autoLayout ?? 'Auto layout',
60
+ disabled: !hasTree || isPublished,
61
+ onClick: () => actions.autoLayout(),
62
+ });
63
+ }
64
+ function appendCapabilityButtons(items, capabilities, state, actions, labels) {
65
+ const { isPublished, creatingSnapshot, cloning, hasTree } = state;
66
+ if (capabilities.canValidate) {
67
+ items.push({
68
+ kind: TOOLBAR_ITEM_KIND.BUTTON,
69
+ id: 'validate',
70
+ label: labels.validate ?? 'Validate',
71
+ disabled: !hasTree,
72
+ onClick: () => void actions.validate(),
73
+ });
74
+ }
75
+ if (capabilities.canListSnapshots) {
76
+ items.push({
77
+ kind: TOOLBAR_ITEM_KIND.BUTTON,
78
+ id: 'draft-history',
79
+ label: labels.history ?? 'Draft history',
80
+ onClick: () => actions.setShowDraftHistory(true),
81
+ });
82
+ }
83
+ if (capabilities.canListAudit) {
84
+ items.push({
85
+ kind: TOOLBAR_ITEM_KIND.BUTTON,
86
+ id: 'audit',
87
+ label: labels.audit ?? 'Audit log',
88
+ onClick: () => actions.setShowAudit(true),
89
+ });
90
+ }
91
+ if (capabilities.canCreateSnapshot) {
92
+ items.push({
93
+ kind: TOOLBAR_ITEM_KIND.BUTTON,
94
+ id: 'snapshot',
95
+ label: creatingSnapshot ? 'Creating…' : (labels.snapshot ?? 'Snapshot'),
96
+ disabled: isPublished || creatingSnapshot || !hasTree,
97
+ onClick: () => void actions.createSnapshot(),
98
+ });
99
+ }
100
+ if (capabilities.canCloneToDraft) {
101
+ items.push({
102
+ kind: TOOLBAR_ITEM_KIND.BUTTON,
103
+ id: 'clone-to-draft',
104
+ label: cloning ? 'Cloning…' : (labels.clone ?? 'Clone to draft'),
105
+ disabled: cloning,
106
+ onClick: () => void actions.cloneToDraft(),
107
+ });
108
+ }
109
+ }
110
+ function appendSaveAndPublish(items, capabilities, state, actions, labels, preview) {
111
+ const { isPublished, saving, publishing, canPublish, hasTree } = state;
112
+ items.push({
113
+ kind: TOOLBAR_ITEM_KIND.BUTTON,
114
+ id: 'save-draft',
115
+ label: saving ? 'Saving…' : (labels.save ?? 'Save draft'),
116
+ disabled: isPublished || saving || !hasTree,
117
+ onClick: () => void actions.saveDraft(),
118
+ });
119
+ if (capabilities.canPublish) {
120
+ items.push({
121
+ kind: TOOLBAR_ITEM_KIND.BUTTON,
122
+ id: 'publish',
123
+ label: publishing ? 'Publishing…' : (labels.publish ?? 'Publish'),
124
+ disabled: isPublished || publishing || !canPublish,
125
+ onClick: () => actions.setShowPublishModal(true),
126
+ });
127
+ }
128
+ if (preview) {
129
+ items.push({
130
+ kind: TOOLBAR_ITEM_KIND.BUTTON,
131
+ id: 'preview',
132
+ label: labels.preview ?? 'Preview',
133
+ disabled: preview.disabled ?? false,
134
+ onClick: preview.onClick,
135
+ });
136
+ }
137
+ }
138
+ function appendStatusFooter(items, state, labels, extraItems) {
139
+ const { isPublished, autosaveStatus } = state;
140
+ items.push({
141
+ kind: TOOLBAR_ITEM_KIND.BADGE,
142
+ id: 'status',
143
+ label: isPublished
144
+ ? (labels.publishedBadge ?? 'Published')
145
+ : (labels.draftBadge ?? 'Draft'),
146
+ variant: isPublished ? 'success' : 'secondary',
147
+ }, {
148
+ kind: TOOLBAR_ITEM_KIND.TEXT,
149
+ id: 'autosave',
150
+ content: getAutosaveStatusLabel(autosaveStatus),
151
+ }, ...extraItems);
152
+ }
153
+ /** Build the default TreeSpec editor toolbar item list from state, actions, and capability flags. */
154
+ export function buildDefaultToolbarSpec(options) {
155
+ const { state, actions, capabilities = {}, nodeTypes = [], templates = [], backSlot, preview, labels = {}, extraItems = [], } = options;
156
+ const items = [];
157
+ if (backSlot) {
158
+ appendBackSlot(items, backSlot);
159
+ }
160
+ appendAddDropdown(items, nodeTypes, actions, labels, state.isPublished);
161
+ appendTemplatesDropdown(items, templates, actions, labels, state.isPublished);
162
+ appendLayoutButtons(items, state, actions, labels);
163
+ appendCapabilityButtons(items, capabilities, state, actions, labels);
164
+ appendSaveAndPublish(items, capabilities, state, actions, labels, preview);
165
+ appendStatusFooter(items, state, labels, extraItems);
166
+ return items;
167
+ }
@@ -0,0 +1,3 @@
1
+ /** Bootstrap severity badge class for issue rows. */
2
+ export declare function getIssueSeverityBadgeClass(severity: string): string;
3
+ //# sourceMappingURL=panelHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panelHelpers.d.ts","sourceRoot":"","sources":["../../src/lib/panelHelpers.ts"],"names":[],"mappings":"AAEA,qDAAqD;AACrD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWnE"}
@@ -0,0 +1,14 @@
1
+ import { TREE_SPEC_ISSUE_SEVERITY } from '@signalsafe/tree-spec';
2
+ /** Bootstrap severity badge class for issue rows. */
3
+ export function getIssueSeverityBadgeClass(severity) {
4
+ switch (severity) {
5
+ case TREE_SPEC_ISSUE_SEVERITY.ERROR:
6
+ return 'text-bg-danger';
7
+ case TREE_SPEC_ISSUE_SEVERITY.WARNING:
8
+ return 'text-bg-warning text-dark';
9
+ case TREE_SPEC_ISSUE_SEVERITY.INFO:
10
+ return 'text-bg-info text-dark';
11
+ default:
12
+ return 'text-bg-secondary';
13
+ }
14
+ }
@@ -0,0 +1,21 @@
1
+ import type { TreeSpecAuditEventItem } from '@signalsafe/tree-spec-editor-core';
2
+ export interface AuditLogModalProps {
3
+ show: boolean;
4
+ loadingAudit: boolean;
5
+ auditEvents: TreeSpecAuditEventItem[];
6
+ onClose: () => void;
7
+ /** Override the modal title (default "Audit log"). */
8
+ title?: string;
9
+ /** Override the muted subtitle below the title. */
10
+ subtitle?: string;
11
+ /** Override the loading state text. */
12
+ loadingText?: string;
13
+ /** Override the empty-state text (when there are zero events). */
14
+ emptyStateText?: string;
15
+ /** Override the "Actor ID:" label prefix shown for events that have an actor. */
16
+ actorLabel?: string;
17
+ /** Override the Close button label in the footer. */
18
+ closeLabel?: string;
19
+ }
20
+ export default function AuditLogModal({ show, loadingAudit, auditEvents, onClose, title, subtitle, loadingText, emptyStateText, actorLabel, closeLabel, }: Readonly<AuditLogModalProps>): import("react/jsx-runtime").JSX.Element | null;
21
+ //# sourceMappingURL=AuditLogModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuditLogModal.d.ts","sourceRoot":"","sources":["../../src/modals/AuditLogModal.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAEhF,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,sBAAsB,EAAE,CAAC;IACtC,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AASD,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAClC,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,OAAO,EACP,KAAqB,EACrB,QAA2B,EAC3B,WAAkC,EAClC,cAAyC,EACzC,UAAgC,EAChC,UAAgC,GACnC,EAAE,QAAQ,CAAC,kBAAkB,CAAC,kDAwD9B"}
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, CloseButton } from 'react-bootstrap';
3
+ const DEFAULT_TITLE = 'Audit log';
4
+ const DEFAULT_SUBTITLE = 'Authoring actions for this tree_spec version.';
5
+ const DEFAULT_LOADING_TEXT = 'Loading…';
6
+ const DEFAULT_EMPTY_STATE_TEXT = 'No audit events yet.';
7
+ const DEFAULT_ACTOR_LABEL = 'Actor ID:';
8
+ const DEFAULT_CLOSE_LABEL = 'Close';
9
+ export default function AuditLogModal({ show, loadingAudit, auditEvents, onClose, title = DEFAULT_TITLE, subtitle = DEFAULT_SUBTITLE, loadingText = DEFAULT_LOADING_TEXT, emptyStateText = DEFAULT_EMPTY_STATE_TEXT, actorLabel = DEFAULT_ACTOR_LABEL, closeLabel = DEFAULT_CLOSE_LABEL, }) {
10
+ if (!show)
11
+ return null;
12
+ let auditContent;
13
+ if (loadingAudit) {
14
+ auditContent = _jsx("div", { className: "text-muted", children: loadingText });
15
+ }
16
+ else if (auditEvents.length === 0) {
17
+ auditContent = (_jsx("div", { className: "text-muted", children: _jsx("em", { children: emptyStateText }) }));
18
+ }
19
+ else {
20
+ auditContent = (_jsx("ul", { className: "list-unstyled mb-0 overflow-auto-max-h-400", children: auditEvents.map((e) => (_jsxs("li", { className: "border-bottom py-2", children: [_jsxs("div", { className: "d-flex justify-content-between align-items-start", children: [_jsx("span", { className: "badge bg-secondary me-2", children: e.action }), _jsx("span", { className: "text-muted font-size-12", children: new Date(e.created_at).toLocaleString() })] }), e.actor == null ? null : (_jsxs("span", { className: "text-muted font-size-12", children: [actorLabel, " ", e.actor] })), e.detail && Object.keys(e.detail).length > 0 ? (_jsx("pre", { className: "mb-0 mt-1 small text-muted font-size-11", children: JSON.stringify(e.detail) })) : null] }, e.id))) }));
21
+ }
22
+ return (_jsx("dialog", { className: "modal d-block modal-backdrop-dark", open: true, children: _jsx("div", { className: "modal-dialog modal-lg", children: _jsxs("div", { className: "modal-content", children: [_jsxs("div", { className: "modal-header", children: [_jsx("h5", { className: "modal-title", children: title }), _jsx(CloseButton, { "aria-label": "Close", onClick: onClose })] }), _jsxs("div", { className: "modal-body", children: [_jsx("p", { className: "text-muted font-size-13", children: subtitle }), auditContent] }), _jsx("div", { className: "modal-footer", children: _jsx(Button, { variant: "secondary", onClick: onClose, children: closeLabel }) })] }) }) }));
23
+ }
@@ -0,0 +1,34 @@
1
+ import type { EditorTree, TreeSpecSnapshotItem } from '@signalsafe/tree-spec-editor-core';
2
+ export interface DraftHistoryModalProps {
3
+ show: boolean;
4
+ loadingSnapshots: boolean;
5
+ snapshots: TreeSpecSnapshotItem[];
6
+ restoringSnapshotId: string | null;
7
+ creatingSnapshot: boolean;
8
+ tree: EditorTree | null;
9
+ onClose: () => void;
10
+ onCreateSnapshot: () => void;
11
+ onRestoreSnapshot: (snapshotId: string) => void;
12
+ /** Override the modal title (default "Draft history"). */
13
+ title?: string;
14
+ /** Override the muted subtitle below the title. */
15
+ subtitle?: string;
16
+ /** Override the "Snapshots (newest first)" caption above the list. */
17
+ listCaption?: string;
18
+ /** Override the "Create snapshot" button label. */
19
+ createSnapshotLabel?: string;
20
+ /** Override the "Creating\u2026" label while a create is in flight. */
21
+ creatingSnapshotLabel?: string;
22
+ /** Override the "Restore" button label. */
23
+ restoreLabel?: string;
24
+ /** Override the "Restoring\u2026" button label while a restore is in flight. */
25
+ restoringLabel?: string;
26
+ /** Override the loading state text. */
27
+ loadingText?: string;
28
+ /** Override the empty-state text (when there are zero snapshots). */
29
+ emptyStateText?: string;
30
+ /** Override the Close button label in the footer. */
31
+ closeLabel?: string;
32
+ }
33
+ export default function DraftHistoryModal({ show, loadingSnapshots, snapshots, restoringSnapshotId, creatingSnapshot, tree, onClose, onCreateSnapshot, onRestoreSnapshot, title, subtitle, listCaption, createSnapshotLabel, creatingSnapshotLabel, restoreLabel, restoringLabel, loadingText, emptyStateText, closeLabel, }: Readonly<DraftHistoryModalProps>): import("react/jsx-runtime").JSX.Element | null;
34
+ //# sourceMappingURL=DraftHistoryModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DraftHistoryModal.d.ts","sourceRoot":"","sources":["../../src/modals/DraftHistoryModal.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAE1F,MAAM,WAAW,sBAAsB;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,gBAAgB,EAAE,OAAO,CAAC;IAC1B,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAEhD,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,uEAAuE;IACvE,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAcD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EACtC,IAAI,EACJ,gBAAgB,EAChB,SAAS,EACT,mBAAmB,EACnB,gBAAgB,EAChB,IAAI,EACJ,OAAO,EACP,gBAAgB,EAChB,iBAAiB,EACjB,KAAqB,EACrB,QAA2B,EAC3B,WAAkC,EAClC,mBAA0C,EAC1C,qBAA8C,EAC9C,YAAoC,EACpC,cAAwC,EACxC,WAAkC,EAClC,cAAyC,EACzC,UAAgC,GACnC,EAAE,QAAQ,CAAC,sBAAsB,CAAC,kDAuElC"}
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, CloseButton } from 'react-bootstrap';
3
+ const DEFAULT_TITLE = 'Draft history';
4
+ const DEFAULT_SUBTITLE = 'Restore an earlier snapshot into the current draft. Creating a snapshot saves the current graph state.';
5
+ const DEFAULT_LIST_CAPTION = 'Snapshots (newest first)';
6
+ const DEFAULT_CREATE_LABEL = 'Create snapshot';
7
+ const DEFAULT_CREATING_LABEL = 'Creating…';
8
+ const DEFAULT_RESTORE_LABEL = 'Restore';
9
+ const DEFAULT_RESTORING_LABEL = 'Restoring…';
10
+ const DEFAULT_LOADING_TEXT = 'Loading…';
11
+ const DEFAULT_EMPTY_STATE_TEXT = 'No snapshots yet. Create one to save the current draft.';
12
+ const DEFAULT_CLOSE_LABEL = 'Close';
13
+ export default function DraftHistoryModal({ show, loadingSnapshots, snapshots, restoringSnapshotId, creatingSnapshot, tree, onClose, onCreateSnapshot, onRestoreSnapshot, title = DEFAULT_TITLE, subtitle = DEFAULT_SUBTITLE, listCaption = DEFAULT_LIST_CAPTION, createSnapshotLabel = DEFAULT_CREATE_LABEL, creatingSnapshotLabel = DEFAULT_CREATING_LABEL, restoreLabel = DEFAULT_RESTORE_LABEL, restoringLabel = DEFAULT_RESTORING_LABEL, loadingText = DEFAULT_LOADING_TEXT, emptyStateText = DEFAULT_EMPTY_STATE_TEXT, closeLabel = DEFAULT_CLOSE_LABEL, }) {
14
+ if (!show)
15
+ return null;
16
+ let snapshotsContent;
17
+ if (loadingSnapshots) {
18
+ snapshotsContent = _jsx("div", { className: "text-muted", children: loadingText });
19
+ }
20
+ else if (snapshots.length === 0) {
21
+ snapshotsContent = (_jsx("div", { className: "text-muted", children: _jsx("em", { children: emptyStateText }) }));
22
+ }
23
+ else {
24
+ snapshotsContent = (_jsx("ul", { className: "list-unstyled mb-0 overflow-auto-max-h-320", children: snapshots.map((s) => (_jsxs("li", { className: "d-flex justify-content-between align-items-center border-bottom py-2", children: [_jsxs("div", { children: [_jsx("span", { className: "text-muted font-size-12", children: new Date(s.created_at).toLocaleString() }), s.label ? _jsx("span", { className: "ms-2", children: s.label }) : null, s.spec_hash ? (_jsxs("span", { className: "ms-2 text-muted font-size-11", children: [s.spec_hash.slice(0, 8), "\u2026"] })) : null] }), _jsx(Button, { variant: "outline-warning", onClick: () => onRestoreSnapshot(s.id), disabled: restoringSnapshotId !== null, children: restoringSnapshotId === s.id ? restoringLabel : restoreLabel })] }, s.id))) }));
25
+ }
26
+ return (_jsx("dialog", { className: "modal d-block modal-backdrop-dark", open: true, children: _jsx("div", { className: "modal-dialog modal-lg", children: _jsxs("div", { className: "modal-content", children: [_jsxs("div", { className: "modal-header", children: [_jsx("h5", { className: "modal-title", children: title }), _jsx(CloseButton, { "aria-label": "Close", onClick: onClose })] }), _jsxs("div", { className: "modal-body", children: [_jsx("p", { className: "text-muted font-size-13", children: subtitle }), _jsxs("div", { className: "d-flex justify-content-between align-items-center mb-3", children: [_jsx("span", { className: "text-muted font-size-13", children: listCaption }), _jsx(Button, { variant: "outline-primary", onClick: onCreateSnapshot, disabled: !tree || creatingSnapshot, children: creatingSnapshot ? creatingSnapshotLabel : createSnapshotLabel })] }), snapshotsContent] }), _jsx("div", { className: "modal-footer", children: _jsx(Button, { variant: "secondary", onClick: onClose, children: closeLabel }) })] }) }) }));
27
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Publish-review modal for the TreeSpec graph editor.
3
+ *
4
+ * Presentational only: receives the current tree, the baseline tree (loaded from the
5
+ * server before edits), the current validation issues, and callbacks. The diff
6
+ * computation is injected via `computeDiffSummary` so the package stays free of
7
+ * host-specific diff logic.
8
+ */
9
+ import { type TreeSpecIssue } from '@signalsafe/tree-spec';
10
+ import { type EditorTree } from '@signalsafe/tree-spec-editor-core';
11
+ export interface PublishReviewModalProps {
12
+ show: boolean;
13
+ tree: EditorTree | null;
14
+ baselineTree: EditorTree | null;
15
+ issues: TreeSpecIssue[];
16
+ publishing: boolean;
17
+ onClose: () => void;
18
+ onPublish: () => void;
19
+ computeDiffSummary: (before: EditorTree | null, after: EditorTree) => {
20
+ lines: string[];
21
+ hasChanges: boolean;
22
+ };
23
+ /** Override the card title (default "Review changes before publishing"). */
24
+ title?: string;
25
+ /** Override the info alert text shown above the diff summary. */
26
+ summaryText?: string;
27
+ /** Override the error alert shown when validation issues exist. */
28
+ errorAlertText?: string;
29
+ /** Override the Cancel button label. */
30
+ cancelLabel?: string;
31
+ /** Override the Publish button label (default "Publish now"). */
32
+ publishLabel?: string;
33
+ /** Override the Publish button label while publishing (default "Publishing\u2026"). */
34
+ publishingLabel?: string;
35
+ }
36
+ export default function PublishReviewModal({ show, tree, baselineTree, issues, publishing, onClose, onPublish, computeDiffSummary, title, summaryText, errorAlertText, cancelLabel, publishLabel, publishingLabel, }: Readonly<PublishReviewModalProps>): import("react/jsx-runtime").JSX.Element | null;
37
+ //# sourceMappingURL=PublishReviewModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PublishReviewModal.d.ts","sourceRoot":"","sources":["../../src/modals/PublishReviewModal.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAA4B,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGrF,OAAO,EAAsB,KAAK,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAExF,MAAM,WAAW,uBAAuB;IACpC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,kBAAkB,EAAE,CAChB,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,KAAK,EAAE,UAAU,KAChB;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;IAE9C,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uFAAuF;IACvF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAUD,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EACvC,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,UAAU,EACV,OAAO,EACP,SAAS,EACT,kBAAkB,EAClB,KAAqB,EACrB,WAAkC,EAClC,cAAyC,EACzC,WAAkC,EAClC,YAAoC,EACpC,eAA0C,GAC7C,EAAE,QAAQ,CAAC,uBAAuB,CAAC,kDAyCnC"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Publish-review modal for the TreeSpec graph editor.
4
+ *
5
+ * Presentational only: receives the current tree, the baseline tree (loaded from the
6
+ * server before edits), the current validation issues, and callbacks. The diff
7
+ * computation is injected via `computeDiffSummary` so the package stays free of
8
+ * host-specific diff logic.
9
+ */
10
+ import { TREE_SPEC_ISSUE_SEVERITY } from '@signalsafe/tree-spec';
11
+ import { Button, CloseButton } from 'react-bootstrap';
12
+ import { buildStableEntries } from '@signalsafe/tree-spec-editor-core';
13
+ const DEFAULT_TITLE = 'Review changes before publishing';
14
+ const DEFAULT_SUMMARY_TEXT = 'Publishing is immutable. This summary compares the loaded version spec to your current graph.';
15
+ const DEFAULT_ERROR_ALERT_TEXT = 'Validation errors exist. Fix them before publishing.';
16
+ const DEFAULT_CANCEL_LABEL = 'Cancel';
17
+ const DEFAULT_PUBLISH_LABEL = 'Publish now';
18
+ const DEFAULT_PUBLISHING_LABEL = 'Publishing…';
19
+ export default function PublishReviewModal({ show, tree, baselineTree, issues, publishing, onClose, onPublish, computeDiffSummary, title = DEFAULT_TITLE, summaryText = DEFAULT_SUMMARY_TEXT, errorAlertText = DEFAULT_ERROR_ALERT_TEXT, cancelLabel = DEFAULT_CANCEL_LABEL, publishLabel = DEFAULT_PUBLISH_LABEL, publishingLabel = DEFAULT_PUBLISHING_LABEL, }) {
20
+ if (!show)
21
+ return null;
22
+ const hasErrors = issues.some((i) => i.severity === TREE_SPEC_ISSUE_SEVERITY.ERROR);
23
+ const diffLineEntries = buildStableEntries(tree ? computeDiffSummary(baselineTree, tree).lines : [], (line) => line);
24
+ return (_jsx("dialog", { className: "modal d-block modal-backdrop-dark", open: true, children: _jsx("div", { className: "modal-dialog modal-lg", children: _jsxs("div", { className: "modal-content", children: [_jsxs("div", { className: "modal-header", children: [_jsx("h5", { className: "modal-title", children: title }), _jsx(CloseButton, { "aria-label": "Close", onClick: onClose })] }), _jsxs("div", { className: "modal-body", children: [_jsx("div", { className: "alert alert-info font-size-13", children: summaryText }), _jsx("ul", { children: diffLineEntries.map(({ item: line, key }) => (_jsx("li", { children: line }, key))) }), hasErrors ? (_jsx("div", { className: "alert alert-danger", children: errorAlertText })) : null] }), _jsxs("div", { className: "modal-footer", children: [_jsx(Button, { variant: "outline-secondary", onClick: onClose, children: cancelLabel }), _jsx(Button, { variant: "success", disabled: publishing || hasErrors, onClick: onPublish, children: publishing ? publishingLabel : publishLabel })] })] }) }) }));
25
+ }