@elaraai/e3-ui 1.0.103 → 1.0.105
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/src/allocation/functions.d.ts +2 -1
- package/dist/src/allocation/functions.d.ts.map +1 -1
- package/dist/src/allocation/functions.js +3 -2
- package/dist/src/allocation/functions.js.map +1 -1
- package/dist/src/allocation/index.d.ts +120 -1
- package/dist/src/allocation/index.d.ts.map +1 -1
- package/dist/src/allocation/index.js +24 -4
- package/dist/src/allocation/index.js.map +1 -1
- package/dist/src/bind/data-indexed.d.ts +25 -4
- package/dist/src/bind/data-indexed.d.ts.map +1 -1
- package/dist/src/bind/data-indexed.js +58 -7
- package/dist/src/bind/data-indexed.js.map +1 -1
- package/dist/src/bind/data.d.ts +12 -14
- package/dist/src/bind/data.d.ts.map +1 -1
- package/dist/src/bind/data.js +11 -11
- package/dist/src/bind/data.js.map +1 -1
- package/dist/src/bind/func.d.ts +7 -2
- package/dist/src/bind/func.d.ts.map +1 -1
- package/dist/src/bind/func.js +10 -3
- package/dist/src/bind/func.js.map +1 -1
- package/dist/src/calendar/index.d.ts +148 -1
- package/dist/src/calendar/index.d.ts.map +1 -1
- package/dist/src/calendar/index.js +55 -5
- package/dist/src/calendar/index.js.map +1 -1
- package/dist/src/flowchart/canvas.d.ts +32 -14
- package/dist/src/flowchart/canvas.d.ts.map +1 -1
- package/dist/src/flowchart/canvas.js +21 -6
- package/dist/src/flowchart/canvas.js.map +1 -1
- package/dist/src/flowchart/details.d.ts +469 -0
- package/dist/src/flowchart/details.d.ts.map +1 -0
- package/dist/src/flowchart/details.js +1035 -0
- package/dist/src/flowchart/details.js.map +1 -0
- package/dist/src/flowchart/flowchart.d.ts +16 -72
- package/dist/src/flowchart/flowchart.d.ts.map +1 -1
- package/dist/src/flowchart/flowchart.js +10 -1
- package/dist/src/flowchart/flowchart.js.map +1 -1
- package/dist/src/flowchart/index.d.ts +282 -251
- package/dist/src/flowchart/index.d.ts.map +1 -1
- package/dist/src/flowchart/index.js +234 -220
- package/dist/src/flowchart/index.js.map +1 -1
- package/dist/src/flowchart/kinds.d.ts +438 -0
- package/dist/src/flowchart/kinds.d.ts.map +1 -0
- package/dist/src/flowchart/kinds.js +799 -0
- package/dist/src/flowchart/kinds.js.map +1 -0
- package/dist/src/flowchart/library.d.ts +154 -739
- package/dist/src/flowchart/library.d.ts.map +1 -1
- package/dist/src/flowchart/library.js +191 -673
- package/dist/src/flowchart/library.js.map +1 -1
- package/dist/src/flowchart/payload.d.ts +3652 -7843
- package/dist/src/flowchart/payload.d.ts.map +1 -1
- package/dist/src/flowchart/payload.js +331 -469
- package/dist/src/flowchart/payload.js.map +1 -1
- package/dist/src/flowchart/templates.d.ts +657 -0
- package/dist/src/flowchart/templates.d.ts.map +1 -0
- package/dist/src/flowchart/templates.js +658 -0
- package/dist/src/flowchart/templates.js.map +1 -0
- package/dist/src/flowchart/types.d.ts +2258 -214
- package/dist/src/flowchart/types.d.ts.map +1 -1
- package/dist/src/flowchart/types.js +374 -124
- package/dist/src/flowchart/types.js.map +1 -1
- package/dist/src/index.d.ts +13 -15
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +24 -29
- package/dist/src/index.js.map +1 -1
- package/dist/src/internal.d.ts +5 -7
- package/dist/src/internal.d.ts.map +1 -1
- package/dist/src/internal.js +12 -19
- package/dist/src/internal.js.map +1 -1
- package/dist/src/ontology/index.d.ts +44 -15
- package/dist/src/ontology/index.d.ts.map +1 -1
- package/dist/src/ontology/index.js +19 -11
- package/dist/src/ontology/index.js.map +1 -1
- package/dist/src/plan/event-rows.d.ts +2 -1
- package/dist/src/plan/event-rows.d.ts.map +1 -1
- package/dist/src/plan/event-rows.js +6 -4
- package/dist/src/plan/event-rows.js.map +1 -1
- package/dist/src/plan/ir.d.ts +1 -0
- package/dist/src/plan/ir.d.ts.map +1 -1
- package/dist/src/plan/plan.d.ts +145 -1
- package/dist/src/plan/plan.d.ts.map +1 -1
- package/dist/src/plan/plan.js +67 -3
- package/dist/src/plan/plan.js.map +1 -1
- package/dist/src/plan/types.d.ts +1 -0
- package/dist/src/plan/types.d.ts.map +1 -1
- package/dist/src/query/builder.d.ts +362 -315
- package/dist/src/query/builder.d.ts.map +1 -1
- package/dist/src/query/builder.js +12 -1
- package/dist/src/query/builder.js.map +1 -1
- package/dist/src/query/index.d.ts +5 -1
- package/dist/src/query/index.d.ts.map +1 -1
- package/dist/src/query/index.js +3 -1
- package/dist/src/query/index.js.map +1 -1
- package/dist/src/roster/fit.d.ts +5 -2
- package/dist/src/roster/fit.d.ts.map +1 -1
- package/dist/src/roster/fit.js +5 -3
- package/dist/src/roster/fit.js.map +1 -1
- package/dist/src/roster/index.d.ts +103 -2
- package/dist/src/roster/index.d.ts.map +1 -1
- package/dist/src/roster/index.js +45 -6
- package/dist/src/roster/index.js.map +1 -1
- package/dist/src/runtime/index.d.ts +1 -3
- package/dist/src/runtime/index.d.ts.map +1 -1
- package/dist/src/runtime/index.js +1 -3
- package/dist/src/runtime/index.js.map +1 -1
- package/dist/src/schedule/record-window.d.ts +1 -0
- package/dist/src/schedule/record-window.d.ts.map +1 -1
- package/dist/src/schematic/index.d.ts +1 -1
- package/dist/src/schematic/index.d.ts.map +1 -1
- package/dist/src/schematic/index.js +1 -1
- package/dist/src/schematic/index.js.map +1 -1
- package/dist/src/schematic/kinds.d.ts +4 -24
- package/dist/src/schematic/kinds.d.ts.map +1 -1
- package/dist/src/schematic/kinds.js +8 -212
- package/dist/src/schematic/kinds.js.map +1 -1
- package/dist/src/schematic/payload.d.ts +140 -1
- package/dist/src/schematic/payload.d.ts.map +1 -1
- package/dist/src/schematic/payload.js +38 -1
- package/dist/src/schematic/payload.js.map +1 -1
- package/dist/src/schematic/types.d.ts.map +1 -1
- package/dist/src/schematic/types.js +4 -36
- package/dist/src/schematic/types.js.map +1 -1
- package/dist/src/schematic/window.d.ts +9 -42
- package/dist/src/schematic/window.d.ts.map +1 -1
- package/dist/src/schematic/window.js +10 -115
- package/dist/src/schematic/window.js.map +1 -1
- package/dist/src/sheet/actions.d.ts +388 -0
- package/dist/src/sheet/actions.d.ts.map +1 -0
- package/dist/src/sheet/actions.js +594 -0
- package/dist/src/sheet/actions.js.map +1 -0
- package/dist/src/sheet/bridge.d.ts +12 -1
- package/dist/src/sheet/bridge.d.ts.map +1 -1
- package/dist/src/sheet/bridge.js +30 -6
- package/dist/src/sheet/bridge.js.map +1 -1
- package/dist/src/sheet/columns.d.ts +5 -2
- package/dist/src/sheet/columns.d.ts.map +1 -1
- package/dist/src/sheet/columns.js.map +1 -1
- package/dist/src/sheet/draft-bridge.d.ts +9 -4
- package/dist/src/sheet/draft-bridge.d.ts.map +1 -1
- package/dist/src/sheet/draft-bridge.js +22 -7
- package/dist/src/sheet/draft-bridge.js.map +1 -1
- package/dist/src/sheet/fields.d.ts +13 -0
- package/dist/src/sheet/fields.d.ts.map +1 -1
- package/dist/src/sheet/fields.js +3 -0
- package/dist/src/sheet/fields.js.map +1 -1
- package/dist/src/sheet/index.d.ts +32 -2
- package/dist/src/sheet/index.d.ts.map +1 -1
- package/dist/src/sheet/index.js +18 -3
- package/dist/src/sheet/index.js.map +1 -1
- package/dist/src/sheet/library.d.ts +8 -0
- package/dist/src/sheet/library.d.ts.map +1 -1
- package/dist/src/sheet/root.d.ts +23 -1
- package/dist/src/sheet/root.d.ts.map +1 -1
- package/dist/src/sheet/root.js +40 -5
- package/dist/src/sheet/root.js.map +1 -1
- package/dist/src/sheet/sheet.d.ts +7843 -4132
- package/dist/src/sheet/sheet.d.ts.map +1 -1
- package/dist/src/sheet/sheet.js +41 -2
- package/dist/src/sheet/sheet.js.map +1 -1
- package/dist/src/sheet/templates.d.ts +4 -0
- package/dist/src/sheet/templates.d.ts.map +1 -1
- package/dist/src/sheet/types.d.ts +12449 -5268
- package/dist/src/sheet/types.d.ts.map +1 -1
- package/dist/src/sheet/types.js +114 -2
- package/dist/src/sheet/types.js.map +1 -1
- package/dist/src/utils/derive.d.ts +1 -1
- package/dist/src/utils/derive.js +1 -1
- package/dist/src/utils/record-kind.d.ts +625 -0
- package/dist/src/utils/record-kind.d.ts.map +1 -0
- package/dist/src/utils/record-kind.js +450 -0
- package/dist/src/utils/record-kind.js.map +1 -0
- package/dist/src/utils/views.d.ts +55 -0
- package/dist/src/utils/views.d.ts.map +1 -0
- package/dist/src/utils/views.js +72 -0
- package/dist/src/utils/views.js.map +1 -0
- package/dist/src/utils/vocabulary.d.ts +48 -0
- package/dist/src/utils/vocabulary.d.ts.map +1 -0
- package/dist/src/utils/vocabulary.js +47 -0
- package/dist/src/utils/vocabulary.js.map +1 -0
- package/dist/test/allocation/allocation.examples.d.ts +2 -0
- package/dist/test/allocation/allocation.examples.d.ts.map +1 -1
- package/dist/test/allocation/allocation.examples.js +81 -2
- package/dist/test/allocation/allocation.examples.js.map +1 -1
- package/dist/test/bind/func/func.examples.d.ts +19 -1
- package/dist/test/bind/func/func.examples.d.ts.map +1 -1
- package/dist/test/bind/func/func.examples.js +36 -1
- package/dist/test/bind/func/func.examples.js.map +1 -1
- package/dist/test/calendar/calendar.examples.d.ts +2 -0
- package/dist/test/calendar/calendar.examples.d.ts.map +1 -1
- package/dist/test/calendar/calendar.examples.js +80 -2
- package/dist/test/calendar/calendar.examples.js.map +1 -1
- package/dist/test/decision/queue.examples.d.ts +1 -0
- package/dist/test/decision/queue.examples.d.ts.map +1 -1
- package/dist/test/decision/queue.examples.js +12 -0
- package/dist/test/decision/queue.examples.js.map +1 -1
- package/dist/test/examples-package.d.ts.map +1 -1
- package/dist/test/examples-package.js +5 -4
- package/dist/test/examples-package.js.map +1 -1
- package/dist/test/flowchart/flowchart.examples.d.ts +1250 -4605
- package/dist/test/flowchart/flowchart.examples.d.ts.map +1 -1
- package/dist/test/flowchart/flowchart.examples.js +861 -512
- package/dist/test/flowchart/flowchart.examples.js.map +1 -1
- package/dist/test/ontology/ontology.examples.d.ts +2 -3
- package/dist/test/ontology/ontology.examples.d.ts.map +1 -1
- package/dist/test/ontology/ontology.examples.js +32 -21
- package/dist/test/ontology/ontology.examples.js.map +1 -1
- package/dist/test/plan/plan-events.examples.d.ts +1 -0
- package/dist/test/plan/plan-events.examples.d.ts.map +1 -1
- package/dist/test/plan/plan-events.examples.js +44 -0
- package/dist/test/plan/plan-events.examples.js.map +1 -1
- package/dist/test/plan/plan-nested.examples.d.ts +2 -2
- package/dist/test/plan/plan-nested.examples.js +5 -5
- package/dist/test/plan/plan-nested.examples.js.map +1 -1
- package/dist/test/plan/plan-records.examples.d.ts.map +1 -1
- package/dist/test/plan/plan-records.examples.js +1 -1
- package/dist/test/plan/plan-records.examples.js.map +1 -1
- package/dist/test/query/query.examples.d.ts +2 -0
- package/dist/test/query/query.examples.d.ts.map +1 -1
- package/dist/test/query/query.examples.js +37 -1
- package/dist/test/query/query.examples.js.map +1 -1
- package/dist/test/roster/roster.examples.d.ts +2 -0
- package/dist/test/roster/roster.examples.d.ts.map +1 -1
- package/dist/test/roster/roster.examples.js +76 -15
- package/dist/test/roster/roster.examples.js.map +1 -1
- package/dist/test/schematic/schematic-records.examples.d.ts.map +1 -1
- package/dist/test/schematic/schematic-records.examples.js +6 -4
- package/dist/test/schematic/schematic-records.examples.js.map +1 -1
- package/dist/test/schematic/schematic.examples.d.ts +1 -0
- package/dist/test/schematic/schematic.examples.d.ts.map +1 -1
- package/dist/test/schematic/schematic.examples.js +144 -0
- package/dist/test/schematic/schematic.examples.js.map +1 -1
- package/dist/test/sheet/sheet-actions.examples.d.ts +1264 -0
- package/dist/test/sheet/sheet-actions.examples.d.ts.map +1 -0
- package/dist/test/sheet/sheet-actions.examples.js +394 -0
- package/dist/test/sheet/sheet-actions.examples.js.map +1 -0
- package/dist/test/sheet/sheet.examples.d.ts +1 -0
- package/dist/test/sheet/sheet.examples.d.ts.map +1 -1
- package/dist/test/sheet/sheet.examples.js +77 -0
- package/dist/test/sheet/sheet.examples.js.map +1 -1
- package/dist/test/studio/studio.examples.d.ts +1 -0
- package/dist/test/studio/studio.examples.d.ts.map +1 -1
- package/dist/test/studio/studio.examples.js +18 -8
- package/dist/test/studio/studio.examples.js.map +1 -1
- package/package.json +12 -12
- package/dist/src/diff/index.d.ts +0 -407
- package/dist/src/diff/index.d.ts.map +0 -1
- package/dist/src/diff/index.js +0 -203
- package/dist/src/diff/index.js.map +0 -1
- package/dist/src/experiment/index.d.ts +0 -1033
- package/dist/src/experiment/index.d.ts.map +0 -1
- package/dist/src/experiment/index.js +0 -197
- package/dist/src/experiment/index.js.map +0 -1
- package/dist/src/experiment/types.d.ts +0 -1093
- package/dist/src/experiment/types.d.ts.map +0 -1
- package/dist/src/experiment/types.js +0 -423
- package/dist/src/experiment/types.js.map +0 -1
- package/dist/src/flowchart/over.d.ts +0 -227
- package/dist/src/flowchart/over.d.ts.map +0 -1
- package/dist/src/flowchart/over.js +0 -213
- package/dist/src/flowchart/over.js.map +0 -1
- package/dist/src/flowchart/patch.d.ts +0 -64
- package/dist/src/flowchart/patch.d.ts.map +0 -1
- package/dist/src/flowchart/patch.js +0 -67
- package/dist/src/flowchart/patch.js.map +0 -1
- package/dist/src/flowchart/values.d.ts +0 -271
- package/dist/src/flowchart/values.d.ts.map +0 -1
- package/dist/src/flowchart/values.js +0 -220
- package/dist/src/flowchart/values.js.map +0 -1
- package/dist/src/flowchart/window.d.ts +0 -306
- package/dist/src/flowchart/window.d.ts.map +0 -1
- package/dist/src/flowchart/window.js +0 -63
- package/dist/src/flowchart/window.js.map +0 -1
- package/dist/src/runtime/diff.d.ts +0 -36
- package/dist/src/runtime/diff.d.ts.map +0 -1
- package/dist/src/runtime/diff.js +0 -34
- package/dist/src/runtime/diff.js.map +0 -1
- package/dist/src/runtime/experiment.d.ts +0 -48
- package/dist/src/runtime/experiment.d.ts.map +0 -1
- package/dist/src/runtime/experiment.js +0 -10
- package/dist/src/runtime/experiment.js.map +0 -1
- package/dist/test/diff/diff.examples.d.ts +0 -313
- package/dist/test/diff/diff.examples.d.ts.map +0 -1
- package/dist/test/diff/diff.examples.js +0 -452
- package/dist/test/diff/diff.examples.js.map +0 -1
- package/dist/test/experiment/experiment.examples.d.ts +0 -1512
- package/dist/test/experiment/experiment.examples.d.ts.map +0 -1
- package/dist/test/experiment/experiment.examples.js +0 -609
- package/dist/test/experiment/experiment.examples.js.map +0 -1
|
@@ -3,188 +3,89 @@
|
|
|
3
3
|
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* The Flowchart's payload (#1500, `Flowchart Records Spec.md` §3, R1–R4): what
|
|
7
|
+
* `<Flowchart>` hands the renderer through its `Flowchart` carrier — its
|
|
8
|
+
* canvas, its kinds, its narrowing and how a narrowed-out row draws, its
|
|
9
|
+
* library's tabs, whether it has an inspector, the app's own words for a
|
|
10
|
+
* transition's kinds (#1516), whether it is read only, and its name — and
|
|
11
|
+
* every refusal of its props, made when the surface is built. A kind's noun
|
|
12
|
+
* is its own `name`, wherever the Flowchart says it.
|
|
11
13
|
*
|
|
12
|
-
* Its
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* the editing session over the flows (#1246), its Save: the session's keyed
|
|
17
|
-
* batch committed through the patch mutation by `Record.onApply(record, {
|
|
18
|
-
* keyed: true })`. A record always holds flows by name (ruled 2026-10-07:
|
|
19
|
-
* e3's patch mutation writes only keyed records), so a lone flow is a
|
|
20
|
-
* one-entry record, or the host's. With a `flows` source in its `slice`
|
|
21
|
-
* (#1346), the Flows tab pages what the rail narrows the record to, the open
|
|
22
|
-
* flow is read by its name, and the whole record is never read: only the
|
|
23
|
-
* paged window, the read by name and the tab's own search's page cross;
|
|
24
|
-
* - `data`, the host's flows by name or one flow — a value, an expression or a
|
|
25
|
-
* bind handle — the value's type picking the arm. Given the host's
|
|
26
|
-
* `onApply`, the arm carries the session's Save through it (#1247): the
|
|
27
|
-
* session's batch restated as one patch of the host's value, which the
|
|
28
|
-
* host's `onApply` takes and answers. The host's flows are never narrowed
|
|
29
|
-
* (#1346): its `slice` holds only the sources its templates and its tabs
|
|
30
|
-
* name.
|
|
14
|
+
* Its kinds are the app's records (R1, `kinds.ts`): `states`, and beside them
|
|
15
|
+
* `transitions`, `lanes` and `decisions`, each closed over its record behind
|
|
16
|
+
* East functions over beast2 bytes, so the payload is one type whatever the
|
|
17
|
+
* rows hold.
|
|
31
18
|
*
|
|
32
|
-
* Its narrowing is one `Slice.bindRecords` (
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* source
|
|
19
|
+
* Its narrowing is one `Slice.bindRecords` (R4): a source named `states` or
|
|
20
|
+
* `transitions` narrows that kind, read complete through it — or, under
|
|
21
|
+
* `narrowed="dim"`, every row read through it and what the narrowing leaves
|
|
22
|
+
* out drawn as context — and each other source the cards list, the author's
|
|
23
|
+
* tab or the details whose picks it weighs name (#1522). A source named
|
|
24
|
+
* `lanes` or `decisions` is
|
|
25
|
+
* refused: they are read whole. The payload's block binds each source once
|
|
26
|
+
* (`recordSources(…).bind($)`), and each kind reads its own source inside its
|
|
27
|
+
* functions; none reads a source's state, so a choice builds the Flowchart no
|
|
28
|
+
* more.
|
|
36
29
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* Its library's tabs are the `Flowchart.library.*` calls `library` lists, on
|
|
42
|
-
* the wire in that order: `library.ts` builds each — the Flows tab, and the
|
|
43
|
-
* template and author's tabs, each card read from the tab's own rows — and
|
|
44
|
-
* makes the library's refusals (#1248).
|
|
45
|
-
*
|
|
46
|
-
* Its inspector is on by default (#1250, ruled by the user on 2026-10-08):
|
|
47
|
-
* the end pane, Details and Issues, unless `inspector={false}`; and
|
|
48
|
-
* `inspector={{ state, transition }}` gives a kind its own Details in place of
|
|
49
|
-
* its form, each an East function over the row and its writer, wrapped over
|
|
50
|
-
* bytes as the Sheet's own Details are. The hover cards went with it: each
|
|
51
|
-
* hover prop is refused, naming the inspector.
|
|
30
|
+
* Its inspector is on unless `inspector={false}`, and a kind's own Details is
|
|
31
|
+
* its kind's `inspector`. The props the records replace are refused when the
|
|
32
|
+
* surface is built, each naming the form that replaces it.
|
|
52
33
|
*
|
|
53
34
|
* @packageDocumentation
|
|
54
35
|
*/
|
|
55
|
-
import { ArrayType,
|
|
56
|
-
import {
|
|
57
|
-
import { EastUI, Editing, RowSourceType } from "@elaraai/east-ui";
|
|
36
|
+
import { ArrayType, BooleanType, DictType, East, Expr, OptionType, StringType, StructType, isTypeEqual, none, some, variant, } from "@elaraai/east";
|
|
37
|
+
import { EastUI, RowSourceType } from "@elaraai/east-ui";
|
|
58
38
|
import { RecordSlicesChromeType, isRecordSlices } from "@elaraai/east-ui/internal";
|
|
59
|
-
import {
|
|
60
|
-
import { recordSources, sliceSourceNames } from "../utils/record-sources.js";
|
|
61
|
-
import {
|
|
62
|
-
import {
|
|
63
|
-
import {
|
|
64
|
-
import {
|
|
65
|
-
import {
|
|
66
|
-
|
|
67
|
-
// Where the flows come from
|
|
68
|
-
// ============================================================================
|
|
69
|
-
/** A record's commits, newest first: who changed it last, and when. */
|
|
70
|
-
export const FlowchartHistoryType = FunctionType([], OptionType(ArrayType(RecordCommitInfoType)));
|
|
71
|
-
/**
|
|
72
|
-
* The editing session's Save (#1246, #1247, FB22): the session's keyed batch —
|
|
73
|
-
* the open flow's insert, update or delete by name — as the session hands it,
|
|
74
|
-
* bytes of `Editing.Types.ChangeSet(Flowchart.Types.Flow, String)`, sent as
|
|
75
|
-
* one commit and answered as the session's Save is: over a record, one patch
|
|
76
|
-
* through its patch mutation by `Record.onApply(record, { keyed: true })`;
|
|
77
|
-
* over the host's flows or flow, one patch of that value through the host's
|
|
78
|
-
* `onApply`, handed the batch's request id with it (#1275).
|
|
79
|
-
*/
|
|
80
|
-
export const FlowchartSessionApplyType = AsyncFunctionType([BlobType], Editing.Types.ApplyResult);
|
|
81
|
-
/**
|
|
82
|
-
* A record of flows by name, bound with its patch mutation — what the
|
|
83
|
-
* renderer reads the flows from and commits to, as the query builder's
|
|
84
|
-
* `QueriesHandleType` is the saved queries record's.
|
|
85
|
-
*
|
|
86
|
-
* @property read - The record's flows
|
|
87
|
-
* @property history - Its commits, newest first
|
|
88
|
-
* @property commit - Its patch write, awaited: a request id and the patch, answered by the outcome
|
|
89
|
-
* @property apply - The editing session's Apply through that patch write ({@link FlowchartSessionApplyType})
|
|
90
|
-
*/
|
|
91
|
-
export const FlowchartFlowsHandleType = StructType({
|
|
92
|
-
read: FunctionType([], FlowchartFlowsType),
|
|
93
|
-
history: FlowchartHistoryType,
|
|
94
|
-
commit: StructType({ patch: AsyncFunctionType([StringType, PatchType(FlowchartFlowsType)], RecordOutcomeType) }),
|
|
95
|
-
apply: FlowchartSessionApplyType,
|
|
96
|
-
});
|
|
97
|
-
/**
|
|
98
|
-
* The host's commit of its flows' edits (#1247, #1275): the session's request
|
|
99
|
-
* id and one patch of the flows, as a record's patch write takes them, answered
|
|
100
|
-
* as the editing session's Save is. A Retry after a write with no answer hands
|
|
101
|
-
* the same id again, so a host that keys its write by it — as e3's `commit.patch`
|
|
102
|
-
* does — writes once.
|
|
103
|
-
*/
|
|
104
|
-
export const FlowchartFlowsApplyType = AsyncFunctionType([StringType, PatchType(FlowchartFlowsType)], Editing.Types.ApplyResult);
|
|
105
|
-
/**
|
|
106
|
-
* The host's commit of its one flow's edits (#1247, #1275): the session's
|
|
107
|
-
* request id and the flow's own patch, answered as the editing session's Save
|
|
108
|
-
* is — a Retry handing the same id again.
|
|
109
|
-
*/
|
|
110
|
-
export const FlowchartFlowApplyType = AsyncFunctionType([StringType, PatchType(FlowchartFlowType)], Editing.Types.ApplyResult);
|
|
111
|
-
/**
|
|
112
|
-
* The host's flows: its value, of either type, and — when the host takes the
|
|
113
|
-
* flowchart's edits — the session's Save through the host's `onApply` (#1247,
|
|
114
|
-
* FB22), which hands the host the batch's request id and one patch of its own
|
|
115
|
-
* value's type (#1275).
|
|
116
|
-
*
|
|
117
|
-
* @property flows - Flows by name
|
|
118
|
-
* @property flow - One flow
|
|
119
|
-
*/
|
|
120
|
-
export const FlowchartDataType = VariantType({
|
|
121
|
-
flows: StructType({ value: FlowchartFlowsType, apply: OptionType(FlowchartSessionApplyType) }),
|
|
122
|
-
flow: StructType({ value: FlowchartFlowType, apply: OptionType(FlowchartSessionApplyType) }),
|
|
123
|
-
});
|
|
124
|
-
/**
|
|
125
|
-
* Where a flowchart's flows come from.
|
|
126
|
-
*
|
|
127
|
-
* @property record - A record of flows by name, bound with its patch mutation, read whole
|
|
128
|
-
* @property paged - A record of flows by name its slice's `flows` source pages (#1346): the record's identity, the
|
|
129
|
-
* window of the flows the rail narrows it to, a flow read by its name whatever the narrowing, a page of a narrowing
|
|
130
|
-
* of the Flows tab's own search, the record's commits and the session's Save
|
|
131
|
-
* @property data - The host's flows by name, or one flow: the arm its value's type picked
|
|
132
|
-
*/
|
|
133
|
-
export const FlowchartSourceType = VariantType({
|
|
134
|
-
record: FlowchartFlowsHandleType,
|
|
135
|
-
paged: StructType({
|
|
136
|
-
recordId: StringType,
|
|
137
|
-
window: FlowchartWindowType,
|
|
138
|
-
entry: FlowchartReadEntryType,
|
|
139
|
-
search: FlowchartSearchType,
|
|
140
|
-
history: FlowchartHistoryType,
|
|
141
|
-
apply: FlowchartSessionApplyType,
|
|
142
|
-
}),
|
|
143
|
-
data: FlowchartDataType,
|
|
144
|
-
});
|
|
39
|
+
import { typeText } from "../schedule/window.js";
|
|
40
|
+
import { recordSources, sliceSourceNames, templatesSource } from "../utils/record-sources.js";
|
|
41
|
+
import { vocabularyWord } from "../utils/vocabulary.js";
|
|
42
|
+
import { FlowchartCanvasType, buildCanvas } from "./canvas.js";
|
|
43
|
+
import { flowchartIndexedRows } from "./details.js";
|
|
44
|
+
import { isFlowchartKind, } from "./kinds.js";
|
|
45
|
+
import { FlowchartLibraryTabType, buildFlowchartLibrary, flowchartTabSources } from "./library.js";
|
|
46
|
+
import { FlowchartDecisionKindType, FlowchartLaneKindType, FlowchartNarrowedType, FlowchartStateKindType, FlowchartTransitionKindType, } from "./types.js";
|
|
145
47
|
// ============================================================================
|
|
146
|
-
// The
|
|
48
|
+
// The payload
|
|
147
49
|
// ============================================================================
|
|
50
|
+
/** Each source's shown keys on the wire, by the source's name. */
|
|
51
|
+
const ShownType = DictType(StringType, RowSourceType(ArrayType(StringType)));
|
|
148
52
|
/**
|
|
149
|
-
* The
|
|
150
|
-
*
|
|
151
|
-
* — a state's, a transition's — in place of that kind's form, as the Sheet's
|
|
152
|
-
* own Details (SB58) and a Plan event kind's inspector are: the row as bytes,
|
|
153
|
-
* and the writer that takes the edited row back as bytes.
|
|
53
|
+
* The app's own words for what the Flowchart draws of its own (#1516), every one resolved: a transition's kinds. A
|
|
54
|
+
* kind's noun is its own `name` (ruled 5 Nov 2026), so these are the words no kind names.
|
|
154
55
|
*
|
|
155
|
-
* @property
|
|
156
|
-
* @property
|
|
56
|
+
* @property planned - A transition as it was designed (`Planned`)
|
|
57
|
+
* @property observed - A transition as it was seen to run (`Observed`)
|
|
157
58
|
*/
|
|
158
|
-
export const
|
|
159
|
-
state: OptionType(RowInspectorType),
|
|
160
|
-
transition: OptionType(RowInspectorType),
|
|
161
|
-
});
|
|
162
|
-
// ============================================================================
|
|
163
|
-
// The payload
|
|
164
|
-
// ============================================================================
|
|
165
|
-
/** Each source's narrowed keys on the wire, by the source's name. */
|
|
166
|
-
const NarrowedType = DictType(StringType, RowSourceType(ArrayType(StringType)));
|
|
59
|
+
export const FlowchartVocabularyType = StructType({ planned: StringType, observed: StringType });
|
|
167
60
|
/**
|
|
168
|
-
* The `Flowchart` renderer's payload: the
|
|
61
|
+
* The `Flowchart` renderer's payload: the Flowchart's interface (§3).
|
|
169
62
|
*
|
|
170
|
-
* @property canvas - What the canvas draws its
|
|
171
|
-
* @property
|
|
172
|
-
* @property
|
|
63
|
+
* @property canvas - What the canvas draws with besides its kinds ({@link FlowchartCanvasType})
|
|
64
|
+
* @property states - The states, each a card in its lane
|
|
65
|
+
* @property transitions - The transitions between them; `none`, no transitions
|
|
66
|
+
* @property lanes - The lanes, the canvas's columns; `none`, one column
|
|
67
|
+
* @property decisions - The decisions, each a lettered diamond on the transitions that name it; `none`, no decisions
|
|
173
68
|
* @property library - The library pane's tabs, in the order `library` lists them; none, no library pane
|
|
174
|
-
* @property slice - The
|
|
175
|
-
* @property
|
|
176
|
-
* @property
|
|
177
|
-
* @property
|
|
178
|
-
* @property
|
|
69
|
+
* @property slice - The rail's chrome over the one `Slice.bindRecords`; `none`, no rail
|
|
70
|
+
* @property shown - Each source's shown keys, paged through its own data, by the source's name: what a cards list's and a tab's cards follow, and what dims a narrowed-out row
|
|
71
|
+
* @property narrowed - How a narrowed-out row draws: hidden, or dimmed as context
|
|
72
|
+
* @property inspector - Whether the inspector pane shows: on unless `inspector={false}`
|
|
73
|
+
* @property vocabulary - The app's words for a transition's kinds (#1516)
|
|
74
|
+
* @property readOnly - No gesture, drop or inspector edit; selection stays
|
|
75
|
+
* @property name - Keeps the Flowchart's state apart, when a surface holds two
|
|
179
76
|
*/
|
|
180
77
|
export const FlowchartPayloadType = StructType({
|
|
181
78
|
canvas: FlowchartCanvasType,
|
|
182
|
-
|
|
183
|
-
|
|
79
|
+
states: FlowchartStateKindType,
|
|
80
|
+
transitions: OptionType(FlowchartTransitionKindType),
|
|
81
|
+
lanes: OptionType(FlowchartLaneKindType),
|
|
82
|
+
decisions: OptionType(FlowchartDecisionKindType),
|
|
184
83
|
library: ArrayType(FlowchartLibraryTabType),
|
|
185
84
|
slice: OptionType(RecordSlicesChromeType),
|
|
186
|
-
|
|
187
|
-
|
|
85
|
+
shown: ShownType,
|
|
86
|
+
narrowed: FlowchartNarrowedType,
|
|
87
|
+
inspector: BooleanType,
|
|
88
|
+
vocabulary: FlowchartVocabularyType,
|
|
188
89
|
readOnly: BooleanType,
|
|
189
90
|
name: OptionType(StringType),
|
|
190
91
|
});
|
|
@@ -196,378 +97,339 @@ export const FlowchartPayloadType = StructType({
|
|
|
196
97
|
*/
|
|
197
98
|
export const FlowchartComponent = EastUI.component("Flowchart", FlowchartPayloadType, { optional: true });
|
|
198
99
|
// ============================================================================
|
|
199
|
-
// The
|
|
100
|
+
// The Flowchart's shared keys
|
|
200
101
|
// ============================================================================
|
|
201
102
|
/**
|
|
202
|
-
* The names a
|
|
203
|
-
* frame's panes — their open tab and collapsed state
|
|
204
|
-
*
|
|
205
|
-
* library's cards land (#1249).
|
|
103
|
+
* The names a Flowchart keeps its viewer's state under, by its `name`: its
|
|
104
|
+
* frame's panes — their open tab and collapsed state — its library's id, LR ·
|
|
105
|
+
* TD, and its drop surface, where its library's cards land.
|
|
206
106
|
*
|
|
207
107
|
* @remarks
|
|
208
|
-
* As the Plan's `planKeys` and the
|
|
209
|
-
* surface keep apart only when each is named
|
|
210
|
-
* flow together, and turn together, as the query builder's open query is
|
|
211
|
-
* shared by its id.
|
|
108
|
+
* As the Plan's `planKeys` and the Schematic's `schematicKeys`: two
|
|
109
|
+
* Flowcharts on one surface keep apart only when each is named.
|
|
212
110
|
*
|
|
213
|
-
* @param name - The
|
|
111
|
+
* @param name - The Flowchart's name, when a surface holds more than one; omitted, the one Flowchart
|
|
214
112
|
* @returns The keys
|
|
215
113
|
*/
|
|
216
114
|
export function flowchartKeys(name) {
|
|
217
115
|
const suffix = name === undefined ? "" : `.${name}`;
|
|
218
116
|
return {
|
|
219
117
|
frame: `flowchart${suffix}.frame`,
|
|
220
|
-
flow: `flowchart${suffix}.flow`,
|
|
221
118
|
library: `flowchart.library${suffix}`,
|
|
222
119
|
orientation: `flowchart${suffix}.orientation`,
|
|
223
120
|
surface: `flowchart${suffix}.surface`,
|
|
224
121
|
};
|
|
225
122
|
}
|
|
226
|
-
/** The
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
/** The
|
|
237
|
-
const
|
|
123
|
+
/** The refusal of the flows: the kinds over the app's records replace them (R1). */
|
|
124
|
+
const RECORDS = "the Flowchart takes no `record`, `data`, `flow` or `onApply` — its records are its kinds: " +
|
|
125
|
+
"states={Flowchart.states(Record.bind(steps), { label, lane, order })}, transitions={Flowchart.transitions(Record.bind(moves), { from, to })}, " +
|
|
126
|
+
"lanes={Flowchart.lanes(Data.bind(phases), { label })} and decisions={Flowchart.decisions(Data.bind(rules), { label })}";
|
|
127
|
+
/** The refusal of a row mapper: a kind maps its record's fields to its roles (R2). */
|
|
128
|
+
const MAPPERS = "a kind maps its record's fields to its roles — Flowchart.states(record, { label, lane, order }), " +
|
|
129
|
+
"Flowchart.transitions(record, { from, to, decision }), Flowchart.lanes(record, { label, order }) and Flowchart.decisions(record, { label })";
|
|
130
|
+
/** The refusal of a callback for an edit: the editing session's gestures replace them. */
|
|
131
|
+
const SESSION = "every gesture is a transaction of the Flowchart's editing session, and Save writes each record through its patch door — " +
|
|
132
|
+
"bind a kind with Record.bind(record), its record declaring patch: mutation.patch(), to edit it";
|
|
133
|
+
/** The refusal of a hover card: the inspector replaces them. */
|
|
134
|
+
const HOVER = "the inspector shows what is selected, and a kind's own Details is its kind's `inspector`: " +
|
|
135
|
+
"Flowchart.states(record, { …, inspector: East.function([RowType, FunctionType([RowType], NullType)], UIComponentType, ($, row, update) => …) })";
|
|
136
|
+
/** The refusal of a size: the Flowchart fills the box it is given. */
|
|
137
|
+
const SIZE = "the Flowchart fills the box it is given — give it a box of its own height: <Box height=\"560px\"><Flowchart … /></Box>";
|
|
138
|
+
/** Each prop the records and the editing session replace, with the form that replaces it. */
|
|
139
|
+
const REMOVED = {
|
|
140
|
+
record: RECORDS,
|
|
141
|
+
data: RECORDS,
|
|
142
|
+
flow: RECORDS,
|
|
143
|
+
onApply: RECORDS,
|
|
144
|
+
window: "the states and the transitions read through their sources of the slice, `states` and `transitions` — " +
|
|
145
|
+
"slice={{ slice: Slice.bindRecords(key, { states: { source: Data.bindPaged(steps, { indexes }) } }) }}",
|
|
146
|
+
links: "the transitions are `transitions`: transitions={Flowchart.transitions(record, { from, to })}",
|
|
147
|
+
triggers: "the decisions are `decisions`: decisions={Flowchart.decisions(record, { label })}",
|
|
148
|
+
state: MAPPERS,
|
|
149
|
+
link: MAPPERS,
|
|
150
|
+
lane: MAPPERS,
|
|
151
|
+
trigger: MAPPERS,
|
|
152
|
+
height: SIZE,
|
|
153
|
+
maxHeight: SIZE,
|
|
154
|
+
density: "the canvas draws at one rhythm — leave `density` out",
|
|
155
|
+
linkMode: SESSION,
|
|
156
|
+
onCreateLink: SESSION,
|
|
157
|
+
onDeleteLink: SESSION,
|
|
158
|
+
onAddLane: SESSION,
|
|
159
|
+
onRenameLane: SESSION,
|
|
160
|
+
onDeleteLane: SESSION,
|
|
161
|
+
onAddState: SESSION,
|
|
162
|
+
onEditState: SESSION,
|
|
163
|
+
onMoveState: SESSION,
|
|
164
|
+
stateHover: HOVER,
|
|
165
|
+
linkHover: HOVER,
|
|
166
|
+
triggerHover: HOVER,
|
|
167
|
+
affordances: "it moved into `slice`: slice={{ slice: Slice.bindRecords(key, { … }), affordances }}",
|
|
168
|
+
};
|
|
169
|
+
/** Every prop `<Flowchart>` takes. */
|
|
170
|
+
const PROPS = new Set([
|
|
171
|
+
"states", "transitions", "lanes", "decisions", "slice", "narrowed", "library", "inspector", "vocabulary", "readOnly", "name",
|
|
172
|
+
"orientation", "freshness", "minimap", "legend", "onSelectState", "onSelectLink", "onSelectTrigger", "onTracePath", "canConnect", "narrow",
|
|
173
|
+
]);
|
|
174
|
+
/** The canvas's props, which the payload's `canvas` carries. */
|
|
175
|
+
const CANVAS = [
|
|
176
|
+
"orientation", "freshness", "minimap", "legend", "onSelectState", "onSelectLink", "onSelectTrigger", "onTracePath", "canConnect", "narrow",
|
|
177
|
+
];
|
|
178
|
+
/** The declaration each kind's prop takes, as a refusal names it. */
|
|
179
|
+
const DECLARE = {
|
|
180
|
+
states: "Flowchart.states(record, { label, lane?, order? })",
|
|
181
|
+
transitions: "Flowchart.transitions(record, { from, to, decision? })",
|
|
182
|
+
lanes: "Flowchart.lanes(record, { label, order? })",
|
|
183
|
+
decisions: "Flowchart.decisions(record, { label, owner?, queue? })",
|
|
184
|
+
};
|
|
238
185
|
/**
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
186
|
+
* Reads one kind's prop, checked to hold a kind of its sort.
|
|
187
|
+
*
|
|
188
|
+
* @param sort - The prop
|
|
189
|
+
* @param given - What it was given
|
|
190
|
+
* @returns The kind; `undefined` when it is left out
|
|
191
|
+
* @throws {Error} When it holds anything but a kind of its sort, naming the declaration it takes — and the prop the kind it holds belongs under
|
|
242
192
|
*/
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const SLICE = "Flowchart: `slice` takes { slice } — slice={{ slice: Slice.bindRecords(key, { flows, … }) }} over a record of flows; the bare handle is gone, and a flow built from the host's tables (Flowchart.over over `data`) is never narrowed: narrow its rows in the task that builds them";
|
|
252
|
-
/** What the flowchart's slice narrows, as the refusal of a source nothing names says it. */
|
|
253
|
-
const NARROWS = "its flows, and the templates lists and tabs that name a source";
|
|
193
|
+
function kindOf(sort, given) {
|
|
194
|
+
if (given === undefined)
|
|
195
|
+
return undefined;
|
|
196
|
+
if (isFlowchartKind(given, sort))
|
|
197
|
+
return given;
|
|
198
|
+
const other = ["states", "transitions", "lanes", "decisions"].find((s) => isFlowchartKind(given, s));
|
|
199
|
+
throw new Error(`Flowchart: \`${sort}\` is ${DECLARE[sort]} over the app's record` + (other === undefined ? "" : ` — and this is ${DECLARE[other]}: give it as \`${other}\``));
|
|
200
|
+
}
|
|
254
201
|
/**
|
|
255
|
-
*
|
|
202
|
+
* How a narrowed-out row draws, on the wire; and whether it is dimmed, when
|
|
203
|
+
* each kind read through its source reads every row and the renderer draws
|
|
204
|
+
* what the narrowing leaves out as context.
|
|
256
205
|
*
|
|
257
|
-
* @param
|
|
258
|
-
* @
|
|
259
|
-
* @
|
|
260
|
-
* @returns The refusal
|
|
206
|
+
* @param narrowed - The Flowchart's `narrowed`
|
|
207
|
+
* @returns It on the wire, and whether a narrowed-out row is dimmed
|
|
208
|
+
* @throws {Error} For a `narrowed` of another form, naming the forms it takes
|
|
261
209
|
*/
|
|
262
|
-
function
|
|
263
|
-
|
|
210
|
+
function narrowedOf(narrowed) {
|
|
211
|
+
if (narrowed !== undefined && narrowed !== "hide" && narrowed !== "dim") {
|
|
212
|
+
throw new Error("Flowchart: `narrowed` is \"hide\" (the default), which leaves what the narrowing leaves out off the canvas, or \"dim\", which draws it as context");
|
|
213
|
+
}
|
|
214
|
+
const dim = narrowed === "dim";
|
|
215
|
+
return { wire: East.value(variant(dim ? "dim" : "hide", null), FlowchartNarrowedType), dim };
|
|
264
216
|
}
|
|
265
217
|
/**
|
|
266
|
-
* The inspector pane
|
|
267
|
-
* `true`; none for `false`; and each kind's own Details where `{ state,
|
|
268
|
-
* transition }` gives them, checked against the row's type and wrapped over
|
|
269
|
-
* bytes, as the Sheet's own Details are.
|
|
218
|
+
* The inspector pane: on unless `false`.
|
|
270
219
|
*
|
|
271
|
-
* @param inspector - The
|
|
272
|
-
* @returns
|
|
273
|
-
* @throws {Error}
|
|
274
|
-
*
|
|
275
|
-
* type than `(Row, (Row) => Null) => UIComponentType`
|
|
220
|
+
* @param inspector - The Flowchart's `inspector`
|
|
221
|
+
* @returns Whether the pane shows
|
|
222
|
+
* @throws {Error} For an `inspector` that is no Boolean — the `{ state, transition }` the Flowchart took before among
|
|
223
|
+
* them — naming the kind's own `inspector`, the one way to give it Details
|
|
276
224
|
*/
|
|
277
225
|
function inspectorOf(inspector) {
|
|
226
|
+
if (inspector === undefined || inspector === true)
|
|
227
|
+
return true;
|
|
278
228
|
if (inspector === false)
|
|
279
|
-
return
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
if (inspector === null || typeof inspector !== "object" || inspector instanceof Expr || Array.isArray(inspector)) {
|
|
284
|
-
throw new Error("Flowchart: `inspector` is on by default — inspector={false} removes the pane, and inspector={{ state, transition }} gives a state or a transition its own Details, each an East function over the row and its writer");
|
|
285
|
-
}
|
|
286
|
-
const given = inspector;
|
|
287
|
-
for (const key of Object.keys(given)) {
|
|
288
|
-
if (key !== "state" && key !== "transition") {
|
|
289
|
-
throw new Error(`Flowchart: \`inspector\` gives a state or a transition its own Details — { state, transition } — and \`${key}\` is neither: every other kind's Details are its form`);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
const state = given.state === undefined ? none : some(rowInspector(given.state, FlowchartStateType, rowRefusal("state", "State", "state")));
|
|
293
|
-
const transition = given.transition === undefined ? none : some(rowInspector(given.transition, FlowchartLinkType, rowRefusal("transition", "Link", "link")));
|
|
294
|
-
return East.value(some({ state, transition }), OptionType(FlowchartInspectorType));
|
|
295
|
-
}
|
|
296
|
-
/** The refusal of a record not bound with its patch mutation. */
|
|
297
|
-
const UNBOUND = "Flowchart: `record` is an e3 record bound with its patch mutation — Record.bind(record), its record declaring patch: mutation.patch()";
|
|
298
|
-
/** A field of a struct type, or `undefined`. */
|
|
299
|
-
function fieldOf(type, name) {
|
|
300
|
-
return type?.type === "Struct" ? type.fields[name] : undefined;
|
|
229
|
+
return false;
|
|
230
|
+
throw new Error("Flowchart: `inspector` is true or false — on unless false — and a kind's own Details is its kind's `inspector`: " +
|
|
231
|
+
"Flowchart.states(record, { …, inspector: East.function([RowType, FunctionType([RowType], NullType)], UIComponentType, ($, row, update) => …) })");
|
|
301
232
|
}
|
|
233
|
+
/** Each kind's noun as the vocabulary would give it, by the kind its own `name` names instead. */
|
|
234
|
+
const KIND_WORDS = new Map([["state", "states"], ["transition", "transitions"], ["lane", "lanes"], ["decision", "decisions"]]);
|
|
235
|
+
/** Each kind's declaration, its `name` among its options, as a refusal of a kind's noun in the vocabulary shows it. */
|
|
236
|
+
const NAMED = {
|
|
237
|
+
states: "Flowchart.states(record, { label, name })",
|
|
238
|
+
transitions: "Flowchart.transitions(record, { from, to, name })",
|
|
239
|
+
lanes: "Flowchart.lanes(record, { label, name })",
|
|
240
|
+
decisions: "Flowchart.decisions(record, { label, name })",
|
|
241
|
+
};
|
|
302
242
|
/**
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
243
|
+
* The Flowchart's words, resolved: a transition's kinds, each the app's or its default.
|
|
244
|
+
*
|
|
245
|
+
* @param given - The Flowchart's `vocabulary`
|
|
246
|
+
* @returns Both words
|
|
247
|
+
* @throws {Error} For a `vocabulary` that is no object; an entry naming a kind's noun, naming the kind's `name` that
|
|
248
|
+
* gives it; an entry the Flowchart has no word for; and an entry given empty
|
|
249
|
+
* @internal
|
|
307
250
|
*/
|
|
308
|
-
function
|
|
309
|
-
if (
|
|
310
|
-
throw new Error(
|
|
311
|
-
const type = Expr.type(record);
|
|
312
|
-
const read = fieldOf(type, "read");
|
|
313
|
-
if (read === undefined || read.type !== "Function" || read.inputs.length !== 0
|
|
314
|
-
|| fieldOf(type, "history")?.type !== "Function" || fieldOf(type, "binding") === undefined) {
|
|
315
|
-
throw new Error(UNBOUND);
|
|
251
|
+
export function flowchartVocabulary(given) {
|
|
252
|
+
if (given !== undefined && (typeof given !== "object" || given === null || given instanceof Expr)) {
|
|
253
|
+
throw new Error("Flowchart: `vocabulary` takes the app's words for a transition's kinds — vocabulary={{ planned?, observed? }}");
|
|
316
254
|
}
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
const door = fieldOf(fieldOf(type, "commit"), "patch");
|
|
327
|
-
if (door === undefined || !isTypeEqual(door, AsyncFunctionType([StringType, PatchType(FlowchartFlowsType)], RecordOutcomeType))) {
|
|
328
|
-
throw new Error(`${UNBOUND}, and this binding ${door === undefined ? "has no `patch`" : "has a `patch` that takes another patch than the record's"}`);
|
|
255
|
+
const words = (given ?? {});
|
|
256
|
+
for (const entry of Object.keys(words)) {
|
|
257
|
+
const kind = KIND_WORDS.get(entry);
|
|
258
|
+
if (kind !== undefined) {
|
|
259
|
+
throw new Error(`Flowchart: \`vocabulary.${entry}\` is not one of its words — a kind's noun is its own \`name\`: ${NAMED[kind]}`);
|
|
260
|
+
}
|
|
261
|
+
if (entry !== "planned" && entry !== "observed") {
|
|
262
|
+
throw new Error(`Flowchart: \`vocabulary.${entry}\` is not one of its words — it takes \`planned\` and \`observed\`, a transition's kinds, and a kind's noun is its own \`name\``);
|
|
263
|
+
}
|
|
329
264
|
}
|
|
330
|
-
// The session's Apply (#1246): its keyed batch, decoded at its own type
|
|
331
|
-
// and committed as it is — each flow's insert, update or delete by name —
|
|
332
|
-
// through the patch door, by Record.onApply's keyed form.
|
|
333
|
-
const keyed = RecordBind.onApply(record, { keyed: true });
|
|
334
|
-
const batchType = Editing.Types.ChangeSet(FlowchartFlowType, StringType);
|
|
335
|
-
const apply = East.asyncFunction([BlobType], Editing.Types.ApplyResult, ($, blob) => {
|
|
336
|
-
const commit = $.const(keyed);
|
|
337
|
-
return commit(blob.decodeBeast(batchType, "v2"));
|
|
338
|
-
});
|
|
339
|
-
return { handle: record, apply };
|
|
340
|
-
}
|
|
341
|
-
/** The record arm: the checked record, its read, its history, its patch write and the session's Apply through it, read whole. */
|
|
342
|
-
function recordArm(record) {
|
|
343
|
-
const { handle, apply } = checkedRecord(record);
|
|
344
265
|
return {
|
|
345
|
-
|
|
346
|
-
|
|
266
|
+
planned: vocabularyWord("Flowchart", "planned", words.planned, "Planned"),
|
|
267
|
+
observed: vocabularyWord("Flowchart", "observed", words.observed, "Observed"),
|
|
347
268
|
};
|
|
348
269
|
}
|
|
349
270
|
/**
|
|
350
|
-
* The
|
|
351
|
-
* the
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
|
|
356
|
-
function pagedArm(record, flows) {
|
|
357
|
-
const { handle, apply } = checkedRecord(record);
|
|
358
|
-
const view = flowchartWindow(flows.part, flows.rows);
|
|
359
|
-
return { many: true, source: variant("paged", { recordId: handle.binding.name, ...view, history: handle.history, apply }) };
|
|
360
|
-
}
|
|
361
|
-
/** The host's flows as an expression: an expression, a bind handle's read, or a value of either type. */
|
|
362
|
-
function dataValue(data) {
|
|
363
|
-
if (data instanceof Expr) {
|
|
364
|
-
const read = fieldOf(Expr.type(data), "read");
|
|
365
|
-
return read !== undefined && read.type === "Function" && read.inputs.length === 0
|
|
366
|
-
? data.read()
|
|
367
|
-
: data;
|
|
368
|
-
}
|
|
369
|
-
if (isValueOf(data, FlowchartFlowsType))
|
|
370
|
-
return East.value(data, FlowchartFlowsType);
|
|
371
|
-
if (isValueOf(data, FlowchartFlowType))
|
|
372
|
-
return East.value(data, FlowchartFlowType);
|
|
373
|
-
throw new Error("Flowchart: `data` is Flowchart.Types.Flows, flows by name, or Flowchart.Types.Flow, one flow — a value, an expression or a bind handle of either; Flowchart.over builds one flow from an app's tables — and this value is neither");
|
|
374
|
-
}
|
|
375
|
-
/** The host's `onApply`, checked against a request id and the patch of its flows' type. */
|
|
376
|
-
function applyOf(onApply, applyType, value) {
|
|
377
|
-
const apply = (onApply instanceof Expr ? onApply : East.value(onApply, applyType));
|
|
378
|
-
const type = Expr.type(apply);
|
|
379
|
-
if (!isTypeEqual(type, applyType)) {
|
|
380
|
-
throw new Error(`Flowchart: \`onApply\` commits \`data\`'s edits, one patch of the value at a time — an East.asyncFunction from the session's request id and PatchType(${value}), [StringType, PatchType(${value})], to Editing.Types.ApplyResult; a Retry hands the same id again — and this one is ${printType(type)}`);
|
|
381
|
-
}
|
|
382
|
-
return apply;
|
|
383
|
-
}
|
|
384
|
-
/**
|
|
385
|
-
* The data arm: the host's flows, of either type, and — when the host takes
|
|
386
|
-
* the edits — the session's Save through its `onApply` (#1247, FB22). The
|
|
387
|
-
* session's batch is keyed by name, as over a record: over flows by name it is
|
|
388
|
-
* restated as one patch of the flows, each change the open flow's insert,
|
|
389
|
-
* update or delete by name, as `Record.onApply(record, { keyed: true })`
|
|
390
|
-
* restates it for a record — never the whole value replaced, so the host's
|
|
391
|
-
* other flows stay as they are; over one flow, its one change is the flow's
|
|
392
|
-
* own patch. The host's `onApply` is handed the batch's request id with it
|
|
393
|
-
* (#1275) — the same id on a Retry, which resends the same batch — and answers
|
|
394
|
-
* the session.
|
|
271
|
+
* The rows a source of the slice narrows (#1522): its binding's joined row,
|
|
272
|
+
* from the type of the binding its part holds.
|
|
273
|
+
*
|
|
274
|
+
* @param narrowing - The Flowchart's `slice`, a `Slice.bindRecords`
|
|
275
|
+
* @param source - The source
|
|
276
|
+
* @returns The row's struct; `undefined` where the part's binding pages no such rows
|
|
395
277
|
*/
|
|
396
|
-
function
|
|
397
|
-
const
|
|
398
|
-
const
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
}
|
|
403
|
-
if (onApply === undefined)
|
|
404
|
-
return { many, source: variant("data", variant(many ? "flows" : "flow", { value, apply: none })) };
|
|
405
|
-
// The host's commit, its patch opaque here, as in `Record.onApply`; its runtime type is exact.
|
|
406
|
-
const host = applyOf(onApply, many ? FlowchartFlowsApplyType : FlowchartFlowApplyType, many ? "Flowchart.Types.Flows" : "Flowchart.Types.Flow");
|
|
407
|
-
const batchType = Editing.Types.ChangeSet(FlowchartFlowType, StringType);
|
|
408
|
-
const apply = many
|
|
409
|
-
? East.asyncFunction([BlobType], Editing.Types.ApplyResult, ($, blob) => {
|
|
410
|
-
const commit = $.const(host);
|
|
411
|
-
const batch = $.const(blob.decodeBeast(batchType, "v2"));
|
|
412
|
-
// Each change is its flow's insert, update or delete, by name: the
|
|
413
|
-
// batch's own values and patches, carrying what the flow was when
|
|
414
|
-
// the edit began.
|
|
415
|
-
const ops = $.let(new Map(), DictType(StringType, dictPatchOpsType(FlowchartFlowType)));
|
|
416
|
-
$.for(batch.changes, ($, change) => {
|
|
417
|
-
$.match(change.patch, {
|
|
418
|
-
replace: ($, swap) => {
|
|
419
|
-
$.match(swap.after, {
|
|
420
|
-
some: ($, after) => {
|
|
421
|
-
$.match(swap.before, {
|
|
422
|
-
none: ($) => { $(ops.insert(change.id, variant("insert", after))); },
|
|
423
|
-
some: ($, before) => { $(ops.insert(change.id, variant("update", East.diff(before, after)))); },
|
|
424
|
-
});
|
|
425
|
-
},
|
|
426
|
-
none: ($) => {
|
|
427
|
-
$.match(swap.before, { some: ($, before) => { $(ops.insert(change.id, variant("delete", before))); } });
|
|
428
|
-
},
|
|
429
|
-
});
|
|
430
|
-
},
|
|
431
|
-
patch: ($, entry) => {
|
|
432
|
-
$.match(entry, { some: ($, update) => { $(ops.insert(change.id, variant("update", update))); } });
|
|
433
|
-
},
|
|
434
|
-
});
|
|
435
|
-
});
|
|
436
|
-
return commit(batch.requestId, variant("patch", ops));
|
|
437
|
-
})
|
|
438
|
-
: East.asyncFunction([BlobType], Editing.Types.ApplyResult, ($, blob) => {
|
|
439
|
-
const commit = $.const(host);
|
|
440
|
-
const batch = $.const(blob.decodeBeast(batchType, "v2"));
|
|
441
|
-
// One flow is one entry, changed in place: its change is the flow's own patch.
|
|
442
|
-
const result = $.let(variant("rejected", [{ entry: "", row: none, field: none,
|
|
443
|
-
message: "One flow is changed in place: Save never adds or removes it" }]), Editing.Types.ApplyResult);
|
|
444
|
-
$.for(batch.changes, ($, change) => {
|
|
445
|
-
$.match(change.patch, {
|
|
446
|
-
replace: ($, swap) => {
|
|
447
|
-
$.match(swap.before, {
|
|
448
|
-
some: ($, before) => {
|
|
449
|
-
$.match(swap.after, { some: ($, after) => { $.assign(result, commit(batch.requestId, East.diff(before, after))); } });
|
|
450
|
-
},
|
|
451
|
-
});
|
|
452
|
-
},
|
|
453
|
-
patch: ($, entry) => {
|
|
454
|
-
$.match(entry, { some: ($, update) => { $.assign(result, commit(batch.requestId, update)); } });
|
|
455
|
-
},
|
|
456
|
-
});
|
|
457
|
-
});
|
|
458
|
-
return result;
|
|
459
|
-
});
|
|
460
|
-
return { many, source: variant("data", variant(many ? "flows" : "flow", { value, apply: some(apply) })) };
|
|
278
|
+
function sliceSourceRows(narrowing, source) {
|
|
279
|
+
const handle = East.value(narrowing.slice);
|
|
280
|
+
const sources = Expr.type(handle).fields["sources"];
|
|
281
|
+
const part = sources?.type === "Struct" ? sources.fields[source] : undefined;
|
|
282
|
+
const binding = part?.type === "Struct" ? part.fields["source"] : undefined;
|
|
283
|
+
return binding === undefined ? undefined : flowchartIndexedRows(binding)?.row;
|
|
461
284
|
}
|
|
462
285
|
/**
|
|
463
|
-
* Creates the
|
|
286
|
+
* Creates the Flowchart's payload alone — what `<Flowchart>` returns through
|
|
464
287
|
* the `Flowchart` carrier — for the tests and the renderer's fixtures, which
|
|
465
288
|
* read it whole.
|
|
466
289
|
*
|
|
467
|
-
* @param props - The
|
|
290
|
+
* @param props - The Flowchart's props ({@link FlowchartProps})
|
|
468
291
|
* @returns An East expression of {@link FlowchartPayloadType}
|
|
469
|
-
* @throws {Error} Naming the prop and the remedy:
|
|
470
|
-
* `
|
|
471
|
-
*
|
|
472
|
-
*
|
|
473
|
-
* `Slice.bindRecords`, or holding a source
|
|
474
|
-
* `
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
*
|
|
479
|
-
*
|
|
480
|
-
* and the patch of `data`'s type; a table or row mapper, which
|
|
481
|
-
* `Flowchart.over` takes; `height` or `maxHeight`, which the box the
|
|
482
|
-
* flowchart fills sets; a callback for an edit, or `linkMode`, which the
|
|
483
|
-
* editing session's gestures replace; a hover card's builder (`stateHover`,
|
|
484
|
-
* `linkHover`, `triggerHover`), which the inspector replaces; `density`,
|
|
485
|
-
* which the canvas's one rhythm replaces; an `inspector` of another kind
|
|
486
|
-
* than a Boolean or `{ state, transition }`, a key other than those two, or
|
|
487
|
-
* a kind's own Details of another type than `(Row, (Row) => Null) =>
|
|
488
|
-
* UIComponentType`; and each of the library's refusals (`library.ts`'s
|
|
489
|
-
* `buildLibrary`): a tab listed twice, the Flows tab over one flow, a tab's
|
|
490
|
-
* source the slice lacks, a data tab's rows of neither an Array nor a
|
|
491
|
-
* `Dict<String, T>` — a record's for a templates list or a tab that follows
|
|
492
|
-
* a source — and a `drop` of another type than its tab's
|
|
292
|
+
* @throws {Error} Naming the prop and the remedy (§3): `record`, `data`, `flow` and `onApply`, which its kinds replace;
|
|
293
|
+
* `window`; the tables and row mappers; `height` and `maxHeight`; `density`; a callback for an edit and `linkMode`;
|
|
294
|
+
* a hover card's builder; `affordances` outside `slice`; a prop the Flowchart doesn't take; no states; a kind's prop
|
|
295
|
+
* holding no kind of its sort; a state's lane with no lanes, and lanes beside states that name none; a transition's
|
|
296
|
+
* decision with no decisions; a `slice` that is not `{ slice }`, or not `Slice.bindRecords`, or holding a source
|
|
297
|
+
* nothing names, a `lanes` or `decisions` source, or the brush; a cards list naming no source of the slice, or its
|
|
298
|
+
* kind's own; details naming no source of the slice, a kind's own, or one over rows of another type than theirs
|
|
299
|
+
* (#1522); a `narrowed` of another form; an `inspector` that is no Boolean, and `inspector={false}` beside a
|
|
300
|
+
* details' read shown in the inspector alone; each of `vocabulary`'s refusals ({@link flowchartVocabulary}); a
|
|
301
|
+
* `name` that is no string; each of the library's refusals (`library.ts`); and each kind's refusals of its binding
|
|
302
|
+
* and its details (`kinds.ts`, `details.ts`)
|
|
493
303
|
* @internal
|
|
494
304
|
*/
|
|
495
305
|
export function createFlowchartPayload(props) {
|
|
496
|
-
const
|
|
497
|
-
for (const
|
|
498
|
-
if (
|
|
499
|
-
throw new Error(`Flowchart: \`${
|
|
500
|
-
}
|
|
306
|
+
const given = props;
|
|
307
|
+
for (const [prop, remedy] of Object.entries(REMOVED)) {
|
|
308
|
+
if (prop in given)
|
|
309
|
+
throw new Error(`Flowchart: \`${prop}\` is gone — ${remedy}`);
|
|
501
310
|
}
|
|
502
|
-
for (const
|
|
503
|
-
if (
|
|
504
|
-
throw new Error(`Flowchart: \`${
|
|
311
|
+
for (const prop of Object.keys(given)) {
|
|
312
|
+
if (!PROPS.has(prop) && !(prop === "children" && given[prop] === undefined)) {
|
|
313
|
+
throw new Error(`Flowchart: \`${prop}\` is not a prop of <Flowchart> — it takes ${[...PROPS].join(", ")}`);
|
|
505
314
|
}
|
|
506
315
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
316
|
+
// The kinds (R1): the states, and beside them the transitions, the lanes and the decisions.
|
|
317
|
+
const states = kindOf("states", given.states);
|
|
318
|
+
if (states === undefined)
|
|
319
|
+
throw new Error(`Flowchart: needs its states — states={${DECLARE.states}}, over the app's record`);
|
|
320
|
+
const transitions = kindOf("transitions", given.transitions);
|
|
321
|
+
const lanes = kindOf("lanes", given.lanes);
|
|
322
|
+
const decisions = kindOf("decisions", given.decisions);
|
|
323
|
+
// A role naming another kind's key needs that kind (R3).
|
|
324
|
+
if (states.lane && lanes === undefined) {
|
|
325
|
+
throw new Error("Flowchart: a state's lane names a lane — give lanes={Flowchart.lanes(…)}, or drop lane");
|
|
513
326
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
327
|
+
if (lanes !== undefined && !states.lane) {
|
|
328
|
+
throw new Error("Flowchart: the lanes are columns: give the states their lane — Flowchart.states(record, { label, lane })");
|
|
329
|
+
}
|
|
330
|
+
if (transitions?.decision === true && decisions === undefined) {
|
|
331
|
+
throw new Error("Flowchart: a transition's decision names a decision — give decisions={Flowchart.decisions(…)}, or drop decision");
|
|
332
|
+
}
|
|
333
|
+
const kinds = [
|
|
334
|
+
{ sort: "states", kind: states },
|
|
335
|
+
...(transitions === undefined ? [] : [{ sort: "transitions", kind: transitions }]),
|
|
336
|
+
...(lanes === undefined ? [] : [{ sort: "lanes", kind: lanes }]),
|
|
337
|
+
...(decisions === undefined ? [] : [{ sort: "decisions", kind: decisions }]),
|
|
338
|
+
];
|
|
339
|
+
// The narrowing (R4): one Slice.bindRecords, its states and transitions sources each named after its kind.
|
|
340
|
+
const slice = given.slice;
|
|
341
|
+
if (slice !== undefined && (slice instanceof Expr || typeof slice !== "object" || slice === null || !("slice" in slice))) {
|
|
342
|
+
throw new Error("Flowchart: `slice` takes { slice } — slice={{ slice: Slice.bindRecords(key, { … }), affordances?, persist? }}, " +
|
|
343
|
+
"its sources `states` and `transitions` each named after the kind it narrows");
|
|
518
344
|
}
|
|
519
|
-
// The narrowing's props #1346 retired, each refused by name for an app that still passes it.
|
|
520
|
-
if (window !== undefined)
|
|
521
|
-
throw new Error(WINDOW);
|
|
522
|
-
if ("affordances" in canvas)
|
|
523
|
-
throw new Error("Flowchart: `affordances` moved into `slice` — slice={{ slice, affordances }}");
|
|
524
|
-
if (slice !== undefined && (slice instanceof Expr || typeof slice !== "object" || slice === null || !("slice" in slice)))
|
|
525
|
-
throw new Error(SLICE);
|
|
526
345
|
const narrowing = slice;
|
|
527
346
|
if (narrowing?.affordances?.includes("brush") === true) {
|
|
528
347
|
throw new Error("Flowchart: `slice`'s affordances list \"brush\", and a flowchart has no continuous axis to brush along — mount fields, search, presets or summary");
|
|
529
348
|
}
|
|
530
|
-
|
|
531
|
-
|
|
349
|
+
const sliceNames = sliceSourceNames(narrowing);
|
|
350
|
+
for (const whole of ["lanes", "decisions"]) {
|
|
351
|
+
if (sliceNames.includes(whole))
|
|
352
|
+
throw new Error(`Flowchart: the ${whole} are read whole: drop the ${whole} source`);
|
|
532
353
|
}
|
|
533
|
-
|
|
534
|
-
|
|
354
|
+
// Each kind's cards are a record of their own, their list naming its source of the slice — refused with the change
|
|
355
|
+
// to make before a source no list names is.
|
|
356
|
+
const cardSources = [];
|
|
357
|
+
if (narrowing === undefined || isRecordSlices(narrowing.slice)) {
|
|
358
|
+
for (const { sort, kind } of kinds) {
|
|
359
|
+
if (!kind.hasTemplates)
|
|
360
|
+
continue;
|
|
361
|
+
const source = templatesSource("Flowchart", "Flowchart.templates(rows, { …, source })", kind.templatesSource, sliceNames);
|
|
362
|
+
if (source === "states" || source === "transitions") {
|
|
363
|
+
throw new Error(`Flowchart: the ${sort}' cards name the source '${source}', which narrows the ${source} — ` +
|
|
364
|
+
"a kind's cards are a record of their own, and their own source of the slice");
|
|
365
|
+
}
|
|
366
|
+
cardSources.push(source);
|
|
367
|
+
}
|
|
535
368
|
}
|
|
536
|
-
|
|
537
|
-
|
|
369
|
+
// The details the rail's picks weigh (#1522, R44): each names a source of the slice over the details' own record.
|
|
370
|
+
const weighing = [];
|
|
371
|
+
if (narrowing === undefined || isRecordSlices(narrowing.slice)) {
|
|
372
|
+
for (const { sort, kind } of kinds) {
|
|
373
|
+
const by = sort === "states" || sort === "transitions" ? kind.weighedBy : undefined;
|
|
374
|
+
if (by === undefined)
|
|
375
|
+
continue;
|
|
376
|
+
if (by.source === "states" || by.source === "transitions") {
|
|
377
|
+
throw new Error(`Flowchart: the ${sort}' details name the source '${by.source}', which narrows the ${by.source} — the picks that ` +
|
|
378
|
+
"weigh details are a source of the slice over the details' own record");
|
|
379
|
+
}
|
|
380
|
+
if (narrowing === undefined || !sliceNames.includes(by.source)) {
|
|
381
|
+
throw new Error(`Flowchart: the ${sort}' details name the source '${by.source}', ` +
|
|
382
|
+
`${narrowing === undefined ? "and the Flowchart has no slice" : `which is none of the slice's sources (${sliceNames.join(", ")})`} — ` +
|
|
383
|
+
`slice={{ slice: Slice.bindRecords(key, { …, ${by.source}: { source: Data.bindPaged(record, { indexes }), fields } }) }}`);
|
|
384
|
+
}
|
|
385
|
+
const rows = sliceSourceRows(narrowing, by.source);
|
|
386
|
+
if (rows !== undefined && !isTypeEqual(rows, by.rowType)) {
|
|
387
|
+
throw new Error(`Flowchart: the ${sort}' details name the source '${by.source}', whose rows are ${typeText(rows)} — and the details' ` +
|
|
388
|
+
`are ${typeText(by.rowType)}: name the source over the details' record`);
|
|
389
|
+
}
|
|
390
|
+
weighing.push(by.source);
|
|
391
|
+
}
|
|
538
392
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
// another kind is refused below, as such.
|
|
542
|
-
if (narrowing === undefined || isRecordSlices(narrowing.slice))
|
|
543
|
-
checkTemplatesSources(library, sliceSourceNames(narrowing));
|
|
544
|
-
// The slice's sources: its flows, and each a templates list or a tab names.
|
|
545
|
-
const named = librarySources(library);
|
|
393
|
+
const tabSources = flowchartTabSources(given.library);
|
|
394
|
+
const names = [...new Set(["states", ...(transitions === undefined ? [] : ["transitions"]), ...cardSources, ...tabSources, ...weighing])];
|
|
546
395
|
const sources = recordSources(narrowing, {
|
|
547
|
-
builder: "Flowchart", names
|
|
548
|
-
|
|
396
|
+
builder: "Flowchart", names,
|
|
397
|
+
what: "its states and its transitions, each by the source named after it, and the cards lists, tabs and details that name a source",
|
|
398
|
+
});
|
|
399
|
+
const library = buildFlowchartLibrary(given.library, {
|
|
400
|
+
kinds: kinds.map(({ sort, kind }) => ({ sort, rowType: kind.rowType, templates: kind.hasTemplates })),
|
|
401
|
+
sources: sources.names,
|
|
549
402
|
});
|
|
550
|
-
const
|
|
551
|
-
|
|
552
|
-
|
|
403
|
+
const inspector = inspectorOf(given.inspector);
|
|
404
|
+
// A details' read shown in the inspector alone is drawn nowhere without its pane (#1507).
|
|
405
|
+
if (!inspector && (states.inspectorReads || transitions?.inspectorReads === true)) {
|
|
406
|
+
throw new Error("Flowchart: the inspector's reads have no pane — drop inspector={false}, or show them on the canvas");
|
|
553
407
|
}
|
|
408
|
+
const vocabulary = flowchartVocabulary(given.vocabulary);
|
|
409
|
+
const narrowed = narrowedOf(given.narrowed);
|
|
410
|
+
const name = given.name;
|
|
411
|
+
if (name !== undefined && (typeof name !== "string" || name === "")) {
|
|
412
|
+
throw new Error("Flowchart: `name` keeps the Flowchart's state apart — a string, needed only when one surface holds two");
|
|
413
|
+
}
|
|
414
|
+
const canvas = buildCanvas(Object.fromEntries(CANVAS.filter((prop) => given[prop] !== undefined).map((prop) => [prop, given[prop]])));
|
|
554
415
|
return Expr.block(($) => {
|
|
416
|
+
// Each source bound once: a kind reads its own source inside its functions.
|
|
555
417
|
const bound = sources.bind($);
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
: record !== undefined ? recordArm(record) : dataArm(data, onApply);
|
|
559
|
-
if (flow !== undefined && !arm.many) {
|
|
560
|
-
throw new Error("Flowchart: `flow` opens one of many flows first, and this `data` is one flow, Flowchart.Types.Flow — leave `flow` out");
|
|
561
|
-
}
|
|
418
|
+
const shown = East.value(new Map(Object.entries(bound.keys)), ShownType);
|
|
419
|
+
// Dimmed, a kind read through its source reads every row: the renderer draws what the narrowing leaves out as context.
|
|
562
420
|
return East.value({
|
|
563
|
-
canvas
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
421
|
+
canvas,
|
|
422
|
+
states: states.build(bound.parts["states"], narrowed.dim),
|
|
423
|
+
transitions: transitions === undefined ? none : some(transitions.build(bound.parts["transitions"], narrowed.dim)),
|
|
424
|
+
lanes: lanes === undefined ? none : some(lanes.build(undefined, false)),
|
|
425
|
+
decisions: decisions === undefined ? none : some(decisions.build(undefined, false)),
|
|
426
|
+
library,
|
|
567
427
|
slice: sources.chrome,
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
428
|
+
shown,
|
|
429
|
+
narrowed: narrowed.wire,
|
|
430
|
+
inspector,
|
|
431
|
+
vocabulary,
|
|
432
|
+
readOnly: given.readOnly ?? false,
|
|
571
433
|
name: name === undefined ? none : some(name),
|
|
572
434
|
}, FlowchartPayloadType);
|
|
573
435
|
});
|