@formicoidea/labre-core 0.35.0 → 0.37.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/_pkgs/affine-block-surface/extensions/reading-toolbar.js +12 -12
- package/dist/_pkgs/affine-block-surface/extensions/reading-widget.d.ts +25 -13
- package/dist/_pkgs/affine-block-surface/extensions/reading-widget.js +58 -24
- package/dist/_pkgs/affine-block-surface/extensions/reading.d.ts +83 -7
- package/dist/_pkgs/affine-block-surface/extensions/reading.js +41 -14
- package/dist/_pkgs/affine-block-surface/extensions/tags-toolbar.js +7 -0
- package/dist/_pkgs/affine-components/highlight-dropdown-menu/highlight-duotone-icon.js +8 -8
- package/dist/_pkgs/affine-components/highlight-dropdown-menu/text-duotone-icon.js +11 -11
- package/dist/_pkgs/affine-components/icons/text.js +426 -426
- package/dist/_pkgs/affine-components/toolbar/menu-button.js +13 -0
- package/dist/_pkgs/affine-gfx-shape/element-view.d.ts +42 -1
- package/dist/_pkgs/affine-gfx-shape/element-view.js +54 -0
- package/dist/_pkgs/affine-gfx-shape/toolbar/index.d.ts +1 -0
- package/dist/_pkgs/affine-gfx-shape/toolbar/index.js +1 -0
- package/dist/_pkgs/affine-gfx-shape/toolbar/palette-color-action.d.ts +25 -0
- package/dist/_pkgs/affine-gfx-shape/toolbar/palette-color-action.js +123 -0
- package/dist/_pkgs/affine-model/elements/wardley/node.d.ts +21 -6
- package/dist/_pkgs/affine-model/elements/wardley/node.js +20 -5
- package/dist/_pkgs/affine-shared/services/telemetry-service/block-lifecycle-watcher.d.ts +16 -1
- package/dist/_pkgs/affine-shared/services/telemetry-service/block-lifecycle-watcher.js +27 -2
- package/dist/_pkgs/affine-widget-edgeless-auto-connect/index.js +124 -124
- package/dist/_pkgs/affine-widget-edgeless-zoom-toolbar/index.js +26 -26
- package/dist/_pkgs/affine-widget-keyboard-toolbar/icons.js +98 -98
- package/dist/_pkgs/affine-widget-page-dragging-area/index.js +10 -10
- package/dist/_pkgs/affine-widget-viewport-overlay/index.js +13 -13
- package/dist/_pkgs/data-view/core/group-by/renderer/boolean-group.js +11 -11
- package/dist/_pkgs/data-view/core/utils/menu-title.js +17 -17
- package/dist/_pkgs/data-view/view-presets/table/pc-virtual/group/top/group-title.js +18 -18
- package/dist/_pkgs/std/extension/command-registry.d.ts +15 -8
- package/dist/extensions/command-telemetry.js +4 -0
- package/dist/translations.js +8 -2
- package/package.json +1 -1
|
@@ -58,18 +58,18 @@ const READ_LABEL_FALLBACK = 'Read this component';
|
|
|
58
58
|
* Drawn inline like its neighbours: this package does not depend on
|
|
59
59
|
* `@blocksuite/icons` and one glyph is not worth a new dependency.
|
|
60
60
|
*/
|
|
61
|
-
const ReadIcon = html `<svg
|
|
62
|
-
width="20"
|
|
63
|
-
height="20"
|
|
64
|
-
viewBox="0 0 24 24"
|
|
65
|
-
fill="none"
|
|
66
|
-
stroke="currentColor"
|
|
67
|
-
stroke-width="2"
|
|
68
|
-
stroke-linecap="round"
|
|
69
|
-
stroke-linejoin="round"
|
|
70
|
-
>
|
|
71
|
-
<path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6-10-6-10-6z" />
|
|
72
|
-
<circle cx="12" cy="12" r="3" />
|
|
61
|
+
const ReadIcon = html `<svg
|
|
62
|
+
width="20"
|
|
63
|
+
height="20"
|
|
64
|
+
viewBox="0 0 24 24"
|
|
65
|
+
fill="none"
|
|
66
|
+
stroke="currentColor"
|
|
67
|
+
stroke-width="2"
|
|
68
|
+
stroke-linecap="round"
|
|
69
|
+
stroke-linejoin="round"
|
|
70
|
+
>
|
|
71
|
+
<path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6-10-6-10-6z" />
|
|
72
|
+
<circle cx="12" cy="12" r="3" />
|
|
73
73
|
</svg>`;
|
|
74
74
|
/** The command this module drives. Spelled once. */
|
|
75
75
|
const ELEMENT_READ_ID = 'element.read';
|
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
import { nothing, type TemplateResult } from 'lit';
|
|
2
2
|
import { EditorAnchoredPanel } from './editor-anchored-panel.js';
|
|
3
3
|
export declare const READING_PROPOSAL_WIDGET = "affine-reading-proposal-widget";
|
|
4
|
-
/**
|
|
5
|
-
* How the panel names each side of a parent-child relation, keyed under
|
|
6
|
-
* `com.labre.reading.relations.`. Chrome, and only chrome.
|
|
7
|
-
*
|
|
8
|
-
* Exported because it is DATA: the translation-key manifest walks it rather
|
|
9
|
-
* than restating the two wordings, which a source scan could not check — the
|
|
10
|
-
* key is built as a template literal and the fallback reaches `translateKey`
|
|
11
|
-
* through a local helper.
|
|
12
|
-
*/
|
|
13
|
-
export declare const RELATION_SIDE_FALLBACK: {
|
|
14
|
-
readonly consumers: "Consumers (above)";
|
|
15
|
-
readonly suppliers: "Suppliers (below)";
|
|
16
|
-
};
|
|
17
4
|
/**
|
|
18
5
|
* **The proposal panel** — what the tool reads of one component, offered for
|
|
19
6
|
* confirmation (MF3).
|
|
@@ -94,6 +81,14 @@ export declare class ReadingProposalWidget extends EditorAnchoredPanel {
|
|
|
94
81
|
* host's word into the document.
|
|
95
82
|
*/
|
|
96
83
|
private _renderNature;
|
|
84
|
+
/**
|
|
85
|
+
* The typed edges touching the subject, grouped by side and named with the
|
|
86
|
+
* FRAMEWORK's own two words (`ReadingRelationDef.sides`).
|
|
87
|
+
*
|
|
88
|
+
* The `data-testid` keeps the shape it shipped with — `reading-consumers`,
|
|
89
|
+
* `reading-suppliers` — because it names the SIDE, which is generic, and not
|
|
90
|
+
* the wording, which is now the framework's.
|
|
91
|
+
*/
|
|
97
92
|
private _renderRelations;
|
|
98
93
|
/**
|
|
99
94
|
* **Value flow** — the same typed edges as the relations above, said the way
|
|
@@ -110,8 +105,25 @@ export declare class ReadingProposalWidget extends EditorAnchoredPanel {
|
|
|
110
105
|
* "Value flows up from X to Y"; a host that translates
|
|
111
106
|
* `com.labre.reading.value-flow` gets the same two slots in its own order via
|
|
112
107
|
* the `.to` suffix key.
|
|
108
|
+
*
|
|
109
|
+
* ## Why it is gated on the framework's `geometry`
|
|
110
|
+
*
|
|
111
|
+
* "Up" is a claim about the board, not about the edge: it is only true where
|
|
112
|
+
* the framework said the vertical axis carries the order
|
|
113
|
+
* (`ReadingRelationDef.geometry`). Wardley says it, and this section is the
|
|
114
|
+
* value chain read from the bottom. Nobody else does, and "value flows up
|
|
115
|
+
* from Receive order to Check stock" would be a sentence BPMN never said.
|
|
113
116
|
*/
|
|
114
117
|
private _renderValueFlow;
|
|
118
|
+
/**
|
|
119
|
+
* Where the subject sits along the frame's phase axis.
|
|
120
|
+
*
|
|
121
|
+
* Absent ENTIRELY — not "no phase to read" — for a framework that declares no
|
|
122
|
+
* frame. The empty state below is about a component that could have been on a
|
|
123
|
+
* map and is not; telling the author of a BPMN task that it is "not on a
|
|
124
|
+
* framework background" would be answering a question their notation never
|
|
125
|
+
* asks.
|
|
126
|
+
*/
|
|
115
127
|
private _renderPhase;
|
|
116
128
|
private _renderNaming;
|
|
117
129
|
/**
|
|
@@ -46,18 +46,16 @@ export const READING_PROPOSAL_WIDGET = 'affine-reading-proposal-widget';
|
|
|
46
46
|
const TAG_SET_ID = 'tag.set';
|
|
47
47
|
const PIVOT_BIND_ID = 'pivot.bind';
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
49
|
+
* The two sides of a relation, in the order the panel lists them: what needs
|
|
50
|
+
* the subject first, then what the subject needs.
|
|
51
51
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
52
|
+
* The WORDINGS are no longer here. They used to be a chrome table
|
|
53
|
+
* (`Consumers (above)` / `Suppliers (below)`), which was Wardley's sentence
|
|
54
|
+
* written into the engine — a BPMN sequence flow has no "above". Each framework
|
|
55
|
+
* now names its own two sides on its {@link ReadingProfile}, Wardley included,
|
|
56
|
+
* and restates those very keys and wordings so nothing on a Wardley map moved.
|
|
56
57
|
*/
|
|
57
|
-
|
|
58
|
-
consumers: 'Consumers (above)',
|
|
59
|
-
suppliers: 'Suppliers (below)',
|
|
60
|
-
};
|
|
58
|
+
const RELATION_SIDES = ['consumer', 'supplier'];
|
|
61
59
|
/**
|
|
62
60
|
* **The proposal panel** — what the tool reads of one component, offered for
|
|
63
61
|
* confirmation (MF3).
|
|
@@ -411,24 +409,38 @@ let ReadingProposalWidget = (() => {
|
|
|
411
409
|
</div>`
|
|
412
410
|
: nothing}`);
|
|
413
411
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
412
|
+
/**
|
|
413
|
+
* The typed edges touching the subject, grouped by side and named with the
|
|
414
|
+
* FRAMEWORK's own two words (`ReadingRelationDef.sides`).
|
|
415
|
+
*
|
|
416
|
+
* The `data-testid` keeps the shape it shipped with — `reading-consumers`,
|
|
417
|
+
* `reading-suppliers` — because it names the SIDE, which is generic, and not
|
|
418
|
+
* the wording, which is now the framework's.
|
|
419
|
+
*/
|
|
420
|
+
_renderRelations(reading, profile) {
|
|
421
|
+
const sides = profile.relation?.sides;
|
|
422
|
+
const line = (side) => {
|
|
423
|
+
const relations = reading.relations.filter(r => r.side === side);
|
|
424
|
+
const wording = sides?.[side];
|
|
425
|
+
// No wording means the framework declared no relation at all, in which
|
|
426
|
+
// case there is nothing to list either. Silence rather than a heading
|
|
427
|
+
// this library would have had to invent.
|
|
428
|
+
if (!relations.length || !wording)
|
|
429
|
+
return nothing;
|
|
430
|
+
return html `<div class="reading-value" data-testid=${`reading-${side}s`}>
|
|
431
|
+
${translateKey(this.std, wording.labelKey, wording.labelFallback)}:
|
|
432
|
+
${relations
|
|
421
433
|
.map(relation => relation.otherName || relation.otherId)
|
|
422
434
|
.join(', ')}
|
|
423
|
-
|
|
424
|
-
|
|
435
|
+
</div>`;
|
|
436
|
+
};
|
|
425
437
|
const contradictions = reading.relations.filter(r => r.contradictsGeometry);
|
|
426
438
|
return this._field('reading-relations', translateKey(this.std, 'com.labre.reading.field.relations', 'Parent-child relations'), html `${reading.relations.length === 0
|
|
427
439
|
? html `<div class="reading-empty">
|
|
428
440
|
${translateKey(this.std, 'com.labre.reading.relations.none', 'No typed link touches this component.')}
|
|
429
441
|
</div>`
|
|
430
442
|
: nothing}
|
|
431
|
-
${
|
|
443
|
+
${RELATION_SIDES.map(line)}
|
|
432
444
|
${contradictions.length
|
|
433
445
|
? html `<div class="reading-note" data-testid="reading-contradiction">
|
|
434
446
|
${translateKey(this.std, 'com.labre.reading.relations.contradiction', 'A link states the opposite of what the positions show')}:
|
|
@@ -453,8 +465,18 @@ let ReadingProposalWidget = (() => {
|
|
|
453
465
|
* "Value flows up from X to Y"; a host that translates
|
|
454
466
|
* `com.labre.reading.value-flow` gets the same two slots in its own order via
|
|
455
467
|
* the `.to` suffix key.
|
|
468
|
+
*
|
|
469
|
+
* ## Why it is gated on the framework's `geometry`
|
|
470
|
+
*
|
|
471
|
+
* "Up" is a claim about the board, not about the edge: it is only true where
|
|
472
|
+
* the framework said the vertical axis carries the order
|
|
473
|
+
* (`ReadingRelationDef.geometry`). Wardley says it, and this section is the
|
|
474
|
+
* value chain read from the bottom. Nobody else does, and "value flows up
|
|
475
|
+
* from Receive order to Check stock" would be a sentence BPMN never said.
|
|
456
476
|
*/
|
|
457
|
-
_renderValueFlow(reading) {
|
|
477
|
+
_renderValueFlow(reading, profile) {
|
|
478
|
+
if (profile.relation?.geometry !== 'vertical')
|
|
479
|
+
return nothing;
|
|
458
480
|
const flows = readValueFlows(reading);
|
|
459
481
|
if (flows.length === 0)
|
|
460
482
|
return nothing;
|
|
@@ -468,7 +490,18 @@ let ReadingProposalWidget = (() => {
|
|
|
468
490
|
${from} ${flow.from} ${to} ${flow.to}
|
|
469
491
|
</div>`)}`);
|
|
470
492
|
}
|
|
471
|
-
|
|
493
|
+
/**
|
|
494
|
+
* Where the subject sits along the frame's phase axis.
|
|
495
|
+
*
|
|
496
|
+
* Absent ENTIRELY — not "no phase to read" — for a framework that declares no
|
|
497
|
+
* frame. The empty state below is about a component that could have been on a
|
|
498
|
+
* map and is not; telling the author of a BPMN task that it is "not on a
|
|
499
|
+
* framework background" would be answering a question their notation never
|
|
500
|
+
* asks.
|
|
501
|
+
*/
|
|
502
|
+
_renderPhase(reading, profile) {
|
|
503
|
+
if (!profile.frame)
|
|
504
|
+
return nothing;
|
|
472
505
|
const { phase } = reading;
|
|
473
506
|
return this._field('reading-phase', translateKey(this.std, 'com.labre.reading.field.phase', 'Evolution phase'), phase
|
|
474
507
|
? html `<div class="reading-value" data-zone-id=${phase.zoneId}>
|
|
@@ -600,8 +633,9 @@ let ReadingProposalWidget = (() => {
|
|
|
600
633
|
${translateKey(this.std, 'com.labre.reading.panel.title', 'What this map says about this component')}
|
|
601
634
|
</div>`, html `${this._renderNodeType(reading, profile)}
|
|
602
635
|
${this._renderNature(reading, profile, record, writable)}
|
|
603
|
-
${this._renderRelations(reading
|
|
604
|
-
${this.
|
|
636
|
+
${this._renderRelations(reading, profile)}
|
|
637
|
+
${this._renderValueFlow(reading, profile)}
|
|
638
|
+
${this._renderPhase(reading, profile)} ${this._renderNaming(reading)}
|
|
605
639
|
${this._renderRecord(reading, writable)}
|
|
606
640
|
${writable ? this._renderDrift(reading) : nothing}`);
|
|
607
641
|
}
|
|
@@ -80,6 +80,53 @@ export interface ReadingNamingConvention {
|
|
|
80
80
|
/** English default, for a host that ships no catalogue. */
|
|
81
81
|
hintFallback: string;
|
|
82
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* How a framework names ONE end of its typed relation, in the panel.
|
|
85
|
+
*
|
|
86
|
+
* Key plus the framework's own wording, exactly like a role's label or a rule's
|
|
87
|
+
* message: the host localises it, and a host with no catalogue still reads a
|
|
88
|
+
* real phrase.
|
|
89
|
+
*/
|
|
90
|
+
export interface ReadingRelationSideLabel {
|
|
91
|
+
labelKey: string;
|
|
92
|
+
/** The framework's own English wording, for a host that ships no catalogue. */
|
|
93
|
+
labelFallback: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The typed edge a reading walks, and the two words the framework reads it
|
|
97
|
+
* with.
|
|
98
|
+
*
|
|
99
|
+
* The wordings live HERE rather than in the panel because they are the
|
|
100
|
+
* framework's own sentence and nobody else's: "Consumers (above)" is a Wardley
|
|
101
|
+
* value chain, "Followed by" is a BPMN sequence, "Upstream" is a context map.
|
|
102
|
+
* The panel used to hard-code the first pair, which is exactly what made the
|
|
103
|
+
* reading a Wardley feature wearing a generic coat.
|
|
104
|
+
*/
|
|
105
|
+
export interface ReadingRelationDef {
|
|
106
|
+
edgeRole: RoleId;
|
|
107
|
+
/**
|
|
108
|
+
* One wording per side, keyed by what the OTHER end is to the subject — the
|
|
109
|
+
* same convention {@link ReadingRelation.side} carries. `supplier` labels the
|
|
110
|
+
* edges LEAVING the subject (the subject is the `source`, i.e. the subject of
|
|
111
|
+
* the role's verb), `consumer` the edges arriving at it.
|
|
112
|
+
*/
|
|
113
|
+
sides: Record<ReadingRelationSide, ReadingRelationSideLabel>;
|
|
114
|
+
/**
|
|
115
|
+
* The framework claims its board has a VERTICAL reading — that the axis the
|
|
116
|
+
* elements are drawn along IS the statement of order, so a link and the two
|
|
117
|
+
* positions can contradict each other.
|
|
118
|
+
*
|
|
119
|
+
* Opt-in, and only Wardley opts in: on a value chain a consumer is drawn
|
|
120
|
+
* above what it needs (ADR 0010 § 5), so an edge pointing the other way is a
|
|
121
|
+
* disagreement worth reporting. On a BPMN pool, a context map or a storming
|
|
122
|
+
* roll, "above" means nothing — two tasks side by side are not in conflict —
|
|
123
|
+
* and a contradiction note there would be a complaint about a drawing that is
|
|
124
|
+
* perfectly correct. Absent, {@link ReadingRelation.contradictsGeometry} is
|
|
125
|
+
* always `false`, and the panel also drops the VALUE FLOW section: "value
|
|
126
|
+
* flows up from X to Y" is the same vertical claim said the other way round.
|
|
127
|
+
*/
|
|
128
|
+
geometry?: 'vertical';
|
|
129
|
+
}
|
|
83
130
|
/**
|
|
84
131
|
* One framework's reading contract. Every section is optional: a framework that
|
|
85
132
|
* declares only `appliesTo` gets the node-type line and nothing else, which is
|
|
@@ -109,9 +156,7 @@ export interface ReadingProfile {
|
|
|
109
156
|
conventions: readonly ReadingNamingConvention[];
|
|
110
157
|
};
|
|
111
158
|
/** The typed edge whose two ends the relation reading walks. */
|
|
112
|
-
relation?:
|
|
113
|
-
edgeRole: RoleId;
|
|
114
|
-
};
|
|
159
|
+
relation?: ReadingRelationDef;
|
|
115
160
|
/** The frame the phase is read from. */
|
|
116
161
|
frame?: {
|
|
117
162
|
backgroundRole: RoleId;
|
|
@@ -159,6 +204,10 @@ export interface ReadingRelation {
|
|
|
159
204
|
* says one thing and the two positions say the other, the reading says so
|
|
160
205
|
* rather than picking a winner: that is W4 seen from the record's side, and
|
|
161
206
|
* the user is the one who decides which of the two was the mistake.
|
|
207
|
+
*
|
|
208
|
+
* Always `false` unless the framework declared
|
|
209
|
+
* {@link ReadingRelationDef.geometry} — a board whose axis carries no order
|
|
210
|
+
* has nothing to contradict.
|
|
162
211
|
*/
|
|
163
212
|
contradictsGeometry: boolean;
|
|
164
213
|
}
|
|
@@ -279,6 +328,15 @@ export interface ReadingValueFlow {
|
|
|
279
328
|
export declare function readValueFlows(reading: ElementReading): ReadingValueFlow[];
|
|
280
329
|
/** The profile governing an element, or `null` — the first match wins. */
|
|
281
330
|
export declare function readingProfileFor(element: GfxPrimitiveElementModel, profiles: readonly ReadingProfile[]): ReadingProfile | null;
|
|
331
|
+
/**
|
|
332
|
+
* How the engine asks the HOST for a wording — `translateKey`, curried with the
|
|
333
|
+
* `std` its caller owns.
|
|
334
|
+
*
|
|
335
|
+
* A function rather than a scope, so every comparison below stays a pure
|
|
336
|
+
* function of its arguments and one caller ({@link ReadingManager}) owns the
|
|
337
|
+
* single `std` read.
|
|
338
|
+
*/
|
|
339
|
+
export type ReadingTranslate = (key: string, fallback: string) => string;
|
|
282
340
|
/**
|
|
283
341
|
* What the LINKED RECORD says about the two fields a reading can compare
|
|
284
342
|
* itself against. Bounded by construction: the profile names at most two host
|
|
@@ -341,6 +399,16 @@ export interface ResolvedRecordNature {
|
|
|
341
399
|
* its words would be inventing it;
|
|
342
400
|
* - **`values: 'open'`** — the def says any string is a value of this tag, so
|
|
343
401
|
* everything resolves. That is the def's own claim, not ours.
|
|
402
|
+
*
|
|
403
|
+
* ## Why there is no `translate` here, unlike {@link compareReading}
|
|
404
|
+
*
|
|
405
|
+
* There is nothing to translate. `TagValueDef.label` is documented as "already
|
|
406
|
+
* localized by the host" (ADR 0007): a pack is SEEDED with the wording of the
|
|
407
|
+
* deployment that seeded it, so the label this resolver already matches against
|
|
408
|
+
* IS the localized one. Adding a resolver would be a parameter that could never
|
|
409
|
+
* change an answer. The zone labels are the opposite case — they are declared
|
|
410
|
+
* in the library, in English, with an i18n key beside them — which is why the
|
|
411
|
+
* phase comparison takes one.
|
|
344
412
|
*/
|
|
345
413
|
export declare function resolveRecordNature(def: TagDef | undefined, values: readonly string[]): ResolvedRecordNature;
|
|
346
414
|
/** One field on which the drawing and the record disagree. */
|
|
@@ -389,11 +457,19 @@ export declare function readRecord(std: BlockStdScope, element: GfxPrimitiveElem
|
|
|
389
457
|
* side. `readRecord` has already resolved what CAN be compared; what could not
|
|
390
458
|
* is not a difference of opinion, it is a difference of alphabet.
|
|
391
459
|
*
|
|
392
|
-
* The phase comparison accepts
|
|
393
|
-
*
|
|
394
|
-
*
|
|
460
|
+
* The phase comparison accepts the zone id, the zone's own English wording, and
|
|
461
|
+
* — when a `translate` is handed in — the wording the HOST's catalogue gives
|
|
462
|
+
* that zone. A French deployment stores "Produit" in its record and reads
|
|
463
|
+
* `product` off the board; without the third spelling the panel would report a
|
|
464
|
+
* permanent, false disagreement on a component nobody had moved. Same shape as
|
|
465
|
+
* the value-id resolution above: a difference of alphabet is not a difference
|
|
466
|
+
* of opinion.
|
|
467
|
+
*
|
|
468
|
+
* `translate` is a PARAMETER rather than a `std` read, so this stays a pure
|
|
469
|
+
* function of its arguments; {@link ReadingManager} owns the single `std` the
|
|
470
|
+
* closure is built from.
|
|
395
471
|
*/
|
|
396
|
-
export declare function compareReading(reading: ElementReading, record: RecordReading): ReadingDriftField[];
|
|
472
|
+
export declare function compareReading(reading: ElementReading, record: RecordReading, translate?: ReadingTranslate): ReadingDriftField[];
|
|
397
473
|
/** A framework registers its reading profile here; nothing else registers one. */
|
|
398
474
|
export declare const ReadingProfileIdentifier: import("../../global/di/types.js").ServiceIdentifier<ReadingProfile> & (<U extends ReadingProfile = ReadingProfile>(variant: import("../../global/di/types.js").ServiceVariant) => import("../../global/di/types.js").ServiceIdentifier<U>);
|
|
399
475
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getUniverseRegistry, hostLanguage, queryPivotProperties, } from '../../affine-shared/services/index.js';
|
|
1
|
+
import { getUniverseRegistry, hostLanguage, queryPivotProperties, translateKey, } from '../../affine-shared/services/index.js';
|
|
2
2
|
import { createIdentifier } from '../../global/di/index.js';
|
|
3
3
|
import { LifeCycleWatcher, } from '../../std/index.js';
|
|
4
4
|
import { GfxControllerIdentifier, GfxPrimitiveElementModel, readElementTags, resolvePivotBinding, roleIsA, } from '../../std/gfx/index.js';
|
|
@@ -270,10 +270,14 @@ function readRelations(element, elements, profile) {
|
|
|
270
270
|
const side = isSource ? 'supplier' : 'consumer';
|
|
271
271
|
const [, otherY] = centreOf(other.elementBound);
|
|
272
272
|
// `y` grows downwards, so "higher on the map" is a SMALLER y. A supplier is
|
|
273
|
-
// expected below the subject, a consumer above it
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
273
|
+
// expected below the subject, a consumer above it — but only on a board
|
|
274
|
+
// whose framework CLAIMED that axis says something (`geometry`). Two BPMN
|
|
275
|
+
// tasks side by side contradict nothing.
|
|
276
|
+
const contradictsGeometry = relation.geometry !== 'vertical'
|
|
277
|
+
? false
|
|
278
|
+
: side === 'supplier'
|
|
279
|
+
? otherY < subjectY - GEOMETRY_EPSILON
|
|
280
|
+
: otherY > subjectY + GEOMETRY_EPSILON;
|
|
277
281
|
relations.push({
|
|
278
282
|
edgeId: edge.id,
|
|
279
283
|
otherId,
|
|
@@ -399,6 +403,16 @@ export function readingProfileFor(element, profiles) {
|
|
|
399
403
|
* its words would be inventing it;
|
|
400
404
|
* - **`values: 'open'`** — the def says any string is a value of this tag, so
|
|
401
405
|
* everything resolves. That is the def's own claim, not ours.
|
|
406
|
+
*
|
|
407
|
+
* ## Why there is no `translate` here, unlike {@link compareReading}
|
|
408
|
+
*
|
|
409
|
+
* There is nothing to translate. `TagValueDef.label` is documented as "already
|
|
410
|
+
* localized by the host" (ADR 0007): a pack is SEEDED with the wording of the
|
|
411
|
+
* deployment that seeded it, so the label this resolver already matches against
|
|
412
|
+
* IS the localized one. Adding a resolver would be a parameter that could never
|
|
413
|
+
* change an answer. The zone labels are the opposite case — they are declared
|
|
414
|
+
* in the library, in English, with an i18n key beside them — which is why the
|
|
415
|
+
* phase comparison takes one.
|
|
402
416
|
*/
|
|
403
417
|
export function resolveRecordNature(def, values) {
|
|
404
418
|
const resolved = [];
|
|
@@ -512,11 +526,19 @@ export function readRecord(std, element, profile) {
|
|
|
512
526
|
* side. `readRecord` has already resolved what CAN be compared; what could not
|
|
513
527
|
* is not a difference of opinion, it is a difference of alphabet.
|
|
514
528
|
*
|
|
515
|
-
* The phase comparison accepts
|
|
516
|
-
*
|
|
517
|
-
*
|
|
529
|
+
* The phase comparison accepts the zone id, the zone's own English wording, and
|
|
530
|
+
* — when a `translate` is handed in — the wording the HOST's catalogue gives
|
|
531
|
+
* that zone. A French deployment stores "Produit" in its record and reads
|
|
532
|
+
* `product` off the board; without the third spelling the panel would report a
|
|
533
|
+
* permanent, false disagreement on a component nobody had moved. Same shape as
|
|
534
|
+
* the value-id resolution above: a difference of alphabet is not a difference
|
|
535
|
+
* of opinion.
|
|
536
|
+
*
|
|
537
|
+
* `translate` is a PARAMETER rather than a `std` read, so this stays a pure
|
|
538
|
+
* function of its arguments; {@link ReadingManager} owns the single `std` the
|
|
539
|
+
* closure is built from.
|
|
518
540
|
*/
|
|
519
|
-
export function compareReading(reading, record) {
|
|
541
|
+
export function compareReading(reading, record, translate) {
|
|
520
542
|
const fields = [];
|
|
521
543
|
const recorded = record.nature ?? [];
|
|
522
544
|
if (recorded.length) {
|
|
@@ -532,10 +554,11 @@ export function compareReading(reading, record) {
|
|
|
532
554
|
}
|
|
533
555
|
}
|
|
534
556
|
if (record.phase && reading.phase) {
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
557
|
+
const { zoneId, labelKey, labelFallback } = reading.phase;
|
|
558
|
+
const localized = translate && labelKey !== undefined
|
|
559
|
+
? translate(labelKey, labelFallback ?? zoneId)
|
|
560
|
+
: '';
|
|
561
|
+
const spellings = [zoneId, labelFallback ?? '', localized].map(value => value.toLowerCase());
|
|
539
562
|
if (!spellings.includes(record.phase.toLowerCase())) {
|
|
540
563
|
fields.push({
|
|
541
564
|
field: 'phase',
|
|
@@ -763,7 +786,11 @@ export class ReadingManager extends LifeCycleWatcher {
|
|
|
763
786
|
this.drift$.value = null;
|
|
764
787
|
return;
|
|
765
788
|
}
|
|
766
|
-
|
|
789
|
+
// The one `std` read the comparison needs, curried into a resolver so
|
|
790
|
+
// `compareReading` stays pure: a host serving French stores "Produit" in
|
|
791
|
+
// its record and would otherwise be told, for ever, that its board says
|
|
792
|
+
// `product` instead.
|
|
793
|
+
const fields = compareReading(reading, record, (key, fallback) => translateKey(this.std, key, fallback));
|
|
767
794
|
if (fields.length === 0) {
|
|
768
795
|
if (this.drift$.value?.elementId === elementId)
|
|
769
796
|
this.drift$.value = null;
|
|
@@ -194,8 +194,15 @@ function renderSection(ctx, target, def) {
|
|
|
194
194
|
const options = offeredValues(def, selected).map(value => {
|
|
195
195
|
const on = selected.includes(value.id);
|
|
196
196
|
const valueLabel = value.label || value.id;
|
|
197
|
+
// `data-toggle` beside `data-option`: the row draws like a native option,
|
|
198
|
+
// but clicking the value in FORCE is how it is un-picked (`toggleValue`),
|
|
199
|
+
// whatever the tag's cardinality. Without it the selected row inherits
|
|
200
|
+
// `editor-menu-action`'s inert `pointer-events: none` — the tick lands
|
|
201
|
+
// under the pointer, the click reaches the section instead, and a
|
|
202
|
+
// qualification can be set but never cleared with a real mouse.
|
|
197
203
|
return html `<editor-menu-action
|
|
198
204
|
data-option
|
|
205
|
+
data-toggle
|
|
199
206
|
data-testid="element-tag-option"
|
|
200
207
|
data-tag-id=${def.id}
|
|
201
208
|
data-value-id=${value.id}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { HighLightDuotoneIcon } from '@blocksuite/icons/lit';
|
|
2
2
|
import { css, LitElement } from 'lit';
|
|
3
3
|
export class HighlightDuotoneIcon extends LitElement {
|
|
4
|
-
static { this.styles = css `
|
|
5
|
-
svg {
|
|
6
|
-
display: flex;
|
|
7
|
-
font-size: 20px;
|
|
8
|
-
}
|
|
9
|
-
svg > path:nth-child(1) {
|
|
10
|
-
fill: var(--color, unset);
|
|
11
|
-
}
|
|
4
|
+
static { this.styles = css `
|
|
5
|
+
svg {
|
|
6
|
+
display: flex;
|
|
7
|
+
font-size: 20px;
|
|
8
|
+
}
|
|
9
|
+
svg > path:nth-child(1) {
|
|
10
|
+
fill: var(--color, unset);
|
|
11
|
+
}
|
|
12
12
|
`; }
|
|
13
13
|
render() {
|
|
14
14
|
return HighLightDuotoneIcon();
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { TextBackgroundDuotoneIcon } from '@blocksuite/icons/lit';
|
|
2
2
|
import { css, LitElement } from 'lit';
|
|
3
3
|
export class TextDuotoneIcon extends LitElement {
|
|
4
|
-
static { this.styles = css `
|
|
5
|
-
svg {
|
|
6
|
-
display: flex;
|
|
7
|
-
font-size: 20px;
|
|
8
|
-
}
|
|
9
|
-
svg > path:nth-child(1) {
|
|
10
|
-
fill: var(--background, unset);
|
|
11
|
-
}
|
|
12
|
-
svg > path:nth-child(3) {
|
|
13
|
-
fill: var(--color, unset);
|
|
14
|
-
}
|
|
4
|
+
static { this.styles = css `
|
|
5
|
+
svg {
|
|
6
|
+
display: flex;
|
|
7
|
+
font-size: 20px;
|
|
8
|
+
}
|
|
9
|
+
svg > path:nth-child(1) {
|
|
10
|
+
fill: var(--background, unset);
|
|
11
|
+
}
|
|
12
|
+
svg > path:nth-child(3) {
|
|
13
|
+
fill: var(--color, unset);
|
|
14
|
+
}
|
|
15
15
|
`; }
|
|
16
16
|
render() {
|
|
17
17
|
return TextBackgroundDuotoneIcon();
|