@djangocfg/ui-tools 2.1.157 → 2.1.159

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 (42) hide show
  1. package/README.md +164 -3
  2. package/dist/{Mermaid.client-KMNEPBQJ.cjs → Mermaid.client-2TAFAXPW.cjs} +100 -143
  3. package/dist/Mermaid.client-2TAFAXPW.cjs.map +1 -0
  4. package/dist/{Mermaid.client-3WPNJ4DF.mjs → Mermaid.client-HG24D5KB.mjs} +100 -143
  5. package/dist/Mermaid.client-HG24D5KB.mjs.map +1 -0
  6. package/dist/index.cjs +4 -9
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +2 -2
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.mjs +4 -9
  11. package/dist/index.mjs.map +1 -1
  12. package/package.json +11 -6
  13. package/src/tools/Mermaid/Mermaid.client.tsx +40 -56
  14. package/src/tools/Mermaid/Mermaid.story.tsx +195 -110
  15. package/src/tools/Mermaid/builders/FlowDiagram/FlowDiagram.ts +96 -0
  16. package/src/tools/Mermaid/builders/FlowDiagram/functions/getEdges.ts +50 -0
  17. package/src/tools/Mermaid/builders/FlowDiagram/functions/getNodes.ts +43 -0
  18. package/src/tools/Mermaid/builders/FlowDiagram/functions/getStyles.ts +90 -0
  19. package/src/tools/Mermaid/builders/FlowDiagram/functions/index.ts +8 -0
  20. package/src/tools/Mermaid/builders/FlowDiagram/index.ts +16 -0
  21. package/src/tools/Mermaid/builders/FlowDiagram/types.ts +130 -0
  22. package/src/tools/Mermaid/builders/JourneyDiagram/JourneyDiagram.ts +88 -0
  23. package/src/tools/Mermaid/builders/JourneyDiagram/index.ts +12 -0
  24. package/src/tools/Mermaid/builders/JourneyDiagram/types.ts +48 -0
  25. package/src/tools/Mermaid/builders/SequenceDiagram/SequenceDiagram.ts +123 -0
  26. package/src/tools/Mermaid/builders/SequenceDiagram/functions/getActivations.ts +30 -0
  27. package/src/tools/Mermaid/builders/SequenceDiagram/functions/getBlocks.ts +112 -0
  28. package/src/tools/Mermaid/builders/SequenceDiagram/functions/getMessages.ts +85 -0
  29. package/src/tools/Mermaid/builders/SequenceDiagram/functions/getNotes.ts +94 -0
  30. package/src/tools/Mermaid/builders/SequenceDiagram/functions/index.ts +16 -0
  31. package/src/tools/Mermaid/builders/SequenceDiagram/index.ts +17 -0
  32. package/src/tools/Mermaid/builders/SequenceDiagram/types.ts +147 -0
  33. package/src/tools/Mermaid/builders/core/DiagramStore.ts +138 -0
  34. package/src/tools/Mermaid/builders/core/index.ts +8 -0
  35. package/src/tools/Mermaid/builders/core/sanitize.ts +78 -0
  36. package/src/tools/Mermaid/builders/core/theme.ts +42 -0
  37. package/src/tools/Mermaid/builders/core/types.ts +183 -0
  38. package/src/tools/Mermaid/builders/index.ts +96 -0
  39. package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +78 -54
  40. package/src/tools/Mermaid/index.tsx +51 -12
  41. package/dist/Mermaid.client-3WPNJ4DF.mjs.map +0 -1
  42. package/dist/Mermaid.client-KMNEPBQJ.cjs.map +0 -1
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Style builder functions for FlowDiagram
3
+ * @module Mermaid/builders/FlowDiagram/functions/getStyles
4
+ */
5
+
6
+ import { DiagramStore } from '../../core/DiagramStore';
7
+ import type { StyleProperties } from '../../core/types';
8
+ import { toNodeId } from '../../core/sanitize';
9
+ import type { StyleBuilder } from '../types';
10
+
11
+ /**
12
+ * Convert style properties to Mermaid classDef syntax
13
+ */
14
+ function propertiesToString(properties: StyleProperties): string {
15
+ const parts: string[] = [];
16
+
17
+ if (properties.fill) parts.push(`fill:${properties.fill}`);
18
+ if (properties.stroke) parts.push(`stroke:${properties.stroke}`);
19
+ if (properties['stroke-width']) parts.push(`stroke-width:${properties['stroke-width']}`);
20
+ if (properties.color) parts.push(`color:${properties.color}`);
21
+ if (properties['font-weight']) parts.push(`font-weight:${properties['font-weight']}`);
22
+ if (properties['stroke-dasharray']) parts.push(`stroke-dasharray:${properties['stroke-dasharray']}`);
23
+
24
+ return parts.join(',');
25
+ }
26
+
27
+ /**
28
+ * Create a style builder
29
+ */
30
+ export function createStyleBuilder(store: DiagramStore): StyleBuilder {
31
+ return {
32
+ define(name: string, properties: StyleProperties): void {
33
+ const propsStr = propertiesToString(properties);
34
+ store.add(`classDef ${name} ${propsStr}`);
35
+ },
36
+
37
+ apply(className: string, ...nodeIds: string[]): void {
38
+ if (nodeIds.length === 0) return;
39
+ const safeIds = nodeIds.map((id) => toNodeId(id)).join(',');
40
+ store.add(`class ${safeIds} ${className}`);
41
+ },
42
+ };
43
+ }
44
+
45
+ // ============================================================================
46
+ // Predefined Style Classes (Common patterns)
47
+ // ============================================================================
48
+
49
+ /**
50
+ * Common style presets for quick use
51
+ */
52
+ export const STYLE_PRESETS = {
53
+ /** Green success style */
54
+ success: {
55
+ fill: '#22c55e',
56
+ stroke: '#16a34a',
57
+ color: '#fff',
58
+ },
59
+ /** Blue primary style */
60
+ primary: {
61
+ fill: '#3b82f6',
62
+ stroke: '#1d4ed8',
63
+ color: '#fff',
64
+ },
65
+ /** Red error/danger style */
66
+ danger: {
67
+ fill: '#ef4444',
68
+ stroke: '#dc2626',
69
+ color: '#fff',
70
+ },
71
+ /** Yellow warning style */
72
+ warning: {
73
+ fill: '#f59e0b',
74
+ stroke: '#d97706',
75
+ color: '#fff',
76
+ },
77
+ /** Gray muted style */
78
+ muted: {
79
+ fill: '#6b7280',
80
+ stroke: '#4b5563',
81
+ color: '#fff',
82
+ },
83
+ /** Emerald/teal accent */
84
+ accent: {
85
+ fill: '#10b981',
86
+ stroke: '#047857',
87
+ color: '#fff',
88
+ 'font-weight': 'bold' as const,
89
+ },
90
+ } satisfies Record<string, StyleProperties>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * FlowDiagram function exports
3
+ * @module Mermaid/builders/FlowDiagram/functions
4
+ */
5
+
6
+ export { createNodeBuilder } from './getNodes';
7
+ export { createEdgeBuilder, createEdgesBuilder } from './getEdges';
8
+ export { createStyleBuilder, STYLE_PRESETS } from './getStyles';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * FlowDiagram builder exports
3
+ * @module Mermaid/builders/FlowDiagram
4
+ */
5
+
6
+ export { FlowDiagram } from './FlowDiagram';
7
+ export { STYLE_PRESETS } from './functions/getStyles';
8
+ export type {
9
+ FlowDiagramOptions,
10
+ FlowDiagramBuilder,
11
+ NodeBuilder,
12
+ EdgeBuilder,
13
+ EdgeEndBuilder,
14
+ StyleBuilder,
15
+ SubgraphBuilder,
16
+ } from './types';
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Types for FlowDiagram builder
3
+ * @module Mermaid/builders/FlowDiagram/types
4
+ */
5
+
6
+ import type { FlowDirection, NodeShape, StyleProperties } from '../core/types';
7
+
8
+ /**
9
+ * Options for FlowDiagram builder
10
+ */
11
+ export interface FlowDiagramOptions {
12
+ /** Diagram direction (default: 'TB') */
13
+ direction?: FlowDirection;
14
+ }
15
+
16
+ /**
17
+ * Node definition
18
+ */
19
+ export interface NodeDefinition {
20
+ id: string;
21
+ label: string;
22
+ shape: NodeShape;
23
+ subtitle?: string;
24
+ }
25
+
26
+ /**
27
+ * Edge definition
28
+ */
29
+ export interface EdgeDefinition {
30
+ from: string;
31
+ to: string;
32
+ label?: string;
33
+ style: 'solid' | 'dotted' | 'thick';
34
+ }
35
+
36
+ /**
37
+ * Style class definition for flow diagrams
38
+ */
39
+ export interface FlowStyleClass {
40
+ name: string;
41
+ properties: StyleProperties;
42
+ }
43
+
44
+ /**
45
+ * Node builder interface - chainable API for creating nodes
46
+ */
47
+ export interface NodeBuilder<Nodes extends string> {
48
+ /** Create a rectangular node [label] */
49
+ rect(label: string, subtitle?: string): void;
50
+ /** Create a rounded node (label) */
51
+ round(label: string, subtitle?: string): void;
52
+ /** Create a stadium/pill node ([label]) */
53
+ stadium(label: string, subtitle?: string): void;
54
+ /** Create a circular node ((label)) */
55
+ circle(label: string, subtitle?: string): void;
56
+ /** Create a rhombus/diamond node {label} */
57
+ rhombus(label: string, subtitle?: string): void;
58
+ /** Create a hexagon node {{label}} */
59
+ hexagon(label: string, subtitle?: string): void;
60
+ /** Create a cylinder/database node [(label)] */
61
+ cylinder(label: string, subtitle?: string): void;
62
+ /** Create a subroutine node [[label]] */
63
+ subroutine(label: string, subtitle?: string): void;
64
+ /** Create a double circle node (((label))) */
65
+ doubleCircle(label: string, subtitle?: string): void;
66
+ }
67
+
68
+ /**
69
+ * Edge builder interface - chainable API for creating edges
70
+ */
71
+ export interface EdgeBuilder<Nodes extends string> {
72
+ /** Target node for the edge */
73
+ to(target: Nodes): EdgeEndBuilder;
74
+ }
75
+
76
+ /**
77
+ * Edge end builder - configures the edge after target is specified
78
+ */
79
+ export interface EdgeEndBuilder {
80
+ /** Solid arrow --> */
81
+ solid(label?: string): void;
82
+ /** Dotted arrow -.-> */
83
+ dotted(label?: string): void;
84
+ /** Thick arrow ==> */
85
+ thick(label?: string): void;
86
+ /** Solid line without arrow --- */
87
+ line(label?: string): void;
88
+ /** Dotted line without arrow -.- */
89
+ dottedLine(label?: string): void;
90
+ }
91
+
92
+ /**
93
+ * Style builder interface
94
+ */
95
+ export interface StyleBuilder {
96
+ /** Define a style class */
97
+ define(name: string, properties: StyleProperties): void;
98
+ /** Apply a class to nodes */
99
+ apply(className: string, ...nodeIds: string[]): void;
100
+ }
101
+
102
+ /**
103
+ * Subgraph builder interface
104
+ */
105
+ export interface SubgraphBuilder<Nodes extends string> {
106
+ /** Set direction inside subgraph */
107
+ direction(dir: FlowDirection): void;
108
+ /** Create a node inside subgraph */
109
+ node(id: Nodes): NodeBuilder<Nodes>;
110
+ }
111
+
112
+ /**
113
+ * Main FlowDiagram builder result
114
+ */
115
+ export interface FlowDiagramBuilder<Nodes extends string> {
116
+ /** Create a node */
117
+ node: (id: Nodes) => NodeBuilder<Nodes>;
118
+ /** Create an edge from a node */
119
+ edge: (from: Nodes) => EdgeBuilder<Nodes>;
120
+ /** Create a subgraph */
121
+ subgraph: (name: string, fn: (sub: SubgraphBuilder<Nodes>) => void) => void;
122
+ /** Style utilities */
123
+ style: StyleBuilder;
124
+ /** Add a comment */
125
+ comment: (text: string) => void;
126
+ /** Add a blank line */
127
+ blank: () => void;
128
+ /** Get the Mermaid string */
129
+ toString: () => string;
130
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * JourneyDiagram Builder
3
+ * Declarative API for building Mermaid user journey diagrams
4
+ * @module Mermaid/builders/JourneyDiagram/JourneyDiagram
5
+ */
6
+
7
+ import { DiagramStore } from '../core/DiagramStore';
8
+ import type { TaskScore } from '../core/types';
9
+ import { sanitizeLabel } from '../core/sanitize';
10
+ import type { JourneyDiagramOptions, JourneyDiagramBuilder, SectionBuilder } from './types';
11
+
12
+ /**
13
+ * Format actors for journey task
14
+ */
15
+ function formatActors(actors: string | string[]): string {
16
+ if (Array.isArray(actors)) {
17
+ return actors.map(sanitizeLabel).join(', ');
18
+ }
19
+ return sanitizeLabel(actors);
20
+ }
21
+
22
+ /**
23
+ * Create a JourneyDiagram builder
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const journey = JourneyDiagram({ title: 'User Registration Flow' });
28
+ *
29
+ * journey.section('Discovery')
30
+ * .task('Visit website', 5, 'User')
31
+ * .task('Read about product', 4, 'User');
32
+ *
33
+ * journey.section('Registration')
34
+ * .task('Click sign up', 5, 'User')
35
+ * .task('Fill form', 2, 'User')
36
+ * .task('Verify email', 3, ['User', 'System']);
37
+ *
38
+ * journey.section('Onboarding')
39
+ * .task('Complete profile', 4, 'User')
40
+ * .task('Start using app', 5, 'User');
41
+ *
42
+ * console.log(journey.toString());
43
+ * ```
44
+ *
45
+ * @param options - Diagram options (title is required)
46
+ * @returns JourneyDiagram builder instance
47
+ */
48
+ export function JourneyDiagram(options: JourneyDiagramOptions): JourneyDiagramBuilder {
49
+ const store = new DiagramStore('journey');
50
+ store.add(`title ${sanitizeLabel(options.title)}`);
51
+
52
+ /**
53
+ * Add a task line
54
+ */
55
+ const addTask = (name: string, score: TaskScore, actors: string | string[]) => {
56
+ const actorStr = formatActors(actors);
57
+ store.add(`${sanitizeLabel(name)}: ${score}: ${actorStr}`);
58
+ };
59
+
60
+ /**
61
+ * Create a section builder for chaining tasks
62
+ */
63
+ const createSectionBuilder = (): SectionBuilder => ({
64
+ task(name: string, score: TaskScore, actors: string | string[]) {
65
+ addTask(name, score, actors);
66
+ return this;
67
+ },
68
+ });
69
+
70
+ return {
71
+ section(name: string) {
72
+ store.add(`section ${sanitizeLabel(name)}`);
73
+ return createSectionBuilder();
74
+ },
75
+
76
+ task(name: string, score: TaskScore, actors: string | string[]) {
77
+ addTask(name, score, actors);
78
+ },
79
+
80
+ comment(text: string) {
81
+ store.addComment(text);
82
+ },
83
+
84
+ toString() {
85
+ return store.toString();
86
+ },
87
+ };
88
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * JourneyDiagram builder exports
3
+ * @module Mermaid/builders/JourneyDiagram
4
+ */
5
+
6
+ export { JourneyDiagram } from './JourneyDiagram';
7
+ export type {
8
+ JourneyDiagramOptions,
9
+ JourneyDiagramBuilder,
10
+ SectionBuilder,
11
+ TaskDefinition,
12
+ } from './types';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Types for JourneyDiagram builder
3
+ * @module Mermaid/builders/JourneyDiagram/types
4
+ */
5
+
6
+ import type { TaskScore } from '../core/types';
7
+
8
+ /**
9
+ * Options for JourneyDiagram builder
10
+ */
11
+ export interface JourneyDiagramOptions {
12
+ /** Diagram title */
13
+ title: string;
14
+ }
15
+
16
+ /**
17
+ * Task definition
18
+ */
19
+ export interface TaskDefinition {
20
+ /** Task name/description */
21
+ name: string;
22
+ /** Score (1-5, where 5 is best) */
23
+ score: TaskScore;
24
+ /** Actor(s) involved */
25
+ actors: string | string[];
26
+ }
27
+
28
+ /**
29
+ * Section builder interface
30
+ */
31
+ export interface SectionBuilder {
32
+ /** Add a task to the current section */
33
+ task(name: string, score: TaskScore, actors: string | string[]): SectionBuilder;
34
+ }
35
+
36
+ /**
37
+ * Main JourneyDiagram builder result
38
+ */
39
+ export interface JourneyDiagramBuilder {
40
+ /** Add a new section */
41
+ section(name: string): SectionBuilder;
42
+ /** Add a task directly (without section - goes to last section or creates implicit one) */
43
+ task(name: string, score: TaskScore, actors: string | string[]): void;
44
+ /** Add a comment */
45
+ comment(text: string): void;
46
+ /** Get the Mermaid string */
47
+ toString(): string;
48
+ }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * SequenceDiagram Builder
3
+ * Declarative API for building Mermaid sequence diagrams
4
+ * @module Mermaid/builders/SequenceDiagram/SequenceDiagram
5
+ */
6
+
7
+ import { DiagramStore } from '../core/DiagramStore';
8
+ import type { ParticipantType } from '../core/types';
9
+ import { sanitizeLabel } from '../core/sanitize';
10
+ import { createMessageBuilder } from './functions/getMessages';
11
+ import { createNoteBuilder } from './functions/getNotes';
12
+ import { createActivationBuilder } from './functions/getActivations';
13
+ import {
14
+ createLoopBuilder,
15
+ createAltBuilder,
16
+ createParBuilder,
17
+ createRectBuilder,
18
+ createCriticalBuilder,
19
+ createBreakBuilder,
20
+ } from './functions/getBlocks';
21
+ import type { ParticipantsObject, SequenceDiagramOptions, SequenceDiagramBuilder } from './types';
22
+
23
+ const DEFAULT_OPTIONS: Required<SequenceDiagramOptions> = {
24
+ autoNumber: false,
25
+ };
26
+
27
+ /**
28
+ * Normalize participant definition to { type, alias } format
29
+ */
30
+ function normalizeParticipant(
31
+ value: ParticipantType | { type: ParticipantType; alias?: string },
32
+ ): { type: ParticipantType; alias?: string } {
33
+ if (typeof value === 'string') {
34
+ return { type: value };
35
+ }
36
+ return value;
37
+ }
38
+
39
+ /**
40
+ * Create a SequenceDiagram builder
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * const { d, note, loop, rect } = SequenceDiagram({
45
+ * Alice: 'participant',
46
+ * Bob: 'actor',
47
+ * Charlie: { type: 'participant', alias: 'C' },
48
+ * }, { autoNumber: true });
49
+ *
50
+ * rect('rgb(200, 220, 255)', () => {
51
+ * d.Alice.sync.Bob.msg('Hello!');
52
+ * d.Bob.syncReply.Alice.msg('Hi there!');
53
+ * });
54
+ *
55
+ * loop('Every minute', () => {
56
+ * d.Alice.async.Charlie.msg('Ping');
57
+ * });
58
+ *
59
+ * note.over.Alice.Bob.msg('Handshake complete');
60
+ *
61
+ * console.log(toString());
62
+ * ```
63
+ *
64
+ * @param participants - Participant definitions
65
+ * @param options - Diagram options
66
+ * @returns SequenceDiagram builder instance
67
+ */
68
+ export function SequenceDiagram<P extends string>(
69
+ participants: ParticipantsObject<P>,
70
+ options: SequenceDiagramOptions = {},
71
+ ): SequenceDiagramBuilder<P> {
72
+ const opts = { ...DEFAULT_OPTIONS, ...options };
73
+ const store = new DiagramStore('sequenceDiagram');
74
+
75
+ // Add autonumber if requested
76
+ if (opts.autoNumber) {
77
+ store.add('autonumber');
78
+ }
79
+
80
+ // Get participant keys
81
+ const participantKeys = Object.keys(participants) as P[];
82
+
83
+ // Declare participants
84
+ store.addBlank();
85
+ participantKeys.forEach((key) => {
86
+ const def = normalizeParticipant(participants[key]);
87
+ if (def.alias) {
88
+ store.add(`${def.type} ${key} as ${sanitizeLabel(def.alias)}`);
89
+ } else {
90
+ store.add(`${def.type} ${key}`);
91
+ }
92
+ });
93
+ store.addBlank();
94
+
95
+ // Create builders
96
+ const messageBuilder = createMessageBuilder<P>(store, participantKeys);
97
+ const noteBuilder = createNoteBuilder<P>(store, participantKeys);
98
+ const activationBuilder = createActivationBuilder<P>(store, participantKeys);
99
+
100
+ return {
101
+ d: messageBuilder,
102
+ note: noteBuilder,
103
+ activate: activationBuilder,
104
+ loop: createLoopBuilder(store),
105
+ alt: createAltBuilder(store),
106
+ par: createParBuilder(store),
107
+ rect: createRectBuilder(store),
108
+ critical: createCriticalBuilder(store),
109
+ break: createBreakBuilder(store),
110
+
111
+ comment(text: string) {
112
+ store.addComment(text);
113
+ },
114
+
115
+ blank() {
116
+ store.addBlank();
117
+ },
118
+
119
+ toString() {
120
+ return store.toString();
121
+ },
122
+ };
123
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Activation builder functions for SequenceDiagram
3
+ * @module Mermaid/builders/SequenceDiagram/functions/getActivations
4
+ */
5
+
6
+ import { DiagramStore } from '../../core/DiagramStore';
7
+ import type { ActivationBuilder } from '../types';
8
+
9
+ /**
10
+ * Create the activation builder for all participants
11
+ */
12
+ export function createActivationBuilder<P extends string>(
13
+ store: DiagramStore,
14
+ participants: readonly P[],
15
+ ): ActivationBuilder<P> {
16
+ const builder = {} as ActivationBuilder<P>;
17
+
18
+ participants.forEach((p) => {
19
+ builder[p] = {
20
+ activate() {
21
+ store.add(`activate ${p}`);
22
+ },
23
+ deactivate() {
24
+ store.add(`deactivate ${p}`);
25
+ },
26
+ };
27
+ });
28
+
29
+ return builder;
30
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Block builder functions for SequenceDiagram (loop, alt, par, rect, etc.)
3
+ * @module Mermaid/builders/SequenceDiagram/functions/getBlocks
4
+ */
5
+
6
+ import { DiagramStore } from '../../core/DiagramStore';
7
+ import { sanitizeLabel } from '../../core/sanitize';
8
+
9
+ /**
10
+ * Create a loop block builder
11
+ */
12
+ export function createLoopBuilder(store: DiagramStore) {
13
+ return (label: string, fn: () => void) => {
14
+ store.add(`loop ${sanitizeLabel(label)}`);
15
+ store.indent();
16
+ fn();
17
+ store.dedent();
18
+ store.add('end');
19
+ };
20
+ }
21
+
22
+ /**
23
+ * Create an alt (alternative/conditional) block builder
24
+ */
25
+ export function createAltBuilder(store: DiagramStore) {
26
+ return (label: string, fn: () => void) => {
27
+ store.add(`alt ${sanitizeLabel(label)}`);
28
+ store.indent();
29
+ fn();
30
+ store.dedent();
31
+
32
+ return {
33
+ else(elseLabel: string, elseFn: () => void) {
34
+ store.add(`else ${sanitizeLabel(elseLabel)}`);
35
+ store.indent();
36
+ elseFn();
37
+ store.dedent();
38
+ store.add('end');
39
+ },
40
+ };
41
+ };
42
+ }
43
+
44
+ /**
45
+ * Create a parallel (par) block builder
46
+ */
47
+ export function createParBuilder(store: DiagramStore) {
48
+ return (label: string, fn: () => void) => {
49
+ store.add(`par ${sanitizeLabel(label)}`);
50
+ store.indent();
51
+ fn();
52
+ store.dedent();
53
+
54
+ return {
55
+ and(andLabel: string, andFn: () => void) {
56
+ store.add(`and ${sanitizeLabel(andLabel)}`);
57
+ store.indent();
58
+ andFn();
59
+ store.dedent();
60
+ store.add('end');
61
+ },
62
+ };
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Create a rect (colored box) block builder
68
+ */
69
+ export function createRectBuilder(store: DiagramStore) {
70
+ return (color: string, fn: () => void) => {
71
+ store.add(`rect ${color}`);
72
+ store.indent();
73
+ fn();
74
+ store.dedent();
75
+ store.add('end');
76
+ };
77
+ }
78
+
79
+ /**
80
+ * Create a critical region block builder
81
+ */
82
+ export function createCriticalBuilder(store: DiagramStore) {
83
+ return (label: string, fn: () => void) => {
84
+ store.add(`critical ${sanitizeLabel(label)}`);
85
+ store.indent();
86
+ fn();
87
+ store.dedent();
88
+
89
+ return {
90
+ option(optionLabel: string, optionFn: () => void) {
91
+ store.add(`option ${sanitizeLabel(optionLabel)}`);
92
+ store.indent();
93
+ optionFn();
94
+ store.dedent();
95
+ store.add('end');
96
+ },
97
+ };
98
+ };
99
+ }
100
+
101
+ /**
102
+ * Create a break block builder
103
+ */
104
+ export function createBreakBuilder(store: DiagramStore) {
105
+ return (label: string, fn: () => void) => {
106
+ store.add(`break ${sanitizeLabel(label)}`);
107
+ store.indent();
108
+ fn();
109
+ store.dedent();
110
+ store.add('end');
111
+ };
112
+ }