@mastra/playground-ui 37.0.0-alpha.5 → 37.0.0
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/CHANGELOG.md +127 -0
- package/dist/components/Columns.cjs.js +1 -1
- package/dist/components/Columns.es.js +1 -1
- package/dist/components/RuleBuilder.cjs.js +10 -0
- package/dist/components/RuleBuilder.cjs.js.map +1 -0
- package/dist/components/RuleBuilder.d.ts +2 -0
- package/dist/components/RuleBuilder.es.js +2 -0
- package/dist/components/RuleBuilder.es.js.map +1 -0
- package/dist/index.cjs.js +65 -908
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +18 -842
- package/dist/index.es.js.map +1 -1
- package/dist/{multi-column-B9TVKcLl.cjs → multi-column-BLp7eL6P.cjs} +1 -2
- package/dist/{multi-column-B9TVKcLl.cjs.map → multi-column-BLp7eL6P.cjs.map} +1 -1
- package/dist/{multi-column-p8sEagdM.js → multi-column-DeSb1YDE.js} +1 -2
- package/dist/{multi-column-p8sEagdM.js.map → multi-column-DeSb1YDE.js.map} +1 -1
- package/dist/rule-builder-Zs6Ywp5-.js +563 -0
- package/dist/rule-builder-Zs6Ywp5-.js.map +1 -0
- package/dist/rule-builder-vwKEUlZU.cjs +594 -0
- package/dist/rule-builder-vwKEUlZU.cjs.map +1 -0
- package/dist/src/ds/components/RuleBuilder/index.d.ts +2 -0
- package/dist/src/utils/colors.d.ts +1 -0
- package/dist/src/utils/errors.d.ts +2 -0
- package/dist/src/utils/file.d.ts +1 -0
- package/dist/src/utils/formatting.d.ts +1 -0
- package/dist/src/utils/json-schema.d.ts +1 -0
- package/dist/src/utils/number.d.ts +1 -0
- package/dist/src/utils/query-utils.d.ts +1 -0
- package/dist/src/utils/rule-engine.d.ts +2 -0
- package/dist/src/utils/string.d.ts +1 -0
- package/dist/src/utils/truncate-string.d.ts +1 -0
- package/dist/utils/colors.cjs.js +15 -0
- package/dist/utils/colors.cjs.js.map +1 -0
- package/dist/utils/colors.d.ts +2 -0
- package/dist/utils/colors.es.js +11 -0
- package/dist/utils/colors.es.js.map +1 -0
- package/dist/utils/errors.cjs.js +33 -0
- package/dist/utils/errors.cjs.js.map +1 -0
- package/dist/utils/errors.d.ts +2 -0
- package/dist/utils/errors.es.js +22 -0
- package/dist/utils/errors.es.js.map +1 -0
- package/dist/utils/file.cjs.js +113 -0
- package/dist/utils/file.cjs.js.map +1 -0
- package/dist/utils/file.d.ts +2 -0
- package/dist/utils/file.es.js +100 -0
- package/dist/utils/file.es.js.map +1 -0
- package/dist/utils/formatting.cjs.js +47 -0
- package/dist/utils/formatting.cjs.js.map +1 -0
- package/dist/utils/formatting.d.ts +2 -0
- package/dist/utils/formatting.es.js +41 -0
- package/dist/utils/formatting.es.js.map +1 -0
- package/dist/utils/json-schema.cjs.js +3 -0
- package/dist/utils/json-schema.cjs.js.map +1 -0
- package/dist/utils/json-schema.d.ts +2 -0
- package/dist/utils/json-schema.es.js +2 -0
- package/dist/utils/json-schema.es.js.map +1 -0
- package/dist/utils/number.cjs.js +10 -0
- package/dist/utils/number.cjs.js.map +1 -0
- package/dist/utils/number.d.ts +2 -0
- package/dist/utils/number.es.js +6 -0
- package/dist/utils/number.es.js.map +1 -0
- package/dist/utils/query-utils.cjs.js +98 -0
- package/dist/utils/query-utils.cjs.js.map +1 -0
- package/dist/utils/query-utils.d.ts +2 -0
- package/dist/utils/query-utils.es.js +88 -0
- package/dist/utils/query-utils.es.js.map +1 -0
- package/dist/utils/rule-engine.cjs.js +29 -0
- package/dist/utils/rule-engine.cjs.js.map +1 -0
- package/dist/utils/rule-engine.d.ts +2 -0
- package/dist/utils/rule-engine.es.js +21 -0
- package/dist/utils/rule-engine.es.js.map +1 -0
- package/dist/utils/string.cjs.js +11 -0
- package/dist/utils/string.cjs.js.map +1 -0
- package/dist/utils/string.d.ts +2 -0
- package/dist/utils/string.es.js +7 -0
- package/dist/utils/string.es.js.map +1 -0
- package/dist/utils/truncate-string.cjs.js +11 -0
- package/dist/utils/truncate-string.cjs.js.map +1 -0
- package/dist/utils/truncate-string.d.ts +2 -0
- package/dist/utils/truncate-string.es.js +7 -0
- package/dist/utils/truncate-string.es.js.map +1 -0
- package/package.json +8 -8
package/dist/index.es.js
CHANGED
|
@@ -37,7 +37,7 @@ export { T as TextFieldBlock } from './text-field-block-DybcFyt-.js';
|
|
|
37
37
|
export { S as SearchFieldBlock } from './search-field-block-CJSnpu8G.js';
|
|
38
38
|
export { S as SelectFieldBlock } from './select-field-block-z5_ve898.js';
|
|
39
39
|
import { H as HoverCard, b as HoverCardTrigger, a as HoverCardContent } from './hover-card-dAmvL_J6.js';
|
|
40
|
-
|
|
40
|
+
export { I as Input } from './input-CmF5qOKQ.js';
|
|
41
41
|
export { I as InputGroup, a as InputGroupAddon, b as InputGroupButton, c as InputGroupInput, d as InputGroupText, e as InputGroupTextarea } from './input-group-iZZD8Z65.js';
|
|
42
42
|
export { K as Kbd } from './kbd-gp0Sr4mW.js';
|
|
43
43
|
export { L as Label } from './label-WtU3xT6v.js';
|
|
@@ -52,8 +52,7 @@ export { S as ScrollArea, a as ScrollBar } from './scroll-area-COFVK-be.js';
|
|
|
52
52
|
export { P as PendingIndicator } from './pending-indicator-D25Svcqn.js';
|
|
53
53
|
import { S as Searchbar } from './searchbar-SYpN7NP_.js';
|
|
54
54
|
export { a as SearchbarWrapper } from './searchbar-SYpN7NP_.js';
|
|
55
|
-
|
|
56
|
-
export { b as SelectGroup } from './select-BSf4VfTX.js';
|
|
55
|
+
export { S as Select, a as SelectContent, b as SelectGroup, c as SelectItem, d as SelectTrigger, e as SelectValue } from './select-BSf4VfTX.js';
|
|
57
56
|
export { S as Shimmer } from './shimmer-C_ea1Lfl.js';
|
|
58
57
|
import { S as Skeleton } from './skeleton-CUjhGPAx.js';
|
|
59
58
|
export { S as Slider } from './slider-Kps70qjb.js';
|
|
@@ -85,7 +84,7 @@ import { b as Tabs, a as TabList, T as Tab } from './tabs-tab-D0Ydz5KC.js';
|
|
|
85
84
|
import { T as TabContent } from './tabs-content-J4YUF8-A.js';
|
|
86
85
|
export { T as TextAndIcon, g as getShortId } from './get-short-id-ZED99MfC.js';
|
|
87
86
|
export { C as ContentBlock, a as ContentBlocks } from './content-block-BTpK7gPz.js';
|
|
88
|
-
export { C as Column, a as Columns, M as MultiColumn } from './multi-column-
|
|
87
|
+
export { C as Column, a as Columns, M as MultiColumn } from './multi-column-DeSb1YDE.js';
|
|
89
88
|
import { C as CodeDiff } from './code-diff-lktH1err.js';
|
|
90
89
|
export { I as ItemList, a as ItemListSkeleton, g as getItemListColumnTemplate, b as getToNextItemFn, c as getToPreviousItemFn } from './helpers-CsdqE6P2.js';
|
|
91
90
|
import { N as Notice } from './Notice-BJ6lke5l.js';
|
|
@@ -128,11 +127,18 @@ export { useIsMobile } from './hooks/use-is-mobile.es.js';
|
|
|
128
127
|
export { useIsApplePlatform, useKeyboardShortcutLabel } from './hooks/use-keyboard-shortcut-label.es.js';
|
|
129
128
|
export { useCustomEnvironmentVariablesEditor, useEnvironmentVariablesEditor } from './hooks/use-environment-variables-editor.es.js';
|
|
130
129
|
import { c as cn } from './cn-BakJzhuv.js';
|
|
130
|
+
export { lodashTitleCase } from './utils/string.es.js';
|
|
131
|
+
export { toSigFigs } from './utils/number.es.js';
|
|
132
|
+
export { formatJSON, formatTypeScript, isValidJson } from './utils/formatting.es.js';
|
|
133
|
+
import { stringToColor } from './utils/colors.es.js';
|
|
134
|
+
import { truncateString } from './utils/truncate-string.es.js';
|
|
135
|
+
import { parseError } from './utils/errors.es.js';
|
|
136
|
+
import { is401UnauthorizedError, is403ForbiddenError, isUnsupportedObservabilityOperationError } from './utils/query-utils.es.js';
|
|
137
|
+
export { is404NotFoundError, isBranchesNotSupportedError, isNonRetryableError, shouldRetryQuery } from './utils/query-utils.es.js';
|
|
131
138
|
import { t as toast } from './toast-BKsfnapA.js';
|
|
132
139
|
export { T as Toaster } from './toast-BKsfnapA.js';
|
|
133
|
-
import {
|
|
134
|
-
import {
|
|
135
|
-
import * as React from 'react';
|
|
140
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
141
|
+
import { ChevronRight, ChevronLeft, LogsIcon, EyeIcon, GaugeIcon, BrainIcon, ChevronUpIcon, ChevronDownIcon, ChevronsUpIcon, ChevronsDownIcon, FoldVerticalIcon, UnfoldVerticalIcon, ChevronsDownUpIcon, ChevronsUpDownIcon, Link2Icon, CircleGaugeIcon, SaveIcon, WrenchIcon, Loader2Icon, DownloadIcon, FileInputIcon, FileOutputIcon, BracesIcon, ExternalLinkIcon, CircleSlashIcon, ArrowUpIcon, ArrowDownIcon, ArrowRightIcon, RotateCcw, ArrowLeftIcon, ArrowUpRight } from 'lucide-react';
|
|
136
142
|
import { useRef, useCallback, useState, useEffect, useMemo, useContext, createContext, Fragment as Fragment$1 } from 'react';
|
|
137
143
|
import { usePanelRef, Panel, Separator, Group } from 'react-resizable-panels';
|
|
138
144
|
import { Icon } from './icons/Icon.es.js';
|
|
@@ -148,6 +154,8 @@ export { AnthropicChatIcon } from './icons/AnthropicChatIcon.es.js';
|
|
|
148
154
|
export { AnthropicMessagesIcon } from './icons/AnthropicMessagesIcon.es.js';
|
|
149
155
|
export { ApiIcon } from './icons/ApiIcon.es.js';
|
|
150
156
|
export { AzureIcon } from './icons/AzureIcon.es.js';
|
|
157
|
+
import { downloadJson } from './utils/file.es.js';
|
|
158
|
+
export { BROWSER_FETCHABLE_SCHEMES, EXTENSION_TO_MIME, NON_FETCHABLE_REMOTE_SCHEMES, REMOTE_URL_SCHEMES, fileToBase64, getFileContentType, isBrowserFetchableUrl, isNonFetchableRemoteUrl, isRemoteUrl } from './utils/file.es.js';
|
|
151
159
|
export { BranchIcon } from './icons/BranchIcon.es.js';
|
|
152
160
|
export { CheckIcon } from './icons/CheckIcon.es.js';
|
|
153
161
|
export { ChevronIcon } from './icons/ChevronIcon.es.js';
|
|
@@ -185,6 +193,7 @@ import { MemoryIcon } from './icons/MemoryIcon.es.js';
|
|
|
185
193
|
export { MetricsIcon } from './icons/MetricsIcon.es.js';
|
|
186
194
|
export { MistralIcon } from './icons/MistralIcon.es.js';
|
|
187
195
|
export { NetlifyIcon } from './icons/NetlifyIcon.es.js';
|
|
196
|
+
export { O as OPERATORS, a as OPERATOR_LABELS, R as RuleBuilder, b as RuleFieldSelect, c as RuleOperatorSelect, d as RuleRow, e as RuleValueInput, g as getChildFieldOptions, f as getFieldOptionAtPath, h as getFieldOptionsFromSchema, p as parseFieldPath } from './rule-builder-Zs6Ywp5-.js';
|
|
188
197
|
export { OpenAIIcon } from './icons/OpenAIIcon.es.js';
|
|
189
198
|
export { OpenaiChatIcon } from './icons/OpenaiChatIcon.es.js';
|
|
190
199
|
export { ProcessorIcon } from './icons/ProcessorIcon.es.js';
|
|
@@ -207,747 +216,12 @@ export { VariablesIcon } from './icons/VariablesIcon.es.js';
|
|
|
207
216
|
export { WorkflowCoinIcon } from './icons/WorkflowCoinIcon.es.js';
|
|
208
217
|
export { WorkspacesIcon } from './icons/WorkspacesIcon.es.js';
|
|
209
218
|
export { XGroqIcon } from './icons/XGroqIcon.es.js';
|
|
210
|
-
|
|
211
|
-
const lodashTitleCase = (str) => {
|
|
212
|
-
const camelCased = str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "").replace(/^(.)/, (char) => char.toLowerCase());
|
|
213
|
-
return camelCased.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).trim();
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
const toSigFigs = (num, sigFigs) => {
|
|
217
|
-
return Number(num.toPrecision(sigFigs));
|
|
218
|
-
};
|
|
219
|
+
export { countLeafRules, createDefaultRule, createDefaultRuleGroup, isRule, isRuleGroup } from './utils/rule-engine.es.js';
|
|
219
220
|
|
|
220
221
|
const isObjectEmpty = (objectName) => {
|
|
221
222
|
return objectName && Object.keys(objectName).length === 0 && objectName.constructor === Object;
|
|
222
223
|
};
|
|
223
224
|
|
|
224
|
-
let prettierModules;
|
|
225
|
-
const loadPrettier = () => prettierModules ??= Promise.all([
|
|
226
|
-
import('prettier/standalone'),
|
|
227
|
-
import('prettier/plugins/babel'),
|
|
228
|
-
import('prettier/plugins/estree')
|
|
229
|
-
]).catch((error) => {
|
|
230
|
-
prettierModules = void 0;
|
|
231
|
-
throw error;
|
|
232
|
-
});
|
|
233
|
-
const formatJSON = async (code) => {
|
|
234
|
-
const [prettier, prettierPluginBabel, prettierPluginEstree] = await loadPrettier();
|
|
235
|
-
const formatted = await prettier.format(code, {
|
|
236
|
-
semi: false,
|
|
237
|
-
parser: "json",
|
|
238
|
-
printWidth: 80,
|
|
239
|
-
tabWidth: 2,
|
|
240
|
-
plugins: [prettierPluginBabel, prettierPluginEstree]
|
|
241
|
-
});
|
|
242
|
-
return formatted;
|
|
243
|
-
};
|
|
244
|
-
const formatTypeScript = async (code) => {
|
|
245
|
-
const [prettier, prettierPluginBabel, prettierPluginEstree] = await loadPrettier();
|
|
246
|
-
const formatted = await prettier.format(code, {
|
|
247
|
-
parser: "babel-ts",
|
|
248
|
-
printWidth: 80,
|
|
249
|
-
tabWidth: 2,
|
|
250
|
-
plugins: [prettierPluginBabel, prettierPluginEstree]
|
|
251
|
-
});
|
|
252
|
-
return formatted;
|
|
253
|
-
};
|
|
254
|
-
const isValidJson = (str) => {
|
|
255
|
-
try {
|
|
256
|
-
const obj = JSON.parse(str);
|
|
257
|
-
return !!obj && typeof obj === "object";
|
|
258
|
-
} catch {
|
|
259
|
-
return false;
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
const stringToColor = (str, lightness = 90, saturation = 100) => {
|
|
264
|
-
let hash = 0;
|
|
265
|
-
for (let i = 0; i < str.length; i++) {
|
|
266
|
-
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
|
267
|
-
hash = hash & hash;
|
|
268
|
-
}
|
|
269
|
-
return `hsl(${hash % 360}, ${saturation}%, ${lightness}%)`;
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
function truncateString(str, maxLength) {
|
|
273
|
-
if (str.length <= maxLength) return str;
|
|
274
|
-
return str.slice(0, maxLength) + "…";
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const errorFallback = "Something went wrong while fetching the data.";
|
|
278
|
-
const parseError = (error) => {
|
|
279
|
-
try {
|
|
280
|
-
const httpErrorPattern = /^HTTP error! status:\s*\d+\s*- \s*/;
|
|
281
|
-
const errorMessage = error?.message.replace(httpErrorPattern, "");
|
|
282
|
-
const jsonError = JSON.parse(errorMessage || "{}");
|
|
283
|
-
return {
|
|
284
|
-
error: jsonError?.error || errorFallback,
|
|
285
|
-
stack: jsonError?.stack || error?.stack
|
|
286
|
-
};
|
|
287
|
-
} catch {
|
|
288
|
-
return {
|
|
289
|
-
error: error?.message || errorFallback,
|
|
290
|
-
stack: void 0
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
const HTTP_NO_RETRY_STATUSES = [400, 401, 403, 404];
|
|
296
|
-
function is401UnauthorizedError(error) {
|
|
297
|
-
if (!error || typeof error !== "object") return false;
|
|
298
|
-
if ("status" in error && error.status === 401) {
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
301
|
-
if ("statusCode" in error && error.statusCode === 401) {
|
|
302
|
-
return true;
|
|
303
|
-
}
|
|
304
|
-
if ("message" in error) {
|
|
305
|
-
const message = error.message;
|
|
306
|
-
if (typeof message === "string") {
|
|
307
|
-
return /\bstatus:\s*401\b/.test(message);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
return false;
|
|
311
|
-
}
|
|
312
|
-
function is403ForbiddenError(error) {
|
|
313
|
-
if (!error || typeof error !== "object") return false;
|
|
314
|
-
if ("status" in error && error.status === 403) {
|
|
315
|
-
return true;
|
|
316
|
-
}
|
|
317
|
-
if ("statusCode" in error && error.statusCode === 403) {
|
|
318
|
-
return true;
|
|
319
|
-
}
|
|
320
|
-
if ("message" in error) {
|
|
321
|
-
const message = error.message;
|
|
322
|
-
if (typeof message === "string") {
|
|
323
|
-
return /\bstatus:\s*403\b/.test(message);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
return false;
|
|
327
|
-
}
|
|
328
|
-
function is404NotFoundError(error) {
|
|
329
|
-
if (!error || typeof error !== "object") return false;
|
|
330
|
-
if ("status" in error && error.status === 404) {
|
|
331
|
-
return true;
|
|
332
|
-
}
|
|
333
|
-
if ("statusCode" in error && error.statusCode === 404) {
|
|
334
|
-
return true;
|
|
335
|
-
}
|
|
336
|
-
if ("message" in error) {
|
|
337
|
-
const message = error.message;
|
|
338
|
-
if (typeof message === "string") {
|
|
339
|
-
return /\bstatus:\s*404\b/.test(message);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
return false;
|
|
343
|
-
}
|
|
344
|
-
function isBranchesNotSupportedError(error) {
|
|
345
|
-
if (!error || typeof error !== "object" || !("message" in error)) return false;
|
|
346
|
-
const message = error.message;
|
|
347
|
-
if (typeof message !== "string") return false;
|
|
348
|
-
return message.includes("does not support listing trace branches");
|
|
349
|
-
}
|
|
350
|
-
function isUnsupportedObservabilityOperationError(error, operation) {
|
|
351
|
-
if (!error || typeof error !== "object" || !("message" in error)) return false;
|
|
352
|
-
const message = error.message;
|
|
353
|
-
if (typeof message !== "string") return false;
|
|
354
|
-
return message.includes(`does not support listing ${operation}`);
|
|
355
|
-
}
|
|
356
|
-
function isNonRetryableError(error) {
|
|
357
|
-
if (!error || typeof error !== "object") return false;
|
|
358
|
-
if ("status" in error) {
|
|
359
|
-
const status = error.status;
|
|
360
|
-
return HTTP_NO_RETRY_STATUSES.includes(status);
|
|
361
|
-
}
|
|
362
|
-
if ("statusCode" in error) {
|
|
363
|
-
const statusCode = error.statusCode;
|
|
364
|
-
return HTTP_NO_RETRY_STATUSES.includes(statusCode);
|
|
365
|
-
}
|
|
366
|
-
if ("message" in error) {
|
|
367
|
-
const message = error.message;
|
|
368
|
-
if (typeof message === "string") {
|
|
369
|
-
return HTTP_NO_RETRY_STATUSES.some((code) => new RegExp(`\\bstatus:\\s*${code}\\b`).test(message));
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
return false;
|
|
373
|
-
}
|
|
374
|
-
function shouldRetryQuery(failureCount, error) {
|
|
375
|
-
if (isNonRetryableError(error)) {
|
|
376
|
-
return false;
|
|
377
|
-
}
|
|
378
|
-
return failureCount < 3;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
const isRule = (condition) => "field" in condition;
|
|
382
|
-
const isRuleGroup = (condition) => "conditions" in condition;
|
|
383
|
-
const countLeafRules = (group) => {
|
|
384
|
-
if (!group) return 0;
|
|
385
|
-
return group.conditions.reduce((count, condition) => {
|
|
386
|
-
if (isRule(condition)) return count + 1;
|
|
387
|
-
return count + countLeafRules(condition);
|
|
388
|
-
}, 0);
|
|
389
|
-
};
|
|
390
|
-
const createDefaultRule = () => ({
|
|
391
|
-
field: "",
|
|
392
|
-
operator: "equals",
|
|
393
|
-
value: ""
|
|
394
|
-
});
|
|
395
|
-
const createDefaultRuleGroup = (operator = "AND") => ({
|
|
396
|
-
operator,
|
|
397
|
-
conditions: [createDefaultRule()]
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
const getPropertyType = (property) => {
|
|
401
|
-
if (Array.isArray(property.type)) {
|
|
402
|
-
return property.type.find((t) => t !== "null") || "string";
|
|
403
|
-
}
|
|
404
|
-
return property.type || "string";
|
|
405
|
-
};
|
|
406
|
-
const hasNestedChildren = (property) => {
|
|
407
|
-
const type = getPropertyType(property);
|
|
408
|
-
if (type === "object" && property.properties) {
|
|
409
|
-
return Object.keys(property.properties).length > 0;
|
|
410
|
-
}
|
|
411
|
-
if (type === "array" && property.items) {
|
|
412
|
-
const itemType = getPropertyType(property.items);
|
|
413
|
-
return itemType === "object" && !!property.items.properties;
|
|
414
|
-
}
|
|
415
|
-
return false;
|
|
416
|
-
};
|
|
417
|
-
const getFieldOptionsFromProperties = (properties, parentPath = "") => {
|
|
418
|
-
if (!properties) return [];
|
|
419
|
-
return Object.entries(properties).map(([key, property]) => {
|
|
420
|
-
const path = parentPath ? `${parentPath}.${key}` : key;
|
|
421
|
-
const type = getPropertyType(property);
|
|
422
|
-
const hasChildren = hasNestedChildren(property);
|
|
423
|
-
return {
|
|
424
|
-
path,
|
|
425
|
-
label: property.title || key,
|
|
426
|
-
type,
|
|
427
|
-
hasChildren,
|
|
428
|
-
children: type === "object" ? property.properties : void 0,
|
|
429
|
-
items: type === "array" ? property.items : void 0
|
|
430
|
-
};
|
|
431
|
-
});
|
|
432
|
-
};
|
|
433
|
-
const getFieldOptionsFromSchema = (schema) => {
|
|
434
|
-
return getFieldOptionsFromProperties(schema.properties);
|
|
435
|
-
};
|
|
436
|
-
const getChildFieldOptions = (fieldOption, currentPath) => {
|
|
437
|
-
if (fieldOption.type === "object" && fieldOption.children) {
|
|
438
|
-
return getFieldOptionsFromProperties(fieldOption.children, currentPath);
|
|
439
|
-
}
|
|
440
|
-
if (fieldOption.type === "array" && fieldOption.items) {
|
|
441
|
-
const itemType = getPropertyType(fieldOption.items);
|
|
442
|
-
if (itemType === "object" && fieldOption.items.properties) {
|
|
443
|
-
return getFieldOptionsFromProperties(fieldOption.items.properties, currentPath);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
return [];
|
|
447
|
-
};
|
|
448
|
-
const parseFieldPath = (path) => {
|
|
449
|
-
return path.split(".").filter(Boolean);
|
|
450
|
-
};
|
|
451
|
-
const getFieldOptionAtPath = (schema, path) => {
|
|
452
|
-
const segments = parseFieldPath(path);
|
|
453
|
-
if (segments.length === 0) return void 0;
|
|
454
|
-
let currentProperties = schema.properties;
|
|
455
|
-
let currentPath = "";
|
|
456
|
-
let result;
|
|
457
|
-
for (let i = 0; i < segments.length; i++) {
|
|
458
|
-
const segment = segments[i];
|
|
459
|
-
if (!currentProperties || !currentProperties[segment]) {
|
|
460
|
-
return void 0;
|
|
461
|
-
}
|
|
462
|
-
const property = currentProperties[segment];
|
|
463
|
-
currentPath = currentPath ? `${currentPath}.${segment}` : segment;
|
|
464
|
-
const type = getPropertyType(property);
|
|
465
|
-
const hasChildren = hasNestedChildren(property);
|
|
466
|
-
result = {
|
|
467
|
-
path: currentPath,
|
|
468
|
-
label: property.title || segment,
|
|
469
|
-
type,
|
|
470
|
-
hasChildren,
|
|
471
|
-
children: type === "object" ? property.properties : void 0,
|
|
472
|
-
items: type === "array" ? property.items : void 0
|
|
473
|
-
};
|
|
474
|
-
if (type === "object" && property.properties) {
|
|
475
|
-
currentProperties = property.properties;
|
|
476
|
-
} else if (type === "array" && property.items?.properties) {
|
|
477
|
-
currentProperties = property.items.properties;
|
|
478
|
-
} else {
|
|
479
|
-
currentProperties = void 0;
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
return result;
|
|
483
|
-
};
|
|
484
|
-
|
|
485
|
-
const getFieldTypeIcon = (type) => {
|
|
486
|
-
switch (type) {
|
|
487
|
-
case "object":
|
|
488
|
-
return /* @__PURE__ */ jsx(Braces, {});
|
|
489
|
-
case "array":
|
|
490
|
-
return /* @__PURE__ */ jsx(List, {});
|
|
491
|
-
case "number":
|
|
492
|
-
case "integer":
|
|
493
|
-
return /* @__PURE__ */ jsx(Hash, {});
|
|
494
|
-
case "boolean":
|
|
495
|
-
return /* @__PURE__ */ jsx(ToggleLeft, {});
|
|
496
|
-
case "string":
|
|
497
|
-
default:
|
|
498
|
-
return /* @__PURE__ */ jsx(Type, {});
|
|
499
|
-
}
|
|
500
|
-
};
|
|
501
|
-
const FieldLevelSelect = ({
|
|
502
|
-
options,
|
|
503
|
-
value,
|
|
504
|
-
onChange,
|
|
505
|
-
placeholder = "Select field",
|
|
506
|
-
className
|
|
507
|
-
}) => {
|
|
508
|
-
return /* @__PURE__ */ jsx("div", { className: cn("relative", className), children: /* @__PURE__ */ jsxs(Select, { value, onValueChange: onChange, children: [
|
|
509
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "min-w-[140px] text-neutral6 bg-surface4", size: "sm", children: /* @__PURE__ */ jsx(SelectValue, { placeholder }) }),
|
|
510
|
-
/* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.path, children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
511
|
-
/* @__PURE__ */ jsx(Icon, { size: "sm", className: "text-neutral3", children: getFieldTypeIcon(option.type) }),
|
|
512
|
-
option.label,
|
|
513
|
-
option.hasChildren && /* @__PURE__ */ jsx("span", { className: "text-neutral3", children: "..." })
|
|
514
|
-
] }) }, option.path)) })
|
|
515
|
-
] }) });
|
|
516
|
-
};
|
|
517
|
-
const RuleFieldSelect = ({ schema, value, onChange, className }) => {
|
|
518
|
-
const pathSegments = React.useMemo(() => parseFieldPath(value), [value]);
|
|
519
|
-
const selectors = React.useMemo(() => {
|
|
520
|
-
const result = [];
|
|
521
|
-
const rootOptions = getFieldOptionsFromSchema(schema);
|
|
522
|
-
if (rootOptions.length === 0) return result;
|
|
523
|
-
result.push({
|
|
524
|
-
options: rootOptions,
|
|
525
|
-
value: pathSegments[0] || "",
|
|
526
|
-
basePath: ""
|
|
527
|
-
});
|
|
528
|
-
let currentPath = "";
|
|
529
|
-
for (let i = 0; i < pathSegments.length; i++) {
|
|
530
|
-
const segment = pathSegments[i];
|
|
531
|
-
currentPath = currentPath ? `${currentPath}.${segment}` : segment;
|
|
532
|
-
const fieldOption = getFieldOptionAtPath(schema, currentPath);
|
|
533
|
-
if (!fieldOption || !fieldOption.hasChildren) break;
|
|
534
|
-
const childOptions = getChildFieldOptions(fieldOption, currentPath);
|
|
535
|
-
if (childOptions.length === 0) break;
|
|
536
|
-
const nextSegment = pathSegments[i + 1];
|
|
537
|
-
const nextPath = nextSegment ? `${currentPath}.${nextSegment}` : "";
|
|
538
|
-
result.push({
|
|
539
|
-
options: childOptions,
|
|
540
|
-
value: nextPath,
|
|
541
|
-
basePath: currentPath
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
return result;
|
|
545
|
-
}, [schema, pathSegments]);
|
|
546
|
-
const handleChange = React.useCallback(
|
|
547
|
-
(levelIndex, newValue) => {
|
|
548
|
-
onChange(newValue);
|
|
549
|
-
},
|
|
550
|
-
[onChange]
|
|
551
|
-
);
|
|
552
|
-
if (selectors.length === 0) {
|
|
553
|
-
return /* @__PURE__ */ jsx("div", { className: cn("text-sm text-neutral3", className), children: "No fields available" });
|
|
554
|
-
}
|
|
555
|
-
return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-1", className), children: selectors.map((selector, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
556
|
-
index > 0 && /* @__PURE__ */ jsx("span", { className: "text-neutral3", children: "." }),
|
|
557
|
-
/* @__PURE__ */ jsx(
|
|
558
|
-
FieldLevelSelect,
|
|
559
|
-
{
|
|
560
|
-
options: selector.options,
|
|
561
|
-
value: selector.value,
|
|
562
|
-
onChange: (newValue) => handleChange(index, newValue),
|
|
563
|
-
placeholder: index === 0 ? "Select field" : "Select property"
|
|
564
|
-
}
|
|
565
|
-
)
|
|
566
|
-
] }, `${selector.basePath}-${index}`)) });
|
|
567
|
-
};
|
|
568
|
-
|
|
569
|
-
const OPERATOR_LABELS = {
|
|
570
|
-
equals: "equals",
|
|
571
|
-
not_equals: "not equals",
|
|
572
|
-
contains: "contains",
|
|
573
|
-
not_contains: "not contains",
|
|
574
|
-
greater_than: "greater than",
|
|
575
|
-
less_than: "less than",
|
|
576
|
-
greater_than_or_equal: "greater than or equal",
|
|
577
|
-
less_than_or_equal: "less than or equal",
|
|
578
|
-
in: "in",
|
|
579
|
-
not_in: "not in",
|
|
580
|
-
exists: "exists",
|
|
581
|
-
not_exists: "not exists"
|
|
582
|
-
};
|
|
583
|
-
const OPERATORS = [
|
|
584
|
-
"equals",
|
|
585
|
-
"not_equals",
|
|
586
|
-
"contains",
|
|
587
|
-
"not_contains",
|
|
588
|
-
"greater_than",
|
|
589
|
-
"less_than",
|
|
590
|
-
"greater_than_or_equal",
|
|
591
|
-
"less_than_or_equal",
|
|
592
|
-
"in",
|
|
593
|
-
"not_in",
|
|
594
|
-
"exists",
|
|
595
|
-
"not_exists"
|
|
596
|
-
];
|
|
597
|
-
|
|
598
|
-
const OPERATOR_ICONS = {
|
|
599
|
-
equals: /* @__PURE__ */ jsx(Equal, {}),
|
|
600
|
-
not_equals: /* @__PURE__ */ jsx(EqualNot, {}),
|
|
601
|
-
contains: /* @__PURE__ */ jsx(TextSearch, {}),
|
|
602
|
-
not_contains: /* @__PURE__ */ jsx(Text, {}),
|
|
603
|
-
greater_than: /* @__PURE__ */ jsx(ChevronRight, {}),
|
|
604
|
-
less_than: /* @__PURE__ */ jsx(ChevronLeft, {}),
|
|
605
|
-
greater_than_or_equal: /* @__PURE__ */ jsx(ChevronsRight, {}),
|
|
606
|
-
less_than_or_equal: /* @__PURE__ */ jsx(ChevronsLeft, {}),
|
|
607
|
-
in: /* @__PURE__ */ jsx(List, {}),
|
|
608
|
-
not_in: /* @__PURE__ */ jsx(ListX, {}),
|
|
609
|
-
exists: /* @__PURE__ */ jsx(Check, {}),
|
|
610
|
-
not_exists: /* @__PURE__ */ jsx(Ban, {})
|
|
611
|
-
};
|
|
612
|
-
const RuleOperatorSelect = ({ value, onChange, operators, className }) => {
|
|
613
|
-
const operatorList = operators ?? OPERATORS;
|
|
614
|
-
return /* @__PURE__ */ jsx("div", { className: cn("relative", className), children: /* @__PURE__ */ jsxs(Select, { value, onValueChange: onChange, children: [
|
|
615
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "min-w-[150px] text-neutral6 bg-surface4", size: "sm", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select operator" }) }),
|
|
616
|
-
/* @__PURE__ */ jsx(SelectContent, { children: operatorList.map((operator) => /* @__PURE__ */ jsx(SelectItem, { value: operator, children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
|
|
617
|
-
/* @__PURE__ */ jsx(Icon, { size: "sm", className: "text-neutral3", children: OPERATOR_ICONS[operator] }),
|
|
618
|
-
OPERATOR_LABELS[operator]
|
|
619
|
-
] }) }, operator)) })
|
|
620
|
-
] }) });
|
|
621
|
-
};
|
|
622
|
-
|
|
623
|
-
const parseValue = (stringValue) => {
|
|
624
|
-
const trimmed = stringValue.trim();
|
|
625
|
-
if (trimmed === "") return "";
|
|
626
|
-
if (trimmed === "true") return true;
|
|
627
|
-
if (trimmed === "false") return false;
|
|
628
|
-
if (trimmed === "null") return null;
|
|
629
|
-
const lowerTrimmed = trimmed.toLowerCase();
|
|
630
|
-
if (lowerTrimmed === "infinity" || lowerTrimmed === "-infinity" || lowerTrimmed === "nan") {
|
|
631
|
-
return trimmed;
|
|
632
|
-
}
|
|
633
|
-
const num = Number(trimmed);
|
|
634
|
-
if (!Number.isNaN(num)) return num;
|
|
635
|
-
return stringValue;
|
|
636
|
-
};
|
|
637
|
-
const parseArrayValue = (stringValue) => {
|
|
638
|
-
if (stringValue.trim() === "") return [];
|
|
639
|
-
return stringValue.split(",").map((item) => parseValue(item.trim()));
|
|
640
|
-
};
|
|
641
|
-
const valueToString = (value) => {
|
|
642
|
-
if (value === null) return "null";
|
|
643
|
-
if (value === void 0) return "";
|
|
644
|
-
if (Array.isArray(value)) return value.map(valueToString).join(", ");
|
|
645
|
-
return String(value);
|
|
646
|
-
};
|
|
647
|
-
const booleanToString = (value) => {
|
|
648
|
-
if (value === true) return "true";
|
|
649
|
-
if (value === false) return "false";
|
|
650
|
-
return "";
|
|
651
|
-
};
|
|
652
|
-
const BooleanValueInput = ({ value, onChange, className }) => {
|
|
653
|
-
const stringValue = booleanToString(value);
|
|
654
|
-
const handleChange = React.useCallback(
|
|
655
|
-
(newValue) => {
|
|
656
|
-
onChange(newValue === "true");
|
|
657
|
-
},
|
|
658
|
-
[onChange]
|
|
659
|
-
);
|
|
660
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
|
|
661
|
-
/* @__PURE__ */ jsx(Icon, { size: "sm", className: "absolute left-2 top-1/2 -translate-y-1/2 text-neutral3 pointer-events-none z-10", children: /* @__PURE__ */ jsx(ToggleLeft, {}) }),
|
|
662
|
-
/* @__PURE__ */ jsxs(Select, { value: stringValue, onValueChange: handleChange, children: [
|
|
663
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "min-w-[140px] bg-surface4 pl-7", size: "sm", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select value" }) }),
|
|
664
|
-
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
665
|
-
/* @__PURE__ */ jsx(SelectItem, { value: "true", children: "true" }),
|
|
666
|
-
/* @__PURE__ */ jsx(SelectItem, { value: "false", children: "false" })
|
|
667
|
-
] })
|
|
668
|
-
] })
|
|
669
|
-
] });
|
|
670
|
-
};
|
|
671
|
-
const NumberValueInput = ({ value, onChange, placeholder, className }) => {
|
|
672
|
-
const displayValue = value === void 0 || value === "" ? "" : String(value);
|
|
673
|
-
const handleChange = React.useCallback(
|
|
674
|
-
(e) => {
|
|
675
|
-
const inputValue = e.target.value;
|
|
676
|
-
if (inputValue === "") {
|
|
677
|
-
onChange("");
|
|
678
|
-
} else {
|
|
679
|
-
const num = Number(inputValue);
|
|
680
|
-
onChange(Number.isNaN(num) ? inputValue : num);
|
|
681
|
-
}
|
|
682
|
-
},
|
|
683
|
-
[onChange]
|
|
684
|
-
);
|
|
685
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
|
|
686
|
-
/* @__PURE__ */ jsx(Icon, { size: "sm", className: "absolute left-2 top-1/2 -translate-y-1/2 text-neutral3 pointer-events-none", children: /* @__PURE__ */ jsx(Hash, {}) }),
|
|
687
|
-
/* @__PURE__ */ jsx(
|
|
688
|
-
Input,
|
|
689
|
-
{
|
|
690
|
-
type: "number",
|
|
691
|
-
value: displayValue,
|
|
692
|
-
onChange: handleChange,
|
|
693
|
-
placeholder: placeholder || "Enter number",
|
|
694
|
-
className: "min-w-[140px] bg-surface4 pl-7",
|
|
695
|
-
size: "sm"
|
|
696
|
-
}
|
|
697
|
-
)
|
|
698
|
-
] });
|
|
699
|
-
};
|
|
700
|
-
const TextValueInput = ({ value, onChange, placeholder, className }) => {
|
|
701
|
-
const displayValue = valueToString(value);
|
|
702
|
-
const handleChange = React.useCallback(
|
|
703
|
-
(e) => {
|
|
704
|
-
onChange(parseValue(e.target.value));
|
|
705
|
-
},
|
|
706
|
-
[onChange]
|
|
707
|
-
);
|
|
708
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
|
|
709
|
-
/* @__PURE__ */ jsx(Icon, { size: "sm", className: "absolute left-2 top-1/2 -translate-y-1/2 text-neutral3 pointer-events-none", children: /* @__PURE__ */ jsx(Type, {}) }),
|
|
710
|
-
/* @__PURE__ */ jsx(
|
|
711
|
-
Input,
|
|
712
|
-
{
|
|
713
|
-
value: displayValue,
|
|
714
|
-
onChange: handleChange,
|
|
715
|
-
placeholder: placeholder || "Enter value",
|
|
716
|
-
className: "min-w-[140px] bg-surface4 pl-7",
|
|
717
|
-
size: "sm"
|
|
718
|
-
}
|
|
719
|
-
)
|
|
720
|
-
] });
|
|
721
|
-
};
|
|
722
|
-
const ArrayValueInput = ({ value, onChange, placeholder, className }) => {
|
|
723
|
-
const displayValue = React.useMemo(() => {
|
|
724
|
-
if (Array.isArray(value)) {
|
|
725
|
-
return value.map(valueToString).join(", ");
|
|
726
|
-
}
|
|
727
|
-
return valueToString(value);
|
|
728
|
-
}, [value]);
|
|
729
|
-
const handleChange = React.useCallback(
|
|
730
|
-
(e) => {
|
|
731
|
-
onChange(parseArrayValue(e.target.value));
|
|
732
|
-
},
|
|
733
|
-
[onChange]
|
|
734
|
-
);
|
|
735
|
-
return /* @__PURE__ */ jsx(
|
|
736
|
-
Input,
|
|
737
|
-
{
|
|
738
|
-
value: displayValue,
|
|
739
|
-
onChange: handleChange,
|
|
740
|
-
placeholder: placeholder || "Enter values (comma-separated)",
|
|
741
|
-
className: cn("min-w-[160px] bg-surface4", className),
|
|
742
|
-
size: "sm"
|
|
743
|
-
}
|
|
744
|
-
);
|
|
745
|
-
};
|
|
746
|
-
const RuleValueInput = ({
|
|
747
|
-
value,
|
|
748
|
-
onChange,
|
|
749
|
-
operator,
|
|
750
|
-
fieldType,
|
|
751
|
-
placeholder,
|
|
752
|
-
className
|
|
753
|
-
}) => {
|
|
754
|
-
const isArrayOperator = operator === "in" || operator === "not_in";
|
|
755
|
-
if (isArrayOperator) {
|
|
756
|
-
return /* @__PURE__ */ jsx(ArrayValueInput, { value, onChange, placeholder, className });
|
|
757
|
-
}
|
|
758
|
-
if (fieldType === "boolean") {
|
|
759
|
-
return /* @__PURE__ */ jsx(BooleanValueInput, { value, onChange, placeholder, className });
|
|
760
|
-
}
|
|
761
|
-
if (fieldType === "number" || fieldType === "integer") {
|
|
762
|
-
return /* @__PURE__ */ jsx(NumberValueInput, { value, onChange, placeholder, className });
|
|
763
|
-
}
|
|
764
|
-
return /* @__PURE__ */ jsx(TextValueInput, { value, onChange, placeholder, className });
|
|
765
|
-
};
|
|
766
|
-
|
|
767
|
-
const PRIMITIVE_TYPES = /* @__PURE__ */ new Set(["string", "number", "boolean", "integer"]);
|
|
768
|
-
const RuleRow = ({ schema, rule, onChange, onRemove, className }) => {
|
|
769
|
-
const fieldType = React.useMemo(() => {
|
|
770
|
-
return getFieldOptionAtPath(schema, rule.field)?.type;
|
|
771
|
-
}, [schema, rule.field]);
|
|
772
|
-
const isPrimitive = fieldType !== void 0 && PRIMITIVE_TYPES.has(fieldType);
|
|
773
|
-
const isArray = fieldType === "array";
|
|
774
|
-
const isArrayOperator = rule.operator === "in" || rule.operator === "not_in";
|
|
775
|
-
const isExistenceOperator = rule.operator === "exists" || rule.operator === "not_exists";
|
|
776
|
-
const showComparator = isPrimitive || isArray;
|
|
777
|
-
const showValueInput = !isExistenceOperator && (isPrimitive || isArray && isArrayOperator);
|
|
778
|
-
const handleFieldChange = React.useCallback(
|
|
779
|
-
(field) => {
|
|
780
|
-
onChange({ ...rule, field });
|
|
781
|
-
},
|
|
782
|
-
[rule, onChange]
|
|
783
|
-
);
|
|
784
|
-
const handleOperatorChange = React.useCallback(
|
|
785
|
-
(operator) => {
|
|
786
|
-
const isNewExistence = operator === "exists" || operator === "not_exists";
|
|
787
|
-
if (isNewExistence) {
|
|
788
|
-
onChange({ ...rule, operator, value: void 0 });
|
|
789
|
-
return;
|
|
790
|
-
}
|
|
791
|
-
const isArrayOperator2 = operator === "in" || operator === "not_in";
|
|
792
|
-
const wasArrayOperator = rule.operator === "in" || rule.operator === "not_in";
|
|
793
|
-
let newValue = rule.value;
|
|
794
|
-
if (isArrayOperator2 && !wasArrayOperator) {
|
|
795
|
-
newValue = rule.value !== void 0 ? [rule.value] : [];
|
|
796
|
-
} else if (!isArrayOperator2 && wasArrayOperator) {
|
|
797
|
-
newValue = Array.isArray(rule.value) ? rule.value[0] : rule.value;
|
|
798
|
-
}
|
|
799
|
-
onChange({ ...rule, operator, value: newValue });
|
|
800
|
-
},
|
|
801
|
-
[rule, onChange]
|
|
802
|
-
);
|
|
803
|
-
const handleValueChange = React.useCallback(
|
|
804
|
-
(value) => {
|
|
805
|
-
onChange({ ...rule, value });
|
|
806
|
-
},
|
|
807
|
-
[rule, onChange]
|
|
808
|
-
);
|
|
809
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex justify-between gap-2", children: [
|
|
810
|
-
/* @__PURE__ */ jsxs("div", { className: cn("flex flex-wrap items-center gap-2", className), children: [
|
|
811
|
-
/* @__PURE__ */ jsx(RuleFieldSelect, { schema, value: rule.field, onChange: handleFieldChange }),
|
|
812
|
-
showComparator && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
813
|
-
/* @__PURE__ */ jsx(
|
|
814
|
-
RuleOperatorSelect,
|
|
815
|
-
{
|
|
816
|
-
value: rule.operator,
|
|
817
|
-
onChange: handleOperatorChange,
|
|
818
|
-
operators: isArray ? ["in", "not_in"] : void 0
|
|
819
|
-
}
|
|
820
|
-
),
|
|
821
|
-
showValueInput && /* @__PURE__ */ jsx(
|
|
822
|
-
RuleValueInput,
|
|
823
|
-
{
|
|
824
|
-
value: rule.value,
|
|
825
|
-
onChange: handleValueChange,
|
|
826
|
-
operator: rule.operator,
|
|
827
|
-
fieldType
|
|
828
|
-
}
|
|
829
|
-
)
|
|
830
|
-
] })
|
|
831
|
-
] }),
|
|
832
|
-
/* @__PURE__ */ jsx(Button, { type: "button", onClick: onRemove, tooltip: "Remove rule", size: "icon-sm", variant: "ghost", children: /* @__PURE__ */ jsx(X, {}) })
|
|
833
|
-
] });
|
|
834
|
-
};
|
|
835
|
-
|
|
836
|
-
const DEFAULT_MAX_DEPTH = 3;
|
|
837
|
-
const RuleGroupView = ({ schema, group, onChange, onRemove, depth, maxDepth }) => {
|
|
838
|
-
const isRoot = depth === 0;
|
|
839
|
-
const handleToggleOperator = () => {
|
|
840
|
-
onChange({ ...group, operator: group.operator === "AND" ? "OR" : "AND" });
|
|
841
|
-
};
|
|
842
|
-
const handleConditionChange = (index, condition) => {
|
|
843
|
-
onChange({
|
|
844
|
-
...group,
|
|
845
|
-
conditions: group.conditions.map((c, i) => i === index ? condition : c)
|
|
846
|
-
});
|
|
847
|
-
};
|
|
848
|
-
const handleRemoveCondition = (index) => {
|
|
849
|
-
const newConditions = group.conditions.filter((_, i) => i !== index);
|
|
850
|
-
if (newConditions.length === 0 && onRemove) {
|
|
851
|
-
onRemove();
|
|
852
|
-
} else {
|
|
853
|
-
onChange({ ...group, conditions: newConditions });
|
|
854
|
-
}
|
|
855
|
-
};
|
|
856
|
-
const handleAddRule = () => {
|
|
857
|
-
onChange({ ...group, conditions: [...group.conditions, createDefaultRule()] });
|
|
858
|
-
};
|
|
859
|
-
const handleAddGroup = () => {
|
|
860
|
-
onChange({
|
|
861
|
-
...group,
|
|
862
|
-
conditions: [
|
|
863
|
-
...group.conditions,
|
|
864
|
-
createDefaultRuleGroup(group.operator === "AND" ? "OR" : "AND")
|
|
865
|
-
]
|
|
866
|
-
});
|
|
867
|
-
};
|
|
868
|
-
return /* @__PURE__ */ jsxs("div", { className: cn(isRoot ? "bg-surface2" : "pl-6 bg-surface3"), children: [
|
|
869
|
-
!isRoot && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pl-3 pr-4 py-1.5 border-b border-border1 border-dashed", children: [
|
|
870
|
-
/* @__PURE__ */ jsx("span", { className: "text-ui-xs text-neutral3", children: "Group" }),
|
|
871
|
-
onRemove && /* @__PURE__ */ jsx(Button, { type: "button", onClick: onRemove, tooltip: "Remove group", size: "icon-sm", variant: "ghost", children: /* @__PURE__ */ jsx(X, {}) })
|
|
872
|
-
] }),
|
|
873
|
-
group.conditions.map((condition, index) => /* @__PURE__ */ jsx("div", { className: "border-b border-border1 border-dashed last:border-b-0", children: /* @__PURE__ */ jsxs("div", { className: cn("relative", isRule(condition) && "p-4 border-l-4 border-border1"), children: [
|
|
874
|
-
index > 0 && /* @__PURE__ */ jsx(
|
|
875
|
-
"button",
|
|
876
|
-
{
|
|
877
|
-
type: "button",
|
|
878
|
-
onClick: handleToggleOperator,
|
|
879
|
-
className: cn(
|
|
880
|
-
"absolute left-1/2 -translate-x-1/2 z-10 -translate-y-1/2 top-0 text-ui-xs px-3 py-0.5 rounded-full cursor-pointer",
|
|
881
|
-
group.operator === "OR" ? "bg-accent6Dark text-accent6 hover:bg-accent6Dark/70" : "bg-accent3Dark text-accent3 hover:bg-accent3Dark/70"
|
|
882
|
-
),
|
|
883
|
-
children: group.operator.toLowerCase()
|
|
884
|
-
}
|
|
885
|
-
),
|
|
886
|
-
isRule(condition) ? /* @__PURE__ */ jsx(
|
|
887
|
-
RuleRow,
|
|
888
|
-
{
|
|
889
|
-
schema,
|
|
890
|
-
rule: condition,
|
|
891
|
-
onChange: (updatedRule) => handleConditionChange(index, updatedRule),
|
|
892
|
-
onRemove: () => handleRemoveCondition(index)
|
|
893
|
-
}
|
|
894
|
-
) : /* @__PURE__ */ jsx(
|
|
895
|
-
RuleGroupView,
|
|
896
|
-
{
|
|
897
|
-
schema,
|
|
898
|
-
group: condition,
|
|
899
|
-
onChange: (updatedGroup) => handleConditionChange(index, updatedGroup),
|
|
900
|
-
onRemove: () => handleRemoveCondition(index),
|
|
901
|
-
depth: depth + 1,
|
|
902
|
-
maxDepth
|
|
903
|
-
}
|
|
904
|
-
)
|
|
905
|
-
] }) }, index)),
|
|
906
|
-
/* @__PURE__ */ jsxs("div", { className: "p-2 flex gap-1", children: [
|
|
907
|
-
/* @__PURE__ */ jsxs(Button, { type: "button", onClick: handleAddRule, variant: "ghost", size: "sm", children: [
|
|
908
|
-
/* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Plus, {}) }),
|
|
909
|
-
"Add rule"
|
|
910
|
-
] }),
|
|
911
|
-
depth < maxDepth - 1 && /* @__PURE__ */ jsxs(Button, { type: "button", onClick: handleAddGroup, variant: "ghost", size: "sm", children: [
|
|
912
|
-
/* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Component, {}) }),
|
|
913
|
-
"Add group"
|
|
914
|
-
] })
|
|
915
|
-
] })
|
|
916
|
-
] });
|
|
917
|
-
};
|
|
918
|
-
const RuleBuilder = ({
|
|
919
|
-
schema,
|
|
920
|
-
ruleGroup,
|
|
921
|
-
onChange,
|
|
922
|
-
maxDepth = DEFAULT_MAX_DEPTH,
|
|
923
|
-
className
|
|
924
|
-
}) => {
|
|
925
|
-
const handleGroupChange = React.useCallback(
|
|
926
|
-
(group) => {
|
|
927
|
-
onChange(group);
|
|
928
|
-
},
|
|
929
|
-
[onChange]
|
|
930
|
-
);
|
|
931
|
-
const handleAddFirstRule = React.useCallback(() => {
|
|
932
|
-
onChange({ operator: "AND", conditions: [createDefaultRule()] });
|
|
933
|
-
}, [onChange]);
|
|
934
|
-
if (!ruleGroup) {
|
|
935
|
-
return /* @__PURE__ */ jsxs(
|
|
936
|
-
"button",
|
|
937
|
-
{
|
|
938
|
-
type: "button",
|
|
939
|
-
onClick: handleAddFirstRule,
|
|
940
|
-
className: "flex items-center justify-center gap-2 text-ui-sm text-neutral3 hover:text-neutral6 w-full border border-dashed border-border1 p-2 rounded-md",
|
|
941
|
-
children: [
|
|
942
|
-
/* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Plus, {}) }),
|
|
943
|
-
"Add conditional rule"
|
|
944
|
-
]
|
|
945
|
-
}
|
|
946
|
-
);
|
|
947
|
-
}
|
|
948
|
-
return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx(RuleGroupView, { schema, group: ruleGroup, onChange: handleGroupChange, depth: 0, maxDepth }) });
|
|
949
|
-
};
|
|
950
|
-
|
|
951
225
|
const PanelEdgeIcon = ({ side }) => /* @__PURE__ */ jsxs(
|
|
952
226
|
"svg",
|
|
953
227
|
{
|
|
@@ -1316,104 +590,6 @@ const PanelDrawer = ({ direction, label, children }) => {
|
|
|
1316
590
|
] });
|
|
1317
591
|
};
|
|
1318
592
|
|
|
1319
|
-
const EXTENSION_TO_MIME = {
|
|
1320
|
-
jpg: "image/jpg",
|
|
1321
|
-
jpeg: "image/jpeg",
|
|
1322
|
-
png: "image/png",
|
|
1323
|
-
gif: "image/gif",
|
|
1324
|
-
webp: "image/webp",
|
|
1325
|
-
svg: "image/svg+xml",
|
|
1326
|
-
bmp: "image/bmp",
|
|
1327
|
-
ico: "image/x-icon",
|
|
1328
|
-
pdf: "application/pdf",
|
|
1329
|
-
// Video
|
|
1330
|
-
mp4: "video/mp4",
|
|
1331
|
-
mov: "video/quicktime",
|
|
1332
|
-
webm: "video/webm",
|
|
1333
|
-
mkv: "video/x-matroska",
|
|
1334
|
-
avi: "video/x-msvideo",
|
|
1335
|
-
mpeg: "video/mpeg",
|
|
1336
|
-
mpg: "video/mpeg",
|
|
1337
|
-
// Audio
|
|
1338
|
-
mp3: "audio/mpeg",
|
|
1339
|
-
wav: "audio/wav",
|
|
1340
|
-
ogg: "audio/ogg",
|
|
1341
|
-
oga: "audio/ogg",
|
|
1342
|
-
m4a: "audio/mp4",
|
|
1343
|
-
aac: "audio/aac",
|
|
1344
|
-
flac: "audio/flac"
|
|
1345
|
-
};
|
|
1346
|
-
|
|
1347
|
-
const BROWSER_FETCHABLE_SCHEMES = ["https://", "http://"];
|
|
1348
|
-
const NON_FETCHABLE_REMOTE_SCHEMES = ["gs://", "s3://"];
|
|
1349
|
-
const REMOTE_URL_SCHEMES = [...BROWSER_FETCHABLE_SCHEMES, ...NON_FETCHABLE_REMOTE_SCHEMES];
|
|
1350
|
-
const isRemoteUrl = (value) => REMOTE_URL_SCHEMES.some((scheme) => value.startsWith(scheme));
|
|
1351
|
-
const isBrowserFetchableUrl = (value) => BROWSER_FETCHABLE_SCHEMES.some((scheme) => value.startsWith(scheme));
|
|
1352
|
-
const isNonFetchableRemoteUrl = (value) => NON_FETCHABLE_REMOTE_SCHEMES.some((scheme) => value.startsWith(scheme));
|
|
1353
|
-
|
|
1354
|
-
const contentTypeFromExtension = (url) => {
|
|
1355
|
-
try {
|
|
1356
|
-
const { pathname } = new URL(url);
|
|
1357
|
-
const extension = pathname.split(".").pop();
|
|
1358
|
-
if (!extension) return void 0;
|
|
1359
|
-
return EXTENSION_TO_MIME[extension.toLowerCase()];
|
|
1360
|
-
} catch {
|
|
1361
|
-
const extension = url.split(".").pop()?.split(/[?#]/)[0];
|
|
1362
|
-
if (!extension) return void 0;
|
|
1363
|
-
return EXTENSION_TO_MIME[extension.toLowerCase()];
|
|
1364
|
-
}
|
|
1365
|
-
};
|
|
1366
|
-
const getFileContentType = async (url) => {
|
|
1367
|
-
if (NON_FETCHABLE_REMOTE_SCHEMES.some((scheme) => url.startsWith(scheme))) {
|
|
1368
|
-
return contentTypeFromExtension(url);
|
|
1369
|
-
}
|
|
1370
|
-
try {
|
|
1371
|
-
const response = await fetch(url, {
|
|
1372
|
-
method: "HEAD"
|
|
1373
|
-
});
|
|
1374
|
-
if (!response.ok) {
|
|
1375
|
-
throw new Error("Failed to get file content type");
|
|
1376
|
-
}
|
|
1377
|
-
const contentType = response.headers.get("content-type");
|
|
1378
|
-
if (!contentType) {
|
|
1379
|
-
throw new Error("Failed to get file content type");
|
|
1380
|
-
}
|
|
1381
|
-
return contentType;
|
|
1382
|
-
} catch {
|
|
1383
|
-
return contentTypeFromExtension(url);
|
|
1384
|
-
}
|
|
1385
|
-
};
|
|
1386
|
-
|
|
1387
|
-
const downloadJson = (filename, data) => {
|
|
1388
|
-
const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
|
|
1389
|
-
const url = URL.createObjectURL(blob);
|
|
1390
|
-
const anchor = document.createElement("a");
|
|
1391
|
-
anchor.href = url;
|
|
1392
|
-
anchor.download = filename;
|
|
1393
|
-
document.body.appendChild(anchor);
|
|
1394
|
-
anchor.click();
|
|
1395
|
-
anchor.remove();
|
|
1396
|
-
URL.revokeObjectURL(url);
|
|
1397
|
-
};
|
|
1398
|
-
|
|
1399
|
-
const fileToBase64 = async (file) => {
|
|
1400
|
-
return new Promise((resolve, reject) => {
|
|
1401
|
-
const reader = new FileReader();
|
|
1402
|
-
reader.onload = () => {
|
|
1403
|
-
const result = reader.result;
|
|
1404
|
-
if (typeof result === "string") {
|
|
1405
|
-
resolve(result);
|
|
1406
|
-
} else {
|
|
1407
|
-
reject(new Error("Failed to convert file to base64."));
|
|
1408
|
-
}
|
|
1409
|
-
};
|
|
1410
|
-
reader.onerror = (error) => {
|
|
1411
|
-
reject(error);
|
|
1412
|
-
};
|
|
1413
|
-
reader.readAsDataURL(file);
|
|
1414
|
-
});
|
|
1415
|
-
};
|
|
1416
|
-
|
|
1417
593
|
const MAX_DEPTH = 10;
|
|
1418
594
|
function generatePropertyDefault(property, depth) {
|
|
1419
595
|
if (property.default !== void 0) {
|
|
@@ -9034,5 +8210,5 @@ function SignalsOverviewPage({ onSignalSelect }) {
|
|
|
9034
8210
|
return /* @__PURE__ */ jsx(TopicsLayout, { sidebar: null, contentPadding: false, children: /* @__PURE__ */ jsx("nav", { className: "h-full min-w-0 overflow-y-auto p-6", "aria-label": "Signals", children: /* @__PURE__ */ jsx("div", { className: "mx-auto flex max-w-6xl flex-col gap-12", children: signals.map((signal) => /* @__PURE__ */ jsx(SignalSection, { signal, onSeeDetails: onSignalSelect }, signal.id)) }) }) });
|
|
9035
8211
|
}
|
|
9036
8212
|
|
|
9037
|
-
export { AgentIcon,
|
|
8213
|
+
export { AgentIcon, Badge, BarListContent, Button, ButtonsGroup, CHART_COLORS, CONTEXT_FIELD_IDS, Checkbox, CodeDiff, CollapsiblePanel, CopyButton, DATE_PRESETS, DEFAULT_LOGS_FILTERS_STORAGE_KEY, DEFAULT_TRACE_FILTERS_STORAGE_KEY, DataDetailsPanel, DataKeysAndValues, DataList, DataListSkeleton, DataPanel, DateRangeSelector, DateTimeRangePicker, Drawer, DrawerBackdrop, DrawerPopup, DrawerPortal, DrawerTitle, DrawerTrigger, DrawerViewport, DropdownMenu, EmptyState, ErrorState, FlameGraph, FolderIcon, HorizontalBars, HoverCard, HoverCardContent, HoverCardTrigger, Icon, KpiCardView, LOGS_DATE_FROM_PARAM, LOGS_DATE_PRESET_PARAM, LOGS_DATE_PRESET_VALUES, LOGS_DATE_TO_PARAM, LOGS_PROPERTY_FILTER_FIELD_IDS, LOGS_PROPERTY_FILTER_PARAM_BY_FIELD, LOGS_ROOT_ENTITY_TYPES, LOGS_ROOT_ENTITY_TYPE_OPTIONS, LOGS_ROOT_ENTITY_TYPE_PARAM, LOG_LEVEL_OPTIONS, LOG_LEVEL_VALUES, LatencyCardView, LogDetailsView, LogsDataList, DataListSkeleton as LogsDataListSkeleton, LogsErrorContent, LogsLayout, LogsListView, LogsToolbar, McpServerIcon, MemoryCardView, MemoryIcon, MemoryStudioPanel, MetricsCard, MetricsLineChart, MetricsProvider, ModelUsageCostCardView, NoLogsInfo, NoTracesInfo, Notice, ObservationDetailView, OpenErrorsInLogsButton, OpenInTracesButton, PanelDrawer, PanelSeparator, PermissionDenied, PropertyFilterActions, PropertyFilterApplied, ROOT_ENTITY_TYPES, ROOT_ENTITY_TYPE_OPTIONS, ScatterPlotChart, ScoresCardView, Searchbar, SessionExpired, SignalChartTab, SignalClusterCard, SignalClusterSidebar, SignalClusterTabs, SignalDetailsPage, SignalSection, SignalTraceDetailsPanel, SignalTraceListTab, SignalsOverviewPage, Skeleton, SpanDataPanelView, SpanDetailsView, SpanTokenUsage, Spinner, StackedRunsBars, TRACE_ANCHOR_SPAN_ID_PARAM, TRACE_DATE_FROM_PARAM, TRACE_DATE_PRESET_PARAM, TRACE_DATE_PRESET_VALUES, TRACE_DATE_TO_PARAM, TRACE_LIST_MODE_OPTIONS, TRACE_LIST_MODE_PARAM, TRACE_LIST_MODE_VALUES, TRACE_PROPERTY_FILTER_FIELD_IDS, TRACE_PROPERTY_FILTER_PARAM_BY_FIELD, TRACE_ROOT_ENTITY_TYPE_PARAM, TRACE_STATUS_OPTIONS, TRACE_STATUS_PARAM, TRACE_STATUS_VALUES, TRACE_SYNTHETIC_FILTER_FIELD_IDS, Tab, TabContent, TabList, Tabs, ThreadContextProgress, TimelineExpandCol, TimelineNameCol, TimelineStructureSign, TimelineTimingCol, TokenUsageByAgentCardView, TokenUsageTimelineCardView, ToolsIcon, Tooltip, TooltipContent, TooltipTrigger, TopicTraceDetailsPanel, TopicTraceSummaryList, TopicsLayout, TraceDataPanelView, TraceDetailsView, TraceKeysAndValues, TraceTimeline, TraceTimelineSpan, TracesDataList, TracesErrorContent, TracesLayout, TracesListModeToggle, TracesListView, TracesToolbar, TracesVolumeCardView, Txt, WorkflowIcon, aggregateTopics, applyLogsPropertyFilterTokens, applyMetricsPropertyFilterTokens, applyTracePropertyFilterTokens, buildLogsDrilldownUrl, buildLogsListFilters, buildMetricsDimensionalFilter, buildTraceListFilters, buildTracesDrilldownUrl, clearSavedLogsFilters, clearSavedMetricsFilters, clearSavedTraceFilters, cn, createLogsPropertyFilterFields, createMetricsPropertyFilterFields, createTracePropertyFilterFields, downloadJson, filterTraceSummaries, formatCompact, formatCost, formatHierarchicalSpans, generateDefaultValues, getAllSpanIds, getInputPreview, getLogsPropertyFilterTokens, getMetricsPropertyFilterTokens, getPreservedLogsFilterParams, getPreservedTraceFilterParams, getSignalChartData, getSignalName, getSpanDescendantIds, getSpanTypeUi, getTokenLimitMessage, getTopicColor, getTopicTraceCount, getTraceCount, getTracePropertyFilterTokens, getTraceShare$1 as getTraceShare, getVisibleTraceSummaries, hasAnyLogsFilterParams, hasAnyMetricsFilterParams, hasAnyTraceFilterParams, is401UnauthorizedError, is403ForbiddenError, isObjectEmpty, isTokenLimitExceeded, isUnsupportedObservabilityOperationError, isValidPreset, loadLogsFiltersFromStorage, loadMetricsFiltersFromStorage, loadTraceFiltersFromStorage, memoryStatusQueryKey, memoryThreadMessagesQueryKey, narrowWindowToBucket, neutralizeFilterTokens, neutralizeLogsFilterTokens, observationalMemoryQueryKey, parseError, saveLogsFiltersToStorage, saveMetricsFiltersToStorage, saveTraceFiltersToStorage, signals, sortTraceSummaries, spanTypePrefixes, stringToColor, toast, truncateString, useActiveResourcesKpiMetrics, useActiveThreadsKpiMetrics, useAgentRunsKpiMetrics, useBranch, useDownloadTraceJson, useDrilldown, useEntityNames, useEnvironments, useInView, useLatencyMetrics, useLogs, useLogsFilterPersistence, useLogsListNavigation, useLogsUrlState, useMemoryStatus, useMemoryThreadMessages, useMetrics, useMetricsFilters, useModelCostKpiMetrics, useModelUsageCostMetrics, useObservationalMemory, usePlaygroundStore, useScoresMetrics, useServiceNames, useSpanDetail, useTags, useTokenUsageByAgentMetrics, useTokenUsageTimeSeries, useTopActiveThreadsMetrics, useTopResourcesByThreadsMetrics, useTotalTokensKpiMetrics, useTraceFilterPersistence, useTraceLightSpans, useTraceListNavigation, useTraceOrBranchSpans, useTraceSpanNavigation, useTraceSpans, useTraceUrlState, useTraceVolumeMetrics, useTraces };
|
|
9038
8214
|
//# sourceMappingURL=index.es.js.map
|