@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.
- package/LICENSE +21 -0
- package/README.md +186 -59
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/lib/PanelHeaderCollapseCarets.d.ts +1 -1
- package/dist/lib/PanelHeaderCollapseCarets.d.ts.map +1 -1
- package/dist/lib/buildDefaultToolbarSpec.d.ts +3 -79
- package/dist/lib/buildDefaultToolbarSpec.d.ts.map +1 -1
- package/dist/lib/buildDefaultToolbarSpec.js +9 -155
- package/dist/lib/panelNodeLink.d.ts +13 -0
- package/dist/lib/panelNodeLink.d.ts.map +1 -0
- package/dist/lib/panelNodeLink.js +12 -0
- package/dist/lib/selectionStyles.d.ts +9 -0
- package/dist/lib/selectionStyles.d.ts.map +1 -0
- package/dist/lib/selectionStyles.js +8 -0
- package/dist/lib/toolbar/defaultToolbarTypes.d.ts +89 -0
- package/dist/lib/toolbar/defaultToolbarTypes.d.ts.map +1 -0
- package/dist/lib/toolbar/defaultToolbarTypes.js +1 -0
- package/dist/lib/toolbar/toolbarSectionBuilders.d.ts +10 -0
- package/dist/lib/toolbar/toolbarSectionBuilders.d.ts.map +1 -0
- package/dist/lib/toolbar/toolbarSectionBuilders.js +153 -0
- package/dist/modals/AuditLogModal.d.ts +1 -1
- package/dist/modals/AuditLogModal.d.ts.map +1 -1
- package/dist/modals/AuditLogModal.js +1 -1
- package/dist/modals/DraftHistoryModal.d.ts +1 -1
- package/dist/modals/DraftHistoryModal.d.ts.map +1 -1
- package/dist/modals/DraftHistoryModal.js +1 -1
- package/dist/modals/PublishReviewModal.d.ts +1 -1
- package/dist/modals/PublishReviewModal.d.ts.map +1 -1
- package/dist/panels/AdvancedJsonPanel.d.ts +1 -1
- package/dist/panels/AdvancedJsonPanel.d.ts.map +1 -1
- package/dist/panels/AppearancePanel.d.ts +26 -0
- package/dist/panels/AppearancePanel.d.ts.map +1 -0
- package/dist/panels/AppearancePanel.js +76 -0
- package/dist/panels/ChoiceEdgeAppearanceFields.d.ts +10 -0
- package/dist/panels/ChoiceEdgeAppearanceFields.d.ts.map +1 -0
- package/dist/panels/ChoiceEdgeAppearanceFields.js +13 -0
- package/dist/panels/ChoiceTemplatesPanel.d.ts +27 -0
- package/dist/panels/ChoiceTemplatesPanel.d.ts.map +1 -0
- package/dist/panels/ChoiceTemplatesPanel.js +9 -0
- package/dist/panels/GraphEditorInfoPanel.d.ts +5 -2
- package/dist/panels/GraphEditorInfoPanel.d.ts.map +1 -1
- package/dist/panels/GraphEditorInfoPanel.js +6 -6
- package/dist/panels/InspectorPanel.d.ts +3 -78
- package/dist/panels/InspectorPanel.d.ts.map +1 -1
- package/dist/panels/InspectorPanel.js +20 -60
- package/dist/panels/IssuesPanel.d.ts +6 -2
- package/dist/panels/IssuesPanel.d.ts.map +1 -1
- package/dist/panels/IssuesPanel.js +15 -3
- package/dist/panels/NodesPanel.d.ts +3 -1
- package/dist/panels/NodesPanel.d.ts.map +1 -1
- package/dist/panels/NodesPanel.js +12 -6
- package/dist/panels/SelectedEdgePanel.d.ts +10 -3
- package/dist/panels/SelectedEdgePanel.d.ts.map +1 -1
- package/dist/panels/SelectedEdgePanel.js +5 -6
- package/dist/panels/ToolbarPanel.d.ts +1 -1
- package/dist/panels/ToolbarPanel.d.ts.map +1 -1
- package/dist/panels/ToolbarPanel.js +2 -4
- package/dist/panels/inspector/ChoiceEditorCard.d.ts +28 -0
- package/dist/panels/inspector/ChoiceEditorCard.d.ts.map +1 -0
- package/dist/panels/inspector/ChoiceEditorCard.js +36 -0
- package/dist/panels/inspector/ChoiceEditorList.d.ts +25 -0
- package/dist/panels/inspector/ChoiceEditorList.d.ts.map +1 -0
- package/dist/panels/inspector/ChoiceEditorList.js +10 -0
- package/dist/panels/inspector/NodeTypeField.d.ts +8 -0
- package/dist/panels/inspector/NodeTypeField.d.ts.map +1 -0
- package/dist/panels/inspector/NodeTypeField.js +12 -0
- package/dist/panels/inspector/RequiredNodeCard.d.ts +14 -0
- package/dist/panels/inspector/RequiredNodeCard.d.ts.map +1 -0
- package/dist/panels/inspector/RequiredNodeCard.js +16 -0
- package/dist/panels/inspector/choiceActionIconProps.d.ts +12 -0
- package/dist/panels/inspector/choiceActionIconProps.d.ts.map +1 -0
- package/dist/panels/inspector/choiceActionIconProps.js +26 -0
- package/dist/panels/inspector/types.d.ts +77 -0
- package/dist/panels/inspector/types.d.ts.map +1 -0
- package/dist/panels/inspector/types.js +11 -0
- package/package.json +83 -65
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectedEdgePanel.d.ts","sourceRoot":"","sources":["../../src/panels/SelectedEdgePanel.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"SelectedEdgePanel.d.ts","sourceRoot":"","sources":["../../src/panels/SelectedEdgePanel.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAE1E,OAAO,EAA+B,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE9F,MAAM,MAAM,0BAA0B,GAAG,oBAAoB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,WAAW,sBAAsB;IACnC,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACtC,wEAAwE;IACxE,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,0BAA0B,KAAK,SAAS,CAAC;CAC1F;AAED,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EACtC,YAAY,EACZ,YAAY,EACZ,KAAuB,EACvB,aAA2C,GAC9C,EAAE,QAAQ,CAAC,sBAAsB,CAAC,sCAalC"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
}
|
|
5
|
-
export default function SelectedEdgePanel({ selectedEdge, title = 'Selected Edge', renderDetails = defaultRenderDetails, }) {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { renderDefaultEdgeBreadcrumb } from '../lib/panelNodeLink';
|
|
3
|
+
export { PanelNodeLink } from '../lib/panelNodeLink';
|
|
4
|
+
export default function SelectedEdgePanel({ selectedEdge, onNodeSelect, title = 'Selected Edge', renderDetails = renderDefaultEdgeBreadcrumb, }) {
|
|
6
5
|
if (!selectedEdge)
|
|
7
6
|
return null;
|
|
8
|
-
return (_jsx("div", { className: "card mt-3", children: _jsxs("div", { className: "card-body", children: [_jsx("div", { className: "fw-bold", children: title }), _jsx("div", { className: "text-muted font-size-12", children: renderDetails(selectedEdge) })] }) }));
|
|
7
|
+
return (_jsx("div", { className: "card mt-3", children: _jsxs("div", { className: "card-body", children: [_jsx("div", { className: "fw-bold", children: title }), _jsx("div", { className: "text-muted font-size-12", children: renderDetails(selectedEdge, { onNodeSelect }) })] }) }));
|
|
9
8
|
}
|
|
@@ -84,5 +84,5 @@ export interface ToolbarPanelProps {
|
|
|
84
84
|
/** Override the outer wrapper className. Default: `"d-flex gap-2 align-items-center flex-wrap"`. */
|
|
85
85
|
className?: string;
|
|
86
86
|
}
|
|
87
|
-
export default function ToolbarPanel({ items, className, }: Readonly<ToolbarPanelProps>): import("react
|
|
87
|
+
export default function ToolbarPanel({ items, className, }: Readonly<ToolbarPanelProps>): import("react").JSX.Element;
|
|
88
88
|
//# sourceMappingURL=ToolbarPanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolbarPanel.d.ts","sourceRoot":"","sources":["../../src/panels/ToolbarPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGjD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;;;;;CAMpB,CAAC;AAEX,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAEzF,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,OAAO,iBAAiB,CAAC,MAAM,CAAC;IACtC,+EAA+E;IAC/E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,iDAAiD;AACjD,MAAM,WAAW,oBAAoB;IACjC,+EAA+E;IAC/E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,OAAO,iBAAiB,CAAC,QAAQ,CAAC;IACxC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAChC,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,OAAO,iBAAiB,CAAC,KAAK,CAAC;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;IACjB,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,OAAO,iBAAiB,CAAC,IAAI,CAAC;IACpC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,SAAS,CAAC;IACnB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,OAAO,iBAAiB,CAAC,MAAM,CAAC;IACtC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,oFAAoF;IACpF,MAAM,EAAE,MAAM,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,WAAW,GACjB,iBAAiB,GACjB,mBAAmB,GACnB,gBAAgB,GAChB,eAAe,GACf,iBAAiB,CAAC;AAExB,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,oGAAoG;IACpG,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;
|
|
1
|
+
{"version":3,"file":"ToolbarPanel.d.ts","sourceRoot":"","sources":["../../src/panels/ToolbarPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGjD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;;;;;CAMpB,CAAC;AAEX,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAEzF,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,OAAO,iBAAiB,CAAC,MAAM,CAAC;IACtC,+EAA+E;IAC/E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,iDAAiD;AACjD,MAAM,WAAW,oBAAoB;IACjC,+EAA+E;IAC/E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,OAAO,iBAAiB,CAAC,QAAQ,CAAC;IACxC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAChC,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,OAAO,iBAAiB,CAAC,KAAK,CAAC;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,CAAC;IACjB,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,OAAO,iBAAiB,CAAC,IAAI,CAAC;IACpC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,SAAS,CAAC;IACnB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,OAAO,iBAAiB,CAAC,MAAM,CAAC;IACtC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,oFAAoF;IACpF,MAAM,EAAE,MAAM,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,WAAW,GACjB,iBAAiB,GACjB,mBAAmB,GACnB,gBAAgB,GAChB,eAAe,GACf,iBAAiB,CAAC;AAExB,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,oGAAoG;IACpG,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAuED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACjC,KAAK,EACL,SAAiC,GACpC,EAAE,QAAQ,CAAC,iBAAiB,CAAC,+BAQ7B"}
|
|
@@ -48,10 +48,8 @@ function renderItem(item) {
|
|
|
48
48
|
return (_jsx("span", { className: item.className ?? DEFAULT_TEXT_CLASS, children: item.content }));
|
|
49
49
|
case TOOLBAR_ITEM_KIND.CUSTOM:
|
|
50
50
|
return item.render();
|
|
51
|
-
default:
|
|
52
|
-
|
|
53
|
-
return exhaustive;
|
|
54
|
-
}
|
|
51
|
+
default:
|
|
52
|
+
return null;
|
|
55
53
|
}
|
|
56
54
|
}
|
|
57
55
|
export default function ToolbarPanel({ items, className = DEFAULT_WRAPPER_CLASS, }) {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { type EditorChoice, type EditorNode, type EditorTree } from '@signalsafe/tree-spec-editor-core';
|
|
3
|
+
import type { ChoiceTypeOption, InspectorChoiceRenderContext } from './types';
|
|
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
|
+
choice: EditorChoice;
|
|
6
|
+
tree: EditorTree;
|
|
7
|
+
selectedNode: EditorNode;
|
|
8
|
+
focusChoiceId: string | null;
|
|
9
|
+
isPublished: boolean;
|
|
10
|
+
canMoveUp: boolean;
|
|
11
|
+
canMoveDown: boolean;
|
|
12
|
+
usedChoiceTypeIds: Set<string>;
|
|
13
|
+
onUpdateSelectedNode: (patch: Partial<EditorNode>) => void;
|
|
14
|
+
onDeleteChoice: (choiceId: string) => void;
|
|
15
|
+
onMoveChoice?: (choiceId: string, direction: 'up' | 'down') => void;
|
|
16
|
+
onSetChoiceTarget: (choiceId: string, targetNodeId: string) => void;
|
|
17
|
+
onSetChoiceOutcome: (choiceId: string, outcome: string) => void;
|
|
18
|
+
onSetChoiceType?: (choiceId: string, typeId: string, defaultLabel?: string) => void;
|
|
19
|
+
choiceTypes?: ReadonlyArray<ChoiceTypeOption>;
|
|
20
|
+
outcomeOptions: ReadonlyArray<{
|
|
21
|
+
value: string;
|
|
22
|
+
label: string;
|
|
23
|
+
}>;
|
|
24
|
+
hideOutcomeField: boolean;
|
|
25
|
+
renderExtraChoiceFields?: (ctx: InspectorChoiceRenderContext) => ReactNode;
|
|
26
|
+
onFocusChoice?: (choiceId: string) => void;
|
|
27
|
+
}>): import("react").JSX.Element;
|
|
28
|
+
//# sourceMappingURL=ChoiceEditorCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChoiceEditorCard.d.ts","sourceRoot":"","sources":["../../../src/panels/inspector/ChoiceEditorCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,SAAS,EAAE,MAAM,OAAO,CAAC;AAGpD,OAAO,EAGH,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,UAAU,EAClB,MAAM,mCAAmC,CAAC;AAI3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAE9E,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACrC,MAAM,EACN,IAAI,EACJ,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,uBAAuB,EACvB,aAAa,GAChB,EAAE,QAAQ,CAAC;IACR,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,UAAU,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,oBAAoB,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IAC3D,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC;IACpE,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACpE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpF,WAAW,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAC9C,cAAc,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,CAAC,GAAG,EAAE,4BAA4B,KAAK,SAAS,CAAC;IAC3E,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC,+BAsJD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Form } from 'react-bootstrap';
|
|
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';
|
|
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
|
+
const transition = getTransition(tree, selectedNode.id, choice.id);
|
|
8
|
+
const targetNodeId = transition?.toNodeId ?? '';
|
|
9
|
+
const outcomeValue = transition?.outcome ?? outcomeOptions[0]?.value ?? '';
|
|
10
|
+
const isFocused = focusChoiceId === choice.id;
|
|
11
|
+
const showOutcome = !hideOutcomeField && targetNodeId === END_NODE_ID;
|
|
12
|
+
const knownTypeIds = new Set((choiceTypes ?? []).map((type) => type.id));
|
|
13
|
+
const showTypeSelect = Boolean(choiceTypes?.length && onSetChoiceType);
|
|
14
|
+
const isCustomType = showTypeSelect && !knownTypeIds.has(choice.id);
|
|
15
|
+
return (_jsxs("div", { id: `choice-editor-${selectedNode.id}-${choice.id}`, className: `list-group-item py-3 px-3${isFocused ? ` ${LIST_SELECTION_CLASS} ${LIST_SELECTION_TEXT_CLASS}` : ''}`, onFocusCapture: () => onFocusChoice?.(choice.id), children: [_jsxs("div", { className: "d-flex w-100 justify-content-between align-items-end gap-2 mb-2", children: [_jsxs("div", { className: "d-flex flex-grow-1 min-w-0 gap-2", children: [showTypeSelect ? (_jsxs(Form.Group, { className: "mb-0 flex-fill min-w-0", children: [_jsx(Form.Label, { className: "mb-1", children: "Type" }), _jsxs(Form.Select, { value: isCustomType ? '__custom__' : choice.id, disabled: isPublished, "aria-label": `Choice type for ${choice.id}`, onChange: (event) => {
|
|
16
|
+
const nextTypeId = event.target.value;
|
|
17
|
+
if (nextTypeId && nextTypeId !== '__custom__') {
|
|
18
|
+
const type = choiceTypes.find((item) => item.id === nextTypeId);
|
|
19
|
+
onSetChoiceType(choice.id, nextTypeId, type?.label);
|
|
20
|
+
}
|
|
21
|
+
}, children: [choiceTypes.map((type) => (_jsx("option", { value: type.id, disabled: type.id !== choice.id && usedChoiceTypeIds.has(type.id), title: type.label, children: type.id }, type.id))), isCustomType ? (_jsxs("option", { value: "__custom__", children: [choice.id, " (custom)"] })) : null] })] })) : (_jsxs(Form.Group, { className: "mb-0 flex-fill min-w-0", children: [_jsx(Form.Label, { className: "mb-1", children: "Type" }), _jsx(Form.Control, { plaintext: true, readOnly: true, className: "text-uppercase fw-semibold", value: choice.id })] })), hideOutcomeField ? null : (_jsxs(Form.Group, { className: "mb-0 flex-fill min-w-0", children: [_jsx(Form.Label, { className: "mb-1", children: "Outcome" }), showOutcome ? (_jsx(Form.Select, { value: outcomeValue, disabled: isPublished, "aria-label": `Outcome for ${choice.id}`, onChange: (e) => onSetChoiceOutcome(choice.id, e.target.value), children: outcomeOptions.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) })) : (_jsx(Form.Select, { disabled: true, "aria-label": `Outcome for ${choice.id}`, value: "", children: _jsx("option", { value: "", children: "When Next is END" }) }))] }))] }), _jsxs("div", { className: "d-flex align-items-center gap-2 flex-shrink-0", children: [onMoveChoice ? (_jsxs(_Fragment, { children: [_jsx("i", { ...choiceActionIconProps(() => onMoveChoice(choice.id, 'up'), 'Move choice up', 'bi bi-chevron-up text-secondary', isPublished || !canMoveUp) }), _jsx("i", { ...choiceActionIconProps(() => onMoveChoice(choice.id, 'down'), 'Move choice down', 'bi bi-chevron-down text-secondary', isPublished || !canMoveDown) })] })) : null, _jsx("i", { ...choiceActionIconProps(() => onDeleteChoice(choice.id), 'Delete choice', 'bi bi-trash text-danger') })] })] }), _jsx(Form.Label, { className: "mt-0", children: "Label" }), _jsx(Form.Control, { value: choice.label, onChange: (event) => {
|
|
22
|
+
const updatedChoices = (selectedNode.choices ?? []).map((existingChoice) => existingChoice.id === choice.id
|
|
23
|
+
? { ...existingChoice, label: event.target.value }
|
|
24
|
+
: existingChoice);
|
|
25
|
+
onUpdateSelectedNode({ choices: updatedChoices });
|
|
26
|
+
} }), _jsx(Form.Label, { className: "mt-2", children: "Next" }), _jsxs(Form.Select, { value: targetNodeId, onChange: (e) => onSetChoiceTarget(choice.id, e.target.value), children: [_jsx("option", { value: "", children: "(not connected)" }), Object.values(tree.nodes).map((n) => (_jsxs("option", { value: n.id, children: [n.id, " \u00B7 ", n.prompt?.slice(0, 40) || n.type] }, n.id))), _jsx("option", { value: END_NODE_ID, children: "END" })] }), renderExtraChoiceFields
|
|
27
|
+
? renderExtraChoiceFields({
|
|
28
|
+
tree,
|
|
29
|
+
node: selectedNode,
|
|
30
|
+
choice,
|
|
31
|
+
transition,
|
|
32
|
+
isPublished,
|
|
33
|
+
onUpdateNode: onUpdateSelectedNode,
|
|
34
|
+
})
|
|
35
|
+
: null] }));
|
|
36
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { EditorNode, EditorTree } from '@signalsafe/tree-spec-editor-core';
|
|
3
|
+
import type { ChoiceTypeOption, InspectorChoiceRenderContext } from './types';
|
|
4
|
+
export default function ChoiceEditorList({ tree, selectedNode, focusChoiceId, isPublished, onAddChoice, onUpdateSelectedNode, onDeleteChoice, onMoveChoice, onSetChoiceTarget, onSetChoiceOutcome, onSetChoiceType, choiceTypes, outcomeOptions, hideOutcomeField, renderExtraChoiceFields, onFocusChoice, }: Readonly<{
|
|
5
|
+
tree: EditorTree;
|
|
6
|
+
selectedNode: EditorNode;
|
|
7
|
+
focusChoiceId: string | null;
|
|
8
|
+
isPublished: boolean;
|
|
9
|
+
onAddChoice: () => void;
|
|
10
|
+
onUpdateSelectedNode: (patch: Partial<EditorNode>) => void;
|
|
11
|
+
onDeleteChoice: (choiceId: string) => void;
|
|
12
|
+
onMoveChoice?: (choiceId: string, direction: 'up' | 'down') => void;
|
|
13
|
+
onSetChoiceTarget: (choiceId: string, targetNodeId: string) => void;
|
|
14
|
+
onSetChoiceOutcome: (choiceId: string, outcome: string) => void;
|
|
15
|
+
onSetChoiceType?: (choiceId: string, typeId: string, defaultLabel?: string) => void;
|
|
16
|
+
choiceTypes?: ReadonlyArray<ChoiceTypeOption>;
|
|
17
|
+
outcomeOptions: ReadonlyArray<{
|
|
18
|
+
value: string;
|
|
19
|
+
label: string;
|
|
20
|
+
}>;
|
|
21
|
+
hideOutcomeField: boolean;
|
|
22
|
+
renderExtraChoiceFields?: (ctx: InspectorChoiceRenderContext) => ReactNode;
|
|
23
|
+
onFocusChoice?: (choiceId: string) => void;
|
|
24
|
+
}>): import("react").JSX.Element;
|
|
25
|
+
//# sourceMappingURL=ChoiceEditorList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChoiceEditorList.d.ts","sourceRoot":"","sources":["../../../src/panels/inspector/ChoiceEditorList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAIhF,OAAO,KAAK,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAE9E,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACrC,IAAI,EACJ,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,uBAAuB,EACvB,aAAa,GAChB,EAAE,QAAQ,CAAC;IACR,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,UAAU,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,oBAAoB,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IAC3D,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC;IACpE,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACpE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpF,WAAW,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAC9C,cAAc,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,CAAC,GAAG,EAAE,4BAA4B,KAAK,SAAS,CAAC;IAC3E,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC,+BAqED"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import PanelHeaderCollapseCarets from '../../lib/PanelHeaderCollapseCarets';
|
|
4
|
+
import ChoiceEditorCard from './ChoiceEditorCard';
|
|
5
|
+
export default function ChoiceEditorList({ tree, selectedNode, focusChoiceId, isPublished, onAddChoice, onUpdateSelectedNode, onDeleteChoice, onMoveChoice, onSetChoiceTarget, onSetChoiceOutcome, onSetChoiceType, choiceTypes, outcomeOptions, hideOutcomeField, renderExtraChoiceFields, onFocusChoice, }) {
|
|
6
|
+
const choices = selectedNode.choices ?? [];
|
|
7
|
+
const [choicesExpanded, setChoicesExpanded] = useState(true);
|
|
8
|
+
const usedChoiceTypeIds = new Set(choices.map((choice) => choice.id));
|
|
9
|
+
return (_jsxs("div", { className: "card mt-3", 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: "Choices" }), _jsx(PanelHeaderCollapseCarets, { expanded: choicesExpanded, onToggle: () => setChoicesExpanded((v) => !v) })] }), _jsx("div", { className: "d-flex align-items-center gap-1 flex-shrink-0", children: _jsx("button", { type: "button", className: "btn p-0 border-0 bg-transparent flex-shrink-0", "aria-label": "Add choice", title: "Add choice", disabled: isPublished, onClick: onAddChoice, children: _jsx("i", { className: `bi bi-plus-lg action-icon${isPublished ? ' text-secondary opacity-50' : ' text-primary cursor-pointer'}`, "aria-hidden": true }) }) })] }), _jsx("div", { className: `card-body p-0${choicesExpanded ? '' : ' d-none'}`, "aria-hidden": !choicesExpanded, children: choices.length === 0 ? (_jsx("div", { className: "text-muted small py-3 px-3", children: _jsx("em", { children: "No choices" }) })) : (_jsx("div", { className: "list-group list-group-flush overflow-auto-max-h-320", children: choices.map((choice, index) => (_jsx(ChoiceEditorCard, { choice: choice, tree: tree, selectedNode: selectedNode, focusChoiceId: focusChoiceId, isPublished: isPublished, canMoveUp: index > 0, canMoveDown: index < choices.length - 1, usedChoiceTypeIds: usedChoiceTypeIds, onUpdateSelectedNode: onUpdateSelectedNode, onDeleteChoice: onDeleteChoice, onMoveChoice: onMoveChoice, onSetChoiceTarget: onSetChoiceTarget, onSetChoiceOutcome: onSetChoiceOutcome, onSetChoiceType: onSetChoiceType, choiceTypes: choiceTypes, outcomeOptions: outcomeOptions, hideOutcomeField: hideOutcomeField, renderExtraChoiceFields: renderExtraChoiceFields, onFocusChoice: onFocusChoice }, choice.id))) })) })] }));
|
|
10
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type EditorNode } from '@signalsafe/tree-spec-editor-core';
|
|
2
|
+
export default function NodeTypeField({ selectedNode, isPublished, onUpdateSelectedNode, typeHelperText, }: Readonly<{
|
|
3
|
+
selectedNode: EditorNode;
|
|
4
|
+
isPublished: boolean;
|
|
5
|
+
onUpdateSelectedNode: (patch: Partial<EditorNode>) => void;
|
|
6
|
+
typeHelperText: string;
|
|
7
|
+
}>): import("react").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=NodeTypeField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NodeTypeField.d.ts","sourceRoot":"","sources":["../../../src/panels/inspector/NodeTypeField.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEH,KAAK,UAAU,EAClB,MAAM,mCAAmC,CAAC;AAE3C,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAClC,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,cAAc,GACjB,EAAE,QAAQ,CAAC;IACR,YAAY,EAAE,UAAU,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,oBAAoB,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IAC3D,cAAc,EAAE,MAAM,CAAC;CAC1B,CAAC,+BAkCD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Form } from 'react-bootstrap';
|
|
3
|
+
import { TREE_SPEC_NODE_TYPE_PRESETS, } from '@signalsafe/tree-spec-editor-core';
|
|
4
|
+
export default function NodeTypeField({ selectedNode, isPublished, onUpdateSelectedNode, typeHelperText, }) {
|
|
5
|
+
const isPreset = TREE_SPEC_NODE_TYPE_PRESETS.includes(selectedNode.type);
|
|
6
|
+
return (_jsxs(Form.Group, { className: "mb-2", children: [_jsx(Form.Label, { children: "Type" }), _jsxs(Form.Select, { value: isPreset ? selectedNode.type : '__custom__', onChange: (e) => {
|
|
7
|
+
const nextType = e.target.value;
|
|
8
|
+
if (nextType === '__custom__')
|
|
9
|
+
return;
|
|
10
|
+
onUpdateSelectedNode({ type: nextType });
|
|
11
|
+
}, disabled: isPublished, children: [TREE_SPEC_NODE_TYPE_PRESETS.map((t) => (_jsx("option", { value: t, children: t }, t))), _jsx("option", { value: "__custom__", children: "custom\u2026" })] }), isPreset ? null : (_jsx(Form.Control, { className: "mt-2", value: selectedNode.type, onChange: (e) => onUpdateSelectedNode({ type: e.target.value }), placeholder: "Enter custom type\u2026", disabled: isPublished })), _jsx("div", { className: "text-muted mt-1 font-size-12", children: typeHelperText })] }));
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { EditorNode, EditorTree } from '@signalsafe/tree-spec-editor-core';
|
|
3
|
+
import type { InspectorNodeRenderContext } from './types';
|
|
4
|
+
export default function RequiredNodeCard({ tree, selectedNode, isPublished, title, typeHelperText, onUpdateSelectedNode, onDeleteSelectedNode, renderExtraNodeFields, }: Readonly<{
|
|
5
|
+
tree: EditorTree;
|
|
6
|
+
selectedNode: EditorNode;
|
|
7
|
+
isPublished: boolean;
|
|
8
|
+
title: string;
|
|
9
|
+
typeHelperText: string;
|
|
10
|
+
onUpdateSelectedNode: (patch: Partial<EditorNode>) => void;
|
|
11
|
+
onDeleteSelectedNode?: () => void;
|
|
12
|
+
renderExtraNodeFields?: (ctx: InspectorNodeRenderContext) => ReactNode;
|
|
13
|
+
}>): import("react").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=RequiredNodeCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequiredNodeCard.d.ts","sourceRoot":"","sources":["../../../src/panels/inspector/RequiredNodeCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,SAAS,EAAE,MAAM,OAAO,CAAC;AAIpD,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAIhF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAE1D,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACrC,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,KAAK,EACL,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACxB,EAAE,QAAQ,CAAC;IACR,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,UAAU,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IAC3D,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,qBAAqB,CAAC,EAAE,CAAC,GAAG,EAAE,0BAA0B,KAAK,SAAS,CAAC;CAC1E,CAAC,+BA4DD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Form } from 'react-bootstrap';
|
|
4
|
+
import PanelHeaderCollapseCarets from '../../lib/PanelHeaderCollapseCarets';
|
|
5
|
+
import NodeTypeField from './NodeTypeField';
|
|
6
|
+
export default function RequiredNodeCard({ tree, selectedNode, isPublished, title, typeHelperText, onUpdateSelectedNode, onDeleteSelectedNode, renderExtraNodeFields, }) {
|
|
7
|
+
const [requiredExpanded, setRequiredExpanded] = useState(true);
|
|
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
|
|
9
|
+
? renderExtraNodeFields({
|
|
10
|
+
tree,
|
|
11
|
+
node: selectedNode,
|
|
12
|
+
isPublished,
|
|
13
|
+
onUpdateNode: onUpdateSelectedNode,
|
|
14
|
+
})
|
|
15
|
+
: null] })] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { KeyboardEvent, MouseEvent } from 'react';
|
|
2
|
+
export declare function choiceActionIconProps(onClick: () => void, title: string, className: string, disabled?: boolean): {
|
|
3
|
+
role: "button";
|
|
4
|
+
tabIndex: number;
|
|
5
|
+
title: string;
|
|
6
|
+
'aria-label': string;
|
|
7
|
+
'aria-disabled': boolean | undefined;
|
|
8
|
+
className: string;
|
|
9
|
+
onClick: ((event: MouseEvent<HTMLElement>) => void) | undefined;
|
|
10
|
+
onKeyDown: ((event: KeyboardEvent<HTMLElement>) => void) | undefined;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=choiceActionIconProps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"choiceActionIconProps.d.ts","sourceRoot":"","sources":["../../../src/panels/inspector/choiceActionIconProps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEvD,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,MAAM,IAAI,EACnB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,QAAQ,UAAQ;;;;;;;sBAaE,UAAU,CAAC,WAAW,CAAC;wBAOvB,aAAa,CAAC,WAAW,CAAC;EAQ/C"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function choiceActionIconProps(onClick, title, className, disabled = false) {
|
|
2
|
+
return {
|
|
3
|
+
role: 'button',
|
|
4
|
+
tabIndex: disabled ? -1 : 0,
|
|
5
|
+
title,
|
|
6
|
+
'aria-label': title,
|
|
7
|
+
'aria-disabled': disabled ? true : undefined,
|
|
8
|
+
className: `${className} action-icon flex-shrink-0${disabled ? ' text-secondary opacity-50' : ' cursor-pointer'}`,
|
|
9
|
+
onClick: disabled
|
|
10
|
+
? undefined
|
|
11
|
+
: (event) => {
|
|
12
|
+
event.preventDefault();
|
|
13
|
+
event.stopPropagation();
|
|
14
|
+
onClick();
|
|
15
|
+
},
|
|
16
|
+
onKeyDown: disabled
|
|
17
|
+
? undefined
|
|
18
|
+
: (event) => {
|
|
19
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
20
|
+
event.preventDefault();
|
|
21
|
+
event.stopPropagation();
|
|
22
|
+
onClick();
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { EditorChoice, EditorNode, EditorTransition, EditorTree } from '@signalsafe/tree-spec-editor-core';
|
|
3
|
+
/** Host-provided choice type (stable id + default label). */
|
|
4
|
+
export type ChoiceTypeOption = {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Canonical outcome values from the `@signalsafe/tree-spec` wire contract.
|
|
10
|
+
* Hosts can override via the `outcomeOptions` prop.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DEFAULT_OUTCOME_OPTIONS: ReadonlyArray<{
|
|
13
|
+
value: string;
|
|
14
|
+
label: string;
|
|
15
|
+
}>;
|
|
16
|
+
export interface InspectorNodeRenderContext {
|
|
17
|
+
tree: EditorTree;
|
|
18
|
+
node: EditorNode;
|
|
19
|
+
isPublished: boolean;
|
|
20
|
+
onUpdateNode: (patch: Partial<EditorNode>) => void;
|
|
21
|
+
}
|
|
22
|
+
export interface InspectorChoiceRenderContext {
|
|
23
|
+
tree: EditorTree;
|
|
24
|
+
node: EditorNode;
|
|
25
|
+
choice: EditorChoice;
|
|
26
|
+
transition: EditorTransition | undefined;
|
|
27
|
+
isPublished: boolean;
|
|
28
|
+
onUpdateNode: (patch: Partial<EditorNode>) => void;
|
|
29
|
+
}
|
|
30
|
+
export interface InspectorPanelProps {
|
|
31
|
+
tree: EditorTree;
|
|
32
|
+
selectedNode: EditorNode | null;
|
|
33
|
+
focusChoiceId?: string | null;
|
|
34
|
+
isPublished?: boolean;
|
|
35
|
+
/** Sync canvas / sidebar highlight when the user focuses a choice field. */
|
|
36
|
+
onFocusChoice?: (choiceId: string) => void;
|
|
37
|
+
onUpdateSelectedNode: (patch: Partial<EditorNode>) => void;
|
|
38
|
+
onAddChoice: () => void;
|
|
39
|
+
onDeleteChoice: (choiceId: string) => void;
|
|
40
|
+
/** Move a choice up or down in the node's choice list. When omitted, reorder controls are hidden. */
|
|
41
|
+
onMoveChoice?: (choiceId: string, direction: 'up' | 'down') => void;
|
|
42
|
+
onSetChoiceTarget: (choiceId: string, targetNodeId: string) => void;
|
|
43
|
+
onSetChoiceOutcome: (choiceId: string, outcome: string) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Override the END-transition outcome `<select>` options.
|
|
46
|
+
* Defaults to the canonical TreeSpec `TerminalOutcome` values.
|
|
47
|
+
*/
|
|
48
|
+
outcomeOptions?: ReadonlyArray<{
|
|
49
|
+
value: string;
|
|
50
|
+
label: string;
|
|
51
|
+
}>;
|
|
52
|
+
/** Hide the outcome selector entirely. Useful when the host manages outcomes elsewhere. */
|
|
53
|
+
hideOutcomeField?: boolean;
|
|
54
|
+
/** Render extra UI below the prompt textarea, scoped to the current node. */
|
|
55
|
+
renderExtraNodeFields?: (ctx: InspectorNodeRenderContext) => ReactNode;
|
|
56
|
+
/** Render extra UI below each choice card (after Next/Outcome). */
|
|
57
|
+
renderExtraChoiceFields?: (ctx: InspectorChoiceRenderContext) => ReactNode;
|
|
58
|
+
/** Host-defined choice types (stable ids) for the Type selector on each choice. */
|
|
59
|
+
choiceTypes?: ReadonlyArray<ChoiceTypeOption>;
|
|
60
|
+
onSetChoiceType?: (choiceId: string, typeId: string, defaultLabel?: string) => void;
|
|
61
|
+
/**
|
|
62
|
+
* When set, shows a delete control in the Required card header (grid-style icon button).
|
|
63
|
+
* Typical host: `editor.actions.deleteSelectedNode`. Disabled when `isPublished` is true.
|
|
64
|
+
*/
|
|
65
|
+
onDeleteSelectedNode?: () => void;
|
|
66
|
+
/** Override the Required card header (default "Required"). */
|
|
67
|
+
title?: string;
|
|
68
|
+
/** Override the empty-state message (default "Select a node to edit it."). */
|
|
69
|
+
emptyStateText?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Override the muted helper text under the Type field.
|
|
72
|
+
* Defaults to: "Type is stored as a string in tree_spec. You can use presets or any custom value."
|
|
73
|
+
*/
|
|
74
|
+
typeHelperText?: string;
|
|
75
|
+
}
|
|
76
|
+
export declare const DEFAULT_TYPE_HELPER_TEXT = "Type is stored as a string in tree_spec. You can use presets or any custom value.";
|
|
77
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/panels/inspector/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { TERMINAL_OUTCOME } from '@signalsafe/tree-spec';
|
|
2
|
+
/**
|
|
3
|
+
* Canonical outcome values from the `@signalsafe/tree-spec` wire contract.
|
|
4
|
+
* Hosts can override via the `outcomeOptions` prop.
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_OUTCOME_OPTIONS = [
|
|
7
|
+
{ value: TERMINAL_OUTCOME.SAFE, label: TERMINAL_OUTCOME.SAFE },
|
|
8
|
+
{ value: TERMINAL_OUTCOME.AT_RISK, label: TERMINAL_OUTCOME.AT_RISK },
|
|
9
|
+
{ value: TERMINAL_OUTCOME.COMPROMISED, label: TERMINAL_OUTCOME.COMPROMISED },
|
|
10
|
+
];
|
|
11
|
+
export const DEFAULT_TYPE_HELPER_TEXT = 'Type is stored as a string in tree_spec. You can use presets or any custom value.';
|
package/package.json
CHANGED
|
@@ -1,69 +1,87 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signalsafe/tree-spec-editor",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Reusable TreeSpec graph editor (React Flow) and authoring helpers (no API or routing).",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/SignalSafeSoftware/tree-spec-editor.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/SignalSafeSoftware/tree-spec-editor/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/SignalSafeSoftware/tree-spec-editor#readme",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"tree-spec",
|
|
17
|
+
"react-flow",
|
|
18
|
+
"editor",
|
|
19
|
+
"graph-editor",
|
|
20
|
+
"decision-tree",
|
|
21
|
+
"react-bootstrap",
|
|
22
|
+
"typescript",
|
|
23
|
+
"signalsafe"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"docs",
|
|
38
|
+
"README.md",
|
|
39
|
+
"LICENSE"
|
|
40
|
+
],
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsc -p tsconfig.build.json",
|
|
49
|
+
"typecheck": "tsc --noEmit",
|
|
50
|
+
"pack:local": "npm pack --pack-destination ../../dist/reusable-npm",
|
|
51
|
+
"release:check": "node ../../scripts/run-private-package-release-checks.mjs --mode prepublish",
|
|
52
|
+
"release:verify": "node ../../scripts/run-private-package-release-checks.mjs --mode postpublish",
|
|
53
|
+
"publish:preflight": "node ../../scripts/check-private-registry-preflight.mjs --scope @signalsafe",
|
|
54
|
+
"publish:dry-run": "npm publish --dry-run",
|
|
55
|
+
"publish:verify": "node ../../scripts/check-private-package-postpublish.mjs --scope @signalsafe --package @signalsafe/tree-spec-editor --version $npm_package_version",
|
|
56
|
+
"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
|
+
"smoke:external": "node ../../scripts/smoke-tree-spec-editor-external-consumer.mjs",
|
|
58
|
+
"smoke:published": "node ../../scripts/smoke-tree-spec-editor-external-consumer.mjs --source registry",
|
|
59
|
+
"prepublishOnly": "npm run build",
|
|
60
|
+
"prepare": "npm run build",
|
|
61
|
+
"test": "vitest run",
|
|
62
|
+
"test:monorepo": "cd ../../frontend && yarn vitest run --config vitest.tree-spec-editor.config.ts"
|
|
63
|
+
},
|
|
64
|
+
"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"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"react": "^18.0.0",
|
|
71
|
+
"react-bootstrap": "^2.10.0",
|
|
72
|
+
"react-dom": "^18.0.0",
|
|
73
|
+
"reactflow": "^11.0.0"
|
|
74
|
+
},
|
|
75
|
+
"devDependencies": {
|
|
76
|
+
"@types/react": "^18.2.66",
|
|
77
|
+
"@types/react-dom": "^18.2.22",
|
|
78
|
+
"@types/react-test-renderer": "^18.3.0",
|
|
79
|
+
"react": "^18.3.1",
|
|
80
|
+
"react-bootstrap": "^2.10.2",
|
|
81
|
+
"react-dom": "^18.3.1",
|
|
82
|
+
"react-test-renderer": "^18.3.1",
|
|
83
|
+
"reactflow": "^11.11.4",
|
|
84
|
+
"typescript": "^5.4.2",
|
|
85
|
+
"vitest": "^3.2.4"
|
|
22
86
|
}
|
|
23
|
-
},
|
|
24
|
-
"files": [
|
|
25
|
-
"dist",
|
|
26
|
-
"docs",
|
|
27
|
-
"README.md"
|
|
28
|
-
],
|
|
29
|
-
"publishConfig": {
|
|
30
|
-
"access": "restricted"
|
|
31
|
-
},
|
|
32
|
-
"scripts": {
|
|
33
|
-
"build": "tsc -p tsconfig.build.json",
|
|
34
|
-
"typecheck": "tsc --noEmit",
|
|
35
|
-
"pack:local": "npm pack --pack-destination ../../dist/reusable-npm",
|
|
36
|
-
"release:check": "node ../../scripts/run-private-package-release-checks.mjs --mode prepublish",
|
|
37
|
-
"release:verify": "node ../../scripts/run-private-package-release-checks.mjs --mode postpublish",
|
|
38
|
-
"publish:preflight": "node ../../scripts/check-private-registry-preflight.mjs --scope @signalsafe",
|
|
39
|
-
"publish:dry-run": "npm publish --dry-run",
|
|
40
|
-
"publish:verify": "node ../../scripts/check-private-package-postpublish.mjs --scope @signalsafe --package @signalsafe/tree-spec-editor --version $npm_package_version",
|
|
41
|
-
"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",
|
|
42
|
-
"smoke:external": "node ../../scripts/smoke-tree-spec-editor-external-consumer.mjs",
|
|
43
|
-
"smoke:published": "node ../../scripts/smoke-tree-spec-editor-external-consumer.mjs --source registry",
|
|
44
|
-
"prepublishOnly": "npm run build",
|
|
45
|
-
"prepare": "npm run build",
|
|
46
|
-
"test": "cd ../../frontend && yarn vitest run --config vitest.tree-spec-editor.config.ts"
|
|
47
|
-
},
|
|
48
|
-
"dependencies": {
|
|
49
|
-
"@signalsafe/tree-spec": "^0.1.4",
|
|
50
|
-
"@signalsafe/tree-spec-editor-core": "^0.1.1",
|
|
51
|
-
"@signalsafe/tree-spec-editor-react": "^0.1.1"
|
|
52
|
-
},
|
|
53
|
-
"peerDependencies": {
|
|
54
|
-
"react": "^18.0.0",
|
|
55
|
-
"react-bootstrap": "^2.10.0",
|
|
56
|
-
"react-dom": "^18.0.0",
|
|
57
|
-
"reactflow": "^11.0.0"
|
|
58
|
-
},
|
|
59
|
-
"devDependencies": {
|
|
60
|
-
"@types/react": "^18.2.66",
|
|
61
|
-
"@types/react-dom": "^18.2.22",
|
|
62
|
-
"react": "^18.3.1",
|
|
63
|
-
"react-bootstrap": "^2.10.2",
|
|
64
|
-
"react-dom": "^18.3.1",
|
|
65
|
-
"react-test-renderer": "18.3.1",
|
|
66
|
-
"reactflow": "^11.11.4",
|
|
67
|
-
"typescript": "^5.4.2"
|
|
68
|
-
}
|
|
69
87
|
}
|