@formicoidea/labre-framework-wardley 0.31.0 → 0.32.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/dist/actions.d.ts +14 -18
- package/dist/actions.js +79 -38
- package/dist/audit-criteria.d.ts +31 -0
- package/dist/audit-criteria.js +90 -0
- package/dist/background.d.ts +14 -0
- package/dist/background.js +338 -0
- package/dist/commands.d.ts +5 -0
- package/dist/commands.js +190 -0
- package/dist/consts.d.ts +10 -4
- package/dist/consts.js +10 -9
- package/dist/descriptor.d.ts +8 -3
- package/dist/descriptor.js +6 -3
- package/dist/element-renderer.d.ts +8 -5
- package/dist/element-renderer.js +12 -147
- package/dist/element-view.d.ts +8 -4
- package/dist/element-view.js +30 -22
- package/dist/gradient.d.ts +6 -11
- package/dist/gradient.js +58 -47
- package/dist/index.d.ts +9 -1
- package/dist/index.js +9 -1
- package/dist/legend.js +8 -0
- package/dist/natures.d.ts +50 -0
- package/dist/natures.js +93 -0
- package/dist/nudges.d.ts +41 -0
- package/dist/nudges.js +69 -0
- package/dist/profiles.d.ts +2 -0
- package/dist/profiles.js +87 -0
- package/dist/reading.d.ts +3 -0
- package/dist/reading.js +129 -0
- package/dist/roles.d.ts +50 -0
- package/dist/roles.js +132 -0
- package/dist/rules.d.ts +2 -0
- package/dist/rules.js +270 -0
- package/dist/templates/index.js +51 -7
- package/dist/templates/maps.js +121 -17
- package/dist/toolbar/wardley-menu.d.ts +8 -15
- package/dist/toolbar/wardley-menu.js +8 -136
- package/dist/translations.d.ts +16 -0
- package/dist/translations.js +24 -0
- package/dist/view.d.ts +17 -0
- package/dist/view.js +116 -13
- package/package.json +2 -2
- package/dist/label-layout.d.ts +0 -20
- package/dist/label-layout.js +0 -72
- package/dist/shortcuts.d.ts +0 -2
- package/dist/shortcuts.js +0 -37
|
@@ -1,144 +1,16 @@
|
|
|
1
1
|
import { EmptyTool } from '@formicoidea/labre-core/gfx/pointer';
|
|
2
|
-
import {
|
|
3
|
-
import { css, html, LitElement } from 'lit';
|
|
4
|
-
import { activateWardleyConnector, createWardleyBackground, createWardleyInertia, createWardleyMarket, createWardleyNode, createWardleyPipeline, } from '../actions.js';
|
|
5
|
-
import { wardleyAnchorIcon, wardleyArrowIcon, wardleyBackgroundIcon, wardleyBenefitIcon, wardleyComponentIcon, wardleyEcosystemIcon, wardleyInertiaIcon, wardleyLinkIcon, wardleyMarketIcon, wardleyMethodIcon, wardleyEvolutionGradientIcon, wardleyOpportunityIcon, wardleyPipelineIcon, } from './icons.js';
|
|
2
|
+
import { EdgelessCommandMenu } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
|
|
6
3
|
/**
|
|
7
|
-
* The popover that opens above the toolbar for the Wardley toolbox.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* The popover that opens above the toolbar for the Wardley toolbox.
|
|
5
|
+
*
|
|
6
|
+
* Since PF3 it holds no artefact list of its own: {@link EdgelessCommandMenu}
|
|
7
|
+
* renders whatever `wardleyCommands` declares for the `senior-menu` surface, so
|
|
8
|
+
* the menu and the shortcut manifest can no longer drift (they did: 13 vs 7).
|
|
10
9
|
*/
|
|
11
|
-
export class EdgelessWardleyMenu extends
|
|
10
|
+
export class EdgelessWardleyMenu extends EdgelessCommandMenu {
|
|
12
11
|
constructor() {
|
|
13
12
|
super(...arguments);
|
|
13
|
+
this.owner = 'wardley';
|
|
14
14
|
this.type = EmptyTool;
|
|
15
|
-
this._createInertia = () => {
|
|
16
|
-
createWardleyInertia(this.gfx);
|
|
17
|
-
};
|
|
18
|
-
this._createPipeline = () => {
|
|
19
|
-
createWardleyPipeline(this.gfx);
|
|
20
|
-
};
|
|
21
|
-
this._createMarket = () => {
|
|
22
|
-
createWardleyMarket(this.gfx);
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
static { this.styles = css `
|
|
26
|
-
:host {
|
|
27
|
-
display: flex;
|
|
28
|
-
z-index: -1;
|
|
29
|
-
justify-content: center;
|
|
30
|
-
}
|
|
31
|
-
.menu-content {
|
|
32
|
-
display: flex;
|
|
33
|
-
align-items: center;
|
|
34
|
-
justify-content: center;
|
|
35
|
-
}
|
|
36
|
-
.button-group-container {
|
|
37
|
-
display: flex;
|
|
38
|
-
align-items: center;
|
|
39
|
-
gap: 14px;
|
|
40
|
-
fill: var(--affine-icon-color);
|
|
41
|
-
}
|
|
42
|
-
.button-group-container svg {
|
|
43
|
-
width: 24px;
|
|
44
|
-
height: 24px;
|
|
45
|
-
}
|
|
46
|
-
`; }
|
|
47
|
-
_createBackground(variant = 'classic') {
|
|
48
|
-
createWardleyBackground(this.gfx, variant);
|
|
49
|
-
}
|
|
50
|
-
_createNode(kind) {
|
|
51
|
-
createWardleyNode(this.gfx, kind);
|
|
52
|
-
}
|
|
53
|
-
_activateConnector(kind) {
|
|
54
|
-
activateWardleyConnector(this.gfx, kind);
|
|
55
|
-
}
|
|
56
|
-
render() {
|
|
57
|
-
return html `
|
|
58
|
-
<edgeless-slide-menu>
|
|
59
|
-
<div class="menu-content">
|
|
60
|
-
<div class="button-group-container">
|
|
61
|
-
<edgeless-tool-icon-button
|
|
62
|
-
.tooltip=${'Wardley map background'}
|
|
63
|
-
@click=${() => this._createBackground('classic')}
|
|
64
|
-
>
|
|
65
|
-
${wardleyBackgroundIcon}
|
|
66
|
-
</edgeless-tool-icon-button>
|
|
67
|
-
<edgeless-tool-icon-button
|
|
68
|
-
.tooltip=${'Opportunity background (gradient)'}
|
|
69
|
-
@click=${() => this._createBackground('opportunity')}
|
|
70
|
-
>
|
|
71
|
-
${wardleyOpportunityIcon}
|
|
72
|
-
</edgeless-tool-icon-button>
|
|
73
|
-
<edgeless-tool-icon-button
|
|
74
|
-
.tooltip=${'Benefit / Investment background (gradient)'}
|
|
75
|
-
@click=${() => this._createBackground('benefit')}
|
|
76
|
-
>
|
|
77
|
-
${wardleyBenefitIcon}
|
|
78
|
-
</edgeless-tool-icon-button>
|
|
79
|
-
<edgeless-tool-icon-button
|
|
80
|
-
.tooltip=${'Evolution background (Wardley presentation)'}
|
|
81
|
-
@click=${() => this._createBackground('evolution-gradient')}
|
|
82
|
-
>
|
|
83
|
-
${wardleyEvolutionGradientIcon}
|
|
84
|
-
</edgeless-tool-icon-button>
|
|
85
|
-
<edgeless-tool-icon-button
|
|
86
|
-
.tooltip=${'Component'}
|
|
87
|
-
@click=${() => this._createNode('component')}
|
|
88
|
-
>
|
|
89
|
-
${wardleyComponentIcon}
|
|
90
|
-
</edgeless-tool-icon-button>
|
|
91
|
-
<edgeless-tool-icon-button
|
|
92
|
-
.tooltip=${'Component + method'}
|
|
93
|
-
@click=${() => this._createNode('method')}
|
|
94
|
-
>
|
|
95
|
-
${wardleyMethodIcon}
|
|
96
|
-
</edgeless-tool-icon-button>
|
|
97
|
-
<edgeless-tool-icon-button
|
|
98
|
-
.tooltip=${'Market'}
|
|
99
|
-
@click=${this._createMarket}
|
|
100
|
-
>
|
|
101
|
-
${wardleyMarketIcon}
|
|
102
|
-
</edgeless-tool-icon-button>
|
|
103
|
-
<edgeless-tool-icon-button
|
|
104
|
-
.tooltip=${'Ecosystem'}
|
|
105
|
-
@click=${() => this._createNode('ecosystem')}
|
|
106
|
-
>
|
|
107
|
-
${wardleyEcosystemIcon}
|
|
108
|
-
</edgeless-tool-icon-button>
|
|
109
|
-
<edgeless-tool-icon-button
|
|
110
|
-
.tooltip=${'Anchor'}
|
|
111
|
-
@click=${() => this._createNode('anchor')}
|
|
112
|
-
>
|
|
113
|
-
${wardleyAnchorIcon}
|
|
114
|
-
</edgeless-tool-icon-button>
|
|
115
|
-
<edgeless-tool-icon-button
|
|
116
|
-
.tooltip=${'Pipeline'}
|
|
117
|
-
@click=${this._createPipeline}
|
|
118
|
-
>
|
|
119
|
-
${wardleyPipelineIcon}
|
|
120
|
-
</edgeless-tool-icon-button>
|
|
121
|
-
<edgeless-tool-icon-button
|
|
122
|
-
.tooltip=${'Link'}
|
|
123
|
-
@click=${() => this._activateConnector('link')}
|
|
124
|
-
>
|
|
125
|
-
${wardleyLinkIcon}
|
|
126
|
-
</edgeless-tool-icon-button>
|
|
127
|
-
<edgeless-tool-icon-button
|
|
128
|
-
.tooltip=${'Arrow (evolution)'}
|
|
129
|
-
@click=${() => this._activateConnector('arrow')}
|
|
130
|
-
>
|
|
131
|
-
${wardleyArrowIcon}
|
|
132
|
-
</edgeless-tool-icon-button>
|
|
133
|
-
<edgeless-tool-icon-button
|
|
134
|
-
.tooltip=${'Inertia'}
|
|
135
|
-
@click=${this._createInertia}
|
|
136
|
-
>
|
|
137
|
-
${wardleyInertiaIcon}
|
|
138
|
-
</edgeless-tool-icon-button>
|
|
139
|
-
</div>
|
|
140
|
-
</div>
|
|
141
|
-
</edgeless-slide-menu>
|
|
142
|
-
`;
|
|
143
15
|
}
|
|
144
16
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type TranslationKeyManifestEntry } from '@formicoidea/labre-core/std';
|
|
2
|
+
/**
|
|
3
|
+
* THIS framework's contribution to the translation-key manifest — every
|
|
4
|
+
* `com.labre.*` key Wardley can hand to `TranslationProvider.t`, derived from
|
|
5
|
+
* the very declarations the editor registers.
|
|
6
|
+
*
|
|
7
|
+
* It lives HERE, not in `@labre/affine/translations`, because the bundled
|
|
8
|
+
* distribution splits the library along exactly this line:
|
|
9
|
+
* `@formicoidea/labre-core` is the editor MINUS the frameworks, and a host that
|
|
10
|
+
* installs `@formicoidea/labre-framework-wardley` composes this export into the
|
|
11
|
+
* catalogue it builds — the same sentence that already holds for
|
|
12
|
+
* `wardleyCommands`. A manifest that named Wardley from the core side would be
|
|
13
|
+
* complete in the monorepo and silently 61 % short (107 keys of 175) in the
|
|
14
|
+
* distribution hosts actually consume.
|
|
15
|
+
*/
|
|
16
|
+
export declare const wardleyTranslationEntries: TranslationKeyManifestEntry[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { collectTranslationKeys, commandTranslationEntries, mergeTranslationEntries, } from '@formicoidea/labre-core/std';
|
|
2
|
+
import { WARDLEY_AUDIT_CRITERIA } from './audit-criteria.js';
|
|
3
|
+
import { WARDLEY_BACKGROUND } from './background.js';
|
|
4
|
+
import { wardleyCommands } from './commands.js';
|
|
5
|
+
import { WARDLEY_NUDGES } from './nudges.js';
|
|
6
|
+
import { WARDLEY_PROFILES } from './profiles.js';
|
|
7
|
+
import { WARDLEY_READING } from './reading.js';
|
|
8
|
+
import { WARDLEY_ROLES } from './roles.js';
|
|
9
|
+
import { WARDLEY_RULES } from './rules.js';
|
|
10
|
+
/**
|
|
11
|
+
* THIS framework's contribution to the translation-key manifest — every
|
|
12
|
+
* `com.labre.*` key Wardley can hand to `TranslationProvider.t`, derived from
|
|
13
|
+
* the very declarations the editor registers.
|
|
14
|
+
*
|
|
15
|
+
* It lives HERE, not in `@labre/affine/translations`, because the bundled
|
|
16
|
+
* distribution splits the library along exactly this line:
|
|
17
|
+
* `@formicoidea/labre-core` is the editor MINUS the frameworks, and a host that
|
|
18
|
+
* installs `@formicoidea/labre-framework-wardley` composes this export into the
|
|
19
|
+
* catalogue it builds — the same sentence that already holds for
|
|
20
|
+
* `wardleyCommands`. A manifest that named Wardley from the core side would be
|
|
21
|
+
* complete in the monorepo and silently 61 % short (107 keys of 175) in the
|
|
22
|
+
* distribution hosts actually consume.
|
|
23
|
+
*/
|
|
24
|
+
export const wardleyTranslationEntries = mergeTranslationEntries(commandTranslationEntries(wardleyCommands), collectTranslationKeys('role', WARDLEY_ROLES), collectTranslationKeys('background', WARDLEY_BACKGROUND), collectTranslationKeys('rule', WARDLEY_RULES), collectTranslationKeys('nudge', WARDLEY_NUDGES), collectTranslationKeys('profile', WARDLEY_PROFILES), collectTranslationKeys('audit-criterion', WARDLEY_AUDIT_CRITERIA), collectTranslationKeys('reading', WARDLEY_READING));
|
package/dist/view.d.ts
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
import { type ViewExtensionContext, ViewExtensionProvider } from '@formicoidea/labre-core/ext-loader';
|
|
2
|
+
/**
|
|
3
|
+
* Wardley rendering — ALWAYS registered, independent of any flag. Disabling
|
|
4
|
+
* `wardley` hides only the creation tooling (see {@link WardleyViewExtension});
|
|
5
|
+
* maps already drawn must still paint, stay selectable, stay editable and keep
|
|
6
|
+
* their contextual toolbar. See `docs/adr/0009`.
|
|
7
|
+
*/
|
|
8
|
+
export declare class WardleyRenderViewExtension extends ViewExtensionProvider {
|
|
9
|
+
name: string;
|
|
10
|
+
setup(context: ViewExtensionContext): void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Wardley creation tooling — flag-gated (`wardley`): the senior toolbar button,
|
|
14
|
+
* its templates category, the edgeless chords (w+c, w+l, ...) and the
|
|
15
|
+
* validation rules and profiles. Both are tooling: a map drawn while the flag
|
|
16
|
+
* was on keeps rendering when it goes off, it just stops being checked — and
|
|
17
|
+
* the profile it was put on stays written, unread, until the flag comes back.
|
|
18
|
+
*/
|
|
2
19
|
export declare class WardleyViewExtension extends ViewExtensionProvider {
|
|
3
20
|
name: string;
|
|
4
21
|
effect(): void;
|
package/dist/view.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
import { ReadingProfileExtension, tagsToolbarConfig, validationToolbarConfig, QualityNudgeExtension, ValidationProfileExtension, ValidationRuleExtension, } from '@formicoidea/labre-core/blocks/surface';
|
|
2
|
+
import { AuditCriterionExtension, ToolbarModuleExtension, UniverseTagDefsExtension, } from '@formicoidea/labre-core/shared/services';
|
|
1
3
|
import { ViewExtensionProvider, } from '@formicoidea/labre-core/ext-loader';
|
|
2
4
|
import { extendTemplateCategory } from '@formicoidea/labre-core/gfx/template';
|
|
3
|
-
import {
|
|
5
|
+
import { BlockFlavourIdentifier, CommandExtension } from '@formicoidea/labre-core/std';
|
|
6
|
+
import { RoleVocabularyExtension } from '@formicoidea/labre-core/std/gfx';
|
|
7
|
+
import { WARDLEY_AUDIT_CRITERIA } from './audit-criteria.js';
|
|
8
|
+
import { wardleyCommandIcons, wardleyCommands } from './commands.js';
|
|
4
9
|
import { effects } from './effects.js';
|
|
5
|
-
import {
|
|
10
|
+
import { WARDLEY_TAG_DEFS } from './natures.js';
|
|
11
|
+
import { WARDLEY_PROFILES } from './profiles.js';
|
|
12
|
+
import { WARDLEY_NUDGES } from './nudges.js';
|
|
13
|
+
import { WARDLEY_READING } from './reading.js';
|
|
14
|
+
import { WARDLEY_ROLES } from './roles.js';
|
|
15
|
+
import { WARDLEY_RULES } from './rules.js';
|
|
6
16
|
import { wardleyTemplateCategory } from './templates/index.js';
|
|
7
17
|
import { WardleyElementRendererExtension } from './element-renderer.js';
|
|
8
18
|
import { WardleyInteraction, WardleyView } from './element-view.js';
|
|
@@ -11,6 +21,44 @@ import { WardleyNodeView } from './node/node-view.js';
|
|
|
11
21
|
import { wardleyNodeToolbarExtension } from './toolbar/node-config.js';
|
|
12
22
|
import { wardleyToolbarExtension } from './toolbar/config.js';
|
|
13
23
|
import { wardleySeniorTool } from './toolbar/senior-tool.js';
|
|
24
|
+
/**
|
|
25
|
+
* Wardley rendering — ALWAYS registered, independent of any flag. Disabling
|
|
26
|
+
* `wardley` hides only the creation tooling (see {@link WardleyViewExtension});
|
|
27
|
+
* maps already drawn must still paint, stay selectable, stay editable and keep
|
|
28
|
+
* their contextual toolbar. See `docs/adr/0009`.
|
|
29
|
+
*/
|
|
30
|
+
export class WardleyRenderViewExtension extends ViewExtensionProvider {
|
|
31
|
+
constructor() {
|
|
32
|
+
super(...arguments);
|
|
33
|
+
this.name = 'affine-wardley-render-gfx';
|
|
34
|
+
}
|
|
35
|
+
setup(context) {
|
|
36
|
+
super.setup(context);
|
|
37
|
+
context.register(WardleyView);
|
|
38
|
+
context.register(WardleyElementRendererExtension);
|
|
39
|
+
context.register(WardleyNodeView);
|
|
40
|
+
context.register(WardleyNodeRendererExtension);
|
|
41
|
+
// The role VOCABULARY, always on. A role is written in the document, not in
|
|
42
|
+
// the tooling: the direction reveal of a typed edge, the inversion command
|
|
43
|
+
// and the toolbar entry that must not lie about one all read this, and they
|
|
44
|
+
// have to keep working on a map drawn while the flag was on and opened
|
|
45
|
+
// while it is off (`docs/adr/0009`, `docs/adr/0010`). The rules that
|
|
46
|
+
// JUDGE those roles stay in the flag-gated extension below.
|
|
47
|
+
context.register(RoleVocabularyExtension(WARDLEY_ROLES));
|
|
48
|
+
if (this.isEdgeless(context.scope)) {
|
|
49
|
+
context.register(WardleyInteraction);
|
|
50
|
+
context.register(wardleyToolbarExtension);
|
|
51
|
+
context.register(wardleyNodeToolbarExtension);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Wardley creation tooling — flag-gated (`wardley`): the senior toolbar button,
|
|
57
|
+
* its templates category, the edgeless chords (w+c, w+l, ...) and the
|
|
58
|
+
* validation rules and profiles. Both are tooling: a map drawn while the flag
|
|
59
|
+
* was on keeps rendering when it goes off, it just stops being checked — and
|
|
60
|
+
* the profile it was put on stays written, unread, until the flag comes back.
|
|
61
|
+
*/
|
|
14
62
|
export class WardleyViewExtension extends ViewExtensionProvider {
|
|
15
63
|
constructor() {
|
|
16
64
|
super(...arguments);
|
|
@@ -18,24 +66,79 @@ export class WardleyViewExtension extends ViewExtensionProvider {
|
|
|
18
66
|
}
|
|
19
67
|
effect() {
|
|
20
68
|
super.effect();
|
|
69
|
+
// Defines the senior button and its menu — tooling-only custom elements.
|
|
21
70
|
effects();
|
|
22
71
|
extendTemplateCategory(wardleyTemplateCategory);
|
|
23
72
|
}
|
|
24
73
|
setup(context) {
|
|
25
74
|
super.setup(context);
|
|
26
|
-
context.register(WardleyView);
|
|
27
|
-
context.register(WardleyElementRendererExtension);
|
|
28
|
-
context.register(WardleyNodeView);
|
|
29
|
-
context.register(WardleyNodeRendererExtension);
|
|
30
75
|
if (this.isEdgeless(context.scope)) {
|
|
31
|
-
context.register(
|
|
76
|
+
context.register(ValidationRuleExtension(WARDLEY_RULES));
|
|
77
|
+
context.register(ValidationProfileExtension(WARDLEY_PROFILES));
|
|
78
|
+
// Map quality (PF13.9): the four nudges the tool cannot judge, and
|
|
79
|
+
// nothing else — the on-demand check-up Wardley used to expose beside
|
|
80
|
+
// them was dropped on the PO recette of 02/08/2026. The engine keeps the
|
|
81
|
+
// capability (PF5.14 and its two families), Wardley simply declares no
|
|
82
|
+
// rule that uses it.
|
|
83
|
+
context.register(QualityNudgeExtension(WARDLEY_NUDGES));
|
|
84
|
+
// A1–A3, the level-3 criteria (PF14.1). Registered HERE, beside the rules
|
|
85
|
+
// and for the same reason: a criterion is tooling, so Wardley switched
|
|
86
|
+
// off contributes none and `map.audit` finds nothing to ask about — while
|
|
87
|
+
// `ai-audit` independently decides whether the command exists at all.
|
|
88
|
+
context.register(AuditCriterionExtension(WARDLEY_AUDIT_CRITERIA));
|
|
89
|
+
// The Validation dropdown on a selected map's contextual toolbar. A
|
|
90
|
+
// SECOND module on the same element, through the `custom:` flavour slot
|
|
91
|
+
// (the pattern `gfx/mindmap` uses on `custom:affine:surface:shape`):
|
|
92
|
+
// `wardleyToolbarExtension` is registered always-on because a stored map
|
|
93
|
+
// must keep its axes and labels, while choosing how hard to check it is
|
|
94
|
+
// tooling and belongs here. The config itself names no framework — it
|
|
95
|
+
// reads roles and profiles — so a second framework registers the very
|
|
96
|
+
// same object on its own flavour.
|
|
97
|
+
context.register(ToolbarModuleExtension({
|
|
98
|
+
id: BlockFlavourIdentifier('custom:affine:surface:wardley'),
|
|
99
|
+
config: validationToolbarConfig,
|
|
100
|
+
}));
|
|
101
|
+
// The four natures — Wardley's type-3 qualification (MF3, ADR 0007).
|
|
102
|
+
// Seeded on the SAME mechanism a host uses for its own taxonomy: the
|
|
103
|
+
// library ships one real pack, and a client's private extension is a
|
|
104
|
+
// second pack with another `packId` that merges with this one, with no
|
|
105
|
+
// library release. All packs must land in this one DI scope — `getAll`
|
|
106
|
+
// never merges across scopes.
|
|
107
|
+
context.register(UniverseTagDefsExtension(WARDLEY_TAG_DEFS));
|
|
108
|
+
// The qualification dropdown on the selected component's toolbar. A
|
|
109
|
+
// THIRD module on the same element, through a free `custom:` flavour
|
|
110
|
+
// slot. Generic in shape — it names no framework and builds its sections
|
|
111
|
+
// from the seeded packs — but parameterized by this framework's role
|
|
112
|
+
// vocabulary, because ADR 0007 § 2bis deliberately keeps roles out of DI
|
|
113
|
+
// and there is therefore no way to look up "which vocabulary governs this
|
|
114
|
+
// element". Registered on the NODE and on the GROUP: one click on a
|
|
115
|
+
// Wardley component selects the group that holds the circle and its
|
|
116
|
+
// label, and the role lives on the circle.
|
|
117
|
+
for (const flavour of [
|
|
118
|
+
'custom:affine:surface:wardleyNode',
|
|
119
|
+
'custom:affine:surface:group',
|
|
120
|
+
]) {
|
|
121
|
+
context.register(ToolbarModuleExtension({
|
|
122
|
+
id: BlockFlavourIdentifier(flavour),
|
|
123
|
+
config: tagsToolbarConfig(WARDLEY_ROLES),
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
// The reversed reading (MF3): what the map says about a component, on
|
|
127
|
+
// demand. One declaration — the roles, the nature tag, the dependency
|
|
128
|
+
// edge and the map's own zones, all of them already stated elsewhere in
|
|
129
|
+
// this framework — is the whole of what makes the generic engine able to
|
|
130
|
+
// read a Wardley map. The CLICK that triggers it is registered once by
|
|
131
|
+
// the surface and gated by the presence of this profile, so it goes with
|
|
132
|
+
// the flag without either side naming the other.
|
|
133
|
+
context.register(ReadingProfileExtension(WARDLEY_READING));
|
|
32
134
|
context.register(wardleySeniorTool);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
//
|
|
36
|
-
// both the wardley flag gating and the
|
|
37
|
-
// the installer is
|
|
38
|
-
|
|
135
|
+
// The 13 Wardley commands, ONE registration for both faces: the
|
|
136
|
+
// enumerable registry the sub-menu renders from, and — through
|
|
137
|
+
// `toShortcutDescriptor` — the edgeless chords (w+c, w+l, ...).
|
|
138
|
+
// Registering here inherits both the wardley flag gating and the
|
|
139
|
+
// edgeless-only availability; the keymap installer is
|
|
140
|
+
// ShortcutKeymapExtension('edgeless') in root.
|
|
141
|
+
context.register(CommandExtension(wardleyCommands, wardleyCommandIcons));
|
|
39
142
|
}
|
|
40
143
|
}
|
|
41
144
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formicoidea/labre-framework-wardley",
|
|
3
3
|
"description": "Labre wardley framework for @formicoidea/labre-core.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.32.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"author": "lajola",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"dist"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@formicoidea/labre-core": "0.
|
|
30
|
+
"@formicoidea/labre-core": "0.32.0",
|
|
31
31
|
"lit": "^3.2.0"
|
|
32
32
|
}
|
|
33
33
|
}
|
package/dist/label-layout.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { WardleyBackgroundElementModel } from '@formicoidea/labre-core/model';
|
|
2
|
-
/** The editable label fields of a Wardley background. */
|
|
3
|
-
export type WardleyLabelField = 'xAxisTitle' | 'yAxisTitle' | 'evolutionStart' | 'evolutionEnd' | 'visibilityHigh' | 'visibilityLow' | 'phase0' | 'phase1' | 'phase2' | 'phase3';
|
|
4
|
-
/** A label's hit box in element-local coordinates (axis-aligned, padded). */
|
|
5
|
-
export interface WardleyLabelHit {
|
|
6
|
-
field: WardleyLabelField;
|
|
7
|
-
minX: number;
|
|
8
|
-
minY: number;
|
|
9
|
-
maxX: number;
|
|
10
|
-
maxY: number;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Compute the clickable boxes of every *visible* Wardley label, in the
|
|
14
|
-
* element's local space. Positions are derived from the SAME constants the
|
|
15
|
-
* renderer uses (`MARGIN` / `OFFSETS` / `FONTS`), so the hit boxes track the
|
|
16
|
-
* drawn text. Boxes are padded so double-clicking is forgiving.
|
|
17
|
-
*/
|
|
18
|
-
export declare function getWardleyLabelHits(model: WardleyBackgroundElementModel, w: number, h: number): WardleyLabelHit[];
|
|
19
|
-
/** First label whose (padded) box contains the local point, or null. */
|
|
20
|
-
export declare function hitTestWardleyLabel(hits: WardleyLabelHit[], lx: number, ly: number): WardleyLabelHit | null;
|
package/dist/label-layout.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { FONTS, MARGIN, OFFSETS } from './consts.js';
|
|
2
|
-
/** Rough per-character advance — only used to size generous hit boxes. */
|
|
3
|
-
const approxTextWidth = (text, fontSize) => Math.max(fontSize, text.length * fontSize * 0.6);
|
|
4
|
-
/**
|
|
5
|
-
* Compute the clickable boxes of every *visible* Wardley label, in the
|
|
6
|
-
* element's local space. Positions are derived from the SAME constants the
|
|
7
|
-
* renderer uses (`MARGIN` / `OFFSETS` / `FONTS`), so the hit boxes track the
|
|
8
|
-
* drawn text. Boxes are padded so double-clicking is forgiving.
|
|
9
|
-
*/
|
|
10
|
-
export function getWardleyLabelHits(model, w, h) {
|
|
11
|
-
const px0 = MARGIN.left;
|
|
12
|
-
const px1 = w - MARGIN.right;
|
|
13
|
-
const py0 = MARGIN.top;
|
|
14
|
-
const py1 = h - MARGIN.bottom;
|
|
15
|
-
const ex = (r) => px0 + r * (px1 - px0);
|
|
16
|
-
const pad = 6;
|
|
17
|
-
const hits = [];
|
|
18
|
-
// Horizontal label anchored on its text baseline.
|
|
19
|
-
const addH = (field, text, fontSize, ax, baseline, align) => {
|
|
20
|
-
const tw = approxTextWidth(text, fontSize);
|
|
21
|
-
const minX = align === 'right' ? ax - tw : ax;
|
|
22
|
-
const maxX = align === 'right' ? ax : ax + tw;
|
|
23
|
-
hits.push({
|
|
24
|
-
field,
|
|
25
|
-
minX: minX - pad,
|
|
26
|
-
maxX: maxX + pad,
|
|
27
|
-
minY: baseline - fontSize - pad,
|
|
28
|
-
maxY: baseline + fontSize * 0.3 + pad,
|
|
29
|
-
});
|
|
30
|
-
};
|
|
31
|
-
// Vertical label (drawn rotated -90°), centered on (ax, ay).
|
|
32
|
-
const addV = (field, text, fontSize, ax, ay) => {
|
|
33
|
-
const tw = approxTextWidth(text, fontSize);
|
|
34
|
-
hits.push({
|
|
35
|
-
field,
|
|
36
|
-
minX: ax - fontSize - pad,
|
|
37
|
-
maxX: ax + fontSize * 0.4 + pad,
|
|
38
|
-
minY: ay - tw / 2 - pad,
|
|
39
|
-
maxY: ay + tw / 2 + pad,
|
|
40
|
-
});
|
|
41
|
-
};
|
|
42
|
-
if (model.showColumnLabels) {
|
|
43
|
-
addH('phase0', model.phase0, FONTS.phase, ex(0) + OFFSETS.phasePad, py1 + OFFSETS.phaseBaseline, 'left');
|
|
44
|
-
addH('phase1', model.phase1, FONTS.phase, ex(0.175) + OFFSETS.phasePad, py1 + OFFSETS.phaseBaseline, 'left');
|
|
45
|
-
addH('phase2', model.phase2, FONTS.phase, ex(0.4) + OFFSETS.phasePad, py1 + OFFSETS.phaseBaseline, 'left');
|
|
46
|
-
addH('phase3', model.phase3, FONTS.phase, ex(0.7) + OFFSETS.phasePad, py1 + OFFSETS.phaseBaseline, 'left');
|
|
47
|
-
}
|
|
48
|
-
if (model.showXAxis) {
|
|
49
|
-
addH('xAxisTitle', model.xAxisTitle, FONTS.axis, px1 - OFFSETS.evolutionPadRight, py1 + OFFSETS.phaseBaseline, 'right');
|
|
50
|
-
}
|
|
51
|
-
if (model.showCornerLabels) {
|
|
52
|
-
addH('evolutionStart', model.evolutionStart, FONTS.direction, px0 + OFFSETS.directionPadLeft, py0 + OFFSETS.directionTop, 'left');
|
|
53
|
-
addH('evolutionEnd', model.evolutionEnd, FONTS.direction, px1 - OFFSETS.directionPadRight, py0 + OFFSETS.directionTop, 'right');
|
|
54
|
-
}
|
|
55
|
-
if (model.showYAxis) {
|
|
56
|
-
addV('yAxisTitle', model.yAxisTitle, FONTS.axis, px0 - OFFSETS.yHug, (py0 + py1) / 2);
|
|
57
|
-
}
|
|
58
|
-
if (model.showVisibilityLabels) {
|
|
59
|
-
addV('visibilityHigh', model.visibilityHigh, FONTS.visibility, px0 - OFFSETS.yHug, py0 + OFFSETS.visibleTop);
|
|
60
|
-
addV('visibilityLow', model.visibilityLow, FONTS.visibility, px0 - OFFSETS.yHug, py1 - OFFSETS.invisibleBottom);
|
|
61
|
-
}
|
|
62
|
-
return hits;
|
|
63
|
-
}
|
|
64
|
-
/** First label whose (padded) box contains the local point, or null. */
|
|
65
|
-
export function hitTestWardleyLabel(hits, lx, ly) {
|
|
66
|
-
for (const hit of hits) {
|
|
67
|
-
if (lx >= hit.minX && lx <= hit.maxX && ly >= hit.minY && ly <= hit.maxY) {
|
|
68
|
-
return hit;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return null;
|
|
72
|
-
}
|
package/dist/shortcuts.d.ts
DELETED
package/dist/shortcuts.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { GfxControllerIdentifier } from '@formicoidea/labre-core/std/gfx';
|
|
2
|
-
import { activateWardleyConnector, createWardleyBackground, createWardleyInertia, createWardleyNode, createWardleyPipeline, WARDLEY_SHORTCUT_SOURCE, } from './actions.js';
|
|
3
|
-
/**
|
|
4
|
-
* Wardley canvas chords: press `w`, then the action key. Edgeless-scoped and
|
|
5
|
-
* registered by {@link WardleyViewExtension}, so they only exist when the
|
|
6
|
-
* edgeless editor is mounted AND the `wardley` block flag is enabled. The
|
|
7
|
-
* host can rebind or disable each id via `ShortcutOverrides`.
|
|
8
|
-
*
|
|
9
|
-
* This is the reference pattern for other frameworks: same shape with their
|
|
10
|
-
* own prefix letter, listed in `FRAMEWORK_SHORTCUT_GROUPS` (manifest) and
|
|
11
|
-
* registered via `ShortcutExtension` in their view extension (binding).
|
|
12
|
-
*/
|
|
13
|
-
const wardleyShortcut = (id, key, run) => ({
|
|
14
|
-
id: `wardley.${id}`,
|
|
15
|
-
labelKey: `com.labre.keyboardShortcuts.wardley.${id}`,
|
|
16
|
-
defaultKeys: { mac: ['w', key], other: ['w', key] },
|
|
17
|
-
scope: 'edgeless',
|
|
18
|
-
owner: 'wardley',
|
|
19
|
-
handler: std => ctx => {
|
|
20
|
-
const gfx = std.get(GfxControllerIdentifier);
|
|
21
|
-
// Never fire while editing text on the canvas.
|
|
22
|
-
if (gfx.selection.editing)
|
|
23
|
-
return false;
|
|
24
|
-
ctx.get('defaultState').event.preventDefault();
|
|
25
|
-
run(gfx);
|
|
26
|
-
return true;
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
export const wardleyShortcuts = [
|
|
30
|
-
wardleyShortcut('addComponent', 'c', gfx => createWardleyNode(gfx, 'component', WARDLEY_SHORTCUT_SOURCE)),
|
|
31
|
-
wardleyShortcut('linkTool', 'l', gfx => activateWardleyConnector(gfx, 'link', WARDLEY_SHORTCUT_SOURCE)),
|
|
32
|
-
wardleyShortcut('evolutionArrow', 'a', gfx => activateWardleyConnector(gfx, 'arrow', WARDLEY_SHORTCUT_SOURCE)),
|
|
33
|
-
wardleyShortcut('addInertia', 'i', gfx => createWardleyInertia(gfx, WARDLEY_SHORTCUT_SOURCE)),
|
|
34
|
-
wardleyShortcut('addPipeline', 'p', gfx => createWardleyPipeline(gfx, WARDLEY_SHORTCUT_SOURCE)),
|
|
35
|
-
wardleyShortcut('addMethod', 'm', gfx => createWardleyNode(gfx, 'method', WARDLEY_SHORTCUT_SOURCE)),
|
|
36
|
-
wardleyShortcut('addBackground', 'b', gfx => createWardleyBackground(gfx, 'classic', WARDLEY_SHORTCUT_SOURCE)),
|
|
37
|
-
];
|