@xenosystem/blocks 0.13.9 → 0.13.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/index.d.ts +77 -11
- package/dist/data/index.js +238 -185
- package/package.json +3 -3
package/dist/data/index.d.ts
CHANGED
|
@@ -1401,18 +1401,59 @@ declare const METRICS_PANEL_ID = "xeno.core.metrics";
|
|
|
1401
1401
|
declare const metricsManifest: PanelManifest;
|
|
1402
1402
|
|
|
1403
1403
|
/**
|
|
1404
|
-
* The Metrics panel
|
|
1404
|
+
* The Metrics panel AS A DECLARATION — the twelfth declared block: KPI tiles over a data-core result.
|
|
1405
1405
|
*
|
|
1406
|
-
*
|
|
1407
|
-
*
|
|
1408
|
-
*
|
|
1409
|
-
*
|
|
1410
|
-
*
|
|
1406
|
+
* Everything drawn is data: the range control and partial badge in the toolbar (only when ranges
|
|
1407
|
+
* exist), the error and empty states, a `TileGrid` of `StatTile`s — each with its level badge, its
|
|
1408
|
+
* display value (an em dash for a partial null, never a zero), a `Delta` toned by the metric's
|
|
1409
|
+
* direction, the partial note, the `Sparkline` — and the status bar. A tile activates as a real
|
|
1410
|
+
* button (`StatTile.onActivate`). No runtime-bound unit.
|
|
1411
1411
|
*/
|
|
1412
1412
|
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1413
|
+
interface MetricsViewTile {
|
|
1414
|
+
id: string;
|
|
1415
|
+
label: string;
|
|
1416
|
+
title?: string;
|
|
1417
|
+
value: string;
|
|
1418
|
+
level: string;
|
|
1419
|
+
hasLevel: boolean;
|
|
1420
|
+
tone: 'error' | 'warning';
|
|
1421
|
+
hasDelta: boolean;
|
|
1422
|
+
delta: number;
|
|
1423
|
+
deltaTone: 'good' | 'bad' | 'neutral';
|
|
1424
|
+
partial: boolean;
|
|
1425
|
+
hasSpark: boolean;
|
|
1426
|
+
spark: number[];
|
|
1427
|
+
sparkLabel: string;
|
|
1428
|
+
}
|
|
1429
|
+
interface MetricsViewModel {
|
|
1430
|
+
hasRanges: boolean;
|
|
1431
|
+
ranges: {
|
|
1432
|
+
value: string;
|
|
1433
|
+
label: string;
|
|
1434
|
+
}[];
|
|
1435
|
+
rangeId: string;
|
|
1436
|
+
partial: boolean;
|
|
1437
|
+
partialHint: string;
|
|
1438
|
+
errorMessage?: string;
|
|
1439
|
+
errored: boolean;
|
|
1440
|
+
empty: boolean;
|
|
1441
|
+
emptyHint: string;
|
|
1442
|
+
ready: boolean;
|
|
1443
|
+
layout: 'grid' | 'row' | 'list';
|
|
1444
|
+
columns: number;
|
|
1445
|
+
tiles: MetricsViewTile[];
|
|
1446
|
+
countLabel: string;
|
|
1447
|
+
partialLabel?: string;
|
|
1448
|
+
}
|
|
1449
|
+
type MetricsUiIntent = {
|
|
1450
|
+
kind: 'range';
|
|
1451
|
+
rangeId: string;
|
|
1452
|
+
} | {
|
|
1453
|
+
kind: 'activate';
|
|
1454
|
+
metricId: string;
|
|
1455
|
+
};
|
|
1456
|
+
interface MetricsViewOptions {
|
|
1416
1457
|
layout?: 'grid' | 'row' | 'list';
|
|
1417
1458
|
columns?: number;
|
|
1418
1459
|
sparkline?: boolean;
|
|
@@ -1420,8 +1461,33 @@ interface MetricsPanelViewProps {
|
|
|
1420
1461
|
emptyHint?: string;
|
|
1421
1462
|
partialHint?: string;
|
|
1422
1463
|
}
|
|
1464
|
+
/** Derive the view from the live controller — the runtime calls this on every draw. */
|
|
1465
|
+
declare function metricsViewState(c: MetricsController, options?: MetricsViewOptions): MetricsViewModel;
|
|
1466
|
+
declare function applyMetricsUi(c: MetricsController, intent: MetricsUiIntent): void;
|
|
1467
|
+
declare const metricsViewManifest: PanelManifest;
|
|
1468
|
+
declare const BEHAVIOURS$1: {
|
|
1469
|
+
'data/metricsPanelView': (inputs: Record<string, unknown>) => MetricsViewModel;
|
|
1470
|
+
};
|
|
1471
|
+
declare const METRICS_RUNTIME_UNITS: readonly [];
|
|
1472
|
+
declare const METRICS_DECLARATION: BlockDeclaration;
|
|
1473
|
+
|
|
1474
|
+
/**
|
|
1475
|
+
* The Metrics panel view — the CODE VIEW of `METRICS_DECLARATION`, drawing the same
|
|
1476
|
+
* `MetricsViewModel` byte-identical (the equivalence suite holds the two together). No runtime-bound
|
|
1477
|
+
* unit; every intent goes through `applyMetricsUi`.
|
|
1478
|
+
*
|
|
1479
|
+
* Composes `@xenosystem/components/chrome`; the host must ensure `@xenosystem/workbench/primitives.css` is
|
|
1480
|
+
* present.
|
|
1481
|
+
*
|
|
1482
|
+
* @module
|
|
1483
|
+
*/
|
|
1484
|
+
|
|
1485
|
+
/** Props for {@link MetricsPanelView}. */
|
|
1486
|
+
interface MetricsPanelViewProps extends MetricsViewOptions {
|
|
1487
|
+
controller: MetricsController;
|
|
1488
|
+
}
|
|
1423
1489
|
/** The Metrics panel view. */
|
|
1424
|
-
declare function MetricsPanelView({ controller,
|
|
1490
|
+
declare function MetricsPanelView({ controller, ...options }: MetricsPanelViewProps): ReactNode;
|
|
1425
1491
|
|
|
1426
1492
|
/**
|
|
1427
1493
|
* The `xeno.core.fields` contract — the query AUTHOR.
|
|
@@ -3381,4 +3447,4 @@ interface ConnectorsPanelViewProps {
|
|
|
3381
3447
|
/** The Connectors panel view. */
|
|
3382
3448
|
declare function ConnectorsPanelView({ controller, emptyHint, }: ConnectorsPanelViewProps): ReactNode;
|
|
3383
3449
|
|
|
3384
|
-
export { AGENT_HIDDEN_COMMANDS, ALL_AGGREGATES, ALL_CHART_TYPES, type BuildChartOptions, type BuildSelectOptions, type BuildSelectResult, CHART_EMPTY_FILL, CHART_PALETTE_STEPS, CHART_PANEL_ID, CONNECTORS_PANEL_ID, type CellAddress, ChartController, type ChartControllerOptions, type ChartHostBridge, type ChartPanelState, ChartPanelView, type ChartPanelViewProps, type ChartRenderContext, type ChartRenderInput, type ChartRenderOptions, type ChartRenderer, type ChartViewState, type ColumnLayout, type ColumnWindow, ConnectorExecuteInput, ConnectorExecuteOutput, ConnectorTransport, ConnectorsController, type ConnectorsControllerOptions, type ConnectorsHostBridge, ConnectorsPanelState, ConnectorsPanelView, type ConnectorsPanelViewProps, type ConnectorsRenderContext, ConnectorsViewState, type CreateChartPanelOptions, type CreateConnectorExecutorOptions, type CreateConnectorsPanelOptions, type CreateFieldsPanelOptions, type CreateMetricsPanelOptions, type CreateTablePanelOptions, type CredentialDraft, type CredentialErrors, DEFAULT_COLUMN_WIDTH, DEFAULT_PAGE_SIZE, DEFAULT_RANGES, type DeltaDirection, EMPTY_LAYOUT, EXPIRY_SKEW_MS, type ExecuteError, BEHAVIOURS as FIELDS_BEHAVIOURS, FIELDS_DECLARATION, FIELDS_PANEL_ID, FIELDS_RUNTIME_UNITS, FieldsController, type FieldsControllerOptions, type FieldsHostBridge, type FieldsPanelState, FieldsPanelView, type FieldsPanelViewProps, type FieldsRenderContext, type FieldsUiIntent, type FieldsViewColumn, type FieldsViewEntry, type FieldsViewFilter, type FieldsViewModel, type FieldsViewOptions, type FieldsViewShelf, type FieldsViewState, type HostSqlResolver, IMPLEMENTED_VIEW_MODES, type LoopbackRequest, type LoopbackVerdict, METRICS_PANEL_ID, MIN_COLUMN_WIDTH, MONO_FILL_PALETTE, MONO_PALETTE, MetricsController, type MetricsControllerOptions, type MetricsHostBridge, type MetricsPanelState, MetricsPanelView, type MetricsPanelViewProps, type MetricsRenderContext, type MetricsViewState, type NumericConstraints, type OAuthStateRecord, type OAuthStateStore, type OAuthStateStoreOptions, type ParseCsvOptions, type ParseResult, type ParsedCsv, type PkcePair, PushdownSplit, type RefreshCoordinator, type ResolvedColumn, SHELF_PRESETS, type StoredOAuthToken, SubstrateFacilities, TABLE_PANEL_ID, TableController, type TableControllerOptions, type TableHostBridge, type TablePanelState, TablePanelView, type TablePanelViewProps, type TableRenderContext, type TableViewMode, type TableViewState, type TokenEndpointResponse, type VirtualWindow, type XenoAlertLevel, type XenoCalculatedFieldRequest, type XenoCellEdit, type XenoChartData, type XenoChartDrillDown, type XenoChartEncoding, type XenoChartExportRequest, type XenoChartHighlight, type XenoChartSeries, type XenoChartType, XenoConnection, XenoConnectionStatus, XenoConnectorFetch, XenoConnectorFileReader, XenoConnectorQueryRequest, XenoCredentialField, XenoCredentialFormSpec, XenoCredentialResult, type XenoFieldStat, type XenoMetricAlert, type XenoMetricRange, type XenoMetricSpec, type XenoMetricThreshold, type XenoMetricValue, XenoResolverErrorCode, XenoRestPaging, type XenoRowActivate, type XenoShelfEntry, type XenoShelfSpec, XenoSqlEngine, applyFieldsUi, applyPrecision, base64Url, breachSideOf, buildChartData, buildRestUrl, buildSelect, chartManifest, chartPanel, clamp, classifyHttpStatus, coerceCsvValues, columnIndexAt, columnsOf, compileForHost, computeColumnWindow, computeWindow, connectorsManifest, connectorsPanel, constraintsOfColumn, createChartPanel, createConnectorExecutor, createConnectorsPanel, createFieldsPanel, createMetricsPanel, createOAuthStateStore, createPkcePair, createRefreshCoordinator, createTablePanel, credentialSpecProblem, defaultAggregateFor, defaultEncoding, deltaToneOf, emptyFilterGroup, entityOf, escapeLikePattern, executeCsvFile, executeDuckDb, executeGraphql, executeJsonFile, executeRest, executeSql, extractJsonPath, extractRows, fieldsManifest, fieldsPanel, fieldsViewManifest, fieldsViewState, firstGraphqlError, frozenWidth, getChartRenderer, isCategorical, isFieldVisible, isFilled, isLeafFilter, isLoopbackHost, isSafeTableName, mergeRefreshResponse, metricsManifest, metricsPanel, moveCell, moveColumn, needsRefresh, nextPageToken, normalizeLayout, normalizeNumeric, offerableAggregates, offerableFilterOps, parseCsv, parseJsonBody, parseJsonPath, parseLinkHeader, parseNumeric, pruneHiddenValues, queriesEqual, quoteIdent, quoteLiteral, redirectUriFor, renderFilterGroup, resolveChartColors, resolveColumns, rowsForMark, scrollLeftToReveal, scrollTopToReveal, setChartRenderer, setColumnVisible, setColumnWidth, setFrozenCount, sniffDelimiter, suggestedShelfFor, tableManifest, tablePanel, toChartJsConfig, toExecuteError, totalWidth, uniqueTableName, unsupportedMessage, validateCredentialDraft, validateEncoding, validateLoopbackRequest, visibleFields };
|
|
3450
|
+
export { AGENT_HIDDEN_COMMANDS, ALL_AGGREGATES, ALL_CHART_TYPES, type BuildChartOptions, type BuildSelectOptions, type BuildSelectResult, CHART_EMPTY_FILL, CHART_PALETTE_STEPS, CHART_PANEL_ID, CONNECTORS_PANEL_ID, type CellAddress, ChartController, type ChartControllerOptions, type ChartHostBridge, type ChartPanelState, ChartPanelView, type ChartPanelViewProps, type ChartRenderContext, type ChartRenderInput, type ChartRenderOptions, type ChartRenderer, type ChartViewState, type ColumnLayout, type ColumnWindow, ConnectorExecuteInput, ConnectorExecuteOutput, ConnectorTransport, ConnectorsController, type ConnectorsControllerOptions, type ConnectorsHostBridge, ConnectorsPanelState, ConnectorsPanelView, type ConnectorsPanelViewProps, type ConnectorsRenderContext, ConnectorsViewState, type CreateChartPanelOptions, type CreateConnectorExecutorOptions, type CreateConnectorsPanelOptions, type CreateFieldsPanelOptions, type CreateMetricsPanelOptions, type CreateTablePanelOptions, type CredentialDraft, type CredentialErrors, DEFAULT_COLUMN_WIDTH, DEFAULT_PAGE_SIZE, DEFAULT_RANGES, type DeltaDirection, EMPTY_LAYOUT, EXPIRY_SKEW_MS, type ExecuteError, BEHAVIOURS as FIELDS_BEHAVIOURS, FIELDS_DECLARATION, FIELDS_PANEL_ID, FIELDS_RUNTIME_UNITS, FieldsController, type FieldsControllerOptions, type FieldsHostBridge, type FieldsPanelState, FieldsPanelView, type FieldsPanelViewProps, type FieldsRenderContext, type FieldsUiIntent, type FieldsViewColumn, type FieldsViewEntry, type FieldsViewFilter, type FieldsViewModel, type FieldsViewOptions, type FieldsViewShelf, type FieldsViewState, type HostSqlResolver, IMPLEMENTED_VIEW_MODES, type LoopbackRequest, type LoopbackVerdict, BEHAVIOURS$1 as METRICS_BEHAVIOURS, METRICS_DECLARATION, METRICS_PANEL_ID, METRICS_RUNTIME_UNITS, MIN_COLUMN_WIDTH, MONO_FILL_PALETTE, MONO_PALETTE, MetricsController, type MetricsControllerOptions, type MetricsHostBridge, type MetricsPanelState, MetricsPanelView, type MetricsPanelViewProps, type MetricsRenderContext, type MetricsUiIntent, type MetricsViewModel, type MetricsViewOptions, type MetricsViewState, type MetricsViewTile, type NumericConstraints, type OAuthStateRecord, type OAuthStateStore, type OAuthStateStoreOptions, type ParseCsvOptions, type ParseResult, type ParsedCsv, type PkcePair, PushdownSplit, type RefreshCoordinator, type ResolvedColumn, SHELF_PRESETS, type StoredOAuthToken, SubstrateFacilities, TABLE_PANEL_ID, TableController, type TableControllerOptions, type TableHostBridge, type TablePanelState, TablePanelView, type TablePanelViewProps, type TableRenderContext, type TableViewMode, type TableViewState, type TokenEndpointResponse, type VirtualWindow, type XenoAlertLevel, type XenoCalculatedFieldRequest, type XenoCellEdit, type XenoChartData, type XenoChartDrillDown, type XenoChartEncoding, type XenoChartExportRequest, type XenoChartHighlight, type XenoChartSeries, type XenoChartType, XenoConnection, XenoConnectionStatus, XenoConnectorFetch, XenoConnectorFileReader, XenoConnectorQueryRequest, XenoCredentialField, XenoCredentialFormSpec, XenoCredentialResult, type XenoFieldStat, type XenoMetricAlert, type XenoMetricRange, type XenoMetricSpec, type XenoMetricThreshold, type XenoMetricValue, XenoResolverErrorCode, XenoRestPaging, type XenoRowActivate, type XenoShelfEntry, type XenoShelfSpec, XenoSqlEngine, applyFieldsUi, applyMetricsUi, applyPrecision, base64Url, breachSideOf, buildChartData, buildRestUrl, buildSelect, chartManifest, chartPanel, clamp, classifyHttpStatus, coerceCsvValues, columnIndexAt, columnsOf, compileForHost, computeColumnWindow, computeWindow, connectorsManifest, connectorsPanel, constraintsOfColumn, createChartPanel, createConnectorExecutor, createConnectorsPanel, createFieldsPanel, createMetricsPanel, createOAuthStateStore, createPkcePair, createRefreshCoordinator, createTablePanel, credentialSpecProblem, defaultAggregateFor, defaultEncoding, deltaToneOf, emptyFilterGroup, entityOf, escapeLikePattern, executeCsvFile, executeDuckDb, executeGraphql, executeJsonFile, executeRest, executeSql, extractJsonPath, extractRows, fieldsManifest, fieldsPanel, fieldsViewManifest, fieldsViewState, firstGraphqlError, frozenWidth, getChartRenderer, isCategorical, isFieldVisible, isFilled, isLeafFilter, isLoopbackHost, isSafeTableName, mergeRefreshResponse, metricsManifest, metricsPanel, metricsViewManifest, metricsViewState, moveCell, moveColumn, needsRefresh, nextPageToken, normalizeLayout, normalizeNumeric, offerableAggregates, offerableFilterOps, parseCsv, parseJsonBody, parseJsonPath, parseLinkHeader, parseNumeric, pruneHiddenValues, queriesEqual, quoteIdent, quoteLiteral, redirectUriFor, renderFilterGroup, resolveChartColors, resolveColumns, rowsForMark, scrollLeftToReveal, scrollTopToReveal, setChartRenderer, setColumnVisible, setColumnWidth, setFrozenCount, sniffDelimiter, suggestedShelfFor, tableManifest, tablePanel, toChartJsConfig, toExecuteError, totalWidth, uniqueTableName, unsupportedMessage, validateCredentialDraft, validateEncoding, validateLoopbackRequest, visibleFields };
|
package/dist/data/index.js
CHANGED
|
@@ -198,8 +198,8 @@ function moveCell(from, delta, bounds) {
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
// src/data/table/numeric.ts
|
|
201
|
-
function parseNumeric(
|
|
202
|
-
const trimmed = String(
|
|
201
|
+
function parseNumeric(text3) {
|
|
202
|
+
const trimmed = String(text3).trim();
|
|
203
203
|
if (trimmed.length === 0) return { ok: false, reason: "empty" };
|
|
204
204
|
const match = /^[+-]?(\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/.exec(trimmed);
|
|
205
205
|
if (!match) return { ok: false, reason: "nan" };
|
|
@@ -553,11 +553,11 @@ var TableController = class {
|
|
|
553
553
|
return true;
|
|
554
554
|
}
|
|
555
555
|
/** Update the in-flight draft. Emits `editPreview` only when `livePreview` is on. */
|
|
556
|
-
updateDraft(
|
|
556
|
+
updateDraft(text3) {
|
|
557
557
|
if (!this.editing) return;
|
|
558
|
-
this.editing = { ...this.editing, draft:
|
|
558
|
+
this.editing = { ...this.editing, draft: text3 };
|
|
559
559
|
if (this.livePreview) {
|
|
560
|
-
const parsed = this.parseDraft(this.editing.columnId,
|
|
560
|
+
const parsed = this.parseDraft(this.editing.columnId, text3);
|
|
561
561
|
if (parsed.ok) {
|
|
562
562
|
this.host.emit("editPreview", this.buildEdit(this.editing, parsed.value));
|
|
563
563
|
}
|
|
@@ -609,12 +609,12 @@ var TableController = class {
|
|
|
609
609
|
};
|
|
610
610
|
}
|
|
611
611
|
/** Parse a draft according to the column's declared type. */
|
|
612
|
-
parseDraft(columnId,
|
|
612
|
+
parseDraft(columnId, text3) {
|
|
613
613
|
const column = this.columnById(columnId);
|
|
614
|
-
const trimmed =
|
|
614
|
+
const trimmed = text3.trim();
|
|
615
615
|
if (column?.type === "number" || column?.type === "integer" || column?.type === "duration") {
|
|
616
616
|
if (trimmed === "") return { ok: true, value: null };
|
|
617
|
-
const parsed = parseNumeric(
|
|
617
|
+
const parsed = parseNumeric(text3);
|
|
618
618
|
if (!parsed.ok) return { ok: false, reason: parsed.reason };
|
|
619
619
|
return { ok: true, value: normalizeNumeric(parsed.value, constraintsOfColumn(column)) };
|
|
620
620
|
}
|
|
@@ -631,7 +631,7 @@ var TableController = class {
|
|
|
631
631
|
value: trimmed === "" ? [] : trimmed.split(",").map((part) => part.trim()).filter(Boolean)
|
|
632
632
|
};
|
|
633
633
|
}
|
|
634
|
-
return { ok: true, value: trimmed === "" ? null :
|
|
634
|
+
return { ok: true, value: trimmed === "" ? null : text3 };
|
|
635
635
|
}
|
|
636
636
|
rowById(rowId) {
|
|
637
637
|
return this.result?.rows.find((r) => r.id === rowId);
|
|
@@ -2912,138 +2912,185 @@ var metricsManifest = {
|
|
|
2912
2912
|
import { useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
2913
2913
|
import {
|
|
2914
2914
|
Badge as Badge3,
|
|
2915
|
+
Column,
|
|
2916
|
+
Delta,
|
|
2915
2917
|
EmptyState as EmptyState3,
|
|
2916
2918
|
ErrorState as ErrorState3,
|
|
2917
2919
|
ScrollArea as ScrollArea2,
|
|
2918
2920
|
SegmentedControl as SegmentedControl3,
|
|
2919
2921
|
Sparkline,
|
|
2922
|
+
Stack,
|
|
2920
2923
|
StatTile,
|
|
2921
2924
|
StatusBar as StatusBar3,
|
|
2925
|
+
Text,
|
|
2926
|
+
TileGrid,
|
|
2922
2927
|
Toolbar as Toolbar3
|
|
2923
2928
|
} from "@xenosystem/components/chrome";
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
{
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2929
|
+
|
|
2930
|
+
// src/data/metrics/declaration.ts
|
|
2931
|
+
function metricsViewState(c, options = {}) {
|
|
2932
|
+
const s = c.getState();
|
|
2933
|
+
const sparkline = options.sparkline ?? true;
|
|
2934
|
+
const showDelta = options.showDelta ?? true;
|
|
2935
|
+
const partialHint = options.partialHint ?? "Some measures have not finished syncing.";
|
|
2936
|
+
const errored = !!s.errorMessage;
|
|
2937
|
+
const empty = !errored && s.metrics.length === 0;
|
|
2938
|
+
return {
|
|
2939
|
+
hasRanges: s.ranges.length > 0,
|
|
2940
|
+
ranges: s.ranges.map((r) => ({ value: r.id, label: r.label })),
|
|
2941
|
+
rangeId: s.rangeId ?? s.ranges[0]?.id ?? "",
|
|
2942
|
+
partial: s.partial,
|
|
2943
|
+
partialHint,
|
|
2944
|
+
errorMessage: s.errorMessage ?? void 0,
|
|
2945
|
+
errored,
|
|
2946
|
+
empty,
|
|
2947
|
+
emptyHint: options.emptyHint ?? "Configure a metric, or wire a result into this panel.",
|
|
2948
|
+
ready: !errored && !empty,
|
|
2949
|
+
layout: options.layout ?? "grid",
|
|
2950
|
+
columns: options.columns ?? 4,
|
|
2951
|
+
tiles: s.metrics.map((metric) => {
|
|
2952
|
+
const level = metric.level === "critical" ? "error" : metric.level === "warn" ? "warning" : void 0;
|
|
2953
|
+
const hasDelta = showDelta && metric.delta !== void 0;
|
|
2954
|
+
const hasSpark = sparkline && !!metric.spark && metric.spark.length > 1;
|
|
2955
|
+
return {
|
|
2956
|
+
id: metric.spec.id,
|
|
2957
|
+
label: metric.spec.label,
|
|
2958
|
+
title: metric.spec.description,
|
|
2959
|
+
// A partial result shows an em dash, never a zero — a zero is a lie the user cannot detect.
|
|
2960
|
+
value: metric.partial && metric.value === null ? "\u2014" : metric.display,
|
|
2961
|
+
level: String(metric.level),
|
|
2962
|
+
hasLevel: level !== void 0,
|
|
2963
|
+
tone: level ?? "warning",
|
|
2964
|
+
hasDelta,
|
|
2965
|
+
delta: metric.delta ?? 0,
|
|
2966
|
+
deltaTone: metric.deltaTone,
|
|
2967
|
+
partial: metric.partial === true,
|
|
2968
|
+
hasSpark,
|
|
2969
|
+
spark: hasSpark ? metric.spark : [],
|
|
2970
|
+
sparkLabel: `${metric.spec.label} trend`
|
|
2971
|
+
};
|
|
2972
|
+
}),
|
|
2973
|
+
countLabel: `${s.metrics.length} metric${s.metrics.length === 1 ? "" : "s"}`,
|
|
2974
|
+
partialLabel: s.partial ? partialHint : void 0
|
|
2975
|
+
};
|
|
2976
|
+
}
|
|
2977
|
+
function applyMetricsUi(c, intent) {
|
|
2978
|
+
switch (intent.kind) {
|
|
2979
|
+
case "range":
|
|
2980
|
+
c.setRange(intent.rangeId);
|
|
2981
|
+
break;
|
|
2982
|
+
case "activate":
|
|
2983
|
+
c.activate(intent.metricId);
|
|
2984
|
+
break;
|
|
2971
2985
|
}
|
|
2972
|
-
const gridStyle = layout === "grid" ? { display: "grid", gridTemplateColumns: `repeat(${Math.max(1, columns)}, minmax(0, 1fr))`, gap: 6 } : layout === "row" ? { display: "flex", gap: 6, overflowX: "auto" } : { display: "flex", flexDirection: "column", gap: 6 };
|
|
2973
|
-
return /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", height: "100%", minHeight: 0 }, children: [
|
|
2974
|
-
toolbar,
|
|
2975
|
-
/* @__PURE__ */ jsx3(ScrollArea2, { children: /* @__PURE__ */ jsx3("div", { style: { ...gridStyle, padding: 6 }, children: state.metrics.map((metric) => /* @__PURE__ */ jsx3(
|
|
2976
|
-
Tile,
|
|
2977
|
-
{
|
|
2978
|
-
metric,
|
|
2979
|
-
sparkline,
|
|
2980
|
-
showDelta,
|
|
2981
|
-
partialHint,
|
|
2982
|
-
onActivate: () => controller.activate(metric.spec.id)
|
|
2983
|
-
},
|
|
2984
|
-
metric.spec.id
|
|
2985
|
-
)) }) }),
|
|
2986
|
-
/* @__PURE__ */ jsx3(
|
|
2987
|
-
StatusBar3,
|
|
2988
|
-
{
|
|
2989
|
-
left: `${state.metrics.length} metric${state.metrics.length === 1 ? "" : "s"}`,
|
|
2990
|
-
right: state.partial ? partialHint : void 0
|
|
2991
|
-
}
|
|
2992
|
-
)
|
|
2993
|
-
] });
|
|
2994
2986
|
}
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
2987
|
+
var metricsViewManifest = {
|
|
2988
|
+
id: metricsManifest.id,
|
|
2989
|
+
version: "1.0.0",
|
|
2990
|
+
title: "Metrics",
|
|
2991
|
+
category: "data",
|
|
2992
|
+
layout: { slot: "center" },
|
|
2993
|
+
inputs: [{ id: "view", type: "object", label: "View state", description: "The MetricsViewModel the runtime derives from the controller on every draw." }],
|
|
2994
|
+
outputs: [{ id: "ui", type: "object", label: "UI intent", description: "{ kind: range | activate, \u2026 } \u2014 applied by the runtime to the controller." }],
|
|
2995
|
+
commands: []
|
|
2996
|
+
};
|
|
2997
|
+
var EMPTY = { hasRanges: false, ranges: [], rangeId: "", partial: false, partialHint: "", errored: false, empty: true, emptyHint: "Configure a metric, or wire a result into this panel.", ready: false, layout: "grid", columns: 4, tiles: [], countLabel: "0 metrics" };
|
|
2998
|
+
var BEHAVIOURS = {
|
|
2999
|
+
"data/metricsPanelView": (inputs) => inputs.view ?? EMPTY
|
|
3000
|
+
};
|
|
3001
|
+
var METRICS_RUNTIME_UNITS = [];
|
|
3002
|
+
var text = (b) => ({ component: "text", props: { text: b } });
|
|
3003
|
+
var ui = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
|
|
3004
|
+
var METRICS_DECLARATION = {
|
|
3005
|
+
format: "xeno.block@1",
|
|
3006
|
+
manifest: metricsViewManifest,
|
|
3007
|
+
behaviour: "data/metricsPanelView",
|
|
3008
|
+
composition: {
|
|
3009
|
+
component: "chrome/Column",
|
|
3010
|
+
children: [
|
|
3011
|
+
{
|
|
3012
|
+
component: "chrome/Toolbar",
|
|
3013
|
+
when: { input: "view.hasRanges" },
|
|
3014
|
+
props: {
|
|
3015
|
+
left: { node: { component: "chrome/SegmentedControl", props: { size: { value: "sm" }, label: { value: "Range" }, options: { input: "view.ranges" }, value: { input: "view.rangeId" } }, on: { onChange: ui("range", { rangeId: { arg: "" } }) } } },
|
|
3016
|
+
right: { node: { component: "chrome/Badge", when: { input: "view.partial" }, props: { tone: { value: "warning" }, title: { input: "view.partialHint" } }, children: [text({ value: "partial" })] } }
|
|
3013
3017
|
}
|
|
3014
3018
|
},
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
"span",
|
|
3019
|
+
{ component: "chrome/ErrorState", when: { input: "view.errored" }, props: { title: { value: "Could not load metrics" }, message: { input: "view.errorMessage" } } },
|
|
3020
|
+
{ component: "chrome/EmptyState", when: { input: "view.empty" }, props: { title: { value: "No metrics" }, hint: { input: "view.emptyHint" } } },
|
|
3021
|
+
{
|
|
3022
|
+
component: "chrome/ScrollArea",
|
|
3023
|
+
when: { input: "view.ready" },
|
|
3024
|
+
children: [
|
|
3025
|
+
{
|
|
3026
|
+
component: "chrome/TileGrid",
|
|
3027
|
+
props: { layout: { input: "view.layout" }, columns: { input: "view.columns" } },
|
|
3028
|
+
children: [
|
|
3026
3029
|
{
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3030
|
+
component: "chrome/StatTile",
|
|
3031
|
+
each: { input: "view.tiles", key: "id" },
|
|
3032
|
+
props: {
|
|
3033
|
+
title: { item: "title" },
|
|
3034
|
+
label: { item: "label" },
|
|
3035
|
+
value: { item: "value" },
|
|
3036
|
+
icon: { node: { component: "chrome/Badge", when: { item: "hasLevel" }, props: { tone: { item: "tone" } }, children: [text({ item: "level" })] } },
|
|
3037
|
+
sub: {
|
|
3038
|
+
node: {
|
|
3039
|
+
component: "chrome/Stack",
|
|
3040
|
+
props: { direction: { value: "row" }, pad: { value: "none" } },
|
|
3041
|
+
children: [
|
|
3042
|
+
{ component: "chrome/Delta", when: { item: "hasDelta" }, props: { value: { item: "delta" }, tone: { item: "deltaTone" } } },
|
|
3043
|
+
{ component: "chrome/Text", when: { item: "partial" }, props: { role: { value: "meta" } }, children: [text({ input: "view.partialHint" })] },
|
|
3044
|
+
{ component: "chrome/Sparkline", when: { item: "hasSpark" }, props: { data: { item: "spark" }, label: { item: "sparkLabel" } } }
|
|
3045
|
+
]
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3031
3048
|
},
|
|
3032
|
-
|
|
3033
|
-
metric.delta > 0 ? "\u25B2" : "\u25BC",
|
|
3034
|
-
" ",
|
|
3035
|
-
Math.abs(metric.delta * 100).toFixed(1),
|
|
3036
|
-
"%"
|
|
3037
|
-
]
|
|
3049
|
+
on: { onActivate: ui("activate", { metricId: { item: "id" } }) }
|
|
3038
3050
|
}
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3051
|
+
]
|
|
3052
|
+
}
|
|
3053
|
+
]
|
|
3054
|
+
},
|
|
3055
|
+
{ component: "chrome/StatusBar", when: { input: "view.ready" }, props: { left: { input: "view.countLabel" }, right: { input: "view.partialLabel" } } }
|
|
3056
|
+
]
|
|
3057
|
+
}
|
|
3058
|
+
};
|
|
3059
|
+
|
|
3060
|
+
// src/data/metrics/react/MetricsPanelView.tsx
|
|
3061
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3062
|
+
function MetricsPanelView({ controller, ...options }) {
|
|
3063
|
+
useSyncExternalStore3(controller.subscribe, controller.getState, controller.getState);
|
|
3064
|
+
const view = metricsViewState(controller, options);
|
|
3065
|
+
const ui3 = (intent) => applyMetricsUi(controller, intent);
|
|
3066
|
+
return /* @__PURE__ */ jsxs3(Column, { children: [
|
|
3067
|
+
view.hasRanges ? /* @__PURE__ */ jsx3(
|
|
3068
|
+
Toolbar3,
|
|
3069
|
+
{
|
|
3070
|
+
left: /* @__PURE__ */ jsx3(SegmentedControl3, { size: "sm", label: "Range", options: view.ranges, value: view.rangeId, onChange: (rangeId) => ui3({ kind: "range", rangeId }) }),
|
|
3071
|
+
right: view.partial ? /* @__PURE__ */ jsx3(Badge3, { tone: "warning", title: view.partialHint, children: "partial" }) : null
|
|
3072
|
+
}
|
|
3073
|
+
) : null,
|
|
3074
|
+
view.errored ? /* @__PURE__ */ jsx3(ErrorState3, { title: "Could not load metrics", message: view.errorMessage }) : null,
|
|
3075
|
+
view.empty ? /* @__PURE__ */ jsx3(EmptyState3, { title: "No metrics", hint: view.emptyHint }) : null,
|
|
3076
|
+
view.ready ? /* @__PURE__ */ jsx3(ScrollArea2, { children: /* @__PURE__ */ jsx3(TileGrid, { layout: view.layout, columns: view.columns, children: view.tiles.map((tile) => /* @__PURE__ */ jsx3(
|
|
3077
|
+
StatTile,
|
|
3078
|
+
{
|
|
3079
|
+
title: tile.title,
|
|
3080
|
+
label: tile.label,
|
|
3081
|
+
value: tile.value,
|
|
3082
|
+
icon: tile.hasLevel ? /* @__PURE__ */ jsx3(Badge3, { tone: tile.tone, children: tile.level }) : null,
|
|
3083
|
+
sub: /* @__PURE__ */ jsxs3(Stack, { direction: "row", pad: "none", children: [
|
|
3084
|
+
tile.hasDelta ? /* @__PURE__ */ jsx3(Delta, { value: tile.delta, tone: tile.deltaTone }) : null,
|
|
3085
|
+
tile.partial ? /* @__PURE__ */ jsx3(Text, { role: "meta", children: view.partialHint }) : null,
|
|
3086
|
+
tile.hasSpark ? /* @__PURE__ */ jsx3(Sparkline, { data: tile.spark, label: tile.sparkLabel }) : null
|
|
3087
|
+
] }),
|
|
3088
|
+
onActivate: () => ui3({ kind: "activate", metricId: tile.id })
|
|
3089
|
+
},
|
|
3090
|
+
tile.id
|
|
3091
|
+
)) }) }) : null,
|
|
3092
|
+
view.ready ? /* @__PURE__ */ jsx3(StatusBar3, { left: view.countLabel, right: view.partialLabel }) : null
|
|
3093
|
+
] });
|
|
3047
3094
|
}
|
|
3048
3095
|
|
|
3049
3096
|
// src/data/metrics/panel.ts
|
|
@@ -3240,7 +3287,7 @@ function emptyFilterGroup() {
|
|
|
3240
3287
|
function offerableFilterOps(column, sourceOps = []) {
|
|
3241
3288
|
const common = ["eq", "ne", "isEmpty", "isNotEmpty", "in", "notIn"];
|
|
3242
3289
|
const ordered = ["gt", "gte", "lt", "lte", "between"];
|
|
3243
|
-
const
|
|
3290
|
+
const text3 = ["contains", "notContains", "startsWith", "endsWith"];
|
|
3244
3291
|
const temporal = ["relative"];
|
|
3245
3292
|
let ops = [...common];
|
|
3246
3293
|
switch (column?.type) {
|
|
@@ -3258,10 +3305,10 @@ function offerableFilterOps(column, sourceOps = []) {
|
|
|
3258
3305
|
case "url":
|
|
3259
3306
|
case "select":
|
|
3260
3307
|
case "multiselect":
|
|
3261
|
-
ops = [...ops, ...
|
|
3308
|
+
ops = [...ops, ...text3];
|
|
3262
3309
|
break;
|
|
3263
3310
|
default:
|
|
3264
|
-
ops = [...ops, ...
|
|
3311
|
+
ops = [...ops, ...text3, ...ordered];
|
|
3265
3312
|
}
|
|
3266
3313
|
if (sourceOps.length === 0) return ops;
|
|
3267
3314
|
return ops.filter((op) => sourceOps.includes(op));
|
|
@@ -3892,7 +3939,7 @@ var fieldsManifest = {
|
|
|
3892
3939
|
import { useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
3893
3940
|
import {
|
|
3894
3941
|
Badge as Badge4,
|
|
3895
|
-
Column,
|
|
3942
|
+
Column as Column2,
|
|
3896
3943
|
EmptyState as EmptyState4,
|
|
3897
3944
|
IconButton as IconButton3,
|
|
3898
3945
|
Note,
|
|
@@ -4027,13 +4074,13 @@ var fieldsViewManifest = {
|
|
|
4027
4074
|
outputs: [{ id: "ui", type: "object", label: "UI intent", description: "{ kind, \u2026 } \u2014 applied by the runtime to the controller." }],
|
|
4028
4075
|
commands: []
|
|
4029
4076
|
};
|
|
4030
|
-
var
|
|
4031
|
-
var
|
|
4032
|
-
"data/fieldsPanelView": (inputs) => inputs.view ??
|
|
4077
|
+
var EMPTY2 = { hasColumns: false, noColumns: true, sampled: false, manualApply: false, applyDisabled: true, columns: [], shelves: [], filters: [], filterCount: 0, hasFilters: false, noFilters: true, combinator: "and", countLabel: "0 fields" };
|
|
4078
|
+
var BEHAVIOURS2 = {
|
|
4079
|
+
"data/fieldsPanelView": (inputs) => inputs.view ?? EMPTY2
|
|
4033
4080
|
};
|
|
4034
4081
|
var FIELDS_RUNTIME_UNITS = [];
|
|
4035
|
-
var
|
|
4036
|
-
var
|
|
4082
|
+
var text2 = (b) => ({ component: "text", props: { text: b } });
|
|
4083
|
+
var ui2 = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
|
|
4037
4084
|
var removeButton = (label, on) => ({
|
|
4038
4085
|
component: "chrome/IconButton",
|
|
4039
4086
|
props: { size: { value: "sm" }, icon: { node: { component: "icons/Close", props: { size: { value: 11 } } } }, label },
|
|
@@ -4054,14 +4101,14 @@ var FIELDS_DECLARATION = {
|
|
|
4054
4101
|
{
|
|
4055
4102
|
component: "chrome/Toolbar",
|
|
4056
4103
|
props: {
|
|
4057
|
-
left: { node: { component: "chrome/Badge", when: { input: "view.sampled" }, props: { tone: { value: "warning" }, title: { input: "view.sampleWarning" } }, children: [
|
|
4104
|
+
left: { node: { component: "chrome/Badge", when: { input: "view.sampled" }, props: { tone: { value: "warning" }, title: { input: "view.sampleWarning" } }, children: [text2({ value: "sampled schema" })] } },
|
|
4058
4105
|
right: {
|
|
4059
4106
|
node: {
|
|
4060
4107
|
component: "chrome/ToolbarGroup",
|
|
4061
4108
|
props: { end: { value: true } },
|
|
4062
4109
|
children: [
|
|
4063
|
-
{ component: "chrome/TextButton", on: { onClick:
|
|
4064
|
-
{ component: "chrome/TextButton", when: { input: "view.manualApply" }, props: { strong: { value: true }, disabled: { input: "view.applyDisabled" } }, on: { onClick:
|
|
4110
|
+
{ component: "chrome/TextButton", on: { onClick: ui2("autoAssign") }, children: [text2({ value: "Auto-assign" })] },
|
|
4111
|
+
{ component: "chrome/TextButton", when: { input: "view.manualApply" }, props: { strong: { value: true }, disabled: { input: "view.applyDisabled" } }, on: { onClick: ui2("apply") }, children: [text2({ value: "Apply" })] }
|
|
4065
4112
|
]
|
|
4066
4113
|
}
|
|
4067
4114
|
}
|
|
@@ -4081,8 +4128,8 @@ var FIELDS_DECLARATION = {
|
|
|
4081
4128
|
{
|
|
4082
4129
|
component: "chrome/Row",
|
|
4083
4130
|
each: { input: "view.columns", key: "id" },
|
|
4084
|
-
props: { label: { item: "name" }, meta: { item: "role" }, selected: { item: "focused" }, trailing: { node: { component: "chrome/Badge", when: { item: "stat" }, props: { title: { item: "statTitle" } }, children: [
|
|
4085
|
-
on: { onClick:
|
|
4131
|
+
props: { label: { item: "name" }, meta: { item: "role" }, selected: { item: "focused" }, trailing: { node: { component: "chrome/Badge", when: { item: "stat" }, props: { title: { item: "statTitle" } }, children: [text2({ item: "stat" })] } } },
|
|
4132
|
+
on: { onClick: ui2("focus", { columnId: { item: "id" } }) }
|
|
4086
4133
|
}
|
|
4087
4134
|
]
|
|
4088
4135
|
}
|
|
@@ -4091,9 +4138,9 @@ var FIELDS_DECLARATION = {
|
|
|
4091
4138
|
{
|
|
4092
4139
|
component: "chrome/Section",
|
|
4093
4140
|
each: { input: "view.shelves", key: "id" },
|
|
4094
|
-
props: { title: { item: "label" }, flush: { value: true }, badge: { node: { component: "chrome/Badge", when: { item: "hasEntries" }, children: [
|
|
4141
|
+
props: { title: { item: "label" }, flush: { value: true }, badge: { node: { component: "chrome/Badge", when: { item: "hasEntries" }, children: [text2({ item: "count" })] } } },
|
|
4095
4142
|
children: [
|
|
4096
|
-
{ component: "chrome/Note", when: { item: "empty" }, children: [
|
|
4143
|
+
{ component: "chrome/Note", when: { item: "empty" }, children: [text2({ item: "hint" })] },
|
|
4097
4144
|
{
|
|
4098
4145
|
component: "chrome/RowList",
|
|
4099
4146
|
when: { item: "hasEntries" },
|
|
@@ -4108,13 +4155,13 @@ var FIELDS_DECLARATION = {
|
|
|
4108
4155
|
node: {
|
|
4109
4156
|
component: "fragment",
|
|
4110
4157
|
children: [
|
|
4111
|
-
{ component: "chrome/Select", when: { item: "aggregated" }, props: { size: { value: "sm" }, label: { value: "Aggregate" }, options: { item: "aggregates" }, value: { item: "fn" } }, on: { onChange:
|
|
4112
|
-
{ component: "chrome/TextButton", when: { item: "sortable" }, on: { onClick:
|
|
4113
|
-
{ component: "chrome/Badge", when: { item: "granularity" }, children: [
|
|
4158
|
+
{ component: "chrome/Select", when: { item: "aggregated" }, props: { size: { value: "sm" }, label: { value: "Aggregate" }, options: { item: "aggregates" }, value: { item: "fn" } }, on: { onChange: ui2("aggregate", { shelfId: { item: "shelfId" }, columnId: { item: "columnId" }, fn: { arg: "" } }) } },
|
|
4159
|
+
{ component: "chrome/TextButton", when: { item: "sortable" }, on: { onClick: ui2("direction", { shelfId: { item: "shelfId" }, columnId: { item: "columnId" } }) }, children: [text2({ item: "direction" })] },
|
|
4160
|
+
{ component: "chrome/Badge", when: { item: "granularity" }, children: [text2({ item: "granularity" })] }
|
|
4114
4161
|
]
|
|
4115
4162
|
}
|
|
4116
4163
|
},
|
|
4117
|
-
trailing: { node: removeButton({ item: "removeLabel" },
|
|
4164
|
+
trailing: { node: removeButton({ item: "removeLabel" }, ui2("remove", { shelfId: { item: "shelfId" }, columnId: { item: "columnId" } })) }
|
|
4118
4165
|
}
|
|
4119
4166
|
}
|
|
4120
4167
|
]
|
|
@@ -4126,11 +4173,11 @@ var FIELDS_DECLARATION = {
|
|
|
4126
4173
|
props: {
|
|
4127
4174
|
title: { value: "Filters" },
|
|
4128
4175
|
flush: { value: true },
|
|
4129
|
-
badge: { node: { component: "chrome/Badge", when: { input: "view.hasFilters" }, children: [
|
|
4130
|
-
actions: { node: { component: "chrome/IconButton", props: { size: { value: "sm" }, icon: { node: { component: "icons/Plus", props: { size: { value: 11 } } } }, label: { value: "Add filter" } }, on: { onClick:
|
|
4176
|
+
badge: { node: { component: "chrome/Badge", when: { input: "view.hasFilters" }, children: [text2({ input: "view.filterCount" })] } },
|
|
4177
|
+
actions: { node: { component: "chrome/IconButton", props: { size: { value: "sm" }, icon: { node: { component: "icons/Plus", props: { size: { value: 11 } } } }, label: { value: "Add filter" } }, on: { onClick: ui2("addFilter") } } }
|
|
4131
4178
|
},
|
|
4132
4179
|
children: [
|
|
4133
|
-
{ component: "chrome/Note", when: { input: "view.noFilters" }, children: [
|
|
4180
|
+
{ component: "chrome/Note", when: { input: "view.noFilters" }, children: [text2({ value: "No filters. Everything passes." })] },
|
|
4134
4181
|
{
|
|
4135
4182
|
component: "chrome/RowList",
|
|
4136
4183
|
when: { input: "view.hasFilters" },
|
|
@@ -4140,8 +4187,8 @@ var FIELDS_DECLARATION = {
|
|
|
4140
4187
|
each: { input: "view.filters", key: "key" },
|
|
4141
4188
|
props: {
|
|
4142
4189
|
label: { item: "label" },
|
|
4143
|
-
meta: { node: { component: "chrome/Select", when: { item: "leaf" }, props: { size: { value: "sm" }, label: { value: "Operator" }, options: { item: "ops" }, value: { item: "op" } }, on: { onChange:
|
|
4144
|
-
trailing: { node: removeButton({ item: "removeLabel" },
|
|
4190
|
+
meta: { node: { component: "chrome/Select", when: { item: "leaf" }, props: { size: { value: "sm" }, label: { value: "Operator" }, options: { item: "ops" }, value: { item: "op" } }, on: { onChange: ui2("filterOp", { index: { item: "index" }, op: { arg: "" } }) } } },
|
|
4191
|
+
trailing: { node: removeButton({ item: "removeLabel" }, ui2("removeFilter", { index: { item: "index" } })) }
|
|
4145
4192
|
}
|
|
4146
4193
|
}
|
|
4147
4194
|
]
|
|
@@ -4150,8 +4197,8 @@ var FIELDS_DECLARATION = {
|
|
|
4150
4197
|
component: "chrome/Toolbar",
|
|
4151
4198
|
props: {
|
|
4152
4199
|
divided: { value: false },
|
|
4153
|
-
left: { node: { component: "chrome/SegmentedControl", props: { size: { value: "sm" }, label: { value: "Combinator" }, options: { value: COMBINATORS }, value: { input: "view.combinator" } }, on: { onChange:
|
|
4154
|
-
right: { node: { component: "chrome/TextButton", on: { onClick:
|
|
4200
|
+
left: { node: { component: "chrome/SegmentedControl", props: { size: { value: "sm" }, label: { value: "Combinator" }, options: { value: COMBINATORS }, value: { input: "view.combinator" } }, on: { onChange: ui2("combinator", { combinator: { arg: "" } }) } } },
|
|
4201
|
+
right: { node: { component: "chrome/TextButton", on: { onClick: ui2("addGroup") }, children: [text2({ value: "+ group" })] } }
|
|
4155
4202
|
}
|
|
4156
4203
|
}
|
|
4157
4204
|
]
|
|
@@ -4173,18 +4220,18 @@ var COMBINATORS2 = [{ value: "and", label: "All" }, { value: "or", label: "Any"
|
|
|
4173
4220
|
function FieldsPanelView({ controller, showStats, manualApply }) {
|
|
4174
4221
|
useSyncExternalStore4(controller.subscribe, controller.getState, controller.getState);
|
|
4175
4222
|
const view = fieldsViewState(controller, { showStats, manualApply });
|
|
4176
|
-
const
|
|
4223
|
+
const ui3 = (intent) => applyFieldsUi(controller, intent);
|
|
4177
4224
|
if (view.noColumns) {
|
|
4178
4225
|
return /* @__PURE__ */ jsx4(EmptyState4, { title: "No fields", hint: "Connect a source \u2014 its columns appear here, ready to drop onto a shelf." });
|
|
4179
4226
|
}
|
|
4180
|
-
return /* @__PURE__ */ jsxs4(
|
|
4227
|
+
return /* @__PURE__ */ jsxs4(Column2, { children: [
|
|
4181
4228
|
/* @__PURE__ */ jsx4(
|
|
4182
4229
|
Toolbar4,
|
|
4183
4230
|
{
|
|
4184
4231
|
left: view.sampled ? /* @__PURE__ */ jsx4(Badge4, { tone: "warning", title: view.sampleWarning, children: "sampled schema" }) : null,
|
|
4185
4232
|
right: /* @__PURE__ */ jsxs4(ToolbarGroup3, { end: true, children: [
|
|
4186
|
-
/* @__PURE__ */ jsx4(TextButton, { onClick: () =>
|
|
4187
|
-
view.manualApply ? /* @__PURE__ */ jsx4(TextButton, { strong: true, disabled: view.applyDisabled, onClick: () =>
|
|
4233
|
+
/* @__PURE__ */ jsx4(TextButton, { onClick: () => ui3({ kind: "autoAssign" }), children: "Auto-assign" }),
|
|
4234
|
+
view.manualApply ? /* @__PURE__ */ jsx4(TextButton, { strong: true, disabled: view.applyDisabled, onClick: () => ui3({ kind: "apply" }), children: "Apply" }) : null
|
|
4188
4235
|
] })
|
|
4189
4236
|
}
|
|
4190
4237
|
),
|
|
@@ -4196,7 +4243,7 @@ function FieldsPanelView({ controller, showStats, manualApply }) {
|
|
|
4196
4243
|
meta: column.role,
|
|
4197
4244
|
selected: column.focused,
|
|
4198
4245
|
trailing: column.stat ? /* @__PURE__ */ jsx4(Badge4, { title: column.statTitle, children: column.stat }) : null,
|
|
4199
|
-
onClick: () =>
|
|
4246
|
+
onClick: () => ui3({ kind: "focus", columnId: column.id })
|
|
4200
4247
|
},
|
|
4201
4248
|
column.id
|
|
4202
4249
|
)) }) }),
|
|
@@ -4208,11 +4255,11 @@ function FieldsPanelView({ controller, showStats, manualApply }) {
|
|
|
4208
4255
|
label: entry.label,
|
|
4209
4256
|
dimmed: entry.suggested,
|
|
4210
4257
|
meta: /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
4211
|
-
entry.aggregated ? /* @__PURE__ */ jsx4(Select, { size: "sm", label: "Aggregate", options: entry.aggregates, value: entry.fn, onChange: (fn) =>
|
|
4212
|
-
entry.sortable ? /* @__PURE__ */ jsx4(TextButton, { onClick: () =>
|
|
4258
|
+
entry.aggregated ? /* @__PURE__ */ jsx4(Select, { size: "sm", label: "Aggregate", options: entry.aggregates, value: entry.fn, onChange: (fn) => ui3({ kind: "aggregate", shelfId: entry.shelfId, columnId: entry.columnId, fn }) }) : null,
|
|
4259
|
+
entry.sortable ? /* @__PURE__ */ jsx4(TextButton, { onClick: () => ui3({ kind: "direction", shelfId: entry.shelfId, columnId: entry.columnId }), children: entry.direction }) : null,
|
|
4213
4260
|
entry.granularity ? /* @__PURE__ */ jsx4(Badge4, { children: entry.granularity }) : null
|
|
4214
4261
|
] }),
|
|
4215
|
-
trailing: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(CloseGlyph, { size: 11 }), label: entry.removeLabel, onClick: () =>
|
|
4262
|
+
trailing: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(CloseGlyph, { size: 11 }), label: entry.removeLabel, onClick: () => ui3({ kind: "remove", shelfId: entry.shelfId, columnId: entry.columnId }) })
|
|
4216
4263
|
},
|
|
4217
4264
|
entry.columnId
|
|
4218
4265
|
)) }) : null
|
|
@@ -4223,15 +4270,15 @@ function FieldsPanelView({ controller, showStats, manualApply }) {
|
|
|
4223
4270
|
title: "Filters",
|
|
4224
4271
|
flush: true,
|
|
4225
4272
|
badge: view.hasFilters ? /* @__PURE__ */ jsx4(Badge4, { children: view.filterCount }) : null,
|
|
4226
|
-
actions: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(PlusGlyph, { size: 11 }), label: "Add filter", onClick: () =>
|
|
4273
|
+
actions: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(PlusGlyph, { size: 11 }), label: "Add filter", onClick: () => ui3({ kind: "addFilter" }) }),
|
|
4227
4274
|
children: [
|
|
4228
4275
|
view.noFilters ? /* @__PURE__ */ jsx4(Note, { children: "No filters. Everything passes." }) : null,
|
|
4229
4276
|
view.hasFilters ? /* @__PURE__ */ jsx4(RowList, { children: view.filters.map((filter) => /* @__PURE__ */ jsx4(
|
|
4230
4277
|
Row,
|
|
4231
4278
|
{
|
|
4232
4279
|
label: filter.label,
|
|
4233
|
-
meta: filter.leaf ? /* @__PURE__ */ jsx4(Select, { size: "sm", label: "Operator", options: filter.ops, value: filter.op, onChange: (op) =>
|
|
4234
|
-
trailing: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(CloseGlyph, { size: 11 }), label: filter.removeLabel, onClick: () =>
|
|
4280
|
+
meta: filter.leaf ? /* @__PURE__ */ jsx4(Select, { size: "sm", label: "Operator", options: filter.ops, value: filter.op, onChange: (op) => ui3({ kind: "filterOp", index: filter.index, op }) }) : null,
|
|
4281
|
+
trailing: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(CloseGlyph, { size: 11 }), label: filter.removeLabel, onClick: () => ui3({ kind: "removeFilter", index: filter.index }) })
|
|
4235
4282
|
},
|
|
4236
4283
|
filter.key
|
|
4237
4284
|
)) }) : null,
|
|
@@ -4239,8 +4286,8 @@ function FieldsPanelView({ controller, showStats, manualApply }) {
|
|
|
4239
4286
|
Toolbar4,
|
|
4240
4287
|
{
|
|
4241
4288
|
divided: false,
|
|
4242
|
-
left: /* @__PURE__ */ jsx4(SegmentedControl4, { size: "sm", label: "Combinator", options: COMBINATORS2, value: view.combinator, onChange: (combinator) =>
|
|
4243
|
-
right: /* @__PURE__ */ jsx4(TextButton, { onClick: () =>
|
|
4289
|
+
left: /* @__PURE__ */ jsx4(SegmentedControl4, { size: "sm", label: "Combinator", options: COMBINATORS2, value: view.combinator, onChange: (combinator) => ui3({ kind: "combinator", combinator }) }),
|
|
4290
|
+
right: /* @__PURE__ */ jsx4(TextButton, { onClick: () => ui3({ kind: "addGroup" }), children: "+ group" })
|
|
4244
4291
|
}
|
|
4245
4292
|
)
|
|
4246
4293
|
]
|
|
@@ -5376,10 +5423,10 @@ function parseJsonPath(path) {
|
|
|
5376
5423
|
}
|
|
5377
5424
|
return steps;
|
|
5378
5425
|
}
|
|
5379
|
-
function findBracketEnd(
|
|
5426
|
+
function findBracketEnd(text3, start) {
|
|
5380
5427
|
let quote = null;
|
|
5381
|
-
for (let i = start + 1; i <
|
|
5382
|
-
const char =
|
|
5428
|
+
for (let i = start + 1; i < text3.length; i += 1) {
|
|
5429
|
+
const char = text3[i];
|
|
5383
5430
|
if (quote) {
|
|
5384
5431
|
if (char === "\\") i += 1;
|
|
5385
5432
|
else if (char === quote) quote = null;
|
|
@@ -5803,9 +5850,9 @@ function firstGraphqlError(errors) {
|
|
|
5803
5850
|
}
|
|
5804
5851
|
|
|
5805
5852
|
// src/data/connectors/executors/csv.ts
|
|
5806
|
-
function sniffDelimiter(
|
|
5853
|
+
function sniffDelimiter(text3) {
|
|
5807
5854
|
const candidates = [",", ";", " ", "|"];
|
|
5808
|
-
const line = firstLogicalLine(
|
|
5855
|
+
const line = firstLogicalLine(text3);
|
|
5809
5856
|
let best = ",";
|
|
5810
5857
|
let bestCount = 0;
|
|
5811
5858
|
for (const candidate of candidates) {
|
|
@@ -5827,21 +5874,21 @@ function sniffDelimiter(text2) {
|
|
|
5827
5874
|
}
|
|
5828
5875
|
return best;
|
|
5829
5876
|
}
|
|
5830
|
-
function firstLogicalLine(
|
|
5877
|
+
function firstLogicalLine(text3) {
|
|
5831
5878
|
let inQuotes = false;
|
|
5832
|
-
for (let i = 0; i <
|
|
5833
|
-
const char =
|
|
5879
|
+
for (let i = 0; i < text3.length; i += 1) {
|
|
5880
|
+
const char = text3[i];
|
|
5834
5881
|
if (char === '"') {
|
|
5835
|
-
if (inQuotes &&
|
|
5882
|
+
if (inQuotes && text3[i + 1] === '"') i += 1;
|
|
5836
5883
|
else inQuotes = !inQuotes;
|
|
5837
5884
|
} else if ((char === "\n" || char === "\r") && !inQuotes) {
|
|
5838
|
-
return
|
|
5885
|
+
return text3.slice(0, i);
|
|
5839
5886
|
}
|
|
5840
5887
|
}
|
|
5841
|
-
return
|
|
5888
|
+
return text3;
|
|
5842
5889
|
}
|
|
5843
|
-
function parseCsv(
|
|
5844
|
-
const source =
|
|
5890
|
+
function parseCsv(text3, options = {}) {
|
|
5891
|
+
const source = text3.charCodeAt(0) === 65279 ? text3.slice(1) : text3;
|
|
5845
5892
|
const delimiter = options.delimiter && options.delimiter.length > 0 ? options.delimiter : sniffDelimiter(source);
|
|
5846
5893
|
const quote = options.quote && options.quote.length > 0 ? options.quote : '"';
|
|
5847
5894
|
const hasHeader = options.hasHeader ?? true;
|
|
@@ -5876,17 +5923,17 @@ function dedupe(names) {
|
|
|
5876
5923
|
return count === 0 ? name : `${name}_${count + 1}`;
|
|
5877
5924
|
});
|
|
5878
5925
|
}
|
|
5879
|
-
function scanRecords(
|
|
5926
|
+
function scanRecords(text3, delimiter, quote) {
|
|
5880
5927
|
const records = [];
|
|
5881
5928
|
let fields = [];
|
|
5882
5929
|
let field = "";
|
|
5883
5930
|
let inQuotes = false;
|
|
5884
5931
|
let i = 0;
|
|
5885
|
-
while (i <
|
|
5886
|
-
const char =
|
|
5932
|
+
while (i < text3.length) {
|
|
5933
|
+
const char = text3[i];
|
|
5887
5934
|
if (inQuotes) {
|
|
5888
5935
|
if (char === quote) {
|
|
5889
|
-
if (
|
|
5936
|
+
if (text3[i + 1] === quote) {
|
|
5890
5937
|
field += quote;
|
|
5891
5938
|
i += 2;
|
|
5892
5939
|
continue;
|
|
@@ -5904,7 +5951,7 @@ function scanRecords(text2, delimiter, quote) {
|
|
|
5904
5951
|
i += 1;
|
|
5905
5952
|
continue;
|
|
5906
5953
|
}
|
|
5907
|
-
if (
|
|
5954
|
+
if (text3.startsWith(delimiter, i)) {
|
|
5908
5955
|
fields.push(field);
|
|
5909
5956
|
field = "";
|
|
5910
5957
|
i += delimiter.length;
|
|
@@ -5915,7 +5962,7 @@ function scanRecords(text2, delimiter, quote) {
|
|
|
5915
5962
|
records.push(fields);
|
|
5916
5963
|
fields = [];
|
|
5917
5964
|
field = "";
|
|
5918
|
-
i += char === "\r" &&
|
|
5965
|
+
i += char === "\r" && text3[i + 1] === "\n" ? 2 : 1;
|
|
5919
5966
|
continue;
|
|
5920
5967
|
}
|
|
5921
5968
|
field += char;
|
|
@@ -7066,14 +7113,17 @@ export {
|
|
|
7066
7113
|
DEFAULT_RANGES,
|
|
7067
7114
|
EMPTY_LAYOUT,
|
|
7068
7115
|
EXPIRY_SKEW_MS,
|
|
7069
|
-
|
|
7116
|
+
BEHAVIOURS2 as FIELDS_BEHAVIOURS,
|
|
7070
7117
|
FIELDS_DECLARATION,
|
|
7071
7118
|
FIELDS_PANEL_ID,
|
|
7072
7119
|
FIELDS_RUNTIME_UNITS,
|
|
7073
7120
|
FieldsController,
|
|
7074
7121
|
FieldsPanelView,
|
|
7075
7122
|
IMPLEMENTED_VIEW_MODES,
|
|
7123
|
+
BEHAVIOURS as METRICS_BEHAVIOURS,
|
|
7124
|
+
METRICS_DECLARATION,
|
|
7076
7125
|
METRICS_PANEL_ID,
|
|
7126
|
+
METRICS_RUNTIME_UNITS,
|
|
7077
7127
|
MIN_COLUMN_WIDTH,
|
|
7078
7128
|
MONO_FILL_PALETTE,
|
|
7079
7129
|
MONO_PALETTE,
|
|
@@ -7085,6 +7135,7 @@ export {
|
|
|
7085
7135
|
TableController,
|
|
7086
7136
|
TablePanelView,
|
|
7087
7137
|
applyFieldsUi,
|
|
7138
|
+
applyMetricsUi,
|
|
7088
7139
|
applyPrecision,
|
|
7089
7140
|
base64Url,
|
|
7090
7141
|
breachSideOf,
|
|
@@ -7150,6 +7201,8 @@ export {
|
|
|
7150
7201
|
mergeRefreshResponse,
|
|
7151
7202
|
metricsManifest,
|
|
7152
7203
|
metricsPanel,
|
|
7204
|
+
metricsViewManifest,
|
|
7205
|
+
metricsViewState,
|
|
7153
7206
|
moveCell,
|
|
7154
7207
|
moveColumn,
|
|
7155
7208
|
needsRefresh,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xenosystem/blocks",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.10",
|
|
4
4
|
"description": "XENO Blocks — rung 3 of the front ladder: components composed into a contract-bearing unit (manifest: ports, intents, commands, agent surface), rendered by @xenosystem/workbench. ONE package, one subpath per family (/auth, /edit, /data, /time, /ops, /trust, /agent), one named export per block — XENO PACKAGE NAMING - STANDARD.md.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@duckdb/duckdb-wasm": ">=1.28.0",
|
|
66
66
|
"@xenosystem/block-sdk": ">=0.3.4 <1",
|
|
67
|
-
"@xenosystem/components": ">=0.
|
|
67
|
+
"@xenosystem/components": ">=0.21.0 <1",
|
|
68
68
|
"@xenosystem/data-core": "^0.1.0",
|
|
69
69
|
"@xenosystem/elements": ">=0.0.1",
|
|
70
70
|
"@xenosystem/elements-react": ">=0.0.1",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"@types/react": "^19.0.0",
|
|
82
82
|
"@types/react-dom": "^19.0.0",
|
|
83
83
|
"@xenosystem/block-sdk": "^0.3.4",
|
|
84
|
-
"@xenosystem/components": "^0.
|
|
84
|
+
"@xenosystem/components": "^0.21.0",
|
|
85
85
|
"@xenosystem/data-core": "^0.1.0",
|
|
86
86
|
"@xenosystem/elements": "0.0.1",
|
|
87
87
|
"@xenosystem/elements-react": "0.0.1",
|