@bitcobblers/wod-wiki-ui 0.10.42 → 0.35.2115

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/index.d.cts CHANGED
@@ -1,10 +1,12 @@
1
- import { Q as QueryExecutor } from './index-CTQ7Hrsa.cjs';
2
- export { B as ButtonAction, C as CursorFocusState, D as DefaultFrontmatterWidget, E as EditorDialect, a as EditorPresetOptions, b as EditorSection, c as EditorSectionSubtype, d as EditorSectionType, e as EmbedType, G as GeometryListener, N as NavigationHook, O as OverlayAction, f as QueryBlockPreviewOptions, R as RuntimePanelEntry, S as SectionRect, g as SectionState, W as WidgetConfig, h as WidgetProps, i as WidgetRegistry, j as activeCursorSection, k as addRuntimePanel, l as blockContentId, m as configureOverlayActions, n as cursorFocusExtension, o as dispatchAddRuntimePanel, p as dispatchExpandRuntimePanel, q as dispatchGutterHighlights, r as dispatchRemoveRuntimePanel, s as editingWidgetsField, t as editorPreset, u as editorTheme, v as embedPreviewDecorations, w as expandRuntimePanel, x as fenceCompletion, y as findQueryBlockSection, z as findWorkoutErrors, A as forceSectionParse, F as frontmatterPreview, H as frontmatterPreviewField, I as getCursorFocusState, J as getOverlayActions, K as gutterHighlightsField, L as gutterUnified, M as handleFenceAutoWrap, P as inlineButtonDecoration, T as lineIdsExtension, U as linkOpen, V as markdownSyntaxHiding, X as markdownTablePreview, Y as navigationFacet, Z as previewDecorations, _ as queryBlockPreview, $ as removeRuntimePanel, a0 as runtimePanelField, a1 as saveBlockQuerySource, a2 as sectionAtPos, a3 as sectionField, a4 as sectionGeometry, a5 as sessionQueryInsert, a6 as sessionQueryWql, a7 as setGutterHighlights, a8 as smartIncrement, a9 as toggleWidgetEdit, aa as urlAtPos, ab as widgetBlockPreview, ac as wodAutoWrap, ad as wodAutocompletion, ae as wodEditorKeymap, af as wodLinter, ag as wodOverlayPanel, ah as workoutLintSource, ai as wrapInTimeFence } from './index-CTQ7Hrsa.cjs';
1
+ import { Q as QueryExecutor } from './index-DMTXLSJ0.cjs';
2
+ export { B as ButtonAction, C as CursorFocusState, a as CustomCompletionSource, D as DefaultFrontmatterWidget, E as EditorDialect, b as EditorPresetOptions, c as EditorSection, d as EditorSectionSubtype, e as EditorSectionType, f as EmbedType, F as FrontmatterSuggestionCatalog, G as GeometryListener, N as NavigationHook, O as OverlayAction, g as QueryBlockPreviewOptions, R as RuntimePanelEntry, S as SectionRect, h as SectionState, W as WidgetConfig, i as WidgetProps, j as WidgetRegistry, k as activeCursorSection, l as addRuntimePanel, m as configureOverlayActions, n as cursorFocusExtension, o as dispatchAddRuntimePanel, p as dispatchExpandRuntimePanel, q as dispatchGutterHighlights, r as dispatchRemoveRuntimePanel, s as editingWidgetsField, t as editorPreset, u as editorTheme, v as embedPreviewDecorations, w as expandRuntimePanel, x as fenceCompletion, y as findQueryBlockSection, z as findWorkoutErrors, A as forceSectionParse, H as frontmatterPreview, I as frontmatterPreviewField, J as frontmatterSuggestions, K as frontmatterVisibility, L as getCursorFocusState, M as getOverlayActions, P as gutterHighlightsField, T as gutterUnified, U as handleFenceAutoWrap, V as inlineButtonDecoration, X as lineIdsExtension, Y as linkOpen, Z as linkPreview, _ as markdownSyntaxHiding, $ as markdownTablePreview, a0 as navigationFacet, a1 as previewDecorations, a2 as queryBlockPreview, a3 as registerCustomCompletionSource, a4 as removeRuntimePanel, a5 as runtimePanelField, a6 as saveBlockQuerySource, a7 as sectionAtPos, a8 as sectionField, a9 as sectionGeometry, aa as sessionQueryInsert, ab as sessionQueryWql, ac as setGutterHighlights, ad as smartIncrement, ae as toggleWidgetEdit, af as unregisterCustomCompletionSource, ag as urlAtPos, ah as widgetBlockPreview, ai as wodAutoWrap, aj as wodAutocompletion, ak as wodEditorKeymap, al as wodLinter, am as wodOverlayPanel, an as workoutLintSource, ao as wrapInTimeFence } from './index-DMTXLSJ0.cjs';
3
3
  import * as react from 'react';
4
- import { ReactNode, ComponentType } from 'react';
5
- import { QueryResult, DashboardToken, DashboardDocument, DashboardWidget, Series, RowsQueryResult, RowsRun, AnyParsedQuery, FindQueryResult, ParsedAggregateQuery, ParsedFindQuery } from '@bitcobblers/wod-wiki-wql';
6
- export { FindOptions, FindQueryResult, ParsedAggregateQuery, ParsedFindQuery, ParsedRowsQuery, QueryOptions, QueryResult, RowsQueryResult, RowsRun } from '@bitcobblers/wod-wiki-wql';
7
- import { Segment, UnifiedEventRecord, BlockIndexRow } from '@bitcobblers/wod-wiki-core';
4
+ import react__default, { ReactNode, ComponentType } from 'react';
5
+ import { QueryResult, DashboardToken, DashboardDocument, DashboardWidget, Series, RowsQueryResult, RowsRun, AnyParsedQuery, FindQueryResult, ParsedAggregateQuery, ParsedFindQuery, ParsedPipelineQuery } from '@bitcobblers/wod-wiki-wql';
6
+ export { CONTENT_GROUPING_DIMENSIONS, FindOptions, FindQueryResult, ParsedAggregateQuery, ParsedFindQuery, ParsedPipelineQuery, ParsedRowsQuery, PipelineResult, QueryOptions, QueryResult, RowsQueryResult, RowsRun } from '@bitcobblers/wod-wiki-wql';
7
+ import { IMetric, EventRecord, BlockIndexRow } from '@bitcobblers/wod-wiki-core';
8
+ export { blockContentId } from '@bitcobblers/wod-wiki-core';
9
+ import { MetricPresentationToken } from '@bitcobblers/wod-wiki-lang';
8
10
  import { ClassValue } from 'clsx';
9
11
  import '@codemirror/state';
10
12
  import '@codemirror/view';
@@ -20,13 +22,46 @@ interface StorageLike {
20
22
  declare const CODEMIRROR_SINGLETON_DEPS: readonly ["@codemirror/autocomplete", "@codemirror/commands", "@codemirror/lang-markdown", "@codemirror/language", "@codemirror/lint", "@codemirror/search", "@codemirror/state", "@codemirror/theme-one-dark", "@codemirror/view", "@lezer/common", "@lezer/highlight", "@lezer/lr", "@lezer/markdown"];
21
23
 
22
24
  interface WidgetFrameProps {
25
+ /** DOM anchor for the frame (e.g. `widget-<key>`) — L3 indexes scroll here. */
26
+ id?: string;
23
27
  title: string;
24
28
  question: string;
25
- query: string;
29
+ /** Raw WQL for the widget. Hidden by default — only rendered with showQuery. */
30
+ query?: string;
26
31
  span?: string;
32
+ /** Show the raw WQL query box (teaching/authoring surfaces). View-first default hides it. */
33
+ showQuery?: boolean;
34
+ /**
35
+ * Read-only inspection affordance — an always-visible button (prebuilt
36
+ * seeds, teaching surfaces) opening the host's query inspector. Distinct
37
+ * from editing: present without a toolbar.
38
+ */
39
+ onInspect?: () => void;
40
+ /** Always-visible affordance: open this widget's resolved query in the
41
+ * WQL explorer (host navigates). */
42
+ onOpenInExplorer?: () => void;
43
+ /**
44
+ * Edit-mode action cluster (edit / duplicate / remove / reorder / size),
45
+ * rendered top-right and always visible while present. The host builds it;
46
+ * the frame only positions it.
47
+ */
48
+ toolbar?: ReactNode;
27
49
  children: ReactNode;
28
50
  }
29
- declare function WidgetFrame({ title, question, query, span, children }: WidgetFrameProps): react.JSX.Element;
51
+ declare function WidgetFrame({ id, title, question, query, span, showQuery, onInspect, onOpenInExplorer, toolbar, children }: WidgetFrameProps): react.JSX.Element;
52
+ /** Standard edit-mode tool-button chrome for the widget toolbar. */
53
+ declare function WidgetToolButton({ label, onClick, disabled, active, children, }: {
54
+ label: string;
55
+ onClick: () => void;
56
+ disabled?: boolean;
57
+ active?: boolean;
58
+ children: ReactNode;
59
+ }): react.JSX.Element;
60
+ /** The primary "open the full editor" affordance inside the toolbar. */
61
+ declare function WidgetEditButton({ title, onClick }: {
62
+ title: string;
63
+ onClick: () => void;
64
+ }): react.JSX.Element;
30
65
 
31
66
  interface QueryValueProps {
32
67
  result: QueryResult;
@@ -66,20 +101,27 @@ interface WidgetChartProps {
66
101
  unit?: string;
67
102
  /** Positional widget parameters from the block body (e.g. goal target or zone targets). */
68
103
  params?: string[];
104
+ /** Fence-tag presentation attributes (decision 22) — preferred over legacy positional params. */
105
+ attributes?: Record<string, string>;
69
106
  }
70
- declare function WidgetChart({ type, result, label, unit, params }: WidgetChartProps): react.JSX.Element;
107
+ declare function WidgetChart({ type, result, label, unit, params, attributes }: WidgetChartProps): react__default.JSX.Element;
71
108
  declare function WidgetProblemBadge({ message }: {
72
109
  message: string;
73
- }): react.JSX.Element;
110
+ }): react__default.JSX.Element;
74
111
  declare function ProposedMetricBadge({ metric }: {
75
112
  metric: string;
76
- }): react.JSX.Element;
113
+ }): react__default.JSX.Element;
77
114
 
78
115
  interface DashboardTokenControlsProps {
79
116
  tokens: DashboardToken[];
80
117
  /** Current value per token name (defaults applied by the caller). */
81
118
  values: Record<string, string>;
82
- /** Present when the note is editable — changes write back to frontmatter. */
119
+ /**
120
+ * Present when the note is editable — a change commits exactly once, on an
121
+ * explicit action: a list-token segment click, or a scalar-token blur /
122
+ * Enter. Keystrokes only edit the local draft — they never rewrite the
123
+ * note or re-run widgets mid-edit.
124
+ */
83
125
  onChange?: (name: string, value: string) => void;
84
126
  }
85
127
  /**
@@ -90,19 +132,50 @@ interface DashboardTokenControlsProps {
90
132
  */
91
133
  declare function DashboardTokenControls({ tokens, values, onChange }: DashboardTokenControlsProps): react.JSX.Element | null;
92
134
 
135
+ /** A widget's grid placement — column span 1..4, or a forced full row. */
136
+ interface WidgetSpanOption {
137
+ spanCols?: number;
138
+ spanFull?: boolean;
139
+ }
140
+ /** A note heading rendered as a full-width grid row between widgets, with its
141
+ * own DOM anchor (L3 scroll target). Order within `headings` is preserved. */
142
+ interface DashboardHeadingAnchor {
143
+ id: string;
144
+ /** Markdown heading level (2+; level 1 renders as the page title surface). */
145
+ level: number;
146
+ text: string;
147
+ /** Insert before this widget index; `widgets.length` = after the last. */
148
+ beforeWidget: number;
149
+ }
93
150
  interface DashboardViewProps {
94
151
  /** Parsed dashboard note (buildDashboardDocument). */
95
152
  document: DashboardDocument;
153
+ /** Note headings to render between the widgets (document order). */
154
+ headings?: DashboardHeadingAnchor[];
96
155
  /** Injected QueryExecutor for executing WQL queries. Zero singleton coupling. */
97
156
  executor?: QueryExecutor;
98
157
  /** Optional rollup fact warmer callback. */
99
158
  onEnsureRollupFacts?: () => Promise<void>;
100
159
  /** Current token values; defaults to each token's declared default. */
101
160
  tokenValues?: Record<string, string>;
102
- /** Present when the note is editable — control changes write back to frontmatter. */
161
+ /** Present when the note is editable — committed control changes write back to frontmatter. */
103
162
  onTokenChange?: (name: string, value: string) => void;
104
- /** Present when the host offers query editing (composer modal owned by the host). */
105
- onEditQuery?: (widget: DashboardWidget) => void;
163
+ /**
164
+ * Edit mode: per-widget arrangement chrome (edit / duplicate / remove /
165
+ * reorder / size) renders on every card. View mode stays chrome-free —
166
+ * the host gates editing on this flag plus the handler set below.
167
+ */
168
+ editMode?: boolean;
169
+ /** Open the shared authoring composer for this widget (edit flow). */
170
+ onEditWidget?: (widget: DashboardWidget) => void;
171
+ /** Read-only query inspection (prebuilt seeds, teaching surfaces). */
172
+ onInspectWidget?: (widget: DashboardWidget) => void;
173
+ /** Open the widget's token-resolved query in the WQL explorer (host navigates). */
174
+ onOpenInExplorer?: (widget: DashboardWidget, query: string) => void;
175
+ onDuplicateWidget?: (widget: DashboardWidget) => void;
176
+ onRemoveWidget?: (widget: DashboardWidget) => void;
177
+ onMoveWidget?: (widget: DashboardWidget, delta: -1 | 1) => void;
178
+ onResizeWidget?: (widget: DashboardWidget, span: WidgetSpanOption) => void;
106
179
  /** Optional execution range (ms epoch). Omit to use each query's own window. */
107
180
  rangeStart?: number;
108
181
  rangeEnd?: number;
@@ -112,15 +185,19 @@ interface DashboardViewProps {
112
185
  * DashboardView — the state-free dashboard renderer (#900, format locked in #899).
113
186
  *
114
187
  * Takes a parsed DashboardDocument + current token values, runs all widget
115
- * queries concurrently via the injected QueryExecutor, and renders the responsive CSS grid.
188
+ * queries concurrently via the injected QueryExecutor, and renders the
189
+ * responsive CSS grid. All authoring interactions are host-owned: the view
190
+ * surfaces the affordances (edit-mode toolbar, inspect button) and reports
191
+ * through the injected callbacks — it never owns dialog or write state.
116
192
  */
117
- declare function DashboardView({ document, executor, onEnsureRollupFacts, tokenValues, onTokenChange, onEditQuery, rangeStart, rangeEnd, preferredUnit, }: DashboardViewProps): react.JSX.Element;
193
+ declare function DashboardView({ document, headings, executor, onEnsureRollupFacts, tokenValues, onTokenChange, editMode, onEditWidget, onInspectWidget, onOpenInExplorer, onDuplicateWidget, onRemoveWidget, onMoveWidget, onResizeWidget, rangeStart, rangeEnd, preferredUnit, }: DashboardViewProps): react.JSX.Element;
118
194
 
119
195
  interface WqlEmptyStateProps {
120
- result: QueryResult | undefined;
196
+ result?: QueryResult | undefined;
121
197
  className?: string;
198
+ actions?: ReactNode;
122
199
  }
123
- declare function WqlEmptyState({ result, className }: WqlEmptyStateProps): react.JSX.Element | null;
200
+ declare function WqlEmptyState({ result, className, actions }: WqlEmptyStateProps): react.JSX.Element | null;
124
201
 
125
202
  interface TopListProps {
126
203
  result: QueryResult;
@@ -141,14 +218,18 @@ interface GoalRingsProps {
141
218
  label?: string;
142
219
  unit?: string;
143
220
  }
144
- declare function GoalRings({ result, params, label, unit }: GoalRingsProps): react.JSX.Element;
221
+ declare function GoalRings({ result, attributes, params, label, unit }: GoalRingsProps & {
222
+ attributes?: Record<string, string>;
223
+ }): react.JSX.Element;
145
224
 
146
225
  interface ZoneDistributionProps {
147
226
  result: QueryResult | undefined;
148
227
  params?: string[];
149
228
  unit?: string;
150
229
  }
151
- declare function ZoneDistribution({ result, params }: ZoneDistributionProps): react.JSX.Element;
230
+ declare function ZoneDistribution({ result, params, attributes }: ZoneDistributionProps & {
231
+ attributes?: Record<string, string>;
232
+ }): react.JSX.Element;
152
233
 
153
234
  type AnalyticsRangeWeeks = 4 | 8 | 16;
154
235
  interface RangeSelectorProps {
@@ -220,14 +301,82 @@ interface AnalyticsUnitPreferenceProps {
220
301
  }
221
302
  declare function AnalyticsUnitPreference({ className, unit: unitProp, forced, storage }: AnalyticsUnitPreferenceProps): react.JSX.Element;
222
303
 
304
+ declare function formatMMSS(ms: number): string;
305
+ declare function formatClockTime(d: Date): string;
306
+ declare const TONE_CLASS: Record<string, string>;
307
+ declare function MetricBadge({ token }: {
308
+ token: MetricPresentationToken;
309
+ }): react.JSX.Element | null;
310
+ /** Metric badges for a statement/output metric group. */
311
+ declare function presentBadges(metrics: Iterable<IMetric>): ReactNode;
312
+ declare const OUTPUT_TYPE_CLASS: Record<string, string>;
313
+ declare const OUTPUT_TYPE_DOT: Record<string, string>;
314
+ interface CategorizedMetrics {
315
+ efforts: IMetric[];
316
+ reps: IMetric[];
317
+ loads: IMetric[];
318
+ rounds: IMetric[];
319
+ durations: IMetric[];
320
+ distances: IMetric[];
321
+ hints: IMetric[];
322
+ }
323
+ declare function extractMetricsByCategory(metrics?: Iterable<IMetric>): CategorizedMetrics;
324
+ interface OutputFilterPreset {
325
+ label: string;
326
+ query: string;
327
+ }
328
+ type OutputFilterInput = string | OutputFilterPreset;
329
+ /** Default row filter — segment statements only (the Workbench default). */
330
+ declare const DEFAULT_PRIMARY_FILTER = "type:segment";
331
+ declare const DEFAULT_OUTPUT_FILTERS: OutputFilterPreset[];
332
+ declare function normalizeOutputFilter(filter: OutputFilterInput): OutputFilterPreset;
333
+ /** Structural subset satisfied by live `IOutputStatement`s, stored statements,
334
+ * and `EventRecord` event rows alike. */
335
+ interface OutputStatementRow {
336
+ readonly id?: number | string;
337
+ readonly outputType?: string;
338
+ readonly timeSpan?: {
339
+ started: number;
340
+ ended?: number;
341
+ };
342
+ readonly metrics?: Iterable<IMetric>;
343
+ readonly sourceBlockKey?: string;
344
+ readonly completionReason?: string;
345
+ }
346
+ declare function OutputFilterPills({ presets, filter, onChange, }: {
347
+ presets: OutputFilterPreset[];
348
+ filter: string;
349
+ onChange: (next: string) => void;
350
+ }): react.JSX.Element;
351
+ interface OutputStatementsTableProps {
352
+ outputs: readonly OutputStatementRow[];
353
+ /** Filter expression (`type:segment`, free text). Empty shows all. */
354
+ filter?: string;
355
+ /** Epoch ms the +offset column is relative to. Defaults to first statement start. */
356
+ timeOrigin?: number;
357
+ /** Clears the active filter — enables the Card List's Clear-filter
358
+ * affordance on the filtered-empty state. Optional; hosts without a
359
+ * clearable filter omit it. */
360
+ onClearFilter?: () => void;
361
+ }
362
+ /** The Session Results surface — Card List below `sm`, the 9-column table at
363
+ * `sm` and above. One component: same props, same filtering; hosts (analytics
364
+ * explorer, editor query blocks, workbench) inherit the phone path. */
365
+ declare function OutputStatementsTable({ outputs, filter, timeOrigin, onClearFilter, }: OutputStatementsTableProps): react.JSX.Element;
366
+
223
367
  interface RowsTableProps {
224
368
  result: RowsQueryResult;
225
369
  /** Optional per-run chrome rendered inside the section header (#948 RPE). */
226
370
  renderRunHeaderExtra?: (run: RowsRun) => ReactNode;
227
- /** Optional segment grid renderer (e.g. app's ReviewGrid). Default: clean plain table rows. */
228
- renderSegments?: (segments: Segment[], run: RowsRun) => ReactNode;
371
+ /** Filter presets for the pills row (defaults to All/Segments/Events). */
372
+ presets?: OutputFilterInput[];
373
+ /** Controlled filter expression — omit to let the table own its filter state. */
374
+ filter?: string;
375
+ onFilterChange?: (filter: string) => void;
229
376
  }
230
- declare function RowsTable({ result, renderRunHeaderExtra, renderSegments, }: RowsTableProps): react.JSX.Element;
377
+ /** The Session Results Table — renders a Rows Query result: one section per
378
+ * run, filter pills on top, and the shared statement table as the body. */
379
+ declare function RowsTable({ result, renderRunHeaderExtra, presets, filter, onFilterChange, }: RowsTableProps): react.JSX.Element;
231
380
 
232
381
  interface QueryBlockViewProps {
233
382
  /** Raw text between the ```query fences — the WQL query string or block source. */
@@ -236,8 +385,10 @@ interface QueryBlockViewProps {
236
385
  executor?: QueryExecutor;
237
386
  /** Optional callback or subscription hook for when a result is saved, replacing hardcoded resultRecorder coupling. */
238
387
  onResultSaved?: (callback: () => void) => (() => void) | void;
239
- /** Present when the query block is editable — opens the WQL composer. */
240
- onSaveQuery?: (nextQuery: string) => void;
388
+ /** Present when the query block is editable — opens the WQL composer.
389
+ * May return the write's Promise so a rejected save keeps the editor
390
+ * open; a plain void write is fire-and-forget. */
391
+ onSaveQuery?: (nextQuery: string) => void | Promise<void>;
241
392
  /** When multiple queries appear in one block, the index of this query. */
242
393
  queryIndex?: number;
243
394
  /** When true, editing the query is disallowed. */
@@ -248,14 +399,26 @@ interface QueryBlockViewProps {
248
399
  widgetError?: string;
249
400
  /** Token values from the note's frontmatter, for `$token` substitution. */
250
401
  tokenValues?: Record<string, string>;
402
+ /** Fence-tag presentation attributes (decision 22). */
403
+ attributes?: Record<string, string>;
251
404
  /** Optional RPE capture handler. */
252
405
  onCaptureRpe?: (resultId: string, rpe: number) => Promise<void>;
253
- /** Optional custom segment grid renderer. */
254
- renderSegments?: (segments: Segment[], run: RowsRun) => React.ReactNode;
255
- }
256
- declare function QueryBlockView({ query, executor, onResultSaved, onSaveQuery, queryIndex: _queryIndex, readOnly, widgetType, widgetError, tokenValues, onCaptureRpe, renderSegments, }: QueryBlockViewProps): react.JSX.Element;
257
-
258
- declare function readSessionRpe(events: UnifiedEventRecord[] | undefined): number | undefined;
406
+ /** Optional click handler for opening a note from :note results. */
407
+ onOpenNote?: (item: {
408
+ id: string;
409
+ title?: string;
410
+ blockContentId?: string;
411
+ }) => void;
412
+ /** Optional resolver returning the destination href for an item in :note results. */
413
+ noteHref?: (item: {
414
+ id: string;
415
+ title?: string;
416
+ blockContentId?: string;
417
+ }) => string;
418
+ }
419
+ declare function QueryBlockView({ query, executor, onResultSaved, onSaveQuery, queryIndex: _queryIndex, readOnly, widgetType, widgetError, tokenValues, attributes, onCaptureRpe, onOpenNote, noteHref, }: QueryBlockViewProps): react.JSX.Element;
420
+
421
+ declare function readSessionRpe(events: EventRecord[] | undefined): number | undefined;
259
422
  interface RowsResultsChromeProps {
260
423
  /** The session result id from the written `rows:{result:…}` query. */
261
424
  resultId: string;
@@ -267,21 +430,23 @@ interface RowsResultsChromeProps {
267
430
  onCaptureRpe?: (resultId: string, rpe: number) => Promise<void>;
268
431
  /** Re-run the parent query after a capture so the grid reflects the RPE. */
269
432
  onCaptured?: () => void;
270
- /** Optional segment grid renderer. */
271
- renderSegments?: (segments: Segment[], run: RowsRun) => React.ReactNode;
272
433
  }
273
- declare function RowsResultsChrome({ resultId, sessionResult, executor, onCaptureRpe, onCaptured, renderSegments, }: RowsResultsChromeProps): react.JSX.Element;
434
+ declare function RowsResultsChrome({ resultId, sessionResult, executor, onCaptureRpe, onCaptured, }: RowsResultsChromeProps): react.JSX.Element;
274
435
 
275
436
  interface WqlQueryInspectorModalProps {
276
437
  isOpen: boolean;
277
438
  onClose: () => void;
278
439
  initialQuery: string;
279
- onApply: (newQuery: string) => void;
440
+ /** Persist the applied query. A returned Promise gates the button until
441
+ * it settles; a rejection keeps the dialog open with the error visible. */
442
+ onApply: (newQuery: string) => void | Promise<void>;
280
443
  title?: string;
281
444
  subtitle?: string;
445
+ /** Label for the confirm button (defaults to "Apply to Block"). */
446
+ applyLabel?: string;
282
447
  executor?: QueryExecutor;
283
448
  }
284
- declare function WqlQueryInspectorModal({ isOpen, onClose, initialQuery, onApply, title, subtitle, executor, }: WqlQueryInspectorModalProps): react.JSX.Element | null;
449
+ declare function WqlQueryInspectorModal({ isOpen, onClose, initialQuery, onApply, title, subtitle, applyLabel, executor, }: WqlQueryInspectorModalProps): react.JSX.Element;
285
450
 
286
451
  type WqlExecutor = (ast: AnyParsedQuery) => Promise<FindQueryResult | QueryResult>;
287
452
  type WqlStageCounts = {
@@ -299,22 +464,25 @@ declare const DEFAULT_DIAGNOSTICS_DEBOUNCE_MS = 150;
299
464
  declare function useWqlStageCounts(ast: AnyParsedQuery, valid: boolean, execute: WqlExecutor | undefined, debounceMs?: number): WqlStageCounts | undefined;
300
465
 
301
466
  /**
302
- * Shared query-clause model + WQL compiler for the WqlComposer.
467
+ * The WqlComposer pill vocabulary — types, metadata, and option lists.
468
+ * Compilation and restore live in `./queryAst` (ticket 013): composer state
469
+ * is the C6 AST; strings are produced only through the engine serializer.
303
470
  *
304
- * Source-pivot model (issue #838, decision #836): a single `source` head
305
- * slot — journal | collections | feeds | notes | blocks | efforts | metrics —
306
- * pivots the query kind. Content sources compile the `find:` skeleton; `metrics`
307
- * compiles the aggregate skeleton (`agg:metric{filters} by {dims}.rollup(p)
308
- * [in unit] [where find:…]`). The find target and scope are derived from the
309
- * source value (the legacy `target`/`scope` clause types are retired).
471
+ * Canonical structure (work item 3): a query has a `kind` (find documents vs
472
+ * measure numbers), a singular `target` (colon `<target>` head), and an optional
473
+ * `source` storage scope (`Where stored` — WQL_SOURCE_VALUES; all sources =
474
+ * no source filter). Filter capability sets mirror what the QueryService
475
+ * executors actually apply — parser acceptance alone never advertises a
476
+ * clause (`has:` parses but no executor applies it, so it is not offered).
310
477
  *
311
478
  * Static option lists live here; dynamic typeahead data sources live in
312
479
  * ./suggestionSources (issue #831). All vocab is sourced from the canonical
313
- * modules (@bitcobblers/wod-wiki-engine) — never hardcoded in the composer (decision #824).
480
+ * modules (@bitcobblers/wod-wiki-wql) — never hardcoded in the composer (decision #824).
314
481
  *
315
482
  * Supports freeform token slots, placeholder guidance, and keyboard navigation.
316
483
  */
317
- type ClauseType = 'source' | 'text' | 'catalog' | 'tag' | 'effort' | 'discipline' | 'intensity' | 'origin' | 'type' | 'has' | 'time' | 'where' | 'agg' | 'metric' | 'groupby' | 'rollup' | 'unit' | 'result' | 'block' | 'note' | 'output';
484
+
485
+ type ClauseType = 'kind' | 'target' | 'source' | 'text' | 'catalog' | 'tag' | 'effort' | 'domain' | 'format' | 'equipment' | 'quality' | 'intent' | 'discipline' | 'intensity' | 'origin' | 'type' | 'time' | 'where' | 'agg' | 'metric' | 'groupby' | 'rollup' | 'unit' | 'result' | 'block' | 'note' | 'page' | 'plane' | 'pipes';
318
486
  interface QueryClause {
319
487
  id: string;
320
488
  /** Built-in ClauseType or a custom slot type id from the ComposerRegistry. */
@@ -325,16 +493,39 @@ interface QueryClause {
325
493
  placeholder?: string;
326
494
  icon?: string;
327
495
  prefix?: string;
328
- }
329
- /** Content sources compile `find:note in <scope>`; notes/blocks use `all`. */
330
- declare const CONTENT_SOURCES: ("journal" | "collections" | "feeds" | "notes" | "blocks" | "efforts")[];
331
- /** The plane a source value belongs to — everything but `metrics` is content. */
332
- declare function sourcePlane(source: string): 'content' | 'metrics';
333
- declare const SOURCE_OPTIONS: {
496
+ /** Index into the parsed AST's global filters array (ast.filters[filterIndex])
497
+ * — identifies one specific filter occurrence; editing one occurrence must
498
+ * never merge or rewrite another. */
499
+ filterIndex?: number;
500
+ /** True when this filter occurrence is negated (`!key:value`). */
501
+ negate?: boolean;
502
+ }
503
+ /** Query shape: `find` compiles the colon `<target>` skeleton (`:note{…}`),
504
+ * `aggregate` compiles `agg:metric{filters} by {dims}` and exposes agg/metric. */
505
+ declare const KIND_OPTIONS: {
334
506
  value: string;
335
507
  label: string;
336
508
  description: string;
337
509
  }[];
510
+ /** Singular find targets — the colon `<target>` head (C7 closed enum). */
511
+ declare const TARGET_OPTIONS: {
512
+ value: "note" | "effort" | "segment" | "event" | "session" | "block";
513
+ label: string;
514
+ description: string;
515
+ }[];
516
+ /** Storage scopes — the `source:` filter values (`Where stored`). All
517
+ * sources means no source filter at all. */
518
+ declare const SOURCE_OPTIONS: {
519
+ value: "efforts" | "journal" | "feeds" | "guides" | "playground" | "dashboards";
520
+ label: string;
521
+ description: string;
522
+ }[];
523
+ /** Output-statement planes for `plane:` on `:session` (executor narrows
524
+ * events by the promoted `outputType` column). */
525
+ declare const PLANE_OPTIONS: {
526
+ value: "system" | "segment" | "completion" | "event" | "load" | "compiler" | "analytics" | "wellness";
527
+ label: "system" | "segment" | "completion" | "event" | "load" | "compiler" | "analytics" | "wellness";
528
+ }[];
338
529
  declare const TIME_OPTIONS: {
339
530
  value: string;
340
531
  label: string;
@@ -344,17 +535,20 @@ declare const AGG_OPTIONS: {
344
535
  value: "max" | "min" | "sum" | "avg" | "count" | "last" | "delta";
345
536
  label: "max" | "min" | "sum" | "avg" | "count" | "last" | "delta";
346
537
  }[];
538
+ /** Multi-unit bucket widths — parse accepts any `N>1` + d|w (single-unit
539
+ * day/week grouping is `by {day}`/`by {week}`, never `.rollup(1w)`); the
540
+ * list is common suggestions, typed widths are parser-validated. */
347
541
  declare const ROLLUP_OPTIONS: {
348
- value: "1d" | "1w";
542
+ value: string;
349
543
  label: string;
350
544
  }[];
351
545
  declare const GROUPBY_OPTIONS: {
352
- value: "result" | "day" | "origin" | "page" | "round" | "metric" | "note" | "week" | "effort" | "discipline" | "intensity" | "block" | "session" | "grain" | "tags";
353
- label: "result" | "day" | "origin" | "page" | "round" | "metric" | "note" | "week" | "effort" | "discipline" | "intensity" | "block" | "session" | "grain" | "tags";
546
+ value: "format" | "origin" | "result" | "day" | "page" | "domain" | "round" | "metric" | "note" | "week" | "effort" | "intensity" | "session" | "equipment" | "quality" | "intent" | "discipline" | "block" | "grade" | "grain" | "tags";
547
+ label: "format" | "origin" | "result" | "day" | "page" | "domain" | "round" | "metric" | "note" | "week" | "effort" | "intensity" | "session" | "equipment" | "quality" | "intent" | "discipline" | "block" | "grade" | "grain" | "tags";
354
548
  }[];
355
549
  declare const METRIC_OPTIONS: {
356
- value: "totalVolume" | "totalDistance" | "tis" | "sessionLoad" | "reps" | "distance" | "resistance" | "elapsed" | "power" | "pace" | "calc.metMinutes" | "calc.acwr" | "calc.monotony" | "calc.strain" | "calc.e1rm" | "calc.ctl" | "calc.atl" | "calc.tsb" | "calc.soreness" | "calc.sleep" | "calc.hrv" | "calc.readiness" | "calc.mvcBw" | "calc.ef" | "calc.adherence" | "calc.pct1rm" | "calc.sends";
357
- label: "totalVolume" | "totalDistance" | "tis" | "sessionLoad" | "reps" | "distance" | "resistance" | "elapsed" | "power" | "pace" | "calc.metMinutes" | "calc.acwr" | "calc.monotony" | "calc.strain" | "calc.e1rm" | "calc.ctl" | "calc.atl" | "calc.tsb" | "calc.soreness" | "calc.sleep" | "calc.hrv" | "calc.readiness" | "calc.mvcBw" | "calc.ef" | "calc.adherence" | "calc.pct1rm" | "calc.sends";
550
+ value: "distance" | "resistance" | "elapsed" | "totalVolume" | "totalDistance" | "tis" | "sessionLoad" | "reps" | "power" | "pace" | "calc.metMinutes" | "calc.acwr" | "calc.monotony" | "calc.strain" | "calc.e1rm" | "calc.ctl" | "calc.atl" | "calc.tsb" | "calc.soreness" | "calc.sleep" | "calc.hrv" | "calc.readiness" | "calc.mvcBw" | "calc.ef" | "calc.adherence" | "calc.pct1rm" | "calc.sends";
551
+ label: "distance" | "resistance" | "elapsed" | "totalVolume" | "totalDistance" | "tis" | "sessionLoad" | "reps" | "power" | "pace" | "calc.metMinutes" | "calc.acwr" | "calc.monotony" | "calc.strain" | "calc.e1rm" | "calc.ctl" | "calc.atl" | "calc.tsb" | "calc.soreness" | "calc.sleep" | "calc.hrv" | "calc.readiness" | "calc.mvcBw" | "calc.ef" | "calc.adherence" | "calc.pct1rm" | "calc.sends";
358
552
  }[];
359
553
  declare const UNIT_OPTIONS: {
360
554
  value: "kg" | "lb";
@@ -367,7 +561,6 @@ declare const UNIT_OPTIONS: {
367
561
  */
368
562
  declare const WHERE_AGGREGATORS: readonly string[];
369
563
  declare const WHERE_METRICS: readonly string[];
370
- declare const WHERE_OPERATORS: readonly string[];
371
564
  interface ClauseMeta {
372
565
  label: string;
373
566
  inputType: 'radio' | 'freetext' | 'select';
@@ -385,109 +578,88 @@ declare const CLAUSE_META: Record<ClauseType, ClauseMeta>;
385
578
  * anything else gets a generic fallback so a stale clause still renders.
386
579
  */
387
580
  declare function getClauseMeta(type: string): ClauseMeta;
388
- /**
389
- * Maps a single clause to its WQL fragment syntax.
390
- */
391
- declare function clauseToWql(clause: QueryClause): {
392
- key?: string;
393
- filterStr?: string;
394
- };
395
- /**
396
- * Composes a full WQL string from an array of QueryClauses.
397
- *
398
- * Content planes: find:<target>{<filters>} in <scope> [last <n><unit>] [where <join>]
399
- * — target/scope derived from `source` (journal|collections|feeds → note in
400
- * <source>; notes → note in all; blocks → block in all; anything else →
401
- * note in <verbatim value>, the salvage path for exotic scopes).
402
- * Metrics plane: <agg>:<metric>{<filters>} [by {<dims>}] [.rollup(<p>)] [in <unit>] [where <find join>]
403
- */
404
- declare function clausesToWql(clauses: QueryClause[]): string;
405
- /**
406
- * Restore composer clauses from a WQL string — the inverse of
407
- * `clausesToWql`, used to hydrate composer state from the URL.
408
- *
409
- * Unlike `parseQuery`, this is a *salvage* parser: it mirrors the compiler's
410
- * structure on both planes without validating the fragments, so composer-
411
- * reachable states that are WQL-invalid (e.g. `text:hello world`, a `1m`
412
- * rollup period, an empty metric) still restore exactly — the diagnostics
413
- * strip then attributes the parse error to the offending slot.
414
- *
415
- * Returns null when the string cannot be a composer product: a negated
416
- * filter, or an unknown/custom-less filter key.
417
- */
418
- declare function wqlToClauses(wql: string): QueryClause[] | null;
419
- /**
420
- * Set the aggregate metric, re-basing the clause list on the metrics plane
421
- * when needed (sidebar / launcher flows, issue #839): content planes pivot
422
- * via `pivotClauses` (shared filters survive), a missing source or metric
423
- * clause is seeded, and the metric value lands on the first metric clause.
424
- */
425
- declare function setMetricClause(clauses: QueryClause[], metric: string): QueryClause[];
426
- /**
427
- * Re-base the clause list on a new source value (decision #836): shared
428
- * filter clauses survive the pivot; kind-specific clauses are dropped
429
- * (content plane: time/where and any metrics head; metrics plane: time/
430
- * where). Pivoting to metrics seeds the head slots (agg=sum, metric empty
431
- * for placeholder guidance).
432
- */
433
- declare function pivotClauses(clauses: QueryClause[], source: string): QueryClause[];
434
- declare function defaultClauses(): QueryClause[];
435
- /** Default clauses for aggregate/metrics queries (source=metrics, agg=sum, empty metric). */
436
- declare function defaultMetricsClauses(): QueryClause[];
437
- /**
438
- * Value of the first clause of `type`, trimmed, or `fallback` when absent or
439
- * empty. Mirrors the lookup/defaulting `clausesToWql` performs, so consumers
440
- * (e.g. the Library shelf) share one defaulting rule with the compiler.
441
- */
442
- declare function clauseValue(clauses: QueryClause[], type: string, fallback?: string): string;
443
581
 
444
582
  interface WqlValidationState {
445
- /** True when the composed WQL parses without error. */
446
583
  valid: boolean;
447
- /** Parser error message when invalid. */
448
584
  error?: string;
449
585
  }
450
586
  interface WqlComposerProps {
451
- /** Seed clauses for uncontrolled usage. Defaults to source/time. */
452
- initialClauses?: QueryClause[];
453
- /** Controlled clauses. When provided, the component does not own clause state. */
454
- clauses?: QueryClause[];
455
- /** Fired whenever the clause list changes (add / edit / remove). */
456
- onClausesChange?: (clauses: QueryClause[]) => void;
457
- /** Fired (including on mount) with the composed WQL string. */
458
- onWqlChange?: (wql: string) => void;
459
- /** Fired (including on mount) with parse validation state. */
587
+ initialQuery?: string;
588
+ query?: string;
589
+ /** Synchronous resolved draft, including invalid exact text. Execution debounce belongs to the host. */
590
+ onQueryChange?: (wql: string) => void;
460
591
  onValidationChange?: (state: WqlValidationState) => void;
461
- /** Fired (including on mount) with the parsed AST. */
462
592
  onAstChange?: (ast: AnyParsedQuery) => void;
463
- /**
464
- * Fired on Enter when no free text is pending — the run-on-submit signal
465
- * for hosts like the analytics explorer. Receives the composed WQL.
466
- */
593
+ /** Explicit actions receive the current valid draft on the first activation. */
467
594
  onSubmit?: (wql: string) => void;
468
- /** Render the diagnostics strip (badge, AST summary, stage counts). Default true. */
595
+ actionLabel?: string;
596
+ compact?: boolean;
469
597
  showDiagnostics?: boolean;
470
- /**
471
- * Executor for live stage counts in the diagnostics strip.
472
- */
598
+ diagnosticsPosition?: 'top' | 'bottom';
473
599
  execute?: WqlExecutor;
474
- /** Debounce for live execution feedback. Default 150ms. */
600
+ /** Reuse host execution counts instead of running another query. */
601
+ stages?: WqlStageCounts;
475
602
  debounceMs?: number;
476
- /** Extension point: extra content rendered inside the bar, after the free-text input. */
477
603
  customSlots?: ReactNode;
478
- /** Host actions appended on the diagnostics line. */
479
604
  diagnosticsActions?: ReactNode;
480
- /**
481
- * Clause types kept in the model but NOT rendered as pills.
482
- */
483
605
  hiddenClauseTypes?: ClauseType[];
484
- /** Focus the free-text input on mount. */
606
+ /** Priority only; valid choices are never excluded by favorites. */
607
+ preferredChoices?: readonly string[];
485
608
  autoFocus?: boolean;
486
- /** Free-text input placeholder. */
487
609
  placeholder?: string;
488
610
  className?: string;
489
611
  }
490
- declare function WqlComposer({ initialClauses, clauses: controlledClauses, onClausesChange, onWqlChange, onValidationChange, onAstChange, onSubmit, showDiagnostics, execute, debounceMs, customSlots, diagnosticsActions, hiddenClauseTypes, autoFocus, placeholder, className, }: WqlComposerProps): react.JSX.Element;
612
+ declare function WqlComposer({ initialQuery, query, onQueryChange, onValidationChange, onAstChange, onSubmit, actionLabel, compact, showDiagnostics, diagnosticsPosition, execute, stages: suppliedStages, debounceMs, customSlots, diagnosticsActions, hiddenClauseTypes, preferredChoices, autoFocus, placeholder, className, }: WqlComposerProps): react.JSX.Element;
613
+
614
+ /**
615
+ * filterTypeahead — matches free text typed into the WqlComposer's input
616
+ * against the filter-clause vocabulary (queryClauses). While the user types
617
+ * a filter key ('so', 'inten', 'eff'…) the composer proposes adding that
618
+ * filter — or, when a pill of that type is already on the query, editing it.
619
+ * Accept (Tab or tap) adds/activates the pill and opens its condition
620
+ * editor; the composer owns candidates (source-plane allowlist, existing
621
+ * pills, hidden types) and the accept behavior.
622
+ *
623
+ * Pure module: no React.
624
+ */
625
+ interface FilterTypeaheadCandidate {
626
+ /** Clause type key, e.g. 'source' | 'effort' | 'catalog'. */
627
+ type: string;
628
+ label: string;
629
+ /** Placeholder describing the condition, e.g. 'journal, notes, metrics…'. */
630
+ hint: string;
631
+ icon: string;
632
+ /** True when a pill of this type is already on the query — accept edits it. */
633
+ present: boolean;
634
+ /** Index of the existing pill when `present`. */
635
+ pillIdx?: number;
636
+ }
637
+ interface FilterTypeaheadMatch extends FilterTypeaheadCandidate {
638
+ }
639
+ /**
640
+ * Match the typed text against candidate filter keys/labels: prefix match on
641
+ * the type key first, then the display label; shorter keys rank first within
642
+ * the same class. Mid-WQL text (whitespace, braces, or a `:` — the
643
+ * composer's query/raw/invalid pending paths own that) proposes nothing.
644
+ */
645
+ declare function matchFilterTypeahead(freeText: string, candidates: FilterTypeaheadCandidate[]): FilterTypeaheadMatch[];
646
+
647
+ interface TokenSlotPillProps {
648
+ clause: QueryClause;
649
+ isActive?: boolean;
650
+ invalid?: boolean;
651
+ invalidReason?: string;
652
+ onClick?: () => void;
653
+ onRemove?: () => void;
654
+ compact?: boolean;
655
+ placeholderOverride?: string;
656
+ }
657
+ declare function TokenSlotPill({ clause, isActive, invalid, invalidReason, onClick, onRemove, compact, placeholderOverride, }: TokenSlotPillProps): react.JSX.Element;
658
+
659
+ /** Multi-select (toggle-in-place) clause types. `source` is independently
660
+ * multi-select — applySourceFilter ORs the scope values. Typed tag keys and
661
+ * `groupby` OR their values in the engine (value lists join with `|`). */
662
+ declare const MULTI_VALUE_TYPES: Record<string, true>;
491
663
 
492
664
  interface CustomSlotEditorProps<TValue> {
493
665
  value: TValue | undefined;
@@ -515,47 +687,14 @@ declare class ComposerRegistry {
515
687
  private cachedList;
516
688
  registerSlot<TValue>(def: CustomSlotDefinition<TValue>): () => void;
517
689
  unregisterSlot(type: string): void;
518
- getSlot(type: string): CustomSlotDefinition<any> | undefined;
519
- listSlots(): CustomSlotDefinition<any>[];
520
- getAllSlots(): CustomSlotDefinition<any>[];
690
+ getSlot(type: string): CustomSlotDefinition | undefined;
691
+ listSlots(): CustomSlotDefinition[];
692
+ getAllSlots(): CustomSlotDefinition[];
521
693
  subscribe(listener: () => void): () => void;
522
694
  private notify;
523
695
  }
524
696
  declare const composerRegistry: ComposerRegistry;
525
- declare function useComposerSlots(registry?: ComposerRegistry): CustomSlotDefinition<any>[];
526
-
527
- interface TokenSlotPillProps {
528
- clause: QueryClause;
529
- isActive?: boolean;
530
- invalid?: boolean;
531
- invalidReason?: string;
532
- onClick?: () => void;
533
- onRemove?: () => void;
534
- onChange?: (patch: Partial<QueryClause>) => void;
535
- compact?: boolean;
536
- placeholderOverride?: string;
537
- }
538
- declare function TokenSlotPill({ clause, isActive, invalid, invalidReason, onClick, onRemove, onChange, compact, placeholderOverride, }: TokenSlotPillProps): react.JSX.Element;
539
- declare const MULTI_VALUE_TYPES: Record<string, true>;
540
- declare function ClausePopover({ clause, onClose, onChange, }: {
541
- clause: QueryClause;
542
- onClose: () => void;
543
- onChange: (patch: Partial<QueryClause>) => void;
544
- }): react.JSX.Element;
545
- declare function CustomSlotPopover<TValue>({ clause, definition, onClose, onChange, }: {
546
- clause: QueryClause;
547
- definition: CustomSlotDefinition<TValue>;
548
- onClose: () => void;
549
- onChange: (value: TValue) => void;
550
- }): react.JSX.Element;
551
- declare function AddFilterDropdown({ clauses, onAdd, }: {
552
- clauses: QueryClause[];
553
- onAdd: (clause: QueryClause) => void;
554
- }): react.JSX.Element;
555
- declare function AddCalcDropdown({ clauses, onAdd, }: {
556
- clauses: QueryClause[];
557
- onAdd: (clause: QueryClause) => void;
558
- }): react.JSX.Element | null;
697
+ declare function useComposerSlots(registry?: ComposerRegistry): CustomSlotDefinition[];
559
698
 
560
699
  interface DateRange {
561
700
  start: string;
@@ -581,7 +720,17 @@ interface SuggestionBinding {
581
720
  declare function tagsFromStaticBlocks(blocks: BlockIndexRow[]): string[];
582
721
  declare function catalogIdsFromBlocks(blocks: BlockIndexRow[]): string[];
583
722
  declare function blockTypesFromBlocks(blocks: BlockIndexRow[]): string[];
723
+ /** Tags: user labels rank first with their spelling, corpus fills the rest —
724
+ * one case-insensitive dedup path, insertion order kept (no global sort). */
584
725
  declare function mergeTagSuggestions(userLabels: string[], corpusLabels: string[]): string[];
726
+ /** Canonical static block types — actual indexed corpus types rank ahead at runtime. */
727
+ declare const CANONICAL_BLOCK_TYPES: readonly ["wod", "movement", "workout"];
728
+ /** Suggestion items for a canonical readonly vocabulary; labels are display-only. */
729
+ declare function canonicalSuggestionItems(values: readonly string[]): SuggestionItem[];
730
+ /** Case-insensitive dedup by value key: vault entries keep their position,
731
+ * enum keys take the canonical spelling, then remaining canonical values
732
+ * append. First label wins — it is display-only. */
733
+ declare function mergeSuggestionItems(vault: SuggestionItem[], canonical: SuggestionItem[]): SuggestionItem[];
585
734
  declare const SUGGESTION_BINDINGS: Record<string, SuggestionBinding>;
586
735
  declare function setSuggestionBinding(type: string, binding: SuggestionBinding | undefined): void;
587
736
  declare function getSuggestionBinding(type: string): SuggestionBinding | undefined;
@@ -599,7 +748,7 @@ declare function useSuggestions(type: string): ClauseSuggestions;
599
748
 
600
749
  interface WqlDiagnostics {
601
750
  valid: boolean;
602
- /** The composed WQL string for the current clause set. */
751
+ /** Exact resolved draft text, including invalid input. */
603
752
  wql: string;
604
753
  ast: AnyParsedQuery;
605
754
  error?: string;
@@ -609,6 +758,7 @@ interface WqlFindSummary {
609
758
  target: string;
610
759
  scope: string;
611
760
  timeWindow?: string;
761
+ groupBy?: string;
612
762
  hasJoin: boolean;
613
763
  filterCount: number;
614
764
  }
@@ -624,16 +774,102 @@ interface WqlAggregateSummary {
624
774
  filterCount: number;
625
775
  }
626
776
  declare function summarizeAggregate(ast: ParsedAggregateQuery): WqlAggregateSummary;
627
- declare function diagnoseClauses(clauses: QueryClause[]): WqlDiagnostics;
777
+ interface WqlPipelineSummary {
778
+ source: string;
779
+ /** One entry per transform stage, in order — `sum:tis`, `avg:load`, … */
780
+ functions: string[];
781
+ sink?: string;
782
+ timeWindow?: string;
783
+ filterCount: number;
784
+ }
785
+ declare function summarizePipeline(ast: ParsedPipelineQuery): WqlPipelineSummary;
628
786
 
629
787
  interface WqlDiagnosticsStripProps {
630
788
  diagnostics: WqlDiagnostics;
631
789
  offendingLabel?: string;
632
790
  stages?: WqlStageCounts;
791
+ /** Hide the AST summary chips (target/scope/time or agg/metric/by…) —
792
+ * header contexts where the pills right below already show that state. */
793
+ hideSummary?: boolean;
794
+ /** 'card' (default) renders the rounded, bordered bubble. 'header' renders
795
+ * a flat header section separated from the composer by an accent line. */
796
+ variant?: 'card' | 'header';
633
797
  actions?: ReactNode;
634
798
  className?: string;
635
799
  }
636
- declare function WqlDiagnosticsStrip({ diagnostics, offendingLabel, stages, actions, className, }: WqlDiagnosticsStripProps): react.JSX.Element;
800
+ declare function WqlDiagnosticsStrip({ diagnostics, offendingLabel, stages, hideSummary, variant, actions, className, }: WqlDiagnosticsStripProps): react.JSX.Element;
801
+
802
+ interface QueryDraft {
803
+ wql: string;
804
+ ast: AnyParsedQuery;
805
+ valid: boolean;
806
+ error?: string;
807
+ }
808
+ declare function wqlToPills(wql: string): QueryClause[] | null;
809
+ declare function editQueryClause(query: string, edited: QueryClause, value: string | null): QueryDraft;
810
+ declare function resolveQueryDraft(query: string, pendingText?: string): QueryDraft;
811
+
812
+ interface EditorDialogProps {
813
+ /** Controls visibility; the dialog unmounts its portal when closed. */
814
+ open: boolean;
815
+ onClose: () => void;
816
+ /** Dialog heading (aria-labelledby target). */
817
+ title: string;
818
+ /** Optional secondary line under the title (aria-describedby target). */
819
+ description?: string;
820
+ /** Body content — scrolls independently of the header/footer. */
821
+ children: ReactNode;
822
+ /** Sticky footer (e.g. Cancel/Save) — pinned above the keyboard on mobile. */
823
+ footer?: ReactNode;
824
+ /** 'default' (centered/full-screen, unchanged) or 'sheet' (mobile bottom
825
+ * sheet over the lower visible viewport, non-input initial focus,
826
+ * safe-area footer; desktop keeps the centered panel). */
827
+ presentation?: 'default' | 'sheet';
828
+ }
829
+ /**
830
+ * EditorDialog — accessible editor surface shared by dashboard/effort/note
831
+ * editing flows.
832
+ *
833
+ * Deliberately NOT a native `<dialog>`: the top layer would obscure any
834
+ * body-portaled surfaces a host renders above it (the WQL composer's
835
+ * hover/touch affordances, palette results). This renders a plain fixed
836
+ * overlay via portal, so portaled content keeps painting and receiving
837
+ * clicks/focus above it.
838
+ *
839
+ * Focus containment is lenient by the same constraint: Tab cycles within the
840
+ * dialog only while focus is inside it — focus that moves into a body-portaled
841
+ * popover is never yanked back, and the popover keeps its own keyboard
842
+ * handling. Escape is handled at the dialog container, so Escape consumed by
843
+ * a popover (e.g. to dismiss it) does not also close the dialog.
844
+ *
845
+ * Mobile (< sm): full visual-viewport screen driven by `window.visualViewport`
846
+ * (falls back to `100dvh`) — the keyboard shrinking the viewport lifts the
847
+ * footer, never the focused field. Desktop (sm+): contained centered panel.
848
+ */
849
+ declare function EditorDialog({ open, onClose, title, description, children, footer, presentation, }: EditorDialogProps): react.ReactPortal | null;
850
+
851
+ interface VisualViewportRect {
852
+ /**
853
+ * Visible viewport height in px, or null when the VisualViewport API is
854
+ * unavailable (SSR, older engines). Consumers should fall back to a
855
+ * dynamic-viewport unit (e.g. `100dvh`) in that case.
856
+ */
857
+ height: number | null;
858
+ /** Distance from the layout viewport top to the visual viewport top (pinch-zoom). */
859
+ offsetTop: number;
860
+ /**
861
+ * Distance the visual viewport's bottom edge sits above the layout
862
+ * viewport's bottom edge — i.e. the on-screen keyboard's height (0 when
863
+ * the keyboard is closed).
864
+ */
865
+ offsetBottom: number;
866
+ }
867
+ /**
868
+ * Tracks `window.visualViewport` (resize + scroll). Drives keyboard-aware
869
+ * bottom-anchored UI (dialogs, thumb docks) without keyboard-size guessing
870
+ * or browser sniffing: the platform reports the visible rectangle.
871
+ */
872
+ declare function useVisualViewportRect(): VisualViewportRect;
637
873
 
638
874
  declare function cn(...inputs: ClassValue[]): string;
639
875
  declare function hashCode(str: string): number;
@@ -658,13 +894,13 @@ declare function patchBlockQuery(blockContent: string, newQuery: string, queryIn
658
894
  * Auto-generated build version metadata.
659
895
  * Do not edit directly; updated by scripts/stamp-version.ts
660
896
  */
661
- declare const VERSION = "0.10.42";
662
- declare const GIT_SHA = "79c6d18";
663
- declare const BUILD_TIME = "2026-08-26T04:44:54.356Z";
897
+ declare const VERSION = "0.35.2115";
898
+ declare const GIT_SHA = "37944a8";
899
+ declare const BUILD_TIME = "2026-10-11T23:54:36.367Z";
664
900
  declare const SEMVER: {
665
- readonly version: "0.10.42";
666
- readonly gitSha: "79c6d18";
667
- readonly buildTime: "2026-08-26T04:44:54.356Z";
901
+ readonly version: "0.35.2115";
902
+ readonly gitSha: "37944a8";
903
+ readonly buildTime: "2026-10-11T23:54:36.367Z";
668
904
  };
669
905
 
670
- export { AGG_OPTIONS, ANALYTICS_UNIT_STORAGE_KEY, AddCalcDropdown, AddFilterDropdown, type AnalyticsQueriesState, type AnalyticsQueryDef, type AnalyticsRangeWeeks, type AnalyticsUnit, AnalyticsUnitPreference, type AnalyticsUnitPreferenceProps, BUILD_TIME, CLAUSE_META, CODEMIRROR_SINGLETON_DEPS, CONTENT_SOURCES, type ChartShape, type ClauseMeta, ClausePopover, type ClauseSuggestions, type ClauseType, ComposerRegistry, type CustomSlotDefinition, type CustomSlotEditorProps, CustomSlotPopover, DEFAULT_ANALYTICS_UNIT, DEFAULT_DIAGNOSTICS_DEBOUNCE_MS, DashboardTokenControls, type DashboardTokenControlsProps, DashboardView, type DashboardViewProps, type DateRange, type ExtractedQuery, GIT_SHA, GROUPBY_OPTIONS, GoalRings, type GoalRingsProps, METRIC_OPTIONS, MULTI_VALUE_TYPES, type MergedPoint, ProposedMetricBadge, QueryBlockView, type QueryBlockViewProps, type QueryClause, QueryExecutor, QueryValue, type QueryValueProps, ROLLUP_OPTIONS, RangeSelector, type RangeSelectorProps, RowsResultsChrome, type RowsResultsChromeProps, RowsTable, type RowsTableProps, SEMVER, SERIES_COLORS, SOURCE_OPTIONS, SUGGESTION_BINDINGS, StackedBar, type StackedBarProps, type StorageLike, type SuggestionBinding, type SuggestionCachePolicy, type SuggestionItem, TIME_OPTIONS, TokenSlotPill, type TokenSlotPillProps, TopList, type TopListProps, UNIT_OPTIONS, VERSION, WHERE_AGGREGATORS, WHERE_METRICS, WHERE_OPERATORS, WidgetChart, type WidgetChartProps, WidgetFrame, type WidgetFrameProps, WidgetProblemBadge, type WqlAggregateSummary, WqlBars, type WqlBarsProps, WqlComposer, type WqlComposerProps, type WqlDiagnostics, WqlDiagnosticsStrip, type WqlDiagnosticsStripProps, WqlEmptyState, type WqlEmptyStateProps, type WqlExecutor, type WqlFindSummary, WqlQueryInspectorModal, type WqlQueryInspectorModalProps, type WqlStageCounts, WqlTable, type WqlTableProps, WqlTimeseries, type WqlTimeseriesProps, type WqlValidationState, ZoneDistribution, type ZoneDistributionProps, blockTypesFromBlocks, catalogIdsFromBlocks, clauseToWql, clauseValue, clausesToWql, cn, compactNumber, composerRegistry, dateRangeSlot, defaultClauses, defaultMetricsClauses, diagnoseClauses, extractBlockQueries, formatTimestamp, getClauseMeta, getDashboardEffectiveUnit, getEffectiveAnalyticsUnit, getSuggestionBinding, hashCode, invalidateSuggestions, loadSuggestions, mergeSeries, mergeTagSuggestions, patchBlockQuery, pivotClauses, readSessionRpe, readStoredUnit, setMetricClause, setSuggestionBinding, sourcePlane, summarizeAggregate, summarizeFind, tagsFromStaticBlocks, tooltipTimestamp, useAnalyticsQueries, useAnalyticsUnitPreference, useChartShape, useComposerSlots, useSuggestions, useWqlStageCounts, wqlToClauses };
906
+ export { AGG_OPTIONS, ANALYTICS_UNIT_STORAGE_KEY, type AnalyticsQueriesState, type AnalyticsQueryDef, type AnalyticsRangeWeeks, type AnalyticsUnit, AnalyticsUnitPreference, type AnalyticsUnitPreferenceProps, BUILD_TIME, CANONICAL_BLOCK_TYPES, CLAUSE_META, CODEMIRROR_SINGLETON_DEPS, type CategorizedMetrics, type ChartShape, type ClauseMeta, type ClauseSuggestions, type ClauseType, ComposerRegistry, type CustomSlotDefinition, type CustomSlotEditorProps, DEFAULT_ANALYTICS_UNIT, DEFAULT_DIAGNOSTICS_DEBOUNCE_MS, DEFAULT_OUTPUT_FILTERS, DEFAULT_PRIMARY_FILTER, type DashboardHeadingAnchor, DashboardTokenControls, type DashboardTokenControlsProps, DashboardView, type DashboardViewProps, type DateRange, EditorDialog, type EditorDialogProps, type ExtractedQuery, type FilterTypeaheadCandidate, type FilterTypeaheadMatch, GIT_SHA, GROUPBY_OPTIONS, GoalRings, type GoalRingsProps, KIND_OPTIONS, METRIC_OPTIONS, MULTI_VALUE_TYPES, type MergedPoint, MetricBadge, OUTPUT_TYPE_CLASS, OUTPUT_TYPE_DOT, type OutputFilterInput, OutputFilterPills, type OutputFilterPreset, type OutputStatementRow, OutputStatementsTable, type OutputStatementsTableProps, PLANE_OPTIONS, ProposedMetricBadge, QueryBlockView, type QueryBlockViewProps, type QueryClause, type QueryDraft, QueryExecutor, QueryValue, type QueryValueProps, ROLLUP_OPTIONS, RangeSelector, type RangeSelectorProps, RowsResultsChrome, type RowsResultsChromeProps, RowsTable, type RowsTableProps, SEMVER, SERIES_COLORS, SOURCE_OPTIONS, SUGGESTION_BINDINGS, StackedBar, type StackedBarProps, type StorageLike, type SuggestionBinding, type SuggestionCachePolicy, type SuggestionItem, TARGET_OPTIONS, TIME_OPTIONS, TONE_CLASS, TokenSlotPill, type TokenSlotPillProps, TopList, type TopListProps, UNIT_OPTIONS, VERSION, type VisualViewportRect, WHERE_AGGREGATORS, WHERE_METRICS, WidgetChart, type WidgetChartProps, WidgetEditButton, WidgetFrame, type WidgetFrameProps, WidgetProblemBadge, type WidgetSpanOption, WidgetToolButton, type WqlAggregateSummary, WqlBars, type WqlBarsProps, WqlComposer, type WqlComposerProps, type WqlDiagnostics, WqlDiagnosticsStrip, type WqlDiagnosticsStripProps, WqlEmptyState, type WqlEmptyStateProps, type WqlExecutor, type WqlFindSummary, type WqlPipelineSummary, WqlQueryInspectorModal, type WqlQueryInspectorModalProps, type WqlStageCounts, WqlTable, type WqlTableProps, WqlTimeseries, type WqlTimeseriesProps, type WqlValidationState, ZoneDistribution, type ZoneDistributionProps, blockTypesFromBlocks, canonicalSuggestionItems, catalogIdsFromBlocks, cn, compactNumber, composerRegistry, dateRangeSlot, editQueryClause, extractBlockQueries, extractMetricsByCategory, formatClockTime, formatMMSS, formatTimestamp, getClauseMeta, getDashboardEffectiveUnit, getEffectiveAnalyticsUnit, getSuggestionBinding, hashCode, invalidateSuggestions, loadSuggestions, matchFilterTypeahead, mergeSeries, mergeSuggestionItems, mergeTagSuggestions, normalizeOutputFilter, patchBlockQuery, presentBadges, readSessionRpe, readStoredUnit, resolveQueryDraft, setSuggestionBinding, summarizeAggregate, summarizeFind, summarizePipeline, tagsFromStaticBlocks, tooltipTimestamp, useAnalyticsQueries, useAnalyticsUnitPreference, useChartShape, useComposerSlots, useSuggestions, useVisualViewportRect, useWqlStageCounts, wqlToPills };