@vaultgradient/pipequery-lang 1.2.2

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.
@@ -0,0 +1,1374 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/react/PipeQueryBuilder.tsx
2
+ var _react = require('react');
3
+ var _material = require('@mui/material');
4
+
5
+ // src/react/SourceNode.tsx
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+ var _Storage = require('@mui/icons-material/Storage'); var _Storage2 = _interopRequireDefault(_Storage);
17
+ var _jsxruntime = require('react/jsx-runtime');
18
+ function SourceNode({
19
+ source,
20
+ onSourceChange,
21
+ availableSources,
22
+ rowCount,
23
+ orientation,
24
+ compact
25
+ }) {
26
+ const isH = orientation === "horizontal";
27
+ const iconSz = compact ? 16 : 20;
28
+ const chipFontSz = compact ? "0.6rem" : "0.7rem";
29
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
30
+ _material.Paper,
31
+ {
32
+ variant: "outlined",
33
+ sx: {
34
+ p: compact ? 0.75 : 1.5,
35
+ ...isH ? {
36
+ borderLeft: "3px solid",
37
+ borderLeftColor: "primary.main",
38
+ width: compact ? 140 : 180,
39
+ flexShrink: 0,
40
+ alignSelf: "stretch",
41
+ display: "flex",
42
+ alignItems: "center"
43
+ } : {
44
+ borderTop: "3px solid",
45
+ borderTopColor: "primary.main"
46
+ },
47
+ background: (t) => `linear-gradient(135deg, ${_material.alpha.call(void 0, t.palette.primary.main, 0.06)} 0%, transparent 60%)`
48
+ },
49
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
50
+ _material.Stack,
51
+ {
52
+ direction: isH && compact ? "column" : "row",
53
+ spacing: compact ? 0.5 : 1,
54
+ sx: { alignItems: isH && compact ? "flex-start" : "center", width: "100%" },
55
+ children: [
56
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _Storage2.default, { sx: { color: "primary.main", fontSize: iconSz } }),
57
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.FormControl, { size: "small", sx: { flex: 1, minWidth: 0 }, children: [
58
+ !compact && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.InputLabel, { children: "Source" }),
59
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
60
+ _material.Select,
61
+ {
62
+ value: source,
63
+ label: compact ? void 0 : "Source",
64
+ onChange: (e) => onSourceChange(e.target.value),
65
+ MenuProps: { style: { zIndex: 1400 } },
66
+ sx: {
67
+ fontSize: compact ? "0.72rem" : "0.85rem",
68
+ "& .MuiSelect-select": compact ? { py: 0.5, px: 0.75 } : {}
69
+ },
70
+ children: availableSources.map((s) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.MenuItem, { value: s, sx: { fontSize: compact ? "0.72rem" : "0.85rem" }, children: s }, s))
71
+ }
72
+ )
73
+ ] }),
74
+ rowCount != null && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
75
+ _material.Chip,
76
+ {
77
+ label: `${rowCount.toLocaleString()}`,
78
+ size: "small",
79
+ variant: "outlined",
80
+ sx: {
81
+ fontFamily: '"JetBrains Mono", monospace',
82
+ fontSize: chipFontSz,
83
+ height: compact ? 18 : 24,
84
+ borderColor: (t) => _material.alpha.call(void 0, t.palette.primary.main, 0.3)
85
+ }
86
+ }
87
+ )
88
+ ]
89
+ }
90
+ )
91
+ }
92
+ );
93
+ }
94
+
95
+ // src/react/ResultNode.tsx
96
+
97
+ var _Code = require('@mui/icons-material/Code'); var _Code2 = _interopRequireDefault(_Code);
98
+
99
+ function ResultNode({
100
+ query,
101
+ orientation,
102
+ compact
103
+ }) {
104
+ const isH = orientation === "horizontal";
105
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
106
+ _material.Paper,
107
+ {
108
+ variant: "outlined",
109
+ sx: {
110
+ p: compact ? 0.75 : 1.5,
111
+ ...isH ? {
112
+ borderRight: "3px solid",
113
+ borderRightColor: "success.main",
114
+ width: compact ? 160 : 220,
115
+ flexShrink: 0,
116
+ alignSelf: "stretch",
117
+ display: "flex",
118
+ flexDirection: "column",
119
+ justifyContent: "center"
120
+ } : {
121
+ borderBottom: "3px solid",
122
+ borderBottomColor: "success.main"
123
+ },
124
+ background: (t) => `linear-gradient(135deg, ${_material.alpha.call(void 0, t.palette.success.main, 0.04)} 0%, transparent 60%)`
125
+ },
126
+ children: [
127
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Stack, { direction: "row", spacing: 0.5, sx: { alignItems: "center", mb: compact ? 0.25 : 0.75 }, children: [
128
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _Code2.default, { sx: { fontSize: compact ? 14 : 18, color: "success.main" } }),
129
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Typography, { sx: { fontWeight: 600, fontSize: compact ? "0.65rem" : "0.8rem" }, children: "Query" })
130
+ ] }),
131
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Box, { sx: {
132
+ p: compact ? 0.5 : 1,
133
+ bgcolor: "background.default",
134
+ borderRadius: 0.5,
135
+ fontFamily: '"JetBrains Mono", "Fira Code", monospace',
136
+ fontSize: compact ? "0.62rem" : "0.72rem",
137
+ color: "text.primary",
138
+ minHeight: compact ? 20 : 32,
139
+ whiteSpace: "pre-wrap",
140
+ wordBreak: "break-all",
141
+ lineHeight: 1.5,
142
+ overflow: "hidden",
143
+ maxHeight: isH ? 80 : "none"
144
+ }, children: query || "\u2014" })
145
+ ]
146
+ }
147
+ );
148
+ }
149
+
150
+ // src/react/PipelineConnector.tsx
151
+
152
+
153
+ var _Add = require('@mui/icons-material/Add'); var _Add2 = _interopRequireDefault(_Add);
154
+
155
+ // src/react/StepPicker.tsx
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+ // src/react/icons.tsx
170
+ var _FilterList = require('@mui/icons-material/FilterList'); var _FilterList2 = _interopRequireDefault(_FilterList);
171
+ var _ViewColumn = require('@mui/icons-material/ViewColumn'); var _ViewColumn2 = _interopRequireDefault(_ViewColumn);
172
+ var _SwapVert = require('@mui/icons-material/SwapVert'); var _SwapVert2 = _interopRequireDefault(_SwapVert);
173
+ var _Workspaces = require('@mui/icons-material/Workspaces'); var _Workspaces2 = _interopRequireDefault(_Workspaces);
174
+ var _VerticalAlignTop = require('@mui/icons-material/VerticalAlignTop'); var _VerticalAlignTop2 = _interopRequireDefault(_VerticalAlignTop);
175
+ var _VerticalAlignBottom = require('@mui/icons-material/VerticalAlignBottom'); var _VerticalAlignBottom2 = _interopRequireDefault(_VerticalAlignBottom);
176
+ var _MergeType = require('@mui/icons-material/MergeType'); var _MergeType2 = _interopRequireDefault(_MergeType);
177
+ var _Transform = require('@mui/icons-material/Transform'); var _Transform2 = _interopRequireDefault(_Transform);
178
+ var _BarChart = require('@mui/icons-material/BarChart'); var _BarChart2 = _interopRequireDefault(_BarChart);
179
+ var _SwapHoriz = require('@mui/icons-material/SwapHoriz'); var _SwapHoriz2 = _interopRequireDefault(_SwapHoriz);
180
+ var _UnfoldLess = require('@mui/icons-material/UnfoldLess'); var _UnfoldLess2 = _interopRequireDefault(_UnfoldLess);
181
+ var _Compress = require('@mui/icons-material/Compress'); var _Compress2 = _interopRequireDefault(_Compress);
182
+ var _Deblur = require('@mui/icons-material/Deblur'); var _Deblur2 = _interopRequireDefault(_Deblur);
183
+ var _PivotTableChart = require('@mui/icons-material/PivotTableChart'); var _PivotTableChart2 = _interopRequireDefault(_PivotTableChart);
184
+
185
+ var ICON_MAP = {
186
+ where: _FilterList2.default,
187
+ distinct: _Deblur2.default,
188
+ select: _ViewColumn2.default,
189
+ map: _Transform2.default,
190
+ flatten: _UnfoldLess2.default,
191
+ transpose: _SwapHoriz2.default,
192
+ sort: _SwapVert2.default,
193
+ groupBy: _Workspaces2.default,
194
+ reduce: _Compress2.default,
195
+ rollup: _BarChart2.default,
196
+ pivot: _PivotTableChart2.default,
197
+ first: _VerticalAlignTop2.default,
198
+ last: _VerticalAlignBottom2.default,
199
+ join: _MergeType2.default
200
+ };
201
+ function OperationIcon({ type, size = 16 }) {
202
+ const Icon = ICON_MAP[type];
203
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Icon, { sx: { fontSize: size } });
204
+ }
205
+
206
+ // src/react/types.ts
207
+ var CATEGORY_COLORS = {
208
+ filter: "#42a5f5",
209
+ transform: "#66bb6a",
210
+ sort: "#ffa726",
211
+ aggregate: "#ab47bc",
212
+ limit: "#26a69a",
213
+ join: "#ff7043"
214
+ };
215
+ var OPERATION_META = {
216
+ where: { label: "Filter (where)", shortLabel: "where", category: "filter", color: CATEGORY_COLORS.filter },
217
+ distinct: { label: "Distinct", shortLabel: "distinct", category: "filter", color: CATEGORY_COLORS.filter },
218
+ select: { label: "Select fields", shortLabel: "select", category: "transform", color: CATEGORY_COLORS.transform },
219
+ map: { label: "Map (add fields)", shortLabel: "map", category: "transform", color: CATEGORY_COLORS.transform },
220
+ flatten: { label: "Flatten", shortLabel: "flatten", category: "transform", color: CATEGORY_COLORS.transform },
221
+ transpose: { label: "Transpose", shortLabel: "transpose", category: "transform", color: CATEGORY_COLORS.transform },
222
+ sort: { label: "Sort", shortLabel: "sort", category: "sort", color: CATEGORY_COLORS.sort },
223
+ groupBy: { label: "Group By", shortLabel: "groupBy", category: "aggregate", color: CATEGORY_COLORS.aggregate },
224
+ reduce: { label: "Reduce", shortLabel: "reduce", category: "aggregate", color: CATEGORY_COLORS.aggregate },
225
+ rollup: { label: "Rollup", shortLabel: "rollup", category: "aggregate", color: CATEGORY_COLORS.aggregate },
226
+ pivot: { label: "Pivot", shortLabel: "pivot", category: "aggregate", color: CATEGORY_COLORS.aggregate },
227
+ first: { label: "First N", shortLabel: "first", category: "limit", color: CATEGORY_COLORS.limit },
228
+ last: { label: "Last N", shortLabel: "last", category: "limit", color: CATEGORY_COLORS.limit },
229
+ join: { label: "Join", shortLabel: "join", category: "join", color: CATEGORY_COLORS.join }
230
+ };
231
+ var CATEGORIES_ORDERED = [
232
+ { key: "filter", label: "Filter", ops: ["where", "distinct"] },
233
+ { key: "transform", label: "Transform", ops: ["select", "map", "flatten", "transpose"] },
234
+ { key: "sort", label: "Sort", ops: ["sort"] },
235
+ { key: "aggregate", label: "Aggregate", ops: ["groupBy", "reduce", "rollup", "pivot"] },
236
+ { key: "limit", label: "Limit", ops: ["first", "last"] },
237
+ { key: "join", label: "Join", ops: ["join"] }
238
+ ];
239
+ function createDefaultConfig(type) {
240
+ switch (type) {
241
+ case "where":
242
+ return { type, config: { condition: "" } };
243
+ case "select":
244
+ return { type, config: { fields: [], expressions: [] } };
245
+ case "sort":
246
+ return { type, config: { criteria: [{ field: "", direction: "asc" }] } };
247
+ case "groupBy":
248
+ return { type, config: { fields: [] } };
249
+ case "join":
250
+ return { type, config: { rightSource: "", condition: "" } };
251
+ case "first":
252
+ return { type, config: { count: 10 } };
253
+ case "last":
254
+ return { type, config: { count: 10 } };
255
+ case "distinct":
256
+ return { type, config: { fields: [] } };
257
+ case "map":
258
+ return { type, config: { expressions: [""] } };
259
+ case "reduce":
260
+ return { type, config: { initial: "0", accumulator: "" } };
261
+ case "rollup":
262
+ return { type, config: { keys: [], aggregates: [""] } };
263
+ case "pivot":
264
+ return { type, config: { pivotField: "", aggregates: [""] } };
265
+ case "flatten":
266
+ return { type, config: { field: "" } };
267
+ case "transpose":
268
+ return { type, config: { headerField: "" } };
269
+ }
270
+ }
271
+ function getStepSummary(step) {
272
+ switch (step.type) {
273
+ case "where":
274
+ return step.config.condition || "(no condition)";
275
+ case "select": {
276
+ const all = [...step.config.fields, ...step.config.expressions.filter(Boolean)];
277
+ return all.length > 0 ? all.join(", ") : "(no fields)";
278
+ }
279
+ case "sort": {
280
+ const parts = step.config.criteria.filter((c) => c.field).map(
281
+ (c) => c.direction === "desc" ? `${c.field} \u2193` : `${c.field} \u2191`
282
+ );
283
+ return parts.length > 0 ? parts.join(", ") : "(no criteria)";
284
+ }
285
+ case "groupBy":
286
+ return step.config.fields.length > 0 ? step.config.fields.join(", ") : "(no fields)";
287
+ case "join":
288
+ return step.config.rightSource ? `${step.config.rightSource} on ${step.config.condition || "..."}` : "(not configured)";
289
+ case "first":
290
+ case "last":
291
+ return `${step.config.count} rows`;
292
+ case "distinct":
293
+ return step.config.fields.length > 0 ? step.config.fields.join(", ") : "all fields";
294
+ case "map": {
295
+ const exprs = step.config.expressions.filter(Boolean);
296
+ return exprs.length > 0 ? exprs.join(", ") : "(no expressions)";
297
+ }
298
+ case "reduce":
299
+ return step.config.accumulator || "(no accumulator)";
300
+ case "rollup": {
301
+ const parts = [...step.config.keys, ...step.config.aggregates.filter(Boolean)];
302
+ return parts.length > 0 ? parts.join(", ") : "(not configured)";
303
+ }
304
+ case "pivot":
305
+ return step.config.pivotField || "(no pivot field)";
306
+ case "flatten":
307
+ return step.config.field || "all";
308
+ case "transpose":
309
+ return step.config.headerField || "auto";
310
+ }
311
+ }
312
+ function generateQuery(source, steps) {
313
+ if (!source) return "";
314
+ const parts = [source];
315
+ for (const { step } of steps) {
316
+ const dsl = stepToDsl(step);
317
+ if (dsl) parts.push(dsl);
318
+ }
319
+ return parts.join(" | ");
320
+ }
321
+ function stepToDsl(step) {
322
+ switch (step.type) {
323
+ case "where":
324
+ return step.config.condition ? `where(${step.config.condition})` : null;
325
+ case "select": {
326
+ const all = [...step.config.fields, ...step.config.expressions.filter(Boolean)];
327
+ return all.length > 0 ? `select(${all.join(", ")})` : null;
328
+ }
329
+ case "sort": {
330
+ const parts = step.config.criteria.filter((c) => c.field).map((c) => c.direction === "desc" ? `${c.field} desc` : c.field);
331
+ return parts.length > 0 ? `sort(${parts.join(", ")})` : null;
332
+ }
333
+ case "groupBy":
334
+ return step.config.fields.length > 0 ? `groupBy(${step.config.fields.join(", ")})` : null;
335
+ case "join":
336
+ return step.config.rightSource && step.config.condition ? `join(${step.config.rightSource}, ${step.config.condition})` : null;
337
+ case "first":
338
+ return `first(${step.config.count})`;
339
+ case "last":
340
+ return `last(${step.config.count})`;
341
+ case "distinct":
342
+ return step.config.fields.length > 0 ? `distinct(${step.config.fields.join(", ")})` : "distinct()";
343
+ case "map": {
344
+ const exprs = step.config.expressions.filter(Boolean);
345
+ return exprs.length > 0 ? `map(${exprs.join(", ")})` : null;
346
+ }
347
+ case "reduce":
348
+ return step.config.initial && step.config.accumulator ? `reduce(${step.config.initial}, ${step.config.accumulator})` : null;
349
+ case "rollup": {
350
+ const parts = [...step.config.keys, ...step.config.aggregates.filter(Boolean)];
351
+ return parts.length > 0 ? `rollup(${parts.join(", ")})` : null;
352
+ }
353
+ case "pivot": {
354
+ const aggs = step.config.aggregates.filter(Boolean);
355
+ return step.config.pivotField && aggs.length > 0 ? `pivot(${step.config.pivotField}, ${aggs.join(", ")})` : null;
356
+ }
357
+ case "flatten":
358
+ return step.config.field ? `flatten(${step.config.field})` : "flatten()";
359
+ case "transpose":
360
+ return step.config.headerField ? `transpose(${step.config.headerField})` : "transpose()";
361
+ }
362
+ }
363
+
364
+ // src/react/StepPicker.tsx
365
+
366
+ function PopoverPicker({ anchorEl, onClose, onSelect, orientation }) {
367
+ const isH = orientation === "horizontal";
368
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
369
+ _material.Popover,
370
+ {
371
+ open: Boolean(anchorEl),
372
+ anchorEl,
373
+ onClose,
374
+ anchorOrigin: isH ? { vertical: "bottom", horizontal: "center" } : { vertical: "center", horizontal: "right" },
375
+ transformOrigin: isH ? { vertical: "top", horizontal: "center" } : { vertical: "center", horizontal: "left" },
376
+ slotProps: { paper: { sx: { p: 1.5, minWidth: 240, maxWidth: 320 } } },
377
+ children: CATEGORIES_ORDERED.map(({ key, label, ops }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Box, { sx: { mb: 1.25, "&:last-child": { mb: 0 } }, children: [
378
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
379
+ _material.Typography,
380
+ {
381
+ variant: "caption",
382
+ sx: {
383
+ color: CATEGORY_COLORS[key],
384
+ fontWeight: 700,
385
+ textTransform: "uppercase",
386
+ letterSpacing: "0.05em",
387
+ fontSize: "0.58rem",
388
+ mb: 0.4,
389
+ display: "block"
390
+ },
391
+ children: label
392
+ }
393
+ ),
394
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Stack, { direction: "row", sx: { flexWrap: "wrap", gap: 0.5 }, children: ops.map((op) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
395
+ _material.Chip,
396
+ {
397
+ label: OPERATION_META[op].shortLabel,
398
+ size: "small",
399
+ icon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, OperationIcon, { type: op, size: 14 }),
400
+ onClick: () => onSelect(op),
401
+ variant: "outlined",
402
+ sx: {
403
+ cursor: "pointer",
404
+ height: 24,
405
+ fontSize: "0.68rem",
406
+ borderColor: _material.alpha.call(void 0, CATEGORY_COLORS[key], 0.35),
407
+ color: CATEGORY_COLORS[key],
408
+ "& .MuiChip-icon": { color: CATEGORY_COLORS[key] },
409
+ "&:hover": {
410
+ bgcolor: _material.alpha.call(void 0, CATEGORY_COLORS[key], 0.12),
411
+ borderColor: CATEGORY_COLORS[key]
412
+ }
413
+ }
414
+ },
415
+ op
416
+ )) })
417
+ ] }, key))
418
+ }
419
+ );
420
+ }
421
+ function CompactPicker({ onSelect }) {
422
+ const [value, setValue] = _react.useState.call(void 0, "");
423
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
424
+ _material.Select,
425
+ {
426
+ size: "small",
427
+ value,
428
+ displayEmpty: true,
429
+ onChange: (e) => {
430
+ const v = e.target.value;
431
+ if (v) {
432
+ onSelect(v);
433
+ setValue("");
434
+ }
435
+ },
436
+ renderValue: () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Typography, { sx: { fontSize: "0.65rem", color: "text.secondary" }, children: "+ step" }),
437
+ MenuProps: { style: { zIndex: 1400 } },
438
+ sx: {
439
+ minWidth: 70,
440
+ height: 22,
441
+ "& .MuiSelect-select": { py: 0.25, px: 0.75 },
442
+ fontSize: "0.7rem"
443
+ },
444
+ children: CATEGORIES_ORDERED.map(({ key, label, ops }) => [
445
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
446
+ _material.ListSubheader,
447
+ {
448
+ sx: {
449
+ fontSize: "0.58rem",
450
+ fontWeight: 700,
451
+ textTransform: "uppercase",
452
+ letterSpacing: "0.05em",
453
+ color: CATEGORY_COLORS[key],
454
+ lineHeight: "24px",
455
+ bgcolor: "background.paper"
456
+ },
457
+ children: label
458
+ },
459
+ `h-${key}`
460
+ ),
461
+ ...ops.map((op) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
462
+ _material.MenuItem,
463
+ {
464
+ value: op,
465
+ sx: {
466
+ fontSize: "0.7rem",
467
+ py: 0.25,
468
+ minHeight: "auto",
469
+ gap: 0.75,
470
+ color: CATEGORY_COLORS[key]
471
+ },
472
+ children: [
473
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, OperationIcon, { type: op, size: 13 }),
474
+ OPERATION_META[op].shortLabel
475
+ ]
476
+ },
477
+ op
478
+ ))
479
+ ]).flat()
480
+ }
481
+ );
482
+ }
483
+ function StepPicker({
484
+ anchorEl,
485
+ onClose,
486
+ onSelect,
487
+ compact,
488
+ orientation
489
+ }) {
490
+ if (compact) {
491
+ return null;
492
+ }
493
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
494
+ PopoverPicker,
495
+ {
496
+ anchorEl,
497
+ onClose,
498
+ onSelect,
499
+ orientation
500
+ }
501
+ );
502
+ }
503
+
504
+ // src/react/PipelineConnector.tsx
505
+
506
+ function PipelineConnector({
507
+ orientation,
508
+ compact,
509
+ onInsert
510
+ }) {
511
+ const [anchorEl, setAnchorEl] = _react.useState.call(void 0, null);
512
+ const isH = orientation === "horizontal";
513
+ const lineLen = compact ? 6 : 10;
514
+ const btnSize = compact ? 20 : 26;
515
+ const iconSize = compact ? 12 : 14;
516
+ if (compact) {
517
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Box, { sx: {
518
+ display: "flex",
519
+ flexDirection: isH ? "row" : "column",
520
+ alignItems: "center",
521
+ ...isH ? { py: 0 } : { px: 0 }
522
+ }, children: [
523
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Box, { sx: {
524
+ ...isH ? { height: 2, width: lineLen, bgcolor: (t) => _material.alpha.call(void 0, t.palette.text.secondary, 0.15) } : { width: 2, height: lineLen, bgcolor: (t) => _material.alpha.call(void 0, t.palette.text.secondary, 0.15) }
525
+ } }),
526
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CompactPicker, { onSelect: onInsert }),
527
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Box, { sx: {
528
+ ...isH ? { height: 2, width: lineLen, bgcolor: (t) => _material.alpha.call(void 0, t.palette.text.secondary, 0.15) } : { width: 2, height: lineLen, bgcolor: (t) => _material.alpha.call(void 0, t.palette.text.secondary, 0.15) }
529
+ } })
530
+ ] });
531
+ }
532
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Box, { sx: {
533
+ display: "flex",
534
+ flexDirection: isH ? "row" : "column",
535
+ alignItems: "center",
536
+ ...isH ? { py: 0 } : { py: 0.25 }
537
+ }, children: [
538
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Box, { sx: {
539
+ ...isH ? { height: 2, width: lineLen, bgcolor: (t) => _material.alpha.call(void 0, t.palette.text.secondary, 0.2) } : { width: 2, height: lineLen, bgcolor: (t) => _material.alpha.call(void 0, t.palette.text.secondary, 0.2) }
540
+ } }),
541
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
542
+ _material.IconButton,
543
+ {
544
+ size: "small",
545
+ onClick: (e) => setAnchorEl(e.currentTarget),
546
+ sx: {
547
+ width: btnSize,
548
+ height: btnSize,
549
+ border: "2px dashed",
550
+ borderColor: (t) => _material.alpha.call(void 0, t.palette.text.secondary, 0.25),
551
+ color: "text.secondary",
552
+ transition: "all 0.2s",
553
+ "&:hover": {
554
+ borderColor: "primary.main",
555
+ borderStyle: "solid",
556
+ color: "primary.main",
557
+ bgcolor: (t) => _material.alpha.call(void 0, t.palette.primary.main, 0.08),
558
+ transform: "scale(1.15)"
559
+ }
560
+ },
561
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _Add2.default, { sx: { fontSize: iconSize } })
562
+ }
563
+ ),
564
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Box, { sx: {
565
+ ...isH ? { height: 2, width: lineLen, bgcolor: (t) => _material.alpha.call(void 0, t.palette.text.secondary, 0.2) } : { width: 2, height: lineLen, bgcolor: (t) => _material.alpha.call(void 0, t.palette.text.secondary, 0.2) }
566
+ } }),
567
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
568
+ StepPicker,
569
+ {
570
+ anchorEl,
571
+ onClose: () => setAnchorEl(null),
572
+ onSelect: (type) => {
573
+ onInsert(type);
574
+ setAnchorEl(null);
575
+ },
576
+ compact: false,
577
+ orientation
578
+ }
579
+ )
580
+ ] });
581
+ }
582
+
583
+ // src/react/StepCard.tsx
584
+
585
+
586
+
587
+
588
+
589
+
590
+
591
+
592
+
593
+ var _DeleteOutlined = require('@mui/icons-material/DeleteOutlined'); var _DeleteOutlined2 = _interopRequireDefault(_DeleteOutlined);
594
+ var _ArrowUpward = require('@mui/icons-material/ArrowUpward'); var _ArrowUpward2 = _interopRequireDefault(_ArrowUpward);
595
+ var _ArrowDownward = require('@mui/icons-material/ArrowDownward'); var _ArrowDownward2 = _interopRequireDefault(_ArrowDownward);
596
+ var _ArrowBack = require('@mui/icons-material/ArrowBack'); var _ArrowBack2 = _interopRequireDefault(_ArrowBack);
597
+ var _ArrowForward = require('@mui/icons-material/ArrowForward'); var _ArrowForward2 = _interopRequireDefault(_ArrowForward);
598
+ var _ExpandMore = require('@mui/icons-material/ExpandMore'); var _ExpandMore2 = _interopRequireDefault(_ExpandMore);
599
+
600
+ // src/react/StepConfigForm.tsx
601
+
602
+
603
+
604
+
605
+
606
+
607
+
608
+
609
+
610
+
611
+
612
+
613
+
614
+
615
+
616
+
617
+
618
+
619
+
620
+ var MONO = '"JetBrains Mono", "Fira Code", monospace';
621
+ var POPPER_PROPS = { style: { zIndex: 1400 } };
622
+ var AGG_CATALOG = [
623
+ { group: "Basic", name: "count", hint: "Row count" },
624
+ { group: "Basic", name: "sum", hint: "Total" },
625
+ { group: "Basic", name: "avg", hint: "Arithmetic mean" },
626
+ { group: "Basic", name: "min", hint: "Minimum" },
627
+ { group: "Basic", name: "max", hint: "Maximum" },
628
+ { group: "Statistical", name: "median", hint: "50th percentile" },
629
+ { group: "Statistical", name: "stddev", hint: "Std deviation" },
630
+ { group: "Statistical", name: "var", hint: "Variance" },
631
+ { group: "Statistical", name: "percentile", hint: "p-th percentile (2-arg)" },
632
+ { group: "Distribution", name: "skew", hint: "Skewness" },
633
+ { group: "Distribution", name: "kurt", hint: "Excess kurtosis" },
634
+ { group: "Finance", name: "vwap", hint: "Vol-weighted avg price (2-arg)" },
635
+ { group: "Finance", name: "wavg", hint: "Weighted average (2-arg)" },
636
+ { group: "Finance", name: "drawdown", hint: "Max peak-to-trough decline" },
637
+ { group: "Ratios", name: "pct", hint: "Group % of total" },
638
+ { group: "Ratios", name: "sharpe", hint: "mean / stddev" },
639
+ { group: "Ratios", name: "calmar", hint: "mean / |max drawdown|" },
640
+ { group: "Ratios", name: "sortino", hint: "mean / downside dev" },
641
+ { group: "Ratios", name: "info_ratio", hint: "Information ratio (2-arg)" },
642
+ { group: "Counting", name: "distinct_count", hint: "Unique values" },
643
+ { group: "Counting", name: "sum_abs", hint: "Sum of |values|" },
644
+ { group: "Counting", name: "abs_sum", hint: "|Sum of values|" },
645
+ { group: "Counting", name: "first_value", hint: "First in group" },
646
+ { group: "Counting", name: "last_value", hint: "Last in group" }
647
+ ];
648
+ var AGG_NAMES_SET = new Set(AGG_CATALOG.map((a) => a.name));
649
+ var TWO_ARG_FNS = /* @__PURE__ */ new Set(["percentile", "vwap", "wavg", "info_ratio"]);
650
+ var AGG_RE = /^(\w+)\(\s*([^,)]*?)\s*(?:,\s*([^)]*?)\s*)?\)(?:\s+as\s+(\w+))?$/;
651
+ function parseAggExpr(expr) {
652
+ if (!expr.trim()) return { fn: "", field: "", field2: "", alias: "" };
653
+ const m = expr.trim().match(AGG_RE);
654
+ if (!m) return null;
655
+ const [, fn, field = "", field2 = "", alias = ""] = m;
656
+ if (!AGG_NAMES_SET.has(fn)) return null;
657
+ return { fn, field: field.trim(), field2: field2.trim(), alias: alias.trim() };
658
+ }
659
+ function serializeAgg(p) {
660
+ if (!p.fn) return "";
661
+ const args = p.field2 ? `${p.field}, ${p.field2}` : p.field;
662
+ const base = `${p.fn}(${args})`;
663
+ return p.alias ? `${base} as ${p.alias}` : base;
664
+ }
665
+ function AggregateExprRow({
666
+ value,
667
+ availableFields,
668
+ compact,
669
+ onChangeValue,
670
+ onDelete,
671
+ canDelete
672
+ }) {
673
+ const mono = { fontFamily: MONO, fontSize: compact ? "0.72rem" : "0.8rem" };
674
+ const parsed = parseAggExpr(value);
675
+ if (parsed === null) {
676
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Stack, { direction: "row", spacing: 0.5, sx: { alignItems: "center" }, children: [
677
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
678
+ _material.TextField,
679
+ {
680
+ size: "small",
681
+ fullWidth: true,
682
+ placeholder: "e.g. sum(revenue) as total",
683
+ value,
684
+ onChange: (e) => onChangeValue(e.target.value),
685
+ slotProps: { input: { sx: mono } }
686
+ }
687
+ ),
688
+ canDelete && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.IconButton, { size: "small", sx: { p: 0.25 }, onClick: onDelete, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _DeleteOutlined2.default, { sx: { fontSize: compact ? 12 : 14 } }) })
689
+ ] });
690
+ }
691
+ const isTwoArg = TWO_ARG_FNS.has(parsed.fn);
692
+ const update = (patch) => {
693
+ const next = { ...parsed, ...patch };
694
+ if (patch.fn !== void 0 && !TWO_ARG_FNS.has(patch.fn)) {
695
+ next.field2 = "";
696
+ }
697
+ onChangeValue(serializeAgg(next));
698
+ };
699
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Stack, { direction: "row", spacing: 0.5, sx: { alignItems: "center", flexWrap: "wrap" }, children: [
700
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
701
+ _material.Autocomplete,
702
+ {
703
+ size: "small",
704
+ options: AGG_CATALOG,
705
+ groupBy: (opt) => opt.group,
706
+ getOptionLabel: (opt) => typeof opt === "string" ? opt : opt.name,
707
+ isOptionEqualToValue: (opt, val) => opt.name === (typeof val === "string" ? val : val.name),
708
+ value: _nullishCoalesce(AGG_CATALOG.find((a) => a.name === parsed.fn), () => ( null)),
709
+ onChange: (_, v) => update({ fn: _nullishCoalesce(_optionalChain([v, 'optionalAccess', _2 => _2.name]), () => ( "")) }),
710
+ slotProps: { popper: POPPER_PROPS },
711
+ renderOption: (props, opt) => /* @__PURE__ */ _react.createElement.call(void 0, _material.Box, { component: "li", ...props, key: opt.name, sx: { display: "flex", gap: 1, alignItems: "center" } }, /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Typography, { sx: { fontFamily: MONO, fontSize: "0.78rem", fontWeight: 600, color: "#82aaff", minWidth: 90 }, children: opt.name }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Typography, { sx: { fontSize: "0.72rem", color: _material.alpha.call(void 0, "#fff", 0.45) }, children: opt.hint })),
712
+ sx: { minWidth: compact ? 100 : 130, flex: "0 1 auto" },
713
+ renderInput: (p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.TextField, { ...p, placeholder: "fn", sx: { "& input": { ...mono, minWidth: "60px !important" } } })
714
+ }
715
+ ),
716
+ parsed.fn !== "" && parsed.fn !== "count" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
717
+ _material.Autocomplete,
718
+ {
719
+ size: "small",
720
+ freeSolo: true,
721
+ options: availableFields,
722
+ value: parsed.field,
723
+ onInputChange: (_, v) => update({ field: v }),
724
+ sx: { minWidth: compact ? 80 : 100, flex: 1 },
725
+ slotProps: { popper: POPPER_PROPS },
726
+ renderInput: (p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.TextField, { ...p, placeholder: "field", sx: { "& input": mono } })
727
+ }
728
+ ),
729
+ isTwoArg && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
730
+ _material.Autocomplete,
731
+ {
732
+ size: "small",
733
+ freeSolo: true,
734
+ options: availableFields,
735
+ value: parsed.field2,
736
+ onInputChange: (_, v) => update({ field2: v }),
737
+ sx: { minWidth: compact ? 80 : 100, flex: 1 },
738
+ slotProps: { popper: POPPER_PROPS },
739
+ renderInput: (p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.TextField, { ...p, placeholder: "arg2", sx: { "& input": mono } })
740
+ }
741
+ ),
742
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
743
+ _material.TextField,
744
+ {
745
+ size: "small",
746
+ placeholder: "as",
747
+ value: parsed.alias,
748
+ onChange: (e) => update({ alias: e.target.value }),
749
+ sx: { width: compact ? 60 : 80 },
750
+ slotProps: { input: { sx: { ...mono, px: 0.5 } } }
751
+ }
752
+ ),
753
+ canDelete && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.IconButton, { size: "small", sx: { p: 0.25 }, onClick: onDelete, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _DeleteOutlined2.default, { sx: { fontSize: compact ? 12 : 14 } }) })
754
+ ] });
755
+ }
756
+ function AggregateList({
757
+ aggregates,
758
+ availableFields,
759
+ compact,
760
+ btnSz,
761
+ onChange
762
+ }) {
763
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
764
+ aggregates.map((agg, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
765
+ AggregateExprRow,
766
+ {
767
+ value: agg,
768
+ availableFields,
769
+ compact,
770
+ canDelete: aggregates.length > 1,
771
+ onChangeValue: (v) => {
772
+ const next = [...aggregates];
773
+ next[i] = v;
774
+ onChange(next);
775
+ },
776
+ onDelete: () => onChange(aggregates.filter((_, j) => j !== i))
777
+ },
778
+ i
779
+ )),
780
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
781
+ _material.Button,
782
+ {
783
+ size: "small",
784
+ sx: { fontSize: btnSz, py: 0.25, alignSelf: "flex-start" },
785
+ onClick: () => onChange([...aggregates, ""]),
786
+ children: "+ agg"
787
+ }
788
+ )
789
+ ] });
790
+ }
791
+ function StepConfigForm({
792
+ step,
793
+ availableFields,
794
+ joinSources,
795
+ compact,
796
+ onChange
797
+ }) {
798
+ const sp = compact ? 0.5 : 1;
799
+ const mono = { fontFamily: MONO, fontSize: compact ? "0.72rem" : "0.8rem" };
800
+ const btnSz = compact ? "0.65rem" : "0.75rem";
801
+ switch (step.type) {
802
+ case "where":
803
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
804
+ _material.TextField,
805
+ {
806
+ size: "small",
807
+ fullWidth: true,
808
+ placeholder: "e.g. price > 100",
809
+ value: step.config.condition,
810
+ onChange: (e) => onChange({ ...step, config: { condition: e.target.value } }),
811
+ slotProps: { input: { sx: mono } }
812
+ }
813
+ );
814
+ case "select":
815
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Stack, { spacing: sp, children: [
816
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
817
+ _material.Autocomplete,
818
+ {
819
+ multiple: true,
820
+ size: "small",
821
+ freeSolo: true,
822
+ options: availableFields,
823
+ value: step.config.fields,
824
+ onChange: (_, v) => onChange({ ...step, config: { ...step.config, fields: v } }),
825
+ slotProps: { popper: POPPER_PROPS },
826
+ renderInput: (p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.TextField, { ...p, placeholder: "Fields...", sx: { "& input": mono } })
827
+ }
828
+ ),
829
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
830
+ AggregateList,
831
+ {
832
+ aggregates: step.config.expressions,
833
+ availableFields,
834
+ compact,
835
+ btnSz,
836
+ onChange: (expressions) => onChange({ ...step, config: { ...step.config, expressions } })
837
+ }
838
+ )
839
+ ] });
840
+ case "sort":
841
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Stack, { spacing: sp, children: [
842
+ step.config.criteria.map((c, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Stack, { direction: "row", spacing: 0.5, sx: { alignItems: "center" }, children: [
843
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
844
+ _material.Autocomplete,
845
+ {
846
+ size: "small",
847
+ freeSolo: true,
848
+ options: availableFields,
849
+ sx: { flex: 1 },
850
+ value: c.field,
851
+ slotProps: { popper: POPPER_PROPS },
852
+ onInputChange: (_, v) => {
853
+ const criteria = [...step.config.criteria];
854
+ criteria[i] = { ...criteria[i], field: v };
855
+ onChange({ ...step, config: { criteria } });
856
+ },
857
+ renderInput: (p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.TextField, { ...p, placeholder: "Field", sx: { "& input": mono } })
858
+ }
859
+ ),
860
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
861
+ _material.ToggleButtonGroup,
862
+ {
863
+ size: "small",
864
+ exclusive: true,
865
+ value: c.direction,
866
+ onChange: (_, v) => {
867
+ if (!v) return;
868
+ const criteria = [...step.config.criteria];
869
+ criteria[i] = { ...criteria[i], direction: v };
870
+ onChange({ ...step, config: { criteria } });
871
+ },
872
+ children: [
873
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.ToggleButton, { value: "asc", sx: { px: 0.75, fontSize: compact ? "0.6rem" : "0.7rem" }, children: "ASC" }),
874
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.ToggleButton, { value: "desc", sx: { px: 0.75, fontSize: compact ? "0.6rem" : "0.7rem" }, children: "DESC" })
875
+ ]
876
+ }
877
+ ),
878
+ step.config.criteria.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.IconButton, { size: "small", sx: { p: 0.25 }, onClick: () => {
879
+ const criteria = step.config.criteria.filter((_, j) => j !== i);
880
+ onChange({ ...step, config: { criteria } });
881
+ }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _DeleteOutlined2.default, { sx: { fontSize: compact ? 12 : 14 } }) })
882
+ ] }, i)),
883
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
884
+ _material.Button,
885
+ {
886
+ size: "small",
887
+ sx: { fontSize: btnSz, py: 0.25, alignSelf: "flex-start" },
888
+ onClick: () => onChange({ ...step, config: { criteria: [...step.config.criteria, { field: "", direction: "asc" }] } }),
889
+ children: "+ criterion"
890
+ }
891
+ )
892
+ ] });
893
+ case "groupBy":
894
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
895
+ _material.Autocomplete,
896
+ {
897
+ multiple: true,
898
+ size: "small",
899
+ freeSolo: true,
900
+ options: availableFields,
901
+ value: step.config.fields,
902
+ onChange: (_, v) => onChange({ ...step, config: { fields: v } }),
903
+ slotProps: { popper: POPPER_PROPS },
904
+ renderInput: (p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.TextField, { ...p, placeholder: "Fields to group by...", sx: { "& input": mono } })
905
+ }
906
+ );
907
+ case "join":
908
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Stack, { spacing: sp, children: [
909
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.FormControl, { size: "small", fullWidth: true, children: [
910
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.InputLabel, { children: "Right source" }),
911
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
912
+ _material.Select,
913
+ {
914
+ value: step.config.rightSource,
915
+ label: "Right source",
916
+ onChange: (e) => onChange({ ...step, config: { ...step.config, rightSource: e.target.value } }),
917
+ MenuProps: { style: { zIndex: 1400 } },
918
+ children: joinSources.map((s) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.MenuItem, { value: s, children: s }, s))
919
+ }
920
+ )
921
+ ] }),
922
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
923
+ _material.TextField,
924
+ {
925
+ size: "small",
926
+ fullWidth: true,
927
+ placeholder: "e.g. customerId == id",
928
+ value: step.config.condition,
929
+ onChange: (e) => onChange({ ...step, config: { ...step.config, condition: e.target.value } }),
930
+ slotProps: { input: { sx: mono } }
931
+ }
932
+ )
933
+ ] });
934
+ case "first":
935
+ case "last":
936
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
937
+ _material.TextField,
938
+ {
939
+ size: "small",
940
+ type: "number",
941
+ fullWidth: true,
942
+ value: step.config.count,
943
+ onChange: (e) => onChange({ ...step, config: { count: Number(e.target.value) || 1 } }),
944
+ slotProps: { input: { sx: mono } }
945
+ }
946
+ );
947
+ case "distinct":
948
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
949
+ _material.Autocomplete,
950
+ {
951
+ multiple: true,
952
+ size: "small",
953
+ freeSolo: true,
954
+ options: availableFields,
955
+ value: step.config.fields,
956
+ onChange: (_, v) => onChange({ ...step, config: { fields: v } }),
957
+ slotProps: { popper: POPPER_PROPS },
958
+ renderInput: (p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.TextField, { ...p, placeholder: "Fields (empty = all)...", sx: { "& input": mono } })
959
+ }
960
+ );
961
+ case "map":
962
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Stack, { spacing: sp, children: [
963
+ step.config.expressions.map((expr, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
964
+ _material.TextField,
965
+ {
966
+ size: "small",
967
+ fullWidth: true,
968
+ placeholder: "e.g. price * 1.1 as priceWithTax",
969
+ value: expr,
970
+ onChange: (e) => {
971
+ const expressions = [...step.config.expressions];
972
+ expressions[i] = e.target.value;
973
+ onChange({ ...step, config: { expressions } });
974
+ },
975
+ slotProps: { input: { sx: mono } }
976
+ },
977
+ i
978
+ )),
979
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
980
+ _material.Button,
981
+ {
982
+ size: "small",
983
+ sx: { fontSize: btnSz, py: 0.25, alignSelf: "flex-start" },
984
+ onClick: () => onChange({ ...step, config: { expressions: [...step.config.expressions, ""] } }),
985
+ children: "+ expr"
986
+ }
987
+ )
988
+ ] });
989
+ case "reduce":
990
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Stack, { spacing: sp, children: [
991
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
992
+ _material.TextField,
993
+ {
994
+ size: "small",
995
+ fullWidth: true,
996
+ label: "Initial",
997
+ placeholder: "e.g. 0",
998
+ value: step.config.initial,
999
+ onChange: (e) => onChange({ ...step, config: { ...step.config, initial: e.target.value } }),
1000
+ slotProps: { input: { sx: mono } }
1001
+ }
1002
+ ),
1003
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1004
+ _material.TextField,
1005
+ {
1006
+ size: "small",
1007
+ fullWidth: true,
1008
+ label: "Accumulator",
1009
+ placeholder: "e.g. _acc + price",
1010
+ value: step.config.accumulator,
1011
+ onChange: (e) => onChange({ ...step, config: { ...step.config, accumulator: e.target.value } }),
1012
+ slotProps: { input: { sx: mono } }
1013
+ }
1014
+ )
1015
+ ] });
1016
+ case "rollup":
1017
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Stack, { spacing: sp, children: [
1018
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1019
+ _material.Autocomplete,
1020
+ {
1021
+ multiple: true,
1022
+ size: "small",
1023
+ freeSolo: true,
1024
+ options: availableFields,
1025
+ value: step.config.keys,
1026
+ onChange: (_, v) => onChange({ ...step, config: { ...step.config, keys: v } }),
1027
+ slotProps: { popper: POPPER_PROPS },
1028
+ renderInput: (p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.TextField, { ...p, placeholder: "Group keys...", sx: { "& input": mono } })
1029
+ }
1030
+ ),
1031
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1032
+ AggregateList,
1033
+ {
1034
+ aggregates: step.config.aggregates,
1035
+ availableFields,
1036
+ compact,
1037
+ btnSz,
1038
+ onChange: (aggregates) => onChange({ ...step, config: { ...step.config, aggregates } })
1039
+ }
1040
+ )
1041
+ ] });
1042
+ case "pivot":
1043
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Stack, { spacing: sp, children: [
1044
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1045
+ _material.Autocomplete,
1046
+ {
1047
+ size: "small",
1048
+ freeSolo: true,
1049
+ options: availableFields,
1050
+ value: step.config.pivotField,
1051
+ onInputChange: (_, v) => onChange({ ...step, config: { ...step.config, pivotField: v } }),
1052
+ slotProps: { popper: POPPER_PROPS },
1053
+ renderInput: (p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.TextField, { ...p, placeholder: "Pivot field...", sx: { "& input": mono } })
1054
+ }
1055
+ ),
1056
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1057
+ AggregateList,
1058
+ {
1059
+ aggregates: step.config.aggregates,
1060
+ availableFields,
1061
+ compact,
1062
+ btnSz,
1063
+ onChange: (aggregates) => onChange({ ...step, config: { ...step.config, aggregates } })
1064
+ }
1065
+ )
1066
+ ] });
1067
+ case "flatten":
1068
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1069
+ _material.Autocomplete,
1070
+ {
1071
+ size: "small",
1072
+ freeSolo: true,
1073
+ options: availableFields,
1074
+ value: step.config.field,
1075
+ onInputChange: (_, v) => onChange({ ...step, config: { field: v } }),
1076
+ slotProps: { popper: POPPER_PROPS },
1077
+ renderInput: (p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.TextField, { ...p, placeholder: "Field (optional)...", sx: { "& input": mono } })
1078
+ }
1079
+ );
1080
+ case "transpose":
1081
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1082
+ _material.Autocomplete,
1083
+ {
1084
+ size: "small",
1085
+ freeSolo: true,
1086
+ options: availableFields,
1087
+ value: step.config.headerField,
1088
+ onInputChange: (_, v) => onChange({ ...step, config: { headerField: v } }),
1089
+ slotProps: { popper: POPPER_PROPS },
1090
+ renderInput: (p) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.TextField, { ...p, placeholder: "Header field...", sx: { "& input": mono } })
1091
+ }
1092
+ );
1093
+ }
1094
+ }
1095
+
1096
+ // src/react/StepCard.tsx
1097
+
1098
+ function StepCard({
1099
+ step,
1100
+ isFirst,
1101
+ isLast,
1102
+ expanded,
1103
+ onToggleExpand,
1104
+ availableFields,
1105
+ joinSources,
1106
+ onUpdate,
1107
+ onRemove,
1108
+ onMoveUp,
1109
+ onMoveDown,
1110
+ orientation,
1111
+ compact
1112
+ }) {
1113
+ const meta = OPERATION_META[step.step.type];
1114
+ const summary = getStepSummary(step.step);
1115
+ const isH = orientation === "horizontal";
1116
+ const iconSz = compact ? 14 : 16;
1117
+ const actionIconSz = compact ? 12 : 14;
1118
+ const PrevIcon = isH ? _ArrowBack2.default : _ArrowUpward2.default;
1119
+ const NextIcon = isH ? _ArrowForward2.default : _ArrowDownward2.default;
1120
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1121
+ _material.Paper,
1122
+ {
1123
+ variant: "outlined",
1124
+ sx: {
1125
+ overflow: "hidden",
1126
+ ...isH ? {
1127
+ borderTop: "3px solid",
1128
+ borderTopColor: meta.color,
1129
+ borderRadius: "8px 8px 4px 4px",
1130
+ width: compact ? expanded ? 240 : 140 : expanded ? 280 : 200,
1131
+ flexShrink: 0,
1132
+ alignSelf: "stretch",
1133
+ transition: "box-shadow 0.2s, width 0.25s ease"
1134
+ } : {
1135
+ borderLeft: "4px solid",
1136
+ borderLeftColor: meta.color,
1137
+ borderRadius: "4px 8px 8px 4px",
1138
+ transition: "box-shadow 0.2s"
1139
+ },
1140
+ "&:hover": {
1141
+ boxShadow: `0 0 0 1px ${_material.alpha.call(void 0, meta.color, 0.25)}`
1142
+ },
1143
+ "& .step-actions": {
1144
+ opacity: 0,
1145
+ transition: "opacity 0.15s"
1146
+ },
1147
+ "&:hover .step-actions": {
1148
+ opacity: 1
1149
+ }
1150
+ },
1151
+ children: [
1152
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1153
+ _material.Stack,
1154
+ {
1155
+ direction: "row",
1156
+ spacing: 0.5,
1157
+ onClick: onToggleExpand,
1158
+ sx: {
1159
+ alignItems: "center",
1160
+ px: compact ? 0.75 : 1.25,
1161
+ py: compact ? 0.375 : 0.75,
1162
+ cursor: "pointer",
1163
+ "&:hover": { bgcolor: _material.alpha.call(void 0, meta.color, 0.04) }
1164
+ },
1165
+ children: [
1166
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Box, { sx: { color: meta.color, display: "flex", alignItems: "center", flexShrink: 0 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, OperationIcon, { type: step.step.type, size: iconSz }) }),
1167
+ !compact && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Typography, { sx: {
1168
+ fontWeight: 600,
1169
+ fontSize: "0.75rem",
1170
+ whiteSpace: "nowrap"
1171
+ }, children: meta.shortLabel }),
1172
+ !expanded && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1173
+ _material.Typography,
1174
+ {
1175
+ sx: {
1176
+ color: "text.secondary",
1177
+ fontFamily: '"JetBrains Mono", monospace',
1178
+ fontSize: compact ? "0.62rem" : "0.68rem",
1179
+ overflow: "hidden",
1180
+ textOverflow: "ellipsis",
1181
+ whiteSpace: "nowrap",
1182
+ flex: 1,
1183
+ minWidth: 0
1184
+ },
1185
+ children: compact ? `${meta.shortLabel}: ${summary}` : summary
1186
+ }
1187
+ ),
1188
+ expanded && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Box, { sx: { flex: 1 } }),
1189
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1190
+ _material.Stack,
1191
+ {
1192
+ direction: "row",
1193
+ spacing: 0,
1194
+ className: "step-actions",
1195
+ onClick: (e) => e.stopPropagation(),
1196
+ sx: { flexShrink: 0 },
1197
+ children: [
1198
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.IconButton, { size: "small", onClick: onMoveUp, disabled: isFirst, sx: { p: compact ? 0.25 : 0.375 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PrevIcon, { sx: { fontSize: actionIconSz } }) }),
1199
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.IconButton, { size: "small", onClick: onMoveDown, disabled: isLast, sx: { p: compact ? 0.25 : 0.375 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NextIcon, { sx: { fontSize: actionIconSz } }) }),
1200
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.IconButton, { size: "small", onClick: onRemove, sx: { p: compact ? 0.25 : 0.375, color: "error.main" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _DeleteOutlined2.default, { sx: { fontSize: actionIconSz } }) })
1201
+ ]
1202
+ }
1203
+ ),
1204
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _ExpandMore2.default, { sx: {
1205
+ fontSize: compact ? 14 : 18,
1206
+ color: "text.secondary",
1207
+ transition: "transform 0.2s",
1208
+ transform: expanded ? "rotate(180deg)" : "rotate(0deg)",
1209
+ flexShrink: 0
1210
+ } })
1211
+ ]
1212
+ }
1213
+ ),
1214
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Collapse, { in: expanded, timeout: 200, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Box, { sx: { px: compact ? 0.75 : 1.25, pb: compact ? 0.75 : 1.25 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1215
+ StepConfigForm,
1216
+ {
1217
+ step: step.step,
1218
+ availableFields,
1219
+ joinSources,
1220
+ compact,
1221
+ onChange: onUpdate
1222
+ }
1223
+ ) }) })
1224
+ ]
1225
+ }
1226
+ );
1227
+ }
1228
+
1229
+ // src/react/PipeQueryBuilder.tsx
1230
+
1231
+ function PipeQueryBuilder({
1232
+ orientation,
1233
+ source,
1234
+ onSourceChange,
1235
+ availableSources,
1236
+ availableFields,
1237
+ onQueryChange,
1238
+ compact = false,
1239
+ maxSteps,
1240
+ initialSteps,
1241
+ showResult = true,
1242
+ joinSources = [],
1243
+ rowCount
1244
+ }) {
1245
+ const [steps, setSteps] = _react.useState.call(void 0, () => _nullishCoalesce(initialSteps, () => ( [])));
1246
+ const [expandedId, setExpandedId] = _react.useState.call(void 0, null);
1247
+ const nextId = _react.useRef.call(void 0, 1);
1248
+ const isH = orientation === "horizontal";
1249
+ const generatedQuery = _react.useMemo.call(void 0,
1250
+ () => generateQuery(source, steps),
1251
+ [source, steps]
1252
+ );
1253
+ _react.useEffect.call(void 0, () => {
1254
+ onQueryChange(generatedQuery);
1255
+ }, [generatedQuery, onQueryChange]);
1256
+ const insertStepAt = _react.useCallback.call(void 0, (index, type) => {
1257
+ if (maxSteps != null && steps.length >= maxSteps) return;
1258
+ const newId = `pq_${nextId.current++}`;
1259
+ setSteps((prev) => {
1260
+ const next = [...prev];
1261
+ next.splice(index, 0, { id: newId, step: createDefaultConfig(type) });
1262
+ return next;
1263
+ });
1264
+ setExpandedId(newId);
1265
+ }, [maxSteps, steps.length]);
1266
+ const removeStep = _react.useCallback.call(void 0, (id) => {
1267
+ setSteps((prev) => prev.filter((s) => s.id !== id));
1268
+ setExpandedId((prev) => prev === id ? null : prev);
1269
+ }, []);
1270
+ const moveStep = _react.useCallback.call(void 0, (id, direction) => {
1271
+ setSteps((prev) => {
1272
+ const idx = prev.findIndex((s) => s.id === id);
1273
+ if (idx < 0) return prev;
1274
+ const newIdx = direction === "prev" ? idx - 1 : idx + 1;
1275
+ if (newIdx < 0 || newIdx >= prev.length) return prev;
1276
+ const next = [...prev];
1277
+ [next[idx], next[newIdx]] = [next[newIdx], next[idx]];
1278
+ return next;
1279
+ });
1280
+ }, []);
1281
+ const updateStep = _react.useCallback.call(void 0, (id, newStep) => {
1282
+ setSteps((prev) => prev.map((s) => s.id === id ? { ...s, step: newStep } : s));
1283
+ }, []);
1284
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _material.Box, { sx: {
1285
+ display: "flex",
1286
+ flexDirection: isH ? "row" : "column",
1287
+ alignItems: isH ? "stretch" : "center",
1288
+ overflowX: isH ? "auto" : "visible",
1289
+ overflowY: isH ? "visible" : "auto",
1290
+ flex: 1,
1291
+ py: compact ? 0.5 : 1,
1292
+ gap: 0,
1293
+ "&::-webkit-scrollbar": { height: 4 },
1294
+ "&::-webkit-scrollbar-thumb": { bgcolor: "rgba(255,255,255,0.15)", borderRadius: 2 }
1295
+ }, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _material.Box, { sx: {
1296
+ display: "flex",
1297
+ flexDirection: isH ? "row" : "column",
1298
+ alignItems: isH ? "stretch" : "stretch",
1299
+ ...isH ? {} : { width: "100%", maxWidth: compact ? 360 : 520 }
1300
+ }, children: [
1301
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1302
+ SourceNode,
1303
+ {
1304
+ source,
1305
+ onSourceChange,
1306
+ availableSources,
1307
+ rowCount,
1308
+ orientation,
1309
+ compact
1310
+ }
1311
+ ),
1312
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1313
+ PipelineConnector,
1314
+ {
1315
+ orientation,
1316
+ compact,
1317
+ onInsert: (type) => insertStepAt(0, type)
1318
+ }
1319
+ ),
1320
+ steps.map((step, idx) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1321
+ _material.Box,
1322
+ {
1323
+ sx: {
1324
+ display: "flex",
1325
+ flexDirection: isH ? "row" : "column",
1326
+ alignItems: isH ? "stretch" : "stretch"
1327
+ },
1328
+ children: [
1329
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1330
+ StepCard,
1331
+ {
1332
+ step,
1333
+ isFirst: idx === 0,
1334
+ isLast: idx === steps.length - 1,
1335
+ expanded: expandedId === step.id,
1336
+ onToggleExpand: () => setExpandedId(expandedId === step.id ? null : step.id),
1337
+ availableFields,
1338
+ joinSources,
1339
+ onUpdate: (newStep) => updateStep(step.id, newStep),
1340
+ onRemove: () => removeStep(step.id),
1341
+ onMoveUp: () => moveStep(step.id, "prev"),
1342
+ onMoveDown: () => moveStep(step.id, "next"),
1343
+ orientation,
1344
+ compact
1345
+ }
1346
+ ),
1347
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1348
+ PipelineConnector,
1349
+ {
1350
+ orientation,
1351
+ compact,
1352
+ onInsert: (type) => insertStepAt(idx + 1, type)
1353
+ }
1354
+ )
1355
+ ]
1356
+ },
1357
+ step.id
1358
+ )),
1359
+ showResult && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1360
+ ResultNode,
1361
+ {
1362
+ query: generatedQuery,
1363
+ orientation,
1364
+ compact
1365
+ }
1366
+ )
1367
+ ] }) });
1368
+ }
1369
+
1370
+
1371
+
1372
+
1373
+
1374
+ exports.PipeQueryBuilder = PipeQueryBuilder; exports.createDefaultConfig = createDefaultConfig; exports.generateQuery = generateQuery; exports.getStepSummary = getStepSummary;