@xenosystem/blocks 0.13.7 → 0.13.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-6HJROQCN.js → chunk-W4PTX2Y4.js} +111 -27
- package/dist/data/index.d.ts +140 -11
- package/dist/data/index.js +363 -226
- package/dist/edit/index.js +3 -4
- package/dist/icons/index.js +1 -2
- package/dist/time/index.d.ts +114 -7
- package/dist/time/index.js +293 -180
- package/package.json +3 -3
- package/dist/chunk-GTN5EDY3.js +0 -107
package/dist/data/index.js
CHANGED
|
@@ -6,15 +6,16 @@ import {
|
|
|
6
6
|
quoteLiteral,
|
|
7
7
|
renderFilterGroup
|
|
8
8
|
} from "../chunk-DJJGZ6U4.js";
|
|
9
|
+
import {
|
|
10
|
+
ICONS
|
|
11
|
+
} from "../chunk-W4PTX2Y4.js";
|
|
9
12
|
import {
|
|
10
13
|
ChevronGlyph,
|
|
11
14
|
DownloadGlyph,
|
|
12
15
|
PlugGlyph,
|
|
13
|
-
PlusGlyph,
|
|
14
16
|
RefreshGlyph,
|
|
15
17
|
SortAscGlyph,
|
|
16
|
-
SortDescGlyph
|
|
17
|
-
XGlyph
|
|
18
|
+
SortDescGlyph
|
|
18
19
|
} from "../chunk-K7YLLV2W.js";
|
|
19
20
|
import "../chunk-2KG3PWR4.js";
|
|
20
21
|
|
|
@@ -197,8 +198,8 @@ function moveCell(from, delta, bounds) {
|
|
|
197
198
|
}
|
|
198
199
|
|
|
199
200
|
// src/data/table/numeric.ts
|
|
200
|
-
function parseNumeric(
|
|
201
|
-
const trimmed = String(
|
|
201
|
+
function parseNumeric(text2) {
|
|
202
|
+
const trimmed = String(text2).trim();
|
|
202
203
|
if (trimmed.length === 0) return { ok: false, reason: "empty" };
|
|
203
204
|
const match = /^[+-]?(\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/.exec(trimmed);
|
|
204
205
|
if (!match) return { ok: false, reason: "nan" };
|
|
@@ -552,11 +553,11 @@ var TableController = class {
|
|
|
552
553
|
return true;
|
|
553
554
|
}
|
|
554
555
|
/** Update the in-flight draft. Emits `editPreview` only when `livePreview` is on. */
|
|
555
|
-
updateDraft(
|
|
556
|
+
updateDraft(text2) {
|
|
556
557
|
if (!this.editing) return;
|
|
557
|
-
this.editing = { ...this.editing, draft:
|
|
558
|
+
this.editing = { ...this.editing, draft: text2 };
|
|
558
559
|
if (this.livePreview) {
|
|
559
|
-
const parsed = this.parseDraft(this.editing.columnId,
|
|
560
|
+
const parsed = this.parseDraft(this.editing.columnId, text2);
|
|
560
561
|
if (parsed.ok) {
|
|
561
562
|
this.host.emit("editPreview", this.buildEdit(this.editing, parsed.value));
|
|
562
563
|
}
|
|
@@ -608,12 +609,12 @@ var TableController = class {
|
|
|
608
609
|
};
|
|
609
610
|
}
|
|
610
611
|
/** Parse a draft according to the column's declared type. */
|
|
611
|
-
parseDraft(columnId,
|
|
612
|
+
parseDraft(columnId, text2) {
|
|
612
613
|
const column = this.columnById(columnId);
|
|
613
|
-
const trimmed =
|
|
614
|
+
const trimmed = text2.trim();
|
|
614
615
|
if (column?.type === "number" || column?.type === "integer" || column?.type === "duration") {
|
|
615
616
|
if (trimmed === "") return { ok: true, value: null };
|
|
616
|
-
const parsed = parseNumeric(
|
|
617
|
+
const parsed = parseNumeric(text2);
|
|
617
618
|
if (!parsed.ok) return { ok: false, reason: parsed.reason };
|
|
618
619
|
return { ok: true, value: normalizeNumeric(parsed.value, constraintsOfColumn(column)) };
|
|
619
620
|
}
|
|
@@ -630,7 +631,7 @@ var TableController = class {
|
|
|
630
631
|
value: trimmed === "" ? [] : trimmed.split(",").map((part) => part.trim()).filter(Boolean)
|
|
631
632
|
};
|
|
632
633
|
}
|
|
633
|
-
return { ok: true, value: trimmed === "" ? null :
|
|
634
|
+
return { ok: true, value: trimmed === "" ? null : text2 };
|
|
634
635
|
}
|
|
635
636
|
rowById(rowId) {
|
|
636
637
|
return this.result?.rows.find((r) => r.id === rowId);
|
|
@@ -3239,7 +3240,7 @@ function emptyFilterGroup() {
|
|
|
3239
3240
|
function offerableFilterOps(column, sourceOps = []) {
|
|
3240
3241
|
const common = ["eq", "ne", "isEmpty", "isNotEmpty", "in", "notIn"];
|
|
3241
3242
|
const ordered = ["gt", "gte", "lt", "lte", "between"];
|
|
3242
|
-
const
|
|
3243
|
+
const text2 = ["contains", "notContains", "startsWith", "endsWith"];
|
|
3243
3244
|
const temporal = ["relative"];
|
|
3244
3245
|
let ops = [...common];
|
|
3245
3246
|
switch (column?.type) {
|
|
@@ -3257,10 +3258,10 @@ function offerableFilterOps(column, sourceOps = []) {
|
|
|
3257
3258
|
case "url":
|
|
3258
3259
|
case "select":
|
|
3259
3260
|
case "multiselect":
|
|
3260
|
-
ops = [...ops, ...
|
|
3261
|
+
ops = [...ops, ...text2];
|
|
3261
3262
|
break;
|
|
3262
3263
|
default:
|
|
3263
|
-
ops = [...ops, ...
|
|
3264
|
+
ops = [...ops, ...text2, ...ordered];
|
|
3264
3265
|
}
|
|
3265
3266
|
if (sourceOps.length === 0) return ops;
|
|
3266
3267
|
return ops.filter((op) => sourceOps.includes(op));
|
|
@@ -3891,233 +3892,363 @@ var fieldsManifest = {
|
|
|
3891
3892
|
import { useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
3892
3893
|
import {
|
|
3893
3894
|
Badge as Badge4,
|
|
3895
|
+
Column,
|
|
3894
3896
|
EmptyState as EmptyState4,
|
|
3895
3897
|
IconButton as IconButton3,
|
|
3898
|
+
Note,
|
|
3896
3899
|
Row,
|
|
3897
3900
|
RowList,
|
|
3898
3901
|
ScrollArea as ScrollArea3,
|
|
3899
3902
|
Section,
|
|
3900
3903
|
SegmentedControl as SegmentedControl4,
|
|
3904
|
+
Select,
|
|
3901
3905
|
StatusBar as StatusBar4,
|
|
3902
3906
|
TextButton,
|
|
3903
3907
|
Toolbar as Toolbar4,
|
|
3904
3908
|
ToolbarGroup as ToolbarGroup3
|
|
3905
3909
|
} from "@xenosystem/components/chrome";
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
const
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3910
|
+
|
|
3911
|
+
// src/data/fields/declaration.ts
|
|
3912
|
+
var COMBINATORS = [{ value: "and", label: "All" }, { value: "or", label: "Any" }];
|
|
3913
|
+
function fieldsViewState(c, options = {}) {
|
|
3914
|
+
const s = c.getState();
|
|
3915
|
+
const showStats = options.showStats ?? true;
|
|
3916
|
+
const manualApply = options.manualApply ?? false;
|
|
3917
|
+
const columnOf = (id) => s.columns.find((col) => col.id === id);
|
|
3918
|
+
const shelves = s.shelves.filter((shelf) => shelf.id !== "filters").map((shelf) => {
|
|
3919
|
+
const entries = s.entries[shelf.id] ?? [];
|
|
3920
|
+
return {
|
|
3921
|
+
id: shelf.id,
|
|
3922
|
+
label: shelf.label,
|
|
3923
|
+
count: entries.length,
|
|
3924
|
+
hasEntries: entries.length > 0,
|
|
3925
|
+
empty: entries.length === 0,
|
|
3926
|
+
hint: shelf.hint ?? `Drop a ${shelf.accepts.join(" or ")} here.`,
|
|
3927
|
+
entries: entries.map((entry) => {
|
|
3928
|
+
const column = columnOf(entry.columnId);
|
|
3929
|
+
return {
|
|
3930
|
+
shelfId: shelf.id,
|
|
3931
|
+
columnId: entry.columnId,
|
|
3932
|
+
label: entry.label ?? column?.name ?? entry.columnId,
|
|
3933
|
+
suggested: entry.suggested === true,
|
|
3934
|
+
aggregated: shelf.aggregated === true,
|
|
3935
|
+
fn: entry.fn ?? "count",
|
|
3936
|
+
aggregates: shelf.aggregated ? offerableAggregates(column, s.allowedAggregates).map((fn) => ({ value: fn, label: fn })) : [],
|
|
3937
|
+
sortable: !shelf.aggregated && shelf.id === "sorts",
|
|
3938
|
+
direction: entry.direction === "desc" ? "desc" : "asc",
|
|
3939
|
+
granularity: !shelf.aggregated && shelf.id !== "sorts" ? entry.granularity : void 0,
|
|
3940
|
+
removeLabel: `Remove ${column?.name ?? entry.columnId}`
|
|
3941
|
+
};
|
|
3942
|
+
})
|
|
3943
|
+
};
|
|
3944
|
+
});
|
|
3945
|
+
const filters = s.filters.filters.map((member, index) => {
|
|
3946
|
+
if (!isLeafFilter(member)) {
|
|
3947
|
+
return { key: `g${index}`, index, leaf: false, label: `(${member.combinator.toUpperCase()} group \u2014 ${member.filters.length})`, op: "", ops: [], removeLabel: "Remove group" };
|
|
3948
|
+
}
|
|
3949
|
+
const column = columnOf(member.columnId);
|
|
3950
|
+
return {
|
|
3951
|
+
key: `f${index}`,
|
|
3952
|
+
index,
|
|
3953
|
+
leaf: true,
|
|
3954
|
+
label: column?.name ?? member.columnId,
|
|
3955
|
+
op: member.op,
|
|
3956
|
+
ops: offerableFilterOps(column, s.allowedFilterOps).map((op) => ({ value: op, label: op })),
|
|
3957
|
+
removeLabel: "Remove filter"
|
|
3958
|
+
};
|
|
3959
|
+
});
|
|
3960
|
+
return {
|
|
3961
|
+
hasColumns: s.columns.length > 0,
|
|
3962
|
+
noColumns: s.columns.length === 0,
|
|
3963
|
+
sampleWarning: s.sampleWarning ?? void 0,
|
|
3964
|
+
sampled: !!s.sampleWarning,
|
|
3965
|
+
manualApply,
|
|
3966
|
+
applyDisabled: !s.dirty,
|
|
3967
|
+
columns: s.columns.map((column) => {
|
|
3968
|
+
const stat = showStats ? s.stats[column.id] : void 0;
|
|
3969
|
+
return { id: column.id, name: column.name, role: column.role ?? "dimension", focused: s.focusedColumnId === column.id, stat: stat ? String(stat.distinct ?? 0) : void 0, statTitle: stat ? `${stat.nulls ?? 0} empty` : void 0 };
|
|
3970
|
+
}),
|
|
3971
|
+
shelves,
|
|
3972
|
+
filters,
|
|
3973
|
+
filterCount: s.filters.filters.length,
|
|
3974
|
+
hasFilters: s.filters.filters.length > 0,
|
|
3975
|
+
noFilters: s.filters.filters.length === 0,
|
|
3976
|
+
combinator: s.filters.combinator,
|
|
3977
|
+
countLabel: `${s.columns.length} field${s.columns.length === 1 ? "" : "s"}`,
|
|
3978
|
+
dirtyLabel: s.dirty ? "unapplied" : void 0
|
|
3979
|
+
};
|
|
3980
|
+
}
|
|
3981
|
+
function applyFieldsUi(c, intent) {
|
|
3982
|
+
switch (intent.kind) {
|
|
3983
|
+
case "autoAssign":
|
|
3984
|
+
c.autoAssign();
|
|
3985
|
+
break;
|
|
3986
|
+
case "apply":
|
|
3987
|
+
c.apply(true);
|
|
3988
|
+
break;
|
|
3989
|
+
case "focus":
|
|
3990
|
+
c.focusColumn(intent.columnId);
|
|
3991
|
+
break;
|
|
3992
|
+
case "remove":
|
|
3993
|
+
c.removeFromShelf(intent.shelfId, intent.columnId);
|
|
3994
|
+
break;
|
|
3995
|
+
case "aggregate":
|
|
3996
|
+
c.setAggregate(intent.shelfId, intent.columnId, intent.fn);
|
|
3997
|
+
break;
|
|
3998
|
+
case "direction":
|
|
3999
|
+
c.toggleDirection(intent.shelfId, intent.columnId);
|
|
4000
|
+
break;
|
|
4001
|
+
case "addFilter": {
|
|
4002
|
+
const column = c.getState().columns[0];
|
|
4003
|
+
if (column) c.addFilter([], { columnId: column.id, op: "eq", value: null });
|
|
4004
|
+
break;
|
|
4005
|
+
}
|
|
4006
|
+
case "addGroup":
|
|
4007
|
+
c.addFilterGroup([]);
|
|
4008
|
+
break;
|
|
4009
|
+
case "filterOp":
|
|
4010
|
+
c.updateFilter([], intent.index, { op: intent.op });
|
|
4011
|
+
break;
|
|
4012
|
+
case "removeFilter":
|
|
4013
|
+
c.removeFilter([], intent.index);
|
|
4014
|
+
break;
|
|
4015
|
+
case "combinator":
|
|
4016
|
+
c.setCombinator([], intent.combinator);
|
|
4017
|
+
break;
|
|
4018
|
+
}
|
|
4019
|
+
}
|
|
4020
|
+
var fieldsViewManifest = {
|
|
4021
|
+
id: fieldsManifest.id,
|
|
4022
|
+
version: "1.0.0",
|
|
4023
|
+
title: "Fields",
|
|
4024
|
+
category: "data",
|
|
4025
|
+
layout: { slot: "side" },
|
|
4026
|
+
inputs: [{ id: "view", type: "object", label: "View state", description: "The FieldsViewModel the runtime derives from the controller on every draw." }],
|
|
4027
|
+
outputs: [{ id: "ui", type: "object", label: "UI intent", description: "{ kind, \u2026 } \u2014 applied by the runtime to the controller." }],
|
|
4028
|
+
commands: []
|
|
4029
|
+
};
|
|
4030
|
+
var EMPTY = { hasColumns: false, noColumns: true, sampled: false, manualApply: false, applyDisabled: true, columns: [], shelves: [], filters: [], filterCount: 0, hasFilters: false, noFilters: true, combinator: "and", countLabel: "0 fields" };
|
|
4031
|
+
var BEHAVIOURS = {
|
|
4032
|
+
"data/fieldsPanelView": (inputs) => inputs.view ?? EMPTY
|
|
4033
|
+
};
|
|
4034
|
+
var FIELDS_RUNTIME_UNITS = [];
|
|
4035
|
+
var text = (b) => ({ component: "text", props: { text: b } });
|
|
4036
|
+
var ui = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
|
|
4037
|
+
var removeButton = (label, on) => ({
|
|
4038
|
+
component: "chrome/IconButton",
|
|
4039
|
+
props: { size: { value: "sm" }, icon: { node: { component: "icons/Close", props: { size: { value: 11 } } } }, label },
|
|
4040
|
+
on: { onClick: on }
|
|
4041
|
+
});
|
|
4042
|
+
var FIELDS_DECLARATION = {
|
|
4043
|
+
format: "xeno.block@1",
|
|
4044
|
+
manifest: fieldsViewManifest,
|
|
4045
|
+
behaviour: "data/fieldsPanelView",
|
|
4046
|
+
composition: {
|
|
4047
|
+
component: "fragment",
|
|
4048
|
+
children: [
|
|
4049
|
+
{ component: "chrome/EmptyState", when: { input: "view.noColumns" }, props: { title: { value: "No fields" }, hint: { value: "Connect a source \u2014 its columns appear here, ready to drop onto a shelf." } } },
|
|
3916
4050
|
{
|
|
3917
|
-
|
|
3918
|
-
|
|
4051
|
+
component: "chrome/Column",
|
|
4052
|
+
when: { input: "view.hasColumns" },
|
|
4053
|
+
children: [
|
|
4054
|
+
{
|
|
4055
|
+
component: "chrome/Toolbar",
|
|
4056
|
+
props: {
|
|
4057
|
+
left: { node: { component: "chrome/Badge", when: { input: "view.sampled" }, props: { tone: { value: "warning" }, title: { input: "view.sampleWarning" } }, children: [text({ value: "sampled schema" })] } },
|
|
4058
|
+
right: {
|
|
4059
|
+
node: {
|
|
4060
|
+
component: "chrome/ToolbarGroup",
|
|
4061
|
+
props: { end: { value: true } },
|
|
4062
|
+
children: [
|
|
4063
|
+
{ component: "chrome/TextButton", on: { onClick: ui("autoAssign") }, children: [text({ value: "Auto-assign" })] },
|
|
4064
|
+
{ component: "chrome/TextButton", when: { input: "view.manualApply" }, props: { strong: { value: true }, disabled: { input: "view.applyDisabled" } }, on: { onClick: ui("apply") }, children: [text({ value: "Apply" })] }
|
|
4065
|
+
]
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
}
|
|
4069
|
+
},
|
|
4070
|
+
{
|
|
4071
|
+
component: "chrome/ScrollArea",
|
|
4072
|
+
children: [
|
|
4073
|
+
{
|
|
4074
|
+
component: "chrome/Section",
|
|
4075
|
+
props: { title: { value: "Fields" }, flush: { value: true } },
|
|
4076
|
+
children: [
|
|
4077
|
+
{
|
|
4078
|
+
component: "chrome/RowList",
|
|
4079
|
+
props: { role: { value: "listbox" }, "aria-label": { value: "Fields" } },
|
|
4080
|
+
children: [
|
|
4081
|
+
{
|
|
4082
|
+
component: "chrome/Row",
|
|
4083
|
+
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: [text({ item: "stat" })] } } },
|
|
4085
|
+
on: { onClick: ui("focus", { columnId: { item: "id" } }) }
|
|
4086
|
+
}
|
|
4087
|
+
]
|
|
4088
|
+
}
|
|
4089
|
+
]
|
|
4090
|
+
},
|
|
4091
|
+
{
|
|
4092
|
+
component: "chrome/Section",
|
|
4093
|
+
each: { input: "view.shelves", key: "id" },
|
|
4094
|
+
props: { title: { item: "label" }, flush: { value: true }, badge: { node: { component: "chrome/Badge", when: { item: "hasEntries" }, children: [text({ item: "count" })] } } },
|
|
4095
|
+
children: [
|
|
4096
|
+
{ component: "chrome/Note", when: { item: "empty" }, children: [text({ item: "hint" })] },
|
|
4097
|
+
{
|
|
4098
|
+
component: "chrome/RowList",
|
|
4099
|
+
when: { item: "hasEntries" },
|
|
4100
|
+
children: [
|
|
4101
|
+
{
|
|
4102
|
+
component: "chrome/Row",
|
|
4103
|
+
each: { item: "entries", key: "columnId" },
|
|
4104
|
+
props: {
|
|
4105
|
+
label: { item: "label" },
|
|
4106
|
+
dimmed: { item: "suggested" },
|
|
4107
|
+
meta: {
|
|
4108
|
+
node: {
|
|
4109
|
+
component: "fragment",
|
|
4110
|
+
children: [
|
|
4111
|
+
{ component: "chrome/Select", when: { item: "aggregated" }, props: { size: { value: "sm" }, label: { value: "Aggregate" }, options: { item: "aggregates" }, value: { item: "fn" } }, on: { onChange: ui("aggregate", { shelfId: { item: "shelfId" }, columnId: { item: "columnId" }, fn: { arg: "" } }) } },
|
|
4112
|
+
{ component: "chrome/TextButton", when: { item: "sortable" }, on: { onClick: ui("direction", { shelfId: { item: "shelfId" }, columnId: { item: "columnId" } }) }, children: [text({ item: "direction" })] },
|
|
4113
|
+
{ component: "chrome/Badge", when: { item: "granularity" }, children: [text({ item: "granularity" })] }
|
|
4114
|
+
]
|
|
4115
|
+
}
|
|
4116
|
+
},
|
|
4117
|
+
trailing: { node: removeButton({ item: "removeLabel" }, ui("remove", { shelfId: { item: "shelfId" }, columnId: { item: "columnId" } })) }
|
|
4118
|
+
}
|
|
4119
|
+
}
|
|
4120
|
+
]
|
|
4121
|
+
}
|
|
4122
|
+
]
|
|
4123
|
+
},
|
|
4124
|
+
{
|
|
4125
|
+
component: "chrome/Section",
|
|
4126
|
+
props: {
|
|
4127
|
+
title: { value: "Filters" },
|
|
4128
|
+
flush: { value: true },
|
|
4129
|
+
badge: { node: { component: "chrome/Badge", when: { input: "view.hasFilters" }, children: [text({ input: "view.filterCount" })] } },
|
|
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: ui("addFilter") } } }
|
|
4131
|
+
},
|
|
4132
|
+
children: [
|
|
4133
|
+
{ component: "chrome/Note", when: { input: "view.noFilters" }, children: [text({ value: "No filters. Everything passes." })] },
|
|
4134
|
+
{
|
|
4135
|
+
component: "chrome/RowList",
|
|
4136
|
+
when: { input: "view.hasFilters" },
|
|
4137
|
+
children: [
|
|
4138
|
+
{
|
|
4139
|
+
component: "chrome/Row",
|
|
4140
|
+
each: { input: "view.filters", key: "key" },
|
|
4141
|
+
props: {
|
|
4142
|
+
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: ui("filterOp", { index: { item: "index" }, op: { arg: "" } }) } } },
|
|
4144
|
+
trailing: { node: removeButton({ item: "removeLabel" }, ui("removeFilter", { index: { item: "index" } })) }
|
|
4145
|
+
}
|
|
4146
|
+
}
|
|
4147
|
+
]
|
|
4148
|
+
},
|
|
4149
|
+
{
|
|
4150
|
+
component: "chrome/Toolbar",
|
|
4151
|
+
props: {
|
|
4152
|
+
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: ui("combinator", { combinator: { arg: "" } }) } } },
|
|
4154
|
+
right: { node: { component: "chrome/TextButton", on: { onClick: ui("addGroup") }, children: [text({ value: "+ group" })] } }
|
|
4155
|
+
}
|
|
4156
|
+
}
|
|
4157
|
+
]
|
|
4158
|
+
}
|
|
4159
|
+
]
|
|
4160
|
+
},
|
|
4161
|
+
{ component: "chrome/StatusBar", props: { left: { input: "view.countLabel" }, right: { input: "view.dirtyLabel" } } }
|
|
4162
|
+
]
|
|
3919
4163
|
}
|
|
3920
|
-
|
|
4164
|
+
]
|
|
3921
4165
|
}
|
|
3922
|
-
|
|
4166
|
+
};
|
|
4167
|
+
|
|
4168
|
+
// src/data/fields/react/FieldsPanelView.tsx
|
|
4169
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
4170
|
+
var CloseGlyph = ICONS["icons/Close"];
|
|
4171
|
+
var PlusGlyph = ICONS["icons/Plus"];
|
|
4172
|
+
var COMBINATORS2 = [{ value: "and", label: "All" }, { value: "or", label: "Any" }];
|
|
4173
|
+
function FieldsPanelView({ controller, showStats, manualApply }) {
|
|
4174
|
+
useSyncExternalStore4(controller.subscribe, controller.getState, controller.getState);
|
|
4175
|
+
const view = fieldsViewState(controller, { showStats, manualApply });
|
|
4176
|
+
const ui2 = (intent) => applyFieldsUi(controller, intent);
|
|
4177
|
+
if (view.noColumns) {
|
|
4178
|
+
return /* @__PURE__ */ jsx4(EmptyState4, { title: "No fields", hint: "Connect a source \u2014 its columns appear here, ready to drop onto a shelf." });
|
|
4179
|
+
}
|
|
4180
|
+
return /* @__PURE__ */ jsxs4(Column, { children: [
|
|
3923
4181
|
/* @__PURE__ */ jsx4(
|
|
3924
4182
|
Toolbar4,
|
|
3925
4183
|
{
|
|
3926
|
-
left:
|
|
3927
|
-
// An inferred shape is a GUESS; building a query on a guessed column is how a
|
|
3928
|
-
// dashboard breaks next Tuesday.
|
|
3929
|
-
// Badge has no title prop, so the tooltip lives on a wrapper.
|
|
3930
|
-
/* @__PURE__ */ jsx4("span", { title: state.sampleWarning, children: /* @__PURE__ */ jsx4(Badge4, { tone: "warning", children: "sampled schema" }) })
|
|
3931
|
-
) : void 0,
|
|
4184
|
+
left: view.sampled ? /* @__PURE__ */ jsx4(Badge4, { tone: "warning", title: view.sampleWarning, children: "sampled schema" }) : null,
|
|
3932
4185
|
right: /* @__PURE__ */ jsxs4(ToolbarGroup3, { end: true, children: [
|
|
3933
|
-
/* @__PURE__ */ jsx4(TextButton, { onClick: () =>
|
|
3934
|
-
manualApply ? /* @__PURE__ */ jsx4(TextButton, { strong: true, disabled:
|
|
4186
|
+
/* @__PURE__ */ jsx4(TextButton, { onClick: () => ui2({ kind: "autoAssign" }), children: "Auto-assign" }),
|
|
4187
|
+
view.manualApply ? /* @__PURE__ */ jsx4(TextButton, { strong: true, disabled: view.applyDisabled, onClick: () => ui2({ kind: "apply" }), children: "Apply" }) : null
|
|
3935
4188
|
] })
|
|
3936
4189
|
}
|
|
3937
4190
|
),
|
|
3938
4191
|
/* @__PURE__ */ jsxs4(ScrollArea3, { children: [
|
|
3939
|
-
/* @__PURE__ */ jsx4(Section, { title: "Fields", flush: true, children: /* @__PURE__ */ jsx4(RowList, { children:
|
|
4192
|
+
/* @__PURE__ */ jsx4(Section, { title: "Fields", flush: true, children: /* @__PURE__ */ jsx4(RowList, { role: "listbox", "aria-label": "Fields", children: view.columns.map((column) => /* @__PURE__ */ jsx4(
|
|
3940
4193
|
Row,
|
|
3941
4194
|
{
|
|
3942
4195
|
label: column.name,
|
|
3943
|
-
meta: column.role
|
|
3944
|
-
selected:
|
|
3945
|
-
|
|
3946
|
-
|
|
4196
|
+
meta: column.role,
|
|
4197
|
+
selected: column.focused,
|
|
4198
|
+
trailing: column.stat ? /* @__PURE__ */ jsx4(Badge4, { title: column.statTitle, children: column.stat }) : null,
|
|
4199
|
+
onClick: () => ui2({ kind: "focus", columnId: column.id })
|
|
3947
4200
|
},
|
|
3948
4201
|
column.id
|
|
3949
4202
|
)) }) }),
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
4203
|
+
view.shelves.map((shelf) => /* @__PURE__ */ jsxs4(Section, { title: shelf.label, flush: true, badge: shelf.hasEntries ? /* @__PURE__ */ jsx4(Badge4, { children: shelf.count }) : null, children: [
|
|
4204
|
+
shelf.empty ? /* @__PURE__ */ jsx4(Note, { children: shelf.hint }) : null,
|
|
4205
|
+
shelf.hasEntries ? /* @__PURE__ */ jsx4(RowList, { children: shelf.entries.map((entry) => /* @__PURE__ */ jsx4(
|
|
4206
|
+
Row,
|
|
3954
4207
|
{
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
label: entry.label ?? column?.name ?? entry.columnId,
|
|
3964
|
-
style: entry.suggested ? { opacity: 0.6 } : void 0,
|
|
3965
|
-
meta: shelf.aggregated ? /* @__PURE__ */ jsx4(
|
|
3966
|
-
AggregateSelect,
|
|
3967
|
-
{
|
|
3968
|
-
controller,
|
|
3969
|
-
shelfId: shelf.id,
|
|
3970
|
-
column,
|
|
3971
|
-
value: entry.fn ?? "count",
|
|
3972
|
-
allowed: state.allowedAggregates
|
|
3973
|
-
}
|
|
3974
|
-
) : shelf.id === "sorts" ? /* @__PURE__ */ jsx4(
|
|
3975
|
-
TextButton,
|
|
3976
|
-
{
|
|
3977
|
-
onClick: () => controller.toggleDirection(shelf.id, entry.columnId),
|
|
3978
|
-
children: entry.direction === "desc" ? "desc" : "asc"
|
|
3979
|
-
}
|
|
3980
|
-
) : entry.granularity ? /* @__PURE__ */ jsx4(Badge4, { children: entry.granularity }) : null,
|
|
3981
|
-
trailing: /* @__PURE__ */ jsx4(
|
|
3982
|
-
IconButton3,
|
|
3983
|
-
{
|
|
3984
|
-
size: "sm",
|
|
3985
|
-
icon: /* @__PURE__ */ jsx4(XGlyph, {}),
|
|
3986
|
-
label: `Remove ${column?.name ?? entry.columnId}`,
|
|
3987
|
-
onClick: () => controller.removeFromShelf(shelf.id, entry.columnId)
|
|
3988
|
-
}
|
|
3989
|
-
)
|
|
3990
|
-
},
|
|
3991
|
-
entry.columnId
|
|
3992
|
-
);
|
|
3993
|
-
}) })
|
|
4208
|
+
label: entry.label,
|
|
4209
|
+
dimmed: entry.suggested,
|
|
4210
|
+
meta: /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
4211
|
+
entry.aggregated ? /* @__PURE__ */ jsx4(Select, { size: "sm", label: "Aggregate", options: entry.aggregates, value: entry.fn, onChange: (fn) => ui2({ kind: "aggregate", shelfId: entry.shelfId, columnId: entry.columnId, fn }) }) : null,
|
|
4212
|
+
entry.sortable ? /* @__PURE__ */ jsx4(TextButton, { onClick: () => ui2({ kind: "direction", shelfId: entry.shelfId, columnId: entry.columnId }), children: entry.direction }) : null,
|
|
4213
|
+
entry.granularity ? /* @__PURE__ */ jsx4(Badge4, { children: entry.granularity }) : null
|
|
4214
|
+
] }),
|
|
4215
|
+
trailing: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(CloseGlyph, { size: 11 }), label: entry.removeLabel, onClick: () => ui2({ kind: "remove", shelfId: entry.shelfId, columnId: entry.columnId }) })
|
|
3994
4216
|
},
|
|
3995
|
-
|
|
3996
|
-
)
|
|
3997
|
-
}),
|
|
3998
|
-
/* @__PURE__ */
|
|
3999
|
-
|
|
4000
|
-
/* @__PURE__ */ jsx4(
|
|
4001
|
-
StatusBar4,
|
|
4002
|
-
{
|
|
4003
|
-
left: `${state.columns.length} field${state.columns.length === 1 ? "" : "s"}`,
|
|
4004
|
-
right: state.dirty ? "unapplied" : void 0
|
|
4005
|
-
}
|
|
4006
|
-
)
|
|
4007
|
-
] });
|
|
4008
|
-
}
|
|
4009
|
-
function AggregateSelect({
|
|
4010
|
-
controller,
|
|
4011
|
-
shelfId,
|
|
4012
|
-
column,
|
|
4013
|
-
value,
|
|
4014
|
-
allowed
|
|
4015
|
-
}) {
|
|
4016
|
-
const options = offerableAggregates(column, allowed);
|
|
4017
|
-
return /* @__PURE__ */ jsx4(
|
|
4018
|
-
"select",
|
|
4019
|
-
{
|
|
4020
|
-
value,
|
|
4021
|
-
onClick: (e) => e.stopPropagation(),
|
|
4022
|
-
onChange: (e) => controller.setAggregate(shelfId, column?.id ?? "", e.target.value),
|
|
4023
|
-
style: { font: "inherit", fontSize: 9, background: "transparent", color: "inherit", border: "none" },
|
|
4024
|
-
children: options.map((fn) => /* @__PURE__ */ jsx4("option", { value: fn, children: fn }, fn))
|
|
4025
|
-
}
|
|
4026
|
-
);
|
|
4027
|
-
}
|
|
4028
|
-
function FilterBuilder({ controller }) {
|
|
4029
|
-
const state = useSyncExternalStore4(controller.subscribe, controller.getState, controller.getState);
|
|
4030
|
-
return /* @__PURE__ */ jsxs4(
|
|
4031
|
-
Section,
|
|
4032
|
-
{
|
|
4033
|
-
title: "Filters",
|
|
4034
|
-
badge: state.filters.filters.length > 0 ? /* @__PURE__ */ jsx4(Badge4, { children: String(state.filters.filters.length) }) : void 0,
|
|
4035
|
-
actions: /* @__PURE__ */ jsx4(
|
|
4036
|
-
IconButton3,
|
|
4217
|
+
entry.columnId
|
|
4218
|
+
)) }) : null
|
|
4219
|
+
] }, shelf.id)),
|
|
4220
|
+
/* @__PURE__ */ jsxs4(
|
|
4221
|
+
Section,
|
|
4037
4222
|
{
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
onClick: () => {
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
}
|
|
4046
|
-
),
|
|
4047
|
-
flush: true,
|
|
4048
|
-
children: [
|
|
4049
|
-
state.filters.filters.length === 0 ? /* @__PURE__ */ jsx4("div", { style: { padding: "4px 8px", fontSize: 10, opacity: 0.5 }, children: "No filters. Everything passes." }) : /* @__PURE__ */ jsx4(RowList, { children: state.filters.filters.map((member, index) => {
|
|
4050
|
-
if (!isLeafFilter(member)) {
|
|
4051
|
-
return /* @__PURE__ */ jsx4(
|
|
4223
|
+
title: "Filters",
|
|
4224
|
+
flush: true,
|
|
4225
|
+
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: () => ui2({ kind: "addFilter" }) }),
|
|
4227
|
+
children: [
|
|
4228
|
+
view.noFilters ? /* @__PURE__ */ jsx4(Note, { children: "No filters. Everything passes." }) : null,
|
|
4229
|
+
view.hasFilters ? /* @__PURE__ */ jsx4(RowList, { children: view.filters.map((filter) => /* @__PURE__ */ jsx4(
|
|
4052
4230
|
Row,
|
|
4053
4231
|
{
|
|
4054
|
-
label:
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
{
|
|
4058
|
-
size: "sm",
|
|
4059
|
-
icon: /* @__PURE__ */ jsx4(XGlyph, {}),
|
|
4060
|
-
label: "Remove group",
|
|
4061
|
-
onClick: () => controller.removeFilter([], index)
|
|
4062
|
-
}
|
|
4063
|
-
)
|
|
4232
|
+
label: filter.label,
|
|
4233
|
+
meta: filter.leaf ? /* @__PURE__ */ jsx4(Select, { size: "sm", label: "Operator", options: filter.ops, value: filter.op, onChange: (op) => ui2({ kind: "filterOp", index: filter.index, op }) }) : null,
|
|
4234
|
+
trailing: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(CloseGlyph, { size: 11 }), label: filter.removeLabel, onClick: () => ui2({ kind: "removeFilter", index: filter.index }) })
|
|
4064
4235
|
},
|
|
4065
|
-
|
|
4066
|
-
)
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
fontSize: 9,
|
|
4082
|
-
background: "transparent",
|
|
4083
|
-
color: "inherit",
|
|
4084
|
-
border: "none"
|
|
4085
|
-
},
|
|
4086
|
-
children: offerableFilterOps(column, state.allowedFilterOps).map((op) => /* @__PURE__ */ jsx4("option", { value: op, children: op }, op))
|
|
4087
|
-
}
|
|
4088
|
-
),
|
|
4089
|
-
trailing: /* @__PURE__ */ jsx4(
|
|
4090
|
-
IconButton3,
|
|
4091
|
-
{
|
|
4092
|
-
size: "sm",
|
|
4093
|
-
icon: /* @__PURE__ */ jsx4(XGlyph, {}),
|
|
4094
|
-
label: "Remove filter",
|
|
4095
|
-
onClick: () => controller.removeFilter([], index)
|
|
4096
|
-
}
|
|
4097
|
-
)
|
|
4098
|
-
},
|
|
4099
|
-
`f${index}`
|
|
4100
|
-
);
|
|
4101
|
-
}) }),
|
|
4102
|
-
/* @__PURE__ */ jsxs4("div", { style: { padding: "2px 8px", display: "flex", gap: 8 }, children: [
|
|
4103
|
-
/* @__PURE__ */ jsx4(
|
|
4104
|
-
SegmentedControl4,
|
|
4105
|
-
{
|
|
4106
|
-
size: "sm",
|
|
4107
|
-
label: "Combinator",
|
|
4108
|
-
options: [
|
|
4109
|
-
{ value: "and", label: "All" },
|
|
4110
|
-
{ value: "or", label: "Any" }
|
|
4111
|
-
],
|
|
4112
|
-
value: state.filters.combinator,
|
|
4113
|
-
onChange: (c) => controller.setCombinator([], c)
|
|
4114
|
-
}
|
|
4115
|
-
),
|
|
4116
|
-
/* @__PURE__ */ jsx4(TextButton, { onClick: () => controller.addFilterGroup([]), children: "+ group" })
|
|
4117
|
-
] })
|
|
4118
|
-
]
|
|
4119
|
-
}
|
|
4120
|
-
);
|
|
4236
|
+
filter.key
|
|
4237
|
+
)) }) : null,
|
|
4238
|
+
/* @__PURE__ */ jsx4(
|
|
4239
|
+
Toolbar4,
|
|
4240
|
+
{
|
|
4241
|
+
divided: false,
|
|
4242
|
+
left: /* @__PURE__ */ jsx4(SegmentedControl4, { size: "sm", label: "Combinator", options: COMBINATORS2, value: view.combinator, onChange: (combinator) => ui2({ kind: "combinator", combinator }) }),
|
|
4243
|
+
right: /* @__PURE__ */ jsx4(TextButton, { onClick: () => ui2({ kind: "addGroup" }), children: "+ group" })
|
|
4244
|
+
}
|
|
4245
|
+
)
|
|
4246
|
+
]
|
|
4247
|
+
}
|
|
4248
|
+
)
|
|
4249
|
+
] }),
|
|
4250
|
+
/* @__PURE__ */ jsx4(StatusBar4, { left: view.countLabel, right: view.dirtyLabel })
|
|
4251
|
+
] });
|
|
4121
4252
|
}
|
|
4122
4253
|
|
|
4123
4254
|
// src/data/fields/panel.ts
|
|
@@ -5245,10 +5376,10 @@ function parseJsonPath(path) {
|
|
|
5245
5376
|
}
|
|
5246
5377
|
return steps;
|
|
5247
5378
|
}
|
|
5248
|
-
function findBracketEnd(
|
|
5379
|
+
function findBracketEnd(text2, start) {
|
|
5249
5380
|
let quote = null;
|
|
5250
|
-
for (let i = start + 1; i <
|
|
5251
|
-
const char =
|
|
5381
|
+
for (let i = start + 1; i < text2.length; i += 1) {
|
|
5382
|
+
const char = text2[i];
|
|
5252
5383
|
if (quote) {
|
|
5253
5384
|
if (char === "\\") i += 1;
|
|
5254
5385
|
else if (char === quote) quote = null;
|
|
@@ -5672,9 +5803,9 @@ function firstGraphqlError(errors) {
|
|
|
5672
5803
|
}
|
|
5673
5804
|
|
|
5674
5805
|
// src/data/connectors/executors/csv.ts
|
|
5675
|
-
function sniffDelimiter(
|
|
5806
|
+
function sniffDelimiter(text2) {
|
|
5676
5807
|
const candidates = [",", ";", " ", "|"];
|
|
5677
|
-
const line = firstLogicalLine(
|
|
5808
|
+
const line = firstLogicalLine(text2);
|
|
5678
5809
|
let best = ",";
|
|
5679
5810
|
let bestCount = 0;
|
|
5680
5811
|
for (const candidate of candidates) {
|
|
@@ -5696,21 +5827,21 @@ function sniffDelimiter(text) {
|
|
|
5696
5827
|
}
|
|
5697
5828
|
return best;
|
|
5698
5829
|
}
|
|
5699
|
-
function firstLogicalLine(
|
|
5830
|
+
function firstLogicalLine(text2) {
|
|
5700
5831
|
let inQuotes = false;
|
|
5701
|
-
for (let i = 0; i <
|
|
5702
|
-
const char =
|
|
5832
|
+
for (let i = 0; i < text2.length; i += 1) {
|
|
5833
|
+
const char = text2[i];
|
|
5703
5834
|
if (char === '"') {
|
|
5704
|
-
if (inQuotes &&
|
|
5835
|
+
if (inQuotes && text2[i + 1] === '"') i += 1;
|
|
5705
5836
|
else inQuotes = !inQuotes;
|
|
5706
5837
|
} else if ((char === "\n" || char === "\r") && !inQuotes) {
|
|
5707
|
-
return
|
|
5838
|
+
return text2.slice(0, i);
|
|
5708
5839
|
}
|
|
5709
5840
|
}
|
|
5710
|
-
return
|
|
5841
|
+
return text2;
|
|
5711
5842
|
}
|
|
5712
|
-
function parseCsv(
|
|
5713
|
-
const source =
|
|
5843
|
+
function parseCsv(text2, options = {}) {
|
|
5844
|
+
const source = text2.charCodeAt(0) === 65279 ? text2.slice(1) : text2;
|
|
5714
5845
|
const delimiter = options.delimiter && options.delimiter.length > 0 ? options.delimiter : sniffDelimiter(source);
|
|
5715
5846
|
const quote = options.quote && options.quote.length > 0 ? options.quote : '"';
|
|
5716
5847
|
const hasHeader = options.hasHeader ?? true;
|
|
@@ -5745,17 +5876,17 @@ function dedupe(names) {
|
|
|
5745
5876
|
return count === 0 ? name : `${name}_${count + 1}`;
|
|
5746
5877
|
});
|
|
5747
5878
|
}
|
|
5748
|
-
function scanRecords(
|
|
5879
|
+
function scanRecords(text2, delimiter, quote) {
|
|
5749
5880
|
const records = [];
|
|
5750
5881
|
let fields = [];
|
|
5751
5882
|
let field = "";
|
|
5752
5883
|
let inQuotes = false;
|
|
5753
5884
|
let i = 0;
|
|
5754
|
-
while (i <
|
|
5755
|
-
const char =
|
|
5885
|
+
while (i < text2.length) {
|
|
5886
|
+
const char = text2[i];
|
|
5756
5887
|
if (inQuotes) {
|
|
5757
5888
|
if (char === quote) {
|
|
5758
|
-
if (
|
|
5889
|
+
if (text2[i + 1] === quote) {
|
|
5759
5890
|
field += quote;
|
|
5760
5891
|
i += 2;
|
|
5761
5892
|
continue;
|
|
@@ -5773,7 +5904,7 @@ function scanRecords(text, delimiter, quote) {
|
|
|
5773
5904
|
i += 1;
|
|
5774
5905
|
continue;
|
|
5775
5906
|
}
|
|
5776
|
-
if (
|
|
5907
|
+
if (text2.startsWith(delimiter, i)) {
|
|
5777
5908
|
fields.push(field);
|
|
5778
5909
|
field = "";
|
|
5779
5910
|
i += delimiter.length;
|
|
@@ -5784,7 +5915,7 @@ function scanRecords(text, delimiter, quote) {
|
|
|
5784
5915
|
records.push(fields);
|
|
5785
5916
|
fields = [];
|
|
5786
5917
|
field = "";
|
|
5787
|
-
i += char === "\r" &&
|
|
5918
|
+
i += char === "\r" && text2[i + 1] === "\n" ? 2 : 1;
|
|
5788
5919
|
continue;
|
|
5789
5920
|
}
|
|
5790
5921
|
field += char;
|
|
@@ -6935,7 +7066,10 @@ export {
|
|
|
6935
7066
|
DEFAULT_RANGES,
|
|
6936
7067
|
EMPTY_LAYOUT,
|
|
6937
7068
|
EXPIRY_SKEW_MS,
|
|
7069
|
+
BEHAVIOURS as FIELDS_BEHAVIOURS,
|
|
7070
|
+
FIELDS_DECLARATION,
|
|
6938
7071
|
FIELDS_PANEL_ID,
|
|
7072
|
+
FIELDS_RUNTIME_UNITS,
|
|
6939
7073
|
FieldsController,
|
|
6940
7074
|
FieldsPanelView,
|
|
6941
7075
|
IMPLEMENTED_VIEW_MODES,
|
|
@@ -6950,6 +7084,7 @@ export {
|
|
|
6950
7084
|
TABLE_PANEL_ID,
|
|
6951
7085
|
TableController,
|
|
6952
7086
|
TablePanelView,
|
|
7087
|
+
applyFieldsUi,
|
|
6953
7088
|
applyPrecision,
|
|
6954
7089
|
base64Url,
|
|
6955
7090
|
breachSideOf,
|
|
@@ -7001,6 +7136,8 @@ export {
|
|
|
7001
7136
|
facilitiesOf,
|
|
7002
7137
|
fieldsManifest,
|
|
7003
7138
|
fieldsPanel,
|
|
7139
|
+
fieldsViewManifest,
|
|
7140
|
+
fieldsViewState,
|
|
7004
7141
|
firstGraphqlError,
|
|
7005
7142
|
frozenWidth,
|
|
7006
7143
|
getChartRenderer,
|