@bitcobblers/wod-wiki-ui 0.10.41 → 0.11.43

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.
@@ -4,7 +4,7 @@ import { tags, styleTags, Tag } from '@lezer/highlight';
4
4
  import { RangeSetBuilder, Facet, StateEffect, StateField, Prec, EditorState, EditorSelection, countColumn } from '@codemirror/state';
5
5
  import { linter, forEachDiagnostic } from '@codemirror/lint';
6
6
  import { whiteboardScriptLanguage, createParser, getAnalyticsFromLogs, whiteboardScript } from '@bitcobblers/wod-wiki-lang';
7
- import { WQL_SOURCES, WQL_AGGREGATORS, WQL_ROLLUP_PERIODS, WQL_VIRTUAL_DIMS, WQL_TAG_KEYS, WQL_METRIC_AGGREGATES, WQL_METRIC_FAMILIES, WQL_CALC_TARGETS, WQL_DISPLAY_UNITS, WQL_INTENSITY_TIERS, parseQueryWidgetSuffix, WQL_COMPARISON_OPS, parseQuery, isRowsQuery, isDashboardWidgetType, unknownWidgetTypeMessage, resolveWidgetType, PLANNED_WIDGET_TYPES, parseWqlSuffixes, WQL_FIND_TARGETS, isFindQuery, isAggregateQuery, splitWidgetBody, substituteTokens, unknownTokensMessage, wql, wqlLanguage } from '@bitcobblers/wod-wiki-wql';
7
+ import { WQL_SOURCES, WQL_AGGREGATORS, WQL_ROLLUP_PERIODS, WQL_VIRTUAL_DIMS, WQL_TAG_KEYS, WQL_METRIC_AGGREGATES, WQL_METRIC_FAMILIES, WQL_CALC_TARGETS, WQL_DISPLAY_UNITS, WQL_INTENSITY_TIERS, parseQueryWidgetSuffix, WQL_COMPARISON_OPS, parseQuery, isRowsQuery, isDashboardWidgetType, unknownWidgetTypeMessage, resolveWidgetType, PLANNED_WIDGET_TYPES, isFindQuery, isAggregateQuery, splitWidgetBody, substituteTokens, unknownTokensMessage, wql, serialize, wqlLanguage } from '@bitcobblers/wod-wiki-wql';
8
8
  import { clsx } from 'clsx';
9
9
  import { twMerge } from 'tailwind-merge';
10
10
  import { snippet, autocompletion, closeBrackets, closeBracketsKeymap, CompletionContext, ifNotIn, completeFromList, snippetCompletion } from '@codemirror/autocomplete';
@@ -2872,7 +2872,6 @@ var CONTENT_SOURCES = WQL_SOURCES.filter((s) => s !== "metrics");
2872
2872
  function sourcePlane(source) {
2873
2873
  return source === "metrics" ? "metrics" : "content";
2874
2874
  }
2875
- var METRICS_ONLY_TYPES = /* @__PURE__ */ new Set(["agg", "metric", "groupby", "rollup", "unit"]);
2876
2875
  var SOURCE_OPTIONS = [
2877
2876
  { value: "journal", label: "Journal", description: "Find notes in the personal journal" },
2878
2877
  { value: "collections", label: "Collections", description: "Find notes in workout catalogs" },
@@ -2950,263 +2949,6 @@ function getClauseMeta(type) {
2950
2949
  description: ""
2951
2950
  };
2952
2951
  }
2953
- function clauseToWql(clause) {
2954
- if (!clause.value.trim()) return {};
2955
- const val = clause.value.trim();
2956
- switch (clause.type) {
2957
- case "text": {
2958
- const needsQuotes = /\s/.test(val) && !(val.startsWith('"') && val.endsWith('"'));
2959
- return { filterStr: `text:${needsQuotes ? `"${val}"` : val}` };
2960
- }
2961
- case "catalog":
2962
- return { filterStr: `catalog:${val}` };
2963
- case "tag":
2964
- return { filterStr: `tags:${val}` };
2965
- case "effort":
2966
- return { filterStr: `effort:${val}` };
2967
- case "discipline":
2968
- return { filterStr: `discipline:${val}` };
2969
- case "intensity":
2970
- return { filterStr: `intensity:${val}` };
2971
- case "origin":
2972
- return { filterStr: `origin:${val}` };
2973
- case "type":
2974
- return { filterStr: `type:${val}` };
2975
- case "has":
2976
- return { filterStr: `has:${val}` };
2977
- case "result":
2978
- return { filterStr: `result:${val}` };
2979
- case "block":
2980
- return { filterStr: `block:${val}` };
2981
- case "note":
2982
- return { filterStr: `note:${val}` };
2983
- default: {
2984
- const def = composerRegistry.getSlot(clause.type);
2985
- if (!def) return {};
2986
- if (!def.parseValue) return {};
2987
- const value = def.parseValue(val);
2988
- if (value === void 0) return {};
2989
- const fragment = def.wqlGenerator(value);
2990
- return fragment.trim() ? { filterStr: fragment } : {};
2991
- }
2992
- }
2993
- }
2994
- function clausesToWql(clauses) {
2995
- const whereClause = clauses.find((c) => c.type === "where");
2996
- const whereStr = whereClause?.value?.trim() ? `where ${whereClause.value.trim()}` : "";
2997
- const filterParts = [];
2998
- for (const c of clauses) {
2999
- const res = clauseToWql(c);
3000
- if (res.filterStr) {
3001
- filterParts.push(res.filterStr);
3002
- }
3003
- }
3004
- const filterBraces = filterParts.length > 0 ? `{${filterParts.join(", ")}}` : "";
3005
- const source = clauseValue(clauses, "source", "notes");
3006
- if (source === "rows") {
3007
- const output = clauseValue(clauses, "output", "") || "all";
3008
- const timeClause2 = clauses.find((c) => c.type === "time");
3009
- let timeStr2 = "";
3010
- if (timeClause2 && timeClause2.value && timeClause2.value !== "all") {
3011
- const rawVal = timeClause2.value.trim();
3012
- timeStr2 = rawVal.startsWith("last") ? rawVal : `last ${rawVal}`;
3013
- }
3014
- return [
3015
- `rows:${output}${filterBraces}`,
3016
- timeStr2
3017
- ].filter(Boolean).join(" ").trim();
3018
- }
3019
- if (source === "metrics") {
3020
- const agg = clauseValue(clauses, "agg", "sum");
3021
- const metric = clauseValue(clauses, "metric", "");
3022
- const dims = clauses.filter((c) => c.type === "groupby" && c.value.trim()).map((c) => c.value.trim());
3023
- const rollup = clauseValue(clauses, "rollup", "");
3024
- const unit = clauseValue(clauses, "unit", "");
3025
- const byStr = dims.length ? `by {${dims.join(", ")}}` : "";
3026
- const rollupStr = rollup ? `.rollup(${rollup})` : "";
3027
- const head = byStr ? `${agg}:${metric}${filterBraces}` : `${agg}:${metric}${filterBraces}${rollupStr}`;
3028
- return [
3029
- head,
3030
- `${byStr}${byStr ? rollupStr : ""}`,
3031
- unit ? `in ${unit}` : "",
3032
- whereStr
3033
- ].filter(Boolean).join(" ").trim();
3034
- }
3035
- const target = source === "blocks" ? "block" : source === "efforts" ? "effort" : "note";
3036
- const scope = source === "notes" || source === "blocks" || source === "efforts" ? "all" : source;
3037
- const timeClause = clauses.find((c) => c.type === "time");
3038
- let timeStr = "";
3039
- if (timeClause && timeClause.value && timeClause.value !== "all") {
3040
- const rawVal = timeClause.value.trim();
3041
- timeStr = rawVal.startsWith("last") ? rawVal : `last ${rawVal}`;
3042
- }
3043
- return [
3044
- `find:${target}${filterBraces}`,
3045
- `in ${scope}`,
3046
- timeStr,
3047
- whereStr
3048
- ].filter(Boolean).join(" ").trim();
3049
- }
3050
- var POSITIONAL_CLAUSE_TYPES = /* @__PURE__ */ new Set(["source", "time", "where", "agg", "metric", "groupby", "rollup", "unit", "output"]);
3051
- var FILTER_KEY_TO_CLAUSE_TYPE = Object.fromEntries(
3052
- Object.entries(CLAUSE_META).filter(([type]) => !POSITIONAL_CLAUSE_TYPES.has(type)).map(([type, meta]) => [meta.prefix.replace(/:$/, ""), type])
3053
- );
3054
- function splitTopLevel(body) {
3055
- const parts = [];
3056
- let depth = 0;
3057
- let inQuote = false;
3058
- let start = 0;
3059
- for (let i = 0; i < body.length; i++) {
3060
- const c = body[i];
3061
- if (c === '"') inQuote = !inQuote;
3062
- else if (!inQuote && c === "{") depth++;
3063
- else if (!inQuote && c === "}") depth = Math.max(0, depth - 1);
3064
- else if (!inQuote && c === "," && depth === 0) {
3065
- parts.push(body.slice(start, i));
3066
- start = i + 1;
3067
- }
3068
- }
3069
- parts.push(body.slice(start));
3070
- return parts;
3071
- }
3072
- var RESTORE_FIND_HEAD_RE = /^find:([a-zA-Z0-9_-]*)/;
3073
- var RESTORE_AGG_HEAD_RE = /^([a-zA-Z0-9_-]+):([a-zA-Z0-9_.-]*)/;
3074
- function restoreClause(id, type, value) {
3075
- return { id, type, ...getClauseMeta(type), value };
3076
- }
3077
- function filterFragmentToClause(fragment, index) {
3078
- if (fragment.startsWith("!")) return null;
3079
- const colon2 = fragment.indexOf(":");
3080
- if (colon2 <= 0) return null;
3081
- const key = fragment.slice(0, colon2);
3082
- const value = fragment.slice(colon2 + 1);
3083
- if (!value.trim()) return null;
3084
- if (key === "source") {
3085
- return restoreClause(`c-source-${index}`, "source", value);
3086
- }
3087
- const builtin = FILTER_KEY_TO_CLAUSE_TYPE[key];
3088
- if (builtin) {
3089
- const restoredValue = builtin === "text" && value.length >= 2 && value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value;
3090
- return restoreClause(`c-${builtin}-${index}`, builtin, restoredValue);
3091
- }
3092
- for (const slot of composerRegistry.getAllSlots()) {
3093
- if (!slot.parseValue || !slot.formatValue) continue;
3094
- const typed = slot.parseValue(value);
3095
- if (typed !== void 0 && slot.wqlGenerator(typed) === fragment) {
3096
- return restoreClause(`c-${slot.type}-${index}`, slot.type, slot.formatValue(typed));
3097
- }
3098
- }
3099
- return null;
3100
- }
3101
- function restoreFilters(rest) {
3102
- if (!rest) return [];
3103
- if (!rest.startsWith("{") || !rest.endsWith("}")) return null;
3104
- const body = rest.slice(1, -1);
3105
- const fragments = splitTopLevel(body).map((f) => f.trim()).filter(Boolean);
3106
- const clauses = [];
3107
- for (let i = 0; i < fragments.length; i++) {
3108
- const clause = filterFragmentToClause(fragments[i], i);
3109
- if (!clause) return null;
3110
- clauses.push(clause);
3111
- }
3112
- return clauses;
3113
- }
3114
- function wqlToClauses(wql2) {
3115
- const suffixes = parseWqlSuffixes(wql2.trim());
3116
- if (suffixes.conflicts?.length) return null;
3117
- const { where, displayUnit, groupBy, rollup, window: window2, legacyScope, primaryText } = suffixes;
3118
- if (window2?.kind === "range") return null;
3119
- const rowsMatch = /^rows(?:\:([a-zA-Z0-9_-]+))?\:?/.exec(primaryText);
3120
- if (rowsMatch) {
3121
- if (where || groupBy || rollup) return null;
3122
- const rest2 = primaryText.slice(rowsMatch[0].length).trim();
3123
- const filterClauses2 = restoreFilters(rest2);
3124
- if (!filterClauses2) return null;
3125
- const clauses2 = [
3126
- restoreClause("c-source", "source", "rows"),
3127
- restoreClause("c-time", "time", window2?.kind === "relative" ? `last ${window2.size}${window2.unit}` : "all"),
3128
- ...rowsMatch[1] ? [restoreClause("c-output", "output", rowsMatch[1])] : [],
3129
- ...filterClauses2
3130
- ];
3131
- return clauses2;
3132
- }
3133
- if (primaryText.startsWith("find:")) {
3134
- const headMatch2 = RESTORE_FIND_HEAD_RE.exec(primaryText);
3135
- if (!headMatch2) return null;
3136
- const targetValue = headMatch2[1];
3137
- if (!WQL_FIND_TARGETS.includes(targetValue)) return null;
3138
- const rest2 = primaryText.slice(headMatch2[0].length).trim();
3139
- const filterClauses2 = restoreFilters(rest2);
3140
- if (!filterClauses2) return null;
3141
- const timeValue = window2?.kind === "relative" ? `last ${window2.size}${window2.unit}` : "all";
3142
- const sourceClauseIdx = filterClauses2.findIndex((c) => c.type === "source");
3143
- const sourceFromFilter = sourceClauseIdx !== -1 ? filterClauses2[sourceClauseIdx].value : void 0;
3144
- const scopeValue = legacyScope ?? sourceFromFilter;
3145
- const remainingFilterClauses = sourceClauseIdx !== -1 ? filterClauses2.filter((_, idx) => idx !== sourceClauseIdx) : filterClauses2;
3146
- const sourceValue = targetValue === "block" ? "blocks" : targetValue === "effort" ? "efforts" : !scopeValue || scopeValue === "all" ? "notes" : scopeValue;
3147
- const clauses2 = [
3148
- restoreClause("c-source", "source", sourceValue),
3149
- restoreClause("c-time", "time", timeValue),
3150
- ...remainingFilterClauses
3151
- ];
3152
- if (where) clauses2.push(restoreClause("c-where", "where", where));
3153
- return clauses2;
3154
- }
3155
- if (window2) return null;
3156
- const headMatch = RESTORE_AGG_HEAD_RE.exec(primaryText);
3157
- if (!headMatch) return null;
3158
- const aggValue = headMatch[1];
3159
- const metricValue = headMatch[2] ?? "";
3160
- const rest = primaryText.slice(headMatch[0].length).trim();
3161
- const filterClauses = restoreFilters(rest);
3162
- if (!filterClauses) return null;
3163
- const dimValues = groupBy ?? [];
3164
- const rollupValue = rollup?.raw ?? "";
3165
- const unitValue = displayUnit ?? "";
3166
- const clauses = [
3167
- restoreClause("c-source", "source", "metrics"),
3168
- restoreClause("c-agg", "agg", aggValue),
3169
- restoreClause("c-metric", "metric", metricValue),
3170
- ...filterClauses,
3171
- ...dimValues.map((d, i) => restoreClause(`c-groupby-${i}`, "groupby", d))
3172
- ];
3173
- if (rollupValue) clauses.push(restoreClause("c-rollup", "rollup", rollupValue));
3174
- if (unitValue) clauses.push(restoreClause("c-unit", "unit", unitValue));
3175
- if (where) clauses.push(restoreClause("c-where", "where", where));
3176
- return clauses;
3177
- }
3178
- function setMetricClause(clauses, metric) {
3179
- const withSource = clauses.some((c) => c.type === "source") ? clauses : [restoreClause("c-source", "source", "metrics"), ...clauses];
3180
- const pivoted = clauseValue(withSource, "source") === "metrics" ? withSource : pivotClauses(withSource, "metrics");
3181
- return pivoted.some((c) => c.type === "metric") ? pivoted.map((c) => c.type === "metric" ? { ...c, value: metric } : c) : [...pivoted, restoreClause("c-metric", "metric", metric)];
3182
- }
3183
- function pivotClauses(clauses, source) {
3184
- const next = clauses.filter((c) => !METRICS_ONLY_TYPES.has(c.type) && c.type !== "time" && c.type !== "where").map((c) => c.type === "source" ? { ...c, value: source } : c);
3185
- if (source === "metrics") {
3186
- const sourceIdx = next.findIndex((c) => c.type === "source");
3187
- const head = [];
3188
- if (!next.some((c) => c.type === "agg")) head.push(restoreClause("c-agg", "agg", "sum"));
3189
- if (!next.some((c) => c.type === "metric")) head.push(restoreClause("c-metric", "metric", ""));
3190
- next.splice(sourceIdx >= 0 ? sourceIdx + 1 : next.length, 0, ...head);
3191
- }
3192
- return next;
3193
- }
3194
- function defaultClauses() {
3195
- return [
3196
- { id: "c-source", type: "source", ...CLAUSE_META.source, value: "notes" },
3197
- { id: "c-time", type: "time", ...CLAUSE_META.time, value: "last 2w" }
3198
- ];
3199
- }
3200
- function defaultMetricsClauses() {
3201
- return [
3202
- { id: "c-source", type: "source", ...CLAUSE_META.source, value: "metrics" },
3203
- { id: "c-agg", type: "agg", ...CLAUSE_META.agg, value: "sum" },
3204
- { id: "c-metric", type: "metric", ...CLAUSE_META.metric, value: "" }
3205
- ];
3206
- }
3207
- function clauseValue(clauses, type, fallback = "") {
3208
- return clauses.find((c) => c.type === type)?.value?.trim() || fallback;
3209
- }
3210
2952
  function TokenSlotPill({
3211
2953
  clause,
3212
2954
  isActive,
@@ -3658,6 +3400,247 @@ function AddCalcDropdown({
3658
3400
  )
3659
3401
  ] });
3660
3402
  }
3403
+ var PILL_KEY = {
3404
+ text: "text",
3405
+ catalog: "catalog",
3406
+ tag: "tags",
3407
+ effort: "effort",
3408
+ discipline: "discipline",
3409
+ intensity: "intensity",
3410
+ origin: "origin",
3411
+ type: "type",
3412
+ has: "has",
3413
+ result: "result",
3414
+ block: "block",
3415
+ note: "note"
3416
+ };
3417
+ var KEY_PILL = Object.fromEntries(
3418
+ Object.entries(PILL_KEY).map(([pill, key]) => [key, pill])
3419
+ );
3420
+ function pillValueToFilter(type, rawValue) {
3421
+ const key = PILL_KEY[type];
3422
+ if (!key) return null;
3423
+ const values2 = rawValue.split("|").map((v) => v.trim()).filter(Boolean).map((v) => ({
3424
+ value: v.endsWith("*") ? v.slice(0, -1) : v,
3425
+ wildcard: v.endsWith("*")
3426
+ }));
3427
+ if (values2.length === 0) return null;
3428
+ return { key, negate: false, values: values2 };
3429
+ }
3430
+ function filterFragment(f) {
3431
+ const render = (v) => {
3432
+ const bare = /^[a-zA-Z0-9_-]+(:[a-zA-Z0-9_-]+)?$/.test(v.value);
3433
+ return `${bare ? v.value : `"${v.value}"`}${v.wildcard ? "*" : ""}`;
3434
+ };
3435
+ return `${f.negate ? "!" : ""}${f.key}:${f.values.map(render).join("|")}`;
3436
+ }
3437
+ function filterToPill(f, index) {
3438
+ if (f.negate) return null;
3439
+ const pillValue2 = f.values.map((v) => `${v.value}${v.wildcard ? "*" : ""}`).join("|");
3440
+ if (!pillValue2.trim()) return null;
3441
+ if (f.key === "source") {
3442
+ return restorePill(`c-source-${index}`, "source", pillValue2);
3443
+ }
3444
+ const builtin = KEY_PILL[f.key];
3445
+ if (builtin) {
3446
+ const value = builtin === "text" && f.values.length === 1 && /\s/.test(f.values[0].value) ? f.values[0].value : pillValue2;
3447
+ return restorePill(`c-${builtin}-${index}`, builtin, value);
3448
+ }
3449
+ const fragment = filterFragment(f);
3450
+ for (const slot of composerRegistry.getAllSlots()) {
3451
+ if (!slot.parseValue || !slot.formatValue) continue;
3452
+ const typed = slot.parseValue(pillValue2);
3453
+ if (typed !== void 0 && slot.wqlGenerator(typed) === fragment) {
3454
+ return restorePill(`c-${slot.type}-${index}`, slot.type, slot.formatValue(typed));
3455
+ }
3456
+ }
3457
+ return null;
3458
+ }
3459
+ function restorePill(id, type, value) {
3460
+ return { id, type, ...getClauseMeta(type), value };
3461
+ }
3462
+ function astToPills(ast) {
3463
+ if (ast.error) return null;
3464
+ if (isRowsQuery(ast)) {
3465
+ if (ast.window?.kind === "range") return null;
3466
+ if (ast.filters.some((f) => f.key === "source")) return null;
3467
+ const filterPills = [];
3468
+ for (let i = 0; i < ast.filters.length; i++) {
3469
+ const p = filterToPill(ast.filters[i], i);
3470
+ if (!p) return null;
3471
+ filterPills.push(p);
3472
+ }
3473
+ return [
3474
+ restorePill("c-source", "source", "rows"),
3475
+ restorePill("c-time", "time", windowPillValue(ast.window)),
3476
+ restorePill("c-output", "output", ast.outputType ?? "all"),
3477
+ ...filterPills
3478
+ ];
3479
+ }
3480
+ if (isFindQuery(ast)) {
3481
+ if (ast.window?.kind === "range") return null;
3482
+ const sourceFilter = ast.filters.find((f) => f.key === "source" && !f.negate);
3483
+ const nonIdentitySource = sourceFilter && !sourceFilter.values.every((v) => v.value === "all");
3484
+ if ((ast.target === "block" || ast.target === "effort") && nonIdentitySource) return null;
3485
+ const sourceValue = ast.target === "block" ? "blocks" : ast.target === "effort" ? "efforts" : !sourceFilter || sourceFilter.values.every((v) => v.value === "all") ? "notes" : sourceFilter.values.map((v) => v.value).join("|");
3486
+ const rest = ast.filters.filter((f) => f !== sourceFilter);
3487
+ const filterPills = [];
3488
+ for (let i = 0; i < rest.length; i++) {
3489
+ const p = filterToPill(rest[i], i);
3490
+ if (!p) return null;
3491
+ filterPills.push(p);
3492
+ }
3493
+ const pills = [
3494
+ restorePill("c-source", "source", sourceValue),
3495
+ restorePill("c-time", "time", windowPillValue(ast.window)),
3496
+ ...filterPills
3497
+ ];
3498
+ if (ast.join) {
3499
+ const j = ast.join;
3500
+ const head = serialize({
3501
+ family: "aggregate",
3502
+ raw: "",
3503
+ agg: j.agg,
3504
+ metric: j.metric,
3505
+ filters: j.filters,
3506
+ groupBy: []
3507
+ });
3508
+ pills.push(restorePill("c-where", "where", `${head} ${j.operator} ${j.threshold}`));
3509
+ }
3510
+ return pills;
3511
+ }
3512
+ if (isAggregateQuery(ast)) {
3513
+ if (ast.window?.kind === "range") return null;
3514
+ const filterPills = [];
3515
+ for (let i = 0; i < ast.filters.length; i++) {
3516
+ const p = filterToPill(ast.filters[i], i);
3517
+ if (!p) return null;
3518
+ filterPills.push(p);
3519
+ }
3520
+ const pills = [
3521
+ restorePill("c-source", "source", "metrics"),
3522
+ restorePill("c-agg", "agg", ast.agg),
3523
+ restorePill("c-metric", "metric", ast.metric),
3524
+ ...filterPills,
3525
+ ...ast.groupBy.map((d, i) => restorePill(`c-groupby-${i}`, "groupby", d))
3526
+ ];
3527
+ if (ast.rollup) pills.push(restorePill("c-rollup", "rollup", `${ast.rollup.size}${ast.rollup.unit}`));
3528
+ if (ast.displayUnit) pills.push(restorePill("c-unit", "unit", ast.displayUnit));
3529
+ if (ast.window) pills.push(restorePill("c-time", "time", windowPillValue(ast.window)));
3530
+ if (ast.join) {
3531
+ pills.push(
3532
+ restorePill(
3533
+ "c-where",
3534
+ "where",
3535
+ serialize({
3536
+ family: "find",
3537
+ raw: "",
3538
+ target: ast.join.target,
3539
+ filters: ast.join.filters,
3540
+ window: ast.join.last ? { kind: "relative", size: ast.join.last.size, unit: ast.join.last.unit } : void 0
3541
+ })
3542
+ )
3543
+ );
3544
+ }
3545
+ return pills;
3546
+ }
3547
+ return null;
3548
+ }
3549
+ function windowPillValue(w) {
3550
+ if (!w) return "all";
3551
+ return `last ${w.size}${w.unit}`;
3552
+ }
3553
+ function wqlToPills(wql2) {
3554
+ const direct = astToPills(parseQuery(wql2.trim()));
3555
+ if (direct) return direct;
3556
+ const probed = wql2.trim().replace(/^([a-zA-Z_]\w*):(\s*\{)/, "$1:__placeholder__$2");
3557
+ if (probed === wql2.trim()) return null;
3558
+ const salvaged = astToPills(parseQuery(probed));
3559
+ if (!salvaged) return null;
3560
+ return salvaged.map((p) => p.type === "metric" ? { ...p, value: "" } : p);
3561
+ }
3562
+ function timePillText(raw) {
3563
+ const v = raw.trim();
3564
+ if (!v || v === "all") return "";
3565
+ if (v.startsWith("last") || v.startsWith("from")) return v;
3566
+ return `last ${v}`;
3567
+ }
3568
+ function buildCandidateText(pills) {
3569
+ const source = pillValue(pills, "source", "notes");
3570
+ const filterParts = [];
3571
+ for (const pill of pills) {
3572
+ const v = pill.value.trim();
3573
+ if (!v) continue;
3574
+ const builtin = pillValueToFilter(pill.type, v);
3575
+ if (builtin) {
3576
+ filterParts.push(filterFragment(builtin));
3577
+ continue;
3578
+ }
3579
+ const def = composerRegistry.getSlot(pill.type);
3580
+ if (!def?.parseValue) continue;
3581
+ const typed = def.parseValue(v);
3582
+ if (typed === void 0) continue;
3583
+ const fragment = def.wqlGenerator(typed).trim();
3584
+ if (fragment) filterParts.push(fragment);
3585
+ }
3586
+ const timePill = pills.find((c) => c.type === "time");
3587
+ const timeText = timePill ? timePillText(timePill.value) : "";
3588
+ const wherePill = pills.find((c) => c.type === "where");
3589
+ const whereText = wherePill?.value.trim() ? `where ${wherePill.value.trim()}` : "";
3590
+ if (source === "rows") {
3591
+ const output = pillValue(pills, "output", "all") || "all";
3592
+ return [`rows:${output}{${filterParts.join(",")}}`, timeText].filter(Boolean).join(" ").trim();
3593
+ }
3594
+ if (sourcePlane(source) === "metrics") {
3595
+ const agg = pillValue(pills, "agg", "sum");
3596
+ const metric = pillValue(pills, "metric", "");
3597
+ const dims = pills.filter((c) => c.type === "groupby" && c.value.trim()).map((c) => c.value.trim());
3598
+ const rollup = pillValue(pills, "rollup", "");
3599
+ const unit = pillValue(pills, "unit", "");
3600
+ return [
3601
+ `${agg}:${metric}{${filterParts.join(",")}}`,
3602
+ dims.length ? `by {${dims.join(", ")}}` : "",
3603
+ rollup ? `.rollup(${rollup})` : "",
3604
+ unit ? `in ${unit}` : "",
3605
+ timeText,
3606
+ whereText
3607
+ ].filter(Boolean).join(" ").trim();
3608
+ }
3609
+ const target = source === "blocks" ? "block" : source === "efforts" ? "effort" : "note";
3610
+ const withSource = source === "notes" || source === "blocks" || source === "efforts" ? filterParts : [`source:${source}`, ...filterParts];
3611
+ const braces = withSource.length ? `{${withSource.join(",")}}` : "";
3612
+ return [`find:${target}${braces}`, timeText, whereText].filter(Boolean).join(" ").trim();
3613
+ }
3614
+ function pillsToAst(pills) {
3615
+ return parseQuery(buildCandidateText(pills));
3616
+ }
3617
+ var METRICS_HEAD_TYPES = /* @__PURE__ */ new Set(["agg", "metric", "groupby", "rollup", "unit"]);
3618
+ function pivotPills(pills, source) {
3619
+ const next = pills.filter((c) => !METRICS_HEAD_TYPES.has(c.type) && c.type !== "where").map((c) => c.type === "source" ? { ...c, value: source } : c);
3620
+ if (source === "metrics") {
3621
+ const sourceIdx = next.findIndex((c) => c.type === "source");
3622
+ const head = [];
3623
+ if (!next.some((c) => c.type === "agg")) head.push(restorePill("c-agg", "agg", "sum"));
3624
+ if (!next.some((c) => c.type === "metric")) head.push(restorePill("c-metric", "metric", ""));
3625
+ next.splice(sourceIdx >= 0 ? sourceIdx + 1 : next.length, 0, ...head);
3626
+ }
3627
+ if (source === "rows" && !next.some((c) => c.type === "output")) {
3628
+ const sourceIdx = next.findIndex((c) => c.type === "source");
3629
+ next.splice(sourceIdx >= 0 ? sourceIdx + 1 : next.length, 0, restorePill("c-output", "output", "all"));
3630
+ }
3631
+ return next;
3632
+ }
3633
+ function defaultPills() {
3634
+ return [
3635
+ restorePill("c-source", "source", "notes"),
3636
+ restorePill("c-time", "time", "last 2w")
3637
+ ];
3638
+ }
3639
+ function pillValue(pills, type, fallback = "") {
3640
+ return pills.find((c) => c.type === type)?.value?.trim() || fallback;
3641
+ }
3642
+
3643
+ // src/composer/diagnostics.ts
3661
3644
  function summarizeFind(ast) {
3662
3645
  const sourceFilter = ast.filters.find((f) => f.key === "source");
3663
3646
  const scope = sourceFilter ? sourceFilter.values.map((v) => v.value).join(",") : "all";
@@ -3689,21 +3672,21 @@ function customSlotError(clause) {
3689
3672
  if (parsed === void 0) return `Invalid ${custom.label} value`;
3690
3673
  return custom.validate ? custom.validate(parsed) : null;
3691
3674
  }
3692
- function diagnoseClauses(clauses) {
3693
- for (const clause of clauses) {
3694
- const error = customSlotError(clause);
3675
+ function diagnosePills(pills) {
3676
+ for (const pill of pills) {
3677
+ const error = customSlotError(pill);
3695
3678
  if (error) {
3696
3679
  return {
3697
3680
  valid: false,
3698
- wql: clausesToWql(clauses),
3681
+ wql: serialize(pillsToAst(pills)),
3699
3682
  ast: { family: "aggregate", raw: "", agg: "sum", metric: "", filters: [], groupBy: [], error },
3700
3683
  error,
3701
- offendingClauseId: clause.id
3684
+ offendingClauseId: pill.id
3702
3685
  };
3703
3686
  }
3704
3687
  }
3705
- const wql2 = clausesToWql(clauses);
3706
- const ast = parseQuery(wql2);
3688
+ const ast = pillsToAst(pills);
3689
+ const wql2 = serialize(ast);
3707
3690
  if (ast.error) {
3708
3691
  return {
3709
3692
  valid: false,
@@ -3831,10 +3814,9 @@ function useWqlStageCounts(ast, valid, execute, debounceMs = DEFAULT_DIAGNOSTICS
3831
3814
  return runnable ? stages : void 0;
3832
3815
  }
3833
3816
  function WqlComposer({
3834
- initialClauses,
3835
- clauses: controlledClauses,
3836
- onClausesChange,
3837
- onWqlChange,
3817
+ initialQuery,
3818
+ query: controlledQuery,
3819
+ onQueryChange,
3838
3820
  onValidationChange,
3839
3821
  onAstChange,
3840
3822
  onSubmit,
@@ -3848,52 +3830,91 @@ function WqlComposer({
3848
3830
  placeholder = "Type search term and press Enter...",
3849
3831
  className
3850
3832
  }) {
3851
- const [internalClauses, setInternalClauses] = useState(
3852
- () => initialClauses ?? defaultClauses()
3833
+ const [internalPills, setInternalPills] = useState(
3834
+ () => wqlToPills(initialQuery ?? "") ?? defaultPills()
3835
+ );
3836
+ const controlledPills = useMemo(
3837
+ () => controlledQuery === void 0 ? void 0 : wqlToPills(controlledQuery),
3838
+ [controlledQuery]
3853
3839
  );
3854
- const clauses = controlledClauses ?? internalClauses;
3840
+ const pills = controlledPills ?? internalPills;
3855
3841
  const hiddenTypes = useMemo(() => new Set(hiddenClauseTypes), [hiddenClauseTypes]);
3856
3842
  const [activeSlotIdx, setActiveSlotIdx] = useState(null);
3857
3843
  const [freeText, setFreeText] = useState("");
3858
3844
  const inputRef = useRef(null);
3845
+ const freeTextInitRef = useRef(null);
3846
+ useEffect(() => {
3847
+ if (controlledQuery === void 0) return;
3848
+ if (controlledPills === null) {
3849
+ if (freeTextInitRef.current !== controlledQuery) {
3850
+ freeTextInitRef.current = controlledQuery;
3851
+ setFreeText(controlledQuery);
3852
+ }
3853
+ } else if (freeTextInitRef.current !== null) {
3854
+ freeTextInitRef.current = null;
3855
+ setFreeText("");
3856
+ }
3857
+ }, [controlledQuery, controlledPills]);
3859
3858
  useEffect(() => {
3860
3859
  if (!autoFocus) return;
3861
3860
  const t = setTimeout(() => inputRef.current?.focus(), 0);
3862
3861
  return () => clearTimeout(t);
3863
3862
  }, [autoFocus]);
3864
- const setClauses = useCallback(
3863
+ const setPills = useCallback(
3865
3864
  (next) => {
3866
- if (controlledClauses === void 0) setInternalClauses(next);
3867
- onClausesChange?.(next);
3865
+ if (controlledQuery === void 0) setInternalPills(next);
3868
3866
  },
3869
- [controlledClauses, onClausesChange]
3867
+ [controlledQuery]
3870
3868
  );
3871
3869
  const registeredSlots = useComposerSlots();
3872
- const diagnostics = useMemo(() => diagnoseClauses(clauses), [clauses, registeredSlots]);
3873
- const callbacksRef = useRef({ onWqlChange, onValidationChange, onAstChange });
3874
- callbacksRef.current = { onWqlChange, onValidationChange, onAstChange };
3870
+ const rawEscape = controlledQuery !== void 0 && controlledPills === null;
3871
+ const diagnostics = useMemo(() => {
3872
+ if (rawEscape) {
3873
+ const ast = parseQuery(controlledQuery);
3874
+ return {
3875
+ valid: !ast.error,
3876
+ wql: controlledQuery,
3877
+ ast,
3878
+ error: ast.error
3879
+ };
3880
+ }
3881
+ return diagnosePills(pills);
3882
+ }, [rawEscape, controlledQuery, pills, registeredSlots]);
3883
+ const callbacksRef = useRef({ onQueryChange, onValidationChange, onAstChange });
3884
+ callbacksRef.current = { onQueryChange, onValidationChange, onAstChange };
3875
3885
  useEffect(() => {
3876
3886
  const validation = diagnostics.valid ? { valid: true } : { valid: false, error: diagnostics.error };
3877
- callbacksRef.current.onWqlChange?.(diagnostics.wql);
3887
+ if (controlledQuery === void 0) callbacksRef.current.onQueryChange?.(diagnostics.wql);
3878
3888
  callbacksRef.current.onAstChange?.(diagnostics.ast);
3879
3889
  callbacksRef.current.onValidationChange?.(validation);
3880
3890
  }, [diagnostics]);
3881
3891
  const stages = useWqlStageCounts(diagnostics.ast, diagnostics.valid, execute, debounceMs);
3882
- const offendingClause = diagnostics.offendingClauseId ? clauses.find((c) => c.id === diagnostics.offendingClauseId) : void 0;
3883
- const offendingLabel = offendingClause ? getClauseMeta(offendingClause.type).label : void 0;
3884
- const updateClause = (idx, patch) => {
3885
- const updated = clauses.map((c, i) => i === idx ? { ...c, ...patch } : c);
3886
- const edited = clauses[idx];
3892
+ const offendingPill = diagnostics.offendingClauseId ? pills.find((c) => c.id === diagnostics.offendingClauseId) : void 0;
3893
+ const offendingLabel = offendingPill ? getClauseMeta(offendingPill.type).label : void 0;
3894
+ const updatePill = (idx, patch) => {
3895
+ const updated = pills.map((c, i) => i === idx ? { ...c, ...patch } : c);
3896
+ const edited = pills[idx];
3887
3897
  if (edited?.type === "source" && patch.value !== void 0 && patch.value !== edited.value) {
3888
- setClauses(pivotClauses(updated, patch.value));
3898
+ setPills(pivotPills(updated, patch.value));
3899
+ emitIfControlled(pivotPills(updated, patch.value));
3889
3900
  return;
3890
3901
  }
3891
- setClauses(updated);
3902
+ setPills(updated);
3903
+ emitIfControlled(updated);
3892
3904
  };
3893
- const removeClause = (idx) => {
3894
- setClauses(clauses.filter((_, i) => i !== idx));
3905
+ const removePill = (idx) => {
3906
+ const next = pills.filter((_, i) => i !== idx);
3907
+ setPills(next);
3908
+ emitIfControlled(next);
3895
3909
  };
3896
- const makeClause = (type, value) => {
3910
+ const emitIfControlled = (next) => {
3911
+ if (controlledQuery !== void 0) {
3912
+ const nextAst = pillsToAst(next);
3913
+ const nextWql = serialize(nextAst);
3914
+ if (nextWql !== controlledQuery) callbacksRef.current.onQueryChange?.(nextWql);
3915
+ }
3916
+ };
3917
+ const makePill = (type, value) => {
3897
3918
  const meta = getClauseMeta(type);
3898
3919
  return {
3899
3920
  id: `c-${Date.now()}-${Math.random()}`,
@@ -3907,10 +3928,13 @@ function WqlComposer({
3907
3928
  const pending = useMemo(() => {
3908
3929
  const raw = freeText.trim();
3909
3930
  if (!raw) return null;
3910
- const restored = wqlToClauses(raw);
3911
- if (restored) {
3912
- const parsed = parseQuery(raw);
3913
- if (!("error" in parsed && parsed.error)) return { kind: "query", clauses: restored };
3931
+ const restored = wqlToPills(raw);
3932
+ if (restored) return { kind: "query", pills: restored };
3933
+ const parsed = parseQuery(raw);
3934
+ if (!parsed.error && /[:{]/.test(raw)) {
3935
+ return { kind: "raw", value: raw };
3936
+ }
3937
+ if (parsed.error && /[:{]/.test(raw)) {
3914
3938
  return { kind: "invalid", reason: String(parsed.error) };
3915
3939
  }
3916
3940
  const words = raw.match(/[a-zA-Z0-9_-]+/g);
@@ -3922,42 +3946,48 @@ function WqlComposer({
3922
3946
  }
3923
3947
  return { kind: "text", value: words[0] };
3924
3948
  }, [freeText]);
3925
- const addClause = (clause) => {
3926
- const type = clause.type;
3927
- const seed = type === "time" ? "last 2w" : type === "where" ? "sum:totalVolume{} > 5000" : type === "agg" ? "sum" : type === "groupby" ? "week" : type === "rollup" ? "1w" : clause.value;
3928
- setClauses([...clauses, { ...clause, value: seed }]);
3949
+ const addPill = (pill) => {
3950
+ const type = pill.type;
3951
+ const seed = type === "time" ? "last 2w" : type === "where" ? "sum:totalVolume{} > 5000" : type === "agg" ? "sum" : type === "groupby" ? "week" : type === "rollup" ? "1w" : pill.value;
3952
+ const next = [...pills, { ...pill, value: seed }];
3953
+ setPills(next);
3954
+ emitIfControlled(next);
3929
3955
  };
3930
- const addCalc = (clause) => {
3931
- const { type, value } = clause;
3956
+ const addCalc = (pill) => {
3957
+ const { type, value } = pill;
3932
3958
  if (type === "metric") {
3933
- if (clauses.some((c) => c.type === "metric")) return;
3959
+ if (pills.some((c) => c.type === "metric")) return;
3934
3960
  const afterIdx = Math.max(
3935
- clauses.findIndex((c) => c.type === "agg"),
3936
- clauses.findIndex((c) => c.type === "source")
3961
+ pills.findIndex((c) => c.type === "agg"),
3962
+ pills.findIndex((c) => c.type === "source")
3937
3963
  );
3938
- const next2 = [...clauses];
3939
- next2.splice(afterIdx + 1, 0, makeClause("metric", value));
3940
- setClauses(next2);
3964
+ const next2 = [...pills];
3965
+ next2.splice(afterIdx + 1, 0, makePill("metric", value));
3966
+ setPills(next2);
3967
+ emitIfControlled(next2);
3941
3968
  return;
3942
3969
  }
3943
3970
  if (type !== "agg") {
3944
- addClause(clause);
3971
+ addPill(pill);
3945
3972
  return;
3946
3973
  }
3947
3974
  const agg = value || "sum";
3948
- const existingIdx = clauses.findIndex((c) => c.type === "agg");
3975
+ const existingIdx = pills.findIndex((c) => c.type === "agg");
3949
3976
  if (existingIdx >= 0) {
3950
- updateClause(existingIdx, { value: agg });
3977
+ updatePill(existingIdx, { value: agg });
3951
3978
  return;
3952
3979
  }
3953
- if (sourcePlane(clauseValue(clauses, "source", "notes")) !== "metrics") {
3954
- setClauses(pivotClauses(clauses, "metrics").map((c) => c.type === "agg" ? { ...c, value: agg } : c));
3980
+ if (sourcePlane(pillValue(pills, "source", "notes")) !== "metrics") {
3981
+ const next2 = pivotPills(pills, "metrics").map((c) => c.type === "agg" ? { ...c, value: agg } : c);
3982
+ setPills(next2);
3983
+ emitIfControlled(next2);
3955
3984
  return;
3956
3985
  }
3957
- const sourceIdx = clauses.findIndex((c) => c.type === "source");
3958
- const next = [...clauses];
3959
- next.splice(sourceIdx + 1, 0, makeClause("agg", agg));
3960
- setClauses(next);
3986
+ const sourceIdx = pills.findIndex((c) => c.type === "source");
3987
+ const next = [...pills];
3988
+ next.splice(sourceIdx + 1, 0, makePill("agg", agg));
3989
+ setPills(next);
3990
+ emitIfControlled(next);
3961
3991
  };
3962
3992
  const handleKeyDown = (e) => {
3963
3993
  if (e.key !== "Enter") return;
@@ -3965,10 +3995,15 @@ function WqlComposer({
3965
3995
  e.preventDefault();
3966
3996
  e.stopPropagation();
3967
3997
  if (pending?.kind === "query") {
3968
- setClauses(pending.clauses);
3998
+ setPills(pending.pills);
3999
+ emitIfControlled(pending.pills);
3969
4000
  setFreeText("");
4001
+ } else if (pending?.kind === "raw") {
4002
+ onSubmit?.(pending.value);
3970
4003
  } else if (pending?.kind === "text") {
3971
- setClauses([...clauses, makeClause("text", pending.value)]);
4004
+ const next = [...pills, makePill("text", pending.value)];
4005
+ setPills(next);
4006
+ emitIfControlled(next);
3972
4007
  setFreeText("");
3973
4008
  }
3974
4009
  return;
@@ -3991,20 +4026,20 @@ function WqlComposer({
3991
4026
  "data-testid": "wql-composer",
3992
4027
  children: [
3993
4028
  /* @__PURE__ */ jsx(Command, { className: "size-4 text-amber-500 shrink-0 mr-0.5" }),
3994
- clauses.map(
3995
- (clause, idx) => hiddenTypes.has(clause.type) ? null : /* @__PURE__ */ jsx(
4029
+ pills.map(
4030
+ (pill, idx) => hiddenTypes.has(pill.type) ? null : /* @__PURE__ */ jsx(
3996
4031
  TokenSlotPill,
3997
4032
  {
3998
- clause,
4033
+ clause: pill,
3999
4034
  isActive: activeSlotIdx === idx,
4000
- invalid: diagnostics.offendingClauseId === clause.id,
4001
- invalidReason: diagnostics.offendingClauseId === clause.id ? diagnostics.error : void 0,
4035
+ invalid: diagnostics.offendingClauseId === pill.id,
4036
+ invalidReason: diagnostics.offendingClauseId === pill.id ? diagnostics.error : void 0,
4002
4037
  onClick: () => setActiveSlotIdx(idx),
4003
- onChange: (patch) => updateClause(idx, patch),
4004
- onRemove: () => removeClause(idx),
4038
+ onChange: (patch) => updatePill(idx, patch),
4039
+ onRemove: () => removePill(idx),
4005
4040
  compact: true
4006
4041
  },
4007
- clause.id
4042
+ pill.id
4008
4043
  )
4009
4044
  ),
4010
4045
  /* @__PURE__ */ jsx(
@@ -4035,6 +4070,7 @@ function WqlComposer({
4035
4070
  role: pending.kind === "invalid" ? "alert" : void 0,
4036
4071
  children: [
4037
4072
  pending.kind === "query" && "\u21B5 Use as query",
4073
+ pending.kind === "raw" && "\u21B5 Run query",
4038
4074
  pending.kind === "text" && `\u21B5 Search text: ${pending.value}`,
4039
4075
  pending.kind === "invalid" && pending.reason
4040
4076
  ]
@@ -4047,14 +4083,14 @@ function WqlComposer({
4047
4083
  offendingLabel,
4048
4084
  stages,
4049
4085
  actions: /* @__PURE__ */ jsxs(Fragment, { children: [
4050
- /* @__PURE__ */ jsx(AddCalcDropdown, { clauses, onAdd: addCalc }),
4051
- /* @__PURE__ */ jsx(AddFilterDropdown, { clauses, onAdd: addClause }),
4086
+ /* @__PURE__ */ jsx(AddCalcDropdown, { clauses: pills, onAdd: addCalc }),
4087
+ /* @__PURE__ */ jsx(AddFilterDropdown, { clauses: pills, onAdd: addPill }),
4052
4088
  diagnosticsActions
4053
4089
  ] })
4054
4090
  }
4055
4091
  ) : /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-1.5 px-1.5", "data-testid": "wql-add-row", children: [
4056
- /* @__PURE__ */ jsx(AddCalcDropdown, { clauses, onAdd: addCalc }),
4057
- /* @__PURE__ */ jsx(AddFilterDropdown, { clauses, onAdd: addClause }),
4092
+ /* @__PURE__ */ jsx(AddCalcDropdown, { clauses: pills, onAdd: addCalc }),
4093
+ /* @__PURE__ */ jsx(AddFilterDropdown, { clauses: pills, onAdd: addPill }),
4058
4094
  diagnosticsActions
4059
4095
  ] })
4060
4096
  ] });
@@ -4145,13 +4181,10 @@ function WqlQueryInspectorModal({
4145
4181
  subtitle = "Use the Omni-Composer to edit this block query.",
4146
4182
  executor
4147
4183
  }) {
4148
- const [clauses, setClauses] = useState([]);
4184
+ const [wql2, setWql] = useState(initialQuery);
4149
4185
  const [isValid, setIsValid] = useState(true);
4150
4186
  useEffect(() => {
4151
- if (isOpen) {
4152
- const restored = wqlToClauses(initialQuery);
4153
- setClauses(restored ?? defaultMetricsClauses());
4154
- }
4187
+ if (isOpen) setWql(initialQuery);
4155
4188
  }, [isOpen, initialQuery]);
4156
4189
  const diagnosticsExecutor = useCallback(
4157
4190
  (ast) => {
@@ -4169,8 +4202,7 @@ function WqlQueryInspectorModal({
4169
4202
  );
4170
4203
  const handleApply = () => {
4171
4204
  if (!isValid) return;
4172
- const nextWql = clausesToWql(clauses);
4173
- onApply(nextWql);
4205
+ onApply(wql2);
4174
4206
  onClose();
4175
4207
  };
4176
4208
  if (!isOpen) return null;
@@ -4201,15 +4233,15 @@ function WqlQueryInspectorModal({
4201
4233
  /* @__PURE__ */ jsx("div", { className: "p-6 overflow-y-auto space-y-4", children: /* @__PURE__ */ jsx(
4202
4234
  WqlComposer,
4203
4235
  {
4204
- clauses,
4205
- onClausesChange: setClauses,
4236
+ query: wql2,
4237
+ onQueryChange: setWql,
4206
4238
  onValidationChange: (v) => setIsValid(v.valid),
4207
4239
  execute: diagnosticsExecutor,
4208
4240
  showDiagnostics: true
4209
4241
  }
4210
4242
  ) }),
4211
4243
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-6 py-3 border-t border-border/80 bg-muted/10", children: [
4212
- /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground font-mono", children: clausesToWql(clauses) }),
4244
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground font-mono", children: wql2 }),
4213
4245
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
4214
4246
  /* @__PURE__ */ jsx(
4215
4247
  "button",
@@ -10379,6 +10411,6 @@ function editorPreset(optionsOrDialect = "markdown") {
10379
10411
  return extensions;
10380
10412
  }
10381
10413
 
10382
- export { AGG_OPTIONS, AddCalcDropdown, AddFilterDropdown, CLAUSE_META, CONTENT_SOURCES, ClausePopover, ComposerRegistry, CustomSlotPopover, DEFAULT_DIAGNOSTICS_DEBOUNCE_MS, DefaultFrontmatterWidget, GROUPBY_OPTIONS, GoalRings, METRIC_OPTIONS, MULTI_VALUE_TYPES, ProposedMetricBadge, QueryBlockView, QueryValue, ROLLUP_OPTIONS, RowsResultsChrome, RowsTable, SERIES_COLORS, SOURCE_OPTIONS, SUGGESTION_BINDINGS, StackedBar, TIME_OPTIONS, TokenSlotPill, TopList, UNIT_OPTIONS, WHERE_AGGREGATORS, WHERE_METRICS, WHERE_OPERATORS, WidgetChart, WidgetProblemBadge, WqlBars, WqlComposer, WqlDiagnosticsStrip, WqlEmptyState, WqlQueryInspectorModal, WqlTable, WqlTimeseries, ZoneDistribution, activeCursorSection, addRuntimePanel, blockContentId, blockTypesFromBlocks, catalogIdsFromBlocks, clauseToWql, clauseValue, clausesToWql, cn, compactNumber, composerRegistry, configureOverlayActions, cursorFocusExtension, dateRangeSlot, defaultClauses, defaultMetricsClauses, diagnoseClauses, dispatchAddRuntimePanel, dispatchExpandRuntimePanel, dispatchGutterHighlights, dispatchRemoveRuntimePanel, editingWidgetsField, editorPreset, editorTheme, embedPreviewDecorations, expandRuntimePanel, extractBlockQueries, fenceCompletion, findQueryBlockSection, findWorkoutErrors, forceSectionParse, formatTimestamp, frontmatterPreview, frontmatterPreviewField, getClauseMeta, getCursorFocusState, getOverlayActions, getSuggestionBinding, gutterHighlightsField, gutterUnified, handleFenceAutoWrap, hashCode, inlineButtonDecoration, invalidateSuggestions, lineIdsExtension, linkOpen, loadSuggestions, markdownSyntaxHiding, markdownTablePreview, mergeSeries, mergeTagSuggestions, navigationFacet, patchBlockQuery, pivotClauses, previewDecorations, queryBlockPreview, readSessionRpe, removeRuntimePanel, runtimePanelField, saveBlockQuerySource, sectionAtPos, sectionField, sectionGeometry, sessionQueryInsert, sessionQueryWql, setGutterHighlights, setMetricClause, setSuggestionBinding, smartIncrement, sourcePlane, summarizeAggregate, summarizeFind, tagsFromStaticBlocks, toggleWidgetEdit, tooltipTimestamp, urlAtPos, useChartShape, useComposerSlots, useSuggestions, useWqlStageCounts, widgetBlockPreview, wodAutoWrap, wodAutocompletion, wodEditorKeymap, wodLinter, wodOverlayPanel, workoutLintSource, wqlToClauses, wrapInTimeFence };
10383
- //# sourceMappingURL=chunk-S77JRUQM.mjs.map
10384
- //# sourceMappingURL=chunk-S77JRUQM.mjs.map
10414
+ export { AGG_OPTIONS, AddCalcDropdown, AddFilterDropdown, CONTENT_SOURCES, ClausePopover, ComposerRegistry, CustomSlotPopover, DEFAULT_DIAGNOSTICS_DEBOUNCE_MS, DefaultFrontmatterWidget, GROUPBY_OPTIONS, GoalRings, METRIC_OPTIONS, MULTI_VALUE_TYPES, ProposedMetricBadge, QueryBlockView, QueryValue, ROLLUP_OPTIONS, RowsResultsChrome, RowsTable, SERIES_COLORS, SOURCE_OPTIONS, SUGGESTION_BINDINGS, StackedBar, TIME_OPTIONS, TokenSlotPill, TopList, UNIT_OPTIONS, WHERE_AGGREGATORS, WHERE_METRICS, WHERE_OPERATORS, WidgetChart, WidgetProblemBadge, WqlBars, WqlComposer, WqlDiagnosticsStrip, WqlEmptyState, WqlQueryInspectorModal, WqlTable, WqlTimeseries, ZoneDistribution, activeCursorSection, addRuntimePanel, blockContentId, blockTypesFromBlocks, catalogIdsFromBlocks, cn, compactNumber, composerRegistry, configureOverlayActions, cursorFocusExtension, dateRangeSlot, dispatchAddRuntimePanel, dispatchExpandRuntimePanel, dispatchGutterHighlights, dispatchRemoveRuntimePanel, editingWidgetsField, editorPreset, editorTheme, embedPreviewDecorations, expandRuntimePanel, extractBlockQueries, fenceCompletion, findQueryBlockSection, findWorkoutErrors, forceSectionParse, formatTimestamp, frontmatterPreview, frontmatterPreviewField, getCursorFocusState, getOverlayActions, getSuggestionBinding, gutterHighlightsField, gutterUnified, handleFenceAutoWrap, hashCode, inlineButtonDecoration, invalidateSuggestions, lineIdsExtension, linkOpen, loadSuggestions, markdownSyntaxHiding, markdownTablePreview, mergeSeries, mergeTagSuggestions, navigationFacet, patchBlockQuery, previewDecorations, queryBlockPreview, readSessionRpe, removeRuntimePanel, runtimePanelField, saveBlockQuerySource, sectionAtPos, sectionField, sectionGeometry, sessionQueryInsert, sessionQueryWql, setGutterHighlights, setSuggestionBinding, smartIncrement, sourcePlane, summarizeAggregate, summarizeFind, tagsFromStaticBlocks, toggleWidgetEdit, tooltipTimestamp, urlAtPos, useChartShape, useComposerSlots, useSuggestions, useWqlStageCounts, widgetBlockPreview, wodAutoWrap, wodAutocompletion, wodEditorKeymap, wodLinter, wodOverlayPanel, workoutLintSource, wrapInTimeFence };
10415
+ //# sourceMappingURL=chunk-PZXX6GBK.mjs.map
10416
+ //# sourceMappingURL=chunk-PZXX6GBK.mjs.map