@unofficialbox/box-open-elements 0.35.0 → 0.36.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.
@@ -14,6 +14,9 @@ export interface ProcessBox<N = unknown> {
14
14
  node: N;
15
15
  kind: string;
16
16
  title: string;
17
+ /** Graph notes keep box identity but are not workflow steps. */
18
+ role?: "flow" | "note";
19
+ /** For graph notes, the visible note text (title is the fallback). */
17
20
  description?: string;
18
21
  /** Description used in Technical view; absent values fall back to description. */
19
22
  technicalDescription?: string;
@@ -40,6 +43,8 @@ export interface ProcessBox<N = unknown> {
40
43
  }
41
44
  export interface ProcessLine {
42
45
  id: string;
46
+ /** Associations attach graph notes without participating in workflow flow. */
47
+ role?: "flow" | "association";
43
48
  from: string;
44
49
  to: string;
45
50
  label?: string;
@@ -54,6 +59,9 @@ export interface ProcessLine {
54
59
  /** Optional last-run traffic share, between 0 and 1. */
55
60
  share?: number;
56
61
  }
62
+ /** Semantic eligibility is independent of host kind names. */
63
+ export declare const isFlowBox: (box: ProcessBox) => boolean;
64
+ export declare const isFlowLine: (line: ProcessLine) => boolean;
57
65
  export type ProcessSide = "north" | "east" | "south" | "west";
58
66
  export interface ProcessConnection {
59
67
  name: string;
@@ -148,19 +156,58 @@ export interface ProcessExpressionField {
148
156
  export interface ProcessField {
149
157
  key: string;
150
158
  label: string;
151
- kind: "text" | "multiline" | "number" | "choice" | "boolean" | "expression" | "search" | "action";
159
+ kind: "text" | "multiline" | "number" | "choice" | "boolean" | "expression" | "search" | "action" | "time" | "datetime-local";
152
160
  value: string | number | boolean;
153
161
  description?: string;
154
162
  options?: readonly {
155
163
  value: string;
156
164
  label: string;
157
165
  group?: string;
166
+ description?: string;
167
+ }[];
168
+ /** Action category order and optional headings supplied by the host catalog. */
169
+ actionGroups?: readonly {
170
+ name: string;
171
+ heading?: string;
158
172
  }[];
173
+ /** Permit a dotted action key absent from the host catalog. The host validates it. */
174
+ allowCustomValue?: boolean;
159
175
  placeholder?: string;
160
176
  required?: boolean;
161
177
  disabled?: boolean;
162
178
  problem?: string;
163
179
  expression?: ProcessExpressionField;
180
+ /** Visible rows for multiline fields. Expression fields use expression.rows. */
181
+ rows?: number;
182
+ /** Monospace presentation for host-owned code or structured text. */
183
+ format?: 'code';
184
+ /** Native constraints for number fields; the host still validates edits. */
185
+ min?: number;
186
+ max?: number;
187
+ step?: number | 'any';
188
+ /** Adjacent fields with the same key share a titled section. */
189
+ section?: {
190
+ key: string;
191
+ title: string;
192
+ description?: string;
193
+ descriptionSegments?: ProcessTechnicalDetail['segments'];
194
+ };
195
+ /** Adjacent fields with the same key share a native disclosure. */
196
+ disclosure?: {
197
+ key: string;
198
+ summary: string;
199
+ open?: boolean;
200
+ };
201
+ /** Adjacent fields with the same key share a row; default columns are equal. */
202
+ row?: {
203
+ key: string;
204
+ leadingWidth?: number;
205
+ gap?: number;
206
+ };
207
+ /** A visible optional marker, independent of native required validation. */
208
+ optional?: boolean;
209
+ /** Plain-text type/location hint after validation feedback. */
210
+ annotation?: string;
164
211
  }
165
212
  export interface ProcessPositionSnapshot {
166
213
  path?: NodePath;
@@ -182,6 +229,8 @@ export interface ProcessProjection<N = unknown> {
182
229
  lines: readonly ProcessLine[];
183
230
  }
184
231
  export interface ProcessKind extends FlowKind {
232
+ /** False for metadata-only kinds that must not appear in Add or insert choices. */
233
+ addable?: boolean;
185
234
  /** Alternative terms included in palette search. */
186
235
  aliases?: readonly string[];
187
236
  /** Host kind names never dictate the reusable visual anatomy. */
@@ -291,7 +340,7 @@ export type ProcessSelectionItem = {
291
340
  readonly id: string;
292
341
  };
293
342
  export interface ProcessEdit {
294
- type: "add" | "delete" | "duplicate" | "connect" | "disconnect" | "reattach" | "insert" | "reparent" | "reset-line" | "tidy" | "make-section" | "delete-selection";
343
+ type: "add" | "delete" | "duplicate" | "connect" | "disconnect" | "reattach" | "insert" | "reparent" | "reset-line" | "tidy" | "make-section" | "delete-selection" | "edit-line";
295
344
  /** One atomic mixed deletion; the host owns protected roots, descendants,
296
345
  * incident edges and notes. Unsupported hosts must leave it unapplied. */
297
346
  selection?: readonly ProcessSelectionItem[];
@@ -308,6 +357,9 @@ export interface ProcessEdit {
308
357
  from?: string;
309
358
  to?: string;
310
359
  lineId?: string;
360
+ /** Host-owned branch presentation; edit-line preserves endpoints and routing. */
361
+ label?: string;
362
+ weight?: number;
311
363
  kind?: FlowKind;
312
364
  position?: BoxPosition;
313
365
  /** Optional for existing hosts; all built-in insertion producers supply intent. */
@@ -1,3 +1,6 @@
1
+ /** Semantic eligibility is independent of host kind names. */
2
+ export const isFlowBox = (box) => box.role !== "note";
3
+ export const isFlowLine = (line) => line.role !== "association";
1
4
  export function validateProjection(projection) {
2
5
  const ids = new Set();
3
6
  for (const box of projection.boxes) {
@@ -35,7 +38,7 @@ export function completeLayout(projection, layout) {
35
38
  .filter((child) => child.parentId === box.id)
36
39
  .map(measure);
37
40
  const size = {
38
- width: Math.max(box.frame || box.shape === "frame" ? 320 : box.shape === "gateway" || box.shape === "event" ? 56 : 224, ...children.map((child) => child.width + 40)),
41
+ width: Math.max(box.frame || box.shape === "frame" ? 320 : box.shape === "gateway" || box.shape === "event" ? 56 : box.role === "note" ? 208 : 224, ...children.map((child) => child.width + 40)),
39
42
  height: box.frame
40
43
  ? Math.max(180, 64 + children.reduce((sum, child) => sum + child.height + 24, 0))
41
44
  : box.shape === "gateway" || box.shape === "event" ? 56 : 64,
@@ -49,13 +52,30 @@ export function completeLayout(projection, layout) {
49
52
  let y = top;
50
53
  for (const box of siblings) {
51
54
  const size = sizes.get(box.id);
52
- boxes[box.id] ??= { x, y, ...size };
55
+ if (!boxes[box.id]) {
56
+ if (box.role === "note") {
57
+ // Flow ranks are already placed; unplaced graph notes need free space
58
+ // regardless of their order in the projection.
59
+ const ancestors = new Set();
60
+ for (let parent = box.parentId; parent; parent = projection.boxes.find(b => b.id === parent)?.parentId)
61
+ ancestors.add(parent);
62
+ let overlaps;
63
+ do {
64
+ overlaps = Object.entries(boxes).filter(([id]) => !ancestors.has(id)).map(([, p]) => p).filter(p => x < p.x + (p.width ?? 224) && x + size.width > p.x && y < p.y + (p.height ?? 64) && y + size.height > p.y);
65
+ if (overlaps.length)
66
+ y = Math.max(...overlaps.map(p => p.y + (p.height ?? 64))) + 60;
67
+ } while (overlaps.length);
68
+ boxes[box.id] = { x, y, width: size.width };
69
+ }
70
+ else
71
+ boxes[box.id] = { x, y, ...size };
72
+ }
53
73
  const position = boxes[box.id];
54
74
  place(projection.boxes.filter((child) => child.parentId === box.id), position.x + 20, position.y + 64);
55
75
  y += (position.height ?? size.height) + 60;
56
76
  }
57
77
  };
58
- place(roots, 40, 40);
78
+ place([...roots.filter(box => box.role !== "note"), ...roots.filter(box => box.role === "note")], 40, 40);
59
79
  return { ...layout, boxes };
60
80
  }
61
81
  /** Bounded history shared by layout edits and host-accepted document commands. */
@@ -60,6 +60,10 @@ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends
60
60
  private checks;
61
61
  private renderer?;
62
62
  private cleanupInspector?;
63
+ private inspectorFieldCleanups;
64
+ private pendingActionChoice?;
65
+ private quietActionFocus;
66
+ private cleanupInspectorFields;
63
67
  private inspected?;
64
68
  private inspectedId?;
65
69
  private inspectedControls;
@@ -118,6 +122,8 @@ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends
118
122
  private narrowValue;
119
123
  private suppressClick;
120
124
  private resizeObserver?;
125
+ private autoNoteHeights;
126
+ private unplacedNotes;
121
127
  private routedLines;
122
128
  private computedChecks;
123
129
  get selectedBoxes(): readonly ProcessBox<N>[];
@@ -258,6 +264,7 @@ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends
258
264
  private navigateSelection;
259
265
  private revealBox;
260
266
  private pointerDown;
267
+ private selectMarquee;
261
268
  private distance;
262
269
  private pointerMove;
263
270
  private pointerEnd;
@@ -280,6 +287,7 @@ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends
280
287
  private addLayoutKind;
281
288
  private showConnectTooltip;
282
289
  protected update(): void;
290
+ private measureGraphNotes;
283
291
  private get allChecks();
284
292
  private collectChecks;
285
293
  private renderWorld;
@@ -294,7 +302,9 @@ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends
294
302
  private finishPalettePointer;
295
303
  private renderPalette;
296
304
  private renderChecks;
305
+ private renderFields;
297
306
  private renderField;
307
+ private renderLeadsTo;
298
308
  private renderSelection;
299
309
  private renderLocalVariables;
300
310
  private requestLocalVariableEdit;