@formicoidea/labre-framework-edgy 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 +21 -0
- package/dist/actions.js +140 -0
- package/dist/board-renderer.d.ts +12 -0
- package/dist/board-renderer.js +25 -0
- package/dist/board-view.d.ts +11 -0
- package/dist/board-view.js +20 -0
- package/dist/commands.d.ts +4 -0
- package/dist/commands.js +85 -0
- package/dist/consts.d.ts +35 -0
- package/dist/consts.js +46 -0
- package/dist/descriptor.d.ts +8 -3
- package/dist/descriptor.js +6 -3
- package/dist/element-renderer.js +19 -11
- package/dist/element-view.js +9 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/templates/index.d.ts +30 -1
- package/dist/templates/index.js +166 -18
- package/dist/toolbar/config.d.ts +23 -0
- package/dist/toolbar/config.js +44 -14
- package/dist/toolbar/edgy-menu.d.ts +7 -25
- package/dist/toolbar/edgy-menu.js +7 -186
- package/dist/toolbar/icons.d.ts +4 -0
- package/dist/toolbar/icons.js +18 -0
- package/dist/translations.d.ts +14 -0
- package/dist/translations.js +15 -0
- package/dist/view.d.ts +15 -0
- package/dist/view.js +46 -8
- package/package.json +2 -2
package/dist/templates/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { makeTemplateSnapshot, surfaceText, } from '@formicoidea/labre-core/gfx/template';
|
|
2
2
|
import { ConnectorMode, FontFamily, PointStyle, ShapeStyle, StrokeStyle, TextAlign, } from '@formicoidea/labre-core/model';
|
|
3
|
-
import {
|
|
4
|
-
import { ACTIVITY_VERTICES, INNER_FONT_SIZE, NODE_FILL, NODE_STROKE, NODE_STROKE_WIDTH, OUTCOME_RADIUS, } from '../node/consts.js';
|
|
3
|
+
import { CROP, CROP_LABELED } from '../consts.js';
|
|
4
|
+
import { ACTIVITY_VERTICES, INNER_FONT_SIZE, NODE_FILL, NODE_SIZE, NODE_STROKE, NODE_STROKE_WIDTH, OUTCOME_RADIUS, } from '../node/consts.js';
|
|
5
5
|
// EDGY facet palette (header / pale sub-card).
|
|
6
6
|
const C = {
|
|
7
7
|
identity: ['#1ec873', '#9fe6c2'],
|
|
@@ -85,6 +85,24 @@ function line(x1, y1, x2, y2, opts = {}) {
|
|
|
85
85
|
target: { position: [x2, y2] },
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Connector ATTACHED to two template elements (by key): endpoints clip to the
|
|
90
|
+
* element edges and follow moves — unlike `line()`, whose free positions are
|
|
91
|
+
* only right until the user drags something.
|
|
92
|
+
*/
|
|
93
|
+
function attach(src, dst, opts = {}) {
|
|
94
|
+
return {
|
|
95
|
+
type: 'connector',
|
|
96
|
+
mode: opts.mode ?? ConnectorMode.Straight,
|
|
97
|
+
stroke: NODE_STROKE,
|
|
98
|
+
strokeWidth: 2,
|
|
99
|
+
strokeStyle: StrokeStyle.Solid,
|
|
100
|
+
frontEndpointStyle: PointStyle.None,
|
|
101
|
+
rearEndpointStyle: opts.arrow ? PointStyle.Triangle : PointStyle.None,
|
|
102
|
+
source: { id: src },
|
|
103
|
+
target: { id: dst },
|
|
104
|
+
};
|
|
105
|
+
}
|
|
88
106
|
// ── Facets overview (six facets, sub-cards, facets/intersections) ─────
|
|
89
107
|
function facetsOverview() {
|
|
90
108
|
const out = {};
|
|
@@ -137,8 +155,8 @@ function journey() {
|
|
|
137
155
|
use1: label(258, 504, 184, 20, 'uses', { fontSize: 13, color: '#5f6368' }),
|
|
138
156
|
use2: label(518, 504, 184, 20, 'uses', { fontSize: 13, color: '#5f6368' }),
|
|
139
157
|
use3: label(778, 504, 184, 20, 'uses', { fontSize: 13, color: '#5f6368' }),
|
|
140
|
-
l1:
|
|
141
|
-
l4:
|
|
158
|
+
l1: attach('s1', 'c1'), l2: attach('s2', 'c2'), l3: attach('s3', 'c3'),
|
|
159
|
+
l4: attach('c1', 't1'), l5: attach('c2', 't2'), l6: attach('c3', 't3'),
|
|
142
160
|
};
|
|
143
161
|
}
|
|
144
162
|
// ── Service blueprint (six swimlanes) ─────────────────────────────────
|
|
@@ -162,14 +180,14 @@ function blueprint() {
|
|
|
162
180
|
csv: chev(280, 514, B, 'Customer service'), cfu: box(1010, 514, B, 'Customer follow-up'),
|
|
163
181
|
pf: chev(600, 664, B, 'Process Form'), dec: chev(900, 664, B, 'Decision [Accept|Reject]'),
|
|
164
182
|
crm: box(280, 814, B, 'CRM Application'), cms: box(600, 814, B, 'Case Management'), pay: box(900, 814, B, 'Payments System'),
|
|
165
|
-
a1:
|
|
166
|
-
a2:
|
|
167
|
-
a3:
|
|
168
|
-
a4:
|
|
169
|
-
a5:
|
|
170
|
-
a6:
|
|
171
|
-
a7:
|
|
172
|
-
a8:
|
|
183
|
+
a1: attach('af', 'sf', { arrow: true }),
|
|
184
|
+
a2: attach('sf', 'fs', { arrow: true }),
|
|
185
|
+
a3: attach('fs', 'rd', { arrow: true }),
|
|
186
|
+
a4: attach('sf', 'fh', { arrow: true }),
|
|
187
|
+
a5: attach('fh', 'csv', { arrow: true }),
|
|
188
|
+
a6: attach('pf', 'dec', { arrow: true }),
|
|
189
|
+
a7: attach('crm', 'cms', { arrow: true }),
|
|
190
|
+
a8: attach('cms', 'pay', { arrow: true }),
|
|
173
191
|
});
|
|
174
192
|
return out;
|
|
175
193
|
}
|
|
@@ -181,18 +199,147 @@ function orgChart() {
|
|
|
181
199
|
org: u(420, 40, 180, 'Organisation'),
|
|
182
200
|
a: u(120, 200, 200, 'Business Unit A'), b: u(410, 200, 200, 'Business Unit B'), c: u(700, 200, 200, 'Business Unit C'),
|
|
183
201
|
a1: u(60, 360, 170, 'Group A-1'), a2: u(260, 360, 170, 'Group A-2'), c1: u(715, 360, 170, 'Group C-1'),
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
202
|
+
// Attached orthogonal connectors: the router draws the org-chart elbows
|
|
203
|
+
// and the links follow when units are moved around.
|
|
204
|
+
e1: attach('org', 'a', { mode: ConnectorMode.Orthogonal }),
|
|
205
|
+
e2: attach('org', 'b', { mode: ConnectorMode.Orthogonal }),
|
|
206
|
+
e3: attach('org', 'c', { mode: ConnectorMode.Orthogonal }),
|
|
207
|
+
e4: attach('a', 'a1', { mode: ConnectorMode.Orthogonal }),
|
|
208
|
+
e5: attach('a', 'a2', { mode: ConnectorMode.Orthogonal }),
|
|
209
|
+
e6: attach('c', 'c1', { mode: ConnectorMode.Orthogonal }),
|
|
189
210
|
};
|
|
190
211
|
}
|
|
212
|
+
// ── EDGY dynamic (the relational metamodel, on the facets background) ──
|
|
213
|
+
/**
|
|
214
|
+
* Background scale (from REF coords to model coords): large enough that the
|
|
215
|
+
* default-size nodes breathe inside each zone. The background is cropped to
|
|
216
|
+
* the circles (`cropToCircles`), so its xywh covers CROP × DYN_SCALE.
|
|
217
|
+
*/
|
|
218
|
+
export const DYN_SCALE = 4.8;
|
|
219
|
+
/**
|
|
220
|
+
* The 24 canonical EDGY relations (source, target, verb, label position along
|
|
221
|
+
* the link) — exported for the unit tests. 7 per facet + 3 between the
|
|
222
|
+
* intersections. The optional 4th member mirrors the reference diagram's
|
|
223
|
+
* placements: verbs of intersection-outgoing links sit near the far element
|
|
224
|
+
* (`labelOffset.distance` ≈ .75), short peer links keep the middle.
|
|
225
|
+
*/
|
|
226
|
+
export const EDGY_DYNAMIC_RELATIONS = [
|
|
227
|
+
// Identity
|
|
228
|
+
['content', 'purpose', 'expresses'],
|
|
229
|
+
['content', 'story', 'conveys', 0.75],
|
|
230
|
+
['story', 'purpose', 'contextualises', 0.8],
|
|
231
|
+
['organisation', 'purpose', 'pursues', 0.8],
|
|
232
|
+
['organisation', 'story', 'authors', 0.6],
|
|
233
|
+
['brand', 'purpose', 'represents', 0.8],
|
|
234
|
+
['brand', 'story', 'evokes', 0.65],
|
|
235
|
+
// Architecture
|
|
236
|
+
['organisation', 'process', 'performs', 0.8],
|
|
237
|
+
['process', 'capability', 'realises', 0.75],
|
|
238
|
+
['process', 'asset', 'requires'],
|
|
239
|
+
['capability', 'asset', 'requires', 0.75],
|
|
240
|
+
['organisation', 'capability', 'has', 0.6],
|
|
241
|
+
['product', 'capability', 'requires', 0.75],
|
|
242
|
+
['process', 'product', 'creates', 0.65],
|
|
243
|
+
// Experience
|
|
244
|
+
['task', 'journey', 'is part of', 0.6],
|
|
245
|
+
['task', 'channel', 'uses', 0.6],
|
|
246
|
+
['journey', 'channel', 'traverses', 0.6],
|
|
247
|
+
['product', 'task', 'serves', 0.9],
|
|
248
|
+
['product', 'journey', 'features in', 0.8],
|
|
249
|
+
['brand', 'task', 'supports', 0.8],
|
|
250
|
+
['brand', 'journey', 'appears in', 0.9],
|
|
251
|
+
// Intersections
|
|
252
|
+
['organisation', 'brand', 'builds', 0.85],
|
|
253
|
+
['organisation', 'product', 'makes', 0.65],
|
|
254
|
+
['product', 'brand', 'embodies', 0.8],
|
|
255
|
+
];
|
|
256
|
+
/**
|
|
257
|
+
* The 12 elements, centred coordinates in REFERENCE coords (the fixed space
|
|
258
|
+
* of consts.ts — the same space as `VENN`), laid out like the reference
|
|
259
|
+
* "elements & relations" diagram: aligned top row, Story/Capability flanks,
|
|
260
|
+
* Brand/Product astride the white centre, Task/Journey/Channel triangle.
|
|
261
|
+
* Exported (with {@link dynToModel}) for the containment test.
|
|
262
|
+
*/
|
|
263
|
+
/** Official pastel fills per facet (the `pictograms/Shape-*.svg` colors). */
|
|
264
|
+
const PASTEL = {
|
|
265
|
+
identity: '#80ffb7',
|
|
266
|
+
architecture: '#a6c0ff',
|
|
267
|
+
experience: '#ff99bd',
|
|
268
|
+
organisation: '#80eaff',
|
|
269
|
+
brand: '#ffd580',
|
|
270
|
+
product: '#e599ff',
|
|
271
|
+
};
|
|
272
|
+
export const EDGY_DYNAMIC_NODES = {
|
|
273
|
+
content: { kind: 'object', cx: 237.5, cy: 100, fill: PASTEL.identity },
|
|
274
|
+
purpose: { kind: 'outcome', cx: 282.5, cy: 100, fill: PASTEL.identity },
|
|
275
|
+
organisation: { kind: 'object', cx: 340, cy: 100, w: 175, fill: PASTEL.organisation },
|
|
276
|
+
process: { kind: 'activity', cx: 397.5, cy: 100, fill: PASTEL.architecture },
|
|
277
|
+
asset: { kind: 'object', cx: 442.5, cy: 100, fill: PASTEL.architecture },
|
|
278
|
+
story: { kind: 'activity', cx: 255, cy: 152.5, fill: PASTEL.identity },
|
|
279
|
+
capability: { kind: 'outcome', cx: 425, cy: 152.5, w: 150, fill: PASTEL.architecture },
|
|
280
|
+
brand: { kind: 'object', cx: 280, cy: 195, fill: PASTEL.brand },
|
|
281
|
+
product: { kind: 'object', cx: 400, cy: 195, fill: PASTEL.product },
|
|
282
|
+
task: { kind: 'outcome', cx: 310, cy: 257.5, fill: PASTEL.experience },
|
|
283
|
+
journey: { kind: 'activity', cx: 370, cy: 257.5, fill: PASTEL.experience },
|
|
284
|
+
channel: { kind: 'object', cx: 340, cy: 297.5, fill: PASTEL.experience },
|
|
285
|
+
};
|
|
286
|
+
/**
|
|
287
|
+
* Reference coords → template model coords: the background element sits at
|
|
288
|
+
* (0,0) and renders the cropped circles box, so a reference point maps to
|
|
289
|
+
* `(p - CROP.origin) × DYN_SCALE`.
|
|
290
|
+
*/
|
|
291
|
+
export function dynToModel(refX, refY) {
|
|
292
|
+
return [(refX - CROP.x) * DYN_SCALE, (refY - CROP.y) * DYN_SCALE];
|
|
293
|
+
}
|
|
294
|
+
function dynamic() {
|
|
295
|
+
const out = {
|
|
296
|
+
bg: {
|
|
297
|
+
type: 'edgy',
|
|
298
|
+
showLabels: false,
|
|
299
|
+
showPictos: false,
|
|
300
|
+
cropToCircles: true,
|
|
301
|
+
xywh: `[0,0,${CROP.w * DYN_SCALE},${CROP.h * DYN_SCALE}]`,
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
for (const [key, { kind, cx, cy, w, fill }] of Object.entries(EDGY_DYNAMIC_NODES)) {
|
|
305
|
+
const nw = w ?? NODE_SIZE[kind].w;
|
|
306
|
+
const nh = NODE_SIZE[kind].h;
|
|
307
|
+
const [mx, my] = dynToModel(cx, cy);
|
|
308
|
+
const name = key.charAt(0).toUpperCase() + key.slice(1);
|
|
309
|
+
out[key] = enode(kind, mx - nw / 2, my - nh / 2, nw, nh, {
|
|
310
|
+
text: name,
|
|
311
|
+
fill,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
EDGY_DYNAMIC_RELATIONS.forEach(([src, dst, verb, t], i) => {
|
|
315
|
+
out[`rel${i}`] = {
|
|
316
|
+
type: 'connector',
|
|
317
|
+
mode: ConnectorMode.Straight,
|
|
318
|
+
stroke: NODE_STROKE,
|
|
319
|
+
strokeWidth: 2,
|
|
320
|
+
strokeStyle: StrokeStyle.Solid,
|
|
321
|
+
frontEndpointStyle: PointStyle.None,
|
|
322
|
+
rearEndpointStyle: PointStyle.None,
|
|
323
|
+
source: { id: src },
|
|
324
|
+
target: { id: dst },
|
|
325
|
+
// Native connector label: the verb travels with the link. The x/y are
|
|
326
|
+
// re-centred on the path at the first layout, but the w/h ARE the label
|
|
327
|
+
// box — size it to the verb so the text lays out on one line. The
|
|
328
|
+
// distance slides the verb along the link like the reference diagram.
|
|
329
|
+
text: surfaceText(verb),
|
|
330
|
+
labelXYWH: [0, 0, verb.length * 9 + 24, 26],
|
|
331
|
+
labelOffset: { distance: t ?? 0.5 },
|
|
332
|
+
};
|
|
333
|
+
});
|
|
334
|
+
return out;
|
|
335
|
+
}
|
|
191
336
|
const single = (el) => ({ a: el });
|
|
192
337
|
const ATTRS = 'width="100%" height="100%" viewBox="0 0 135 80" xmlns="http://www.w3.org/2000/svg"';
|
|
193
338
|
function tpl(name, preview, elements) {
|
|
194
339
|
return { name, type: 'template', preview, content: makeTemplateSnapshot(elements, name) };
|
|
195
340
|
}
|
|
341
|
+
/** Exported for direct insertion from the EDGY senior toolbar menu. */
|
|
342
|
+
export const edgyDynamicTemplate = tpl('EDGY dynamic', `<svg ${ATTRS}><circle cx="55" cy="34" r="18" fill="#00ea4e" opacity="0.9"/><circle cx="80" cy="34" r="18" fill="#034cee" opacity="0.9"/><circle cx="67" cy="54" r="18" fill="#ff0056" opacity="0.9"/><path d="M55 30 H80 M56 31 L66 52 M79 31 L69 52" stroke="#fff" stroke-width="2"/><rect x="51" y="26" width="8" height="8" fill="#fff"/><circle cx="80" cy="30" r="4" fill="#fff"/><path d="M62 49 h6 l3 3 -3 3 h-6 z" fill="#fff"/></svg>`, dynamic());
|
|
196
343
|
export const edgyTemplateCategory = {
|
|
197
344
|
name: 'EDGY',
|
|
198
345
|
templates: [
|
|
@@ -200,7 +347,8 @@ export const edgyTemplateCategory = {
|
|
|
200
347
|
tpl('Customer journey', `<svg ${ATTRS} fill="none"><path d="M20 24 H110 L122 40 L110 56 H20 Z" fill="#f3a3c0"/><rect x="26" y="30" width="22" height="20" fill="none" stroke="#fff"/><rect x="54" y="30" width="22" height="20" fill="none" stroke="#fff"/><rect x="82" y="30" width="22" height="20" fill="none" stroke="#fff"/></svg>`, journey()),
|
|
201
348
|
tpl('Service blueprint', `<svg ${ATTRS} fill="none"><rect x="8" y="14" width="119" height="16" fill="#fbd5e0"/><rect x="8" y="32" width="119" height="34" fill="#d4e9f8"/><rect x="20" y="18" width="22" height="9" fill="#f5246e" opacity="0.5"/><rect x="20" y="40" width="22" height="9" fill="#2f6ff0" opacity="0.4"/><rect x="60" y="40" width="22" height="9" fill="#2f6ff0" opacity="0.4"/></svg>`, blueprint()),
|
|
202
349
|
tpl('Organisation chart', `<svg ${ATTRS} fill="none"><rect x="52" y="12" width="32" height="14" rx="2" fill="#4fd0ea"/><rect x="14" y="38" width="32" height="14" rx="2" fill="#4fd0ea"/><rect x="52" y="38" width="32" height="14" rx="2" fill="#4fd0ea"/><rect x="90" y="38" width="32" height="14" rx="2" fill="#4fd0ea"/><path d="M68 26 V32 M30 32 H106 M30 32 V38 M68 32 V38 M106 32 V38" stroke="#262626"/></svg>`, orgChart()),
|
|
203
|
-
tpl('Facets diagram', `<svg ${ATTRS}><circle cx="55" cy="34" r="18" fill="#00ea4e" opacity="0.9"/><circle cx="80" cy="34" r="18" fill="#034cee" opacity="0.9"/><circle cx="67" cy="54" r="18" fill="#ff0056" opacity="0.9"/></svg>`, single({ type: 'edgy', xywh: `[0,0,${
|
|
350
|
+
tpl('Facets diagram', `<svg ${ATTRS}><circle cx="55" cy="34" r="18" fill="#00ea4e" opacity="0.9"/><circle cx="80" cy="34" r="18" fill="#034cee" opacity="0.9"/><circle cx="67" cy="54" r="18" fill="#ff0056" opacity="0.9"/></svg>`, single({ type: 'edgy', cropToCircles: true, xywh: `[0,0,${CROP_LABELED.w * 1.5},${CROP_LABELED.h * 1.5}]` })),
|
|
351
|
+
edgyDynamicTemplate,
|
|
204
352
|
tpl('People', `<svg ${ATTRS} fill="#262626"><circle cx="67" cy="32" r="9" fill="none" stroke="#262626" stroke-width="2.4"/><path d="M50 60 a17 17 0 0 1 34 0" fill="none" stroke="#262626" stroke-width="2.4"/></svg>`, { n: enode('people', 0, 0, 64, 64), l: label(-28, 70, 120, 24, 'People', { fontSize: 16 }) }),
|
|
205
353
|
tpl('Outcome', `<svg ${ATTRS} fill="none"><rect x="20" y="24" width="95" height="34" rx="6" stroke="#262626" stroke-width="2"/></svg>`, single(enode('outcome', 0, 0, 130, 80, { text: 'Outcome' }))),
|
|
206
354
|
tpl('Object', `<svg ${ATTRS} fill="none"><rect x="20" y="24" width="95" height="34" stroke="#262626" stroke-width="2"/></svg>`, single(enode('object', 0, 0, 130, 80, { text: 'Object' }))),
|
package/dist/toolbar/config.d.ts
CHANGED
|
@@ -13,7 +13,30 @@ 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;
|
|
16
22
|
}];
|
|
17
23
|
readonly when: (ctx: ToolbarContext) => boolean;
|
|
18
24
|
};
|
|
19
25
|
export declare const edgyToolbarExtension: import("@formicoidea/labre-core/store").ExtensionType;
|
|
26
|
+
export declare const edgyBoardToolbarConfig: {
|
|
27
|
+
readonly actions: [{
|
|
28
|
+
id: string;
|
|
29
|
+
tooltip: string;
|
|
30
|
+
icon: TemplateResult;
|
|
31
|
+
active(ctx: ToolbarContext): boolean;
|
|
32
|
+
run(ctx: ToolbarContext): void;
|
|
33
|
+
}, {
|
|
34
|
+
id: string;
|
|
35
|
+
tooltip: string;
|
|
36
|
+
icon: TemplateResult;
|
|
37
|
+
active(ctx: ToolbarContext): boolean;
|
|
38
|
+
run(ctx: ToolbarContext): void;
|
|
39
|
+
}];
|
|
40
|
+
readonly when: (ctx: ToolbarContext) => boolean;
|
|
41
|
+
};
|
|
42
|
+
export declare const edgyBoardToolbarExtension: import("@formicoidea/labre-core/store").ExtensionType;
|
package/dist/toolbar/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EdgelessCRUDIdentifier } from '@formicoidea/labre-core/blocks/surface';
|
|
2
|
-
import { EdgyFacetsElementModel } from '@formicoidea/labre-core/model';
|
|
2
|
+
import { EdgyBoardElementModel, EdgyFacetsElementModel, } from '@formicoidea/labre-core/model';
|
|
3
3
|
import { ToolbarModuleExtension, } from '@formicoidea/labre-core/shared/services';
|
|
4
4
|
import { BlockFlavourIdentifier } from '@formicoidea/labre-core/std';
|
|
5
5
|
import { html } from 'lit';
|
|
@@ -30,37 +30,56 @@ const LabelsIcon = html `<svg
|
|
|
30
30
|
<path d="M3 8.5l6-4.5 12 0 0 16-12 0-6-4.5z" />
|
|
31
31
|
<circle cx="8" cy="12" r="1.4" />
|
|
32
32
|
</svg>`;
|
|
33
|
+
/** Spot with rays — enable / disable the hover spotlight. */
|
|
34
|
+
const SpotlightIcon = html `<svg
|
|
35
|
+
width="24"
|
|
36
|
+
height="24"
|
|
37
|
+
viewBox="0 0 24 24"
|
|
38
|
+
fill="none"
|
|
39
|
+
stroke="currentColor"
|
|
40
|
+
stroke-width="1.6"
|
|
41
|
+
stroke-linecap="round"
|
|
42
|
+
>
|
|
43
|
+
<circle cx="12" cy="12" r="3.4" />
|
|
44
|
+
<path
|
|
45
|
+
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"
|
|
46
|
+
/>
|
|
47
|
+
</svg>`;
|
|
33
48
|
/**
|
|
34
|
-
* Build a toolbar toggle that flips a boolean flag on every selected
|
|
35
|
-
*
|
|
36
|
-
* checkpoint).
|
|
49
|
+
* Build a toolbar toggle that flips a boolean flag on every selected element
|
|
50
|
+
* of the given class: `active` reflects the current state, `run` flips it
|
|
51
|
+
* (with an undo checkpoint).
|
|
37
52
|
*/
|
|
38
|
-
function booleanToggle(id, tooltip, icon, prop) {
|
|
53
|
+
function booleanToggle(Model, id, tooltip, icon, prop) {
|
|
54
|
+
const models = (ctx) => ctx.getSurfaceModelsByType(Model);
|
|
39
55
|
return {
|
|
40
56
|
id,
|
|
41
57
|
tooltip,
|
|
42
58
|
icon,
|
|
43
59
|
active(ctx) {
|
|
44
|
-
const
|
|
45
|
-
return
|
|
60
|
+
const all = models(ctx);
|
|
61
|
+
return all.length > 0 && all.every(model => model[prop]);
|
|
46
62
|
},
|
|
47
63
|
run(ctx) {
|
|
48
|
-
const
|
|
49
|
-
if (!
|
|
64
|
+
const all = models(ctx);
|
|
65
|
+
if (!all.length)
|
|
50
66
|
return;
|
|
51
|
-
const enable = !
|
|
67
|
+
const enable = !all.every(model => model[prop]);
|
|
52
68
|
ctx.std.store.captureSync();
|
|
53
69
|
const crud = ctx.std.get(EdgelessCRUDIdentifier);
|
|
54
|
-
for (const model of
|
|
55
|
-
crud.updateElement(model.id, {
|
|
70
|
+
for (const model of all) {
|
|
71
|
+
crud.updateElement(model.id, {
|
|
72
|
+
[prop]: enable,
|
|
73
|
+
});
|
|
56
74
|
}
|
|
57
75
|
},
|
|
58
76
|
};
|
|
59
77
|
}
|
|
60
78
|
export const edgyToolbarConfig = {
|
|
61
79
|
actions: [
|
|
62
|
-
booleanToggle('a.toggle-resize', 'Enable / lock resizing', ResizeIcon, 'resizeEnabled'),
|
|
63
|
-
booleanToggle('b.toggle-labels', 'Show / hide facet labels', LabelsIcon, 'showLabels'),
|
|
80
|
+
booleanToggle(EdgyFacetsElementModel, 'a.toggle-resize', 'Enable / lock resizing', ResizeIcon, 'resizeEnabled'),
|
|
81
|
+
booleanToggle(EdgyFacetsElementModel, 'b.toggle-labels', 'Show / hide facet labels', LabelsIcon, 'showLabels'),
|
|
82
|
+
booleanToggle(EdgyFacetsElementModel, 'c.toggle-spotlight', 'Enable / disable hover spotlight', SpotlightIcon, 'spotlightEnabled'),
|
|
64
83
|
],
|
|
65
84
|
when: ctx => ctx.getSurfaceModelsByType(EdgyFacetsElementModel).length > 0,
|
|
66
85
|
};
|
|
@@ -68,3 +87,14 @@ export const edgyToolbarExtension = ToolbarModuleExtension({
|
|
|
68
87
|
id: BlockFlavourIdentifier('affine:surface:edgy'),
|
|
69
88
|
config: edgyToolbarConfig,
|
|
70
89
|
});
|
|
90
|
+
export const edgyBoardToolbarConfig = {
|
|
91
|
+
actions: [
|
|
92
|
+
booleanToggle(EdgyBoardElementModel, 'a.toggle-resize', 'Enable / lock resizing', ResizeIcon, 'resizeEnabled'),
|
|
93
|
+
booleanToggle(EdgyBoardElementModel, 'b.toggle-spotlight', 'Enable / disable hover spotlight', SpotlightIcon, 'spotlightEnabled'),
|
|
94
|
+
],
|
|
95
|
+
when: ctx => ctx.getSurfaceModelsByType(EdgyBoardElementModel).length > 0,
|
|
96
|
+
};
|
|
97
|
+
export const edgyBoardToolbarExtension = ToolbarModuleExtension({
|
|
98
|
+
id: BlockFlavourIdentifier('affine:surface:edgyBoard'),
|
|
99
|
+
config: edgyBoardToolbarConfig,
|
|
100
|
+
});
|
|
@@ -1,30 +1,12 @@
|
|
|
1
1
|
import { EmptyTool } from '@formicoidea/labre-core/gfx/pointer';
|
|
2
|
-
import {
|
|
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.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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
|
|
10
|
-
|
|
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 {
|
|
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.
|
|
18
|
-
*
|
|
19
|
-
*
|
|
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
|
|
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
|
}
|
package/dist/toolbar/icons.d.ts
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
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. */
|
package/dist/toolbar/icons.js
CHANGED
|
@@ -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"/>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type TranslationKeyManifestEntry } from '@formicoidea/labre-core/std';
|
|
2
|
+
/**
|
|
3
|
+
* THIS framework's contribution to the translation-key manifest.
|
|
4
|
+
*
|
|
5
|
+
* Its command labels and descriptions are built from a TEMPLATE, so the
|
|
6
|
+
* concrete keys exist nowhere but in the declarations themselves and the
|
|
7
|
+
* core manifest could not restate them even if it wanted to. The
|
|
8
|
+
* contribution therefore ships WITH the framework: in the bundled
|
|
9
|
+
* distribution `@formicoidea/labre-framework-edgy` carries it, and a host
|
|
10
|
+
* composes it into its catalogue exactly as it already composes
|
|
11
|
+
* `edgyCommands` into the command registry. See
|
|
12
|
+
* `packages/affine/all/src/translations.ts`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const edgyTranslationEntries: TranslationKeyManifestEntry[];
|