@bitcobblers/wod-wiki-ui 0.48.2176 → 0.49.2178
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/{chunk-6NFNCUZU.mjs → chunk-2XY6AZR6.mjs} +480 -162
- package/dist/chunk-2XY6AZR6.mjs.map +1 -0
- package/dist/extensions/index.cjs +477 -159
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.mjs +1 -1
- package/dist/index.cjs +483 -165
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -8
- package/dist/index.d.ts +15 -8
- package/dist/index.mjs +8 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/dist/chunk-6NFNCUZU.mjs.map +0 -1
|
@@ -5478,7 +5478,7 @@ function InlineClauseEditor({
|
|
|
5478
5478
|
const meta = getClauseMeta(clause2.type);
|
|
5479
5479
|
const current = clause2.value.trim();
|
|
5480
5480
|
const typedIdx = filteredItems.length;
|
|
5481
|
-
const shownValues = selectedValues
|
|
5481
|
+
const shownValues = selectedValues;
|
|
5482
5482
|
const reorder = (i, dir) => {
|
|
5483
5483
|
if (!onReorder) return;
|
|
5484
5484
|
const to = i + dir;
|
|
@@ -5490,24 +5490,15 @@ function InlineClauseEditor({
|
|
|
5490
5490
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5491
5491
|
"div",
|
|
5492
5492
|
{
|
|
5493
|
-
className: "
|
|
5493
|
+
className: "min-w-0 pt-0.5",
|
|
5494
5494
|
"data-testid": "wql-clause-editor",
|
|
5495
5495
|
"data-clause-type": clause2.type,
|
|
5496
5496
|
children: [
|
|
5497
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
5498
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "text-[11px]", children: meta.icon }),
|
|
5499
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[11px] font-semibold text-foreground font-mono", children: meta.label }),
|
|
5500
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "hidden sm:block ml-auto text-[10px] text-muted-foreground/70 font-mono truncate", children: [
|
|
5501
|
-
"\u2191\u2193 move \xB7 Enter ",
|
|
5502
|
-
isMulti ? "add/remove" : "set",
|
|
5503
|
-
" \xB7 Esc done \xB7 Tab exits"
|
|
5504
|
-
] })
|
|
5505
|
-
] }),
|
|
5506
|
-
shownValues.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("px-2 pb-1.5", isMulti && "border-b border-border/50"), children: [
|
|
5497
|
+
isMulti && shownValues.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-border/50 px-2 pb-1.5", children: [
|
|
5507
5498
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1.5 sm:gap-1 max-h-24 overflow-y-auto overscroll-contain touch-pan-y sm:max-h-none sm:overflow-visible", children: shownValues.map((v, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5508
5499
|
"span",
|
|
5509
5500
|
{
|
|
5510
|
-
className: "inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-primary/
|
|
5501
|
+
className: "inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-primary/15 text-primary text-xs sm:text-[10px] font-mono min-h-8 sm:min-h-0",
|
|
5511
5502
|
children: [
|
|
5512
5503
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-40 truncate", children: v }),
|
|
5513
5504
|
onReorder && shownValues.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -5557,7 +5548,7 @@ function InlineClauseEditor({
|
|
|
5557
5548
|
role: "listbox",
|
|
5558
5549
|
"aria-label": `${meta.label} options`,
|
|
5559
5550
|
"aria-multiselectable": isMulti || void 0,
|
|
5560
|
-
className: "max-h-[min(
|
|
5551
|
+
className: "max-h-[min(38svh,16rem)] sm:max-h-36 overflow-y-auto overscroll-contain touch-pan-y flex flex-col gap-0.5 pt-1",
|
|
5561
5552
|
children: [
|
|
5562
5553
|
canCommitTyped && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5563
5554
|
"button",
|
|
@@ -5571,19 +5562,19 @@ function InlineClauseEditor({
|
|
|
5571
5562
|
onClick: () => onCommitTyped(typedValue),
|
|
5572
5563
|
"data-testid": `clause-commit-typed-${clause2.type}`,
|
|
5573
5564
|
className: cn(
|
|
5574
|
-
"flex items-center justify-between px-2 py-2 sm:py-1 text-sm sm:text-xs text-left rounded hover:bg-muted/60 transition-colors font-mono min-h-
|
|
5575
|
-
highlightIdx === typedIdx && "bg-muted/
|
|
5565
|
+
"flex items-center justify-between px-2.5 py-2 sm:py-1.5 text-sm sm:text-xs text-left rounded-md hover:bg-muted/60 transition-colors font-mono min-h-11 sm:min-h-0",
|
|
5566
|
+
highlightIdx === typedIdx && "bg-muted/70 ring-1 ring-border"
|
|
5576
5567
|
),
|
|
5577
5568
|
children: [
|
|
5578
5569
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "truncate", children: [
|
|
5579
5570
|
"Search for ",
|
|
5580
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-semibold", children: [
|
|
5571
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-semibold text-foreground", children: [
|
|
5581
5572
|
"\u201C",
|
|
5582
5573
|
typedValue,
|
|
5583
5574
|
"\u201D"
|
|
5584
5575
|
] })
|
|
5585
5576
|
] }),
|
|
5586
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/60 ml-1 shrink-0", children: "\u21B5" })
|
|
5577
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/60 ml-1 shrink-0 font-sans text-xs", children: "\u21B5" })
|
|
5587
5578
|
]
|
|
5588
5579
|
}
|
|
5589
5580
|
),
|
|
@@ -5602,29 +5593,39 @@ function InlineClauseEditor({
|
|
|
5602
5593
|
onMouseEnter: () => onHighlight(idx),
|
|
5603
5594
|
onClick: () => onCommitValue(item.value),
|
|
5604
5595
|
className: cn(
|
|
5605
|
-
"flex items-center justify-between px-2 py-2 sm:py-1 text-sm sm:text-xs text-left rounded transition-colors
|
|
5606
|
-
active ? "bg-primary/
|
|
5607
|
-
selected && "text-primary"
|
|
5596
|
+
"flex items-center justify-between px-2.5 py-2 sm:py-1.5 text-sm sm:text-xs text-left rounded-md transition-colors min-h-11 sm:min-h-0",
|
|
5597
|
+
active ? "bg-primary/10 text-foreground font-medium" : "hover:bg-muted/60 text-muted-foreground hover:text-foreground",
|
|
5598
|
+
selected && "text-primary font-medium"
|
|
5608
5599
|
),
|
|
5609
5600
|
children: [
|
|
5610
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5611
|
-
|
|
5601
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline justify-between gap-2 min-w-0 flex-1", children: [
|
|
5602
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: item.label }),
|
|
5603
|
+
item.label !== item.value && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "font-mono text-[11px] text-muted-foreground/70 shrink-0", children: item.value })
|
|
5604
|
+
] }),
|
|
5605
|
+
selected && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-3.5 h-3.5 text-primary shrink-0 ml-1.5" })
|
|
5612
5606
|
]
|
|
5613
5607
|
},
|
|
5614
5608
|
item.value
|
|
5615
5609
|
);
|
|
5616
5610
|
}),
|
|
5617
|
-
emptyText && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-2
|
|
5611
|
+
emptyText && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2.5 py-2 text-sm sm:text-xs text-muted-foreground italic", children: emptyText })
|
|
5618
5612
|
]
|
|
5619
5613
|
}
|
|
5620
5614
|
),
|
|
5621
|
-
|
|
5615
|
+
(filteredItems.length > 0 || canCommitTyped) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden sm:flex items-center justify-between px-2 pt-2 text-[10px] text-muted-foreground/70 font-mono border-t border-border/40 mt-1", children: [
|
|
5616
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
5617
|
+
"\u2191\u2193 choose \xB7 Enter ",
|
|
5618
|
+
isMulti ? "toggle" : "set"
|
|
5619
|
+
] }),
|
|
5620
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Tab next segment \xB7 Esc close" })
|
|
5621
|
+
] }),
|
|
5622
|
+
isMulti && onDone && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-2 flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5622
5623
|
"button",
|
|
5623
5624
|
{
|
|
5624
5625
|
type: "button",
|
|
5625
5626
|
onClick: onDone,
|
|
5626
5627
|
"data-testid": "wql-clause-editor-done",
|
|
5627
|
-
className: "inline-flex w-full sm:w-auto items-center justify-center min-h-
|
|
5628
|
+
className: "inline-flex w-full sm:w-auto items-center justify-center min-h-10 sm:min-h-7 px-3 rounded-md bg-primary text-primary-foreground text-xs font-semibold hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
5628
5629
|
children: [
|
|
5629
5630
|
"Done",
|
|
5630
5631
|
shownValues.length > 0 ? ` \xB7 ${shownValues.length} selected` : ""
|
|
@@ -5663,7 +5664,11 @@ var STATIC_OPTIONS = {
|
|
|
5663
5664
|
groupby: GROUPBY_OPTIONS,
|
|
5664
5665
|
metric: METRIC_OPTIONS,
|
|
5665
5666
|
unit: UNIT_OPTIONS,
|
|
5666
|
-
intensity: wodWikiWql.WQL_INTENSITY_TIERS.map((v) => ({ value: v, label: v }))
|
|
5667
|
+
intensity: wodWikiWql.WQL_INTENSITY_TIERS.map((v) => ({ value: v, label: v })),
|
|
5668
|
+
subscribed: [
|
|
5669
|
+
{ value: "true", label: "Subscribed" },
|
|
5670
|
+
{ value: "false", label: "All / unsubscribed" }
|
|
5671
|
+
]
|
|
5667
5672
|
};
|
|
5668
5673
|
var CANONICAL_BLOCK_TYPES = ["wod", "query", "widget", "embed"];
|
|
5669
5674
|
function canonicalSuggestionItems(values2) {
|
|
@@ -5909,7 +5914,7 @@ function WqlDiagnosticsStrip({
|
|
|
5909
5914
|
"aria-live": "polite",
|
|
5910
5915
|
className: cn(
|
|
5911
5916
|
"flex flex-wrap items-center justify-between gap-x-4 gap-y-1.5 px-3 py-1.5 text-xs font-mono transition-colors",
|
|
5912
|
-
header ? valid ? "border-b border-
|
|
5917
|
+
header ? valid ? "border-b border-border/60 bg-muted/20 text-muted-foreground" : "border-b border-destructive/40 bg-destructive/5 text-destructive" : cn(
|
|
5913
5918
|
"rounded-lg border",
|
|
5914
5919
|
valid ? "bg-muted/30 border-border text-muted-foreground" : "bg-destructive/5 border-destructive/30 text-destructive"
|
|
5915
5920
|
),
|
|
@@ -6236,23 +6241,128 @@ var completionIcons = {
|
|
|
6236
6241
|
value: server.renderToStaticMarkup(React2.createElement(lucideReact.Tag, { size: 16 }))
|
|
6237
6242
|
};
|
|
6238
6243
|
var SLOT_NODES = { Head: true, Filter: true, TagValue: true, Rollup: true };
|
|
6244
|
+
var activeSegmentEffect = state.StateEffect.define();
|
|
6245
|
+
var activeSegmentField = state.StateField.define({
|
|
6246
|
+
create: () => view.Decoration.none,
|
|
6247
|
+
update(decorations, transaction) {
|
|
6248
|
+
const mapped = decorations.map(transaction.changes);
|
|
6249
|
+
for (const effect of transaction.effects) {
|
|
6250
|
+
if (!effect.is(activeSegmentEffect)) continue;
|
|
6251
|
+
const range = effect.value;
|
|
6252
|
+
if (!range || range.from >= range.to) return view.Decoration.none;
|
|
6253
|
+
return view.Decoration.set([view.Decoration.mark({ class: "wql-active-segment" }).range(range.from, range.to)]);
|
|
6254
|
+
}
|
|
6255
|
+
return mapped;
|
|
6256
|
+
},
|
|
6257
|
+
provide: (field) => view.EditorView.decorations.from(field)
|
|
6258
|
+
});
|
|
6259
|
+
function findClauseRange(state, clause2) {
|
|
6260
|
+
if (!clause2) return void 0;
|
|
6261
|
+
let range;
|
|
6262
|
+
const tree = language.syntaxTree(state);
|
|
6263
|
+
if (clause2.filterIndex !== void 0) {
|
|
6264
|
+
let index = 0;
|
|
6265
|
+
tree.iterate({
|
|
6266
|
+
enter: (node) => {
|
|
6267
|
+
if (node.name === "Filter") {
|
|
6268
|
+
if (index === clause2.filterIndex) {
|
|
6269
|
+
range = { from: node.from, to: node.to };
|
|
6270
|
+
return false;
|
|
6271
|
+
}
|
|
6272
|
+
index++;
|
|
6273
|
+
}
|
|
6274
|
+
return true;
|
|
6275
|
+
}
|
|
6276
|
+
});
|
|
6277
|
+
return range;
|
|
6278
|
+
}
|
|
6279
|
+
if (["kind", "target", "agg", "metric"].includes(clause2.type)) {
|
|
6280
|
+
tree.iterate({
|
|
6281
|
+
enter: (node) => {
|
|
6282
|
+
if (node.name === "Head") {
|
|
6283
|
+
range = { from: node.from, to: node.to };
|
|
6284
|
+
return false;
|
|
6285
|
+
}
|
|
6286
|
+
return true;
|
|
6287
|
+
}
|
|
6288
|
+
});
|
|
6289
|
+
return range;
|
|
6290
|
+
}
|
|
6291
|
+
if (clause2.type === "groupby") {
|
|
6292
|
+
tree.iterate({
|
|
6293
|
+
enter: (node) => {
|
|
6294
|
+
if (node.name === "GroupBy") {
|
|
6295
|
+
range = { from: node.from, to: node.to };
|
|
6296
|
+
return false;
|
|
6297
|
+
}
|
|
6298
|
+
return true;
|
|
6299
|
+
}
|
|
6300
|
+
});
|
|
6301
|
+
return range;
|
|
6302
|
+
}
|
|
6303
|
+
if (clause2.type === "rollup") {
|
|
6304
|
+
tree.iterate({
|
|
6305
|
+
enter: (node) => {
|
|
6306
|
+
if (node.name === "Rollup") {
|
|
6307
|
+
range = { from: node.from, to: node.to };
|
|
6308
|
+
return false;
|
|
6309
|
+
}
|
|
6310
|
+
return true;
|
|
6311
|
+
}
|
|
6312
|
+
});
|
|
6313
|
+
return range;
|
|
6314
|
+
}
|
|
6315
|
+
if (clause2.type === "time") {
|
|
6316
|
+
const doc = state.doc.toString();
|
|
6317
|
+
const match = /\b(last\s+\d+[dw]|from\s+\S+(?:\s+to\s+\S+)?)/i.exec(doc);
|
|
6318
|
+
if (match) return { from: match.index, to: match.index + match[0].length };
|
|
6319
|
+
}
|
|
6320
|
+
return void 0;
|
|
6321
|
+
}
|
|
6239
6322
|
function slotPositions(state) {
|
|
6240
6323
|
const slots = [];
|
|
6241
6324
|
language.syntaxTree(state).iterate({
|
|
6242
6325
|
enter: (node) => {
|
|
6243
6326
|
if (SLOT_NODES[node.name]) slots.push(node.from);
|
|
6244
|
-
else if (node.name === "Word" && node.node.parent?.name
|
|
6327
|
+
else if (node.name === "Word" && ["GroupBy", "Dimension"].includes(node.node.parent?.name ?? "")) slots.push(node.from);
|
|
6245
6328
|
return true;
|
|
6246
6329
|
}
|
|
6247
6330
|
});
|
|
6248
6331
|
return slots.sort((a, b) => a - b);
|
|
6249
6332
|
}
|
|
6250
|
-
function
|
|
6333
|
+
function activateSlot(view, position, onActivate) {
|
|
6334
|
+
if (!onActivate) return;
|
|
6335
|
+
let node = language.syntaxTree(view.state).resolveInner(position, 1);
|
|
6336
|
+
while (node.parent && !["Head", "Filter", "GroupBy", "Rollup"].includes(node.name)) node = node.parent;
|
|
6337
|
+
if (!["Head", "Filter", "GroupBy", "Rollup"].includes(node.name)) return;
|
|
6338
|
+
let filterIndex;
|
|
6339
|
+
if (node.name === "Filter") {
|
|
6340
|
+
filterIndex = 0;
|
|
6341
|
+
language.syntaxTree(view.state).iterate({
|
|
6342
|
+
enter: (candidate) => {
|
|
6343
|
+
if (candidate.name === "Filter") {
|
|
6344
|
+
if (candidate.from === node.from) return false;
|
|
6345
|
+
if (candidate.from < node.from) filterIndex += 1;
|
|
6346
|
+
}
|
|
6347
|
+
return true;
|
|
6348
|
+
}
|
|
6349
|
+
});
|
|
6350
|
+
}
|
|
6351
|
+
let text = view.state.sliceDoc(node.from, node.to);
|
|
6352
|
+
if (node.name === "Head") {
|
|
6353
|
+
const line = view.state.doc.lineAt(position);
|
|
6354
|
+
const word = Array.from(line.text.matchAll(/[\w.*-]+/g)).find((match) => line.from + match.index <= position && position <= line.from + match.index + match[0].length);
|
|
6355
|
+
if (word) text = word[0];
|
|
6356
|
+
}
|
|
6357
|
+
onActivate({ node: node.name, filterIndex, from: node.from, to: node.to, text });
|
|
6358
|
+
}
|
|
6359
|
+
function advanceSlot(view, dir, onActivate) {
|
|
6251
6360
|
const head = view.state.selection.main.head;
|
|
6252
6361
|
const slots = slotPositions(view.state);
|
|
6253
6362
|
const next = dir > 0 ? slots.find((slot) => slot > head) : [...slots].reverse().find((slot) => slot < head);
|
|
6254
6363
|
if (next === void 0) return false;
|
|
6255
6364
|
view.dispatch({ selection: { anchor: next }, scrollIntoView: true });
|
|
6365
|
+
activateSlot(view, next, onActivate);
|
|
6256
6366
|
return true;
|
|
6257
6367
|
}
|
|
6258
6368
|
function wqlLint(view) {
|
|
@@ -6295,7 +6405,7 @@ function wqlLint(view) {
|
|
|
6295
6405
|
});
|
|
6296
6406
|
return out;
|
|
6297
6407
|
}
|
|
6298
|
-
function wqlEditorKeymap(onSubmit, onEscape) {
|
|
6408
|
+
function wqlEditorKeymap(onSubmit, onEscape, onSlotActivate) {
|
|
6299
6409
|
return [
|
|
6300
6410
|
{ key: "Mod-Enter", run: () => {
|
|
6301
6411
|
onSubmit();
|
|
@@ -6319,7 +6429,7 @@ function wqlEditorKeymap(onSubmit, onEscape) {
|
|
|
6319
6429
|
run: (view) => {
|
|
6320
6430
|
if (view.compositionStarted) return false;
|
|
6321
6431
|
const accepted = autocomplete.acceptCompletion(view);
|
|
6322
|
-
return advanceSlot(view, 1) || accepted;
|
|
6432
|
+
return advanceSlot(view, 1, onSlotActivate) || accepted;
|
|
6323
6433
|
}
|
|
6324
6434
|
},
|
|
6325
6435
|
{
|
|
@@ -6327,7 +6437,7 @@ function wqlEditorKeymap(onSubmit, onEscape) {
|
|
|
6327
6437
|
run: (view) => {
|
|
6328
6438
|
if (view.compositionStarted) return false;
|
|
6329
6439
|
const accepted = autocomplete.acceptCompletion(view);
|
|
6330
|
-
return advanceSlot(view, -1) || accepted;
|
|
6440
|
+
return advanceSlot(view, -1, onSlotActivate) || accepted;
|
|
6331
6441
|
}
|
|
6332
6442
|
},
|
|
6333
6443
|
{
|
|
@@ -6346,11 +6456,11 @@ function wqlEditorKeymap(onSubmit, onEscape) {
|
|
|
6346
6456
|
...commands.historyKeymap
|
|
6347
6457
|
];
|
|
6348
6458
|
}
|
|
6349
|
-
function WqlTextEditor({ value, onChange, onSubmit, onEscape, placeholder, autoFocus = false, dense = false }) {
|
|
6459
|
+
function WqlTextEditor({ value, onChange, onSubmit, onEscape, placeholder, autoFocus = false, dense = false, onSlotActivate, activeRange, activeClause, className }) {
|
|
6350
6460
|
const host = React2.useRef(null);
|
|
6351
6461
|
const view$1 = React2.useRef(void 0);
|
|
6352
|
-
const callbacks = React2.useRef({ onChange, onSubmit, onEscape });
|
|
6353
|
-
callbacks.current = { onChange, onSubmit, onEscape };
|
|
6462
|
+
const callbacks = React2.useRef({ onChange, onSubmit, onEscape, onSlotActivate });
|
|
6463
|
+
callbacks.current = { onChange, onSubmit, onEscape, onSlotActivate };
|
|
6354
6464
|
const replacing = React2.useRef(false);
|
|
6355
6465
|
const initialValue = React2.useRef(value);
|
|
6356
6466
|
React2.useEffect(() => {
|
|
@@ -6367,6 +6477,7 @@ function WqlTextEditor({ value, onChange, onSubmit, onEscape, placeholder, autoF
|
|
|
6367
6477
|
language.syntaxHighlighting(wodWikiWql.wqlHighlightStyle),
|
|
6368
6478
|
commands.history(),
|
|
6369
6479
|
view.EditorView.lineWrapping,
|
|
6480
|
+
activeSegmentField,
|
|
6370
6481
|
...placeholder ? [view.placeholder(placeholder)] : [],
|
|
6371
6482
|
view.EditorView.contentAttributes.of({ "aria-label": "WQL", "data-testid": "wql-text-input" }),
|
|
6372
6483
|
autocomplete.autocompletion({
|
|
@@ -6387,11 +6498,12 @@ function WqlTextEditor({ value, onChange, onSubmit, onEscape, placeholder, autoF
|
|
|
6387
6498
|
lint.linter(wqlLint),
|
|
6388
6499
|
view.keymap.of(wqlEditorKeymap(
|
|
6389
6500
|
() => callbacks.current.onSubmit(),
|
|
6390
|
-
() => callbacks.current.onEscape()
|
|
6501
|
+
() => callbacks.current.onEscape(),
|
|
6502
|
+
(slot) => callbacks.current.onSlotActivate?.(slot)
|
|
6391
6503
|
)),
|
|
6392
6504
|
view.EditorView.domEventHandlers({
|
|
6393
|
-
//
|
|
6394
|
-
//
|
|
6505
|
+
// Host composers open the contextual writer; standalone editors
|
|
6506
|
+
// retain token selection and in-row completion.
|
|
6395
6507
|
mouseup: (event, editor2) => {
|
|
6396
6508
|
if (event.button !== 0) return false;
|
|
6397
6509
|
let { from, to } = editor2.state.selection.main;
|
|
@@ -6402,11 +6514,18 @@ function WqlTextEditor({ value, onChange, onSubmit, onEscape, placeholder, autoF
|
|
|
6402
6514
|
from = line.from + word.index;
|
|
6403
6515
|
to = from + word[0].length;
|
|
6404
6516
|
let node = language.syntaxTree(editor2.state).resolveInner(to, -1);
|
|
6405
|
-
while (node.parent && !["Head", "Filter"].includes(node.name)) node = node.parent;
|
|
6406
|
-
if (!["Head", "Filter"].includes(node.name)) return false;
|
|
6407
|
-
|
|
6517
|
+
while (node.parent && !["Head", "Filter", "GroupBy", "Rollup"].includes(node.name)) node = node.parent;
|
|
6518
|
+
if (!["Head", "Filter", "GroupBy", "Rollup"].includes(node.name)) return false;
|
|
6519
|
+
if (!callbacks.current.onSlotActivate) {
|
|
6520
|
+
editor2.dispatch({ selection: { anchor: from, head: to } });
|
|
6521
|
+
}
|
|
6522
|
+
}
|
|
6523
|
+
if (callbacks.current.onSlotActivate) {
|
|
6524
|
+
autocomplete.closeCompletion(editor2);
|
|
6525
|
+
activateSlot(editor2, from, (slot) => callbacks.current.onSlotActivate?.(slot));
|
|
6526
|
+
} else {
|
|
6527
|
+
autocomplete.startCompletion(editor2);
|
|
6408
6528
|
}
|
|
6409
|
-
autocomplete.startCompletion(editor2);
|
|
6410
6529
|
return false;
|
|
6411
6530
|
},
|
|
6412
6531
|
keydown: (event, editor2) => {
|
|
@@ -6426,7 +6545,8 @@ function WqlTextEditor({ value, onChange, onSubmit, onEscape, placeholder, autoF
|
|
|
6426
6545
|
'.cm-line span[class*="tok-"]:hover, .cm-line span[class^="tok-"]:hover': { fontWeight: "700", textShadow: "0 0 0.5px currentColor", cursor: "pointer" },
|
|
6427
6546
|
".cm-scroller": { overflow: "auto" },
|
|
6428
6547
|
".cm-placeholder": { color: "hsl(var(--muted-foreground))" },
|
|
6429
|
-
".wql-completion-icon": { display: "inline-flex", flexShrink: "0", color: "hsl(var(--primary))" }
|
|
6548
|
+
".wql-completion-icon": { display: "inline-flex", flexShrink: "0", color: "hsl(var(--primary))" },
|
|
6549
|
+
".wql-active-segment": { backgroundColor: "hsl(var(--primary) / 0.16)", boxShadow: "inset 0 -2px hsl(var(--primary))", borderRadius: "4px", padding: "1px 2px", margin: "0 -2px", fontWeight: "600" }
|
|
6430
6550
|
}),
|
|
6431
6551
|
autocompleteTooltipTheme
|
|
6432
6552
|
]
|
|
@@ -6446,7 +6566,13 @@ function WqlTextEditor({ value, onChange, onSubmit, onEscape, placeholder, autoF
|
|
|
6446
6566
|
editor.dispatch({ changes: { from: 0, to: editor.state.doc.length, insert: value } });
|
|
6447
6567
|
replacing.current = false;
|
|
6448
6568
|
}, [value]);
|
|
6449
|
-
|
|
6569
|
+
React2.useEffect(() => {
|
|
6570
|
+
const editor = view$1.current;
|
|
6571
|
+
if (!editor) return;
|
|
6572
|
+
const resolvedRange = activeRange ?? findClauseRange(editor.state, activeClause);
|
|
6573
|
+
editor.dispatch({ effects: activeSegmentEffect.of(resolvedRange ?? null) });
|
|
6574
|
+
}, [activeRange, activeClause, value]);
|
|
6575
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: host, className: className ?? "min-w-0 w-full rounded-lg border border-border bg-background focus-within:ring-2 focus-within:ring-ring", "data-testid": "wql-text-editor" });
|
|
6450
6576
|
}
|
|
6451
6577
|
function WqlComposer({
|
|
6452
6578
|
initialQuery,
|
|
@@ -6468,7 +6594,8 @@ function WqlComposer({
|
|
|
6468
6594
|
preferredChoices,
|
|
6469
6595
|
autoFocus = false,
|
|
6470
6596
|
placeholder = "Search text or enter WQL",
|
|
6471
|
-
className
|
|
6597
|
+
className,
|
|
6598
|
+
segmentEditRequest
|
|
6472
6599
|
}) {
|
|
6473
6600
|
const [desktop, setDesktop] = React2.useState(false);
|
|
6474
6601
|
const [base, setBase] = React2.useState(query ?? initialQuery ?? ":note");
|
|
@@ -6550,7 +6677,7 @@ function WqlComposer({
|
|
|
6550
6677
|
}, [autoFocus]);
|
|
6551
6678
|
React2.useEffect(() => {
|
|
6552
6679
|
if (active.kind === "value") pickerRef.current?.focus();
|
|
6553
|
-
}, [active
|
|
6680
|
+
}, [active]);
|
|
6554
6681
|
React2.useEffect(() => {
|
|
6555
6682
|
if (highlight >= 0) document.getElementById(`${listId}-option-${highlight}`)?.scrollIntoView?.({ block: "nearest" });
|
|
6556
6683
|
}, [highlight, listId]);
|
|
@@ -6576,14 +6703,14 @@ function WqlComposer({
|
|
|
6576
6703
|
if (openerRef.current?.isConnected) openerRef.current.focus();
|
|
6577
6704
|
else inputRef.current?.focus();
|
|
6578
6705
|
};
|
|
6579
|
-
const openEditor = (clause2) => {
|
|
6706
|
+
const openEditor = (clause2, range) => {
|
|
6580
6707
|
if (pending && currentRef.current.valid) commit(currentRef.current);
|
|
6581
6708
|
openerRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
6582
6709
|
if (clause2.type === "where" || clause2.type === "pipes") {
|
|
6583
6710
|
setActive({ kind: "wql" });
|
|
6584
6711
|
commit(currentRef.current);
|
|
6585
6712
|
} else {
|
|
6586
|
-
setActive({ kind: "value", clause: clause2 });
|
|
6713
|
+
setActive({ kind: "value", clause: clause2, range });
|
|
6587
6714
|
setSearch("");
|
|
6588
6715
|
}
|
|
6589
6716
|
setHighlight(-1);
|
|
@@ -6594,6 +6721,24 @@ function WqlComposer({
|
|
|
6594
6721
|
if (pending) commit(resolveQueryDraft(base));
|
|
6595
6722
|
openEditor(existing ?? { id: `new-${type}`, type, ...getClauseMeta(type), value: "" });
|
|
6596
6723
|
};
|
|
6724
|
+
const openFieldRef = React2.useRef(openField);
|
|
6725
|
+
openFieldRef.current = openField;
|
|
6726
|
+
React2.useEffect(() => {
|
|
6727
|
+
if (segmentEditRequest) openFieldRef.current(segmentEditRequest.type);
|
|
6728
|
+
}, [segmentEditRequest]);
|
|
6729
|
+
const activateWqlSlot = (slot) => {
|
|
6730
|
+
const clause2 = slot.filterIndex !== void 0 ? pills.find((pill) => pill.filterIndex === slot.filterIndex) : slot.node === "GroupBy" ? pills.find((pill) => pill.type === "groupby") : slot.node === "Rollup" ? pills.find((pill) => pill.type === "rollup") : slot.node === "Head" ? pills.find((pill) => ["kind", "target", "agg", "metric"].includes(pill.type) && pill.value === slot.text) : void 0;
|
|
6731
|
+
if (clause2) openEditor(clause2, { from: slot.from, to: slot.to });
|
|
6732
|
+
};
|
|
6733
|
+
const moveEditor = (direction) => {
|
|
6734
|
+
if (active.kind !== "value") return false;
|
|
6735
|
+
const visible = pills.filter((pill) => !hidden.has(pill.type));
|
|
6736
|
+
const index = visible.findIndex((pill) => pill.id === active.clause.id);
|
|
6737
|
+
const next = visible[index + direction];
|
|
6738
|
+
if (!next) return false;
|
|
6739
|
+
openEditor(next);
|
|
6740
|
+
return true;
|
|
6741
|
+
};
|
|
6597
6742
|
const updateClause = (clause2, value) => {
|
|
6598
6743
|
if (clause2.type === "kind" || clause2.type === "target") {
|
|
6599
6744
|
const next2 = pivotQuery(currentRef.current.wql, clause2.type, value ?? "");
|
|
@@ -6645,6 +6790,13 @@ function WqlComposer({
|
|
|
6645
6790
|
onSubmit?.(draft.wql);
|
|
6646
6791
|
};
|
|
6647
6792
|
const handleKeys = (event) => {
|
|
6793
|
+
if (active.kind === "value" && event.key === "Tab" && !event.nativeEvent.isComposing) {
|
|
6794
|
+
if (moveEditor(event.shiftKey ? -1 : 1)) {
|
|
6795
|
+
event.preventDefault();
|
|
6796
|
+
event.stopPropagation();
|
|
6797
|
+
}
|
|
6798
|
+
return;
|
|
6799
|
+
}
|
|
6648
6800
|
if (event.nativeEvent.isComposing) return;
|
|
6649
6801
|
if (event.key === "Enter" && (event.ctrlKey || event.metaKey)) {
|
|
6650
6802
|
event.preventDefault();
|
|
@@ -6709,119 +6861,285 @@ function WqlComposer({
|
|
|
6709
6861
|
diagnosticsActions
|
|
6710
6862
|
] });
|
|
6711
6863
|
const diagnostics = { ...resolved, valid: resolved.valid && !error, error: error ?? resolved.error };
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
commit(resolveQueryDraft(undo));
|
|
6751
|
-
setUndo(void 0);
|
|
6752
|
-
}, className: cn("rounded-lg", desktop && compact ? "min-h-9 px-2.5 text-xs text-muted-foreground hover:text-foreground" : "min-h-12 px-3"), children: "Undo removal" })
|
|
6753
|
-
] }),
|
|
6754
|
-
active.kind === "value" && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-testid": "wql-field-picker", className: "min-w-0 rounded-xl border border-border p-2 focus-within:ring-2 focus-within:ring-ring", onKeyDown: (event) => {
|
|
6755
|
-
if (event.key === "Escape" || event.key === "Enter" && (event.ctrlKey || event.metaKey)) handleKeys(event);
|
|
6756
|
-
}, children: [
|
|
6757
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: closeEditor, className: "min-h-12 px-3", children: "Back" }),
|
|
6758
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block text-sm", children: [
|
|
6759
|
-
"Search ",
|
|
6760
|
-
getClauseMeta(active.clause.type).label,
|
|
6761
|
-
/* @__PURE__ */ jsxRuntime.jsx("input", { ref: pickerRef, type: "search", role: "combobox", "aria-label": `Search ${getClauseMeta(active.clause.type).label}`, "aria-controls": listId, "aria-expanded": "true", "aria-activedescendant": highlight >= 0 ? `${listId}-option-${highlight}` : void 0, value: search, onChange: (event) => {
|
|
6762
|
-
setSearch(event.target.value);
|
|
6763
|
-
setHighlight(-1);
|
|
6764
|
-
setError(void 0);
|
|
6765
|
-
}, onKeyDown: handleKeys, className: "min-h-12 w-full rounded border border-border bg-background px-3 text-base", "data-testid": "wql-picker-search" })
|
|
6766
|
-
] }),
|
|
6767
|
-
active.kind === "value" && active.clause.filterIndex !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
6768
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex min-h-12 items-center gap-2", children: [
|
|
6769
|
-
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: active.clause.negate ?? false, onChange: (event) => updateClause({ ...active.clause, negate: event.target.checked }, active.clause.value) }),
|
|
6770
|
-
"Exclude"
|
|
6864
|
+
const visiblePills = pills.filter((pill) => !hidden.has(pill.type));
|
|
6865
|
+
const activePillIndex = active.kind === "value" ? visiblePills.findIndex((pill) => pill.id === active.clause.id) : -1;
|
|
6866
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6867
|
+
"div",
|
|
6868
|
+
{
|
|
6869
|
+
className: cn(
|
|
6870
|
+
"min-w-0",
|
|
6871
|
+
compact ? "flex flex-col overflow-hidden rounded-xl border border-border bg-card shadow-xs transition-shadow focus-within:ring-2 focus-within:ring-ring" : "space-y-2",
|
|
6872
|
+
className
|
|
6873
|
+
),
|
|
6874
|
+
"data-testid": "wql-composer-root",
|
|
6875
|
+
children: [
|
|
6876
|
+
diagnosticsPosition === "top" && showDiagnostics && /* @__PURE__ */ jsxRuntime.jsx(WqlDiagnosticsStrip, { diagnostics, stages, actions: action, variant: "header" }),
|
|
6877
|
+
(desktop || compact || active.kind === "wql" || !guided) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 w-full items-center gap-2", children: [
|
|
6878
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6879
|
+
WqlTextEditor,
|
|
6880
|
+
{
|
|
6881
|
+
value: resolved.wql,
|
|
6882
|
+
placeholder,
|
|
6883
|
+
dense: compact,
|
|
6884
|
+
className: compact ? "min-w-0 w-full bg-transparent" : void 0,
|
|
6885
|
+
activeRange: active.kind === "value" ? active.range : void 0,
|
|
6886
|
+
activeClause: active.kind === "value" ? active.clause : void 0,
|
|
6887
|
+
onSlotActivate: activateWqlSlot,
|
|
6888
|
+
onChange: (text) => commit(resolveQueryDraft(text)),
|
|
6889
|
+
onSubmit: submit,
|
|
6890
|
+
onEscape: () => {
|
|
6891
|
+
if (active.kind === "closed") return false;
|
|
6892
|
+
closeEditor();
|
|
6893
|
+
return true;
|
|
6894
|
+
},
|
|
6895
|
+
autoFocus
|
|
6896
|
+
}
|
|
6897
|
+
) }),
|
|
6898
|
+
desktop && compact && undo && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => {
|
|
6899
|
+
commit(resolveQueryDraft(undo));
|
|
6900
|
+
setUndo(void 0);
|
|
6901
|
+
}, className: "min-h-9 shrink-0 rounded-lg px-2.5 text-xs text-muted-foreground hover:text-foreground", children: "Undo removal" })
|
|
6771
6902
|
] }),
|
|
6772
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6903
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-w-0 flex-wrap items-center gap-1", !desktop && !compact && "rounded-xl border border-border p-2", compact && "hidden"), "data-testid": "wql-composer", onKeyDown: (event) => {
|
|
6904
|
+
if (!["Delete", "Backspace"].includes(event.key) || !(event.target instanceof HTMLButtonElement)) return;
|
|
6905
|
+
const buttons = Array.from(event.currentTarget.querySelectorAll('[data-testid^="token-slot-"]:not([data-testid^="token-slot-remove-"]):not([data-testid^="token-slot-value-"])'));
|
|
6906
|
+
const pill = visiblePills[buttons.indexOf(event.target)];
|
|
6907
|
+
if (!pill || ["kind", "target", "agg", "metric"].includes(pill.type)) return;
|
|
6908
|
+
event.preventDefault();
|
|
6909
|
+
event.stopPropagation();
|
|
6910
|
+
setUndo(currentRef.current.wql);
|
|
6911
|
+
updateClause(pill, null);
|
|
6912
|
+
inputRef.current?.focus();
|
|
6913
|
+
}, children: [
|
|
6914
|
+
guided && active.kind !== "wql" && visiblePills.map((pill) => /* @__PURE__ */ jsxRuntime.jsx(TokenSlotPill, { clause: pill, compact, isActive: active.kind === "value" && active.clause.id === pill.id, onClick: () => openEditor(pill), onRemove: ["kind", "target", "agg", "metric"].includes(pill.type) ? void 0 : () => {
|
|
6915
|
+
setUndo(currentRef.current.wql);
|
|
6916
|
+
updateClause(pill, null);
|
|
6917
|
+
} }, pill.id)),
|
|
6918
|
+
!desktop && !compact && active.kind !== "wql" && guided && /* @__PURE__ */ jsxRuntime.jsx("input", { ref: inputRef, type: "text", role: "combobox", "aria-label": "Search text or WQL", "aria-controls": suggesting ? listId : void 0, "aria-expanded": suggesting, "aria-activedescendant": suggesting && highlight >= 0 ? `${listId}-option-${highlight}` : void 0, value: pending, placeholder, onChange: (event) => {
|
|
6919
|
+
const text = event.target.value;
|
|
6920
|
+
setPending(text);
|
|
6921
|
+
setHighlight(-1);
|
|
6922
|
+
setError(void 0);
|
|
6923
|
+
notify(resolveQueryDraft(base, text));
|
|
6924
|
+
}, onKeyDown: handleKeys, className: "min-h-12 min-w-0 flex-[1_1_140px] bg-transparent font-mono text-base outline-none", "data-testid": "wql-composer-input" }),
|
|
6925
|
+
customSlots
|
|
6784
6926
|
] }),
|
|
6785
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
6786
|
-
"
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
] }),
|
|
6796
|
-
suggesting && /* @__PURE__ */ jsxRuntime.jsxs("div", { id: listId, role: "listbox", "aria-label": "Query conditions", className: "max-h-64 overflow-y-auto rounded-xl border border-border p-1", "data-testid": "wql-filter-typeahead", children: [
|
|
6797
|
-
catalog.map((type, index) => /* @__PURE__ */ jsxRuntime.jsxs("button", { id: `${listId}-option-${index}`, type: "button", role: "option", "aria-selected": false, onMouseEnter: () => setHighlight(index), onClick: () => openField(type), className: cn("flex min-h-12 w-full items-center gap-2 rounded px-3 text-left", index === highlight && "bg-muted"), "data-testid": `wql-filter-typeahead-${type}`, children: [
|
|
6798
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
6799
|
-
pills.some((pill) => pill.type === type) ? "Edit" : "Add",
|
|
6800
|
-
" ",
|
|
6801
|
-
getClauseMeta(type).label
|
|
6927
|
+
(!desktop && !compact || !compact && undo) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
6928
|
+
!desktop && !compact && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => {
|
|
6929
|
+
commit(currentRef.current);
|
|
6930
|
+
if (active.kind === "wql") closeEditor();
|
|
6931
|
+
else setActive({ kind: "wql" });
|
|
6932
|
+
}, disabled: active.kind === "wql" && !guided, className: "min-h-12 rounded-lg px-3", children: active.kind === "wql" ? "Guided controls" : "Edit WQL" }),
|
|
6933
|
+
undo && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => {
|
|
6934
|
+
commit(resolveQueryDraft(undo));
|
|
6935
|
+
setUndo(void 0);
|
|
6936
|
+
}, className: "min-h-12 rounded-lg px-3", children: "Undo removal" })
|
|
6802
6937
|
] }),
|
|
6803
|
-
/* @__PURE__ */ jsxRuntime.
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6938
|
+
active.kind === "value" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6939
|
+
"div",
|
|
6940
|
+
{
|
|
6941
|
+
"data-testid": "wql-field-picker",
|
|
6942
|
+
className: cn(
|
|
6943
|
+
"min-w-0",
|
|
6944
|
+
compact ? "border-t border-border/70 bg-muted/20 px-2.5 py-2 space-y-1.5" : "space-y-2 rounded-xl border border-border/80 bg-muted/30 p-2 sm:p-2.5 shadow-xs backdrop-blur-sm"
|
|
6945
|
+
),
|
|
6946
|
+
onKeyDown: (event) => {
|
|
6947
|
+
if (event.key === "Escape" || event.key === "Enter" && (event.ctrlKey || event.metaKey)) handleKeys(event);
|
|
6948
|
+
},
|
|
6949
|
+
children: [
|
|
6950
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
6951
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex shrink-0 items-center gap-1.5 rounded-md border border-border/70 bg-background/80 px-2.5 py-1 text-xs font-semibold text-foreground font-mono", children: [
|
|
6952
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "text-xs", children: getClauseMeta(active.clause.type).icon }),
|
|
6953
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: getClauseMeta(active.clause.type).label })
|
|
6954
|
+
] }),
|
|
6955
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "sr-only", children: [
|
|
6956
|
+
"Search ",
|
|
6957
|
+
getClauseMeta(active.clause.type).label
|
|
6958
|
+
] }),
|
|
6959
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6960
|
+
"input",
|
|
6961
|
+
{
|
|
6962
|
+
ref: pickerRef,
|
|
6963
|
+
type: "search",
|
|
6964
|
+
role: "combobox",
|
|
6965
|
+
"aria-label": `Search ${getClauseMeta(active.clause.type).label}`,
|
|
6966
|
+
"aria-controls": listId,
|
|
6967
|
+
"aria-expanded": "true",
|
|
6968
|
+
"aria-activedescendant": highlight >= 0 ? `${listId}-option-${highlight}` : void 0,
|
|
6969
|
+
value: search,
|
|
6970
|
+
placeholder: active.clause.value ? `Current: ${active.clause.value}` : `Type value for ${getClauseMeta(active.clause.type).label}\u2026`,
|
|
6971
|
+
onChange: (event) => {
|
|
6972
|
+
setSearch(event.target.value);
|
|
6973
|
+
setHighlight(-1);
|
|
6974
|
+
setError(void 0);
|
|
6975
|
+
},
|
|
6976
|
+
onKeyDown: handleKeys,
|
|
6977
|
+
className: "min-h-10 sm:min-h-8 min-w-0 flex-1 rounded-lg border border-border/80 bg-background px-2.5 font-mono text-sm sm:text-xs text-foreground placeholder:text-muted-foreground/60 focus:outline-none focus:ring-1 focus:ring-primary shadow-xs",
|
|
6978
|
+
"data-testid": "wql-picker-search"
|
|
6979
|
+
}
|
|
6980
|
+
),
|
|
6981
|
+
active.clause.filterIndex !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "order-last flex w-full items-center gap-1.5 sm:order-none sm:w-auto", children: [
|
|
6982
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex cursor-pointer select-none items-center gap-1.5 px-2 py-0.5 rounded-md border border-border/60 bg-background/70 text-[11px] text-muted-foreground hover:text-foreground transition-colors", children: [
|
|
6983
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6984
|
+
"input",
|
|
6985
|
+
{
|
|
6986
|
+
type: "checkbox",
|
|
6987
|
+
checked: active.clause.negate ?? false,
|
|
6988
|
+
onChange: (event) => updateClause({ ...active.clause, negate: event.target.checked }, active.clause.value),
|
|
6989
|
+
className: "size-3 rounded border-border text-primary focus:ring-primary"
|
|
6990
|
+
}
|
|
6991
|
+
),
|
|
6992
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Exclude" })
|
|
6993
|
+
] }),
|
|
6994
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex cursor-pointer select-none items-center gap-1.5 px-2 py-0.5 rounded-md border border-border/60 bg-background/70 text-[11px] text-muted-foreground hover:text-foreground transition-colors", children: [
|
|
6995
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6996
|
+
"input",
|
|
6997
|
+
{
|
|
6998
|
+
type: "checkbox",
|
|
6999
|
+
checked: active.clause.value.split("|").every((value) => value.endsWith("*")),
|
|
7000
|
+
onChange: (event) => updateClause(active.clause, active.clause.value.split("|").map((value) => `${value.replace(/\*$/, "")}${event.target.checked ? "*" : ""}`).join("|")),
|
|
7001
|
+
className: "size-3 rounded border-border text-primary focus:ring-primary"
|
|
7002
|
+
}
|
|
7003
|
+
),
|
|
7004
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Starts with" })
|
|
7005
|
+
] })
|
|
7006
|
+
] }),
|
|
7007
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
7008
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7009
|
+
"button",
|
|
7010
|
+
{
|
|
7011
|
+
type: "button",
|
|
7012
|
+
"aria-label": "Previous WQL segment",
|
|
7013
|
+
"data-testid": "wql-segment-previous",
|
|
7014
|
+
disabled: activePillIndex <= 0,
|
|
7015
|
+
onClick: () => {
|
|
7016
|
+
if (moveEditor(-1)) pickerRef.current?.focus();
|
|
7017
|
+
},
|
|
7018
|
+
className: "flex items-center justify-center min-h-9 min-w-9 sm:min-h-7 sm:min-w-7 rounded-md border border-border/70 bg-background/80 text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-40 disabled:pointer-events-none text-xs transition-colors",
|
|
7019
|
+
children: "\u2190"
|
|
7020
|
+
}
|
|
7021
|
+
),
|
|
7022
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7023
|
+
"button",
|
|
7024
|
+
{
|
|
7025
|
+
type: "button",
|
|
7026
|
+
"aria-label": "Next WQL segment",
|
|
7027
|
+
"data-testid": "wql-segment-next",
|
|
7028
|
+
disabled: activePillIndex < 0 || activePillIndex >= visiblePills.length - 1,
|
|
7029
|
+
onClick: () => {
|
|
7030
|
+
if (moveEditor(1)) pickerRef.current?.focus();
|
|
7031
|
+
},
|
|
7032
|
+
className: "flex items-center justify-center min-h-9 min-w-9 sm:min-h-7 sm:min-w-7 rounded-md border border-border/70 bg-background/80 text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-40 disabled:pointer-events-none text-xs transition-colors",
|
|
7033
|
+
children: "\u2192"
|
|
7034
|
+
}
|
|
7035
|
+
),
|
|
7036
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7037
|
+
"button",
|
|
7038
|
+
{
|
|
7039
|
+
type: "button",
|
|
7040
|
+
"aria-label": "Close segment editor",
|
|
7041
|
+
onClick: closeEditor,
|
|
7042
|
+
className: "flex items-center justify-center min-h-9 min-w-9 sm:min-h-7 sm:min-w-7 rounded-md text-muted-foreground hover:bg-muted hover:text-foreground text-xs transition-colors",
|
|
7043
|
+
children: "\u2715"
|
|
7044
|
+
}
|
|
7045
|
+
)
|
|
7046
|
+
] })
|
|
7047
|
+
] }),
|
|
7048
|
+
active.kind === "value" && active.clause.type === "time" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2 pt-0.5 text-xs", children: [
|
|
7049
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block text-muted-foreground", children: [
|
|
7050
|
+
"Start date",
|
|
7051
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7052
|
+
"input",
|
|
7053
|
+
{
|
|
7054
|
+
type: "date",
|
|
7055
|
+
"aria-label": "Start date",
|
|
7056
|
+
className: "mt-1 min-h-8 w-full rounded-md border border-border/80 bg-background px-2.5 text-xs text-foreground",
|
|
7057
|
+
onChange: (event) => {
|
|
7058
|
+
const end = draftWindow();
|
|
7059
|
+
updateClause(active.clause, `from ${event.target.value}${end?.kind === "range" && end.end ? ` to ${end.end}` : ""}`);
|
|
7060
|
+
},
|
|
7061
|
+
value: astWindow?.kind === "range" ? astWindow.start : ""
|
|
7062
|
+
}
|
|
7063
|
+
)
|
|
7064
|
+
] }),
|
|
7065
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block text-muted-foreground", children: [
|
|
7066
|
+
"End date",
|
|
7067
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7068
|
+
"input",
|
|
7069
|
+
{
|
|
7070
|
+
type: "date",
|
|
7071
|
+
"aria-label": "End date",
|
|
7072
|
+
className: "mt-1 min-h-8 w-full rounded-md border border-border/80 bg-background px-2.5 text-xs text-foreground",
|
|
7073
|
+
onChange: (event) => {
|
|
7074
|
+
const window2 = draftWindow();
|
|
7075
|
+
if (window2?.kind === "range") updateClause(active.clause, `from ${window2.start}${event.target.value ? ` to ${event.target.value}` : ""}`);
|
|
7076
|
+
else setError("Choose a start date first");
|
|
7077
|
+
},
|
|
7078
|
+
value: astWindow?.kind === "range" ? astWindow.end ?? "" : ""
|
|
7079
|
+
}
|
|
7080
|
+
)
|
|
7081
|
+
] })
|
|
7082
|
+
] }),
|
|
7083
|
+
active.kind === "value" && (customEditor ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
7084
|
+
customEditor.Editor,
|
|
7085
|
+
{
|
|
7086
|
+
value: customEditor.parseValue ? customEditor.parseValue(active.clause.value) : active.clause.value,
|
|
7087
|
+
onChange: (value) => updateClause(active.clause, customEditor.formatValue ? customEditor.formatValue(value) : String(value)),
|
|
7088
|
+
onClose: closeEditor
|
|
7089
|
+
}
|
|
7090
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
7091
|
+
InlineClauseEditor,
|
|
7092
|
+
{
|
|
7093
|
+
clause: active.clause,
|
|
7094
|
+
filteredItems: preferredItems,
|
|
7095
|
+
selectedValues: values2.selectedValues,
|
|
7096
|
+
isMulti: values2.isMulti,
|
|
7097
|
+
typedValue: values2.typedValue,
|
|
7098
|
+
canCommitTyped: values2.canCommitTyped,
|
|
7099
|
+
emptyText: values2.emptyText,
|
|
7100
|
+
highlightIdx: highlight,
|
|
7101
|
+
onHighlight: setHighlight,
|
|
7102
|
+
onCommitValue: chooseValue,
|
|
7103
|
+
onCommitTyped: chooseValue,
|
|
7104
|
+
listId,
|
|
7105
|
+
onDone: closeEditor,
|
|
7106
|
+
onReorder: (dimensions) => updateClause(active.clause, dimensions.join("|"))
|
|
7107
|
+
}
|
|
7108
|
+
))
|
|
7109
|
+
]
|
|
7110
|
+
}
|
|
7111
|
+
),
|
|
7112
|
+
suggesting && /* @__PURE__ */ jsxRuntime.jsxs("div", { id: listId, role: "listbox", "aria-label": "Query conditions", className: "max-h-64 overflow-y-auto rounded-xl border border-border p-1", "data-testid": "wql-filter-typeahead", children: [
|
|
7113
|
+
catalog.map((type, index) => /* @__PURE__ */ jsxRuntime.jsxs("button", { id: `${listId}-option-${index}`, type: "button", role: "option", "aria-selected": false, onMouseEnter: () => setHighlight(index), onClick: () => openField(type), className: cn("flex min-h-12 w-full items-center gap-2 rounded px-3 text-left", index === highlight && "bg-muted"), "data-testid": `wql-filter-typeahead-${type}`, children: [
|
|
7114
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
7115
|
+
pills.some((pill) => pill.type === type) ? "Edit" : "Add",
|
|
7116
|
+
" ",
|
|
7117
|
+
getClauseMeta(type).label
|
|
7118
|
+
] }),
|
|
7119
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: type })
|
|
7120
|
+
] }, type)),
|
|
7121
|
+
textAction && /* @__PURE__ */ jsxRuntime.jsxs("button", { id: `${listId}-option-${catalog.length}`, type: "button", role: "option", "aria-selected": false, onMouseEnter: () => setHighlight(catalog.length), className: cn("min-h-12 w-full rounded px-3 text-left", highlight === catalog.length && "bg-muted"), onClick: submit, children: [
|
|
7122
|
+
"Search text ",
|
|
7123
|
+
pending
|
|
7124
|
+
] })
|
|
7125
|
+
] }),
|
|
7126
|
+
pivot && /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alertdialog", "aria-label": "Confirm query pivot", className: "rounded-xl border border-border p-3", children: [
|
|
7127
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Changing the query removes incompatible clauses:" }),
|
|
7128
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { children: pivot.removed.map((item) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: item }, item)) }),
|
|
7129
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "min-h-12 px-3", onClick: () => setPivot(void 0), children: "Cancel" }),
|
|
7130
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "min-h-12 px-3", onClick: () => {
|
|
7131
|
+
commit(pivot.draft);
|
|
7132
|
+
setPivot(void 0);
|
|
7133
|
+
closeEditor();
|
|
7134
|
+
}, children: "Change query" })
|
|
7135
|
+
] }),
|
|
7136
|
+
!showDiagnostics && (error ?? resolved.error) && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "text-sm text-destructive", children: error ?? resolved.error }),
|
|
7137
|
+
!guided && !resolved.error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Use Edit WQL to preserve every clause." }),
|
|
7138
|
+
pending && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", "data-testid": "wql-composer-pending", children: resolved.valid ? "Current draft includes this text" : resolved.error }),
|
|
7139
|
+
showDiagnostics && diagnosticsPosition === "bottom" ? /* @__PURE__ */ jsxRuntime.jsx(WqlDiagnosticsStrip, { diagnostics, stages, actions: action }) : diagnosticsPosition !== "top" || !showDiagnostics ? Boolean(actionLabel || diagnosticsActions) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center justify-end gap-2", children: action }) : null
|
|
7140
|
+
]
|
|
7141
|
+
}
|
|
7142
|
+
);
|
|
6825
7143
|
}
|
|
6826
7144
|
function WqlQueryInspectorModal({
|
|
6827
7145
|
isOpen,
|