@signalsafe/tree-spec-editor 0.2.2 → 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.
- package/README.md +132 -33
- package/dist/index.d.ts +39 -41
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -26
- package/dist/lib/PanelHeaderCollapseCarets.d.ts.map +1 -1
- package/dist/lib/PanelHeaderCollapseCarets.js +2 -1
- package/dist/lib/panelHelpers.d.ts +8 -1
- package/dist/lib/panelHelpers.d.ts.map +1 -1
- package/dist/lib/panelHelpers.js +14 -6
- package/dist/lib/panelNodeLink.d.ts.map +1 -1
- package/dist/lib/panelNodeLink.js +2 -1
- package/dist/lib/selectionStyles.d.ts +6 -6
- package/dist/lib/selectionStyles.d.ts.map +1 -1
- package/dist/lib/selectionStyles.js +6 -6
- package/dist/modals/AuditLogModal.d.ts +0 -6
- package/dist/modals/AuditLogModal.d.ts.map +1 -1
- package/dist/modals/AuditLogModal.js +6 -5
- package/dist/modals/DraftHistoryModal.d.ts +0 -10
- package/dist/modals/DraftHistoryModal.d.ts.map +1 -1
- package/dist/modals/DraftHistoryModal.js +6 -5
- package/dist/modals/PublishReviewModal.d.ts.map +1 -1
- package/dist/modals/PublishReviewModal.js +3 -2
- package/dist/panels/AdvancedJsonPanel.d.ts +1 -1
- package/dist/panels/AdvancedJsonPanel.d.ts.map +1 -1
- package/dist/panels/AdvancedJsonPanel.js +4 -4
- package/dist/panels/AppearancePanel.d.ts +1 -1
- package/dist/panels/AppearancePanel.d.ts.map +1 -1
- package/dist/panels/AppearancePanel.js +9 -11
- package/dist/panels/ChoiceEdgeAppearanceFields.d.ts.map +1 -1
- package/dist/panels/ChoiceEdgeAppearanceFields.js +4 -3
- package/dist/panels/ChoiceTemplatesPanel.d.ts.map +1 -1
- package/dist/panels/ChoiceTemplatesPanel.js +4 -3
- package/dist/panels/GraphEditorInfoPanel.d.ts.map +1 -1
- package/dist/panels/GraphEditorInfoPanel.js +6 -5
- package/dist/panels/InspectorPanel.d.ts +2 -2
- package/dist/panels/InspectorPanel.d.ts.map +1 -1
- package/dist/panels/InspectorPanel.js +5 -5
- package/dist/panels/IssuesPanel.d.ts.map +1 -1
- package/dist/panels/IssuesPanel.js +7 -8
- package/dist/panels/NodesPanel.d.ts.map +1 -1
- package/dist/panels/NodesPanel.js +9 -8
- package/dist/panels/SelectedEdgePanel.d.ts +2 -2
- package/dist/panels/SelectedEdgePanel.d.ts.map +1 -1
- package/dist/panels/SelectedEdgePanel.js +4 -3
- package/dist/panels/ToolbarPanel.d.ts +6 -18
- package/dist/panels/ToolbarPanel.d.ts.map +1 -1
- package/dist/panels/ToolbarPanel.js +10 -24
- package/dist/panels/inspector/ChoiceEditorCard.d.ts +1 -1
- package/dist/panels/inspector/ChoiceEditorCard.d.ts.map +1 -1
- package/dist/panels/inspector/ChoiceEditorCard.js +7 -6
- package/dist/panels/inspector/ChoiceEditorList.d.ts +1 -1
- package/dist/panels/inspector/ChoiceEditorList.d.ts.map +1 -1
- package/dist/panels/inspector/ChoiceEditorList.js +5 -3
- package/dist/panels/inspector/NodeTypeField.d.ts.map +1 -1
- package/dist/panels/inspector/NodeTypeField.js +4 -3
- package/dist/panels/inspector/RequiredNodeCard.d.ts +1 -1
- package/dist/panels/inspector/RequiredNodeCard.d.ts.map +1 -1
- package/dist/panels/inspector/RequiredNodeCard.js +5 -4
- package/dist/panels/inspector/choiceActionIconProps.d.ts +3 -2
- package/dist/panels/inspector/choiceActionIconProps.d.ts.map +1 -1
- package/dist/panels/inspector/choiceActionIconProps.js +4 -2
- package/dist/ui/editorClasses.d.ts +66 -0
- package/dist/ui/editorClasses.d.ts.map +1 -0
- package/dist/ui/editorClasses.js +89 -0
- package/dist/ui/primitives.d.ts +23 -0
- package/dist/ui/primitives.d.ts.map +1 -0
- package/dist/ui/primitives.js +32 -0
- package/docs/UI_KIT_AGNOSTIC_REFACTOR.md +186 -0
- package/docs/UI_KIT_AGNOSTIC_USAGE.md +129 -0
- package/package.json +11 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/ui/primitives.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,SAAS,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,OAAO,CAAC;AAcrJ,wBAAgB,YAAY,CAAC,EACzB,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,GAAG,IAAI,EACV,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,+BAM7D;AAED,wBAAgB,gBAAgB,CAAC,EAC7B,SAAS,EACT,QAAQ,EACR,GAAG,IAAI,EACV,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,+BAMzC;AAED,wBAAgB,iBAAiB,CAAC,EAC9B,SAAS,EACT,KAAe,EACf,GAAG,IAAI,EACV,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,+BAW9D;AAED,wBAAgB,WAAW,CAAC,EACxB,SAAS,EACT,GAAG,IAAI,EACV,EAAE,mBAAmB,CAAC,gBAAgB,CAAC,+BAEvC;AAED,wBAAgB,YAAY,CAAC,EACzB,SAAS,EACT,QAAQ,EACR,GAAG,IAAI,EACV,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,+BAMzC;AAED,wBAAgB,cAAc,CAAC,EAC3B,SAAS,EACT,GAAG,IAAI,EACV,EAAE,sBAAsB,CAAC,mBAAmB,CAAC,+BAE7C;AAED,wBAAgB,WAAW,CAAC,EACxB,SAAS,EACT,QAAQ,GACX,EAAE;IACC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACvB,+BAEA;AAED,wBAAgB,WAAW,CAAC,EACxB,SAAS,EACT,QAAQ,EACR,GAAG,IAAI,EACV,EAAE,mBAAmB,CAAC,gBAAgB,CAAC,+BAMvC;AAED,wBAAgB,cAAc,CAAC,EAC3B,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACV,EAAE,mBAAmB,CAAC,gBAAgB,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,+BAO/D;AAED,wBAAgB,YAAY,CAAC,EACzB,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACV,EAAE,mBAAmB,CAAC,gBAAgB,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,+BAO/D"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { EDITOR_BTN, EDITOR_CHECKBOX, EDITOR_FIELD, EDITOR_FIELD_LABEL, EDITOR_INPUT, EDITOR_SELECT, EDITOR_TEXTAREA, editorBtnToneClass, joinClasses, } from './editorClasses.js';
|
|
3
|
+
export function EditorButton({ tone, className, children, ...rest }) {
|
|
4
|
+
return (_jsx("button", { type: "button", className: joinClasses(editorBtnToneClass(tone), className), ...rest, children: children }));
|
|
5
|
+
}
|
|
6
|
+
export function EditorIconButton({ className, children, ...rest }) {
|
|
7
|
+
return (_jsx("button", { type: "button", className: joinClasses(`${EDITOR_BTN} graph-editor-btn--icon`, className), ...rest, children: children }));
|
|
8
|
+
}
|
|
9
|
+
export function EditorCloseButton({ className, label = 'Close', ...rest }) {
|
|
10
|
+
return (_jsx("button", { type: "button", className: joinClasses(`${EDITOR_BTN} graph-editor-btn--close`, className), "aria-label": label, ...rest, children: "\u00D7" }));
|
|
11
|
+
}
|
|
12
|
+
export function EditorInput({ className, ...rest }) {
|
|
13
|
+
return _jsx("input", { className: joinClasses(EDITOR_INPUT, className), ...rest });
|
|
14
|
+
}
|
|
15
|
+
export function EditorSelect({ className, children, ...rest }) {
|
|
16
|
+
return (_jsx("select", { className: joinClasses(EDITOR_SELECT, className), ...rest, children: children }));
|
|
17
|
+
}
|
|
18
|
+
export function EditorTextarea({ className, ...rest }) {
|
|
19
|
+
return _jsx("textarea", { className: joinClasses(EDITOR_TEXTAREA, className), ...rest });
|
|
20
|
+
}
|
|
21
|
+
export function EditorField({ className, children, }) {
|
|
22
|
+
return _jsx("div", { className: joinClasses(EDITOR_FIELD, className), children: children });
|
|
23
|
+
}
|
|
24
|
+
export function EditorLabel({ className, children, ...rest }) {
|
|
25
|
+
return (_jsx("label", { className: joinClasses(EDITOR_FIELD_LABEL, className), ...rest, children: children }));
|
|
26
|
+
}
|
|
27
|
+
export function EditorCheckbox({ className, label, ...rest }) {
|
|
28
|
+
return (_jsxs("label", { className: joinClasses(EDITOR_CHECKBOX, className), children: [_jsx("input", { type: "checkbox", ...rest }), label ? _jsx("span", { children: label }) : null] }));
|
|
29
|
+
}
|
|
30
|
+
export function EditorSwitch({ className, label, ...rest }) {
|
|
31
|
+
return (_jsxs("label", { className: joinClasses(`${EDITOR_CHECKBOX} graph-editor-checkbox--switch`, className), children: [_jsx("input", { type: "checkbox", role: "switch", ...rest }), label ? _jsx("span", { children: label }) : null] }));
|
|
32
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# UI-kit agnostic editor refactor — design scan (Prompt 8)
|
|
2
|
+
|
|
3
|
+
**Status:** Implemented on `cleanup` (Prompts 9–10, 9A). `@signalsafe/tree-spec-editor@0.3.0` and `@signalsafe/tree-spec-editor-react@0.2.0` are UI-kit agnostic. See [UI_KIT_AGNOSTIC_USAGE.md](./UI_KIT_AGNOSTIC_USAGE.md) and [`tree-spec-editor-react` canvas doc](../../tree-spec-editor-react/docs/UI_KIT_AGNOSTIC_CANVAS.md).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Executive summary (historical — Prompt 8 scan)
|
|
8
|
+
|
|
9
|
+
| Package | react-bootstrap | Bootstrap CSS classes | Ready for UI-kit agnostic goal |
|
|
10
|
+
|---------|-----------------|----------------------|--------------------------------|
|
|
11
|
+
| `tree-spec-editor-core` | None | None | **Yes** — already meets boundary |
|
|
12
|
+
| `tree-spec-editor-react` | None | **None (0.2.0+)** | **Yes** — canvas uses `graph-editor-*` hooks |
|
|
13
|
+
| `tree-spec-editor` | ~~**Yes** — 13 source files~~ → **None (0.3.0+)** | ~~**Yes**~~ → **`graph-editor-*` hooks** | **Yes** — shell refactor complete |
|
|
14
|
+
|
|
15
|
+
**Likely semver:** `@signalsafe/tree-spec-editor` **0.3.0** (remove `react-bootstrap` peer; public panel/modal API and styling contract change). `@signalsafe/tree-spec-editor-react` **0.2.0** (canvas class renames / neutral tokens). `@signalsafe/tree-spec-editor-core` **patch or unchanged**.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Search inventory (Prompt 8 task list)
|
|
20
|
+
|
|
21
|
+
### `tree-spec-editor`
|
|
22
|
+
|
|
23
|
+
| Category | Matches |
|
|
24
|
+
|----------|---------|
|
|
25
|
+
| **Runtime `react-bootstrap` imports** | 13 files under `src/` (see table below) |
|
|
26
|
+
| **Bootstrap CSS only (no import)** | Modals (`<dialog>` + `modal-*`, `alert-*`), all sidebar panels (`card-*`, `list-group-*`, `btn-*`), `panelNodeLink.tsx`, `PanelHeaderCollapseCarets.tsx` |
|
|
27
|
+
| **Public exports (Bootstrap-coupled)** | All panel/modal components; `ToolbarPanel`; `getIssueSeverityBadgeClass`; `LIST_*` / `CANVAS_*` selection class constants; `buildDefaultToolbarSpec` (variant strings) |
|
|
28
|
+
| **Package metadata** | `peerDependencies.react-bootstrap`, keyword `react-bootstrap`, README install line includes `react-bootstrap bootstrap` |
|
|
29
|
+
| **Tests** | `ToolbarPanel.test.ts` mocks `react-bootstrap`; `panelHelpers.test.ts` asserts `text-bg-*`; `NodesPanel` / `IssuesPanel` assert `list-group-item-primary` |
|
|
30
|
+
| **Docs** | README positions package as “React **Bootstrap UI shell**” (throughout) |
|
|
31
|
+
| **Not used** | `Tabs`, `Accordion`, `Overlay`, `Popover`, `Toast`, `react-bootstrap` `Modal` (native `<dialog>` + Bootstrap classes instead) |
|
|
32
|
+
|
|
33
|
+
**Runtime `react-bootstrap` import sites:**
|
|
34
|
+
|
|
35
|
+
| File | Components imported |
|
|
36
|
+
|------|---------------------|
|
|
37
|
+
| `src/modals/DraftHistoryModal.tsx` | `Button`, `CloseButton` |
|
|
38
|
+
| `src/modals/AuditLogModal.tsx` | `Button`, `CloseButton` |
|
|
39
|
+
| `src/modals/PublishReviewModal.tsx` | `Button`, `CloseButton` |
|
|
40
|
+
| `src/panels/GraphEditorInfoPanel.tsx` | `Badge`, `Form`, `Table` |
|
|
41
|
+
| `src/panels/AdvancedJsonPanel.tsx` | `Button` |
|
|
42
|
+
| `src/panels/IssuesPanel.tsx` | `Form` |
|
|
43
|
+
| `src/panels/NodesPanel.tsx` | `Form` |
|
|
44
|
+
| `src/panels/ChoiceEdgeAppearanceFields.tsx` | `Form` |
|
|
45
|
+
| `src/panels/inspector/ChoiceEditorCard.tsx` | `Form` |
|
|
46
|
+
| `src/panels/inspector/NodeTypeField.tsx` | `Form` |
|
|
47
|
+
| `src/panels/inspector/RequiredNodeCard.tsx` | `Form` |
|
|
48
|
+
| `src/panels/ToolbarPanel.tsx` | `Button`, `Dropdown` |
|
|
49
|
+
| `src/panels/ChoiceTemplatesPanel.tsx` | `Button`, `Card` |
|
|
50
|
+
|
|
51
|
+
**Public API — types mentioning Bootstrap:**
|
|
52
|
+
|
|
53
|
+
- `ToolbarButtonItem.variant`, `ToolbarDropdownItem.variant`, `ToolbarBadgeItem.variant` — documented as Bootstrap variant strings.
|
|
54
|
+
- `PublishReviewModalProps.errorAlertText` — uses Bootstrap `alert-danger` markup (prop name only; rendering is Bootstrap CSS).
|
|
55
|
+
|
|
56
|
+
### `tree-spec-editor-react`
|
|
57
|
+
|
|
58
|
+
| Category | Matches |
|
|
59
|
+
|----------|---------|
|
|
60
|
+
| **react-bootstrap** | **None** (docs/comments only) |
|
|
61
|
+
| **Bootstrap CSS in runtime** | 9 files: `PromptNode.tsx`, `PromptNodeHeader.tsx`, `PromptNodeChoicesList.tsx`, `PromptNodeIssueBadges.tsx`, `PromptNodeToolbar.tsx`, `ChoiceCanvasRow.tsx`, `EndNode.tsx`, `GraphCanvasContextMenu.tsx`, `canvas/constants.ts` (`dropdown-menu`, `card-*`, `badge`, `btn-*`, `list-group-*`, `bg-body-secondary`) |
|
|
62
|
+
| **False positives** | `useTreeSpecEditor` “bootstrap graph” comments (data bootstrap, not UI) |
|
|
63
|
+
| **Public API** | `TreeSpecGraphEditorProps.colorScheme` doc mentions Bootstrap `colorScheme` — host contract leak |
|
|
64
|
+
|
|
65
|
+
### `tree-spec-editor-core`
|
|
66
|
+
|
|
67
|
+
| Category | Matches |
|
|
68
|
+
|----------|---------|
|
|
69
|
+
| **All matches** | README / `index.ts` comments stating “no Bootstrap” — **docs only** |
|
|
70
|
+
| **Runtime** | **Clean** |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Current vs target boundaries
|
|
75
|
+
|
|
76
|
+
### Target (ecosystem policy)
|
|
77
|
+
|
|
78
|
+
1. **`tree-spec-editor-core`** — pure logic, no React/DOM/Bootstrap. **Already there.**
|
|
79
|
+
2. **`tree-spec-editor-react`** — React Flow + hooks; **no Bootstrap/MUI**; neutral canvas markup.
|
|
80
|
+
3. **`tree-spec-editor`** — UI-kit agnostic composition (hooks, primitives, render props); **must not** require `react-bootstrap` or Bootstrap CSS.
|
|
81
|
+
|
|
82
|
+
### Optional future package
|
|
83
|
+
|
|
84
|
+
`@signalsafe/tree-spec-editor-bootstrap` — migrate **today’s** panel/modal/toolbar implementations here for hosts that want the reference Bootstrap shell (including DeliveryPlus during transition).
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Refactor strategy (recommended phases)
|
|
89
|
+
|
|
90
|
+
### Phase 0 — No behavior change (prep)
|
|
91
|
+
|
|
92
|
+
- Add this design doc; align DeliveryPlus on timeline.
|
|
93
|
+
- Snapshot README/API contract before refactors.
|
|
94
|
+
|
|
95
|
+
### Phase 1 — `tree-spec-editor-react` neutral canvas
|
|
96
|
+
|
|
97
|
+
- Replace Bootstrap class names in node/context-menu components with **`graph-editor-*`** semantic classes.
|
|
98
|
+
- Ship minimal package CSS (or document host-provided tokens) mapping semantic classes → host theme.
|
|
99
|
+
- Change `CONTEXT_MENU_CLASS` off `dropdown-menu` to neutral menu classes.
|
|
100
|
+
- Update tests in `-react` that assert Bootstrap class strings.
|
|
101
|
+
- **semver:** minor (`0.2.0`).
|
|
102
|
+
|
|
103
|
+
### Phase 2 — Headless shell API in `tree-spec-editor`
|
|
104
|
+
|
|
105
|
+
Introduce UI-kit agnostic layer **alongside** existing components (deprecate, then remove):
|
|
106
|
+
|
|
107
|
+
| Pattern | Use for |
|
|
108
|
+
|---------|---------|
|
|
109
|
+
| **Hooks** | Re-export / wrap `useTreeSpecEditor` with panel-state helpers (`useInspectorState`, `useToolbarActions`) |
|
|
110
|
+
| **Primitives** | Unstyled structural components: `EditorSidebarSection`, `EditorModalFrame`, `EditorListRow` — semantics + ARIA only |
|
|
111
|
+
| **Render props / slots** | `InspectorPanel` already has `renderExtraNodeFields` / `renderExtraChoiceFields` — extend to **all** chrome (buttons, badges, inputs) |
|
|
112
|
+
| **Data-only helpers** | Replace `getIssueSeverityBadgeClass` with `getIssueSeverityToken()` → `'error' \| 'warning' \| 'info'`; hosts map to UI |
|
|
113
|
+
| **Selection tokens** | Replace exported `LIST_SELECTION_CLASS` Bootstrap strings with stable token constants |
|
|
114
|
+
|
|
115
|
+
Remove from **`tree-spec-editor` public API** (breaking):
|
|
116
|
+
|
|
117
|
+
- Direct export of Bootstrap-backed panels/modals **or** move them to `@signalsafe/tree-spec-editor-bootstrap`.
|
|
118
|
+
|
|
119
|
+
### Phase 3 — Optional `@signalsafe/tree-spec-editor-bootstrap`
|
|
120
|
+
|
|
121
|
+
- Move current `src/panels/`, `src/modals/`, Bootstrap `ToolbarPanel` implementation verbatim.
|
|
122
|
+
- Keep peer deps: `react-bootstrap`, `bootstrap` (CSS loaded by host).
|
|
123
|
+
- `tree-spec-editor` re-exports bootstrap package temporarily with deprecation notice.
|
|
124
|
+
|
|
125
|
+
### Phase 4 — Docs & metadata
|
|
126
|
+
|
|
127
|
+
- Remove `react-bootstrap` from `peerDependencies` and keywords on `@signalsafe/tree-spec-editor`.
|
|
128
|
+
- README: primary path = hooks + render props; Bootstrap = optional add-on package.
|
|
129
|
+
- **semver:** `@signalsafe/tree-spec-editor` **0.3.0**.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## DeliveryPlus migration impact
|
|
134
|
+
|
|
135
|
+
**Today (inferred from package docs):**
|
|
136
|
+
|
|
137
|
+
- Installs `@signalsafe/tree-spec-editor` + peers including **`react-bootstrap`** and **Bootstrap CSS**.
|
|
138
|
+
- Uses exported panels, modals, toolbar, and canvas default export from one barrel.
|
|
139
|
+
|
|
140
|
+
**After refactor:**
|
|
141
|
+
|
|
142
|
+
- **Short term:** Pin `@signalsafe/tree-spec-editor-bootstrap` (or pre-0.3.0 line) until DeliveryPlus rebuilds shell with its UI library.
|
|
143
|
+
- **Target:** Depend on `@signalsafe/tree-spec-editor-react` + `@signalsafe/tree-spec-editor-core` + **DeliveryPlus-owned** panel/modal components using render props / hooks.
|
|
144
|
+
- **CSS:** Must load neutral `graph-editor-*` styles from `-react` (or map tokens in DeliveryPlus theme) — no implicit Bootstrap on canvas.
|
|
145
|
+
|
|
146
|
+
**Do not modify DeliveryPlus in this prompt.**
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Risks
|
|
151
|
+
|
|
152
|
+
| Risk | Mitigation |
|
|
153
|
+
|------|------------|
|
|
154
|
+
| Breaking visual parity | Optional bootstrap package; screenshot tests in bootstrap package only |
|
|
155
|
+
| Class-based tests fail | Update tests to assert semantic tokens / `graph-editor-*` classes |
|
|
156
|
+
| Hidden Bootstrap in `-react` | Phase 1 before removing bootstrap from shell |
|
|
157
|
+
| Toolbar `variant` strings | Replace with theme-agnostic `tone: 'primary' \| 'neutral' \| 'danger'` |
|
|
158
|
+
| Modal `<dialog>` + Bootstrap layout | `EditorModalFrame` primitive with slot for actions |
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Tests needed (implementation prompts)
|
|
163
|
+
|
|
164
|
+
- [ ] `-react`: canvas renders without Bootstrap CSS loaded (layout smoke).
|
|
165
|
+
- [ ] `-react`: context menu keyboard/a11y with neutral classes.
|
|
166
|
+
- [ ] `tree-spec-editor`: hook + render-prop contract tests (no `react-bootstrap` import in package).
|
|
167
|
+
- [ ] `tree-spec-editor-bootstrap`: port existing panel/modal vitest suite.
|
|
168
|
+
- [ ] Cross-package: `buildDefaultToolbarSpec` works with agnostic toolbar renderer.
|
|
169
|
+
- [ ] DeliveryPlus integration checklist (manual).
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Recommended action summary
|
|
174
|
+
|
|
175
|
+
| Repo | Action |
|
|
176
|
+
|------|--------|
|
|
177
|
+
| `tree-spec-editor-core` | **None** — maintain boundary |
|
|
178
|
+
| `tree-spec-editor-react` | **Phase 1 ✓** — Bootstrap CSS removed from canvas (`0.2.0`) |
|
|
179
|
+
| `tree-spec-editor` | **Phase 2–4** — headless API + optional bootstrap split; **0.3.0** |
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## References
|
|
184
|
+
|
|
185
|
+
- Ecosystem boundaries: `prompts/summary.md` (Option A — UI-kit agnostic editor)
|
|
186
|
+
- npm packages (release-ready on `cleanup`, not yet published): `@signalsafe/tree-spec-editor@0.3.0`, `@signalsafe/tree-spec-editor-react@0.2.0`, `@signalsafe/tree-spec-editor-core@0.1.3`
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# UI-kit agnostic editor — usage and migration
|
|
2
|
+
|
|
3
|
+
**Package:** `@signalsafe/tree-spec-editor`
|
|
4
|
+
**Status:** Implemented (0.3.0+)
|
|
5
|
+
**Related:** [UI_KIT_AGNOSTIC_REFACTOR.md](./UI_KIT_AGNOSTIC_REFACTOR.md) (design scan)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
`@signalsafe/tree-spec-editor` ships **composable React panels, modals, and toolbar** with semantic HTML and stable **`graph-editor-*` class hooks**. It does **not** require Bootstrap, Material UI, or any other UI library.
|
|
12
|
+
|
|
13
|
+
**The host application owns styling.** Map `graph-editor-*` classes to your design system, or load optional host CSS (Bootstrap, MUI, Tailwind, etc.).
|
|
14
|
+
|
|
15
|
+
Peer dependencies: `react`, `react-dom`, `reactflow` only.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Architecture
|
|
20
|
+
|
|
21
|
+
| Layer | Package | UI library |
|
|
22
|
+
|-------|---------|------------|
|
|
23
|
+
| Wire | `@signalsafe/tree-spec` | None |
|
|
24
|
+
| Model | `@signalsafe/tree-spec-editor-core` | None |
|
|
25
|
+
| Canvas | `@signalsafe/tree-spec-editor-react` | None (React Flow only; canvas emits `graph-editor-*` hooks — see [`UI_KIT_AGNOSTIC_CANVAS.md`](../../tree-spec-editor-react/docs/UI_KIT_AGNOSTIC_CANVAS.md)) |
|
|
26
|
+
| Shell | `@signalsafe/tree-spec-editor` | **Host-owned** — semantic hooks only |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Class hooks (`graph-editor-*`)
|
|
31
|
+
|
|
32
|
+
Panels, modals, and toolbar emit predictable class names from `src/ui/editorClasses.ts`:
|
|
33
|
+
|
|
34
|
+
| Token | Example classes | Used for |
|
|
35
|
+
|-------|-----------------|----------|
|
|
36
|
+
| Card chrome | `graph-editor-card`, `graph-editor-card__header`, `graph-editor-card__body` | Sidebar panels |
|
|
37
|
+
| Lists | `graph-editor-list`, `graph-editor-list__item`, `graph-editor-list__item--selected` | Nodes / Issues rows |
|
|
38
|
+
| Buttons | `graph-editor-btn`, `graph-editor-btn--neutral`, `graph-editor-btn--success` | Toolbar, modals, inspector |
|
|
39
|
+
| Badges | `graph-editor-badge`, `graph-editor-badge--error` | Severity, toolbar status |
|
|
40
|
+
| Modals | `graph-editor-modal`, `graph-editor-modal__dialog`, `graph-editor-alert--danger` | Publish / draft / audit dialogs |
|
|
41
|
+
| Forms | `graph-editor-input`, `graph-editor-select`, `graph-editor-field` | Inspector fields |
|
|
42
|
+
| Toolbar | `graph-editor-toolbar`, `graph-editor-dropdown__menu` | `ToolbarPanel` |
|
|
43
|
+
|
|
44
|
+
**Tone mapping:** `ToolbarPanel` and `EditorButton` accept legacy Bootstrap `variant` strings (`outline-secondary`, `success`, …). They are mapped to tone hooks (`neutral`, `success`, …) via `normalizeToolbarTone()` — you may pass either style during migration.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Primitives (internal building blocks)
|
|
49
|
+
|
|
50
|
+
The package uses small presentational components in `src/ui/primitives.tsx`. They are **not** re-exported from the public barrel today; hosts typically style via `graph-editor-*` CSS. Maintainers and fork authors may import them from source when composing custom panels:
|
|
51
|
+
|
|
52
|
+
| Primitive | Role |
|
|
53
|
+
|-----------|------|
|
|
54
|
+
| `EditorButton` | `<button>` with `tone` → `graph-editor-btn--*` |
|
|
55
|
+
| `EditorIconButton` / `EditorCloseButton` | Icon and modal close controls |
|
|
56
|
+
| `EditorInput`, `EditorSelect`, `EditorTextarea` | Form controls |
|
|
57
|
+
| `EditorField`, `EditorLabel`, `EditorCheckbox`, `EditorSwitch` | Field layout |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Render props and extension slots
|
|
62
|
+
|
|
63
|
+
Several panels accept host injection without replacing the whole component:
|
|
64
|
+
|
|
65
|
+
### `InspectorPanel`
|
|
66
|
+
|
|
67
|
+
| Prop | Purpose |
|
|
68
|
+
|------|---------|
|
|
69
|
+
| `renderExtraNodeFields(ctx)` | Extra UI below the prompt textarea |
|
|
70
|
+
| `renderExtraChoiceFields(ctx)` | Extra UI per choice card |
|
|
71
|
+
| `outcomeOptions` | Override END-transition `<select>` options |
|
|
72
|
+
| `hideOutcomeField` | Hide outcome field when host manages outcomes elsewhere |
|
|
73
|
+
| `choiceTypes` / `onSetChoiceType` | Host-defined choice type catalog |
|
|
74
|
+
|
|
75
|
+
### `AppearancePanel`
|
|
76
|
+
|
|
77
|
+
| Prop | Purpose |
|
|
78
|
+
|------|---------|
|
|
79
|
+
| `renderAppearanceFields(ctx)` | Replace default node/edge appearance fields |
|
|
80
|
+
|
|
81
|
+
### `SelectedEdgePanel`
|
|
82
|
+
|
|
83
|
+
| Prop | Purpose |
|
|
84
|
+
|------|---------|
|
|
85
|
+
| `renderDetails(edge, ctx)` | Custom edge summary line |
|
|
86
|
+
|
|
87
|
+
### `ToolbarPanel`
|
|
88
|
+
|
|
89
|
+
| Item kind | Purpose |
|
|
90
|
+
|-----------|---------|
|
|
91
|
+
| `kind: 'custom'` | `render: () => ReactNode` for router links, host widgets |
|
|
92
|
+
|
|
93
|
+
### `buildDefaultToolbarSpec`
|
|
94
|
+
|
|
95
|
+
Returns a `ToolbarItem[]` for the standard authoring actions. Host closures own capability gates and labels; `ToolbarPanel` renders them with semantic classes.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Helpers (public API)
|
|
100
|
+
|
|
101
|
+
| Export | Before (≤0.2.x) | After (0.3.0+) |
|
|
102
|
+
|--------|-----------------|----------------|
|
|
103
|
+
| `getIssueSeverityBadgeClass(severity)` | `text-bg-danger`, … | `graph-editor-badge graph-editor-badge--error`, … |
|
|
104
|
+
| `getIssueSeverityToken(severity)` | *(not exported)* | `'error' \| 'warning' \| 'info' \| 'neutral'` |
|
|
105
|
+
| `LIST_SELECTION_CLASS` | `list-group-item-primary` | `graph-editor-list__item--selected` |
|
|
106
|
+
| `CANVAS_SELECTION_CLASS` | Bootstrap canvas class | `graph-editor-canvas__selected` |
|
|
107
|
+
|
|
108
|
+
Prefer **`getIssueSeverityToken`** when mapping to MUI/Bootstrap/theme tokens in host code.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## DeliveryPlus migration (guidance only)
|
|
113
|
+
|
|
114
|
+
**Do not change DeliveryPlus in editor package work.** When DeliveryPlus upgrades to `@signalsafe/tree-spec-editor@0.3.0`:
|
|
115
|
+
|
|
116
|
+
1. **Remove** `react-bootstrap` as a required peer for this package (keep it only if DeliveryPlus still uses Bootstrap elsewhere).
|
|
117
|
+
2. **Add CSS** mapping `graph-editor-*` → DeliveryPlus/Bootstrap theme, **or** ship a small `graph-editor.css` in the host app.
|
|
118
|
+
3. **Update tests** that assert `text-bg-*`, `list-group-item-primary`, or `btn-*` on panel output — assert `graph-editor-*` instead.
|
|
119
|
+
4. **Toolbar variants** — existing `outline-secondary` / `success` strings still work via tone mapping.
|
|
120
|
+
5. **Optional short-term pin** — stay on `0.2.x` until host CSS is ready; then bump to `0.3.0`.
|
|
121
|
+
6. **Future (optional)** — `@signalsafe/tree-spec-editor-bootstrap` may provide a reference Bootstrap skin without coupling the core package.
|
|
122
|
+
|
|
123
|
+
**Canvas (`@signalsafe/tree-spec-editor-react@0.2.0`):** uses the same `graph-editor-*` prefix for node cards, lists, badges, and context menus. Map canvas hooks in host CSS alongside panel hooks.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Semver
|
|
128
|
+
|
|
129
|
+
**0.3.0** — removes `react-bootstrap` peer dependency; changes styling class contract and adds `getIssueSeverityToken`. Component prop names and export surface are largely unchanged; visual parity requires host CSS updates.
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signalsafe/tree-spec-editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "UI-kit agnostic TreeSpec graph editor shell (React Flow canvas, panels, modals, toolbar).",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
"editor",
|
|
19
19
|
"graph-editor",
|
|
20
20
|
"decision-tree",
|
|
21
|
-
"react-bootstrap",
|
|
22
21
|
"typescript",
|
|
23
22
|
"signalsafe"
|
|
24
23
|
],
|
|
@@ -39,13 +38,15 @@
|
|
|
39
38
|
"LICENSE"
|
|
40
39
|
],
|
|
41
40
|
"engines": {
|
|
42
|
-
"node": ">=
|
|
41
|
+
"node": ">=22.12.0"
|
|
43
42
|
},
|
|
43
|
+
"packageManager": "yarn@1.22.22",
|
|
44
44
|
"publishConfig": {
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "tsc -p tsconfig.build.json",
|
|
49
|
+
"lint": "yarn typecheck",
|
|
49
50
|
"typecheck": "tsc --noEmit",
|
|
50
51
|
"pack:local": "npm pack --pack-destination ../../dist/reusable-npm",
|
|
51
52
|
"release:check": "node ../../scripts/run-private-package-release-checks.mjs --mode prepublish",
|
|
@@ -56,19 +57,20 @@
|
|
|
56
57
|
"pack:check": "node ../../scripts/check-package-tarball.mjs --tgz \"../../dist/reusable-npm/signalsafe-tree-spec-editor-$npm_package_version.tgz\" --expect package/dist/index.js --expect package/dist/index.d.ts --expect package/package.json --expect package/README.md",
|
|
57
58
|
"smoke:external": "node ../../scripts/smoke-tree-spec-editor-external-consumer.mjs",
|
|
58
59
|
"smoke:published": "node ../../scripts/smoke-tree-spec-editor-external-consumer.mjs --source registry",
|
|
60
|
+
"smoke:package": "node scripts/smoke-package.mjs",
|
|
59
61
|
"prepublishOnly": "npm run build",
|
|
60
62
|
"prepare": "npm run build",
|
|
61
63
|
"test": "vitest run",
|
|
64
|
+
"test:coverage": "yarn test --coverage",
|
|
62
65
|
"test:monorepo": "cd ../../frontend && yarn vitest run --config vitest.tree-spec-editor.config.ts"
|
|
63
66
|
},
|
|
64
67
|
"dependencies": {
|
|
65
|
-
"@signalsafe/tree-spec": "^0.3.
|
|
66
|
-
"@signalsafe/tree-spec-editor-core": "^0.1.
|
|
67
|
-
"@signalsafe/tree-spec-editor-react": "^0.
|
|
68
|
+
"@signalsafe/tree-spec": "^0.3.3",
|
|
69
|
+
"@signalsafe/tree-spec-editor-core": "^0.1.4",
|
|
70
|
+
"@signalsafe/tree-spec-editor-react": "^0.2.0"
|
|
68
71
|
},
|
|
69
72
|
"peerDependencies": {
|
|
70
73
|
"react": "^18.0.0",
|
|
71
|
-
"react-bootstrap": "^2.10.0",
|
|
72
74
|
"react-dom": "^18.0.0",
|
|
73
75
|
"reactflow": "^11.0.0"
|
|
74
76
|
},
|
|
@@ -77,11 +79,11 @@
|
|
|
77
79
|
"@types/react-dom": "^18.2.22",
|
|
78
80
|
"@types/react-test-renderer": "^18.3.0",
|
|
79
81
|
"react": "^18.3.1",
|
|
80
|
-
"react-bootstrap": "^2.10.2",
|
|
81
82
|
"react-dom": "^18.3.1",
|
|
82
83
|
"react-test-renderer": "^18.3.1",
|
|
83
84
|
"reactflow": "^11.11.4",
|
|
84
85
|
"typescript": "^5.4.2",
|
|
86
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
85
87
|
"vitest": "^3.2.4"
|
|
86
88
|
}
|
|
87
89
|
}
|