@formicoidea/labre-framework-edgy 0.31.0 → 0.33.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.
Files changed (48) hide show
  1. package/dist/actions.d.ts +39 -0
  2. package/dist/actions.js +193 -0
  3. package/dist/board-renderer.d.ts +12 -0
  4. package/dist/board-renderer.js +28 -0
  5. package/dist/board-view.d.ts +11 -0
  6. package/dist/board-view.js +20 -0
  7. package/dist/commands.d.ts +4 -0
  8. package/dist/commands.js +103 -0
  9. package/dist/consts.d.ts +35 -0
  10. package/dist/consts.js +46 -0
  11. package/dist/descriptor.d.ts +8 -3
  12. package/dist/descriptor.js +6 -3
  13. package/dist/element-renderer.js +24 -13
  14. package/dist/element-view.js +9 -3
  15. package/dist/index.d.ts +2 -1
  16. package/dist/index.js +2 -1
  17. package/dist/label-layout.js +8 -2
  18. package/dist/legend.d.ts +2 -0
  19. package/dist/legend.js +109 -0
  20. package/dist/metamodel.d.ts +96 -0
  21. package/dist/metamodel.js +128 -0
  22. package/dist/nudges.d.ts +26 -0
  23. package/dist/nudges.js +54 -0
  24. package/dist/profiles.d.ts +2 -0
  25. package/dist/profiles.js +66 -0
  26. package/dist/relation-resolver.d.ts +32 -0
  27. package/dist/relation-resolver.js +101 -0
  28. package/dist/relation.d.ts +142 -0
  29. package/dist/relation.js +188 -0
  30. package/dist/roles.d.ts +108 -0
  31. package/dist/roles.js +182 -0
  32. package/dist/rules.d.ts +43 -0
  33. package/dist/rules.js +153 -0
  34. package/dist/templates/index.d.ts +22 -1
  35. package/dist/templates/index.js +303 -52
  36. package/dist/toolbar/config.d.ts +33 -0
  37. package/dist/toolbar/config.js +82 -15
  38. package/dist/toolbar/edgy-menu.d.ts +7 -25
  39. package/dist/toolbar/edgy-menu.js +7 -186
  40. package/dist/toolbar/edgy-senior-button.js +8 -2
  41. package/dist/toolbar/icons.d.ts +12 -0
  42. package/dist/toolbar/icons.js +31 -0
  43. package/dist/toolbar/senior-tool.js +1 -0
  44. package/dist/translations.d.ts +24 -0
  45. package/dist/translations.js +29 -0
  46. package/dist/view.d.ts +18 -0
  47. package/dist/view.js +95 -8
  48. package/package.json +6 -3
@@ -13,7 +13,40 @@ export declare const edgyToolbarConfig: {
13
13
  icon: TemplateResult;
14
14
  active(ctx: ToolbarContext): boolean;
15
15
  run(ctx: ToolbarContext): void;
16
+ }, {
17
+ id: string;
18
+ tooltip: string;
19
+ icon: TemplateResult;
20
+ active(ctx: ToolbarContext): boolean;
21
+ run(ctx: ToolbarContext): void;
22
+ }, {
23
+ id: string;
24
+ tooltip: string;
25
+ icon: TemplateResult<1>;
26
+ run(ctx: ToolbarContext): void;
16
27
  }];
17
28
  readonly when: (ctx: ToolbarContext) => boolean;
18
29
  };
19
30
  export declare const edgyToolbarExtension: import("@formicoidea/labre-core/store").ExtensionType;
31
+ export declare const edgyBoardToolbarConfig: {
32
+ readonly actions: [{
33
+ id: string;
34
+ tooltip: string;
35
+ icon: TemplateResult;
36
+ active(ctx: ToolbarContext): boolean;
37
+ run(ctx: ToolbarContext): void;
38
+ }, {
39
+ id: string;
40
+ tooltip: string;
41
+ icon: TemplateResult;
42
+ active(ctx: ToolbarContext): boolean;
43
+ run(ctx: ToolbarContext): void;
44
+ }, {
45
+ id: string;
46
+ tooltip: string;
47
+ icon: TemplateResult<1>;
48
+ run(ctx: ToolbarContext): void;
49
+ }];
50
+ readonly when: (ctx: ToolbarContext) => boolean;
51
+ };
52
+ export declare const edgyBoardToolbarExtension: import("@formicoidea/labre-core/store").ExtensionType;
@@ -1,8 +1,10 @@
1
1
  import { EdgelessCRUDIdentifier } from '@formicoidea/labre-core/blocks/surface';
2
- import { EdgyFacetsElementModel } from '@formicoidea/labre-core/model';
3
- import { ToolbarModuleExtension, } from '@formicoidea/labre-core/shared/services';
2
+ import { createAutoLegend, dddLegendIcon } from '@formicoidea/labre-ddd-shared';
3
+ import { EdgyBoardElementModel, EdgyFacetsElementModel, } from '@formicoidea/labre-core/model';
4
+ import { TelemetryProvider, ToolbarModuleExtension, } from '@formicoidea/labre-core/shared/services';
4
5
  import { BlockFlavourIdentifier } from '@formicoidea/labre-core/std';
5
6
  import { html } from 'lit';
7
+ import { EDGY_AUTO_LEGEND } from '../legend.js';
6
8
  const ResizeIcon = html `<svg
7
9
  width="24"
8
10
  height="24"
@@ -30,37 +32,90 @@ const LabelsIcon = html `<svg
30
32
  <path d="M3 8.5l6-4.5 12 0 0 16-12 0-6-4.5z" />
31
33
  <circle cx="8" cy="12" r="1.4" />
32
34
  </svg>`;
35
+ /** Spot with rays — enable / disable the hover spotlight. */
36
+ const SpotlightIcon = html `<svg
37
+ width="24"
38
+ height="24"
39
+ viewBox="0 0 24 24"
40
+ fill="none"
41
+ stroke="currentColor"
42
+ stroke-width="1.6"
43
+ stroke-linecap="round"
44
+ >
45
+ <circle cx="12" cy="12" r="3.4" />
46
+ <path
47
+ d="M12 4v2.5M12 17.5V20M4 12h2.5M17.5 12H20M6.3 6.3l1.8 1.8M15.9 15.9l1.7 1.7M17.7 6.3l-1.8 1.8M8.1 15.9l-1.7 1.7"
48
+ />
49
+ </svg>`;
33
50
  /**
34
- * Build a toolbar toggle that flips a boolean flag on every selected facets
35
- * diagram: `active` reflects the current state, `run` flips it (with an undo
36
- * checkpoint).
51
+ * Build a toolbar toggle that flips a boolean flag on every selected element
52
+ * of the given class: `active` reflects the current state, `run` flips it
53
+ * (with an undo checkpoint).
37
54
  */
38
- function booleanToggle(id, tooltip, icon, prop) {
55
+ function booleanToggle(Model, id, tooltip, icon, prop) {
56
+ const models = (ctx) => ctx.getSurfaceModelsByType(Model);
39
57
  return {
40
58
  id,
41
59
  tooltip,
42
60
  icon,
43
61
  active(ctx) {
44
- const models = ctx.getSurfaceModelsByType(EdgyFacetsElementModel);
45
- return models.length > 0 && models.every(model => model[prop]);
62
+ const all = models(ctx);
63
+ return all.length > 0 && all.every(model => model[prop]);
46
64
  },
47
65
  run(ctx) {
48
- const models = ctx.getSurfaceModelsByType(EdgyFacetsElementModel);
49
- if (!models.length)
66
+ const all = models(ctx);
67
+ if (!all.length)
50
68
  return;
51
- const enable = !models.every(model => model[prop]);
69
+ const enable = !all.every(model => model[prop]);
52
70
  ctx.std.store.captureSync();
53
71
  const crud = ctx.std.get(EdgelessCRUDIdentifier);
54
- for (const model of models) {
55
- crud.updateElement(model.id, { [prop]: enable });
72
+ for (const model of all) {
73
+ crud.updateElement(model.id, {
74
+ [prop]: enable,
75
+ });
56
76
  }
57
77
  },
58
78
  };
59
79
  }
80
+ /**
81
+ * The legend action, shared by the two EDGY backgrounds: both frame the same
82
+ * notation, so both answer the same question — "what is actually drawn here" —
83
+ * with the same table ({@link EDGY_AUTO_LEGEND}) and the same box.
84
+ *
85
+ * Registered ALWAYS-ON (`EdgyRenderViewExtension`) with the toggles it sits
86
+ * next to: a legend is real, editable elements written into the document, so
87
+ * generating one is authoring, not tooling a flag may take away
88
+ * (`docs/adr/0009`).
89
+ */
90
+ function legendAction(Model, id) {
91
+ return {
92
+ id,
93
+ tooltip: 'Generate the legend (notation present)',
94
+ icon: dddLegendIcon,
95
+ run(ctx) {
96
+ const background = ctx.getSurfaceModelsByType(Model)[0];
97
+ if (!background)
98
+ return;
99
+ createAutoLegend(ctx.std, background, EDGY_AUTO_LEGEND);
100
+ ctx.std.getOptional(TelemetryProvider)?.track('FrameworkLegendCreated', {
101
+ // The WIRE value from `frameworks.ts` (`telemetryKey`), which for EDGY
102
+ // happens to be the module id itself. Same field set as Wardley's and
103
+ // the three DDD legend buttons, so the four are comparable.
104
+ framework: 'edgy',
105
+ element: 'legend',
106
+ page: 'whiteboard editor',
107
+ segment: 'element toolbar',
108
+ module: 'edgy toolbar',
109
+ });
110
+ },
111
+ };
112
+ }
60
113
  export const edgyToolbarConfig = {
61
114
  actions: [
62
- booleanToggle('a.toggle-resize', 'Enable / lock resizing', ResizeIcon, 'resizeEnabled'),
63
- booleanToggle('b.toggle-labels', 'Show / hide facet labels', LabelsIcon, 'showLabels'),
115
+ booleanToggle(EdgyFacetsElementModel, 'a.toggle-resize', 'Enable / lock resizing', ResizeIcon, 'resizeEnabled'),
116
+ booleanToggle(EdgyFacetsElementModel, 'b.toggle-labels', 'Show / hide facet labels', LabelsIcon, 'showLabels'),
117
+ booleanToggle(EdgyFacetsElementModel, 'c.toggle-spotlight', 'Enable / disable hover spotlight', SpotlightIcon, 'spotlightEnabled'),
118
+ legendAction(EdgyFacetsElementModel, 'd.legend'),
64
119
  ],
65
120
  when: ctx => ctx.getSurfaceModelsByType(EdgyFacetsElementModel).length > 0,
66
121
  };
@@ -68,3 +123,15 @@ export const edgyToolbarExtension = ToolbarModuleExtension({
68
123
  id: BlockFlavourIdentifier('affine:surface:edgy'),
69
124
  config: edgyToolbarConfig,
70
125
  });
126
+ export const edgyBoardToolbarConfig = {
127
+ actions: [
128
+ booleanToggle(EdgyBoardElementModel, 'a.toggle-resize', 'Enable / lock resizing', ResizeIcon, 'resizeEnabled'),
129
+ booleanToggle(EdgyBoardElementModel, 'b.toggle-spotlight', 'Enable / disable hover spotlight', SpotlightIcon, 'spotlightEnabled'),
130
+ legendAction(EdgyBoardElementModel, 'c.legend'),
131
+ ],
132
+ when: ctx => ctx.getSurfaceModelsByType(EdgyBoardElementModel).length > 0,
133
+ };
134
+ export const edgyBoardToolbarExtension = ToolbarModuleExtension({
135
+ id: BlockFlavourIdentifier('affine:surface:edgyBoard'),
136
+ config: edgyBoardToolbarConfig,
137
+ });
@@ -1,30 +1,12 @@
1
1
  import { EmptyTool } from '@formicoidea/labre-core/gfx/pointer';
2
- import { LitElement } from 'lit';
3
- declare const EdgelessEdgyMenu_base: typeof LitElement & import("@formicoidea/labre-core/_pkgs/global/utils").Constructor<import("@formicoidea/labre-core/_pkgs/affine-widget-edgeless-toolbar").EdgelessToolbarToolClass>;
2
+ import { EdgelessCommandMenu } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
4
3
  /**
5
- * The popover above the toolbar for the EDGY toolbox. Items create the facets
6
- * diagram (the on-click Venn) and the four base-element prefab shapes — all
7
- * native shapes so they stay editable.
4
+ * The popover above the toolbar for the EDGY toolbox. Since PF3 it declares
5
+ * nothing: {@link EdgelessCommandMenu} renders `edgyCommands` for the
6
+ * `senior-menu` surface, and the same seven artefacts are now reachable from
7
+ * Settings › Shortcuts, which never saw them before (`docs/adr/0008`).
8
8
  */
9
- export declare class EdgelessEdgyMenu extends EdgelessEdgyMenu_base {
10
- static styles: import("lit").CSSResult;
9
+ export declare class EdgelessEdgyMenu extends EdgelessCommandMenu {
10
+ protected owner: "edgy";
11
11
  type: typeof EmptyTool;
12
- /** Create the Enterprise Design Facets diagram centred on the viewport. */
13
- private _createFacets;
14
- /** Add a native free-text label (Inter), used for the People node. */
15
- private _addLabel;
16
- private _group;
17
- /** Shared props for an EDGY node shape. */
18
- private _baseShapeProps;
19
- /** Create a box base element (outcome / object / activity) with inner text. */
20
- private _createBox;
21
- /**
22
- * Create the People base element: an (invisible) ellipse decorated with the
23
- * person glyph by the renderer, plus a native text label below, grouped.
24
- */
25
- private _createPeople;
26
- private _finish;
27
- private _track;
28
- render(): import("lit-html").TemplateResult<1>;
29
12
  }
30
- export {};
@@ -1,194 +1,15 @@
1
- import { DefaultTool } from '@formicoidea/labre-core/blocks/surface';
2
- import { createGroupCommand } from '@formicoidea/labre-core/gfx/group';
3
1
  import { EmptyTool } from '@formicoidea/labre-core/gfx/pointer';
4
- import { FontFamily, ShapeStyle } from '@formicoidea/labre-core/model';
5
- import { TelemetryProvider } from '@formicoidea/labre-core/shared/services';
6
- import { EdgelessToolbarToolMixin } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
7
- import { Bound } from '@formicoidea/labre-core/global/gfx';
8
- import { css, html, LitElement } from 'lit';
9
- import { REF_H, REF_W } from '../consts.js';
10
- import { ACTIVITY_VERTICES, INNER_FONT_SIZE, LABEL_FONT_SIZE, LABEL_GAP, NODE_FILL, NODE_LABEL, NODE_SIZE, NODE_STROKE, NODE_STROKE_WIDTH, OUTCOME_RADIUS, } from '../node/consts.js';
11
- import { edgyActivityIcon, edgyFacetsIcon, edgyObjectIcon, edgyOutcomeIcon, edgyPeopleIcon, } from './icons.js';
12
- /** Default facets-diagram size (REF aspect, scaled up so it reads on canvas). */
13
- const FACETS_SCALE = 1.5;
14
- /** Height of the native People free-text label. */
15
- const LABEL_H = LABEL_FONT_SIZE + 8;
2
+ import { EdgelessCommandMenu } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
16
3
  /**
17
- * The popover above the toolbar for the EDGY toolbox. Items create the facets
18
- * diagram (the on-click Venn) and the four base-element prefab shapes — all
19
- * native shapes so they stay editable.
4
+ * The popover above the toolbar for the EDGY toolbox. Since PF3 it declares
5
+ * nothing: {@link EdgelessCommandMenu} renders `edgyCommands` for the
6
+ * `senior-menu` surface, and the same seven artefacts are now reachable from
7
+ * Settings › Shortcuts, which never saw them before (`docs/adr/0008`).
20
8
  */
21
- export class EdgelessEdgyMenu extends EdgelessToolbarToolMixin(LitElement) {
9
+ export class EdgelessEdgyMenu extends EdgelessCommandMenu {
22
10
  constructor() {
23
11
  super(...arguments);
12
+ this.owner = 'edgy';
24
13
  this.type = EmptyTool;
25
14
  }
26
- static { this.styles = css `
27
- :host {
28
- display: flex;
29
- z-index: -1;
30
- justify-content: center;
31
- }
32
- .menu-content {
33
- display: flex;
34
- align-items: center;
35
- justify-content: center;
36
- }
37
- .button-group-container {
38
- display: flex;
39
- align-items: center;
40
- gap: 14px;
41
- fill: var(--affine-icon-color);
42
- }
43
- .button-group-container svg {
44
- width: 24px;
45
- height: 24px;
46
- }
47
- `; }
48
- /** Create the Enterprise Design Facets diagram centred on the viewport. */
49
- _createFacets() {
50
- const { gfx } = this;
51
- if (!gfx.surface)
52
- return;
53
- const width = REF_W * FACETS_SCALE;
54
- const height = REF_H * FACETS_SCALE;
55
- const { centerX, centerY } = gfx.viewport;
56
- const id = gfx.surface.addElement({
57
- type: 'edgy',
58
- xywh: new Bound(centerX - width / 2, centerY - height / 2, width, height).serialize(),
59
- });
60
- this._track('facets');
61
- this._finish(id);
62
- }
63
- /** Add a native free-text label (Inter), used for the People node. */
64
- _addLabel(surface, text, x, y) {
65
- return surface.addElement({
66
- type: 'text',
67
- text,
68
- fontFamily: FontFamily.Inter,
69
- fontSize: LABEL_FONT_SIZE,
70
- color: NODE_STROKE,
71
- textAlign: 'center',
72
- xywh: new Bound(x, y, 120, LABEL_H).serialize(),
73
- });
74
- }
75
- _group(ids) {
76
- const [, result] = this.edgeless.std.command.exec(createGroupCommand, {
77
- elements: ids,
78
- });
79
- return result.groupId || ids[0];
80
- }
81
- /** Shared props for an EDGY node shape. */
82
- _baseShapeProps(kind) {
83
- return {
84
- type: 'edgyNode',
85
- kind,
86
- filled: true,
87
- fillColor: NODE_FILL,
88
- strokeColor: NODE_STROKE,
89
- shapeStyle: ShapeStyle.General,
90
- roughness: 0,
91
- };
92
- }
93
- /** Create a box base element (outcome / object / activity) with inner text. */
94
- _createBox(kind) {
95
- const surface = this.gfx.surface;
96
- if (!surface)
97
- return;
98
- const { w, h } = NODE_SIZE[kind];
99
- const { centerX: cx, centerY: cy } = this.gfx.viewport;
100
- const shapeType = kind === 'activity' ? 'polygon' : 'rect';
101
- const id = surface.addElement({
102
- ...this._baseShapeProps(kind),
103
- shapeType,
104
- strokeWidth: NODE_STROKE_WIDTH,
105
- radius: kind === 'outcome' ? OUTCOME_RADIUS : 0,
106
- vertices: kind === 'activity' ? ACTIVITY_VERTICES : null,
107
- text: NODE_LABEL[kind],
108
- color: NODE_STROKE,
109
- fontFamily: FontFamily.Inter,
110
- fontSize: INNER_FONT_SIZE,
111
- textAlign: 'center',
112
- xywh: new Bound(cx - w / 2, cy - h / 2, w, h).serialize(),
113
- });
114
- this._track(`node:${kind}`);
115
- this._finish(id);
116
- }
117
- /**
118
- * Create the People base element: an (invisible) ellipse decorated with the
119
- * person glyph by the renderer, plus a native text label below, grouped.
120
- */
121
- _createPeople() {
122
- const surface = this.gfx.surface;
123
- if (!surface)
124
- return;
125
- const { w, h } = NODE_SIZE.people;
126
- const { centerX: cx, centerY: cy } = this.gfx.viewport;
127
- const nodeId = surface.addElement({
128
- ...this._baseShapeProps('people'),
129
- shapeType: 'ellipse',
130
- // No visible outline — People is just the glyph; the ellipse is the bound.
131
- strokeWidth: 0,
132
- xywh: new Bound(cx - w / 2, cy - h / 2, w, h).serialize(),
133
- });
134
- const labelId = this._addLabel(surface, NODE_LABEL.people, cx - 60, cy + h / 2 + LABEL_GAP);
135
- this._track('node:people');
136
- this._finish(this._group([nodeId, labelId]));
137
- }
138
- _finish(id) {
139
- const { gfx } = this;
140
- gfx.doc.captureSync();
141
- gfx.tool.setTool(DefaultTool);
142
- gfx.selection.set({ elements: [id], editing: false });
143
- // Keep the palette open (native sub-menu behaviour).
144
- }
145
- _track(element) {
146
- this.edgeless.std.getOptional(TelemetryProvider)?.track('FrameworkElementAdded', {
147
- framework: 'edgy',
148
- element,
149
- page: 'whiteboard editor',
150
- segment: 'edgy toolbox',
151
- module: 'edgy menu',
152
- });
153
- }
154
- render() {
155
- return html `
156
- <edgeless-slide-menu>
157
- <div class="menu-content">
158
- <div class="button-group-container">
159
- <edgeless-tool-icon-button
160
- .tooltip=${'Enterprise Design facets'}
161
- @click=${this._createFacets}
162
- >
163
- ${edgyFacetsIcon}
164
- </edgeless-tool-icon-button>
165
- <edgeless-tool-icon-button
166
- .tooltip=${'People'}
167
- @click=${this._createPeople}
168
- >
169
- ${edgyPeopleIcon}
170
- </edgeless-tool-icon-button>
171
- <edgeless-tool-icon-button
172
- .tooltip=${'Outcome'}
173
- @click=${() => this._createBox('outcome')}
174
- >
175
- ${edgyOutcomeIcon}
176
- </edgeless-tool-icon-button>
177
- <edgeless-tool-icon-button
178
- .tooltip=${'Object'}
179
- @click=${() => this._createBox('object')}
180
- >
181
- ${edgyObjectIcon}
182
- </edgeless-tool-icon-button>
183
- <edgeless-tool-icon-button
184
- .tooltip=${'Activity'}
185
- @click=${() => this._createBox('activity')}
186
- >
187
- ${edgyActivityIcon}
188
- </edgeless-tool-icon-button>
189
- </div>
190
- </div>
191
- </edgeless-slide-menu>
192
- `;
193
- }
194
15
  }
@@ -1,5 +1,6 @@
1
1
  import { DefaultTool } from '@formicoidea/labre-core/blocks/surface';
2
2
  import { EmptyTool } from '@formicoidea/labre-core/gfx/pointer';
3
+ import { translateKey } from '@formicoidea/labre-core/shared/services';
3
4
  import { EdgelessToolbarToolMixin } from '@formicoidea/labre-core/widgets/edgeless-toolbar';
4
5
  import { SignalWatcher } from '@formicoidea/labre-core/global/lit';
5
6
  import { css, html, LitElement } from 'lit';
@@ -44,7 +45,10 @@ export class EdgelessEdgySeniorButton extends EdgelessToolbarToolMixin(SignalWat
44
45
  translate: var(--active-x, 0) var(--active-y, 0);
45
46
  rotate: var(--active-r, -2deg);
46
47
  scale: var(--active-s, 1);
47
- transition: transform 0.3s ease, translate 0.3s ease, rotate 0.3s ease,
48
+ transition:
49
+ transform 0.3s ease,
50
+ translate 0.3s ease,
51
+ rotate 0.3s ease,
48
52
  scale 0.3s ease;
49
53
  }
50
54
  .edgy-card svg {
@@ -71,7 +75,9 @@ export class EdgelessEdgySeniorButton extends EdgelessToolbarToolMixin(SignalWat
71
75
  render() {
72
76
  return html `<edgeless-toolbar-button
73
77
  class="edgy-button"
74
- .tooltip=${this.popper ? '' : 'EDGY'}
78
+ .tooltip=${this.popper
79
+ ? ''
80
+ : translateKey(this.edgeless.std, 'com.labre.framework.edgy', 'EDGY')}
75
81
  .tooltipOffset=${4}
76
82
  .active=${!!this.popper}
77
83
  @click=${this._toggleMenu}
@@ -2,11 +2,23 @@
2
2
  export declare const edgyToolbarIcon: import("lit-html").TemplateResult<2>;
3
3
  /** Menu icon — the facets diagram (colored mini Venn). */
4
4
  export declare const edgyFacetsIcon: import("lit-html").TemplateResult<2>;
5
+ /** Menu icon — the dynamic diagram: mini Venn + three connected white shapes. */
6
+ export declare const edgyDynamicIcon: import("lit-html").TemplateResult<2>;
7
+ /** Menu icon — the blank board: rounded rect + connected facet-colored shapes. */
8
+ export declare const edgyBoardIcon: import("lit-html").TemplateResult<2>;
5
9
  /** People — person glyph (official Icon-People), uses currentColor. */
6
10
  export declare const edgyPeopleIcon: import("lit-html").TemplateResult<2>;
7
11
  /** Outcome — lightly rounded rectangle. */
8
12
  export declare const edgyOutcomeIcon: import("lit-html").TemplateResult<2>;
9
13
  /** Object — plain rectangle. */
10
14
  export declare const edgyObjectIcon: import("lit-html").TemplateResult<2>;
15
+ /**
16
+ * Relation — a bare line between two ends, with the label riding on it.
17
+ *
18
+ * No arrowhead, exactly like the 24 relations of the metamodel template: EDGY
19
+ * draws its links as plain lines and lets the verb say which way the sentence
20
+ * runs. The little box in the middle IS the verb the tool writes there.
21
+ */
22
+ export declare const edgyRelationIcon: import("lit-html").TemplateResult<2>;
11
23
  /** Activity — right-pointing chevron. */
12
24
  export declare const edgyActivityIcon: import("lit-html").TemplateResult<2>;
@@ -13,6 +13,24 @@ export const edgyFacetsIcon = svg `<svg width="24" height="24" viewBox="0 0 24 2
13
13
  <circle cx="14.5" cy="10" r="6" fill="#034cee" opacity="0.92"/>
14
14
  <circle cx="12" cy="14.5" r="6" fill="#ff0056" opacity="0.92"/>
15
15
  </svg>`;
16
+ /** Menu icon — the dynamic diagram: mini Venn + three connected white shapes. */
17
+ export const edgyDynamicIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
18
+ <circle cx="9.5" cy="10" r="6" fill="#00ea4e" opacity="0.92"/>
19
+ <circle cx="14.5" cy="10" r="6" fill="#034cee" opacity="0.92"/>
20
+ <circle cx="12" cy="14.5" r="6" fill="#ff0056" opacity="0.92"/>
21
+ <path d="M8.5 8.5 L15.5 8.5 M8.5 8.5 L12 16 M15.5 8.5 L12 16" stroke="#fff" stroke-width="1.3"/>
22
+ <rect x="6.9" y="6.9" width="3.2" height="3.2" fill="#fff"/>
23
+ <circle cx="15.5" cy="8.5" r="1.7" fill="#fff"/>
24
+ <path d="M10.4 14.9 H12.9 L14 16 L12.9 17.1 H10.4 Z" fill="#fff"/>
25
+ </svg>`;
26
+ /** Menu icon — the blank board: rounded rect + connected facet-colored shapes. */
27
+ export const edgyBoardIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
28
+ <rect x="3" y="4.5" width="18" height="15" rx="2.5" stroke="currentColor" stroke-width="1.4"/>
29
+ <path d="M8.3 9 L15.7 9 M8.3 9 L12 15.2 M15.7 9 L12 15.2" stroke="currentColor" stroke-width="1.1"/>
30
+ <rect x="6.8" y="7.5" width="3" height="3" fill="#00ea4e"/>
31
+ <circle cx="15.7" cy="9" r="1.7" fill="#034cee"/>
32
+ <path d="M10.5 14.1 H12.8 L13.9 15.2 L12.8 16.3 H10.5 Z" fill="#ff0056"/>
33
+ </svg>`;
16
34
  /** People — person glyph (official Icon-People), uses currentColor. */
17
35
  export const edgyPeopleIcon = svg `<svg width="24" height="24" viewBox="0 0 32 32" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
18
36
  <path d="m16,19c-3.308,0-6-2.692-6-6v-4c0-3.308,2.692-6,6-6s6,2.692,6,6v4c0,3.308-2.692,6-6,6Zm0-14c-2.206,0-4,1.794-4,4v4c0,2.206,1.794,4,4,4s4-1.794,4-4v-4c0-2.206-1.794-4-4-4Z"/>
@@ -26,6 +44,19 @@ export const edgyOutcomeIcon = svg `<svg width="24" height="24" viewBox="0 0 24
26
44
  export const edgyObjectIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
27
45
  <rect x="3.5" y="6.5" width="17" height="11" stroke="currentColor" stroke-width="1.6"/>
28
46
  </svg>`;
47
+ /**
48
+ * Relation — a bare line between two ends, with the label riding on it.
49
+ *
50
+ * No arrowhead, exactly like the 24 relations of the metamodel template: EDGY
51
+ * draws its links as plain lines and lets the verb say which way the sentence
52
+ * runs. The little box in the middle IS the verb the tool writes there.
53
+ */
54
+ export const edgyRelationIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
55
+ <path d="M3.5 12 H20.5" stroke="currentColor" stroke-width="1.6"/>
56
+ <circle cx="3.8" cy="12" r="1.6" fill="currentColor"/>
57
+ <circle cx="20.2" cy="12" r="1.6" fill="currentColor"/>
58
+ <rect x="8" y="8.6" width="8" height="6.8" rx="1.4" fill="var(--affine-background-primary-color, #fff)" stroke="currentColor" stroke-width="1.4"/>
59
+ </svg>`;
29
60
  /** Activity — right-pointing chevron. */
30
61
  export const edgyActivityIcon = svg `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
31
62
  <path d="M3.5 6.5 H15 L20.5 12 L15 17.5 H3.5 Z" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/>
@@ -3,6 +3,7 @@ import { html } from 'lit';
3
3
  export const edgySeniorTool = SeniorToolExtension('edgy', ({ block }) => {
4
4
  return {
5
5
  name: 'EDGY',
6
+ labelKey: 'com.labre.framework.edgy',
6
7
  content: html `<edgeless-edgy-senior-button
7
8
  .edgeless=${block}
8
9
  ></edgeless-edgy-senior-button>`,
@@ -0,0 +1,24 @@
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 EDGY can hand to `TranslationProvider.t`, derived from the
5
+ * very declarations the editor registers.
6
+ *
7
+ * Its command labels and descriptions are built from a TEMPLATE, so the
8
+ * concrete keys exist nowhere but in the declarations themselves and the core
9
+ * manifest could not restate them even if it wanted to. The same now holds for
10
+ * the roles: one key per canonical verb, derived from the metamodel, so a
11
+ * relation added there contributes its keys without anybody editing this file.
12
+ *
13
+ * That derivation is why the hand-drawn relation tool needed no line here: its
14
+ * `com.labre.commands.edgy.addRelation` and the `.description` key that carries
15
+ * its gesture sentence — the first DESCRIPTION any EDGY command has declared —
16
+ * are collected off `edgyCommands` with their English fallbacks, like every
17
+ * label before them.
18
+ *
19
+ * The contribution therefore ships WITH the framework: in the bundled
20
+ * distribution `@formicoidea/labre-framework-edgy` carries it, and a host
21
+ * composes it into its catalogue exactly as it already composes `edgyCommands`
22
+ * into the command registry. See `packages/affine/all/src/translations.ts`.
23
+ */
24
+ export declare const edgyTranslationEntries: TranslationKeyManifestEntry[];
@@ -0,0 +1,29 @@
1
+ import { collectTranslationKeys, commandTranslationEntries, mergeTranslationEntries, } from '@formicoidea/labre-core/std';
2
+ import { edgyCommands } from './commands.js';
3
+ import { EDGY_NUDGES } from './nudges.js';
4
+ import { EDGY_PROFILES } from './profiles.js';
5
+ import { EDGY_ROLES } from './roles.js';
6
+ import { EDGY_RULES } from './rules.js';
7
+ /**
8
+ * THIS framework's contribution to the translation-key manifest — every
9
+ * `com.labre.*` key EDGY can hand to `TranslationProvider.t`, derived from the
10
+ * very declarations the editor registers.
11
+ *
12
+ * Its command labels and descriptions are built from a TEMPLATE, so the
13
+ * concrete keys exist nowhere but in the declarations themselves and the core
14
+ * manifest could not restate them even if it wanted to. The same now holds for
15
+ * the roles: one key per canonical verb, derived from the metamodel, so a
16
+ * relation added there contributes its keys without anybody editing this file.
17
+ *
18
+ * That derivation is why the hand-drawn relation tool needed no line here: its
19
+ * `com.labre.commands.edgy.addRelation` and the `.description` key that carries
20
+ * its gesture sentence — the first DESCRIPTION any EDGY command has declared —
21
+ * are collected off `edgyCommands` with their English fallbacks, like every
22
+ * label before them.
23
+ *
24
+ * The contribution therefore ships WITH the framework: in the bundled
25
+ * distribution `@formicoidea/labre-framework-edgy` carries it, and a host
26
+ * composes it into its catalogue exactly as it already composes `edgyCommands`
27
+ * into the command registry. See `packages/affine/all/src/translations.ts`.
28
+ */
29
+ export const edgyTranslationEntries = mergeTranslationEntries(commandTranslationEntries(edgyCommands), collectTranslationKeys('role', EDGY_ROLES), collectTranslationKeys('rule', EDGY_RULES), collectTranslationKeys('nudge', EDGY_NUDGES), collectTranslationKeys('profile', EDGY_PROFILES));
package/dist/view.d.ts CHANGED
@@ -1,4 +1,22 @@
1
1
  import { type ViewExtensionContext, ViewExtensionProvider } from '@formicoidea/labre-core/ext-loader';
2
+ /**
3
+ * EDGY rendering — ALWAYS registered, independent of any flag. Disabling `edgy`
4
+ * hides only the creation tooling (see {@link EdgyViewExtension}); boards and
5
+ * facets already drawn must still paint, stay selectable, stay editable, keep
6
+ * their contextual toolbar and keep the dependency spotlight. See
7
+ * `docs/adr/0009`.
8
+ */
9
+ export declare class EdgyRenderViewExtension extends ViewExtensionProvider {
10
+ name: string;
11
+ setup(context: ViewExtensionContext): void;
12
+ }
13
+ /**
14
+ * EDGY creation tooling — flag-gated (`edgy`): the senior toolbar button, its
15
+ * templates category, and the validation rules, profiles and quality checklist.
16
+ * All of it is tooling: a board drawn while the flag was on keeps rendering when
17
+ * it goes off, it just stops being checked — and the profile it was put on stays
18
+ * written, unread, until the flag comes back (`docs/adr/0009`).
19
+ */
2
20
  export declare class EdgyViewExtension extends ViewExtensionProvider {
3
21
  name: string;
4
22
  effect(): void;