@ngis/plugin-ui 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +25 -0
  3. package/dist/index.cjs +71 -0
  4. package/dist/index.d.ts +114 -0
  5. package/dist/index.mjs +69 -0
  6. package/dist/src/api/analysis.d.ts +140 -0
  7. package/dist/src/api/resources.d.ts +530 -0
  8. package/dist/src/api/scenes.d.ts +251 -0
  9. package/dist/src/api/users.d.ts +22 -0
  10. package/dist/src/api/workflows.d.ts +191 -0
  11. package/dist/src/components/plugin-ui/AttributeTable.d.ts +26 -0
  12. package/dist/src/components/plugin-ui/BatchTable.d.ts +47 -0
  13. package/dist/src/components/plugin-ui/ChartCanvas.d.ts +14 -0
  14. package/dist/src/components/plugin-ui/ExtentPicker.d.ts +22 -0
  15. package/dist/src/components/plugin-ui/FieldSelect.d.ts +23 -0
  16. package/dist/src/components/plugin-ui/Flow.d.ts +256 -0
  17. package/dist/src/components/plugin-ui/ModelSelect.d.ts +36 -0
  18. package/dist/src/components/plugin-ui/ParamForm.d.ts +63 -0
  19. package/dist/src/components/plugin-ui/PickerField.d.ts +52 -0
  20. package/dist/src/components/plugin-ui/ResourceSelect.d.ts +37 -0
  21. package/dist/src/components/plugin-ui/ResultActions.d.ts +48 -0
  22. package/dist/src/components/plugin-ui/RunButton.d.ts +49 -0
  23. package/dist/src/components/plugin-ui/StatChart.d.ts +66 -0
  24. package/dist/src/components/plugin-ui/TaskChrome.d.ts +35 -0
  25. package/dist/src/components/plugin-ui/TaskList.d.ts +29 -0
  26. package/dist/src/components/plugin-ui/TaskStatus.d.ts +55 -0
  27. package/dist/src/components/plugin-ui/batch-model.d.ts +442 -0
  28. package/dist/src/components/plugin-ui/flow-inputs.d.ts +61 -0
  29. package/dist/src/components/plugin-ui/flow-model.d.ts +303 -0
  30. package/dist/src/components/plugin-ui/flow-ports.d.ts +155 -0
  31. package/dist/src/components/plugin-ui/param-form-data.d.ts +122 -0
  32. package/dist/src/components/plugin-ui/param-form-model.d.ts +187 -0
  33. package/dist/src/components/plugin-ui/param-widgets.d.ts +88 -0
  34. package/dist/src/components/plugin-ui/picker-data.d.ts +141 -0
  35. package/dist/src/components/plugin-ui/picker-model.d.ts +150 -0
  36. package/dist/src/components/plugin-ui/recipe-model.d.ts +320 -0
  37. package/dist/src/components/plugin-ui/result-data.d.ts +112 -0
  38. package/dist/src/components/plugin-ui/result-model.d.ts +96 -0
  39. package/dist/src/components/plugin-ui/run-data.d.ts +118 -0
  40. package/dist/src/components/plugin-ui/run-model.d.ts +179 -0
  41. package/dist/src/components/plugin-ui/stat-chart-model.d.ts +168 -0
  42. package/dist/src/components/plugin-ui/validation-messages.d.ts +18 -0
  43. package/dist/src/components/plugin-ui/w2-contracts.d.ts +151 -0
  44. package/dist/src/components/plugin-ui/w3-contracts.d.ts +328 -0
  45. package/dist/src/components/plugin-ui/w4-contracts.d.ts +510 -0
  46. package/dist/src/components/ui/button.d.ts +12 -0
  47. package/dist/src/components/ui/checkbox.d.ts +4 -0
  48. package/dist/src/components/ui/column-resize-handle.d.ts +23 -0
  49. package/dist/src/components/ui/dropdown-menu.d.ts +25 -0
  50. package/dist/src/components/ui/input.d.ts +3 -0
  51. package/dist/src/components/ui/label.d.ts +4 -0
  52. package/dist/src/components/ui/popover.d.ts +10 -0
  53. package/dist/src/components/ui/select.d.ts +15 -0
  54. package/dist/src/components/ui/switch.d.ts +6 -0
  55. package/dist/src/domain/map/types.d.ts +128 -0
  56. package/dist/src/features/gis/components/GisAttributeTable.d.ts +56 -0
  57. package/dist/src/features/gis/hooks/useDatasetFeatureWindow.d.ts +51 -0
  58. package/dist/src/lib/api-error.d.ts +81 -0
  59. package/dist/src/lib/api.d.ts +82 -0
  60. package/dist/src/lib/auth-session.d.ts +22 -0
  61. package/dist/src/lib/hooks/useColumnResize.d.ts +57 -0
  62. package/dist/src/lib/raster-color-layer/RasterColorLayer.d.ts +48 -0
  63. package/dist/src/lib/raster-color-layer/TileGrid.d.ts +31 -0
  64. package/dist/src/lib/raster-color-layer/colorRamp.d.ts +18 -0
  65. package/dist/src/lib/raster-color-layer/shaders/raster-color.frag.d.ts +2 -0
  66. package/dist/src/lib/raster-color-layer/shaders/raster-color.vert.d.ts +2 -0
  67. package/dist/src/lib/raster-color-layer/zoomInterpolate.d.ts +2 -0
  68. package/dist/src/lib/utils.d.ts +2 -0
  69. package/dist/src/sdk/facets/types.d.ts +370 -0
  70. package/dist/src/sdk/host-api.d.ts +256 -0
  71. package/dist/src/sdk/map-api.d.ts +288 -0
  72. package/dist/src/sdk/panels.d.ts +130 -0
  73. package/dist/src/types/analysis.d.ts +205 -0
  74. package/dist/src/types/common.d.ts +17 -0
  75. package/dist/src/types/extensions.d.ts +560 -0
  76. package/dist/src/types/gis.d.ts +242 -0
  77. package/dist/src/types/market-social.d.ts +378 -0
  78. package/dist/src/types/workflow.d.ts +83 -0
  79. package/package.json +59 -0
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Pure projections behind `RunButton` / `TaskStatus` / `TaskList` (Stage 14 Y4a).
3
+ *
4
+ * No React, no host, no clock — the `picker-model.ts` discipline. Everything a
5
+ * run or a task *means* is decided here so it can be asserted without a DOM,
6
+ * and so the two places a parameter map is built (the pre-flight
7
+ * `validate-execution` body and the `tasks.run` payload) are literally the same
8
+ * function composed twice. A differing coercion between those two is the bug
9
+ * that makes a validate pass and the run fail, which is why F14/YD34 froze
10
+ * {@link toWireParams} in `w2-contracts.ts` and why nothing here re-implements
11
+ * it.
12
+ *
13
+ * ## The one thing to read before changing anything below
14
+ *
15
+ * **`validate-execution` takes `params` and `bindings` separately;
16
+ * `POST /api/analysis/tasks` takes one flat `params` map.** F14.3's request body
17
+ * has `bindings: [{port_name, file_ids}]` beside `params`, while
18
+ * `CreateAnalysisTaskParams` (`src/api/analysis.ts:72-78`) and therefore
19
+ * `NgisTaskRunRequest.params` (`src/sdk/facets/types.ts:325-332`) are
20
+ * `Record<string, string>` and nothing else. So the run payload is the validate
21
+ * payload **plus** the bindings folded in as parameters, comma-joined per F14.2's
22
+ * `resource-multi` rule. {@link runParamsOf} is that fold, and it is defined as a
23
+ * superset of {@link validateParamsOf} rather than as a second construction.
24
+ *
25
+ * ## Lifecycle stages, and why there are two lanes
26
+ *
27
+ * F13.2 keeps `NgisTaskStatus` (the *run*) and `NgisTaskStage` (the *lifecycle
28
+ * including scene integration*) apart, and `status: "SUCCESS"` with
29
+ * `stage: "waiting_scene_integration"` is a real, common state. Surfacing it is
30
+ * the whole reason these components exist, so {@link taskLifecycle} reports the
31
+ * two axes separately and never collapses them.
32
+ *
33
+ * The lanes differ because the branches differ, and the difference is read off
34
+ * the facet rather than assumed: the DIRECT projection reuses
35
+ * `analysis-task-runtime.ts`, which really does write
36
+ * `waiting_output_datasets` and `refreshing_scene`
37
+ * (`analysis-task-runtime.ts:339`, `:361`), while `toWorkflowTaskState`
38
+ * (`src/sdk/facets/tasks.ts:225-272`) can only ever produce
39
+ * `queued`/`running`/`waiting_scene_integration`/`success`/`failed`/`cancelled`.
40
+ * A single nine-step lane would leave a workflow run with two segments that can
41
+ * never fill.
42
+ */
43
+ import type { NgisTaskOutput, NgisTaskStage, NgisTaskState } from "../../sdk/facets/types";
44
+ import type { NgisExecutionValidation } from "../../types/analysis";
45
+ import { type NgisPortBinding, type NgisRunSubmission } from "./w2-contracts";
46
+ /**
47
+ * A binding contributes nothing when it resolves to no file ids.
48
+ *
49
+ * F14.4 is explicit that absent, `null`, `""` and `[]` are all **unbound, never
50
+ * "bound to empty"** — so an empty `fileIds` must not become `PORT: ""`. The
51
+ * server would read that as a supplied-but-invalid file id and answer with a
52
+ * parameter error about a value the author never entered.
53
+ */
54
+ export declare function bindingParams(bindings: readonly NgisPortBinding[]): Record<string, string>;
55
+ /**
56
+ * The `params` half of the pre-flight body.
57
+ *
58
+ * Option values plus **output names**: an `output-name` widget's value is a
59
+ * parameter on the wire (F14.2 — it names the output, it is not a file id), and
60
+ * `execution_validation.py:208-218` relies on seeing it, or auto-fills it.
61
+ * Bindings are *not* here — `validate-execution` takes those in their own field.
62
+ */
63
+ export declare function validateParamsOf(submission: NgisRunSubmission): Record<string, string>;
64
+ /**
65
+ * The flat `params` map `host.tasks.run` takes — {@link validateParamsOf} plus
66
+ * the bindings.
67
+ *
68
+ * Bindings are spread **last** deliberately. The three groups are disjoint by
69
+ * role, so a collision means the submission is malformed; when one happens the
70
+ * resource binding is the value the user actually chose in a picker, and losing
71
+ * it to a stale option value would submit a run against the wrong dataset.
72
+ * Deterministic beats clever.
73
+ */
74
+ export declare function runParamsOf(submission: NgisRunSubmission): Record<string, string>;
75
+ /**
76
+ * Whether a submission can be submitted, and what to say when it cannot.
77
+ *
78
+ * The block/advise split is **read from `w2-contracts.ts`, never re-derived**
79
+ * (YD34): F14.9 puts `parameter_errors` / `output_errors` /
80
+ * `missing_parameters` and binding-level `errors` on the blocking side and
81
+ * `warnings` on the advisory side, and two components disagreeing about that
82
+ * line is the same class of bug as two coercions.
83
+ */
84
+ export interface NgisRunGate {
85
+ /** `false` ⇒ the action is inert and a reason is rendered (F14.10). */
86
+ readonly ready: boolean;
87
+ /** Blocking server messages, in F14.9's order. Empty when `ready`. */
88
+ readonly blocking: readonly string[];
89
+ /** Never blocks. Rendered beside a ready action, not instead of it. */
90
+ readonly advisory: readonly string[];
91
+ }
92
+ /**
93
+ * `validation === null` is **not ready**, and that is F14.9 rather than caution:
94
+ * server validation runs *always once before submit*, so a run that has never
95
+ * been validated has not met the precondition. The caller distinguishes "not
96
+ * validated yet" from "validated and blocked" by the empty `blocking` list, and
97
+ * renders its own reason for the former.
98
+ */
99
+ export declare function runGate(submission: NgisRunSubmission | null, validation: NgisExecutionValidation | null): NgisRunGate;
100
+ /**
101
+ * DIRECT's lane. Every member is a stage `analysis-task-runtime.ts` can actually
102
+ * write; `queued` is in the union and reachable through `normalizeTaskStatus`,
103
+ * and a lane step the runtime skips reads as *behind us*, not as stuck — see
104
+ * {@link taskLifecycle}.
105
+ */
106
+ export declare const NGIS_DIRECT_STAGE_LANE: readonly NgisTaskStage[];
107
+ /**
108
+ * WORKFLOW's lane — four steps, because that is all the polling projection can
109
+ * produce. There is no `submitting` (the invoke returns an instance that is
110
+ * already `PENDING`), no `waiting_output_datasets` and no `refreshing_scene`.
111
+ */
112
+ export declare const NGIS_WORKFLOW_STAGE_LANE: readonly NgisTaskStage[];
113
+ export declare function taskStageLane(kind: NgisTaskState["kind"]): readonly NgisTaskStage[];
114
+ export type NgisTaskSegmentState = "done" | "current" | "open";
115
+ export interface NgisTaskRailSegment {
116
+ readonly stage: NgisTaskStage;
117
+ readonly state: NgisTaskSegmentState;
118
+ }
119
+ export interface NgisTaskLifecycle {
120
+ readonly lane: readonly NgisTaskStage[];
121
+ readonly segments: readonly NgisTaskRailSegment[];
122
+ /** `failed` or `cancelled`: the lifecycle stopped off-lane. No segment is
123
+ * `current`, because claiming a position would claim progress the server
124
+ * never reported. */
125
+ readonly halted: boolean;
126
+ /** `status === "SUCCESS"` — the computation finished. */
127
+ readonly runComplete: boolean;
128
+ /** `stage === "success"` — the lifecycle finished, scene integration
129
+ * included. **`runComplete && !integrated` is the distinction these
130
+ * components exist to render.** */
131
+ readonly integrated: boolean;
132
+ }
133
+ /**
134
+ * The rail, from one `NgisTaskState`.
135
+ *
136
+ * A stage the branch skipped is marked `done` rather than left `open`: the task
137
+ * is demonstrably past it, and rendering it as pending would invent a step the
138
+ * run is waiting on. A stage that is not a lane member at all (only `failed` and
139
+ * `cancelled`) sets `halted` and leaves every segment `open`.
140
+ */
141
+ export declare function taskLifecycle(state: NgisTaskState): NgisTaskLifecycle;
142
+ /**
143
+ * Whether this state can still change. Mirrors `isActiveTaskState`'s intent from
144
+ * the other side: a run that is `SUCCESS` but not yet integrated is **not**
145
+ * terminal, because the stage is still moving.
146
+ */
147
+ export declare function isTerminalTaskState(state: NgisTaskState): boolean;
148
+ /**
149
+ * Cancellable while the *run* is still going. Deliberately keyed on `status`,
150
+ * not `stage`: once the computation has succeeded there is nothing left to
151
+ * cancel, and offering the action during scene integration would promise
152
+ * something `tasks.cancel` cannot deliver on either branch.
153
+ */
154
+ export declare function canCancelTaskState(state: NgisTaskState): boolean;
155
+ /**
156
+ * **There is no workflow SSE.** `watch` polls for `kind: "workflow"` and
157
+ * `NgisTaskState.logs` is permanently `[]` there (`facets/tasks.ts:261`), so a
158
+ * component that renders "no output yet" over a workflow task is telling the
159
+ * author to wait for something that will never arrive. Half of all tasks have no
160
+ * log stream, and this function is how a caller says so instead.
161
+ */
162
+ export declare function hasLogStream(state: NgisTaskState): boolean;
163
+ /** Newest activity first — the order both task surfaces already present. */
164
+ export declare function sortTaskStates(states: readonly NgisTaskState[]): readonly NgisTaskState[];
165
+ /**
166
+ * The primary output, or the first — F14.4's `"@run"` resolution rule.
167
+ *
168
+ * **Delegates to the canonical rule (`V-127`, YD45).** This was one of three
169
+ * implementations of one clause; binding resolution is where `"@run"` is decided
170
+ * now, so `flow-model.ts` owns the rule and this is the projection onto a task
171
+ * state. Behaviour is unchanged — neither this nor `ngisPrimaryTaskOutput`
172
+ * filters on `fileId`, which is the case the three disagreed about and which the
173
+ * canonical rule decides explicitly (see its doc comment).
174
+ *
175
+ * The **explicit return annotation is part of the fix**: without it the emitted
176
+ * `.d.ts` widened away the `| null`, so every consumer of the built package
177
+ * believed this function always returns an output.
178
+ */
179
+ export declare function primaryTaskOutput(state: NgisTaskState): NgisTaskOutput | null;
@@ -0,0 +1,168 @@
1
+ /**
2
+ * `<StatChart>`'s whole projection: `NgisChartSpec` → an ECharts option, a table
3
+ * twin, and the advisories that go beneath it (Stage 14 Y4b, **F14.3**).
4
+ *
5
+ * ## Why the projection is a pure module and not part of the component
6
+ *
7
+ * The `picker-model.ts` / `picker-data.ts` discipline Y2 established, applied to
8
+ * a chart: everything decidable from the spec alone lives here and is asserted
9
+ * without a DOM and **without loading ECharts at all** (the only ECharts
10
+ * reference below is a type-only import, erased at runtime). What is left in
11
+ * `StatChart.tsx` is mounting, theming and the table toggle.
12
+ *
13
+ * That split is also what keeps `viz.chart` worker-ready: `NgisChartSpec` is
14
+ * declarative data (F14.3 / F13.1 L6), and the whole chart is a function of it.
15
+ * A spec that carried a formatter callback or a raw ECharts option would not
16
+ * survive Stage 15's worker tier, and nothing here needs one.
17
+ *
18
+ * ## The colour system is computed, not chosen
19
+ *
20
+ * The eight categorical slots below are the `dataviz` skill's validated default
21
+ * palette, **re-validated against this codebase's real surfaces** rather than
22
+ * the skill's defaults, because a contrast or CVD result only means something
23
+ * against the surface the chart actually renders on. Every plugin-ui component
24
+ * renders inside `.gis-theme` (Tenon, `DESIGN_new.md`), so the surfaces are the
25
+ * Tenon card steps — light `#efe9de`, dark `#0f1011`:
26
+ *
27
+ * ```
28
+ * light #efe9de : band PASS · chroma PASS · CVD adjacent worst ΔE 9.1 · normal-vision worst ΔE 19.6 · contrast WARN
29
+ * dark #0f1011 : band PASS · chroma PASS · CVD adjacent worst ΔE 8.4 · normal-vision worst ΔE 19.3 · contrast PASS
30
+ * ```
31
+ *
32
+ * The **light-mode contrast WARN is not dismissable** — four slots sit under
33
+ * 3:1 on parchment — so the relief it obliges is shipped: a legend is always
34
+ * present for two or more series, and every chart has a table twin one click
35
+ * away ({@link chartTable}). That is also why `StatChart` has a table toggle at
36
+ * all; it is an accessibility obligation, not a nicety.
37
+ *
38
+ * **Slot order is the CVD-safety mechanism, not decoration.** Do not reorder,
39
+ * do not extend past eight, and never generate a ninth hue — a generated hue is
40
+ * indistinguishable from an existing slot under simulated CVD. Past eight the
41
+ * tail is dropped with an advisory (and, for `pie`, folded into one `Other`
42
+ * segment, which is the part-to-whole answer).
43
+ *
44
+ * **Series colour follows the entity's slot index, never its rank.** Filtering
45
+ * a series out must not repaint the survivors, so nothing here sorts before
46
+ * assigning a colour — except `pie`, where the fold *is* the encoding.
47
+ */
48
+ import type { EChartsCoreOption } from "echarts/core";
49
+ import type { NgisChartSeries, NgisChartSpec } from "../../sdk/host-api";
50
+ export type NgisChartTheme = "light" | "dark";
51
+ /**
52
+ * The eight categorical slots, in frozen order. Both columns are the same eight
53
+ * hues stepped for their own surface — not two palettes.
54
+ */
55
+ export declare const NGIS_CHART_SERIES_COLORS: Readonly<Record<NgisChartTheme, readonly string[]>>;
56
+ /**
57
+ * Chart chrome. **Text never wears the data colour** — axis labels, legend text
58
+ * and tooltip labels are ink; identity comes from the coloured mark beside the
59
+ * text. `surface` is what the 2px separator gaps and the marker rings are
60
+ * painted in, so it must match the card the chart sits on.
61
+ */
62
+ export declare const NGIS_CHART_INK: Readonly<Record<NgisChartTheme, {
63
+ readonly surface: string;
64
+ readonly primary: string;
65
+ readonly secondary: string;
66
+ readonly muted: string;
67
+ readonly grid: string;
68
+ readonly axis: string;
69
+ }>>;
70
+ /** The token ceiling. A ninth hue is never generated (see the header). */
71
+ export declare const NGIS_CHART_MAX_SERIES = 8;
72
+ /** Part-to-whole at a glance stops working past this; the tail folds to `Other`. */
73
+ export declare const NGIS_CHART_MAX_PIE_SEGMENTS = 6;
74
+ /** Bar/column mark cap. The band's leftover is air, never a wider bar. */
75
+ export declare const NGIS_CHART_MAX_BAR_WIDTH = 24;
76
+ /** The 2px separator that does the separating — never a stroke around a mark. */
77
+ export declare const NGIS_CHART_SURFACE_GAP = 2;
78
+ export declare function chartSeriesColor(index: number, theme: NgisChartTheme): string;
79
+ /**
80
+ * What the chart could not do exactly as asked. Returned as **codes with their
81
+ * numbers**, never as text: this module is locale-free by construction, and the
82
+ * component translates under `GIS.pluginUi.run.chart.*`. Surfaced, never
83
+ * masked — the `ExtensionSettingsForm` rule.
84
+ */
85
+ export type NgisChartAdvisory =
86
+ /** The spec carries no plottable numbers. */
87
+ {
88
+ readonly id: "empty";
89
+ }
90
+ /** More than `NGIS_CHART_MAX_SERIES`; `dropped` series were not drawn. */
91
+ | {
92
+ readonly id: "seriesCapped";
93
+ readonly dropped: number;
94
+ }
95
+ /** A pie past `NGIS_CHART_MAX_PIE_SEGMENTS`; `folded` segments became `Other`. */
96
+ | {
97
+ readonly id: "pieFolded";
98
+ readonly folded: number;
99
+ }
100
+ /** `categories` is shorter than the longest series, so the tail has no label. */
101
+ | {
102
+ readonly id: "categoriesShort";
103
+ readonly missing: number;
104
+ }
105
+ /** `scatter` fell back to the point index because `categories` are not numeric. */
106
+ | {
107
+ readonly id: "scatterIndexed";
108
+ };
109
+ /** `true` when every category parses as a finite number — `scatter`'s x source. */
110
+ export declare function categoriesAreNumeric(categories: readonly string[] | undefined): boolean;
111
+ export declare function chartAdvisories(spec: NgisChartSpec): readonly NgisChartAdvisory[];
112
+ export interface NgisHistogramBins {
113
+ /** `bins + 1` edges, ascending. */
114
+ readonly edges: readonly number[];
115
+ /** One label per bin, `[lo, hi)`. */
116
+ readonly labels: readonly string[];
117
+ /** One count array per input series, over the shared edges. */
118
+ readonly counts: readonly (readonly number[])[];
119
+ }
120
+ /**
121
+ * **`histogram` reads `values` as raw observations, not as bar heights.** That
122
+ * is the whole difference between `histogram` and `bar` — `bar` takes heights
123
+ * already aligned to `categories`, and if `histogram` did too it would be an
124
+ * alias with a different name. Stated here because the frozen `NgisChartSpec`
125
+ * has no field to say which, and F14.3's five kinds have to differ in something.
126
+ *
127
+ * Bin width is **Freedman–Diaconis** (`2·IQR·n^(-1/3)`), which is robust to the
128
+ * long tails real analysis output produces, falling back to **Sturges**
129
+ * (`⌈log₂ n⌉ + 1`) when the IQR is zero — the degenerate case where FD would ask
130
+ * for an infinite number of bins.
131
+ *
132
+ * Every series is binned over **one shared edge set** computed from the pooled
133
+ * observations, so two distributions are actually comparable; binning each
134
+ * series on its own edges would put different x axes in one plot.
135
+ */
136
+ export declare function binHistogram(series: readonly NgisChartSeries[]): NgisHistogramBins;
137
+ export interface NgisChartTable {
138
+ readonly head: readonly string[];
139
+ readonly rows: readonly (readonly string[])[];
140
+ }
141
+ /**
142
+ * The WCAG-clean twin every chart has to have — and, on the light Tenon surface,
143
+ * the relief the palette's sub-3:1 slots oblige. Values are reachable here
144
+ * without hovering anything, so no tooltip ever *gates* a number.
145
+ *
146
+ * `head[0]` is intentionally empty rather than "Category": the caller supplies
147
+ * `xLabel` and this module holds no copy.
148
+ */
149
+ export declare function chartTable(spec: NgisChartSpec): NgisChartTable;
150
+ export interface NgisChartOptionLabels {
151
+ /** The folded pie tail's segment name. */
152
+ readonly other: string;
153
+ }
154
+ /**
155
+ * `NgisChartSpec` → the option `setOption` takes.
156
+ *
157
+ * Marks follow one fixed spec across all five kinds, so charts from different
158
+ * plugins read as one system: **≤24px bars with a 4px rounded cap and a square
159
+ * baseline · 2px lines with round joins · ≥8px markers carrying a 2px surface
160
+ * ring · hairline solid grid one step off the surface · a legend whenever there
161
+ * are two or more series and none when there is one** (the title already names a
162
+ * lone series, and a one-swatch box restates it).
163
+ *
164
+ * There is deliberately **no second y axis, ever**. Two measures of different
165
+ * scale are two charts or one indexed base — a dual-axis plot invents a
166
+ * correlation that is not in the data, and `NgisChartSpec` cannot express one.
167
+ */
168
+ export declare function toChartOption(spec: NgisChartSpec, theme: NgisChartTheme, labels: NgisChartOptionLabels): EChartsCoreOption;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * User-facing wording for the structured parts of `validate-execution`.
3
+ *
4
+ * The service still returns `parameter_errors` and most binding errors as free
5
+ * text, so those remain verbatim diagnostic detail. The two stable structured
6
+ * cases below must not leak backend English into the tool panel: users need an
7
+ * action (fill a parameter or bind an input), not an API-field name.
8
+ */
9
+ import type { NgisExecutionValidation } from "../../types/analysis";
10
+ export interface NgisValidationMessageLabels {
11
+ missingParameter: (name: string) => string;
12
+ requiredInputNotBound: (name: string) => string;
13
+ }
14
+ /**
15
+ * Formats only blocking server-validation messages. Blocking semantics remain
16
+ * in `isSubmitBlocked`; this function changes wording, never validation logic.
17
+ */
18
+ export declare function displayBlockingValidationMessages(validation: NgisExecutionValidation, labels: NgisValidationMessageLabels): readonly string[];
@@ -0,0 +1,151 @@
1
+ /**
2
+ * W2 shared contracts — authored at the **W2 kickoff**, read-only to Y3 and Y4.
3
+ *
4
+ * Stage 14's wave rule: every surface read by more than one session in a wave is
5
+ * authored at the kickoff, so neither agent needs live coordination with a
6
+ * sibling. Y3 owns `ParamForm`, Y4 owns `RunButton`/`TaskStatus`/`TaskList`/
7
+ * `ResultActions`/`AttributeTable`/`StatChart` — and the two meet at exactly
8
+ * three seams, all frozen here:
9
+ *
10
+ * 1. what a generated form hands a run action ({@link NgisRunSubmission})
11
+ * 2. the flow port ids they publish and read ({@link NGIS_W2_PORT_IDS})
12
+ * 3. which server messages block a submit ({@link isSubmitBlocked})
13
+ *
14
+ * Nothing here is a component. Nothing here imports React. Keeping it that way
15
+ * is what lets both sessions unit-test their halves of the seam without a DOM
16
+ * and without each other — the `picker-model.ts` / `picker-data.ts` split Y2
17
+ * established, applied to a cross-session boundary.
18
+ *
19
+ * Contract: F14.2 (widget vocabulary), F14.3 (validation DTOs), F14.5 (ports),
20
+ * F14.8 (presets), F14.9 (form lifecycle), F14.10 (no `disabled` prop).
21
+ */
22
+ import type { NgisExecutionValidation, NgisUiSchemaValueType, NgisWidgetKey } from "../../types/analysis";
23
+ /**
24
+ * A single generated-form value. Narrower than `unknown` on purpose: F14.2's
25
+ * `value_type` is one of four scalars, and every widget in the registry either
26
+ * produces one of them or produces a `string` encoding (`resource-multi` is a
27
+ * comma-joined file-id list, `extent` is not a param at all).
28
+ */
29
+ export type NgisParamValue = string | number | boolean | null;
30
+ export type NgisParamValues = Readonly<Record<string, NgisParamValue>>;
31
+ /**
32
+ * The wire form. `POST …/validate-execution` and the task API both take
33
+ * `params` as `Record<string, string>` (F14.3), so a form value crosses to the
34
+ * server through exactly this coercion and no other. Frozen here so Y3's
35
+ * pre-flight and Y4's submit cannot disagree about how `false` or `null` is
36
+ * spelled on the wire — the class of bug that makes a validate pass and the
37
+ * subsequent run fail.
38
+ */
39
+ export declare function toWireParams(values: NgisParamValues): Record<string, string>;
40
+ /** The inverse, for seeding a form from a preset or a saved recipe. */
41
+ export declare function fromWireValue(raw: string, valueType: NgisUiSchemaValueType): NgisParamValue;
42
+ /** One dataset binding, camelCase at the facet boundary (F14.3). */
43
+ export interface NgisPortBinding {
44
+ readonly portName: string;
45
+ readonly fileIds: readonly string[];
46
+ }
47
+ /**
48
+ * What a generated form hands a run action. **The only Y3 → Y4 data contract.**
49
+ *
50
+ * `params` carries option-role values only; `bindings` carries input-role
51
+ * resource ports; `outputNames` carries `output-name` widget values keyed by
52
+ * param name. Splitting them here rather than at submit time is deliberate:
53
+ * `validate-execution` takes the three separately, so a component that merged
54
+ * them would have to re-split with a second copy of the role rules.
55
+ */
56
+ export interface NgisRunSubmission {
57
+ readonly toolId: string;
58
+ readonly toolVersion: number;
59
+ readonly params: NgisParamValues;
60
+ readonly bindings: readonly NgisPortBinding[];
61
+ readonly outputNames: Readonly<Record<string, string>>;
62
+ }
63
+ /**
64
+ * Reserved port ids (F14.5's per-component table). A component's `id` prop
65
+ * overrides the *scope* id, never these member names.
66
+ */
67
+ export declare const NGIS_W2_PORT_IDS: {
68
+ /** `ParamForm` out (`record`), and every picker's out port. */
69
+ readonly value: "value";
70
+ /** `RunButton` out (`task`); `TaskStatus`/`TaskList`/`ResultActions`/`StatChart` in. */
71
+ readonly taskId: "taskId";
72
+ /** `FieldSelect` in — the parent resource port (`parentPortId`). */
73
+ readonly parent: "parent";
74
+ /** `AttributeTable` in, and `StatChart`'s alternative in. */
75
+ readonly resource: "resource";
76
+ };
77
+ export type NgisW2PortId = (typeof NGIS_W2_PORT_IDS)[keyof typeof NGIS_W2_PORT_IDS];
78
+ /**
79
+ * F14.10's single sanctioned publication out of a flow scope: the task id,
80
+ * written by the plugin as the bare key `taskId` and published by the host as
81
+ * `plugin:<pluginId>:taskId` (F14.11). Y4 writes it; nothing else publishes.
82
+ */
83
+ export declare const NGIS_TASK_ID_CONTEXT_KEY = "taskId";
84
+ /** F14.9's four names, frozen so Y3 does not invent a fifth. */
85
+ export type NgisParamFormPhase = "initialize" | "mutate" | "validate-client" | "validate-server";
86
+ export declare const NGIS_PARAM_FORM_PHASES: readonly NgisParamFormPhase[];
87
+ /** F14.9: server validation is debounced 400 ms, and always runs once before submit. */
88
+ export declare const NGIS_SERVER_VALIDATE_DEBOUNCE_MS = 400;
89
+ /**
90
+ * Per-field state. `altered` is the edit-protection flag: F14.9's *mutate*
91
+ * phase repopulates dependent lists and **must never overwrite a field whose
92
+ * `altered` is true**. `visible` is `depends_on` visibility, not enablement —
93
+ * F14.10 forbids a `disabled` prop, and a hidden field is not a disabled one.
94
+ */
95
+ export interface NgisFieldState {
96
+ readonly value: NgisParamValue;
97
+ readonly altered: boolean;
98
+ readonly hasBeenValidated: boolean;
99
+ readonly visible: boolean;
100
+ readonly errors: readonly string[];
101
+ }
102
+ export declare function initialFieldState(value: NgisParamValue): NgisFieldState;
103
+ /**
104
+ * A widget registry is **total over the union with no fallback** (F14.2/F14.9).
105
+ * Expressed as a mapped type so a missing key is a compile error rather than a
106
+ * runtime `undefined` that renders nothing — the failure mode a `Partial` plus
107
+ * a default widget would have hidden.
108
+ */
109
+ export type NgisWidgetRegistry<TWidget> = {
110
+ readonly [K in NgisWidgetKey]: TWidget;
111
+ };
112
+ /**
113
+ * F14.9: `parameter_errors` / `output_errors` / `missing_parameters` block a
114
+ * submit; `warnings` do not. Binding-level `errors` block too — an unresolved
115
+ * or `FAIL` port cannot run.
116
+ */
117
+ export declare function blockingValidationMessages(validation: NgisExecutionValidation): readonly string[];
118
+ export declare function isSubmitBlocked(validation: NgisExecutionValidation): boolean;
119
+ /** Advisory only — never blocks (F14.9). */
120
+ export declare function advisoryValidationMessages(validation: NgisExecutionValidation): readonly string[];
121
+ /**
122
+ * `data-slot` names reserved for W2. Two reasons they live in one frozen table:
123
+ * `first-party-plugins/scripts/verify-externals.mjs` fingerprints plugin-ui by
124
+ * these strings, and a duplicate across components would make that check
125
+ * ambiguous.
126
+ */
127
+ export declare const NGIS_W2_DATA_SLOTS: {
128
+ readonly paramForm: "ngis-param-form";
129
+ readonly paramField: "ngis-param-field";
130
+ readonly runButton: "ngis-run-button";
131
+ readonly taskStatus: "ngis-task-status";
132
+ readonly taskList: "ngis-task-list";
133
+ readonly resultActions: "ngis-result-actions";
134
+ readonly attributeTable: "ngis-attribute-table";
135
+ readonly statChart: "ngis-stat-chart";
136
+ };
137
+ /** F14.8: a preset value is a literal, an escaped literal, or a context read. */
138
+ export declare const NGIS_PRESET_CONTEXT_PREFIX = "$context:";
139
+ export type NgisPresetValue = {
140
+ readonly kind: "literal";
141
+ readonly value: string;
142
+ } | {
143
+ readonly kind: "context";
144
+ readonly key: string;
145
+ };
146
+ /**
147
+ * `$$` escapes a literal `$`. A `$context:` reference resolving to `null`,
148
+ * `undefined` or `""` refuses the launch with a message naming the key — the
149
+ * caller's job, but the parse is frozen here so both callers parse alike.
150
+ */
151
+ export declare function parsePresetValue(raw: string): NgisPresetValue;