@bitcobblers/wod-wiki-ui 0.35.2119 → 0.35.2120
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.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.mjs +6 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -894,13 +894,13 @@ declare function patchBlockQuery(blockContent: string, newQuery: string, queryIn
|
|
|
894
894
|
* Auto-generated build version metadata.
|
|
895
895
|
* Do not edit directly; updated by scripts/stamp-version.ts
|
|
896
896
|
*/
|
|
897
|
-
declare const VERSION = "0.35.
|
|
898
|
-
declare const GIT_SHA = "
|
|
899
|
-
declare const BUILD_TIME = "2026-10-13T06:
|
|
897
|
+
declare const VERSION = "0.35.2120";
|
|
898
|
+
declare const GIT_SHA = "62def0d";
|
|
899
|
+
declare const BUILD_TIME = "2026-10-13T06:46:25.596Z";
|
|
900
900
|
declare const SEMVER: {
|
|
901
|
-
readonly version: "0.35.
|
|
902
|
-
readonly gitSha: "
|
|
903
|
-
readonly buildTime: "2026-10-13T06:
|
|
901
|
+
readonly version: "0.35.2120";
|
|
902
|
+
readonly gitSha: "62def0d";
|
|
903
|
+
readonly buildTime: "2026-10-13T06:46:25.596Z";
|
|
904
904
|
};
|
|
905
905
|
|
|
906
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -894,13 +894,13 @@ declare function patchBlockQuery(blockContent: string, newQuery: string, queryIn
|
|
|
894
894
|
* Auto-generated build version metadata.
|
|
895
895
|
* Do not edit directly; updated by scripts/stamp-version.ts
|
|
896
896
|
*/
|
|
897
|
-
declare const VERSION = "0.35.
|
|
898
|
-
declare const GIT_SHA = "
|
|
899
|
-
declare const BUILD_TIME = "2026-10-13T06:
|
|
897
|
+
declare const VERSION = "0.35.2120";
|
|
898
|
+
declare const GIT_SHA = "62def0d";
|
|
899
|
+
declare const BUILD_TIME = "2026-10-13T06:46:25.596Z";
|
|
900
900
|
declare const SEMVER: {
|
|
901
|
-
readonly version: "0.35.
|
|
902
|
-
readonly gitSha: "
|
|
903
|
-
readonly buildTime: "2026-10-13T06:
|
|
901
|
+
readonly version: "0.35.2120";
|
|
902
|
+
readonly gitSha: "62def0d";
|
|
903
|
+
readonly buildTime: "2026-10-13T06:46:25.596Z";
|
|
904
904
|
};
|
|
905
905
|
|
|
906
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 };
|
package/dist/index.mjs
CHANGED
|
@@ -680,13 +680,13 @@ function AnalyticsUnitPreference({ className, unit: unitProp, forced = false, st
|
|
|
680
680
|
}
|
|
681
681
|
|
|
682
682
|
// src/version.ts
|
|
683
|
-
var VERSION = "0.35.
|
|
684
|
-
var GIT_SHA = "
|
|
685
|
-
var BUILD_TIME = "2026-10-13T06:
|
|
683
|
+
var VERSION = "0.35.2120";
|
|
684
|
+
var GIT_SHA = "62def0d";
|
|
685
|
+
var BUILD_TIME = "2026-10-13T06:46:25.596Z";
|
|
686
686
|
var SEMVER = {
|
|
687
|
-
version: "0.35.
|
|
688
|
-
gitSha: "
|
|
689
|
-
buildTime: "2026-10-13T06:
|
|
687
|
+
version: "0.35.2120",
|
|
688
|
+
gitSha: "62def0d",
|
|
689
|
+
buildTime: "2026-10-13T06:46:25.596Z"
|
|
690
690
|
};
|
|
691
691
|
|
|
692
692
|
export { ANALYTICS_UNIT_STORAGE_KEY, AnalyticsUnitPreference, BUILD_TIME, CODEMIRROR_SINGLETON_DEPS, DEFAULT_ANALYTICS_UNIT, DashboardTokenControls, DashboardView, GIT_SHA, RangeSelector, SEMVER, VERSION, WidgetEditButton, WidgetFrame, WidgetToolButton, getDashboardEffectiveUnit, getEffectiveAnalyticsUnit, readStoredUnit, useAnalyticsQueries, useAnalyticsUnitPreference };
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/contracts/dedupe.ts","../src/widgets/WidgetFrame.tsx","../src/widgets/DashboardTokenControls.tsx","../src/widgets/DashboardView.tsx","../src/widgets/RangeSelector.tsx","../src/widgets/useAnalyticsQueries.ts","../src/widgets/useAnalyticsUnitPreference.tsx","../src/version.ts"],"names":["jsx","jsxs","useState","useEffect","Fragment","SharedQueryDocumentRunner","parseQuery"],"mappings":";;;;;;;;AAAO,IAAM,yBAAA,GAA4B;AAAA,EACvC,0BAAA;AAAA,EACA,sBAAA;AAAA,EACA,2BAAA;AAAA,EACA,sBAAA;AAAA,EACA,kBAAA;AAAA,EACA,oBAAA;AAAA,EACA,mBAAA;AAAA,EACA,4BAAA;AAAA,EACA,kBAAA;AAAA,EACA,eAAA;AAAA,EACA,kBAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF;ACkBO,SAAS,WAAA,CAAY,EAAE,EAAA,EAAI,KAAA,EAAO,QAAA,EAAU,KAAA,EAAO,IAAA,EAAM,SAAA,GAAY,KAAA,EAAO,SAAA,EAAW,gBAAA,EAAkB,OAAA,EAAS,UAAS,EAAqB;AACrJ,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,EAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,wFAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,6CAAA,EACb,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,SAAA,EACb,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,uCAAA,EAAyC,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,YAC5D,QAAA,oBAAY,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,sCAAsC,QAAA,EAAA,QAAA,EAAS;AAAA,WAAA,EAC3E,CAAA;AAAA,UAAA,CACE,SAAA,IAAa,gBAAA,qBACb,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,kCAAA,EACZ,QAAA,EAAA;AAAA,YAAA,SAAA,oBACC,GAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,OAAA,EAAS,SAAA;AAAA,gBACT,KAAA,EAAM,sBAAA;AAAA,gBACN,YAAA,EAAY,CAAA,kBAAA,EAAqB,KAAA,IAAS,QAAQ,CAAA,CAAA;AAAA,gBAClD,SAAA,EAAU,+JAAA;AAAA,gBAEV,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAU,aAAA,EAAc;AAAA;AAAA,aAC/B;AAAA,YAED,gBAAA,oBACC,GAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,OAAA,EAAS,gBAAA;AAAA,gBACT,KAAA,EAAM,kBAAA;AAAA,gBACN,YAAA,EAAY,CAAA,KAAA,EAAQ,KAAA,IAAS,QAAQ,CAAA,YAAA,CAAA;AAAA,gBACrC,SAAA,EAAU,+JAAA;AAAA,gBAEV,QAAA,kBAAA,GAAA,CAAC,YAAA,EAAA,EAAa,SAAA,EAAU,aAAA,EAAc;AAAA;AAAA;AACxC,WAAA,EAEJ;AAAA,SAAA,EAEJ,CAAA;AAAA,QACC,OAAA,oBAAW,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,QAAQ,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,QAI1C,SAAA,IAAa,SAAS,IAAA,IAAQ,KAAA,KAAU,sBACvC,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6GAAA,EACZ,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,wBAEF,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EAAkB,QAAA,EAAS;AAAA;AAAA;AAAA,GAC5C;AAEJ;AAGO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,KAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAMG;AACD,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,OAAA;AAAA,MACA,KAAA,EAAO,KAAA;AAAA,MACP,YAAA,EAAY,KAAA;AAAA,MACZ,QAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,wNAAA;AAAA,QACA,MAAA,IAAU;AAAA,OACZ;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;AAGO,SAAS,gBAAA,CAAiB,EAAE,KAAA,EAAO,OAAA,EAAQ,EAA2C;AAC3F,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,OAAA;AAAA,MACA,KAAA,EAAM,aAAA;AAAA,MACN,YAAA,EAAY,CAAA,YAAA,EAAe,KAAA,IAAS,EAAE,GAAG,IAAA,EAAK;AAAA,MAC9C,SAAA,EAAU,+JAAA;AAAA,MAEV,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAU,aAAA,EAAc;AAAA;AAAA,GACjC;AAEJ;AC7GA,SAAS,gBAAA,CAAiB;AAAA,EACxB,IAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAKG;AACD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,KAAK,CAAA;AACxC,EAAA,SAAA,CAAU,MAAM,QAAA,CAAS,KAAK,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAExC,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,IAAI,KAAA,KAAU,KAAA,EAAO,QAAA,CAAS,KAAK,CAAA;AAAA,EACrC,CAAA;AAEA,EAAA,uBACEA,GAAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,MAAA;AAAA,MACL,KAAA,EAAO,KAAA;AAAA,MACP,QAAA;AAAA,MACA,UAAU,CAAC,CAAA,KAAM,QAAA,CAAS,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,MACxC,MAAA,EAAQ,MAAA;AAAA,MACR,SAAA,EAAW,CAAC,CAAA,KAAM;AAChB,QAAA,IAAI,CAAA,CAAE,QAAQ,OAAA,EAAS;AACrB,UAAA,MAAA,EAAO;AACP,UAAA,CAAA,CAAE,cAAc,IAAA,EAAK;AAAA,QACvB;AAAA,MACF,CAAA;AAAA,MACA,YAAA,EAAY,SAAS,IAAI,CAAA,CAAA;AAAA,MACzB,SAAA,EAAU;AAAA;AAAA,GACZ;AAEJ;AAQO,SAAS,sBAAA,CAAuB,EAAE,MAAA,EAAQ,MAAA,EAAQ,UAAS,EAAgC;AAChG,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAChC,EAAA,MAAM,WAAW,CAAC,QAAA;AAElB,EAAA,uBACEA,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAY,0BAAA;AAAA,MACZ,SAAA,EAAU,kDAAA;AAAA,MAET,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AACrB,QAAA,MAAM,UAAU,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA,IAAK,KAAA,CAAM,OAAO,CAAC,CAAA;AACpD,QAAA,uBACEC,IAAAA,CAAC,KAAA,EAAA,EAAqB,SAAA,EAAU,yBAAA,EAC9B,QAAA,EAAA;AAAA,0BAAAA,IAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,6CAAA,EAA8C,QAAA,EAAA;AAAA,YAAA,GAAA;AAAA,YAAE,KAAA,CAAM;AAAA,WAAA,EAAK,CAAA;AAAA,UAC1E,KAAA,CAAM,MAAA,mBACLD,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4EAAA,EACZ,QAAA,EAAA,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,CAAC,MAAA,qBACjBA,GAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cAEC,IAAA,EAAK,QAAA;AAAA,cACL,QAAA,EAAU,QAAA;AAAA,cACV,SAAS,MAAM;AAEb,gBAAA,IAAI,MAAA,KAAW,OAAA,EAAS,QAAA,GAAW,KAAA,CAAM,MAAM,MAAM,CAAA;AAAA,cACvD,CAAA;AAAA,cACA,SAAA,EAAW,EAAA;AAAA,gBACT,kDAAA;AAAA,gBACA,MAAA,KAAW,UACP,gDAAA,GACA,4DAAA;AAAA,gBACJ,QAAA,IAAY;AAAA,eACd;AAAA,cAEC,QAAA,EAAA;AAAA,aAAA;AAAA,YAfI;AAAA,WAiBR,CAAA,EACH,CAAA,GACE,QAAA,mBACFA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mCAAA,EAAqC,QAAA,EAAA,OAAA,EAAQ,CAAA,mBAE7DA,GAAAA;AAAA,YAAC,gBAAA;AAAA,YAAA;AAAA,cACC,MAAM,KAAA,CAAM,IAAA;AAAA,cACZ,KAAA,EAAO,OAAA;AAAA,cACP,UAAU,CAAC,IAAA,KAAS,QAAA,GAAW,KAAA,CAAM,MAAM,IAAI;AAAA;AAAA;AACjD,SAAA,EAAA,EAhCM,MAAM,IAkChB,CAAA;AAAA,MAEJ,CAAC;AAAA;AAAA,GACH;AAEJ;AClCO,SAAS,0BAAA,CACd,QAAA,EACA,KAAA,GAAgH,EAAC,EACxF;AACzB,EAAA,OAAO;AAAA,IACL,cAAc,CAAC,SAAA,EAAW,SAAA,KACxB,QAAA,CAAS,SAAS,SAAA,EAAW;AAAA,MAC3B,SAAS,SAAA,CAAU,OAAA;AAAA,MACnB,YAAY,KAAA,CAAM,UAAA;AAAA,MAClB,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,eAAe,KAAA,CAAM;AAAA,KACtB,CAAA;AAAA,IACH,OAAA,EAAS,OAAO,SAAA,EAAW,OAAA,KAAY;AACrC,MAAA,MAAM,MAAA,GAAS,WAAW,SAAS,CAAA;AACnC,MAAA,IAAI,CAAC,WAAA,CAAY,MAAM,CAAA,EAAG,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,CAAA,qBAAA,EAAwB,SAAS,CAAA,CAAA,EAAG;AAC5F,MAAA,MAAM,GAAA,GAAM,MAAM,QAAA,CAAS,OAAA,CAAQ,MAAA,EAAQ;AAAA,QACzC,OAAA;AAAA,QACA,KAAA,EAAO,KAAA,CAAM,UAAA,KAAe,MAAA,GACxB,EAAE,KAAA,EAAO,KAAA,CAAM,UAAA,EAAY,GAAA,EAAK,MAAM,QAAA,IAAY,MAAA,CAAO,gBAAA,EAAkB,YAAA,EAAc,OAAM,GAC/F;AAAA,OACL,CAAA;AACD,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,MAAA;AAAA,QACN,OAAO,GAAA,CAAI,KAAA;AAAA,QACX,QAAQ,GAAA,CAAI,MAAA;AAAA,QACZ,SAAS,GAAA,CAAI,OAAA;AAAA,QACb,YAAY,GAAA,CAAI,UAAA;AAAA,QAChB,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,OAAO,GAAA,CAAI;AAAA,OACb;AAAA,IACF,CAAA;AAAA,IACA,WAAA,EAAa,OAAO,SAAA,EAAW,OAAA,KAAY;AACzC,MAAA,MAAM,GAAA,GAAM,MAAM,QAAA,CAAS,WAAA,GAAc,SAAA,EAAW;AAAA,QAClD,OAAA;AAAA,QACA,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,UAAU,KAAA,CAAM,QAAA;AAAA,QAChB,eAAe,KAAA,CAAM;AAAA,OACtB,CAAA;AACD,MAAA,OAAO,GAAA,IAAO,EAAE,KAAA,EAAO,qDAAA,EAAsD;AAAA,IAC/E,CAAA;AAAA,IACA,cAAc,KAAA,CAAM;AAAA,GACtB;AACF;AAGA,SAAS,iBAAA,CAAkB,QAAwB,GAAA,EAAsC;AACvF,EAAA,MAAM,OAAO,aAAA,CAAc,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAI,MAAA,EAAQ,IAAA,EAAM,GAAA,CAAI,IAAA,EAAM,OAAO,GAAA,CAAI,KAAA,EAAO,KAAA,EAAO,GAAA,CAAI,OAAO,CAAA;AAC7G,EAAA,OAAO,MAAA,CAAO,OAAO,IAAA,EAAM;AAAA,IACzB,GAAI,IAAI,KAAA,GAAQ,EAAE,OAAO,GAAA,CAAI,KAAA,KAAU,EAAC;AAAA,IACxC,GAAI,IAAI,MAAA,GAAS,EAAE,QAAQ,GAAA,CAAI,MAAA,KAAW,EAAC;AAAA,IAC3C,GAAI,IAAI,OAAA,GAAU,EAAE,SAAS,GAAA,CAAI,OAAA,KAAY,EAAC;AAAA,IAC9C,GAAI,IAAI,UAAA,GAAa,EAAE,YAAY,GAAA,CAAI,UAAA,KAAe,EAAC;AAAA,IACvD,GAAI,IAAI,IAAA,GAAO,EAAE,MAAM,GAAA,CAAI,IAAA,KAAS;AAAC,GACtC,CAAA;AACH;AAMA,SAAS,UAAU,MAAA,EAAiC;AAClD,EAAA,IAAI,MAAA,CAAO,UAAU,OAAO,wCAAA;AAC5B,EAAA,IAAI,MAAA,CAAO,YAAY,IAAA,EAAM;AAC3B,IAAA,IAAI,MAAA,CAAO,QAAA,IAAY,CAAA,EAAG,OAAO,YAAA;AACjC,IAAA,IAAI,MAAA,CAAO,QAAA,KAAa,CAAA,EAAG,OAAO,0BAAA;AAClC,IAAA,IAAI,MAAA,CAAO,QAAA,KAAa,CAAA,EAAG,OAAO,wCAAA;AAClC,IAAA,OAAO,wCAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,MAAA,CAAO,IAAI,CAAA;AAC9C,EAAA,IAAI,QAAA,KAAa,SAAS,OAAO,YAAA;AACjC,EAAA,IAAI,QAAA,KAAa,SAAS,OAAO,0BAAA;AACjC,EAAA,OAAO,wCAAA;AACT;AAGA,IAAM,YAAA,GAAiF;AAAA,EACrF,EAAE,OAAO,eAAA,EAAiB,IAAA,EAAM,EAAE,QAAA,EAAU,CAAA,EAAE,EAAG,MAAA,EAAQ,eAAA,EAAgB;AAAA,EACzE,EAAE,OAAO,gBAAA,EAAkB,IAAA,EAAM,EAAE,QAAA,EAAU,CAAA,EAAE,EAAG,MAAA,EAAQ,eAAA,EAAgB;AAAA,EAC1E,EAAE,OAAO,gBAAA,EAAkB,IAAA,EAAM,EAAE,QAAA,EAAU,CAAA,EAAE,EAAG,MAAA,EAAQ,eAAA,EAAgB;AAAA,EAC1E,EAAE,OAAO,UAAA,EAAY,IAAA,EAAM,EAAE,QAAA,EAAU,IAAA,EAAK,EAAG,MAAA,EAAQ,kBAAA;AACzD,CAAA;AAEA,SAAS,YAAA,CAAa,QAAyB,IAAA,EAAiC;AAC9E,EAAA,IAAI,IAAA,CAAK,QAAA,EAAU,OAAO,MAAA,CAAO,QAAA,KAAa,IAAA;AAC9C,EAAA,OAAO,CAAC,MAAA,CAAO,QAAA,IAAA,CAAa,OAAO,QAAA,IAAY,IAAA,OAAW,KAAK,QAAA,IAAY,IAAA,CAAA;AAC7E;AAWO,SAAS,aAAA,CAAc;AAAA,EAC5B,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,mBAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,YAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,iBAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAAuB;AACrB,EAAA,MAAM,MAAA,GAAS,OAAA;AAAA,IACb,OAAO,EAAE,GAAG,kBAAA,CAAmB,SAAS,MAAM,CAAA,EAAG,GAAG,WAAA,EAAY,CAAA;AAAA,IAChE,CAAC,QAAA,CAAS,MAAA,EAAQ,WAAW;AAAA,GAC/B;AAEA,EAAA,MAAM,QAAA,GAAW,OAAA;AAAA,IACf,MACE,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AAC/B,MAAA,MAAM,EAAE,KAAA,EAAO,OAAA,KAAY,gBAAA,CAAiB,MAAA,CAAO,MAAM,MAAM,CAAA;AAI/D,MAAA,MAAM,aAAqC,EAAC;AAC5C,MAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,OAAO,CAAA;AAClC,MAAA,KAAA,MAAW,CAAC,KAAK,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,UAAU,CAAA,EAAG;AAC5D,QAAA,MAAM,GAAA,GAAM,gBAAA,CAAiB,KAAA,EAAO,MAAM,CAAA;AAC1C,QAAA,UAAA,CAAW,GAAG,IAAI,GAAA,CAAI,KAAA;AACtB,QAAA,KAAA,MAAW,CAAA,IAAK,GAAA,CAAI,OAAA,EAAS,UAAA,CAAW,IAAI,CAAC,CAAA;AAAA,MAC/C;AACA,MAAA,OAAO,EAAE,QAAQ,KAAA,EAAO,OAAA,EAAS,CAAC,GAAG,UAAU,GAAG,UAAA,EAAW;AAAA,IAC/D,CAAC,CAAA;AAAA,IACH,CAAC,QAAA,CAAS,OAAA,EAAS,MAAM;AAAA,GAC3B;AAEA,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIE,QAAAA,CAAoC,EAAE,CAAA;AAC9D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,SAAS,IAAI,CAAA;AAE3C,EAAA,MAAM,WAAA,GAAc,OAAA;AAAA,IAClB,MAAM,QAAA,CAAS,GAAA,CAAI,CAAC,MAAM,CAAA,EAAG,CAAA,CAAE,MAAA,CAAO,GAAG,IAAI,CAAA,CAAE,KAAK,CAAA,CAAE,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,IAChE,CAAC,QAAQ;AAAA,GACX;AAEA,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,UAAA,CAAW,IAAI,CAAA;AAEf,IAAA,eAAe,IAAA,GAAO;AACpB,MAAA,MAAM,OAAkC,EAAC;AACzC,MAAA,MAAM,WAAsF,EAAC;AAE7F,MAAA,KAAA,MAAW,EAAE,MAAA,EAAQ,KAAA,EAAO,OAAA,MAAa,QAAA,EAAU;AACjD,QAAA,IAAI,OAAO,IAAA,KAAS,EAAA,IAAM,CAAC,qBAAA,CAAsB,MAAA,CAAO,IAAI,CAAA,EAAG;AAC7D,UAAA,IAAA,CAAK,MAAA,CAAO,GAAG,CAAA,GAAI,EAAE,OAAO,wBAAA,CAAyB,MAAA,CAAO,IAAI,CAAA,EAAE;AAClE,UAAA;AAAA,QACF;AACA,QAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,UAAA,IAAA,CAAK,OAAO,GAAG,CAAA,GAAI,EAAE,KAAA,EAAO,oBAAA,CAAqB,OAAO,CAAA,EAAE;AAC1D,UAAA;AAAA,QACF;AACA,QAAA,MAAM,MAAA,GAAS,WAAW,KAAK,CAAA;AAC/B,QAAA,IAAI,OAAO,KAAA,EAAO;AAChB,UAAA,IAAA,CAAK,OAAO,GAAG,CAAA,GAAI,EAAE,KAAA,EAAO,OAAO,KAAA,EAAM;AACzC,UAAA;AAAA,QACF;AACA,QAAA,MAAM,YAAA,GAAe,iBAAA,CAAkB,MAAA,CAAO,IAAI,CAAA;AAClD,QAAA,IAAI,WAAA,CAAY,MAAM,CAAA,EAAG;AACvB,UAAA,IAAI,YAAA,KAAiB,OAAA,IAAW,YAAA,KAAiB,MAAA,EAAQ;AACvD,YAAA,IAAA,CAAK,MAAA,CAAO,GAAG,CAAA,GAAI,EAAE,OAAO,yEAAA,EAAqE;AACjG,YAAA;AAAA,UACF;AAAA,QACF,WAAW,CAAC,eAAA,CAAgB,MAAM,CAAA,IAAK,iBAAiB,MAAA,EAAQ;AAC9D,UAAA,IAAA,CAAK,MAAA,CAAO,GAAG,CAAA,GAAI,EAAE,OAAO,6EAAA,EAAyE;AACrG,UAAA;AAAA,QACF;AACA,QAAA,QAAA,CAAS,IAAA,CAAK,EAAE,MAAA,EAAQ,KAAA,EAAO,QAAQ,CAAA;AAAA,MACzC;AAEA,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,IAAI,CAAC,SAAA,EAAW;AACd,UAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,UAAA,UAAA,CAAW,KAAK,CAAA;AAAA,QAClB;AACA,QAAA;AAAA,MACF;AAMA,MAAA,MAAM,IAAA,GAAO,2BAA2B,QAAA,EAAU;AAAA,QAChD,UAAA;AAAA,QACA,QAAA;AAAA,QACA,aAAA;AAAA,QACA,YAAA,EAAc;AAAA,OACf,CAAA;AAED,MAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,QACZ,SAAS,GAAA,CAAI,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,QAAO,KAAM;AAChD,UAAA,IAAI;AACF,YAAA,MAAM,MAAA,GAAS,IAAI,yBAAA,CAA0B,IAAI,CAAA;AACjD,YAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AAClC,YAAA,MAAM,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA;AACzB,YAAA,IAAI,CAAC,GAAA,EAAK;AACR,cAAA,IAAA,CAAK,MAAA,CAAO,GAAG,CAAA,GAAI,EAAE,OAAO,GAAA,CAAI,WAAA,CAAY,CAAC,CAAA,IAAK,2BAAA,EAA4B;AAC9E,cAAA;AAAA,YACF;AACA,YAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,IAAS,GAAA,CAAI,YAAY,CAAC,CAAA;AAC5C,YAAA,IAAA,CAAK,MAAA,CAAO,GAAG,CAAA,GAAI;AAAA,cACjB,MAAA,EAAQ,iBAAA,CAAkB,MAAA,EAAQ,GAAG,CAAA;AAAA,cACrC,GAAI,KAAA,GAAQ,EAAE,KAAA,KAAU;AAAC,aAC3B;AAAA,UACF,SAAS,GAAA,EAAK;AACZ,YAAA,IAAA,CAAK,MAAA,CAAO,GAAG,CAAA,GAAI,EAAE,KAAA,EAAO,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAA,EAAE;AAAA,UAC/E;AAAA,QACF,CAAC;AAAA,OACH;AAEA,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB;AAAA,IACF;AAEA,IAAA,KAAK,IAAA,EAAK;AACV,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,WAAA,EAAa,QAAA,EAAU,UAAU,mBAAA,EAAqB,UAAA,EAAY,QAAA,EAAU,aAAa,CAAC,CAAA;AAE9F,EAAA,uBACEF,IAAAA,CAAC,KAAA,EAAA,EAAI,aAAA,EAAY,gBAAA,EACf,QAAA,EAAA;AAAA,oBAAAD,IAAC,sBAAA,EAAA,EAAuB,MAAA,EAAQ,SAAS,MAAA,EAAQ,MAAA,EAAgB,UAAU,aAAA,EAAe,CAAA;AAAA,IAEzF,2BAAWA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sCAAqC,QAAA,EAAA,uBAAA,EAAgB,CAAA;AAAA,oBAEhFC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sDAAA,EACZ,QAAA,EAAA;AAAA,MAAA,QAAA,CAAS,IAAI,CAAC,EAAE,QAAQ,KAAA,EAAO,UAAA,IAAc,KAAA,KAAU;AACtD,QAAA,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,GAAG,CAAA;AAC3B,QAAA,MAAM,UAAA,GAAa,QAAA,KAAa,YAAA,IAAgB,iBAAA,IAAqB,kBAAkB,YAAA,IAAgB,cAAA,CAAA;AACvG,QAAA,MAAM,MAAA,GAAA,CAAU,YAAY,EAAC,EAAG,OAAO,CAAC,CAAA,KAAM,CAAA,CAAE,YAAA,KAAiB,KAAK,CAAA;AACtE,QAAA,uBACEA,KAAC,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,UAAA,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,qBACXD,GAAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cAEC,IAAI,CAAA,CAAE,EAAA;AAAA,cACN,WAAW,EAAA,CAAG,6CAAA,EAA+C,EAAE,KAAA,IAAS,CAAA,GAAI,mBAAmB,SAAS,CAAA;AAAA,cAEvG,QAAA,EAAA,CAAA,CAAE;AAAA,aAAA;AAAA,YAJE,CAAA,CAAE;AAAA,WAMV,CAAA;AAAA,0BACDA,GAAAA;AAAA,YAAC,WAAA;AAAA,YAAA;AAAA,cAED,EAAA,EAAI,CAAA,OAAA,EAAU,MAAA,CAAO,GAAG,CAAA,CAAA;AAAA,cACxB,KAAA,EAAO,OAAO,KAAA,IAAS,EAAA;AAAA,cACvB,QAAA,EAAU,OAAO,QAAA,IAAY,EAAA;AAAA,cAC7B,KAAA;AAAA,cACA,IAAA,EAAM,UAAU,MAAM,CAAA;AAAA,cACtB,SAAA,EAAW,eAAA,GAAkB,MAAM,eAAA,CAAgB,MAAM,CAAA,GAAI,MAAA;AAAA,cAC7D,kBAAkB,gBAAA,GAAmB,MAAM,gBAAA,CAAiB,MAAA,EAAQ,KAAK,CAAA,GAAI,MAAA;AAAA,cAC7E,OAAA,EACE,UAAA,mBACEC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qCAAA,EAAsC,aAAA,EAAa,CAAA,eAAA,EAAkB,MAAA,CAAO,GAAG,CAAA,CAAA,EAC3F,QAAA,EAAA;AAAA,gBAAA,YAAA,oBAAgBD,GAAAA,CAAC,gBAAA,EAAA,EAAiB,KAAA,EAAO,MAAA,CAAO,KAAA,IAAS,EAAA,EAAI,OAAA,EAAS,MAAM,YAAA,CAAa,MAAM,CAAA,EAAG,CAAA;AAAA,gBAClG,YAAA,oBACCC,IAAAA,CAAAG,UAAAA,EAAA,EACE,QAAA,EAAA;AAAA,kCAAAJ,GAAAA;AAAA,oBAAC,gBAAA;AAAA,oBAAA;AAAA,sBACC,KAAA,EAAO,CAAA,KAAA,EAAQ,MAAA,CAAO,KAAA,IAAS,QAAQ,CAAA,GAAA,CAAA;AAAA,sBACvC,UAAU,KAAA,KAAU,CAAA;AAAA,sBACpB,OAAA,EAAS,MAAM,YAAA,CAAa,MAAA,EAAQ,EAAE,CAAA;AAAA,sBAEtC,QAAA,kBAAAA,GAAAA,CAAC,SAAA,EAAA,EAAU,SAAA,EAAU,aAAA,EAAc;AAAA;AAAA,mBACrC;AAAA,kCACAA,GAAAA;AAAA,oBAAC,gBAAA;AAAA,oBAAA;AAAA,sBACC,KAAA,EAAO,CAAA,KAAA,EAAQ,MAAA,CAAO,KAAA,IAAS,QAAQ,CAAA,KAAA,CAAA;AAAA,sBACvC,QAAA,EAAU,KAAA,KAAU,QAAA,CAAS,MAAA,GAAS,CAAA;AAAA,sBACtC,OAAA,EAAS,MAAM,YAAA,CAAa,MAAA,EAAQ,CAAC,CAAA;AAAA,sBAErC,QAAA,kBAAAA,GAAAA,CAAC,WAAA,EAAA,EAAY,SAAA,EAAU,aAAA,EAAc;AAAA;AAAA;AACvC,iBAAA,EACF,CAAA;AAAA,gBAED,cAAA,oBACCA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qDACZ,QAAA,EAAA,YAAA,CAAa,GAAA,CAAI,CAAC,MAAA,qBACjBA,GAAAA;AAAA,kBAAC,QAAA;AAAA,kBAAA;AAAA,oBAEC,IAAA,EAAK,QAAA;AAAA,oBACL,eAAa,CAAA,EAAG,MAAA,CAAO,MAAM,CAAA,CAAA,EAAI,OAAO,GAAG,CAAA,CAAA;AAAA,oBAC3C,OAAO,MAAA,CAAO,KAAA;AAAA,oBACd,cAAY,CAAA,EAAG,MAAA,CAAO,KAAK,CAAA,KAAA,EAAQ,MAAA,CAAO,SAAS,QAAQ,CAAA,CAAA;AAAA,oBAC3D,cAAA,EAAc,YAAA,CAAa,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAA;AAAA,oBAC9C,QAAA,EAAU,YAAA,CAAa,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAA;AAAA,oBAC1C,OAAA,EAAS,MAAM,cAAA,CAAe,MAAA,EAAQ,OAAO,IAAI,CAAA;AAAA,oBACjD,SAAA,EAAU,wMAAA;AAAA,oBAET,QAAA,EAAA,MAAA,CAAO,IAAA,CAAK,QAAA,mBAAWA,GAAAA,CAAC,gBAAa,SAAA,EAAU,SAAA,EAAU,CAAA,GAAK,MAAA,CAAO,IAAA,CAAK;AAAA,mBAAA;AAAA,kBAVtE,MAAA,CAAO;AAAA,iBAYf,CAAA,EACH,CAAA;AAAA,gBAED,qCACCA,GAAAA;AAAA,kBAAC,gBAAA;AAAA,kBAAA;AAAA,oBACC,KAAA,EAAO,CAAA,UAAA,EAAa,MAAA,CAAO,KAAA,IAAS,QAAQ,CAAA,CAAA;AAAA,oBAC5C,OAAA,EAAS,MAAM,iBAAA,CAAkB,MAAM,CAAA;AAAA,oBAEvC,QAAA,kBAAAA,GAAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,aAAA,EAAc;AAAA;AAAA,iBAChC;AAAA,gBAED,kCACCA,GAAAA;AAAA,kBAAC,gBAAA;AAAA,kBAAA;AAAA,oBACC,KAAA,EAAO,CAAA,OAAA,EAAU,MAAA,CAAO,KAAA,IAAS,QAAQ,CAAA,CAAA;AAAA,oBACzC,OAAA,EAAS,MAAM,cAAA,CAAe,MAAM,CAAA;AAAA,oBAEpC,QAAA,kBAAAA,GAAAA,CAAC,MAAA,EAAA,EAAO,SAAA,EAAU,aAAA,EAAc;AAAA;AAAA;AAClC,eAAA,EAEJ,CAAA,GACE,MAAA;AAAA,cAGL,QAAA,EAAA,GAAA,EAAK,wBACJA,GAAAA,CAAC,sBAAmB,OAAA,EAAS,GAAA,CAAI,KAAA,EAAO,CAAA,mBAExCA,GAAAA;AAAA,gBAAC,WAAA;AAAA,gBAAA;AAAA,kBACC,MAAM,MAAA,CAAO,IAAA;AAAA,kBACb,QAAQ,GAAA,EAAK,MAAA;AAAA,kBACb,OAAO,MAAA,CAAO,KAAA;AAAA,kBACd,IAAA,EAAM,aAAA;AAAA,kBACN;AAAA;AAAA;AACF,aAAA;AAAA,YA9EG,MAAA,CAAO;AAAA;AAgFd,SAAA,EAAA,EA3Fe,OAAO,GA4FtB,CAAA;AAAA,MAEJ,CAAC,CAAA;AAAA,MAAA,CACC,QAAA,IAAY,EAAC,EAAG,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,YAAA,IAAgB,QAAA,CAAS,MAAM,CAAA,CAAE,GAAA,CAAI,CAAC,sBACtEA,GAAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UAEC,IAAI,CAAA,CAAE,EAAA;AAAA,UACN,WAAW,EAAA,CAAG,6CAAA,EAA+C,EAAE,KAAA,IAAS,CAAA,GAAI,mBAAmB,SAAS,CAAA;AAAA,UAEvG,QAAA,EAAA,CAAA,CAAE;AAAA,SAAA;AAAA,QAJE,CAAA,CAAE;AAAA,OAMV;AAAA,KAAA,EACH;AAAA,GAAA,EACF,CAAA;AAEJ;ACxaO,SAAS,cAAc,EAAE,KAAA,EAAO,SAAA,EAAW,aAAA,EAAe,WAAU,EAAuB;AAChG,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAIE,SAAiB,EAAE,CAAA;AAC7D,EAAA,MAAM,eAAe,SAAA,IAAa,aAAA;AAElC,EAAA,MAAM,YAAA,GAAe,CAAC,CAAA,KAAc;AAClC,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,aAAA,CAAc,CAAC,CAAA;AAAA,IACjB,CAAA,MAAO;AACL,MAAA,gBAAA,CAAiB,CAAC,CAAA;AAAA,IACpB;AAAA,EACF,CAAA;AAEA,EAAA,uBACEF,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,8EAA8E,SAAS,CAAA,EACvG,QAAA,EAAA,CAAC,CAAA,EAAG,GAAG,EAAE,CAAA,CAAE,GAAA,CAAI,CAAC,sBACfC,IAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MAEC,IAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAS,MAAM,YAAA,CAAa,CAAC,CAAA;AAAA,MAC7B,SAAA,EAAW,EAAA;AAAA,QACT,kDAAA;AAAA,QACA,YAAA,KAAiB,IACb,gDAAA,GACA;AAAA,OACN;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,CAAA;AAAA,QAAE;AAAA;AAAA,KAAA;AAAA,IAVE;AAAA,GAYR,CAAA,EACH,CAAA;AAEJ;ACpCA,IAAM,GAAA,GAAM,KAAA;AACZ,IAAM,OAAO,CAAA,GAAI,GAAA;AAYV,SAAS,oBACd,OAAA,EACA,KAAA,EACA,UACA,UAAA,GAAa,CAAA,EACb,eACA,mBAAA,EACuB;AACvB,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIC,QAAAA,CAAsC,EAAE,CAAA;AACtE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,SAAS,IAAI,CAAA;AAE3C,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,IAAA,eAAe,IAAA,GAAO;AACpB,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,IAAI,CAAC,SAAA,EAAW,UAAA,CAAW,KAAK,CAAA;AAChC,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,MAAA,MAAM,UAAA,GAAa,MAAM,KAAA,GAAQ,IAAA;AAIjC,MAAA,MAAM,IAAA,GAAO,2BAA2B,QAAA,EAAU;AAAA,QAChD,UAAA;AAAA,QACA,QAAA,EAAU,GAAA;AAAA,QACV,aAAA;AAAA,QACA,YAAA,EAAc;AAAA,OACf,CAAA;AACD,MAAA,MAAM,MAAA,GAAS,IAAIE,yBAAAA,CAA0B,IAAI,CAAA;AACjD,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAA;AAAA,UAC5B,OAAA,CAAQ,GAAA,CAAI,OAAO,CAAA,KAAM;AACvB,YAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,GAAA,CAAI,EAAE,KAAK,CAAA;AACpC,YAAA,MAAM,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA;AACzB,YAAA,MAAM,KAAA,GAAQ,GAAA,EAAK,KAAA,IAAS,GAAA,CAAI,YAAY,CAAC,CAAA;AAG7C,YAAA,MAAM,SAAS,aAAA,CAAc;AAAA,cAC3B,MAAA,EAAQC,UAAAA,CAAW,CAAA,CAAE,KAAK,CAAA;AAAA,cAC1B,QAAQ,GAAA,EAAK,MAAA;AAAA,cACb,MAAM,GAAA,EAAK,IAAA;AAAA,cACX,KAAA;AAAA,cACA,OAAO,GAAA,EAAK;AAAA,aACb,CAAA;AACD,YAAA,IAAI,GAAA,EAAK,KAAA,EAAO,MAAA,CAAO,KAAA,GAAQ,GAAA,CAAI,KAAA;AACnC,YAAA,IAAI,GAAA,EAAK,MAAA,EAAQ,MAAA,CAAO,MAAA,GAAS,GAAA,CAAI,MAAA;AACrC,YAAA,IAAI,GAAA,EAAK,OAAA,EAAS,MAAA,CAAO,OAAA,GAAU,GAAA,CAAI,OAAA;AACvC,YAAA,IAAI,GAAA,EAAK,IAAA,EAAM,MAAA,CAAO,IAAA,GAAO,GAAA,CAAI,IAAA;AACjC,YAAA,OAAO,CAAC,CAAA,CAAE,GAAA,EAAK,MAAM,CAAA;AAAA,UACvB,CAAC;AAAA,SACH;AACA,QAAA,IAAI,CAAC,SAAA,EAAW,UAAA,CAAW,MAAA,CAAO,WAAA,CAAY,OAAO,CAAC,CAAA;AAAA,MACxD,CAAA,SAAE;AACA,QAAA,IAAI,CAAC,SAAA,EAAW,UAAA,CAAW,KAAK,CAAA;AAAA,MAClC;AAAA,IACF;AAEA,IAAA,KAAK,IAAA,EAAK;AAEV,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,OAAA,EAAS,KAAA,EAAO,UAAU,UAAA,EAAY,aAAA,EAAe,mBAAmB,CAAC,CAAA;AAE7E,EAAA,OAAO,EAAE,SAAS,OAAA,EAAQ;AAC5B;ACjFO,IAAM,0BAAA,GAA6B;AACnC,IAAM,sBAAA,GAAyB;AAGtC,IAAM,WAAA,GAAwC,CAAC,IAAA,EAAM,IAAI,CAAA;AAEzD,IAAM,WAAA,uBAAkB,GAAA,EAAoB;AAC5C,IAAM,eAAA,GAA+B;AAAA,EACnC,SAAS,CAAC,GAAA,KAAgB,WAAA,CAAY,GAAA,CAAI,GAAG,CAAA,IAAK,IAAA;AAAA,EAClD,OAAA,EAAS,CAAC,GAAA,EAAa,KAAA,KAAkB;AACvC,IAAA,WAAA,CAAY,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,EAC5B,CAAA;AAAA,EACA,UAAA,EAAY,CAAC,GAAA,KAAgB;AAC3B,IAAA,WAAA,CAAY,OAAO,GAAG,CAAA;AAAA,EACxB;AACF,CAAA;AAEA,IAAM,aAAA,uBAAoB,GAAA,EAAgB;AAC1C,SAAS,gBAAA,GAAmB;AAC1B,EAAA,KAAA,MAAW,CAAA,IAAK,eAAe,CAAA,EAAE;AACnC;AAEA,SAAS,eAAe,MAAA,EAAmC;AACzD,EAAA,OAAO,MAAA,IAAU,eAAA;AACnB;AAEO,SAAS,eAAe,OAAA,EAAsC;AACnE,EAAA,MAAM,KAAA,GAAQ,eAAe,OAAO,CAAA;AACpC,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,CAAQ,0BAA0B,CAAA;AACvD,EAAA,OAAQ,WAAA,CAAkC,QAAA,CAAS,MAAA,IAAU,EAAE,IAC1D,MAAA,GACD,sBAAA;AACN;AAEO,SAAS,2BAA2B,aAAA,EAA6B;AACtE,EAAA,MAAM,OAAA,GAAU,eAAe,aAAa,CAAA;AAC5C,EAAA,MAAM,CAAC,MAAM,YAAY,CAAA,GAAIJ,SAAwB,MAAM,cAAA,CAAe,OAAO,CAAC,CAAA;AAElF,EAAAC,UAAU,MAAM;AACd,IAAA,YAAA,CAAa,cAAA,CAAe,OAAO,CAAC,CAAA;AACpC,IAAA,MAAM,IAAA,GAAO,MAAM,YAAA,CAAa,cAAA,CAAe,OAAO,CAAC,CAAA;AACvD,IAAA,aAAA,CAAc,IAAI,IAAI,CAAA;AACtB,IAAA,OAAO,MAAM;AACX,MAAA,aAAA,CAAc,OAAO,IAAI,CAAA;AAAA,IAC3B,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,MAAM,OAAA,GAAU,WAAA;AAAA,IACd,CAAC,IAAA,KAAwB;AACvB,MAAA,OAAA,CAAQ,OAAA,CAAQ,4BAA4B,IAAI,CAAA;AAChD,MAAA,YAAA,CAAa,IAAI,CAAA;AACjB,MAAA,gBAAA,EAAiB;AAAA,IACnB,CAAA;AAAA,IACA,CAAC,OAAO;AAAA,GACV;AAEA,EAAA,MAAM,UAAA,GAAa,YAAY,MAAM;AACnC,IAAA,MAAM,IAAA,GAAsB,IAAA,KAAS,IAAA,GAAO,IAAA,GAAO,IAAA;AACnD,IAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,EACd,CAAA,EAAG,CAAC,IAAA,EAAM,OAAO,CAAC,CAAA;AAElB,EAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,UAAA,EAAW;AACrC;AAEO,SAAS,yBAAA,CACd,OACA,aAAA,EAC0C;AAC1C,EAAA,MAAM,MAAA,GAASG,WAAW,KAAK,CAAA;AAC/B,EAAA,MAAM,WAAA,GAAc,aAAA,IAAiB,MAAA,GAAS,MAAA,CAAO,WAAA,GAAc,MAAA;AACnE,EAAA,IAAI,WAAA,KAAgB,IAAA,IAAQ,WAAA,KAAgB,IAAA,EAAM;AAChD,IAAA,OAAO,EAAE,IAAA,EAAM,WAAA,EAA8B,MAAA,EAAQ,IAAA,EAAK;AAAA,EAC5D;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,aAAA,EAAe,MAAA,EAAQ,KAAA,EAAM;AAC9C;AAEO,SAAS,yBAAA,CACd,SACA,aAAA,EAC0C;AAC1C,EAAA,MAAM,KAAA,GAAQ,OAAA,CACX,GAAA,CAAI,CAAC,CAAA,KAAM;AACV,IAAA,MAAM,MAAA,GAASA,UAAAA,CAAW,CAAA,CAAE,KAAK,CAAA;AACjC,IAAA,OAAO,aAAA,IAAiB,MAAA,GAAS,MAAA,CAAO,WAAA,GAAc,MAAA;AAAA,EACxD,CAAC,EACA,MAAA,CAAO,CAAC,MAAmB,CAAA,KAAM,IAAA,IAAQ,MAAM,IAAI,CAAA;AAEtD,EAAA,MAAM,SAAS,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAI,KAAK,CAAC,CAAA;AACxC,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,CAAO,CAAC,CAAA,EAAoB,QAAQ,IAAA,EAAK;AAAA,EAC1D;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,aAAA,EAAe,MAAA,EAAQ,KAAA,EAAM;AAC9C;AAQO,SAAS,uBAAA,CAAwB,EAAE,SAAA,EAAW,IAAA,EAAM,UAAU,MAAA,GAAS,KAAA,EAAO,SAAQ,EAAiC;AAC5H,EAAA,MAAM,EAAE,IAAA,EAAM,UAAA,EAAY,OAAA,EAAQ,GAAI,2BAA2B,OAAO,CAAA;AACxE,EAAA,MAAM,aAAa,QAAA,IAAY,UAAA;AAE/B,EAAA,uBACEL,IAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAY,2BAAA;AAAA,MACZ,SAAA,EAAW,EAAA,CAAG,wCAAA,EAA0C,SAAS,CAAA;AAAA,MAEjE,QAAA,EAAA;AAAA,wBAAAA,IAAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,EAAA;AAAA,cACT,sEAAA;AAAA,cACA,MAAA,IAAU;AAAA,aACZ;AAAA,YACA,KAAA,EAAO,SAAS,6CAAA,GAAgD,yBAAA;AAAA,YAEhE,QAAA,EAAA;AAAA,8BAAAD,GAAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,IAAA,EAAK,QAAA;AAAA,kBACL,QAAA,EAAU,MAAA;AAAA,kBACV,OAAA,EAAS,MAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,kBAC3B,SAAA,EAAW,EAAA;AAAA,oBACT,4DAAA;AAAA,oBACA,UAAA,KAAe,OACX,gDAAA,GACA,4DAAA;AAAA,oBACJ,MAAA,IAAU;AAAA,mBACZ;AAAA,kBACD,QAAA,EAAA;AAAA;AAAA,eAED;AAAA,8BACAA,GAAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,IAAA,EAAK,QAAA;AAAA,kBACL,QAAA,EAAU,MAAA;AAAA,kBACV,OAAA,EAAS,MAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,kBAC3B,SAAA,EAAW,EAAA;AAAA,oBACT,4DAAA;AAAA,oBACA,UAAA,KAAe,OACX,gDAAA,GACA,4DAAA;AAAA,oBACJ,MAAA,IAAU;AAAA,mBACZ;AAAA,kBACD,QAAA,EAAA;AAAA;AAAA;AAED;AAAA;AAAA,SACF;AAAA,QACC,0BACCA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,4CAA2C,QAAA,EAAA,gBAAA,EAAc;AAAA;AAAA;AAAA,GAE7E;AAEJ;;;ACxJO,IAAM,OAAA,GAAU;AAChB,IAAM,OAAA,GAAU;AAChB,IAAM,UAAA,GAAa;AACnB,IAAM,MAAA,GAAS;AAAA,EACpB,OAAA,EAAS,WAAA;AAAA,EACT,MAAA,EAAQ,SAAA;AAAA,EACR,SAAA,EAAW;AACb","file":"index.mjs","sourcesContent":["export const CODEMIRROR_SINGLETON_DEPS = [\n '@codemirror/autocomplete',\n '@codemirror/commands',\n '@codemirror/lang-markdown',\n '@codemirror/language',\n '@codemirror/lint',\n '@codemirror/search',\n '@codemirror/state',\n '@codemirror/theme-one-dark',\n '@codemirror/view',\n '@lezer/common',\n '@lezer/highlight',\n '@lezer/lr',\n '@lezer/markdown',\n] as const;\n","import type { ReactNode } from 'react';\nimport { Edit3, ExternalLink, Eye } from 'lucide-react';\nimport { cn } from '../utils/cn';\n\nexport interface WidgetFrameProps {\n /** DOM anchor for the frame (e.g. `widget-<key>`) — L3 indexes scroll here. */\n id?: string;\n title: string;\n question: string;\n /** Raw WQL for the widget. Hidden by default — only rendered with showQuery. */\n query?: string;\n span?: string;\n /** Show the raw WQL query box (teaching/authoring surfaces). View-first default hides it. */\n showQuery?: boolean;\n /**\n * Read-only inspection affordance — an always-visible button (prebuilt\n * seeds, teaching surfaces) opening the host's query inspector. Distinct\n * from editing: present without a toolbar.\n */\n onInspect?: () => void;\n /** Always-visible affordance: open this widget's resolved query in the\n * WQL explorer (host navigates). */\n onOpenInExplorer?: () => void;\n /**\n * Edit-mode action cluster (edit / duplicate / remove / reorder / size),\n * rendered top-right and always visible while present. The host builds it;\n * the frame only positions it.\n */\n toolbar?: ReactNode;\n children: ReactNode;\n}\n\nexport function WidgetFrame({ id, title, question, query, span, showQuery = false, onInspect, onOpenInExplorer, toolbar, children }: WidgetFrameProps) {\n return (\n <div\n id={id}\n className={cn(\n 'relative group/frame bg-card border border-border rounded-lg p-4 flex flex-col min-h-0',\n span,\n )}\n >\n <div className=\"flex items-start justify-between gap-3 mb-2\">\n <div className=\"min-w-0\">\n <h3 className=\"text-sm font-semibold text-foreground\">{title}</h3>\n {question && <p className=\"mt-1 text-xs text-muted-foreground\">{question}</p>}\n </div>\n {(onInspect || onOpenInExplorer) && (\n <div className=\"flex shrink-0 items-center gap-1\">\n {onInspect && (\n <button\n type=\"button\"\n onClick={onInspect}\n title=\"Inspect widget query\"\n aria-label={`Inspect query for ${title || 'widget'}`}\n className=\"inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground transition-colors\"\n >\n <Eye className=\"w-3.5 h-3.5\" />\n </button>\n )}\n {onOpenInExplorer && (\n <button\n type=\"button\"\n onClick={onOpenInExplorer}\n title=\"Open in explorer\"\n aria-label={`Open ${title || 'widget'} in explorer`}\n className=\"inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground transition-colors\"\n >\n <ExternalLink className=\"w-3.5 h-3.5\" />\n </button>\n )}\n </div>\n )}\n </div>\n {toolbar && <div className=\"mb-3\">{toolbar}</div>}\n {/* Long WQL wraps in place - an in-card horizontal scrollbar reads as\n a layout bug (dogfood #4). `break-all` covers spaceless fragments\n like `sum:totalVolume{effort:bench-press}`. */}\n {showQuery && query != null && query !== '' && (\n <div className=\"font-mono text-[11px] text-primary/90 bg-background/60 rounded px-2 py-1 mb-3 whitespace-pre-wrap break-all\">\n {query}\n </div>\n )}\n <div className=\"flex-1 min-h-0\">{children}</div>\n </div>\n );\n}\n\n/** Standard edit-mode tool-button chrome for the widget toolbar. */\nexport function WidgetToolButton({\n label,\n onClick,\n disabled,\n active,\n children,\n}: {\n label: string;\n onClick: () => void;\n disabled?: boolean;\n active?: boolean;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={label}\n aria-label={label}\n disabled={disabled}\n className={cn(\n 'inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground disabled:opacity-40 disabled:hover:text-muted-foreground transition-colors',\n active && 'text-primary bg-primary/10',\n )}\n >\n {children}\n </button>\n );\n}\n\n/** The primary \"open the full editor\" affordance inside the toolbar. */\nexport function WidgetEditButton({ title, onClick }: { title: string; onClick: () => void }) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title=\"Edit widget\"\n aria-label={`Edit widget ${title || ''}`.trim()}\n className=\"inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground transition-colors\"\n >\n <Edit3 className=\"w-3.5 h-3.5\" />\n </button>\n );\n}\n","import { useEffect, useState } from 'react';\nimport type { DashboardToken } from '@bitcobblers/wod-wiki-wql';\nimport { cn } from '../utils/cn';\n\nexport interface DashboardTokenControlsProps {\n tokens: DashboardToken[];\n /** Current value per token name (defaults applied by the caller). */\n values: Record<string, string>;\n /**\n * Present when the note is editable — a change commits exactly once, on an\n * explicit action: a list-token segment click, or a scalar-token blur /\n * Enter. Keystrokes only edit the local draft — they never rewrite the\n * note or re-run widgets mid-edit.\n */\n onChange?: (name: string, value: string) => void;\n}\n\n/**\n * Scalar token input — owns a local draft so typing stays in-process; the\n * committed value (blur or Enter) is the only write. External value changes\n * (e.g. a written note re-resolved) re-sync the draft.\n */\nfunction ScalarTokenInput({\n name,\n value,\n disabled,\n onCommit,\n}: {\n name: string;\n value: string;\n disabled?: boolean;\n onCommit: (value: string) => void;\n}) {\n const [draft, setDraft] = useState(value);\n useEffect(() => setDraft(value), [value]);\n\n const commit = () => {\n if (draft !== value) onCommit(draft);\n };\n\n return (\n <input\n type=\"text\"\n value={draft}\n disabled={disabled}\n onChange={(e) => setDraft(e.target.value)}\n onBlur={commit}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n commit();\n e.currentTarget.blur();\n }\n }}\n aria-label={`Token ${name}`}\n className=\"w-20 rounded-lg border border-border bg-card px-2 py-1 text-xs font-mono text-foreground focus:outline-none focus:border-primary disabled:opacity-60\"\n />\n );\n}\n\n/**\n * DashboardTokenControls — the control row a dashboard note's frontmatter\n * tokens render as (#899): scalar tokens become inputs, list tokens segmented\n * controls (first entry = default). Read-only views (no onChange) render the\n * current values as static text.\n */\nexport function DashboardTokenControls({ tokens, values, onChange }: DashboardTokenControlsProps) {\n if (tokens.length === 0) return null;\n const readOnly = !onChange;\n\n return (\n <div\n data-testid=\"dashboard-token-controls\"\n className=\"flex flex-wrap items-center gap-x-5 gap-y-2 mb-4\"\n >\n {tokens.map((token) => {\n const current = values[token.name] ?? token.values[0];\n return (\n <div key={token.name} className=\"flex items-center gap-2\">\n <span className=\"font-mono text-[11px] text-muted-foreground\">${token.name}</span>\n {token.isList ? (\n <div className=\"inline-flex items-center gap-1 rounded-lg border border-border bg-card p-1\">\n {token.values.map((option) => (\n <button\n key={option}\n type=\"button\"\n disabled={readOnly}\n onClick={() => {\n // A segment click IS the explicit commit — no draft.\n if (option !== current) onChange?.(token.name, option);\n }}\n className={cn(\n 'text-xs px-2.5 py-1 rounded-md transition-colors',\n option === current\n ? 'bg-primary text-primary-foreground font-medium'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted',\n readOnly && 'cursor-default',\n )}\n >\n {option}\n </button>\n ))}\n </div>\n ) : readOnly ? (\n <span className=\"text-xs text-foreground font-mono\">{current}</span>\n ) : (\n <ScalarTokenInput\n name={token.name}\n value={current}\n onCommit={(next) => onChange?.(token.name, next)}\n />\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","import { Fragment, useEffect, useMemo, useState } from 'react';\nimport { ChevronDown, ChevronRight, ChevronUp, Copy, Trash2 } from 'lucide-react';\nimport { isFindQuery, isPipelineQuery, parseQuery, type QueryResult, type AnyParsedQuery, defaultTokenValues, isDashboardWidgetType, resolveWidgetType, substituteTokens, unknownTokensMessage, unknownWidgetTypeMessage, type DashboardDocument, type DashboardWidget, SharedQueryDocumentRunner, type QueryDocumentRunnerHost, type DocumentOutput } from '@bitcobblers/wod-wiki-wql';\nimport type { QueryExecutor } from '../contracts/query';\nimport { WidgetFrame, WidgetToolButton, WidgetEditButton } from './WidgetFrame';\nimport { WidgetChart, WidgetProblemBadge } from './WidgetChart';\nimport { toChartResult } from './chartData';\nimport { DashboardTokenControls } from './DashboardTokenControls';\nimport { cn } from '../utils/cn';\n\n/** A widget's grid placement — column span 1..4, or a forced full row. */\nexport interface WidgetSpanOption {\n spanCols?: number;\n spanFull?: boolean;\n}\n\n/** A note heading rendered as a full-width grid row between widgets, with its\n * own DOM anchor (L3 scroll target). Order within `headings` is preserved. */\nexport interface DashboardHeadingAnchor {\n id: string;\n /** Markdown heading level (2+; level 1 renders as the page title surface). */\n level: number;\n text: string;\n /** Insert before this widget index; `widgets.length` = after the last. */\n beforeWidget: number;\n}\n\nexport interface DashboardViewProps {\n /** Parsed dashboard note (buildDashboardDocument). */\n document: DashboardDocument;\n /** Note headings to render between the widgets (document order). */\n headings?: DashboardHeadingAnchor[];\n /** Injected QueryExecutor for executing WQL queries. Zero singleton coupling. */\n executor?: QueryExecutor;\n /** Optional rollup fact warmer callback. */\n onEnsureRollupFacts?: () => Promise<void>;\n /** Current token values; defaults to each token's declared default. */\n tokenValues?: Record<string, string>;\n /** Present when the note is editable — committed control changes write back to frontmatter. */\n onTokenChange?: (name: string, value: string) => void;\n /**\n * Edit mode: per-widget arrangement chrome (edit / duplicate / remove /\n * reorder / size) renders on every card. View mode stays chrome-free —\n * the host gates editing on this flag plus the handler set below.\n */\n editMode?: boolean;\n /** Open the shared authoring composer for this widget (edit flow). */\n onEditWidget?: (widget: DashboardWidget) => void;\n /** Read-only query inspection (prebuilt seeds, teaching surfaces). */\n onInspectWidget?: (widget: DashboardWidget) => void;\n /** Open the widget's token-resolved query in the WQL explorer (host navigates). */\n onOpenInExplorer?: (widget: DashboardWidget, query: string) => void;\n onDuplicateWidget?: (widget: DashboardWidget) => void;\n onRemoveWidget?: (widget: DashboardWidget) => void;\n onMoveWidget?: (widget: DashboardWidget, delta: -1 | 1) => void;\n onResizeWidget?: (widget: DashboardWidget, span: WidgetSpanOption) => void;\n /** Optional execution range (ms epoch). Omit to use each query's own window. */\n rangeStart?: number;\n rangeEnd?: number;\n preferredUnit?: string;\n}\n\n/** Chart-input result plus the content-plane payloads list widgets read. */\ntype WidgetRunResult = QueryResult & {\n notes?: unknown[];\n blocks?: unknown[];\n efforts?: unknown[];\n runs?: unknown[];\n containers?: Record<string, { kind: 'page'; id: string; slug?: string; date?: string } | { kind: 'note'; id: string }>;\n};\n\ninterface WidgetRun {\n result?: WidgetRunResult;\n error?: string;\n}\n\n/**\n * Executor→runner host adapter (ticket 19 cutover): the shared document\n * runner drives family dispatch; the injected QueryExecutor stays the only\n * execution seam. Range/unit ride every aggregate call; missing pipeline\n * capability surfaces as an output diagnostic — never a silent empty result.\n */\nexport function createExecutorDocumentHost(\n executor: QueryExecutor,\n range: { rangeStart?: number; rangeEnd?: number; preferredUnit?: string; rollupEnsure?: () => Promise<void> } = {},\n): QueryDocumentRunnerHost {\n return {\n runAggregate: (queryText, overrides) =>\n executor.runQuery(queryText, {\n context: overrides.context,\n rangeStart: range.rangeStart,\n rangeEnd: range.rangeEnd,\n preferredUnit: range.preferredUnit,\n }),\n runFind: async (queryText, context) => {\n const parsed = parseQuery(queryText);\n if (!isFindQuery(parsed)) return { kind: 'find', error: `not a content query: ${queryText}` };\n const res = await executor.runFind(parsed, {\n context,\n range: range.rangeStart !== undefined\n ? { start: range.rangeStart, end: range.rangeEnd ?? Number.MAX_SAFE_INTEGER, endExclusive: false }\n : undefined,\n });\n return {\n kind: 'find',\n notes: res.notes,\n blocks: res.blocks,\n efforts: res.efforts,\n containers: res.containers,\n runs: res.runs,\n table: res.table,\n };\n },\n runPipeline: async (queryText, context) => {\n const res = await executor.runPipeline?.(queryText, {\n context,\n rangeStart: range.rangeStart,\n rangeEnd: range.rangeEnd,\n preferredUnit: range.preferredUnit,\n });\n return res ?? { error: 'pipeline queries are not supported by this executor' };\n },\n rollupEnsure: range.rollupEnsure,\n };\n}\n\n/** Document output → widget chart input (content payloads ride along). */\nfunction outputToRunResult(parsed: AnyParsedQuery, out: DocumentOutput): WidgetRunResult {\n const base = toChartResult({ parsed, series: out.series, unit: out.unit, error: out.error, table: out.table });\n return Object.assign(base, {\n ...(out.notes ? { notes: out.notes } : {}),\n ...(out.blocks ? { blocks: out.blocks } : {}),\n ...(out.efforts ? { efforts: out.efforts } : {}),\n ...(out.containers ? { containers: out.containers } : {}),\n ...(out.runs ? { runs: out.runs } : {}),\n });\n}\n\n/**\n * Grid span classes for a widget on the 1 / 2 / 4-column responsive grid.\n * An explicit fence span (`-N` / `-full`) wins; otherwise the type default.\n */\nfunction spanClass(widget: DashboardWidget): string {\n if (widget.spanFull) return 'col-span-1 md:col-span-2 lg:col-span-4';\n if (widget.spanCols != null) {\n if (widget.spanCols <= 1) return 'col-span-1';\n if (widget.spanCols === 2) return 'col-span-1 md:col-span-2';\n if (widget.spanCols === 3) return 'col-span-1 md:col-span-2 lg:col-span-3';\n return 'col-span-1 md:col-span-2 lg:col-span-4';\n }\n const resolved = resolveWidgetType(widget.type);\n if (resolved === 'value') return 'col-span-1';\n if (resolved === 'table') return 'col-span-1 md:col-span-2';\n return 'col-span-1 md:col-span-2 lg:col-span-4';\n}\n\n/** Size options in the edit-mode toolbar — column span or a full row. */\nconst SIZE_OPTIONS: Array<{ label: string; span: WidgetSpanOption; testId: string }> = [\n { label: 'Span 1 column', span: { spanCols: 1 }, testId: 'widget-size-1' },\n { label: 'Span 2 columns', span: { spanCols: 2 }, testId: 'widget-size-2' },\n { label: 'Span 4 columns', span: { spanCols: 4 }, testId: 'widget-size-4' },\n { label: 'Full row', span: { spanFull: true }, testId: 'widget-size-full' },\n];\n\nfunction sizeIsActive(widget: DashboardWidget, span: WidgetSpanOption): boolean {\n if (span.spanFull) return widget.spanFull === true;\n return !widget.spanFull && (widget.spanCols ?? null) === (span.spanCols ?? null);\n}\n\n/**\n * DashboardView — the state-free dashboard renderer (#900, format locked in #899).\n *\n * Takes a parsed DashboardDocument + current token values, runs all widget\n * queries concurrently via the injected QueryExecutor, and renders the\n * responsive CSS grid. All authoring interactions are host-owned: the view\n * surfaces the affordances (edit-mode toolbar, inspect button) and reports\n * through the injected callbacks — it never owns dialog or write state.\n */\nexport function DashboardView({\n document,\n headings,\n executor,\n onEnsureRollupFacts,\n tokenValues,\n onTokenChange,\n editMode = false,\n onEditWidget,\n onInspectWidget,\n onOpenInExplorer,\n onDuplicateWidget,\n onRemoveWidget,\n onMoveWidget,\n onResizeWidget,\n rangeStart,\n rangeEnd,\n preferredUnit,\n}: DashboardViewProps) {\n const values = useMemo(\n () => ({ ...defaultTokenValues(document.tokens), ...tokenValues }),\n [document.tokens, tokenValues],\n );\n\n const resolved = useMemo(\n () =>\n document.widgets.map((widget) => {\n const { query, missing } = substituteTokens(widget.body, values);\n // Fence-tag attributes carry presentation params (`goal=$token`) —\n // they ride the same token values as the body, and a missing token\n // blocks the widget instead of rendering a NaN target.\n const attributes: Record<string, string> = {};\n const allMissing = new Set(missing);\n for (const [key, value] of Object.entries(widget.attributes)) {\n const sub = substituteTokens(value, values);\n attributes[key] = sub.query;\n for (const m of sub.missing) allMissing.add(m);\n }\n return { widget, query, missing: [...allMissing], attributes };\n }),\n [document.widgets, values],\n );\n\n const [runs, setRuns] = useState<Record<string, WidgetRun>>({});\n const [loading, setLoading] = useState(true);\n\n const resolvedKey = useMemo(\n () => resolved.map((r) => `${r.widget.key}:${r.query}`).join('|'),\n [resolved],\n );\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n\n async function load() {\n const next: Record<string, WidgetRun> = {};\n const runnable: Array<{ widget: DashboardWidget; query: string; parsed: AnyParsedQuery }> = [];\n\n for (const { widget, query, missing } of resolved) {\n if (widget.type !== '' && !isDashboardWidgetType(widget.type)) {\n next[widget.key] = { error: unknownWidgetTypeMessage(widget.type) };\n continue;\n }\n if (missing.length > 0) {\n next[widget.key] = { error: unknownTokensMessage(missing) };\n continue;\n }\n const parsed = parseQuery(query);\n if (parsed.error) {\n next[widget.key] = { error: parsed.error };\n continue;\n }\n const resolvedType = resolveWidgetType(widget.type);\n if (isFindQuery(parsed)) {\n if (resolvedType !== 'table' && resolvedType !== 'list') {\n next[widget.key] = { error: 'content queries return things — use a table or list widget instead' };\n continue;\n }\n } else if (!isPipelineQuery(parsed) && resolvedType === 'list') {\n next[widget.key] = { error: 'aggregate queries return numbers — use a chart or value widget instead' };\n continue;\n }\n runnable.push({ widget, query, parsed });\n }\n\n if (!executor) {\n if (!cancelled) {\n setRuns(next);\n setLoading(false);\n }\n return;\n }\n\n // One runner host per dashboard run; each widget document gets its own\n // captured execution context (ticket 12) — overlapping runs never\n // borrow each other's snapshot. Rollup-ensure is AST-driven inside the\n // runner (calc.* heads incl. pipeline stages), not string sniffing.\n const host = createExecutorDocumentHost(executor, {\n rangeStart,\n rangeEnd,\n preferredUnit,\n rollupEnsure: onEnsureRollupFacts,\n });\n\n await Promise.all(\n runnable.map(async ({ widget, query, parsed }) => {\n try {\n const runner = new SharedQueryDocumentRunner(host);\n const res = await runner.run(query);\n const out = res.outputs[0];\n if (!out) {\n next[widget.key] = { error: res.diagnostics[0] ?? 'widget produced no output' };\n return;\n }\n const error = out.error ?? res.diagnostics[0];\n next[widget.key] = {\n result: outputToRunResult(parsed, out),\n ...(error ? { error } : {}),\n };\n } catch (err) {\n next[widget.key] = { error: err instanceof Error ? err.message : String(err) };\n }\n }),\n );\n\n if (!cancelled) {\n setRuns(next);\n setLoading(false);\n }\n }\n\n void load();\n return () => {\n cancelled = true;\n };\n }, [resolvedKey, resolved, executor, onEnsureRollupFacts, rangeStart, rangeEnd, preferredUnit]);\n\n return (\n <div data-testid=\"dashboard-view\">\n <DashboardTokenControls tokens={document.tokens} values={values} onChange={onTokenChange} />\n\n {loading && <div className=\"text-sm text-muted-foreground mb-3\">Loading widgets…</div>}\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4\">\n {resolved.map(({ widget, query, attributes }, index) => {\n const run = runs[widget.key];\n const canArrange = editMode && (onEditWidget || onDuplicateWidget || onRemoveWidget || onMoveWidget || onResizeWidget);\n const before = (headings ?? []).filter((h) => h.beforeWidget === index);\n return (\n <Fragment key={widget.key}>\n {before.map((h) => (\n <div\n key={h.id}\n id={h.id}\n className={cn('col-span-full font-semibold text-foreground', h.level <= 2 ? 'text-base mt-2' : 'text-sm')}\n >\n {h.text}\n </div>\n ))}\n <WidgetFrame\n key={widget.key}\n id={`widget-${widget.key}`}\n title={widget.title ?? ''}\n question={widget.question ?? ''}\n query={query}\n span={spanClass(widget)}\n onInspect={onInspectWidget ? () => onInspectWidget(widget) : undefined}\n onOpenInExplorer={onOpenInExplorer ? () => onOpenInExplorer(widget, query) : undefined}\n toolbar={\n canArrange ? (\n <div className=\"flex flex-wrap items-center gap-1.5\" data-testid={`widget-toolbar-${widget.key}`}>\n {onEditWidget && <WidgetEditButton title={widget.title ?? ''} onClick={() => onEditWidget(widget)} />}\n {onMoveWidget && (\n <>\n <WidgetToolButton\n label={`Move ${widget.title || 'widget'} up`}\n disabled={index === 0}\n onClick={() => onMoveWidget(widget, -1)}\n >\n <ChevronUp className=\"w-3.5 h-3.5\" />\n </WidgetToolButton>\n <WidgetToolButton\n label={`Move ${widget.title || 'widget'} down`}\n disabled={index === resolved.length - 1}\n onClick={() => onMoveWidget(widget, 1)}\n >\n <ChevronDown className=\"w-3.5 h-3.5\" />\n </WidgetToolButton>\n </>\n )}\n {onResizeWidget && (\n <div className=\"flex items-center gap-0 rounded bg-muted/60 p-0.5\">\n {SIZE_OPTIONS.map((option) => (\n <button\n key={option.testId}\n type=\"button\"\n data-testid={`${option.testId}-${widget.key}`}\n title={option.label}\n aria-label={`${option.label} for ${widget.title || 'widget'}`}\n aria-pressed={sizeIsActive(widget, option.span)}\n disabled={sizeIsActive(widget, option.span)}\n onClick={() => onResizeWidget(widget, option.span)}\n className=\"inline-flex items-center justify-center px-1 py-0.5 max-lg:min-h-11 max-lg:min-w-11 text-xs font-mono rounded text-muted-foreground hover:text-foreground disabled:text-primary disabled:bg-primary/10\"\n >\n {option.span.spanFull ? <ChevronRight className=\"w-3 h-3\" /> : option.span.spanCols}\n </button>\n ))}\n </div>\n )}\n {onDuplicateWidget && (\n <WidgetToolButton\n label={`Duplicate ${widget.title || 'widget'}`}\n onClick={() => onDuplicateWidget(widget)}\n >\n <Copy className=\"w-3.5 h-3.5\" />\n </WidgetToolButton>\n )}\n {onRemoveWidget && (\n <WidgetToolButton\n label={`Remove ${widget.title || 'widget'}`}\n onClick={() => onRemoveWidget(widget)}\n >\n <Trash2 className=\"w-3.5 h-3.5\" />\n </WidgetToolButton>\n )}\n </div>\n ) : undefined\n }\n >\n {run?.error ? (\n <WidgetProblemBadge message={run.error} />\n ) : (\n <WidgetChart\n type={widget.type}\n result={run?.result}\n label={widget.title}\n unit={preferredUnit}\n attributes={attributes}\n />\n )}\n </WidgetFrame>\n </Fragment>\n );\n })}\n {(headings ?? []).filter((h) => h.beforeWidget >= resolved.length).map((h) => (\n <div\n key={h.id}\n id={h.id}\n className={cn('col-span-full font-semibold text-foreground', h.level <= 2 ? 'text-base mt-2' : 'text-sm')}\n >\n {h.text}\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { cn } from '../utils/cn';\n\nexport type AnalyticsRangeWeeks = 4 | 8 | 16;\n\nexport interface RangeSelectorProps {\n weeks?: number;\n onWeeksChange?: (weeks: number) => void;\n className?: string;\n}\n\nexport function RangeSelector({ weeks: weeksProp, onWeeksChange, className }: RangeSelectorProps) {\n const [internalWeeks, setInternalWeeks] = useState<number>(16);\n const currentWeeks = weeksProp ?? internalWeeks;\n\n const handleSelect = (w: number) => {\n if (onWeeksChange) {\n onWeeksChange(w);\n } else {\n setInternalWeeks(w);\n }\n };\n\n return (\n <div className={cn('inline-flex items-center gap-1 rounded-lg border border-border bg-card p-1', className)}>\n {[4, 8, 16].map((w) => (\n <button\n key={w}\n type=\"button\"\n onClick={() => handleSelect(w)}\n className={cn(\n 'text-xs px-2.5 py-1 rounded-md transition-colors',\n currentWeeks === w\n ? 'bg-primary text-primary-foreground font-medium'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted',\n )}\n >\n {w}w\n </button>\n ))}\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\nimport { parseQuery, SharedQueryDocumentRunner, type QueryResult } from '@bitcobblers/wod-wiki-wql';\nimport type { QueryExecutor } from '../contracts/query';\nimport { createExecutorDocumentHost } from './DashboardView';\nimport { toChartResult } from './chartData';\n\nconst DAY = 86_400_000;\nconst WEEK = 7 * DAY;\n\nexport interface AnalyticsQueryDef {\n key: string;\n query: string;\n}\n\nexport interface AnalyticsQueriesState {\n results: Record<string, QueryResult>;\n loading: boolean;\n}\n\nexport function useAnalyticsQueries(\n queries: AnalyticsQueryDef[],\n weeks: number,\n executor?: QueryExecutor,\n refreshKey = 0,\n preferredUnit?: string,\n onEnsureRollupFacts?: () => Promise<void>,\n): AnalyticsQueriesState {\n const [results, setResults] = useState<Record<string, QueryResult>>({});\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n\n async function load() {\n if (!executor) {\n if (!cancelled) setLoading(false);\n return;\n }\n\n const now = Date.now();\n const rangeStart = now - weeks * WEEK;\n // Ticket 19 cutover: widget queries evaluate through the shared\n // document runner — family dispatch (aggregate/find/rows/pipeline),\n // AST-driven rollup-ensure, and one captured context per query run.\n const host = createExecutorDocumentHost(executor, {\n rangeStart,\n rangeEnd: now,\n preferredUnit,\n rollupEnsure: onEnsureRollupFacts,\n });\n const runner = new SharedQueryDocumentRunner(host);\n try {\n const settled = await Promise.all(\n queries.map(async (q) => {\n const res = await runner.run(q.query);\n const out = res.outputs[0];\n const error = out?.error ?? res.diagnostics[0];\n // The chart input keeps the raw query's own parse so consumers\n // reading `parsed.family`/`raw` see the authored family.\n const result = toChartResult({\n parsed: parseQuery(q.query),\n series: out?.series,\n unit: out?.unit,\n error,\n table: out?.table,\n }) as QueryResult & { notes?: unknown[]; blocks?: unknown[]; efforts?: unknown[]; runs?: unknown[] };\n if (out?.notes) result.notes = out.notes;\n if (out?.blocks) result.blocks = out.blocks;\n if (out?.efforts) result.efforts = out.efforts;\n if (out?.runs) result.runs = out.runs;\n return [q.key, result] as const;\n }),\n );\n if (!cancelled) setResults(Object.fromEntries(settled));\n } finally {\n if (!cancelled) setLoading(false);\n }\n }\n\n void load();\n\n return () => {\n cancelled = true;\n };\n }, [queries, weeks, executor, refreshKey, preferredUnit, onEnsureRollupFacts]);\n\n return { results, loading };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { cn } from '../utils/cn';\nimport { parseQuery } from '@bitcobblers/wod-wiki-wql';\nimport type { AnalyticsQueryDef } from './useAnalyticsQueries';\nimport type { StorageLike } from '../contracts/storage';\n\nexport const ANALYTICS_UNIT_STORAGE_KEY = 'wod.analytics.unit';\nexport const DEFAULT_ANALYTICS_UNIT = 'kg';\nexport type AnalyticsUnit = 'kg' | 'lb';\n\nconst VALID_UNITS: readonly AnalyticsUnit[] = ['kg', 'lb'];\n\nconst memoryStore = new Map<string, string>();\nconst inMemoryStorage: StorageLike = {\n getItem: (key: string) => memoryStore.get(key) ?? null,\n setItem: (key: string, value: string) => {\n memoryStore.set(key, value);\n },\n removeItem: (key: string) => {\n memoryStore.delete(key);\n },\n};\n\nconst unitListeners = new Set<() => void>();\nfunction notifyUnitChange() {\n for (const l of unitListeners) l();\n}\n\nfunction resolveStorage(custom?: StorageLike): StorageLike {\n return custom ?? inMemoryStorage;\n}\n\nexport function readStoredUnit(storage?: StorageLike): AnalyticsUnit {\n const store = resolveStorage(storage);\n const stored = store.getItem(ANALYTICS_UNIT_STORAGE_KEY);\n return (VALID_UNITS as readonly string[]).includes(stored ?? '')\n ? (stored as AnalyticsUnit)\n : DEFAULT_ANALYTICS_UNIT;\n}\n\nexport function useAnalyticsUnitPreference(customStorage?: StorageLike) {\n const storage = resolveStorage(customStorage);\n const [unit, setUnitState] = useState<AnalyticsUnit>(() => readStoredUnit(storage));\n\n useEffect(() => {\n setUnitState(readStoredUnit(storage));\n const sync = () => setUnitState(readStoredUnit(storage));\n unitListeners.add(sync);\n return () => {\n unitListeners.delete(sync);\n };\n }, [storage]);\n\n const setUnit = useCallback(\n (next: AnalyticsUnit) => {\n storage.setItem(ANALYTICS_UNIT_STORAGE_KEY, next);\n setUnitState(next);\n notifyUnitChange();\n },\n [storage],\n );\n\n const toggleUnit = useCallback(() => {\n const next: AnalyticsUnit = unit === 'kg' ? 'lb' : 'kg';\n setUnit(next);\n }, [unit, setUnit]);\n\n return { unit, setUnit, toggleUnit };\n}\n\nexport function getEffectiveAnalyticsUnit(\n query: string,\n preferredUnit: AnalyticsUnit,\n): { unit: AnalyticsUnit; forced: boolean } {\n const parsed = parseQuery(query);\n const displayUnit = 'displayUnit' in parsed ? parsed.displayUnit : undefined;\n if (displayUnit === 'lb' || displayUnit === 'kg') {\n return { unit: displayUnit as AnalyticsUnit, forced: true };\n }\n return { unit: preferredUnit, forced: false };\n}\n\nexport function getDashboardEffectiveUnit(\n queries: AnalyticsQueryDef[],\n preferredUnit: AnalyticsUnit,\n): { unit: AnalyticsUnit; forced: boolean } {\n const units = queries\n .map((q) => {\n const parsed = parseQuery(q.query);\n return 'displayUnit' in parsed ? parsed.displayUnit : undefined;\n })\n .filter((u): u is string => u === 'kg' || u === 'lb');\n\n const unique = Array.from(new Set(units));\n if (unique.length === 1) {\n return { unit: unique[0] as AnalyticsUnit, forced: true };\n }\n return { unit: preferredUnit, forced: false };\n}\nexport interface AnalyticsUnitPreferenceProps {\n className?: string;\n unit?: AnalyticsUnit;\n forced?: boolean;\n storage?: StorageLike;\n}\n\nexport function AnalyticsUnitPreference({ className, unit: unitProp, forced = false, storage }: AnalyticsUnitPreferenceProps) {\n const { unit: storedUnit, setUnit } = useAnalyticsUnitPreference(storage);\n const activeUnit = unitProp ?? storedUnit;\n\n return (\n <div\n data-testid=\"analytics-unit-preference\"\n className={cn('inline-flex items-center gap-1 text-xs', className)}\n >\n <div\n className={cn(\n 'inline-flex items-center rounded-lg border border-border bg-card p-1',\n forced && 'opacity-70',\n )}\n title={forced ? 'Unit forced by query directive in this view' : 'Display unit preference'}\n >\n <button\n type=\"button\"\n disabled={forced}\n onClick={() => setUnit('kg')}\n className={cn(\n 'px-2.5 py-1 rounded-md transition-colors text-xs font-mono',\n activeUnit === 'kg'\n ? 'bg-primary text-primary-foreground font-medium'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted',\n forced && 'cursor-default hover:bg-transparent hover:text-muted-foreground',\n )}\n >\n kg\n </button>\n <button\n type=\"button\"\n disabled={forced}\n onClick={() => setUnit('lb')}\n className={cn(\n 'px-2.5 py-1 rounded-md transition-colors text-xs font-mono',\n activeUnit === 'lb'\n ? 'bg-primary text-primary-foreground font-medium'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted',\n forced && 'cursor-default hover:bg-transparent hover:text-muted-foreground',\n )}\n >\n lb\n </button>\n </div>\n {forced && (\n <span className=\"text-[11px] text-muted-foreground italic\">forced by note</span>\n )}\n </div>\n );\n}\n","/**\n * Auto-generated build version metadata.\n * Do not edit directly; updated by scripts/stamp-version.ts\n */\nexport const VERSION = '0.35.2119';\nexport const GIT_SHA = 'e0eb840';\nexport const BUILD_TIME = '2026-10-13T06:24:52.520Z';\nexport const SEMVER = {\n version: '0.35.2119',\n gitSha: 'e0eb840',\n buildTime: '2026-10-13T06:24:52.520Z',\n} as const;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/contracts/dedupe.ts","../src/widgets/WidgetFrame.tsx","../src/widgets/DashboardTokenControls.tsx","../src/widgets/DashboardView.tsx","../src/widgets/RangeSelector.tsx","../src/widgets/useAnalyticsQueries.ts","../src/widgets/useAnalyticsUnitPreference.tsx","../src/version.ts"],"names":["jsx","jsxs","useState","useEffect","Fragment","SharedQueryDocumentRunner","parseQuery"],"mappings":"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","file":"index.mjs","sourcesContent":["export const CODEMIRROR_SINGLETON_DEPS = [\n '@codemirror/autocomplete',\n '@codemirror/commands',\n '@codemirror/lang-markdown',\n '@codemirror/language',\n '@codemirror/lint',\n '@codemirror/search',\n '@codemirror/state',\n '@codemirror/theme-one-dark',\n '@codemirror/view',\n '@lezer/common',\n '@lezer/highlight',\n '@lezer/lr',\n '@lezer/markdown',\n] as const;\n","import type { ReactNode } from 'react';\nimport { Edit3, ExternalLink, Eye } from 'lucide-react';\nimport { cn } from '../utils/cn';\n\nexport interface WidgetFrameProps {\n /** DOM anchor for the frame (e.g. `widget-<key>`) — L3 indexes scroll here. */\n id?: string;\n title: string;\n question: string;\n /** Raw WQL for the widget. Hidden by default — only rendered with showQuery. */\n query?: string;\n span?: string;\n /** Show the raw WQL query box (teaching/authoring surfaces). View-first default hides it. */\n showQuery?: boolean;\n /**\n * Read-only inspection affordance — an always-visible button (prebuilt\n * seeds, teaching surfaces) opening the host's query inspector. Distinct\n * from editing: present without a toolbar.\n */\n onInspect?: () => void;\n /** Always-visible affordance: open this widget's resolved query in the\n * WQL explorer (host navigates). */\n onOpenInExplorer?: () => void;\n /**\n * Edit-mode action cluster (edit / duplicate / remove / reorder / size),\n * rendered top-right and always visible while present. The host builds it;\n * the frame only positions it.\n */\n toolbar?: ReactNode;\n children: ReactNode;\n}\n\nexport function WidgetFrame({ id, title, question, query, span, showQuery = false, onInspect, onOpenInExplorer, toolbar, children }: WidgetFrameProps) {\n return (\n <div\n id={id}\n className={cn(\n 'relative group/frame bg-card border border-border rounded-lg p-4 flex flex-col min-h-0',\n span,\n )}\n >\n <div className=\"flex items-start justify-between gap-3 mb-2\">\n <div className=\"min-w-0\">\n <h3 className=\"text-sm font-semibold text-foreground\">{title}</h3>\n {question && <p className=\"mt-1 text-xs text-muted-foreground\">{question}</p>}\n </div>\n {(onInspect || onOpenInExplorer) && (\n <div className=\"flex shrink-0 items-center gap-1\">\n {onInspect && (\n <button\n type=\"button\"\n onClick={onInspect}\n title=\"Inspect widget query\"\n aria-label={`Inspect query for ${title || 'widget'}`}\n className=\"inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground transition-colors\"\n >\n <Eye className=\"w-3.5 h-3.5\" />\n </button>\n )}\n {onOpenInExplorer && (\n <button\n type=\"button\"\n onClick={onOpenInExplorer}\n title=\"Open in explorer\"\n aria-label={`Open ${title || 'widget'} in explorer`}\n className=\"inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground transition-colors\"\n >\n <ExternalLink className=\"w-3.5 h-3.5\" />\n </button>\n )}\n </div>\n )}\n </div>\n {toolbar && <div className=\"mb-3\">{toolbar}</div>}\n {/* Long WQL wraps in place - an in-card horizontal scrollbar reads as\n a layout bug (dogfood #4). `break-all` covers spaceless fragments\n like `sum:totalVolume{effort:bench-press}`. */}\n {showQuery && query != null && query !== '' && (\n <div className=\"font-mono text-[11px] text-primary/90 bg-background/60 rounded px-2 py-1 mb-3 whitespace-pre-wrap break-all\">\n {query}\n </div>\n )}\n <div className=\"flex-1 min-h-0\">{children}</div>\n </div>\n );\n}\n\n/** Standard edit-mode tool-button chrome for the widget toolbar. */\nexport function WidgetToolButton({\n label,\n onClick,\n disabled,\n active,\n children,\n}: {\n label: string;\n onClick: () => void;\n disabled?: boolean;\n active?: boolean;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={label}\n aria-label={label}\n disabled={disabled}\n className={cn(\n 'inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground disabled:opacity-40 disabled:hover:text-muted-foreground transition-colors',\n active && 'text-primary bg-primary/10',\n )}\n >\n {children}\n </button>\n );\n}\n\n/** The primary \"open the full editor\" affordance inside the toolbar. */\nexport function WidgetEditButton({ title, onClick }: { title: string; onClick: () => void }) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title=\"Edit widget\"\n aria-label={`Edit widget ${title || ''}`.trim()}\n className=\"inline-flex items-center justify-center p-1 max-lg:min-h-11 max-lg:min-w-11 rounded bg-muted/80 text-muted-foreground hover:text-foreground transition-colors\"\n >\n <Edit3 className=\"w-3.5 h-3.5\" />\n </button>\n );\n}\n","import { useEffect, useState } from 'react';\nimport type { DashboardToken } from '@bitcobblers/wod-wiki-wql';\nimport { cn } from '../utils/cn';\n\nexport interface DashboardTokenControlsProps {\n tokens: DashboardToken[];\n /** Current value per token name (defaults applied by the caller). */\n values: Record<string, string>;\n /**\n * Present when the note is editable — a change commits exactly once, on an\n * explicit action: a list-token segment click, or a scalar-token blur /\n * Enter. Keystrokes only edit the local draft — they never rewrite the\n * note or re-run widgets mid-edit.\n */\n onChange?: (name: string, value: string) => void;\n}\n\n/**\n * Scalar token input — owns a local draft so typing stays in-process; the\n * committed value (blur or Enter) is the only write. External value changes\n * (e.g. a written note re-resolved) re-sync the draft.\n */\nfunction ScalarTokenInput({\n name,\n value,\n disabled,\n onCommit,\n}: {\n name: string;\n value: string;\n disabled?: boolean;\n onCommit: (value: string) => void;\n}) {\n const [draft, setDraft] = useState(value);\n useEffect(() => setDraft(value), [value]);\n\n const commit = () => {\n if (draft !== value) onCommit(draft);\n };\n\n return (\n <input\n type=\"text\"\n value={draft}\n disabled={disabled}\n onChange={(e) => setDraft(e.target.value)}\n onBlur={commit}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n commit();\n e.currentTarget.blur();\n }\n }}\n aria-label={`Token ${name}`}\n className=\"w-20 rounded-lg border border-border bg-card px-2 py-1 text-xs font-mono text-foreground focus:outline-none focus:border-primary disabled:opacity-60\"\n />\n );\n}\n\n/**\n * DashboardTokenControls — the control row a dashboard note's frontmatter\n * tokens render as (#899): scalar tokens become inputs, list tokens segmented\n * controls (first entry = default). Read-only views (no onChange) render the\n * current values as static text.\n */\nexport function DashboardTokenControls({ tokens, values, onChange }: DashboardTokenControlsProps) {\n if (tokens.length === 0) return null;\n const readOnly = !onChange;\n\n return (\n <div\n data-testid=\"dashboard-token-controls\"\n className=\"flex flex-wrap items-center gap-x-5 gap-y-2 mb-4\"\n >\n {tokens.map((token) => {\n const current = values[token.name] ?? token.values[0];\n return (\n <div key={token.name} className=\"flex items-center gap-2\">\n <span className=\"font-mono text-[11px] text-muted-foreground\">${token.name}</span>\n {token.isList ? (\n <div className=\"inline-flex items-center gap-1 rounded-lg border border-border bg-card p-1\">\n {token.values.map((option) => (\n <button\n key={option}\n type=\"button\"\n disabled={readOnly}\n onClick={() => {\n // A segment click IS the explicit commit — no draft.\n if (option !== current) onChange?.(token.name, option);\n }}\n className={cn(\n 'text-xs px-2.5 py-1 rounded-md transition-colors',\n option === current\n ? 'bg-primary text-primary-foreground font-medium'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted',\n readOnly && 'cursor-default',\n )}\n >\n {option}\n </button>\n ))}\n </div>\n ) : readOnly ? (\n <span className=\"text-xs text-foreground font-mono\">{current}</span>\n ) : (\n <ScalarTokenInput\n name={token.name}\n value={current}\n onCommit={(next) => onChange?.(token.name, next)}\n />\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","import { Fragment, useEffect, useMemo, useState } from 'react';\nimport { ChevronDown, ChevronRight, ChevronUp, Copy, Trash2 } from 'lucide-react';\nimport { isFindQuery, isPipelineQuery, parseQuery, type QueryResult, type AnyParsedQuery, defaultTokenValues, isDashboardWidgetType, resolveWidgetType, substituteTokens, unknownTokensMessage, unknownWidgetTypeMessage, type DashboardDocument, type DashboardWidget, SharedQueryDocumentRunner, type QueryDocumentRunnerHost, type DocumentOutput } from '@bitcobblers/wod-wiki-wql';\nimport type { QueryExecutor } from '../contracts/query';\nimport { WidgetFrame, WidgetToolButton, WidgetEditButton } from './WidgetFrame';\nimport { WidgetChart, WidgetProblemBadge } from './WidgetChart';\nimport { toChartResult } from './chartData';\nimport { DashboardTokenControls } from './DashboardTokenControls';\nimport { cn } from '../utils/cn';\n\n/** A widget's grid placement — column span 1..4, or a forced full row. */\nexport interface WidgetSpanOption {\n spanCols?: number;\n spanFull?: boolean;\n}\n\n/** A note heading rendered as a full-width grid row between widgets, with its\n * own DOM anchor (L3 scroll target). Order within `headings` is preserved. */\nexport interface DashboardHeadingAnchor {\n id: string;\n /** Markdown heading level (2+; level 1 renders as the page title surface). */\n level: number;\n text: string;\n /** Insert before this widget index; `widgets.length` = after the last. */\n beforeWidget: number;\n}\n\nexport interface DashboardViewProps {\n /** Parsed dashboard note (buildDashboardDocument). */\n document: DashboardDocument;\n /** Note headings to render between the widgets (document order). */\n headings?: DashboardHeadingAnchor[];\n /** Injected QueryExecutor for executing WQL queries. Zero singleton coupling. */\n executor?: QueryExecutor;\n /** Optional rollup fact warmer callback. */\n onEnsureRollupFacts?: () => Promise<void>;\n /** Current token values; defaults to each token's declared default. */\n tokenValues?: Record<string, string>;\n /** Present when the note is editable — committed control changes write back to frontmatter. */\n onTokenChange?: (name: string, value: string) => void;\n /**\n * Edit mode: per-widget arrangement chrome (edit / duplicate / remove /\n * reorder / size) renders on every card. View mode stays chrome-free —\n * the host gates editing on this flag plus the handler set below.\n */\n editMode?: boolean;\n /** Open the shared authoring composer for this widget (edit flow). */\n onEditWidget?: (widget: DashboardWidget) => void;\n /** Read-only query inspection (prebuilt seeds, teaching surfaces). */\n onInspectWidget?: (widget: DashboardWidget) => void;\n /** Open the widget's token-resolved query in the WQL explorer (host navigates). */\n onOpenInExplorer?: (widget: DashboardWidget, query: string) => void;\n onDuplicateWidget?: (widget: DashboardWidget) => void;\n onRemoveWidget?: (widget: DashboardWidget) => void;\n onMoveWidget?: (widget: DashboardWidget, delta: -1 | 1) => void;\n onResizeWidget?: (widget: DashboardWidget, span: WidgetSpanOption) => void;\n /** Optional execution range (ms epoch). Omit to use each query's own window. */\n rangeStart?: number;\n rangeEnd?: number;\n preferredUnit?: string;\n}\n\n/** Chart-input result plus the content-plane payloads list widgets read. */\ntype WidgetRunResult = QueryResult & {\n notes?: unknown[];\n blocks?: unknown[];\n efforts?: unknown[];\n runs?: unknown[];\n containers?: Record<string, { kind: 'page'; id: string; slug?: string; date?: string } | { kind: 'note'; id: string }>;\n};\n\ninterface WidgetRun {\n result?: WidgetRunResult;\n error?: string;\n}\n\n/**\n * Executor→runner host adapter (ticket 19 cutover): the shared document\n * runner drives family dispatch; the injected QueryExecutor stays the only\n * execution seam. Range/unit ride every aggregate call; missing pipeline\n * capability surfaces as an output diagnostic — never a silent empty result.\n */\nexport function createExecutorDocumentHost(\n executor: QueryExecutor,\n range: { rangeStart?: number; rangeEnd?: number; preferredUnit?: string; rollupEnsure?: () => Promise<void> } = {},\n): QueryDocumentRunnerHost {\n return {\n runAggregate: (queryText, overrides) =>\n executor.runQuery(queryText, {\n context: overrides.context,\n rangeStart: range.rangeStart,\n rangeEnd: range.rangeEnd,\n preferredUnit: range.preferredUnit,\n }),\n runFind: async (queryText, context) => {\n const parsed = parseQuery(queryText);\n if (!isFindQuery(parsed)) return { kind: 'find', error: `not a content query: ${queryText}` };\n const res = await executor.runFind(parsed, {\n context,\n range: range.rangeStart !== undefined\n ? { start: range.rangeStart, end: range.rangeEnd ?? Number.MAX_SAFE_INTEGER, endExclusive: false }\n : undefined,\n });\n return {\n kind: 'find',\n notes: res.notes,\n blocks: res.blocks,\n efforts: res.efforts,\n containers: res.containers,\n runs: res.runs,\n table: res.table,\n };\n },\n runPipeline: async (queryText, context) => {\n const res = await executor.runPipeline?.(queryText, {\n context,\n rangeStart: range.rangeStart,\n rangeEnd: range.rangeEnd,\n preferredUnit: range.preferredUnit,\n });\n return res ?? { error: 'pipeline queries are not supported by this executor' };\n },\n rollupEnsure: range.rollupEnsure,\n };\n}\n\n/** Document output → widget chart input (content payloads ride along). */\nfunction outputToRunResult(parsed: AnyParsedQuery, out: DocumentOutput): WidgetRunResult {\n const base = toChartResult({ parsed, series: out.series, unit: out.unit, error: out.error, table: out.table });\n return Object.assign(base, {\n ...(out.notes ? { notes: out.notes } : {}),\n ...(out.blocks ? { blocks: out.blocks } : {}),\n ...(out.efforts ? { efforts: out.efforts } : {}),\n ...(out.containers ? { containers: out.containers } : {}),\n ...(out.runs ? { runs: out.runs } : {}),\n });\n}\n\n/**\n * Grid span classes for a widget on the 1 / 2 / 4-column responsive grid.\n * An explicit fence span (`-N` / `-full`) wins; otherwise the type default.\n */\nfunction spanClass(widget: DashboardWidget): string {\n if (widget.spanFull) return 'col-span-1 md:col-span-2 lg:col-span-4';\n if (widget.spanCols != null) {\n if (widget.spanCols <= 1) return 'col-span-1';\n if (widget.spanCols === 2) return 'col-span-1 md:col-span-2';\n if (widget.spanCols === 3) return 'col-span-1 md:col-span-2 lg:col-span-3';\n return 'col-span-1 md:col-span-2 lg:col-span-4';\n }\n const resolved = resolveWidgetType(widget.type);\n if (resolved === 'value') return 'col-span-1';\n if (resolved === 'table') return 'col-span-1 md:col-span-2';\n return 'col-span-1 md:col-span-2 lg:col-span-4';\n}\n\n/** Size options in the edit-mode toolbar — column span or a full row. */\nconst SIZE_OPTIONS: Array<{ label: string; span: WidgetSpanOption; testId: string }> = [\n { label: 'Span 1 column', span: { spanCols: 1 }, testId: 'widget-size-1' },\n { label: 'Span 2 columns', span: { spanCols: 2 }, testId: 'widget-size-2' },\n { label: 'Span 4 columns', span: { spanCols: 4 }, testId: 'widget-size-4' },\n { label: 'Full row', span: { spanFull: true }, testId: 'widget-size-full' },\n];\n\nfunction sizeIsActive(widget: DashboardWidget, span: WidgetSpanOption): boolean {\n if (span.spanFull) return widget.spanFull === true;\n return !widget.spanFull && (widget.spanCols ?? null) === (span.spanCols ?? null);\n}\n\n/**\n * DashboardView — the state-free dashboard renderer (#900, format locked in #899).\n *\n * Takes a parsed DashboardDocument + current token values, runs all widget\n * queries concurrently via the injected QueryExecutor, and renders the\n * responsive CSS grid. All authoring interactions are host-owned: the view\n * surfaces the affordances (edit-mode toolbar, inspect button) and reports\n * through the injected callbacks — it never owns dialog or write state.\n */\nexport function DashboardView({\n document,\n headings,\n executor,\n onEnsureRollupFacts,\n tokenValues,\n onTokenChange,\n editMode = false,\n onEditWidget,\n onInspectWidget,\n onOpenInExplorer,\n onDuplicateWidget,\n onRemoveWidget,\n onMoveWidget,\n onResizeWidget,\n rangeStart,\n rangeEnd,\n preferredUnit,\n}: DashboardViewProps) {\n const values = useMemo(\n () => ({ ...defaultTokenValues(document.tokens), ...tokenValues }),\n [document.tokens, tokenValues],\n );\n\n const resolved = useMemo(\n () =>\n document.widgets.map((widget) => {\n const { query, missing } = substituteTokens(widget.body, values);\n // Fence-tag attributes carry presentation params (`goal=$token`) —\n // they ride the same token values as the body, and a missing token\n // blocks the widget instead of rendering a NaN target.\n const attributes: Record<string, string> = {};\n const allMissing = new Set(missing);\n for (const [key, value] of Object.entries(widget.attributes)) {\n const sub = substituteTokens(value, values);\n attributes[key] = sub.query;\n for (const m of sub.missing) allMissing.add(m);\n }\n return { widget, query, missing: [...allMissing], attributes };\n }),\n [document.widgets, values],\n );\n\n const [runs, setRuns] = useState<Record<string, WidgetRun>>({});\n const [loading, setLoading] = useState(true);\n\n const resolvedKey = useMemo(\n () => resolved.map((r) => `${r.widget.key}:${r.query}`).join('|'),\n [resolved],\n );\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n\n async function load() {\n const next: Record<string, WidgetRun> = {};\n const runnable: Array<{ widget: DashboardWidget; query: string; parsed: AnyParsedQuery }> = [];\n\n for (const { widget, query, missing } of resolved) {\n if (widget.type !== '' && !isDashboardWidgetType(widget.type)) {\n next[widget.key] = { error: unknownWidgetTypeMessage(widget.type) };\n continue;\n }\n if (missing.length > 0) {\n next[widget.key] = { error: unknownTokensMessage(missing) };\n continue;\n }\n const parsed = parseQuery(query);\n if (parsed.error) {\n next[widget.key] = { error: parsed.error };\n continue;\n }\n const resolvedType = resolveWidgetType(widget.type);\n if (isFindQuery(parsed)) {\n if (resolvedType !== 'table' && resolvedType !== 'list') {\n next[widget.key] = { error: 'content queries return things — use a table or list widget instead' };\n continue;\n }\n } else if (!isPipelineQuery(parsed) && resolvedType === 'list') {\n next[widget.key] = { error: 'aggregate queries return numbers — use a chart or value widget instead' };\n continue;\n }\n runnable.push({ widget, query, parsed });\n }\n\n if (!executor) {\n if (!cancelled) {\n setRuns(next);\n setLoading(false);\n }\n return;\n }\n\n // One runner host per dashboard run; each widget document gets its own\n // captured execution context (ticket 12) — overlapping runs never\n // borrow each other's snapshot. Rollup-ensure is AST-driven inside the\n // runner (calc.* heads incl. pipeline stages), not string sniffing.\n const host = createExecutorDocumentHost(executor, {\n rangeStart,\n rangeEnd,\n preferredUnit,\n rollupEnsure: onEnsureRollupFacts,\n });\n\n await Promise.all(\n runnable.map(async ({ widget, query, parsed }) => {\n try {\n const runner = new SharedQueryDocumentRunner(host);\n const res = await runner.run(query);\n const out = res.outputs[0];\n if (!out) {\n next[widget.key] = { error: res.diagnostics[0] ?? 'widget produced no output' };\n return;\n }\n const error = out.error ?? res.diagnostics[0];\n next[widget.key] = {\n result: outputToRunResult(parsed, out),\n ...(error ? { error } : {}),\n };\n } catch (err) {\n next[widget.key] = { error: err instanceof Error ? err.message : String(err) };\n }\n }),\n );\n\n if (!cancelled) {\n setRuns(next);\n setLoading(false);\n }\n }\n\n void load();\n return () => {\n cancelled = true;\n };\n }, [resolvedKey, resolved, executor, onEnsureRollupFacts, rangeStart, rangeEnd, preferredUnit]);\n\n return (\n <div data-testid=\"dashboard-view\">\n <DashboardTokenControls tokens={document.tokens} values={values} onChange={onTokenChange} />\n\n {loading && <div className=\"text-sm text-muted-foreground mb-3\">Loading widgets…</div>}\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4\">\n {resolved.map(({ widget, query, attributes }, index) => {\n const run = runs[widget.key];\n const canArrange = editMode && (onEditWidget || onDuplicateWidget || onRemoveWidget || onMoveWidget || onResizeWidget);\n const before = (headings ?? []).filter((h) => h.beforeWidget === index);\n return (\n <Fragment key={widget.key}>\n {before.map((h) => (\n <div\n key={h.id}\n id={h.id}\n className={cn('col-span-full font-semibold text-foreground', h.level <= 2 ? 'text-base mt-2' : 'text-sm')}\n >\n {h.text}\n </div>\n ))}\n <WidgetFrame\n key={widget.key}\n id={`widget-${widget.key}`}\n title={widget.title ?? ''}\n question={widget.question ?? ''}\n query={query}\n span={spanClass(widget)}\n onInspect={onInspectWidget ? () => onInspectWidget(widget) : undefined}\n onOpenInExplorer={onOpenInExplorer ? () => onOpenInExplorer(widget, query) : undefined}\n toolbar={\n canArrange ? (\n <div className=\"flex flex-wrap items-center gap-1.5\" data-testid={`widget-toolbar-${widget.key}`}>\n {onEditWidget && <WidgetEditButton title={widget.title ?? ''} onClick={() => onEditWidget(widget)} />}\n {onMoveWidget && (\n <>\n <WidgetToolButton\n label={`Move ${widget.title || 'widget'} up`}\n disabled={index === 0}\n onClick={() => onMoveWidget(widget, -1)}\n >\n <ChevronUp className=\"w-3.5 h-3.5\" />\n </WidgetToolButton>\n <WidgetToolButton\n label={`Move ${widget.title || 'widget'} down`}\n disabled={index === resolved.length - 1}\n onClick={() => onMoveWidget(widget, 1)}\n >\n <ChevronDown className=\"w-3.5 h-3.5\" />\n </WidgetToolButton>\n </>\n )}\n {onResizeWidget && (\n <div className=\"flex items-center gap-0 rounded bg-muted/60 p-0.5\">\n {SIZE_OPTIONS.map((option) => (\n <button\n key={option.testId}\n type=\"button\"\n data-testid={`${option.testId}-${widget.key}`}\n title={option.label}\n aria-label={`${option.label} for ${widget.title || 'widget'}`}\n aria-pressed={sizeIsActive(widget, option.span)}\n disabled={sizeIsActive(widget, option.span)}\n onClick={() => onResizeWidget(widget, option.span)}\n className=\"inline-flex items-center justify-center px-1 py-0.5 max-lg:min-h-11 max-lg:min-w-11 text-xs font-mono rounded text-muted-foreground hover:text-foreground disabled:text-primary disabled:bg-primary/10\"\n >\n {option.span.spanFull ? <ChevronRight className=\"w-3 h-3\" /> : option.span.spanCols}\n </button>\n ))}\n </div>\n )}\n {onDuplicateWidget && (\n <WidgetToolButton\n label={`Duplicate ${widget.title || 'widget'}`}\n onClick={() => onDuplicateWidget(widget)}\n >\n <Copy className=\"w-3.5 h-3.5\" />\n </WidgetToolButton>\n )}\n {onRemoveWidget && (\n <WidgetToolButton\n label={`Remove ${widget.title || 'widget'}`}\n onClick={() => onRemoveWidget(widget)}\n >\n <Trash2 className=\"w-3.5 h-3.5\" />\n </WidgetToolButton>\n )}\n </div>\n ) : undefined\n }\n >\n {run?.error ? (\n <WidgetProblemBadge message={run.error} />\n ) : (\n <WidgetChart\n type={widget.type}\n result={run?.result}\n label={widget.title}\n unit={preferredUnit}\n attributes={attributes}\n />\n )}\n </WidgetFrame>\n </Fragment>\n );\n })}\n {(headings ?? []).filter((h) => h.beforeWidget >= resolved.length).map((h) => (\n <div\n key={h.id}\n id={h.id}\n className={cn('col-span-full font-semibold text-foreground', h.level <= 2 ? 'text-base mt-2' : 'text-sm')}\n >\n {h.text}\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { cn } from '../utils/cn';\n\nexport type AnalyticsRangeWeeks = 4 | 8 | 16;\n\nexport interface RangeSelectorProps {\n weeks?: number;\n onWeeksChange?: (weeks: number) => void;\n className?: string;\n}\n\nexport function RangeSelector({ weeks: weeksProp, onWeeksChange, className }: RangeSelectorProps) {\n const [internalWeeks, setInternalWeeks] = useState<number>(16);\n const currentWeeks = weeksProp ?? internalWeeks;\n\n const handleSelect = (w: number) => {\n if (onWeeksChange) {\n onWeeksChange(w);\n } else {\n setInternalWeeks(w);\n }\n };\n\n return (\n <div className={cn('inline-flex items-center gap-1 rounded-lg border border-border bg-card p-1', className)}>\n {[4, 8, 16].map((w) => (\n <button\n key={w}\n type=\"button\"\n onClick={() => handleSelect(w)}\n className={cn(\n 'text-xs px-2.5 py-1 rounded-md transition-colors',\n currentWeeks === w\n ? 'bg-primary text-primary-foreground font-medium'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted',\n )}\n >\n {w}w\n </button>\n ))}\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\nimport { parseQuery, SharedQueryDocumentRunner, type QueryResult } from '@bitcobblers/wod-wiki-wql';\nimport type { QueryExecutor } from '../contracts/query';\nimport { createExecutorDocumentHost } from './DashboardView';\nimport { toChartResult } from './chartData';\n\nconst DAY = 86_400_000;\nconst WEEK = 7 * DAY;\n\nexport interface AnalyticsQueryDef {\n key: string;\n query: string;\n}\n\nexport interface AnalyticsQueriesState {\n results: Record<string, QueryResult>;\n loading: boolean;\n}\n\nexport function useAnalyticsQueries(\n queries: AnalyticsQueryDef[],\n weeks: number,\n executor?: QueryExecutor,\n refreshKey = 0,\n preferredUnit?: string,\n onEnsureRollupFacts?: () => Promise<void>,\n): AnalyticsQueriesState {\n const [results, setResults] = useState<Record<string, QueryResult>>({});\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n\n async function load() {\n if (!executor) {\n if (!cancelled) setLoading(false);\n return;\n }\n\n const now = Date.now();\n const rangeStart = now - weeks * WEEK;\n // Ticket 19 cutover: widget queries evaluate through the shared\n // document runner — family dispatch (aggregate/find/rows/pipeline),\n // AST-driven rollup-ensure, and one captured context per query run.\n const host = createExecutorDocumentHost(executor, {\n rangeStart,\n rangeEnd: now,\n preferredUnit,\n rollupEnsure: onEnsureRollupFacts,\n });\n const runner = new SharedQueryDocumentRunner(host);\n try {\n const settled = await Promise.all(\n queries.map(async (q) => {\n const res = await runner.run(q.query);\n const out = res.outputs[0];\n const error = out?.error ?? res.diagnostics[0];\n // The chart input keeps the raw query's own parse so consumers\n // reading `parsed.family`/`raw` see the authored family.\n const result = toChartResult({\n parsed: parseQuery(q.query),\n series: out?.series,\n unit: out?.unit,\n error,\n table: out?.table,\n }) as QueryResult & { notes?: unknown[]; blocks?: unknown[]; efforts?: unknown[]; runs?: unknown[] };\n if (out?.notes) result.notes = out.notes;\n if (out?.blocks) result.blocks = out.blocks;\n if (out?.efforts) result.efforts = out.efforts;\n if (out?.runs) result.runs = out.runs;\n return [q.key, result] as const;\n }),\n );\n if (!cancelled) setResults(Object.fromEntries(settled));\n } finally {\n if (!cancelled) setLoading(false);\n }\n }\n\n void load();\n\n return () => {\n cancelled = true;\n };\n }, [queries, weeks, executor, refreshKey, preferredUnit, onEnsureRollupFacts]);\n\n return { results, loading };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { cn } from '../utils/cn';\nimport { parseQuery } from '@bitcobblers/wod-wiki-wql';\nimport type { AnalyticsQueryDef } from './useAnalyticsQueries';\nimport type { StorageLike } from '../contracts/storage';\n\nexport const ANALYTICS_UNIT_STORAGE_KEY = 'wod.analytics.unit';\nexport const DEFAULT_ANALYTICS_UNIT = 'kg';\nexport type AnalyticsUnit = 'kg' | 'lb';\n\nconst VALID_UNITS: readonly AnalyticsUnit[] = ['kg', 'lb'];\n\nconst memoryStore = new Map<string, string>();\nconst inMemoryStorage: StorageLike = {\n getItem: (key: string) => memoryStore.get(key) ?? null,\n setItem: (key: string, value: string) => {\n memoryStore.set(key, value);\n },\n removeItem: (key: string) => {\n memoryStore.delete(key);\n },\n};\n\nconst unitListeners = new Set<() => void>();\nfunction notifyUnitChange() {\n for (const l of unitListeners) l();\n}\n\nfunction resolveStorage(custom?: StorageLike): StorageLike {\n return custom ?? inMemoryStorage;\n}\n\nexport function readStoredUnit(storage?: StorageLike): AnalyticsUnit {\n const store = resolveStorage(storage);\n const stored = store.getItem(ANALYTICS_UNIT_STORAGE_KEY);\n return (VALID_UNITS as readonly string[]).includes(stored ?? '')\n ? (stored as AnalyticsUnit)\n : DEFAULT_ANALYTICS_UNIT;\n}\n\nexport function useAnalyticsUnitPreference(customStorage?: StorageLike) {\n const storage = resolveStorage(customStorage);\n const [unit, setUnitState] = useState<AnalyticsUnit>(() => readStoredUnit(storage));\n\n useEffect(() => {\n setUnitState(readStoredUnit(storage));\n const sync = () => setUnitState(readStoredUnit(storage));\n unitListeners.add(sync);\n return () => {\n unitListeners.delete(sync);\n };\n }, [storage]);\n\n const setUnit = useCallback(\n (next: AnalyticsUnit) => {\n storage.setItem(ANALYTICS_UNIT_STORAGE_KEY, next);\n setUnitState(next);\n notifyUnitChange();\n },\n [storage],\n );\n\n const toggleUnit = useCallback(() => {\n const next: AnalyticsUnit = unit === 'kg' ? 'lb' : 'kg';\n setUnit(next);\n }, [unit, setUnit]);\n\n return { unit, setUnit, toggleUnit };\n}\n\nexport function getEffectiveAnalyticsUnit(\n query: string,\n preferredUnit: AnalyticsUnit,\n): { unit: AnalyticsUnit; forced: boolean } {\n const parsed = parseQuery(query);\n const displayUnit = 'displayUnit' in parsed ? parsed.displayUnit : undefined;\n if (displayUnit === 'lb' || displayUnit === 'kg') {\n return { unit: displayUnit as AnalyticsUnit, forced: true };\n }\n return { unit: preferredUnit, forced: false };\n}\n\nexport function getDashboardEffectiveUnit(\n queries: AnalyticsQueryDef[],\n preferredUnit: AnalyticsUnit,\n): { unit: AnalyticsUnit; forced: boolean } {\n const units = queries\n .map((q) => {\n const parsed = parseQuery(q.query);\n return 'displayUnit' in parsed ? parsed.displayUnit : undefined;\n })\n .filter((u): u is string => u === 'kg' || u === 'lb');\n\n const unique = Array.from(new Set(units));\n if (unique.length === 1) {\n return { unit: unique[0] as AnalyticsUnit, forced: true };\n }\n return { unit: preferredUnit, forced: false };\n}\nexport interface AnalyticsUnitPreferenceProps {\n className?: string;\n unit?: AnalyticsUnit;\n forced?: boolean;\n storage?: StorageLike;\n}\n\nexport function AnalyticsUnitPreference({ className, unit: unitProp, forced = false, storage }: AnalyticsUnitPreferenceProps) {\n const { unit: storedUnit, setUnit } = useAnalyticsUnitPreference(storage);\n const activeUnit = unitProp ?? storedUnit;\n\n return (\n <div\n data-testid=\"analytics-unit-preference\"\n className={cn('inline-flex items-center gap-1 text-xs', className)}\n >\n <div\n className={cn(\n 'inline-flex items-center rounded-lg border border-border bg-card p-1',\n forced && 'opacity-70',\n )}\n title={forced ? 'Unit forced by query directive in this view' : 'Display unit preference'}\n >\n <button\n type=\"button\"\n disabled={forced}\n onClick={() => setUnit('kg')}\n className={cn(\n 'px-2.5 py-1 rounded-md transition-colors text-xs font-mono',\n activeUnit === 'kg'\n ? 'bg-primary text-primary-foreground font-medium'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted',\n forced && 'cursor-default hover:bg-transparent hover:text-muted-foreground',\n )}\n >\n kg\n </button>\n <button\n type=\"button\"\n disabled={forced}\n onClick={() => setUnit('lb')}\n className={cn(\n 'px-2.5 py-1 rounded-md transition-colors text-xs font-mono',\n activeUnit === 'lb'\n ? 'bg-primary text-primary-foreground font-medium'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted',\n forced && 'cursor-default hover:bg-transparent hover:text-muted-foreground',\n )}\n >\n lb\n </button>\n </div>\n {forced && (\n <span className=\"text-[11px] text-muted-foreground italic\">forced by note</span>\n )}\n </div>\n );\n}\n","/**\n * Auto-generated build version metadata.\n * Do not edit directly; updated by scripts/stamp-version.ts\n */\nexport const VERSION = '0.35.2120';\nexport const GIT_SHA = '62def0d';\nexport const BUILD_TIME = '2026-10-13T06:46:25.596Z';\nexport const SEMVER = {\n version: '0.35.2120',\n gitSha: '62def0d',\n buildTime: '2026-10-13T06:46:25.596Z',\n} as const;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitcobblers/wod-wiki-ui",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.2120",
|
|
4
4
|
"description": "Interactive presentation, CodeMirror editor extensions, and WQL diagram widgets",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"access": "public"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@bitcobblers/wod-wiki-core": "^0.35.
|
|
31
|
-
"@bitcobblers/wod-wiki-lang": "^0.35.
|
|
32
|
-
"@bitcobblers/wod-wiki-wql": "^0.35.
|
|
30
|
+
"@bitcobblers/wod-wiki-core": "^0.35.2120",
|
|
31
|
+
"@bitcobblers/wod-wiki-lang": "^0.35.2120",
|
|
32
|
+
"@bitcobblers/wod-wiki-wql": "^0.35.2120",
|
|
33
33
|
"clsx": "^2.1.1",
|
|
34
34
|
"tailwind-merge": "^3.6.0",
|
|
35
35
|
"@heroicons/react": "^2.2.0"
|