@formicoidea/labre-framework-wardley 0.23.0 → 0.23.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,280 +1,280 @@
1
- import { EdgelessCRUDIdentifier } from '@formicoidea/labre-core/blocks/surface';
2
- import { WardleyBackgroundElementModel } from '@formicoidea/labre-core/model';
3
- import {
4
- TelemetryProvider,
5
- type ToolbarContext,
6
- type ToolbarModuleConfig,
7
- ToolbarModuleExtension,
8
- } from '@formicoidea/labre-core/shared/services';
9
- import { BlockFlavourIdentifier } from '@formicoidea/labre-core/std';
10
- import { html, type TemplateResult } from 'lit';
11
-
12
- import { createWardleyLegend } from '../legend';
13
- import { wardleyLegendIcon } from './icons';
14
-
15
- const ResizeIcon = html`<svg
16
- width="24"
17
- height="24"
18
- viewBox="0 0 24 24"
19
- fill="none"
20
- stroke="currentColor"
21
- stroke-width="1.6"
22
- stroke-linecap="round"
23
- stroke-linejoin="round"
24
- >
25
- <path d="M9 5H5v4M15 19h4v-4" />
26
- <path d="M5 5l6 6M19 19l-6-6" />
27
- </svg>`;
28
-
29
- /** Gradient swatch — show/hide the variant gradient. */
30
- const GradientIcon = html`<svg
31
- width="24"
32
- height="24"
33
- viewBox="0 0 24 24"
34
- fill="none"
35
- xmlns="http://www.w3.org/2000/svg"
36
- >
37
- <defs>
38
- <linearGradient id="wardleyToolbarGrad" x1="0" y1="0" x2="1" y2="0">
39
- <stop offset="0" stop-color="currentColor" stop-opacity="0.85" />
40
- <stop offset="1" stop-color="currentColor" stop-opacity="0.1" />
41
- </linearGradient>
42
- </defs>
43
- <rect
44
- x="4"
45
- y="5"
46
- width="16"
47
- height="14"
48
- rx="2"
49
- fill="url(#wardleyToolbarGrad)"
50
- stroke="currentColor"
51
- stroke-width="1.4"
52
- />
53
- </svg>`;
54
-
55
- /** Horizontal axis with a right-pointing arrow (Evolution / X). */
56
- const XAxisIcon = html`<svg
57
- width="24"
58
- height="24"
59
- viewBox="0 0 24 24"
60
- fill="none"
61
- stroke="currentColor"
62
- stroke-width="1.6"
63
- stroke-linecap="round"
64
- stroke-linejoin="round"
65
- >
66
- <path d="M3 17h15" />
67
- <path d="M15 14l3 3-3 3" />
68
- </svg>`;
69
-
70
- /** Vertical axis with an up-pointing arrow (Value Chain / Y). */
71
- const YAxisIcon = html`<svg
72
- width="24"
73
- height="24"
74
- viewBox="0 0 24 24"
75
- fill="none"
76
- stroke="currentColor"
77
- stroke-width="1.6"
78
- stroke-linecap="round"
79
- stroke-linejoin="round"
80
- >
81
- <path d="M7 21V6" />
82
- <path d="M4 9l3-3 3 3" />
83
- </svg>`;
84
-
85
- /** Dashed vertical column dividers. */
86
- const ColumnsIcon = html`<svg
87
- width="24"
88
- height="24"
89
- viewBox="0 0 24 24"
90
- fill="none"
91
- stroke="currentColor"
92
- stroke-width="1.6"
93
- stroke-linecap="round"
94
- stroke-dasharray="3 3"
95
- >
96
- <path d="M9 4v16M15 4v16" />
97
- </svg>`;
98
-
99
- /** Column labels (short bars under the columns). */
100
- const ColumnLabelsIcon = html`<svg
101
- width="24"
102
- height="24"
103
- viewBox="0 0 24 24"
104
- fill="currentColor"
105
- stroke="none"
106
- >
107
- <rect x="3" y="15" width="4.5" height="3" rx="1" />
108
- <rect x="9.75" y="15" width="4.5" height="3" rx="1" />
109
- <rect x="16.5" y="15" width="4.5" height="3" rx="1" />
110
- </svg>`;
111
-
112
- /** Corner labels (Uncharted / Industrialized, top corners). */
113
- const CornerLabelsIcon = html`<svg
114
- width="24"
115
- height="24"
116
- viewBox="0 0 24 24"
117
- fill="currentColor"
118
- stroke="none"
119
- >
120
- <rect x="3" y="5" width="6" height="3" rx="1" />
121
- <rect x="15" y="5" width="6" height="3" rx="1" />
122
- </svg>`;
123
-
124
- /** Visibility labels (Visible / Invisible) — an eye. */
125
- const VisibilityIcon = html`<svg
126
- width="24"
127
- height="24"
128
- viewBox="0 0 24 24"
129
- fill="none"
130
- stroke="currentColor"
131
- stroke-width="1.6"
132
- stroke-linecap="round"
133
- stroke-linejoin="round"
134
- >
135
- <path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12z" />
136
- <circle cx="12" cy="12" r="2.4" />
137
- </svg>`;
138
-
139
- type WardleyToggleProp =
140
- | 'resizeEnabled'
141
- | 'showGradient'
142
- | 'showXAxis'
143
- | 'showYAxis'
144
- | 'showColumnDividers'
145
- | 'showColumnLabels'
146
- | 'showCornerLabels'
147
- | 'showVisibilityLabels';
148
-
149
- /**
150
- * Build a toolbar toggle that flips a boolean flag on every selected Wardley
151
- * background: `active` reflects the current state, `run` flips it (with an
152
- * undo checkpoint). An optional `when` predicate hides the button.
153
- */
154
- function booleanToggle(
155
- id: string,
156
- tooltip: string,
157
- icon: TemplateResult,
158
- prop: WardleyToggleProp,
159
- when?: (ctx: ToolbarContext) => boolean
160
- ) {
161
- return {
162
- id,
163
- tooltip,
164
- icon,
165
- when: when ?? true,
166
- active(ctx: ToolbarContext) {
167
- const models = ctx.getSurfaceModelsByType(WardleyBackgroundElementModel);
168
- return models.length > 0 && models.every(model => model[prop]);
169
- },
170
- run(ctx: ToolbarContext) {
171
- const models = ctx.getSurfaceModelsByType(WardleyBackgroundElementModel);
172
- if (!models.length) return;
173
-
174
- const enable = !models.every(model => model[prop]);
175
- ctx.std.store.captureSync();
176
- const crud = ctx.std.get(EdgelessCRUDIdentifier);
177
- for (const model of models) {
178
- crud.updateElement(model.id, { [prop]: enable });
179
- }
180
- },
181
- };
182
- }
183
-
184
- export const wardleyToolbarConfig = {
185
- actions: [
186
- booleanToggle(
187
- 'a.toggle-resize',
188
- 'Enable / lock resizing',
189
- ResizeIcon,
190
- 'resizeEnabled'
191
- ),
192
- // Group 1 — evolution (X) side: axis, phase labels, columns, corner
193
- // labels, and the gradient toggle.
194
- {
195
- id: 'b.evolution',
196
- actions: [
197
- booleanToggle(
198
- 'b.1-axis-x',
199
- 'Evolution axis (X)',
200
- XAxisIcon,
201
- 'showXAxis'
202
- ),
203
- booleanToggle(
204
- 'b.2-column-labels',
205
- 'Evolution phase labels',
206
- ColumnLabelsIcon,
207
- 'showColumnLabels'
208
- ),
209
- booleanToggle(
210
- 'b.3-columns',
211
- 'Columns (dividers)',
212
- ColumnsIcon,
213
- 'showColumnDividers'
214
- ),
215
- booleanToggle(
216
- 'b.4-corner-labels',
217
- 'Labels Uncharted / Industrialized',
218
- CornerLabelsIcon,
219
- 'showCornerLabels'
220
- ),
221
- // Only relevant when the selection has a gradient variant.
222
- booleanToggle(
223
- 'b.5-gradient',
224
- 'Show / hide the gradient',
225
- GradientIcon,
226
- 'showGradient',
227
- ctx =>
228
- ctx
229
- .getSurfaceModelsByType(WardleyBackgroundElementModel)
230
- .some(model => model.variant !== 'classic')
231
- ),
232
- ],
233
- },
234
- // Group 2 — value-chain (Y) side: axis and Visible/Invisible labels.
235
- {
236
- id: 'c.value-chain',
237
- actions: [
238
- booleanToggle(
239
- 'c.1-axis-y',
240
- 'Value Chain axis (Y)',
241
- YAxisIcon,
242
- 'showYAxis'
243
- ),
244
- booleanToggle(
245
- 'c.2-visibility-labels',
246
- 'Labels Visible / Invisible',
247
- VisibilityIcon,
248
- 'showVisibilityLabels'
249
- ),
250
- ],
251
- },
252
- // Generate the auto-legend from the components present inside this
253
- // background's perimeter (+ a gradient-meaning block for gradient variants).
254
- {
255
- id: 'd.legend',
256
- tooltip: 'Generate the legend (components present)',
257
- icon: wardleyLegendIcon,
258
- run(ctx) {
259
- const models = ctx.getSurfaceModelsByType(WardleyBackgroundElementModel);
260
- const bg = models[0];
261
- if (!bg) return;
262
- createWardleyLegend(ctx.std, bg);
263
- ctx.std.getOptional(TelemetryProvider)?.track('FrameworkLegendCreated', {
264
- framework: 'wardley',
265
- element: 'legend',
266
- page: 'whiteboard editor',
267
- segment: 'element toolbar',
268
- module: 'wardley toolbar',
269
- });
270
- },
271
- },
272
- ],
273
- when: ctx =>
274
- ctx.getSurfaceModelsByType(WardleyBackgroundElementModel).length > 0,
275
- } as const satisfies ToolbarModuleConfig;
276
-
277
- export const wardleyToolbarExtension = ToolbarModuleExtension({
278
- id: BlockFlavourIdentifier('affine:surface:wardley'),
279
- config: wardleyToolbarConfig,
280
- });
1
+ import { EdgelessCRUDIdentifier } from '@formicoidea/labre-core/blocks/surface';
2
+ import { WardleyBackgroundElementModel } from '@formicoidea/labre-core/model';
3
+ import {
4
+ TelemetryProvider,
5
+ type ToolbarContext,
6
+ type ToolbarModuleConfig,
7
+ ToolbarModuleExtension,
8
+ } from '@formicoidea/labre-core/shared/services';
9
+ import { BlockFlavourIdentifier } from '@formicoidea/labre-core/std';
10
+ import { html, type TemplateResult } from 'lit';
11
+
12
+ import { createWardleyLegend } from '../legend';
13
+ import { wardleyLegendIcon } from './icons';
14
+
15
+ const ResizeIcon = html`<svg
16
+ width="24"
17
+ height="24"
18
+ viewBox="0 0 24 24"
19
+ fill="none"
20
+ stroke="currentColor"
21
+ stroke-width="1.6"
22
+ stroke-linecap="round"
23
+ stroke-linejoin="round"
24
+ >
25
+ <path d="M9 5H5v4M15 19h4v-4" />
26
+ <path d="M5 5l6 6M19 19l-6-6" />
27
+ </svg>`;
28
+
29
+ /** Gradient swatch — show/hide the variant gradient. */
30
+ const GradientIcon = html`<svg
31
+ width="24"
32
+ height="24"
33
+ viewBox="0 0 24 24"
34
+ fill="none"
35
+ xmlns="http://www.w3.org/2000/svg"
36
+ >
37
+ <defs>
38
+ <linearGradient id="wardleyToolbarGrad" x1="0" y1="0" x2="1" y2="0">
39
+ <stop offset="0" stop-color="currentColor" stop-opacity="0.85" />
40
+ <stop offset="1" stop-color="currentColor" stop-opacity="0.1" />
41
+ </linearGradient>
42
+ </defs>
43
+ <rect
44
+ x="4"
45
+ y="5"
46
+ width="16"
47
+ height="14"
48
+ rx="2"
49
+ fill="url(#wardleyToolbarGrad)"
50
+ stroke="currentColor"
51
+ stroke-width="1.4"
52
+ />
53
+ </svg>`;
54
+
55
+ /** Horizontal axis with a right-pointing arrow (Evolution / X). */
56
+ const XAxisIcon = html`<svg
57
+ width="24"
58
+ height="24"
59
+ viewBox="0 0 24 24"
60
+ fill="none"
61
+ stroke="currentColor"
62
+ stroke-width="1.6"
63
+ stroke-linecap="round"
64
+ stroke-linejoin="round"
65
+ >
66
+ <path d="M3 17h15" />
67
+ <path d="M15 14l3 3-3 3" />
68
+ </svg>`;
69
+
70
+ /** Vertical axis with an up-pointing arrow (Value Chain / Y). */
71
+ const YAxisIcon = html`<svg
72
+ width="24"
73
+ height="24"
74
+ viewBox="0 0 24 24"
75
+ fill="none"
76
+ stroke="currentColor"
77
+ stroke-width="1.6"
78
+ stroke-linecap="round"
79
+ stroke-linejoin="round"
80
+ >
81
+ <path d="M7 21V6" />
82
+ <path d="M4 9l3-3 3 3" />
83
+ </svg>`;
84
+
85
+ /** Dashed vertical column dividers. */
86
+ const ColumnsIcon = html`<svg
87
+ width="24"
88
+ height="24"
89
+ viewBox="0 0 24 24"
90
+ fill="none"
91
+ stroke="currentColor"
92
+ stroke-width="1.6"
93
+ stroke-linecap="round"
94
+ stroke-dasharray="3 3"
95
+ >
96
+ <path d="M9 4v16M15 4v16" />
97
+ </svg>`;
98
+
99
+ /** Column labels (short bars under the columns). */
100
+ const ColumnLabelsIcon = html`<svg
101
+ width="24"
102
+ height="24"
103
+ viewBox="0 0 24 24"
104
+ fill="currentColor"
105
+ stroke="none"
106
+ >
107
+ <rect x="3" y="15" width="4.5" height="3" rx="1" />
108
+ <rect x="9.75" y="15" width="4.5" height="3" rx="1" />
109
+ <rect x="16.5" y="15" width="4.5" height="3" rx="1" />
110
+ </svg>`;
111
+
112
+ /** Corner labels (Uncharted / Industrialized, top corners). */
113
+ const CornerLabelsIcon = html`<svg
114
+ width="24"
115
+ height="24"
116
+ viewBox="0 0 24 24"
117
+ fill="currentColor"
118
+ stroke="none"
119
+ >
120
+ <rect x="3" y="5" width="6" height="3" rx="1" />
121
+ <rect x="15" y="5" width="6" height="3" rx="1" />
122
+ </svg>`;
123
+
124
+ /** Visibility labels (Visible / Invisible) — an eye. */
125
+ const VisibilityIcon = html`<svg
126
+ width="24"
127
+ height="24"
128
+ viewBox="0 0 24 24"
129
+ fill="none"
130
+ stroke="currentColor"
131
+ stroke-width="1.6"
132
+ stroke-linecap="round"
133
+ stroke-linejoin="round"
134
+ >
135
+ <path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12z" />
136
+ <circle cx="12" cy="12" r="2.4" />
137
+ </svg>`;
138
+
139
+ type WardleyToggleProp =
140
+ | 'resizeEnabled'
141
+ | 'showGradient'
142
+ | 'showXAxis'
143
+ | 'showYAxis'
144
+ | 'showColumnDividers'
145
+ | 'showColumnLabels'
146
+ | 'showCornerLabels'
147
+ | 'showVisibilityLabels';
148
+
149
+ /**
150
+ * Build a toolbar toggle that flips a boolean flag on every selected Wardley
151
+ * background: `active` reflects the current state, `run` flips it (with an
152
+ * undo checkpoint). An optional `when` predicate hides the button.
153
+ */
154
+ function booleanToggle(
155
+ id: string,
156
+ tooltip: string,
157
+ icon: TemplateResult,
158
+ prop: WardleyToggleProp,
159
+ when?: (ctx: ToolbarContext) => boolean
160
+ ) {
161
+ return {
162
+ id,
163
+ tooltip,
164
+ icon,
165
+ when: when ?? true,
166
+ active(ctx: ToolbarContext) {
167
+ const models = ctx.getSurfaceModelsByType(WardleyBackgroundElementModel);
168
+ return models.length > 0 && models.every(model => model[prop]);
169
+ },
170
+ run(ctx: ToolbarContext) {
171
+ const models = ctx.getSurfaceModelsByType(WardleyBackgroundElementModel);
172
+ if (!models.length) return;
173
+
174
+ const enable = !models.every(model => model[prop]);
175
+ ctx.std.store.captureSync();
176
+ const crud = ctx.std.get(EdgelessCRUDIdentifier);
177
+ for (const model of models) {
178
+ crud.updateElement(model.id, { [prop]: enable });
179
+ }
180
+ },
181
+ };
182
+ }
183
+
184
+ export const wardleyToolbarConfig = {
185
+ actions: [
186
+ booleanToggle(
187
+ 'a.toggle-resize',
188
+ 'Enable / lock resizing',
189
+ ResizeIcon,
190
+ 'resizeEnabled'
191
+ ),
192
+ // Group 1 — evolution (X) side: axis, phase labels, columns, corner
193
+ // labels, and the gradient toggle.
194
+ {
195
+ id: 'b.evolution',
196
+ actions: [
197
+ booleanToggle(
198
+ 'b.1-axis-x',
199
+ 'Evolution axis (X)',
200
+ XAxisIcon,
201
+ 'showXAxis'
202
+ ),
203
+ booleanToggle(
204
+ 'b.2-column-labels',
205
+ 'Evolution phase labels',
206
+ ColumnLabelsIcon,
207
+ 'showColumnLabels'
208
+ ),
209
+ booleanToggle(
210
+ 'b.3-columns',
211
+ 'Columns (dividers)',
212
+ ColumnsIcon,
213
+ 'showColumnDividers'
214
+ ),
215
+ booleanToggle(
216
+ 'b.4-corner-labels',
217
+ 'Labels Uncharted / Industrialized',
218
+ CornerLabelsIcon,
219
+ 'showCornerLabels'
220
+ ),
221
+ // Only relevant when the selection has a gradient variant.
222
+ booleanToggle(
223
+ 'b.5-gradient',
224
+ 'Show / hide the gradient',
225
+ GradientIcon,
226
+ 'showGradient',
227
+ ctx =>
228
+ ctx
229
+ .getSurfaceModelsByType(WardleyBackgroundElementModel)
230
+ .some(model => model.variant !== 'classic')
231
+ ),
232
+ ],
233
+ },
234
+ // Group 2 — value-chain (Y) side: axis and Visible/Invisible labels.
235
+ {
236
+ id: 'c.value-chain',
237
+ actions: [
238
+ booleanToggle(
239
+ 'c.1-axis-y',
240
+ 'Value Chain axis (Y)',
241
+ YAxisIcon,
242
+ 'showYAxis'
243
+ ),
244
+ booleanToggle(
245
+ 'c.2-visibility-labels',
246
+ 'Labels Visible / Invisible',
247
+ VisibilityIcon,
248
+ 'showVisibilityLabels'
249
+ ),
250
+ ],
251
+ },
252
+ // Generate the auto-legend from the components present inside this
253
+ // background's perimeter (+ a gradient-meaning block for gradient variants).
254
+ {
255
+ id: 'd.legend',
256
+ tooltip: 'Generate the legend (components present)',
257
+ icon: wardleyLegendIcon,
258
+ run(ctx) {
259
+ const models = ctx.getSurfaceModelsByType(WardleyBackgroundElementModel);
260
+ const bg = models[0];
261
+ if (!bg) return;
262
+ createWardleyLegend(ctx.std, bg);
263
+ ctx.std.getOptional(TelemetryProvider)?.track('FrameworkLegendCreated', {
264
+ framework: 'wardley',
265
+ element: 'legend',
266
+ page: 'whiteboard editor',
267
+ segment: 'element toolbar',
268
+ module: 'wardley toolbar',
269
+ });
270
+ },
271
+ },
272
+ ],
273
+ when: ctx =>
274
+ ctx.getSurfaceModelsByType(WardleyBackgroundElementModel).length > 0,
275
+ } as const satisfies ToolbarModuleConfig;
276
+
277
+ export const wardleyToolbarExtension = ToolbarModuleExtension({
278
+ id: BlockFlavourIdentifier('affine:surface:wardley'),
279
+ config: wardleyToolbarConfig,
280
+ });
@@ -1,28 +1,28 @@
1
- import { shapeToolbarConfig } from '@formicoidea/labre-core/gfx/shape';
2
- import {
3
- type ToolbarModuleConfig,
4
- ToolbarModuleExtension,
5
- } from '@formicoidea/labre-core/shared/services';
6
- import { BlockFlavourIdentifier } from '@formicoidea/labre-core/std';
7
-
8
- /**
9
- * Wardley nodes are {@link ShapeElementModel} subclasses, so the shape toolbar's
10
- * actions (which target `getSurfaceModelsByType(ShapeElementModel)`) operate on
11
- * them directly. We re-register only the color / line-style actions under the
12
- * `wardleyNode` flavour so the circle's fill / stroke color / stroke width are
13
- * editable — while excluding the shape-only actions (switch type, add inner
14
- * text, edit vertices) that don't make sense for a Wardley node.
15
- */
16
- const KEEP_ACTION_IDS = new Set(['e.color', 'd.style']);
17
-
18
- const wardleyNodeToolbarConfig = {
19
- actions: shapeToolbarConfig.actions.filter(action =>
20
- KEEP_ACTION_IDS.has(action.id)
21
- ),
22
- when: shapeToolbarConfig.when,
23
- } as ToolbarModuleConfig;
24
-
25
- export const wardleyNodeToolbarExtension = ToolbarModuleExtension({
26
- id: BlockFlavourIdentifier('affine:surface:wardleyNode'),
27
- config: wardleyNodeToolbarConfig,
28
- });
1
+ import { shapeToolbarConfig } from '@formicoidea/labre-core/gfx/shape';
2
+ import {
3
+ type ToolbarModuleConfig,
4
+ ToolbarModuleExtension,
5
+ } from '@formicoidea/labre-core/shared/services';
6
+ import { BlockFlavourIdentifier } from '@formicoidea/labre-core/std';
7
+
8
+ /**
9
+ * Wardley nodes are {@link ShapeElementModel} subclasses, so the shape toolbar's
10
+ * actions (which target `getSurfaceModelsByType(ShapeElementModel)`) operate on
11
+ * them directly. We re-register only the color / line-style actions under the
12
+ * `wardleyNode` flavour so the circle's fill / stroke color / stroke width are
13
+ * editable — while excluding the shape-only actions (switch type, add inner
14
+ * text, edit vertices) that don't make sense for a Wardley node.
15
+ */
16
+ const KEEP_ACTION_IDS = new Set(['e.color', 'd.style']);
17
+
18
+ const wardleyNodeToolbarConfig = {
19
+ actions: shapeToolbarConfig.actions.filter(action =>
20
+ KEEP_ACTION_IDS.has(action.id)
21
+ ),
22
+ when: shapeToolbarConfig.when,
23
+ } as ToolbarModuleConfig;
24
+
25
+ export const wardleyNodeToolbarExtension = ToolbarModuleExtension({
26
+ id: BlockFlavourIdentifier('affine:surface:wardleyNode'),
27
+ config: wardleyNodeToolbarConfig,
28
+ });
@@ -1,11 +1,11 @@
1
- import { SeniorToolExtension } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
2
- import { html } from 'lit';
3
-
4
- export const wardleySeniorTool = SeniorToolExtension('wardley', ({ block }) => {
5
- return {
6
- name: 'Wardley map',
7
- content: html`<edgeless-wardley-senior-button
8
- .edgeless=${block}
9
- ></edgeless-wardley-senior-button>`,
10
- };
11
- });
1
+ import { SeniorToolExtension } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
2
+ import { html } from 'lit';
3
+
4
+ export const wardleySeniorTool = SeniorToolExtension('wardley', ({ block }) => {
5
+ return {
6
+ name: 'Wardley map',
7
+ content: html`<edgeless-wardley-senior-button
8
+ .edgeless=${block}
9
+ ></edgeless-wardley-senior-button>`,
10
+ };
11
+ });