@signalsafe/tree-spec-editor 0.2.3 → 0.3.0

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 (65) hide show
  1. package/README.md +74 -25
  2. package/dist/index.d.ts +8 -10
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +7 -10
  5. package/dist/lib/PanelHeaderCollapseCarets.d.ts.map +1 -1
  6. package/dist/lib/PanelHeaderCollapseCarets.js +2 -1
  7. package/dist/lib/panelHelpers.d.ts +8 -1
  8. package/dist/lib/panelHelpers.d.ts.map +1 -1
  9. package/dist/lib/panelHelpers.js +14 -6
  10. package/dist/lib/panelNodeLink.d.ts.map +1 -1
  11. package/dist/lib/panelNodeLink.js +2 -1
  12. package/dist/lib/selectionStyles.d.ts +6 -6
  13. package/dist/lib/selectionStyles.d.ts.map +1 -1
  14. package/dist/lib/selectionStyles.js +6 -6
  15. package/dist/modals/AuditLogModal.d.ts +0 -6
  16. package/dist/modals/AuditLogModal.d.ts.map +1 -1
  17. package/dist/modals/AuditLogModal.js +6 -5
  18. package/dist/modals/DraftHistoryModal.d.ts +0 -10
  19. package/dist/modals/DraftHistoryModal.d.ts.map +1 -1
  20. package/dist/modals/DraftHistoryModal.js +6 -5
  21. package/dist/modals/PublishReviewModal.d.ts.map +1 -1
  22. package/dist/modals/PublishReviewModal.js +3 -2
  23. package/dist/panels/AdvancedJsonPanel.d.ts +1 -1
  24. package/dist/panels/AdvancedJsonPanel.d.ts.map +1 -1
  25. package/dist/panels/AdvancedJsonPanel.js +3 -3
  26. package/dist/panels/AppearancePanel.d.ts.map +1 -1
  27. package/dist/panels/AppearancePanel.js +6 -8
  28. package/dist/panels/ChoiceEdgeAppearanceFields.d.ts.map +1 -1
  29. package/dist/panels/ChoiceEdgeAppearanceFields.js +4 -3
  30. package/dist/panels/ChoiceTemplatesPanel.d.ts.map +1 -1
  31. package/dist/panels/ChoiceTemplatesPanel.js +3 -2
  32. package/dist/panels/GraphEditorInfoPanel.d.ts.map +1 -1
  33. package/dist/panels/GraphEditorInfoPanel.js +5 -4
  34. package/dist/panels/InspectorPanel.d.ts.map +1 -1
  35. package/dist/panels/InspectorPanel.js +1 -1
  36. package/dist/panels/IssuesPanel.d.ts.map +1 -1
  37. package/dist/panels/IssuesPanel.js +4 -5
  38. package/dist/panels/NodesPanel.d.ts.map +1 -1
  39. package/dist/panels/NodesPanel.js +7 -6
  40. package/dist/panels/SelectedEdgePanel.d.ts.map +1 -1
  41. package/dist/panels/SelectedEdgePanel.js +2 -1
  42. package/dist/panels/ToolbarPanel.d.ts +6 -18
  43. package/dist/panels/ToolbarPanel.d.ts.map +1 -1
  44. package/dist/panels/ToolbarPanel.js +10 -24
  45. package/dist/panels/inspector/ChoiceEditorCard.d.ts.map +1 -1
  46. package/dist/panels/inspector/ChoiceEditorCard.js +5 -4
  47. package/dist/panels/inspector/ChoiceEditorList.d.ts.map +1 -1
  48. package/dist/panels/inspector/ChoiceEditorList.js +3 -1
  49. package/dist/panels/inspector/NodeTypeField.d.ts.map +1 -1
  50. package/dist/panels/inspector/NodeTypeField.js +4 -3
  51. package/dist/panels/inspector/RequiredNodeCard.d.ts.map +1 -1
  52. package/dist/panels/inspector/RequiredNodeCard.js +3 -2
  53. package/dist/panels/inspector/choiceActionIconProps.d.ts +3 -2
  54. package/dist/panels/inspector/choiceActionIconProps.d.ts.map +1 -1
  55. package/dist/panels/inspector/choiceActionIconProps.js +4 -2
  56. package/dist/ui/editorClasses.d.ts +66 -0
  57. package/dist/ui/editorClasses.d.ts.map +1 -0
  58. package/dist/ui/editorClasses.js +89 -0
  59. package/dist/ui/primitives.d.ts +23 -0
  60. package/dist/ui/primitives.d.ts.map +1 -0
  61. package/dist/ui/primitives.js +32 -0
  62. package/docs/UI_KIT_AGNOSTIC_REFACTOR.md +186 -0
  63. package/docs/UI_KIT_AGNOSTIC_USAGE.md +129 -0
  64. package/package.json +8 -9
  65. package/README.standalone.md +0 -14
@@ -8,8 +8,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
8
  * host-specific diff logic.
9
9
  */
10
10
  import { TREE_SPEC_ISSUE_SEVERITY } from '@signalsafe/tree-spec';
11
- import { Button, CloseButton } from 'react-bootstrap';
12
11
  import { buildStableEntries } from '@signalsafe/tree-spec-editor-core';
12
+ import { EDITOR_MODAL, EDITOR_MODAL_BODY, EDITOR_MODAL_CONTENT, EDITOR_MODAL_DIALOG, EDITOR_MODAL_FOOTER, EDITOR_MODAL_HEADER, EDITOR_MODAL_TITLE, editorAlertToneClass, joinClasses, } from '../ui/editorClasses.js';
13
+ import { EditorButton, EditorCloseButton } from '../ui/primitives.js';
13
14
  const DEFAULT_TITLE = 'Review changes before publishing';
14
15
  const DEFAULT_SUMMARY_TEXT = 'Publishing is immutable. This summary compares the loaded version spec to your current graph.';
15
16
  const DEFAULT_ERROR_ALERT_TEXT = 'Validation errors exist. Fix them before publishing.';
@@ -21,5 +22,5 @@ export default function PublishReviewModal({ show, tree, baselineTree, issues, p
21
22
  return null;
22
23
  const hasErrors = issues.some((i) => i.severity === TREE_SPEC_ISSUE_SEVERITY.ERROR);
23
24
  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
+ return (_jsx("dialog", { className: joinClasses(EDITOR_MODAL, 'graph-editor-modal--open'), open: true, children: _jsx("div", { className: joinClasses(EDITOR_MODAL_DIALOG, 'graph-editor-modal__dialog--lg'), children: _jsxs("div", { className: EDITOR_MODAL_CONTENT, children: [_jsxs("div", { className: EDITOR_MODAL_HEADER, children: [_jsx("h2", { className: EDITOR_MODAL_TITLE, children: title }), _jsx(EditorCloseButton, { onClick: onClose })] }), _jsxs("div", { className: EDITOR_MODAL_BODY, children: [_jsx("div", { className: editorAlertToneClass('info'), children: summaryText }), _jsx("ul", { children: diffLineEntries.map(({ item: line, key }) => (_jsx("li", { children: line }, key))) }), hasErrors ? (_jsx("div", { className: editorAlertToneClass('danger'), children: errorAlertText })) : null] }), _jsxs("div", { className: EDITOR_MODAL_FOOTER, children: [_jsx(EditorButton, { tone: "neutral", onClick: onClose, children: cancelLabel }), _jsx(EditorButton, { tone: "success", disabled: publishing || hasErrors, onClick: onPublish, children: publishing ? publishingLabel : publishLabel })] })] }) }) }));
25
26
  }
@@ -20,7 +20,7 @@ export interface AdvancedJsonPanelProps {
20
20
  expandAllLabel?: string;
21
21
  /** Optional override for the collapse button label (default "Compress all"). */
22
22
  collapseAllLabel?: string;
23
- /** Optional extra class names applied to the outer `card` element. */
23
+ /** Optional extra class names applied to the outer card element. */
24
24
  className?: string;
25
25
  }
26
26
  export default function AdvancedJsonPanel({ children, title, subtitle, onExpandAll, onCollapseAll, expandAllLabel, collapseAllLabel, className, }: Readonly<AdvancedJsonPanelProps>): import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"AdvancedJsonPanel.d.ts","sourceRoot":"","sources":["../../src/panels/AdvancedJsonPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,MAAM,WAAW,sBAAsB;IACnC,uEAAuE;IACvE,QAAQ,EAAE,SAAS,CAAC;IACpB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EACtC,QAAQ,EACR,KAAqB,EACrB,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAA6B,EAC7B,gBAAiC,EACjC,SAAS,GACZ,EAAE,QAAQ,CAAC,sBAAsB,CAAC,+BAsClC"}
1
+ {"version":3,"file":"AdvancedJsonPanel.d.ts","sourceRoot":"","sources":["../../src/panels/AdvancedJsonPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAsBvC,MAAM,WAAW,sBAAsB;IACnC,uEAAuE;IACvE,QAAQ,EAAE,SAAS,CAAC;IACpB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EACtC,QAAQ,EACR,KAAqB,EACrB,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAA6B,EAC7B,gBAAiC,EACjC,SAAS,GACZ,EAAE,QAAQ,CAAC,sBAAsB,CAAC,+BAwClC"}
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
- import { Button } from 'react-bootstrap';
4
3
  import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
4
+ import { EDITOR_CARD, EDITOR_CARD_BODY, EDITOR_CARD_HEADER, EDITOR_FLEX_BETWEEN, EDITOR_FLEX_ROW, EDITOR_FLEX_SHRINK_0, EDITOR_FLEX_WRAP, EDITOR_HIDDEN, EDITOR_MIN_W_0, EDITOR_MUTED, EDITOR_SPACING_MS_AUTO, EDITOR_SPACING_MT_3, joinClasses, } from '../ui/editorClasses.js';
5
+ import { EditorButton } from '../ui/primitives.js';
5
6
  const DEFAULT_TITLE = 'Advanced JSON (read-only)';
6
7
  export default function AdvancedJsonPanel({ children, title = DEFAULT_TITLE, subtitle, onExpandAll, onCollapseAll, expandAllLabel = 'Expand all', collapseAllLabel = 'Compress all', className, }) {
7
8
  const [expanded, setExpanded] = useState(true);
8
9
  const hasButtons = Boolean(onExpandAll) || Boolean(onCollapseAll);
9
- const cardClassName = ['card', 'mt-3', className].filter(Boolean).join(' ');
10
- return (_jsxs("div", { className: cardClassName, children: [_jsxs("div", { className: "card-header d-flex justify-content-between align-items-start gap-2 flex-wrap bg-body-secondary py-2 px-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "d-flex align-items-center flex-wrap gap-1", children: [_jsx("span", { className: "fw-bold", children: title }), _jsx(PanelHeaderCollapseCarets, { expanded: expanded, onToggle: () => setExpanded((v) => !v) })] }), subtitle ? _jsx("div", { className: "text-muted font-size-12", children: subtitle }) : null] }), hasButtons ? (_jsxs("div", { className: "btn-group btn-group-sm flex-shrink-0 ms-auto", children: [onExpandAll ? (_jsx(Button, { type: "button", variant: "outline-secondary", onClick: onExpandAll, children: expandAllLabel })) : null, onCollapseAll ? (_jsx(Button, { type: "button", variant: "outline-secondary", onClick: onCollapseAll, children: collapseAllLabel })) : null] })) : null] }), _jsx("div", { className: `card-body p-0${expanded ? '' : ' d-none'}`, "aria-hidden": !expanded, children: children })] }));
10
+ return (_jsxs("div", { className: joinClasses(EDITOR_CARD, EDITOR_SPACING_MT_3, className), children: [_jsxs("div", { className: joinClasses(EDITOR_CARD_HEADER, EDITOR_FLEX_BETWEEN, EDITOR_FLEX_WRAP), children: [_jsxs("div", { className: EDITOR_MIN_W_0, children: [_jsxs("div", { className: joinClasses(EDITOR_FLEX_ROW, EDITOR_FLEX_WRAP), children: [_jsx("span", { className: "graph-editor-text--bold", children: title }), _jsx(PanelHeaderCollapseCarets, { expanded: expanded, onToggle: () => setExpanded((v) => !v) })] }), subtitle ? _jsx("div", { className: joinClasses(EDITOR_MUTED, 'graph-editor-text--sm'), children: subtitle }) : null] }), hasButtons ? (_jsxs("div", { className: joinClasses(EDITOR_FLEX_ROW, EDITOR_FLEX_SHRINK_0, EDITOR_SPACING_MS_AUTO, 'graph-editor-btn-group'), children: [onExpandAll ? (_jsx(EditorButton, { tone: "neutral", onClick: onExpandAll, children: expandAllLabel })) : null, onCollapseAll ? (_jsx(EditorButton, { tone: "neutral", onClick: onCollapseAll, children: collapseAllLabel })) : null] })) : null] }), _jsx("div", { className: joinClasses(EDITOR_CARD_BODY, 'graph-editor-card__body--flush', !expanded && EDITOR_HIDDEN), "aria-hidden": !expanded, children: children })] }));
11
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AppearancePanel.d.ts","sourceRoot":"","sources":["../../src/panels/AppearancePanel.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,EAEH,KAAK,eAAe,EAEpB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAClB,MAAM,mCAAmC,CAAC;AAK3C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC,YAAY,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oBAAoB,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IAC3D,yFAAyF;IACzF,sBAAsB,EAAE,CAAC,GAAG,EAAE,0BAA0B,KAAK,SAAS,CAAC;IACvE,uBAAuB,CAAC,EAAE,CACtB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,KAC9B,IAAI,CAAC;IACV,0DAA0D;IAC1D,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAmID,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EACpC,IAAI,EACJ,YAAY,EACZ,YAAmB,EACnB,aAAoB,EACpB,WAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,YAAY,EACZ,KAAoB,EACpB,cAA4D,EAC5D,UAAkE,GACrE,EAAE,QAAQ,CAAC,oBAAoB,CAAC,+BA0EhC"}
1
+ {"version":3,"file":"AppearancePanel.d.ts","sourceRoot":"","sources":["../../src/panels/AppearancePanel.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,EAEH,KAAK,eAAe,EAEpB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAClB,MAAM,mCAAmC,CAAC;AAkB3C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC,YAAY,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oBAAoB,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IAC3D,yFAAyF;IACzF,sBAAsB,EAAE,CAAC,GAAG,EAAE,0BAA0B,KAAK,SAAS,CAAC;IACvE,uBAAuB,CAAC,EAAE,CACtB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,KAC9B,IAAI,CAAC;IACV,0DAA0D;IAC1D,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAgID,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EACpC,IAAI,EACJ,YAAY,EACZ,YAAmB,EACnB,aAAoB,EACpB,WAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,YAAY,EACZ,KAAoB,EACpB,cAA4D,EAC5D,UAAkE,GACrE,EAAE,QAAQ,CAAC,oBAAoB,CAAC,+BA0EhC"}
@@ -3,6 +3,7 @@ import { useState } from 'react';
3
3
  import { getTransition, } from '@signalsafe/tree-spec-editor-core';
4
4
  import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
5
5
  import { PanelNodeLink } from '../lib/panelNodeLink.js';
6
+ import { EDITOR_CARD, EDITOR_CARD_BODY, EDITOR_CARD_HEADER, EDITOR_FLEX_ROW, EDITOR_HIDDEN, EDITOR_MIN_W_0, EDITOR_MUTED, EDITOR_SPACING_MB_2, EDITOR_SPACING_MB_3, EDITOR_SPACING_MT_3, joinClasses, } from '../ui/editorClasses.js';
6
7
  import ChoiceEdgeAppearanceFields from './ChoiceEdgeAppearanceFields.js';
7
8
  function resolveActiveChoiceId(choices, selectedEdge, focusChoiceId) {
8
9
  if (selectedEdge)
@@ -14,16 +15,13 @@ function resolveActiveChoiceId(choices, selectedEdge, focusChoiceId) {
14
15
  }
15
16
  const EDGE_APPEARANCE_HELPER = 'Canvas only (not shown in preview or training)';
16
17
  function EdgeContextBreadcrumb({ fromNodeId, choiceId, toNodeId, onNodeSelect, }) {
17
- return (_jsxs("div", { className: "text-muted font-size-12 mb-3", children: [_jsx(PanelNodeLink, { nodeId: fromNodeId, onNodeSelect: onNodeSelect }), ' · ', choiceId, ' → ', toNodeId ? _jsx(PanelNodeLink, { nodeId: toNodeId, onNodeSelect: onNodeSelect }) : '(not connected)'] }));
18
+ return (_jsxs("div", { className: joinClasses(EDITOR_MUTED, 'graph-editor-text--sm', EDITOR_SPACING_MB_3), children: [_jsx(PanelNodeLink, { nodeId: fromNodeId, onNodeSelect: onNodeSelect }), ' · ', choiceId, ' → ', toNodeId ? _jsx(PanelNodeLink, { nodeId: toNodeId, onNodeSelect: onNodeSelect }) : '(not connected)'] }));
18
19
  }
19
20
  function EdgeAppearanceSection({ choice, isPublished, onPatch, }) {
20
- return (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted small mb-2", children: EDGE_APPEARANCE_HELPER }), _jsx("div", { className: "small fw-semibold mb-2", children: "Edge appearance" }), _jsx(ChoiceEdgeAppearanceFields, { variant: "embedded", choice: choice, isPublished: isPublished, onPatch: onPatch })] }));
21
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: joinClasses(EDITOR_MUTED, 'graph-editor-text--sm', EDITOR_SPACING_MB_2), children: EDGE_APPEARANCE_HELPER }), _jsx("div", { className: joinClasses('graph-editor-text--sm', 'graph-editor-text--semibold', EDITOR_SPACING_MB_2), children: "Edge appearance" }), _jsx(ChoiceEdgeAppearanceFields, { variant: "embedded", choice: choice, isPublished: isPublished, onPatch: onPatch })] }));
21
22
  }
22
23
  function appearancePanelBodyClassName(hasSelection, expanded) {
23
- if (hasSelection && !expanded) {
24
- return 'card-body d-none';
25
- }
26
- return 'card-body';
24
+ return joinClasses(EDITOR_CARD_BODY, hasSelection && !expanded && EDITOR_HIDDEN);
27
25
  }
28
26
  function deriveAppearancePanelViewState({ tree, selectedNode, selectedEdge, focusChoiceId, onUpdateChoiceEdgeHints, }) {
29
27
  const edgeFocused = Boolean(selectedEdge);
@@ -67,10 +65,10 @@ export default function AppearancePanel({ tree, selectedNode, selectedEdge = nul
67
65
  focusChoiceId,
68
66
  onUpdateChoiceEdgeHints,
69
67
  });
70
- return (_jsxs("div", { className: "card mt-3", children: [_jsxs("div", { className: "card-header bg-body-secondary py-2 px-2 d-flex align-items-center min-w-0", children: [_jsx("span", { className: "fw-semibold", children: title }), hasSelection ? (_jsx(PanelHeaderCollapseCarets, { expanded: expanded, onToggle: () => setExpanded((v) => !v) })) : null] }), _jsx("div", { className: appearancePanelBodyClassName(hasSelection, expanded), "aria-hidden": Boolean(hasSelection && !expanded), children: hasSelection && contextNode ? (_jsxs(_Fragment, { children: [showNodeAppearance ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted small mb-2", children: helperText }), renderAppearanceFields({
68
+ return (_jsxs("div", { className: joinClasses(EDITOR_CARD, EDITOR_SPACING_MT_3), children: [_jsxs("div", { className: joinClasses(EDITOR_CARD_HEADER, EDITOR_FLEX_ROW, EDITOR_MIN_W_0), children: [_jsx("span", { className: "graph-editor-text--semibold", children: title }), hasSelection ? (_jsx(PanelHeaderCollapseCarets, { expanded: expanded, onToggle: () => setExpanded((v) => !v) })) : null] }), _jsx("div", { className: appearancePanelBodyClassName(hasSelection, expanded), "aria-hidden": Boolean(hasSelection && !expanded), children: hasSelection && contextNode ? (_jsxs(_Fragment, { children: [showNodeAppearance ? (_jsxs(_Fragment, { children: [_jsx("div", { className: joinClasses(EDITOR_MUTED, 'graph-editor-text--sm', EDITOR_SPACING_MB_2), children: helperText }), renderAppearanceFields({
71
69
  tree,
72
70
  node: contextNode,
73
71
  isPublished,
74
72
  onUpdateNode: onUpdateSelectedNode,
75
- })] })) : null, showEdgeAppearance && edgeFromNodeId && activeChoiceId && activeChoice ? (_jsxs(_Fragment, { children: [_jsx(EdgeContextBreadcrumb, { fromNodeId: edgeFromNodeId, choiceId: activeChoiceId, toNodeId: edgeToNodeId, onNodeSelect: onNodeSelect }), _jsx(EdgeAppearanceSection, { choice: activeChoice, isPublished: isPublished, onPatch: (patch) => onUpdateChoiceEdgeHints(contextNode.id, activeChoice.id, patch) })] })) : null] })) : (_jsx("div", { className: "text-muted", children: _jsx("em", { children: emptyStateText }) })) })] }));
73
+ })] })) : null, showEdgeAppearance && edgeFromNodeId && activeChoiceId && activeChoice ? (_jsxs(_Fragment, { children: [_jsx(EdgeContextBreadcrumb, { fromNodeId: edgeFromNodeId, choiceId: activeChoiceId, toNodeId: edgeToNodeId, onNodeSelect: onNodeSelect }), _jsx(EdgeAppearanceSection, { choice: activeChoice, isPublished: isPublished, onPatch: (patch) => onUpdateChoiceEdgeHints(contextNode.id, activeChoice.id, patch) })] })) : null] })) : (_jsx("div", { className: EDITOR_MUTED, children: _jsx("em", { children: emptyStateText }) })) })] }));
76
74
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ChoiceEdgeAppearanceFields.d.ts","sourceRoot":"","sources":["../../src/panels/ChoiceEdgeAppearanceFields.tsx"],"names":[],"mappings":"AAGA,OAAO,EAIH,KAAK,eAAe,EACpB,KAAK,YAAY,EACpB,MAAM,mCAAmC,CAAC;AAE3C,MAAM,WAAW,+BAA+B;IAC5C,MAAM,EAAE,YAAY,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IACnD,+EAA+E;IAC/E,OAAO,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;CACvC;AAED,MAAM,CAAC,OAAO,UAAU,0BAA0B,CAAC,EAC/C,MAAM,EACN,WAAmB,EACnB,OAAO,EACP,OAAsB,GACzB,EAAE,QAAQ,CAAC,+BAA+B,CAAC,+BAqE3C"}
1
+ {"version":3,"file":"ChoiceEdgeAppearanceFields.d.ts","sourceRoot":"","sources":["../../src/panels/ChoiceEdgeAppearanceFields.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIH,KAAK,eAAe,EACpB,KAAK,YAAY,EACpB,MAAM,mCAAmC,CAAC;AAoB3C,MAAM,WAAW,+BAA+B;IAC5C,MAAM,EAAE,YAAY,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IACnD,+EAA+E;IAC/E,OAAO,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;CACvC;AAED,MAAM,CAAC,OAAO,UAAU,0BAA0B,CAAC,EAC/C,MAAM,EACN,WAAmB,EACnB,OAAO,EACP,OAAsB,GACzB,EAAE,QAAQ,CAAC,+BAA+B,CAAC,+BAqE3C"}
@@ -1,13 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Form } from 'react-bootstrap';
3
2
  import { EDITOR_EDGE_TYPE_OPTIONS, getChoiceEdgeHints, resolveEdgeStrokeColorForDisplay, } from '@signalsafe/tree-spec-editor-core';
3
+ import { EDITOR_FLEX_ROW, EDITOR_SPACING_MB_0, EDITOR_SPACING_MB_1, EDITOR_SPACING_MB_2, EDITOR_SPACING_MT_3, EDITOR_SPACING_PT_2, joinClasses, } from '../ui/editorClasses.js';
4
+ import { EditorButton, EditorField, EditorInput, EditorLabel, EditorSelect, EditorSwitch, } from '../ui/primitives.js';
4
5
  export default function ChoiceEdgeAppearanceFields({ choice, isPublished = false, onPatch, variant = 'standalone', }) {
5
6
  const hints = getChoiceEdgeHints(choice);
6
- const fields = (_jsxs(_Fragment, { children: [_jsx(Form.Check, { type: "switch", id: `choice-edge-show-label-${choice.id}`, className: "mb-2", label: "Show label on canvas", checked: hints.showLabel !== false, disabled: isPublished, onChange: (event) => onPatch({ showLabel: event.target.checked }) }), _jsxs(Form.Group, { className: "mb-2", children: [_jsx(Form.Label, { className: "small mb-1", children: "Stroke color" }), _jsxs("div", { className: "d-flex gap-2 align-items-center", children: [_jsx(Form.Control, { type: "color", className: "graph-editor-appearance-color-input", value: resolveEdgeStrokeColorForDisplay(choice), disabled: isPublished, onChange: (event) => onPatch({ strokeColor: event.target.value }) }), _jsx("button", { type: "button", className: "btn btn-sm btn-outline-secondary", disabled: isPublished || hints.strokeColor === undefined, onClick: () => onPatch({ strokeColor: undefined }), children: "Reset" })] })] }), _jsxs(Form.Group, { className: "mb-0", children: [_jsx(Form.Label, { className: "small mb-1", children: "Edge type" }), _jsx(Form.Select, { value: hints.edgeType ?? 'default', disabled: isPublished, onChange: (event) => onPatch({
7
+ const fields = (_jsxs(_Fragment, { children: [_jsx(EditorSwitch, { id: `choice-edge-show-label-${choice.id}`, className: EDITOR_SPACING_MB_2, label: "Show label on canvas", checked: hints.showLabel !== false, disabled: isPublished, onChange: (event) => onPatch({ showLabel: event.target.checked }) }), _jsxs(EditorField, { className: EDITOR_SPACING_MB_2, children: [_jsx(EditorLabel, { className: joinClasses('graph-editor-text--sm', EDITOR_SPACING_MB_1), children: "Stroke color" }), _jsxs("div", { className: joinClasses(EDITOR_FLEX_ROW, 'graph-editor-flex--gap'), children: [_jsx(EditorInput, { type: "color", className: "graph-editor-appearance-color-input", value: resolveEdgeStrokeColorForDisplay(choice), disabled: isPublished, onChange: (event) => onPatch({ strokeColor: event.target.value }) }), _jsx(EditorButton, { tone: "neutral", disabled: isPublished || hints.strokeColor === undefined, onClick: () => onPatch({ strokeColor: undefined }), children: "Reset" })] })] }), _jsxs(EditorField, { className: EDITOR_SPACING_MB_0, children: [_jsx(EditorLabel, { className: joinClasses('graph-editor-text--sm', EDITOR_SPACING_MB_1), children: "Edge type" }), _jsx(EditorSelect, { value: hints.edgeType ?? 'default', disabled: isPublished, onChange: (event) => onPatch({
7
8
  edgeType: event.target.value,
8
9
  }), children: EDITOR_EDGE_TYPE_OPTIONS.map((option) => (_jsx("option", { value: option.value ?? 'default', children: option.label }, option.value ?? 'default'))) })] })] }));
9
10
  if (variant === 'embedded') {
10
11
  return fields;
11
12
  }
12
- return (_jsxs("div", { className: "mt-3 pt-2 border-top", children: [_jsx("div", { className: "small fw-semibold mb-2", children: "Edge appearance (canvas only)" }), fields] }));
13
+ return (_jsxs("div", { className: joinClasses('graph-editor-card__section', 'graph-editor-card__section--border-top', EDITOR_SPACING_MT_3, EDITOR_SPACING_PT_2), children: [_jsx("div", { className: joinClasses('graph-editor-text--sm', 'graph-editor-text--semibold', EDITOR_SPACING_MB_2), children: "Edge appearance (canvas only)" }), fields] }));
13
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ChoiceTemplatesPanel.d.ts","sourceRoot":"","sources":["../../src/panels/ChoiceTemplatesPanel.tsx"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,2EAA2E;AAC3E,MAAM,MAAM,kBAAkB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1D,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,gBAAgB,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,WAAW,yBAAyB;IACtC,SAAS,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAC7C,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC3D;AAED,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EACzC,SAAS,EACT,cAAc,EACd,WAAmB,EACnB,eAAe,GAClB,EAAE,QAAQ,CAAC,yBAAyB,CAAC,+BAiCrC"}
1
+ {"version":3,"file":"ChoiceTemplatesPanel.d.ts","sourceRoot":"","sources":["../../src/panels/ChoiceTemplatesPanel.tsx"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,2EAA2E;AAC3E,MAAM,MAAM,kBAAkB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1D,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,gBAAgB,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,WAAW,yBAAyB;IACtC,SAAS,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAC7C,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC3D;AAED,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EACzC,SAAS,EACT,cAAc,EACd,WAAmB,EACnB,eAAe,GAClB,EAAE,QAAQ,CAAC,yBAAyB,CAAC,+BAoCrC"}
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
- import { Button, Card } from 'react-bootstrap';
4
3
  import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
4
+ import { EDITOR_CARD, EDITOR_CARD_BODY, EDITOR_CARD_HEADER, EDITOR_FLEX_BETWEEN, EDITOR_FLEX_ROW, EDITOR_FLEX_WRAP, EDITOR_HIDDEN, EDITOR_MUTED, EDITOR_SPACING_MB_0, EDITOR_SPACING_MB_3, EDITOR_SPACING_PY_2, joinClasses, } from '../ui/editorClasses.js';
5
+ import { EditorButton } from '../ui/primitives.js';
5
6
  export default function ChoiceTemplatesPanel({ templates, selectedNodeId, isPublished = false, onApplyTemplate, }) {
6
7
  const [expanded, setExpanded] = useState(true);
7
8
  const disabled = isPublished || !selectedNodeId;
8
- return (_jsxs(Card, { className: "mb-3", children: [_jsxs(Card.Header, { className: "d-flex align-items-center justify-content-between py-2", children: [_jsx("span", { className: "fw-semibold", children: "Choice templates" }), _jsx(PanelHeaderCollapseCarets, { expanded: expanded, onToggle: () => setExpanded((value) => !value) })] }), _jsx("div", { className: `card-body py-2${expanded ? '' : ' d-none'}`, "aria-hidden": !expanded, children: selectedNodeId ? (_jsx("div", { className: "d-flex flex-wrap gap-2", children: templates.map((template) => (_jsx(Button, { type: "button", size: "sm", variant: "outline-secondary", disabled: disabled, title: template.choices.map((choice) => choice.label).join(' · '), onClick: () => onApplyTemplate(template), children: template.label }, template.id))) })) : (_jsx("p", { className: "text-muted small mb-0", children: "Select a node to add preset choices." })) })] }));
9
+ return (_jsxs("div", { className: joinClasses(EDITOR_CARD, EDITOR_SPACING_MB_3), children: [_jsxs("div", { className: joinClasses(EDITOR_CARD_HEADER, EDITOR_FLEX_BETWEEN), children: [_jsx("span", { className: "graph-editor-text--semibold", children: "Choice templates" }), _jsx(PanelHeaderCollapseCarets, { expanded: expanded, onToggle: () => setExpanded((value) => !value) })] }), _jsx("div", { className: joinClasses(EDITOR_CARD_BODY, EDITOR_SPACING_PY_2, !expanded && EDITOR_HIDDEN), "aria-hidden": !expanded, children: selectedNodeId ? (_jsx("div", { className: joinClasses(EDITOR_FLEX_ROW, EDITOR_FLEX_WRAP, 'graph-editor-flex--gap'), children: templates.map((template) => (_jsx(EditorButton, { tone: "neutral", disabled: disabled, title: template.choices.map((choice) => choice.label).join(' · '), onClick: () => onApplyTemplate(template), children: template.label }, template.id))) })) : (_jsx("p", { className: joinClasses(EDITOR_MUTED, 'graph-editor-text--sm', EDITOR_SPACING_MB_0), children: "Select a node to add preset choices." })) })] }));
9
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"GraphEditorInfoPanel.d.ts","sourceRoot":"","sources":["../../src/panels/GraphEditorInfoPanel.tsx"],"names":[],"mappings":"AAKA,OAAO,EAGH,KAAK,cAAc,EACnB,KAAK,mBAAmB,EAC3B,MAAM,mCAAmC,CAAC;AAE3C,MAAM,WAAW,yBAAyB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,kEAAkE;IAClE,WAAW,EAAE,OAAO,CAAC;IACrB,2DAA2D;IAC3D,cAAc,EAAE,cAAc,CAAC;IAC/B,gFAAgF;IAChF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2FAA2F;IAC3F,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C,sEAAsE;IACtE,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,uBAAuB,CAAC,EAAE,CAAC,QAAQ,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACrE;AA0BD,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EACzC,UAAU,EACV,SAAS,EACT,IAAI,EACJ,SAAS,EACT,SAAS,EACT,WAAW,EACX,cAAc,EACd,eAAe,EACf,KAAc,EACd,eAAwC,EACxC,eAA8B,EAC9B,uBAAuB,GAC1B,EAAE,QAAQ,CAAC,yBAAyB,CAAC,+BAsFrC"}
1
+ {"version":3,"file":"GraphEditorInfoPanel.d.ts","sourceRoot":"","sources":["../../src/panels/GraphEditorInfoPanel.tsx"],"names":[],"mappings":"AAIA,OAAO,EAGH,KAAK,cAAc,EACnB,KAAK,mBAAmB,EAC3B,MAAM,mCAAmC,CAAC;AAyB3C,MAAM,WAAW,yBAAyB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,kEAAkE;IAClE,WAAW,EAAE,OAAO,CAAC;IACrB,2DAA2D;IAC3D,cAAc,EAAE,cAAc,CAAC;IAC/B,gFAAgF;IAChF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2FAA2F;IAC3F,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C,sEAAsE;IACtE,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,uBAAuB,CAAC,EAAE,CAAC,QAAQ,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACrE;AA0BD,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EACzC,UAAU,EACV,SAAS,EACT,IAAI,EACJ,SAAS,EACT,SAAS,EACT,WAAW,EACX,cAAc,EACd,eAAe,EACf,KAAc,EACd,eAAwC,EACxC,eAA8B,EAC9B,uBAAuB,GAC1B,EAAE,QAAQ,CAAC,yBAAyB,CAAC,+BAyFrC"}
@@ -1,13 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
- import { Badge, Form, Table } from 'react-bootstrap';
4
3
  import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
5
4
  import { EDITOR_EDGE_TYPE_OPTIONS, getAutosaveStatusLabel, } from '@signalsafe/tree-spec-editor-core';
5
+ import { EDITOR_CARD, EDITOR_CARD_BODY, EDITOR_CARD_HEADER, EDITOR_ALIGN_TOP, EDITOR_FLEX_ROW, EDITOR_FLEX_WRAP, EDITOR_HIDDEN, EDITOR_MONO, EDITOR_MUTED, EDITOR_SPACING_M_0, EDITOR_SPACING_MB_0, EDITOR_SPACING_MB_1, EDITOR_SPACING_MB_2, EDITOR_SPACING_MB_3, EDITOR_SPACING_MT_1, EDITOR_TABLE, EDITOR_TEXT_BREAK, editorBadgeToneClass, joinClasses, } from '../ui/editorClasses.js';
6
+ import { EditorField, EditorLabel, EditorSelect } from '../ui/primitives.js';
6
7
  function defaultFormatTimestamp(iso) {
7
8
  return new Date(iso).toLocaleString();
8
9
  }
9
10
  function PropertyRow({ label, value }) {
10
- return (_jsxs("tr", { children: [_jsx("td", { className: "align-top", children: _jsx("strong", { children: label }) }), _jsx("td", { children: value })] }));
11
+ return (_jsxs("tr", { children: [_jsx("td", { className: EDITOR_ALIGN_TOP, children: _jsx("strong", { children: label }) }), _jsx("td", { children: value })] }));
11
12
  }
12
13
  const STATUS_DRAFT = 'Draft';
13
14
  const STATUS_PUBLISHED = 'Published (read-only)';
@@ -19,7 +20,7 @@ function autosaveDisplay(isPublished, status) {
19
20
  }
20
21
  export default function GraphEditorInfoPanel({ scenarioId, versionId, name, createdAt, updatedAt, isPublished, autosaveStatus, lastValidatedAt, title = 'Info', formatTimestamp = defaultFormatTimestamp, defaultEdgeType = 'smoothstep', onUpdateDefaultEdgeType, }) {
21
22
  const [expanded, setExpanded] = useState(true);
22
- return (_jsxs("div", { className: "card mb-3", children: [_jsx("div", { className: "card-header bg-body-secondary py-2 px-2", children: _jsxs("div", { className: "d-flex align-items-center flex-wrap gap-1", children: [_jsx("h5", { className: "mb-0", children: title }), _jsx(PanelHeaderCollapseCarets, { expanded: expanded, onToggle: () => setExpanded((v) => !v) })] }) }), _jsxs("div", { className: `card-body p-0${expanded ? '' : ' d-none'}`, "aria-hidden": !expanded, children: [_jsx(Table, { striped: true, bordered: true, hover: true, responsive: true, className: "m-0", children: _jsxs("tbody", { children: [_jsx(PropertyRow, { label: "Name", value: name }), _jsx(PropertyRow, { label: "Status", value: _jsx(Badge, { bg: isPublished ? 'success' : 'secondary', children: isPublished ? STATUS_PUBLISHED : STATUS_DRAFT }) }), _jsx(PropertyRow, { label: "Save state", value: _jsx("span", { className: "text-muted", children: autosaveDisplay(isPublished, autosaveStatus) }) }), _jsx(PropertyRow, { label: "Validated", value: _jsx("span", { className: "text-muted", children: lastValidatedAt
23
+ return (_jsxs("div", { className: joinClasses(EDITOR_CARD, EDITOR_SPACING_MB_3), children: [_jsx("div", { className: EDITOR_CARD_HEADER, children: _jsxs("div", { className: joinClasses(EDITOR_FLEX_ROW, EDITOR_FLEX_WRAP), children: [_jsx("h5", { className: EDITOR_SPACING_MB_0, children: title }), _jsx(PanelHeaderCollapseCarets, { expanded: expanded, onToggle: () => setExpanded((v) => !v) })] }) }), _jsxs("div", { className: joinClasses(EDITOR_CARD_BODY, 'graph-editor-card__body--flush', !expanded && EDITOR_HIDDEN), "aria-hidden": !expanded, children: [_jsx("table", { className: joinClasses(EDITOR_TABLE, EDITOR_SPACING_M_0), children: _jsxs("tbody", { children: [_jsx(PropertyRow, { label: "Name", value: name }), _jsx(PropertyRow, { label: "Status", value: _jsx("span", { className: editorBadgeToneClass(isPublished ? 'success' : 'secondary'), children: isPublished ? STATUS_PUBLISHED : STATUS_DRAFT }) }), _jsx(PropertyRow, { label: "Save state", value: _jsx("span", { className: EDITOR_MUTED, children: autosaveDisplay(isPublished, autosaveStatus) }) }), _jsx(PropertyRow, { label: "Validated", value: _jsx("span", { className: EDITOR_MUTED, children: lastValidatedAt
23
24
  ? `Validated ${formatTimestamp(lastValidatedAt)}`
24
- : 'Not validated' }) }), _jsx(PropertyRow, { label: "Scenario ID", value: _jsx("span", { className: "font-monospace small text-break", children: scenarioId }) }), _jsx(PropertyRow, { label: "Version ID", value: _jsx("span", { className: "font-monospace small text-break", children: versionId }) }), _jsx(PropertyRow, { label: "Created", value: createdAt ? formatTimestamp(createdAt) : '—' }), _jsx(PropertyRow, { label: "Updated", value: updatedAt ? formatTimestamp(updatedAt) : '—' })] }) }), onUpdateDefaultEdgeType ? (_jsxs("div", { className: "p-3 border-top", children: [_jsx("div", { className: "small fw-semibold mb-2", children: "Global" }), _jsxs(Form.Group, { className: "mb-0", children: [_jsx(Form.Label, { className: "small mb-1", children: "Scenario default edge type" }), _jsx(Form.Select, { value: defaultEdgeType, disabled: isPublished, onChange: (event) => onUpdateDefaultEdgeType(event.target.value), children: EDITOR_EDGE_TYPE_OPTIONS.filter((option) => option.value !== 'default').map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value))) }), _jsx("div", { className: "text-muted small mt-1", children: "Used when a choice edge type is set to Default." })] })] })) : null] })] }));
25
+ : 'Not validated' }) }), _jsx(PropertyRow, { label: "Scenario ID", value: _jsx("span", { className: joinClasses(EDITOR_MONO, 'graph-editor-text--sm', EDITOR_TEXT_BREAK), children: scenarioId }) }), _jsx(PropertyRow, { label: "Version ID", value: _jsx("span", { className: joinClasses(EDITOR_MONO, 'graph-editor-text--sm', EDITOR_TEXT_BREAK), children: versionId }) }), _jsx(PropertyRow, { label: "Created", value: createdAt ? formatTimestamp(createdAt) : '—' }), _jsx(PropertyRow, { label: "Updated", value: updatedAt ? formatTimestamp(updatedAt) : '—' })] }) }), onUpdateDefaultEdgeType ? (_jsxs("div", { className: "graph-editor-card__section graph-editor-card__section--border-top", children: [_jsx("div", { className: joinClasses('graph-editor-text--sm', 'graph-editor-text--semibold', EDITOR_SPACING_MB_2), children: "Global" }), _jsxs(EditorField, { className: EDITOR_SPACING_MB_0, children: [_jsx(EditorLabel, { className: joinClasses('graph-editor-text--sm', EDITOR_SPACING_MB_1), children: "Scenario default edge type" }), _jsx(EditorSelect, { value: defaultEdgeType, disabled: isPublished, onChange: (event) => onUpdateDefaultEdgeType(event.target.value), children: EDITOR_EDGE_TYPE_OPTIONS.filter((option) => option.value !== 'default').map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value))) }), _jsx("div", { className: joinClasses(EDITOR_MUTED, 'graph-editor-text--sm', EDITOR_SPACING_MT_1), children: "Used when a choice edge type is set to Default." })] })] })) : null] })] }));
25
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"InspectorPanel.d.ts","sourceRoot":"","sources":["../../src/panels/InspectorPanel.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAGH,KAAK,mBAAmB,EAC3B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACH,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,GAC3B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EACnC,IAAI,EACJ,YAAY,EACZ,aAAoB,EACpB,WAAmB,EACnB,oBAAoB,EACpB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,cAAwC,EACxC,gBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,WAAW,EACX,eAAe,EACf,KAAkB,EAClB,cAA4C,EAC5C,cAAyC,EACzC,oBAAoB,EACpB,aAAa,GAChB,EAAE,QAAQ,CAAC,mBAAmB,CAAC,+BAuC/B"}
1
+ {"version":3,"file":"InspectorPanel.d.ts","sourceRoot":"","sources":["../../src/panels/InspectorPanel.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAGH,KAAK,mBAAmB,EAC3B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACH,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,GAC3B,MAAM,sBAAsB,CAAC;AAE9B,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EACnC,IAAI,EACJ,YAAY,EACZ,aAAoB,EACpB,WAAmB,EACnB,oBAAoB,EACpB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,cAAwC,EACxC,gBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,WAAW,EACX,eAAe,EACf,KAAkB,EAClB,cAA4C,EAC5C,cAAyC,EACzC,oBAAoB,EACpB,aAAa,GAChB,EAAE,QAAQ,CAAC,mBAAmB,CAAC,+BAuC/B"}
@@ -19,5 +19,5 @@ import RequiredNodeCard from './inspector/RequiredNodeCard.js';
19
19
  import { DEFAULT_OUTCOME_OPTIONS, DEFAULT_TYPE_HELPER_TEXT, } from './inspector/types.js';
20
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
- 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 }) })) }));
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: "graph-editor-muted", children: _jsx("em", { children: emptyStateText }) })) }));
23
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"IssuesPanel.d.ts","sourceRoot":"","sources":["../../src/panels/IssuesPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAGH,KAAK,UAAU,EACf,KAAK,cAAc,EACtB,MAAM,mCAAmC,CAAC;AAM3C,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC9C;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,wEAAwE;IACxE,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,0FAA0F;IAC1F,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uGAAuG;IACvG,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C;;;;OAIG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAC;CAC3C;AAwCD,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAChC,MAAM,EACN,eAAe,EACf,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,IAAI,EACJ,SAAS,EACT,aAAoB,EACpB,KAAgB,EAChB,iBAAyC,EACzC,eAAwC,EACxC,6BAAoC,GACvC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,+BAoH5B"}
1
+ {"version":3,"file":"IssuesPanel.d.ts","sourceRoot":"","sources":["../../src/panels/IssuesPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAGH,KAAK,UAAU,EACf,KAAK,cAAc,EACtB,MAAM,mCAAmC,CAAC;AA4B3C,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC9C;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,wEAAwE;IACxE,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,0FAA0F;IAC1F,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uGAAuG;IACvG,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C;;;;OAIG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAC;CAC3C;AAwCD,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAChC,MAAM,EACN,eAAe,EACf,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,IAAI,EACJ,SAAS,EACT,aAAoB,EACpB,KAAgB,EAChB,iBAAyC,EACzC,eAAwC,EACxC,6BAAoC,GACvC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,+BAuI5B"}
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useMemo, useState } from 'react';
3
- import { Form } from 'react-bootstrap';
4
3
  import { buildStableEntries, GRAPH_SELECTION_KIND, } from '@signalsafe/tree-spec-editor-core';
5
4
  import { getIssueSeverityBadgeClass } from '../lib/panelHelpers.js';
6
5
  import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
7
6
  import { LIST_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS } from '../lib/selectionStyles.js';
7
+ import { EDITOR_CARD, EDITOR_CARD_BODY, EDITOR_CARD_HEADER, EDITOR_FLEX_BETWEEN, EDITOR_FLEX_GROW_1, EDITOR_FLEX_ROW, EDITOR_FLEX_SHRINK_0, EDITOR_HIDDEN, EDITOR_LIST, EDITOR_LIST_ITEM, EDITOR_MIN_W_0, EDITOR_MONO, EDITOR_MUTED, EDITOR_SCROLL, EDITOR_SPACING_MB_1, EDITOR_TEXT_BREAK, EDITOR_TEXT_END, EDITOR_TEXT_START, joinClasses, } from '../ui/editorClasses.js';
8
+ import { EditorInput } from '../ui/primitives.js';
8
9
  function defaultFormatTimestamp(iso) {
9
10
  return new Date(iso).toLocaleString();
10
11
  }
@@ -42,12 +43,10 @@ export default function IssuesPanel({ issues, lastValidatedAt, onSelectIssue, is
42
43
  const qLower = issueSearch.trim().toLowerCase();
43
44
  const filteredIssues = useMemo(() => issues.filter((issue) => issueMatchesQuery(issue, qLower, tree)), [issues, qLower, tree]);
44
45
  const issueEntries = buildStableEntries(filteredIssues, (issue) => `${issue.severity}-${issue.node_id ?? ''}-${issue.message}`);
45
- 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: expanded, onToggle: () => setExpanded((v) => !v) })] }), showValidationSummaryInHeader ? (_jsx("span", { className: "text-muted font-size-12 text-end flex-shrink-0", children: lastValidatedAt ? `Validated ${formatTimestamp(lastValidatedAt)}` : 'Not validated' })) : null] }), _jsx("div", { className: `card-body p-0${expanded ? '' : ' d-none'}`, "aria-hidden": !expanded, children: issues.length === 0 ? (_jsx("div", { className: "list-group list-group-flush", children: _jsx("div", { className: "list-group-item text-muted small py-2 px-3 border-0", children: _jsx("em", { children: "No issues" }) }) })) : (_jsxs(_Fragment, { children: [_jsx(Form.Control, { className: "rounded-0 border-0 border-bottom shadow-none", placeholder: searchPlaceholder, value: issueSearch, onChange: (e) => onIssueSearchChange(e.target.value) }), _jsx("div", { className: "overflow-auto-max-h-320", children: issueEntries.length === 0 ? (_jsx("div", { className: "list-group list-group-flush", children: _jsx("div", { className: "list-group-item text-muted small py-2 px-3 border-0", children: _jsx("em", { children: "No matching issues." }) }) })) : (_jsx("div", { className: "list-group list-group-flush", children: issueEntries.map(({ item: issue, key }) => {
46
+ return (_jsxs("div", { className: EDITOR_CARD, children: [_jsxs("div", { className: joinClasses(EDITOR_CARD_HEADER, EDITOR_FLEX_BETWEEN), children: [_jsxs("div", { className: joinClasses(EDITOR_FLEX_ROW, EDITOR_MIN_W_0), children: [_jsx("span", { className: "graph-editor-text--semibold", children: title }), _jsx(PanelHeaderCollapseCarets, { expanded: expanded, onToggle: () => setExpanded((v) => !v) })] }), showValidationSummaryInHeader ? (_jsx("span", { className: joinClasses(EDITOR_MUTED, 'graph-editor-text--sm', EDITOR_TEXT_END, EDITOR_FLEX_SHRINK_0), children: lastValidatedAt ? `Validated ${formatTimestamp(lastValidatedAt)}` : 'Not validated' })) : null] }), _jsx("div", { className: joinClasses(EDITOR_CARD_BODY, 'graph-editor-card__body--flush', !expanded && EDITOR_HIDDEN), "aria-hidden": !expanded, children: issues.length === 0 ? (_jsx("div", { className: EDITOR_LIST, children: _jsx("div", { className: joinClasses(EDITOR_LIST_ITEM, EDITOR_MUTED, 'graph-editor-text--sm'), children: _jsx("em", { children: "No issues" }) }) })) : (_jsxs(_Fragment, { children: [_jsx(EditorInput, { className: "graph-editor-input--list-search", placeholder: searchPlaceholder, value: issueSearch, onChange: (e) => onIssueSearchChange(e.target.value) }), _jsx("div", { className: joinClasses(EDITOR_SCROLL, 'overflow-auto-max-h-320'), children: issueEntries.length === 0 ? (_jsx("div", { className: EDITOR_LIST, children: _jsx("div", { className: joinClasses(EDITOR_LIST_ITEM, EDITOR_MUTED, 'graph-editor-text--sm'), children: _jsx("em", { children: "No matching issues." }) }) })) : (_jsx("div", { className: EDITOR_LIST, children: issueEntries.map(({ item: issue, key }) => {
46
47
  const typeLabel = nodeTypeLabel(tree, issue.node_id);
47
48
  const headerTitle = issueHeaderTitle(issue, typeLabel);
48
49
  const isSelected = isIssueRowSelected(issue, selection, focusChoiceId);
49
- return (_jsxs("button", { type: "button", className: `list-group-item px-3 py-2 text-start w-100 min-w-0${isSelected
50
- ? ` ${LIST_SELECTION_CLASS} ${LIST_SELECTION_TEXT_CLASS}`
51
- : ''}`, "aria-current": isSelected ? 'true' : undefined, onClick: () => onSelectIssue(issue), children: [_jsxs("div", { className: "d-flex w-100 justify-content-between align-items-start gap-2 mb-1 min-w-0", children: [_jsxs("div", { className: "min-w-0 flex-grow-1 text-break text-start", title: headerTitle, children: [_jsx("span", { className: "fs-6 fw-semibold text-uppercase", children: issue.node_id ?? '—' }), _jsx("span", { className: `fs-6 text-uppercase${isSelected ? '' : ' text-body-secondary'}`, children: `, ${typeLabel}` })] }), _jsx("span", { className: `badge flex-shrink-0 text-uppercase ${getIssueSeverityBadgeClass(issue.severity)}`, children: issue.severity })] }), _jsx("p", { className: `mb-1 small text-break font-monospace${isSelected ? '' : ' text-body-secondary'}`, children: issue.message }), issue.choice_id ? (_jsx("small", { className: `text-break${isSelected ? '' : ' text-body-secondary'}`, children: issue.choice_id })) : null] }, key));
50
+ return (_jsxs("button", { type: "button", className: joinClasses(EDITOR_LIST_ITEM, 'graph-editor-list__item--button', isSelected && LIST_SELECTION_CLASS, isSelected && LIST_SELECTION_TEXT_CLASS), "aria-current": isSelected ? 'true' : undefined, onClick: () => onSelectIssue(issue), children: [_jsxs("div", { className: joinClasses(EDITOR_FLEX_BETWEEN, EDITOR_SPACING_MB_1, EDITOR_MIN_W_0), children: [_jsxs("div", { className: joinClasses(EDITOR_MIN_W_0, EDITOR_FLEX_GROW_1, EDITOR_TEXT_BREAK, EDITOR_TEXT_START), title: headerTitle, children: [_jsx("span", { className: "graph-editor-text--uppercase graph-editor-text--semibold", children: issue.node_id ?? '—' }), _jsx("span", { className: joinClasses('graph-editor-text--uppercase', !isSelected && EDITOR_MUTED), children: `, ${typeLabel}` })] }), _jsx("span", { className: joinClasses(getIssueSeverityBadgeClass(issue.severity), EDITOR_FLEX_SHRINK_0, 'graph-editor-text--uppercase'), children: issue.severity })] }), _jsx("p", { className: joinClasses(EDITOR_MONO, 'graph-editor-text--sm', EDITOR_TEXT_BREAK, EDITOR_SPACING_MB_1, !isSelected && EDITOR_MUTED), children: issue.message }), issue.choice_id ? (_jsx("small", { className: joinClasses(EDITOR_TEXT_BREAK, !isSelected && EDITOR_MUTED), children: issue.choice_id })) : null] }, key));
52
51
  }) })) })] })) })] }));
53
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"NodesPanel.d.ts","sourceRoot":"","sources":["../../src/panels/NodesPanel.tsx"],"names":[],"mappings":"AAIA,OAAO,EAIH,KAAK,UAAU,EACf,KAAK,cAAc,EACtB,MAAM,mCAAmC,CAAC;AAK3C,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,cAAc,CAAC;IAC1B,wFAAwF;IACxF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,mBAAmB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,mFAAmF;IACnF,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAmCD,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAC/B,IAAI,EACJ,UAAU,EACV,SAAS,EACT,WAAkB,EAClB,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,iBAAwC,EACxC,OAA0B,EAC1B,SAAS,EACT,YAAY,EACZ,WAAmB,GACtB,EAAE,QAAQ,CAAC,eAAe,CAAC,+BA8I3B"}
1
+ {"version":3,"file":"NodesPanel.d.ts","sourceRoot":"","sources":["../../src/panels/NodesPanel.tsx"],"names":[],"mappings":"AAGA,OAAO,EAIH,KAAK,UAAU,EACf,KAAK,cAAc,EACtB,MAAM,mCAAmC,CAAC;AA2B3C,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,cAAc,CAAC;IAC1B,wFAAwF;IACxF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,mBAAmB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,mFAAmF;IACnF,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAmCD,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAC/B,IAAI,EACJ,UAAU,EACV,SAAS,EACT,WAAkB,EAClB,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,iBAAwC,EACxC,OAA0B,EAC1B,SAAS,EACT,YAAY,EACZ,WAAmB,GACtB,EAAE,QAAQ,CAAC,eAAe,CAAC,+BA+J3B"}
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
- import { Form } from 'react-bootstrap';
4
3
  import { GRAPH_SELECTION_KIND, TREE_SPEC_NODE_TYPE_PRESETS, } from '@signalsafe/tree-spec-editor-core';
5
4
  import PanelHeaderCollapseCarets from '../lib/PanelHeaderCollapseCarets.js';
6
5
  import { LIST_SELECTION_CLASS, LIST_SELECTION_TEXT_CLASS } from '../lib/selectionStyles.js';
6
+ import { EDITOR_CARD, EDITOR_CARD_FOOTER, EDITOR_CARD_HEADER, EDITOR_FLEX_BETWEEN, EDITOR_FLEX_GROW_1, EDITOR_FLEX_ROW, EDITOR_FLEX_SHRINK_0, EDITOR_HIDDEN, EDITOR_LIST, EDITOR_LIST_ITEM, EDITOR_MIN_W_0, EDITOR_MUTED, EDITOR_SCROLL, EDITOR_SPACING_MB_1, EDITOR_SPACING_ME_2, EDITOR_SPACING_MT_3, EDITOR_TEXT_BREAK, EDITOR_TEXT_START, joinClasses, } from '../ui/editorClasses.js';
7
+ import { EditorIconButton, EditorInput, EditorSwitch } from '../ui/primitives.js';
7
8
  const DEFAULT_TIP_TEXT = 'Tip: connect choices by dragging the blue dots. Shortcuts: \u2318S save, \u2318\u21E7V validate, \u2318D duplicate, Del delete.';
8
9
  const TYPE_SORT_ORDER = new Map(TREE_SPEC_NODE_TYPE_PRESETS.map((t, i) => [t, i]));
9
10
  function choiceLine(n) {
@@ -44,11 +45,11 @@ export default function NodesPanel({ tree, nodeSearch, selection, focusNodeId =
44
45
  return hitPrompt || hitId || hitType || hitChoices;
45
46
  })
46
47
  .sort(compareNodesByTypeThenId);
47
- 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: "Nodes" }), _jsx(PanelHeaderCollapseCarets, { expanded: expanded, onToggle: () => setExpanded((v) => !v) })] }), onAddNode ? (_jsx("button", { type: "button", className: "btn p-0 border-0 bg-transparent flex-shrink-0", "aria-label": "Add node", title: "Add node", onClick: onAddNode, children: _jsx("i", { className: "bi bi-plus-lg text-primary action-icon cursor-pointer", "aria-hidden": true }) })) : null] }), _jsxs("div", { className: expanded ? undefined : 'd-none', "aria-hidden": !expanded, children: [_jsx(Form.Control, { className: "rounded-0 border-0 border-bottom shadow-none", placeholder: searchPlaceholder, value: nodeSearch, onChange: (e) => onNodeSearchChange(e.target.value) }), _jsx("div", { className: "overflow-auto-max-h-320", children: filteredNodes.length === 0 ? (_jsx("div", { className: "list-group list-group-flush", children: _jsx("div", { className: "list-group-item text-muted small py-2 px-3", children: "No matching nodes." }) })) : (_jsx("div", { className: "list-group list-group-flush", children: filteredNodes.map((n) => {
48
+ return (_jsxs("div", { className: joinClasses(EDITOR_CARD, EDITOR_SPACING_MT_3), children: [_jsxs("div", { className: joinClasses(EDITOR_CARD_HEADER, EDITOR_FLEX_BETWEEN), children: [_jsxs("div", { className: joinClasses(EDITOR_FLEX_ROW, EDITOR_MIN_W_0), children: [_jsx("span", { className: "graph-editor-text--semibold", children: "Nodes" }), _jsx(PanelHeaderCollapseCarets, { expanded: expanded, onToggle: () => setExpanded((v) => !v) })] }), onAddNode ? (_jsx(EditorIconButton, { className: joinClasses(EDITOR_FLEX_SHRINK_0, 'graph-editor-btn--primary'), "aria-label": "Add node", title: "Add node", onClick: onAddNode, children: "+" })) : null] }), _jsxs("div", { className: !expanded ? EDITOR_HIDDEN : undefined, "aria-hidden": !expanded, children: [_jsx(EditorInput, { className: "graph-editor-input--list-search", placeholder: searchPlaceholder, value: nodeSearch, onChange: (e) => onNodeSearchChange(e.target.value) }), _jsx("div", { className: joinClasses(EDITOR_SCROLL, 'overflow-auto-max-h-320'), children: filteredNodes.length === 0 ? (_jsx("div", { className: EDITOR_LIST, children: _jsx("div", { className: joinClasses(EDITOR_LIST_ITEM, EDITOR_MUTED, 'graph-editor-text--sm'), children: "No matching nodes." }) })) : (_jsx("div", { className: EDITOR_LIST, children: filteredNodes.map((n) => {
48
49
  const isSelected = isNodeRowSelected(n.id, selection, focusNodeId);
49
50
  const typeLabel = n.type || 'unknown';
50
- return (_jsx("div", { className: `list-group-item px-3 py-2${isSelected
51
- ? ` ${LIST_SELECTION_CLASS} ${LIST_SELECTION_TEXT_CLASS}`
52
- : ''}`, "aria-current": isSelected ? 'true' : undefined, children: _jsxs("div", { className: "d-flex w-100 justify-content-between align-items-start gap-2 min-w-0", children: [_jsxs("button", { type: "button", className: "btn p-0 border-0 bg-transparent flex-grow-1 text-start min-w-0", onClick: () => onNodeSelect(n.id), children: [_jsx("div", { className: "d-flex w-100 justify-content-between align-items-center gap-2 mb-1 min-w-0", children: _jsxs("div", { className: "min-w-0 flex-grow-1 text-break text-start", title: `${n.id}, ${typeLabel}`, children: [_jsx("span", { className: `fs-6 fw-semibold text-uppercase${isSelected ? '' : ' text-body-secondary'}`, children: n.id }), _jsx("span", { className: `fs-6 text-uppercase${isSelected ? '' : ' text-body-secondary'}`, children: `, ${typeLabel}` })] }) }), _jsx("p", { className: `mb-1 small text-break${isSelected ? '' : ' text-body-secondary'}`, children: n.prompt || '(empty)' }), _jsx("small", { className: isSelected ? '' : ' text-body-secondary', children: choiceLine(n) })] }), onDeleteNode ? (_jsx("button", { type: "button", className: "btn p-0 border-0 bg-transparent flex-shrink-0", "aria-label": `Delete node ${n.id}`, title: "Delete node", disabled: isPublished, onClick: () => onDeleteNode(n.id), children: _jsx("i", { className: `bi bi-trash action-icon cursor-pointer${isPublished ? ' text-secondary opacity-50' : ' text-danger'}`, "aria-hidden": true }) })) : null] }) }, n.id));
53
- }) })) }), _jsx("div", { className: "card-footer p-2 border-top", children: _jsxs("div", { className: "d-flex justify-content-between align-items-center", children: [_jsx("div", { className: "text-muted font-size-12 text-break min-w-0 flex-grow-1 me-2", children: tipText }), _jsx(Form.Check, { type: "switch", id: "showMiniMapToggle", label: "Mini-map", checked: showMiniMap, onChange: (e) => onShowMiniMapChange(e.target.checked), className: "font-size-12" })] }) })] })] }));
51
+ return (_jsx("div", { className: joinClasses(EDITOR_LIST_ITEM, isSelected && LIST_SELECTION_CLASS, isSelected && LIST_SELECTION_TEXT_CLASS), "aria-current": isSelected ? 'true' : undefined, children: _jsxs("div", { className: joinClasses(EDITOR_FLEX_BETWEEN, EDITOR_MIN_W_0), children: [_jsxs("button", { type: "button", className: joinClasses('graph-editor-list__item-action', EDITOR_FLEX_GROW_1, EDITOR_TEXT_START, EDITOR_MIN_W_0), onClick: () => onNodeSelect(n.id), children: [_jsx("div", { className: joinClasses(EDITOR_FLEX_BETWEEN, EDITOR_SPACING_MB_1, EDITOR_MIN_W_0), children: _jsxs("div", { className: joinClasses(EDITOR_MIN_W_0, EDITOR_FLEX_GROW_1, EDITOR_TEXT_BREAK, EDITOR_TEXT_START), title: `${n.id}, ${typeLabel}`, children: [_jsx("span", { className: joinClasses('graph-editor-text--uppercase', 'graph-editor-text--semibold', !isSelected && EDITOR_MUTED), children: n.id }), _jsx("span", { className: joinClasses('graph-editor-text--uppercase', !isSelected && EDITOR_MUTED), children: `, ${typeLabel}` })] }) }), _jsx("p", { className: joinClasses('graph-editor-text--sm', EDITOR_TEXT_BREAK, EDITOR_SPACING_MB_1, !isSelected && EDITOR_MUTED), children: n.prompt || '(empty)' }), _jsx("small", { className: !isSelected ? EDITOR_MUTED : undefined, children: choiceLine(n) })] }), onDeleteNode ? (_jsx(EditorIconButton, { className: joinClasses(EDITOR_FLEX_SHRINK_0, isPublished
52
+ ? 'graph-editor-btn--disabled'
53
+ : 'graph-editor-btn--danger'), "aria-label": `Delete node ${n.id}`, title: "Delete node", disabled: isPublished, onClick: () => onDeleteNode(n.id), children: "\uD83D\uDDD1" })) : null] }) }, n.id));
54
+ }) })) }), _jsx("div", { className: joinClasses(EDITOR_CARD_FOOTER, 'graph-editor-card__footer--border-top'), children: _jsxs("div", { className: EDITOR_FLEX_BETWEEN, children: [_jsx("div", { className: joinClasses(EDITOR_MUTED, 'graph-editor-text--sm', EDITOR_TEXT_BREAK, EDITOR_MIN_W_0, EDITOR_FLEX_GROW_1, EDITOR_SPACING_ME_2), children: tipText }), _jsx(EditorSwitch, { id: "showMiniMapToggle", label: "Mini-map", checked: showMiniMap, onChange: (e) => onShowMiniMapChange(e.target.checked), className: "graph-editor-text--sm" })] }) })] })] }));
54
55
  }
@@ -1 +1 @@
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
+ {"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,yBAAyB,CAAC;AASjG,MAAM,MAAM,0BAA0B,GAAG,oBAAoB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,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,8 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { renderDefaultEdgeBreadcrumb } from '../lib/panelNodeLink.js';
3
+ import { EDITOR_CARD, EDITOR_CARD_BODY, EDITOR_MUTED, EDITOR_SPACING_MT_3, joinClasses, } from '../ui/editorClasses.js';
3
4
  export { PanelNodeLink } from '../lib/panelNodeLink.js';
4
5
  export default function SelectedEdgePanel({ selectedEdge, onNodeSelect, title = 'Selected Edge', renderDetails = renderDefaultEdgeBreadcrumb, }) {
5
6
  if (!selectedEdge)
6
7
  return null;
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 }) })] }) }));
8
+ return (_jsx("div", { className: joinClasses(EDITOR_CARD, EDITOR_SPACING_MT_3), children: _jsxs("div", { className: EDITOR_CARD_BODY, children: [_jsx("div", { className: "graph-editor-text--bold", children: title }), _jsx("div", { className: joinClasses(EDITOR_MUTED, 'graph-editor-text--sm'), children: renderDetails(selectedEdge, { onNodeSelect }) })] }) }));
8
9
  }
@@ -1,15 +1,3 @@
1
- /**
2
- * Data-driven toolbar for the TreeSpec graph editor (and similar editor pages).
3
- *
4
- * Hosts pass an array of `ToolbarItem`s describing the visual elements they want in
5
- * the toolbar — buttons, dropdowns, badges, plain text, or arbitrary custom render
6
- * functions. The package owns layout (wrap, gap, alignment) and Bootstrap chrome;
7
- * the host owns every label, disabled rule, adapter-gated visibility, and callback
8
- * (encoded as closures inside each item).
9
- *
10
- * The `custom` item kind exists for one-offs like router-aware links — that way
11
- * the package stays free of `react-router` (or any other) routing concerns.
12
- */
13
1
  import { type ReactNode } from 'react';
14
2
  /**
15
3
  * Discriminator values used by the `kind` field on every {@link ToolbarItem}.
@@ -31,7 +19,7 @@ export interface ToolbarButtonItem {
31
19
  id?: string;
32
20
  label: ReactNode;
33
21
  onClick: () => void;
34
- /** Bootstrap variant. Default: `"outline-secondary"`. */
22
+ /** Visual tone hook (e.g. `neutral`, `success`, `primary`). Default: `neutral`. Legacy Bootstrap variant strings are mapped. */
35
23
  variant?: string;
36
24
  disabled?: boolean;
37
25
  title?: string;
@@ -44,7 +32,7 @@ export interface ToolbarDropdownEntry {
44
32
  label: ReactNode;
45
33
  onClick?: () => void;
46
34
  disabled?: boolean;
47
- /** When true, render a `<Dropdown.Divider />` and ignore label/onClick. */
35
+ /** When true, render a menu divider and ignore label/onClick. */
48
36
  divider?: boolean;
49
37
  }
50
38
  export interface ToolbarDropdownItem {
@@ -52,7 +40,7 @@ export interface ToolbarDropdownItem {
52
40
  id?: string;
53
41
  label: ReactNode;
54
42
  entries: ToolbarDropdownEntry[];
55
- /** Bootstrap variant for the toggle. Default: `"outline-secondary"`. */
43
+ /** Toggle tone hook. Default: `neutral`. Legacy Bootstrap variant strings are mapped. */
56
44
  variant?: string;
57
45
  disabled?: boolean;
58
46
  className?: string;
@@ -61,7 +49,7 @@ export interface ToolbarBadgeItem {
61
49
  kind: typeof TOOLBAR_ITEM_KIND.BADGE;
62
50
  id?: string;
63
51
  label: ReactNode;
64
- /** Bootstrap badge variant (e.g. `"success"`, `"secondary"`). Default: `"secondary"`. */
52
+ /** Badge tone hook (e.g. `success`, `neutral`). Default: `neutral`. */
65
53
  variant?: string;
66
54
  className?: string;
67
55
  }
@@ -69,7 +57,7 @@ export interface ToolbarTextItem {
69
57
  kind: typeof TOOLBAR_ITEM_KIND.TEXT;
70
58
  id?: string;
71
59
  content: ReactNode;
72
- /** Override the default `"ms-2 text-muted font-size-12"` styling. */
60
+ /** Override default muted toolbar text styling. */
73
61
  className?: string;
74
62
  }
75
63
  export interface ToolbarCustomItem {
@@ -81,7 +69,7 @@ export interface ToolbarCustomItem {
81
69
  export type ToolbarItem = ToolbarButtonItem | ToolbarDropdownItem | ToolbarBadgeItem | ToolbarTextItem | ToolbarCustomItem;
82
70
  export interface ToolbarPanelProps {
83
71
  items: ToolbarItem[];
84
- /** Override the outer wrapper className. Default: `"d-flex gap-2 align-items-center flex-wrap"`. */
72
+ /** Override the outer wrapper className. */
85
73
  className?: string;
86
74
  }
87
75
  export default function ToolbarPanel({ items, className, }: Readonly<ToolbarPanelProps>): import("react").JSX.Element;
@@ -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;AAuED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACjC,KAAK,EACL,SAAiC,GACpC,EAAE,QAAQ,CAAC,iBAAiB,CAAC,+BAQ7B"}
1
+ {"version":3,"file":"ToolbarPanel.d.ts","sourceRoot":"","sources":["../../src/panels/ToolbarPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAcjD;;;;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,gIAAgI;IAChI,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,iEAAiE;IACjE,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,yFAAyF;IACzF,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,uEAAuE;IACvE,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,mDAAmD;IACnD,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,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAwED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACjC,KAAK,EACL,SAAiD,GACpD,EAAE,QAAQ,CAAC,iBAAiB,CAAC,+BAQ7B"}
@@ -1,18 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * Data-driven toolbar for the TreeSpec graph editor (and similar editor pages).
4
- *
5
- * Hosts pass an array of `ToolbarItem`s describing the visual elements they want in
6
- * the toolbar — buttons, dropdowns, badges, plain text, or arbitrary custom render
7
- * functions. The package owns layout (wrap, gap, alignment) and Bootstrap chrome;
8
- * the host owns every label, disabled rule, adapter-gated visibility, and callback
9
- * (encoded as closures inside each item).
10
- *
11
- * The `custom` item kind exists for one-offs like router-aware links — that way
12
- * the package stays free of `react-router` (or any other) routing concerns.
13
- */
14
2
  import { Fragment } from 'react';
15
- import { Button, Dropdown } from 'react-bootstrap';
3
+ import { EDITOR_DROPDOWN, EDITOR_DROPDOWN_DIVIDER, EDITOR_DROPDOWN_ITEM, EDITOR_DROPDOWN_MENU, EDITOR_FLEX, EDITOR_MUTED, editorBadgeToneClass, editorBtnToneClass, joinClasses, } from '../ui/editorClasses.js';
16
4
  /**
17
5
  * Discriminator values used by the `kind` field on every {@link ToolbarItem}.
18
6
  * Use these constants instead of bare string literals (e.g.
@@ -25,25 +13,23 @@ export const TOOLBAR_ITEM_KIND = {
25
13
  TEXT: 'text',
26
14
  CUSTOM: 'custom',
27
15
  };
28
- const DEFAULT_BUTTON_VARIANT = 'outline-secondary';
29
- const DEFAULT_DROPDOWN_VARIANT = 'outline-secondary';
30
- const DEFAULT_BADGE_VARIANT = 'secondary';
31
- const DEFAULT_TEXT_CLASS = 'ms-2 text-muted font-size-12';
32
- const DEFAULT_WRAPPER_CLASS = 'd-flex gap-2 align-items-center flex-wrap';
16
+ const DEFAULT_TEXT_CLASS = `${EDITOR_MUTED} graph-editor-toolbar__text`;
33
17
  function renderItem(item) {
34
18
  switch (item.kind) {
35
19
  case TOOLBAR_ITEM_KIND.BUTTON:
36
- return (_jsx(Button, { variant: item.variant ?? DEFAULT_BUTTON_VARIANT, onClick: item.onClick, disabled: item.disabled, title: item.title, className: item.className, children: item.label }));
20
+ return (_jsx("button", { type: "button", className: joinClasses(editorBtnToneClass(item.variant), item.className), onClick: item.onClick, disabled: item.disabled, title: item.title, children: item.label }));
37
21
  case TOOLBAR_ITEM_KIND.DROPDOWN:
38
- return (_jsxs(Dropdown, { className: item.className ?? 'd-inline', children: [_jsx(Dropdown.Toggle, { variant: item.variant ?? DEFAULT_DROPDOWN_VARIANT, disabled: item.disabled, children: item.label }), _jsx(Dropdown.Menu, { children: item.entries.map((entry, idx) => {
22
+ return (_jsxs("details", { className: joinClasses(EDITOR_DROPDOWN, item.className), children: [_jsx("summary", { className: joinClasses(editorBtnToneClass(item.variant), item.disabled && 'graph-editor-btn--disabled'), children: item.label }), _jsx("div", { className: EDITOR_DROPDOWN_MENU, role: "menu", children: item.entries.map((entry, idx) => {
39
23
  const entryKey = entry.id ?? `entry-${idx}`;
40
24
  if (entry.divider) {
41
- return _jsx(Dropdown.Divider, {}, entryKey);
25
+ return _jsx("div", { className: EDITOR_DROPDOWN_DIVIDER, role: "separator" }, entryKey);
42
26
  }
43
- return (_jsx(Dropdown.Item, { onClick: entry.onClick, disabled: entry.disabled, children: entry.label }, entryKey));
27
+ return (_jsx("button", { type: "button", role: "menuitem", className: EDITOR_DROPDOWN_ITEM, onClick: entry.disabled || !entry.onClick
28
+ ? undefined
29
+ : () => entry.onClick(), disabled: entry.disabled, children: entry.label }, entryKey));
44
30
  }) })] }));
45
31
  case TOOLBAR_ITEM_KIND.BADGE:
46
- return (_jsx("span", { className: item.className ?? `badge bg-${item.variant ?? DEFAULT_BADGE_VARIANT}`, children: item.label }));
32
+ return (_jsx("span", { className: item.className ?? editorBadgeToneClass(item.variant), children: item.label }));
47
33
  case TOOLBAR_ITEM_KIND.TEXT:
48
34
  return (_jsx("span", { className: item.className ?? DEFAULT_TEXT_CLASS, children: item.content }));
49
35
  case TOOLBAR_ITEM_KIND.CUSTOM:
@@ -52,6 +38,6 @@ function renderItem(item) {
52
38
  return null;
53
39
  }
54
40
  }
55
- export default function ToolbarPanel({ items, className = DEFAULT_WRAPPER_CLASS, }) {
41
+ export default function ToolbarPanel({ items, className = `${EDITOR_FLEX} graph-editor-toolbar`, }) {
56
42
  return (_jsx("div", { className: className, children: items.map((item, idx) => (_jsx(Fragment, { children: renderItem(item) }, item.id ?? `item-${idx}`))) }));
57
43
  }
@@ -1 +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"}
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;AAEpD,OAAO,EAGH,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,UAAU,EAClB,MAAM,mCAAmC,CAAC;AA0B3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAEjF,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,+BAgKD"}