@formicoidea/labre-framework-cynefin 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,122 +1,122 @@
1
- import {
2
- type ElementRenderer,
3
- ElementRendererExtension,
4
- } from '@formicoidea/labre-core/blocks/surface';
5
- import type { EstuarineElementModel } from '@formicoidea/labre-core/model';
6
-
7
- import { FONT_FAMILY, refScale } from '../utils';
8
- import {
9
- ARROWHEADS,
10
- AXIS_LABELS,
11
- AXIS_WIDTH,
12
- COLORS,
13
- COUNTERFACTUAL_PATH,
14
- COUNTERFACTUAL_WIDTH,
15
- E_AXIS,
16
- LABEL_LETTER_SPACING,
17
- LABELS,
18
- LIMINAL_PATH,
19
- LIMINAL_WIDTH,
20
- REF_H,
21
- REF_W,
22
- T_AXIS,
23
- VOLATILE_PATH,
24
- VOLATILE_WIDTH,
25
- } from './consts';
26
-
27
- /**
28
- * Canvas renderer for the Estuarine framework map — reproduces the official SVG:
29
- * the e (vertical, double-headed) / t (horizontal, single-headed) axes and the
30
- * three reference curves (Liminal / Volatile / Counter-factual), each with its
31
- * legend and individually hideable. Drawn in the fixed reference space and
32
- * scaled uniformly to the element bounds.
33
- */
34
- export const estuarine: ElementRenderer<EstuarineElementModel> = (
35
- model,
36
- ctx,
37
- matrix
38
- ) => {
39
- const [, , w, h] = model.deserializedXYWH;
40
- const cx = w / 2;
41
- const cy = h / 2;
42
- ctx.setTransform(
43
- matrix.translateSelf(cx, cy).rotateSelf(model.rotate).translateSelf(-cx, -cy)
44
- );
45
-
46
- const { s, ox, oy } = refScale(w, h, REF_W, REF_H);
47
- ctx.translate(ox, oy);
48
- ctx.scale(s, s);
49
-
50
- ctx.lineCap = 'round';
51
- ctx.lineJoin = 'round';
52
-
53
- // ── Axes ────────────────────────────────────────────────────────────
54
- ctx.strokeStyle = COLORS.axis;
55
- ctx.fillStyle = COLORS.axis;
56
- ctx.lineWidth = AXIS_WIDTH;
57
- ctx.beginPath();
58
- ctx.moveTo(E_AXIS.x, E_AXIS.y1);
59
- ctx.lineTo(E_AXIS.x, E_AXIS.y2);
60
- ctx.moveTo(T_AXIS.x1, T_AXIS.y);
61
- ctx.lineTo(T_AXIS.x2, T_AXIS.y);
62
- ctx.stroke();
63
- for (const [[tx, ty], [ax, ay], [bx, by]] of ARROWHEADS) {
64
- ctx.beginPath();
65
- ctx.moveTo(tx, ty);
66
- ctx.lineTo(ax, ay);
67
- ctx.lineTo(bx, by);
68
- ctx.closePath();
69
- ctx.fill();
70
- }
71
-
72
- // Uppercase legend (centre-anchored, alphabetic baseline, letter-spaced).
73
- const hasSpacing = 'letterSpacing' in ctx;
74
- const legend = (l: { text: string; x: number; y: number; size: number; color: string }) => {
75
- ctx.fillStyle = l.color;
76
- ctx.font = `600 ${l.size}px ${FONT_FAMILY}`;
77
- ctx.textAlign = 'center';
78
- ctx.textBaseline = 'alphabetic';
79
- if (hasSpacing) ctx.letterSpacing = `${LABEL_LETTER_SPACING}px`;
80
- ctx.fillText(l.text, l.x, l.y);
81
- if (hasSpacing) ctx.letterSpacing = '0px';
82
- };
83
-
84
- // ── Liminal (green) ─────────────────────────────────────────────────
85
- if (model.showLiminal) {
86
- ctx.strokeStyle = COLORS.liminal;
87
- ctx.lineWidth = LIMINAL_WIDTH;
88
- ctx.stroke(new Path2D(LIMINAL_PATH));
89
- legend(LABELS.liminal);
90
- }
91
-
92
- // ── Volatile (red) ──────────────────────────────────────────────────
93
- if (model.showVolatile) {
94
- ctx.strokeStyle = COLORS.volatile;
95
- ctx.lineWidth = VOLATILE_WIDTH;
96
- ctx.stroke(new Path2D(VOLATILE_PATH));
97
- legend(LABELS.volatile);
98
- }
99
-
100
- // ── Counter-factual (dark) ──────────────────────────────────────────
101
- if (model.showCounterfactual) {
102
- ctx.strokeStyle = COLORS.counterfactual;
103
- ctx.lineWidth = COUNTERFACTUAL_WIDTH;
104
- ctx.stroke(new Path2D(COUNTERFACTUAL_PATH));
105
- legend(LABELS.counterfactual);
106
- }
107
-
108
- // ── Italic e / t axis letters ───────────────────────────────────────
109
- if (model.showAxisLabels) {
110
- ctx.fillStyle = COLORS.axisLabel;
111
- ctx.font = `italic 700 ${AXIS_LABELS.size}px Georgia, serif`;
112
- ctx.textAlign = 'left';
113
- ctx.textBaseline = 'alphabetic';
114
- ctx.fillText(AXIS_LABELS.e.text, AXIS_LABELS.e.x, AXIS_LABELS.e.y);
115
- ctx.fillText(AXIS_LABELS.t.text, AXIS_LABELS.t.x, AXIS_LABELS.t.y);
116
- }
117
- };
118
-
119
- export const EstuarineRendererExtension = ElementRendererExtension(
120
- 'estuarine',
121
- estuarine
122
- );
1
+ import {
2
+ type ElementRenderer,
3
+ ElementRendererExtension,
4
+ } from '@formicoidea/labre-core/blocks/surface';
5
+ import type { EstuarineElementModel } from '@formicoidea/labre-core/model';
6
+
7
+ import { FONT_FAMILY, refScale } from '../utils';
8
+ import {
9
+ ARROWHEADS,
10
+ AXIS_LABELS,
11
+ AXIS_WIDTH,
12
+ COLORS,
13
+ COUNTERFACTUAL_PATH,
14
+ COUNTERFACTUAL_WIDTH,
15
+ E_AXIS,
16
+ LABEL_LETTER_SPACING,
17
+ LABELS,
18
+ LIMINAL_PATH,
19
+ LIMINAL_WIDTH,
20
+ REF_H,
21
+ REF_W,
22
+ T_AXIS,
23
+ VOLATILE_PATH,
24
+ VOLATILE_WIDTH,
25
+ } from './consts';
26
+
27
+ /**
28
+ * Canvas renderer for the Estuarine framework map — reproduces the official SVG:
29
+ * the e (vertical, double-headed) / t (horizontal, single-headed) axes and the
30
+ * three reference curves (Liminal / Volatile / Counter-factual), each with its
31
+ * legend and individually hideable. Drawn in the fixed reference space and
32
+ * scaled uniformly to the element bounds.
33
+ */
34
+ export const estuarine: ElementRenderer<EstuarineElementModel> = (
35
+ model,
36
+ ctx,
37
+ matrix
38
+ ) => {
39
+ const [, , w, h] = model.deserializedXYWH;
40
+ const cx = w / 2;
41
+ const cy = h / 2;
42
+ ctx.setTransform(
43
+ matrix.translateSelf(cx, cy).rotateSelf(model.rotate).translateSelf(-cx, -cy)
44
+ );
45
+
46
+ const { s, ox, oy } = refScale(w, h, REF_W, REF_H);
47
+ ctx.translate(ox, oy);
48
+ ctx.scale(s, s);
49
+
50
+ ctx.lineCap = 'round';
51
+ ctx.lineJoin = 'round';
52
+
53
+ // ── Axes ────────────────────────────────────────────────────────────
54
+ ctx.strokeStyle = COLORS.axis;
55
+ ctx.fillStyle = COLORS.axis;
56
+ ctx.lineWidth = AXIS_WIDTH;
57
+ ctx.beginPath();
58
+ ctx.moveTo(E_AXIS.x, E_AXIS.y1);
59
+ ctx.lineTo(E_AXIS.x, E_AXIS.y2);
60
+ ctx.moveTo(T_AXIS.x1, T_AXIS.y);
61
+ ctx.lineTo(T_AXIS.x2, T_AXIS.y);
62
+ ctx.stroke();
63
+ for (const [[tx, ty], [ax, ay], [bx, by]] of ARROWHEADS) {
64
+ ctx.beginPath();
65
+ ctx.moveTo(tx, ty);
66
+ ctx.lineTo(ax, ay);
67
+ ctx.lineTo(bx, by);
68
+ ctx.closePath();
69
+ ctx.fill();
70
+ }
71
+
72
+ // Uppercase legend (centre-anchored, alphabetic baseline, letter-spaced).
73
+ const hasSpacing = 'letterSpacing' in ctx;
74
+ const legend = (l: { text: string; x: number; y: number; size: number; color: string }) => {
75
+ ctx.fillStyle = l.color;
76
+ ctx.font = `600 ${l.size}px ${FONT_FAMILY}`;
77
+ ctx.textAlign = 'center';
78
+ ctx.textBaseline = 'alphabetic';
79
+ if (hasSpacing) ctx.letterSpacing = `${LABEL_LETTER_SPACING}px`;
80
+ ctx.fillText(l.text, l.x, l.y);
81
+ if (hasSpacing) ctx.letterSpacing = '0px';
82
+ };
83
+
84
+ // ── Liminal (green) ─────────────────────────────────────────────────
85
+ if (model.showLiminal) {
86
+ ctx.strokeStyle = COLORS.liminal;
87
+ ctx.lineWidth = LIMINAL_WIDTH;
88
+ ctx.stroke(new Path2D(LIMINAL_PATH));
89
+ legend(LABELS.liminal);
90
+ }
91
+
92
+ // ── Volatile (red) ──────────────────────────────────────────────────
93
+ if (model.showVolatile) {
94
+ ctx.strokeStyle = COLORS.volatile;
95
+ ctx.lineWidth = VOLATILE_WIDTH;
96
+ ctx.stroke(new Path2D(VOLATILE_PATH));
97
+ legend(LABELS.volatile);
98
+ }
99
+
100
+ // ── Counter-factual (dark) ──────────────────────────────────────────
101
+ if (model.showCounterfactual) {
102
+ ctx.strokeStyle = COLORS.counterfactual;
103
+ ctx.lineWidth = COUNTERFACTUAL_WIDTH;
104
+ ctx.stroke(new Path2D(COUNTERFACTUAL_PATH));
105
+ legend(LABELS.counterfactual);
106
+ }
107
+
108
+ // ── Italic e / t axis letters ───────────────────────────────────────
109
+ if (model.showAxisLabels) {
110
+ ctx.fillStyle = COLORS.axisLabel;
111
+ ctx.font = `italic 700 ${AXIS_LABELS.size}px Georgia, serif`;
112
+ ctx.textAlign = 'left';
113
+ ctx.textBaseline = 'alphabetic';
114
+ ctx.fillText(AXIS_LABELS.e.text, AXIS_LABELS.e.x, AXIS_LABELS.e.y);
115
+ ctx.fillText(AXIS_LABELS.t.text, AXIS_LABELS.t.x, AXIS_LABELS.t.y);
116
+ }
117
+ };
118
+
119
+ export const EstuarineRendererExtension = ElementRendererExtension(
120
+ 'estuarine',
121
+ estuarine
122
+ );
@@ -1,32 +1,32 @@
1
- import type { EstuarineElementModel } from '@formicoidea/labre-core/model';
2
- import {
3
- GfxElementModelView,
4
- GfxViewInteractionExtension,
5
- } from '@formicoidea/labre-core/std/gfx';
6
-
7
- /**
8
- * View for the Estuarine background. Registering it ensures `gfx.view.get(model)`
9
- * returns a view (required so move / select interactions work).
10
- */
11
- export class EstuarineView extends GfxElementModelView<EstuarineElementModel> {
12
- static override type: string = 'estuarine';
13
- }
14
-
15
- /**
16
- * Resize gating: the resize handles are hidden unless `model.resizeEnabled` is
17
- * true (toggled from the toolbar). Moving / selecting stays available.
18
- */
19
- export const EstuarineInteraction = GfxViewInteractionExtension<EstuarineView>(
20
- EstuarineView.type,
21
- {
22
- handleResize({ model }) {
23
- return {
24
- beforeResize({ set }) {
25
- if (!model.resizeEnabled) {
26
- set({ allowedHandlers: [] });
27
- }
28
- },
29
- };
30
- },
31
- }
32
- );
1
+ import type { EstuarineElementModel } from '@formicoidea/labre-core/model';
2
+ import {
3
+ GfxElementModelView,
4
+ GfxViewInteractionExtension,
5
+ } from '@formicoidea/labre-core/std/gfx';
6
+
7
+ /**
8
+ * View for the Estuarine background. Registering it ensures `gfx.view.get(model)`
9
+ * returns a view (required so move / select interactions work).
10
+ */
11
+ export class EstuarineView extends GfxElementModelView<EstuarineElementModel> {
12
+ static override type: string = 'estuarine';
13
+ }
14
+
15
+ /**
16
+ * Resize gating: the resize handles are hidden unless `model.resizeEnabled` is
17
+ * true (toggled from the toolbar). Moving / selecting stays available.
18
+ */
19
+ export const EstuarineInteraction = GfxViewInteractionExtension<EstuarineView>(
20
+ EstuarineView.type,
21
+ {
22
+ handleResize({ model }) {
23
+ return {
24
+ beforeResize({ set }) {
25
+ if (!model.resizeEnabled) {
26
+ set({ allowedHandlers: [] });
27
+ }
28
+ },
29
+ };
30
+ },
31
+ }
32
+ );
@@ -1,65 +1,65 @@
1
- import { EdgelessCRUDIdentifier } from '@formicoidea/labre-core/blocks/surface';
2
- import { EstuarineElementModel } from '@formicoidea/labre-core/model';
3
- import {
4
- type ToolbarContext,
5
- type ToolbarModuleConfig,
6
- ToolbarModuleExtension,
7
- } from '@formicoidea/labre-core/shared/services';
8
- import { BlockFlavourIdentifier } from '@formicoidea/labre-core/std';
9
- import { html, type TemplateResult } from 'lit';
10
-
11
- const ResizeIcon = html`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5H5v4M15 19h4v-4" /><path d="M5 5l6 6M19 19l-6-6" /></svg>`;
12
- // All curve icons use currentColor so the toolbar can grey them when inactive;
13
- // they are distinguished by shape (wave / arc / hooked curve).
14
- const LiminalIcon = html`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M3 13c3-6 6 4 9 0s6-6 9 0" /></svg>`;
15
- const VolatileIcon = html`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M7 4a9 9 0 0 1 0 18" /></svg>`;
16
- const CounterfactualIcon = html`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 7c7 0 11 4 12 14" /></svg>`;
17
- const AxisIcon = html`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3v18M6 12h15" /><path d="M3 6l3-3 3 3M18 9l3 3-3 3" /></svg>`;
18
-
19
- type EstuarineToggleProp =
20
- | 'resizeEnabled'
21
- | 'showLiminal'
22
- | 'showVolatile'
23
- | 'showCounterfactual'
24
- | 'showAxisLabels';
25
-
26
- function booleanToggle(
27
- id: string,
28
- tooltip: string,
29
- icon: TemplateResult,
30
- prop: EstuarineToggleProp
31
- ) {
32
- return {
33
- id,
34
- tooltip,
35
- icon,
36
- active(ctx: ToolbarContext) {
37
- const models = ctx.getSurfaceModelsByType(EstuarineElementModel);
38
- return models.length > 0 && models.every(model => model[prop]);
39
- },
40
- run(ctx: ToolbarContext) {
41
- const models = ctx.getSurfaceModelsByType(EstuarineElementModel);
42
- if (!models.length) return;
43
- const enable = !models.every(model => model[prop]);
44
- ctx.std.store.captureSync();
45
- const crud = ctx.std.get(EdgelessCRUDIdentifier);
46
- for (const model of models) crud.updateElement(model.id, { [prop]: enable });
47
- },
48
- };
49
- }
50
-
51
- export const estuarineToolbarConfig = {
52
- actions: [
53
- booleanToggle('a.toggle-resize', 'Enable / lock resizing', ResizeIcon, 'resizeEnabled'),
54
- booleanToggle('b.toggle-liminal', 'Show / hide the Liminal line', LiminalIcon, 'showLiminal'),
55
- booleanToggle('c.toggle-volatile', 'Show / hide the Volatile line', VolatileIcon, 'showVolatile'),
56
- booleanToggle('d.toggle-counterfactual', 'Show / hide the Counter-factual line', CounterfactualIcon, 'showCounterfactual'),
57
- booleanToggle('e.toggle-axis-labels', 'Show / hide axis labels (e / t)', AxisIcon, 'showAxisLabels'),
58
- ],
59
- when: ctx => ctx.getSurfaceModelsByType(EstuarineElementModel).length > 0,
60
- } as const satisfies ToolbarModuleConfig;
61
-
62
- export const estuarineToolbarExtension = ToolbarModuleExtension({
63
- id: BlockFlavourIdentifier('affine:surface:estuarine'),
64
- config: estuarineToolbarConfig,
65
- });
1
+ import { EdgelessCRUDIdentifier } from '@formicoidea/labre-core/blocks/surface';
2
+ import { EstuarineElementModel } from '@formicoidea/labre-core/model';
3
+ import {
4
+ type ToolbarContext,
5
+ type ToolbarModuleConfig,
6
+ ToolbarModuleExtension,
7
+ } from '@formicoidea/labre-core/shared/services';
8
+ import { BlockFlavourIdentifier } from '@formicoidea/labre-core/std';
9
+ import { html, type TemplateResult } from 'lit';
10
+
11
+ const ResizeIcon = html`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5H5v4M15 19h4v-4" /><path d="M5 5l6 6M19 19l-6-6" /></svg>`;
12
+ // All curve icons use currentColor so the toolbar can grey them when inactive;
13
+ // they are distinguished by shape (wave / arc / hooked curve).
14
+ const LiminalIcon = html`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M3 13c3-6 6 4 9 0s6-6 9 0" /></svg>`;
15
+ const VolatileIcon = html`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M7 4a9 9 0 0 1 0 18" /></svg>`;
16
+ const CounterfactualIcon = html`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 7c7 0 11 4 12 14" /></svg>`;
17
+ const AxisIcon = html`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3v18M6 12h15" /><path d="M3 6l3-3 3 3M18 9l3 3-3 3" /></svg>`;
18
+
19
+ type EstuarineToggleProp =
20
+ | 'resizeEnabled'
21
+ | 'showLiminal'
22
+ | 'showVolatile'
23
+ | 'showCounterfactual'
24
+ | 'showAxisLabels';
25
+
26
+ function booleanToggle(
27
+ id: string,
28
+ tooltip: string,
29
+ icon: TemplateResult,
30
+ prop: EstuarineToggleProp
31
+ ) {
32
+ return {
33
+ id,
34
+ tooltip,
35
+ icon,
36
+ active(ctx: ToolbarContext) {
37
+ const models = ctx.getSurfaceModelsByType(EstuarineElementModel);
38
+ return models.length > 0 && models.every(model => model[prop]);
39
+ },
40
+ run(ctx: ToolbarContext) {
41
+ const models = ctx.getSurfaceModelsByType(EstuarineElementModel);
42
+ if (!models.length) return;
43
+ const enable = !models.every(model => model[prop]);
44
+ ctx.std.store.captureSync();
45
+ const crud = ctx.std.get(EdgelessCRUDIdentifier);
46
+ for (const model of models) crud.updateElement(model.id, { [prop]: enable });
47
+ },
48
+ };
49
+ }
50
+
51
+ export const estuarineToolbarConfig = {
52
+ actions: [
53
+ booleanToggle('a.toggle-resize', 'Enable / lock resizing', ResizeIcon, 'resizeEnabled'),
54
+ booleanToggle('b.toggle-liminal', 'Show / hide the Liminal line', LiminalIcon, 'showLiminal'),
55
+ booleanToggle('c.toggle-volatile', 'Show / hide the Volatile line', VolatileIcon, 'showVolatile'),
56
+ booleanToggle('d.toggle-counterfactual', 'Show / hide the Counter-factual line', CounterfactualIcon, 'showCounterfactual'),
57
+ booleanToggle('e.toggle-axis-labels', 'Show / hide axis labels (e / t)', AxisIcon, 'showAxisLabels'),
58
+ ],
59
+ when: ctx => ctx.getSurfaceModelsByType(EstuarineElementModel).length > 0,
60
+ } as const satisfies ToolbarModuleConfig;
61
+
62
+ export const estuarineToolbarExtension = ToolbarModuleExtension({
63
+ id: BlockFlavourIdentifier('affine:surface:estuarine'),
64
+ config: estuarineToolbarConfig,
65
+ });