@ocelescope/core 0.10.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ActivityPicker-BfA34hBU.js +29 -0
- package/dist/{AreaChart-DoD3LM50.js → AreaChart-q6rVcUIp.js} +4 -3
- package/dist/AttributePicker-Dd8eKA_3.js +95 -0
- package/dist/{BarChart-Cixo5Okd.js → BarChart-BLZS87ex.js} +4 -3
- package/dist/E2ORelationPicker-CcDSJWc0.js +46 -0
- package/dist/EventAttributePicker-Ch0rYS1h.js +27 -0
- package/dist/EventPicker-DbqFMMr2.js +39 -0
- package/dist/HistogramChart-GgiQdlsk.js +87 -0
- package/dist/{LineChart-CVz-dkJI.js → LineChart-Cq935Tk2.js} +4 -3
- package/dist/O2ORelationPicker-_XU1FfIX.js +44 -0
- package/dist/ObjectAttributePicker-Dpt3IfC5.js +27 -0
- package/dist/ObjectPicker-Bd68wl9p.js +39 -0
- package/dist/ObjectTypePicker-CXCMky34.js +42 -0
- package/dist/{OcelChart-DvGTjJXo.js → OcelChart-BnXjHb_r.js} +1 -1
- package/dist/OptionPicker-D9rUIwbY.js +351 -0
- package/dist/{PieChart-DBiASngC.js → PieChart-DZFHaTXD.js} +4 -3
- package/dist/{ScatterChart-jIQOjQes.js → ScatterChart-DJfJmABJ.js} +4 -3
- package/dist/{SqlChart-bwDArK2l.js → SqlChart-Bf7D5o5P.js} +33 -33
- package/dist/{SunburstChart-D6FhYBHI.js → SunburstChart-CMNYlKon.js} +3 -2
- package/dist/attributeOptions-D4slIoZx.js +37 -0
- package/dist/{cartesian-5TPNWjl_.js → cartesian-Dt7weMqK.js} +1 -1
- package/dist/index.d.ts +240 -143
- package/dist/index.js +28 -100
- package/dist/relationOptions-DTtIOIr1.js +33 -0
- package/dist/{series-BBXVjHHY.js → series-W1jsVape.js} +1 -1
- package/dist/style.css +596 -731
- package/dist/{Plot-CxHHyXot.js → useChart-jzzXgs0j.js} +28 -1
- package/dist/{useOcelId-BSU0-Srk.js → useOcelId-DIu_aGLH.js} +5 -2
- package/dist/useSearch-Ad3AtTVj.js +19 -0
- package/package.json +17 -18
- package/dist/ActivityPicker-DbrGeiC_.js +0 -18
- package/dist/EventAttributePicker-Cf2vVKv5.js +0 -27
- package/dist/NamePicker-Be-qmr1x.js +0 -43
- package/dist/ObjectAttributePicker-CL43EsYt.js +0 -27
- package/dist/ObjectTypePicker-CKmszS0y.js +0 -18
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { ChevronsUpDownIcon, SearchIcon, XIcon } from "lucide-react";
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Badge, Button, Flex, Popover, Spinner, Text, TextField, Theme } from "@r4pm/components/ui";
|
|
5
|
+
import { EmptyState, ErrorState, FrequencyPicker, SkeletonList, softBadgeStyle } from "@r4pm/components";
|
|
6
|
+
//#region src/components/Pickers/internal/Field.tsx
|
|
7
|
+
/**
|
|
8
|
+
* A picker's label and help text above it.
|
|
9
|
+
*
|
|
10
|
+
* Its own Radix theme, since a Mantine modal is portalled outside the app's:
|
|
11
|
+
* there the Radix parts would lose their styles. Within the app's theme it
|
|
12
|
+
* only inherits it.
|
|
13
|
+
*/
|
|
14
|
+
const Field = ({ label, description, children }) => /* @__PURE__ */ jsx(Theme, {
|
|
15
|
+
asChild: true,
|
|
16
|
+
hasBackground: false,
|
|
17
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
18
|
+
direction: "column",
|
|
19
|
+
gap: "1",
|
|
20
|
+
width: "100%",
|
|
21
|
+
children: [
|
|
22
|
+
label && /* @__PURE__ */ jsx(Text, {
|
|
23
|
+
as: "div",
|
|
24
|
+
size: "2",
|
|
25
|
+
weight: "medium",
|
|
26
|
+
children: label
|
|
27
|
+
}),
|
|
28
|
+
description && /* @__PURE__ */ jsx(Text, {
|
|
29
|
+
as: "div",
|
|
30
|
+
size: "1",
|
|
31
|
+
color: "gray",
|
|
32
|
+
children: description
|
|
33
|
+
}),
|
|
34
|
+
children
|
|
35
|
+
]
|
|
36
|
+
})
|
|
37
|
+
});
|
|
38
|
+
/** A dot in a choice's colour. */
|
|
39
|
+
const Swatch = ({ color }) => color ? /* @__PURE__ */ jsx("span", {
|
|
40
|
+
"aria-hidden": true,
|
|
41
|
+
style: {
|
|
42
|
+
flex: "none",
|
|
43
|
+
width: 8,
|
|
44
|
+
height: 8,
|
|
45
|
+
borderRadius: "50%",
|
|
46
|
+
background: color
|
|
47
|
+
}
|
|
48
|
+
}) : null;
|
|
49
|
+
/** Picked values as badges, each with a button that takes it out. */
|
|
50
|
+
const PickedBadges = ({ picked, onRemove, disabled }) => picked.length === 0 ? null : /* @__PURE__ */ jsx(Flex, {
|
|
51
|
+
gap: "1",
|
|
52
|
+
wrap: "wrap",
|
|
53
|
+
children: picked.map(({ id, label, color }) => /* @__PURE__ */ jsxs(Badge, {
|
|
54
|
+
size: "1",
|
|
55
|
+
style: color ? softBadgeStyle(color) : void 0,
|
|
56
|
+
color: color ? void 0 : "gray",
|
|
57
|
+
children: [label, !disabled && /* @__PURE__ */ jsx(XIcon, {
|
|
58
|
+
size: 12,
|
|
59
|
+
role: "button",
|
|
60
|
+
tabIndex: 0,
|
|
61
|
+
"aria-label": `Remove ${label}`,
|
|
62
|
+
style: { cursor: "pointer" },
|
|
63
|
+
onClick: () => onRemove(id),
|
|
64
|
+
onKeyDown: (event) => {
|
|
65
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
onRemove(id);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
})]
|
|
71
|
+
}, id))
|
|
72
|
+
});
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/components/Pickers/internal/ListSelect.module.css
|
|
75
|
+
var ListSelect_module_default = {
|
|
76
|
+
"hideCount": "wENrqW_hideCount",
|
|
77
|
+
"single": "wENrqW_single"
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/components/Pickers/internal/options.ts
|
|
81
|
+
const defaultIdOf = (value) => typeof value === "string" ? value : JSON.stringify(value);
|
|
82
|
+
/** The picked values, however the caller holds them. */
|
|
83
|
+
const pickedValues = (selection) => selection.multiple ? [...selection.value] : selection.value == null ? [] : [selection.value];
|
|
84
|
+
/** Report values back as the one value, or the list, the caller asked for. */
|
|
85
|
+
const report = (selection, values) => {
|
|
86
|
+
if (selection.multiple) selection.onChange(values);
|
|
87
|
+
else selection.onChange(values[0]);
|
|
88
|
+
};
|
|
89
|
+
/** Options in groups, in first-seen order. Ungrouped options form one group. */
|
|
90
|
+
const groupOptions = (options) => {
|
|
91
|
+
const groups = /* @__PURE__ */ new Map();
|
|
92
|
+
for (const option of options) {
|
|
93
|
+
const key = option.group?.label ?? "";
|
|
94
|
+
const entry = groups.get(key) ?? {
|
|
95
|
+
group: option.group,
|
|
96
|
+
options: []
|
|
97
|
+
};
|
|
98
|
+
entry.options.push(option);
|
|
99
|
+
groups.set(key, entry);
|
|
100
|
+
}
|
|
101
|
+
return [...groups.values()];
|
|
102
|
+
};
|
|
103
|
+
const sortOptions = (options, sort) => [...options].sort((a, b) => sort === "name" ? a.label.localeCompare(b.label) : (b.count ?? 0) - (a.count ?? 0) || a.label.localeCompare(b.label));
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/components/Pickers/internal/ListSelect.tsx
|
|
106
|
+
/** Lists at most this long get no search box of their own. */
|
|
107
|
+
const SEARCH_FROM = 8;
|
|
108
|
+
/** One r4pm list scrolls after eight rows; several groups of them share
|
|
109
|
+
* this height, so a grouped picker stays as compact. */
|
|
110
|
+
const GROUPS_HEIGHT = 320;
|
|
111
|
+
/**
|
|
112
|
+
* Every choice at once, one r4pm `FrequencyPicker` per group, so choices
|
|
113
|
+
* keep the colour and frequency bars they have in the viewers.
|
|
114
|
+
*/
|
|
115
|
+
const ListSelect = ({ model, counts = true, bars = true, cutoff = false, sort = "count", emptyText, disabled, autoFocus, loading, error, missing, search, onSearch, total }) => {
|
|
116
|
+
const groups = groupOptions(model.options);
|
|
117
|
+
const groupsRef = useRef(null);
|
|
118
|
+
const groupCount = groups.length;
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
if (groupCount < 2) return;
|
|
121
|
+
const frame = requestAnimationFrame(() => groupsRef.current?.scrollTo({ top: 0 }));
|
|
122
|
+
return () => cancelAnimationFrame(frame);
|
|
123
|
+
}, [groupCount]);
|
|
124
|
+
const shownIds = new Set(model.options.map((o) => model.idOf(o.value)));
|
|
125
|
+
const offList = model.picked.filter(({ id }) => !shownIds.has(id));
|
|
126
|
+
const content = () => {
|
|
127
|
+
if (missing) return /* @__PURE__ */ jsx(EmptyState, { title: missing });
|
|
128
|
+
if (error) return /* @__PURE__ */ jsx(ErrorState, {
|
|
129
|
+
error,
|
|
130
|
+
title: "Couldn't load"
|
|
131
|
+
});
|
|
132
|
+
if (loading && model.options.length === 0) return /* @__PURE__ */ jsx(SkeletonList, { rows: 4 });
|
|
133
|
+
if (model.options.length === 0) return /* @__PURE__ */ jsx(EmptyState, { title: emptyText ?? "Nothing to choose from" });
|
|
134
|
+
const lists = groups.map(({ group, options }) => {
|
|
135
|
+
const byLabel = new Map(options.map((option) => [option.label, option]));
|
|
136
|
+
const groupIds = new Set(options.map((o) => model.idOf(o.value)));
|
|
137
|
+
const pickedLabels = options.filter((option) => model.pickedIds.has(model.idOf(option.value))).map((option) => option.label);
|
|
138
|
+
return /* @__PURE__ */ jsxs(Flex, {
|
|
139
|
+
direction: "column",
|
|
140
|
+
gap: "1",
|
|
141
|
+
children: [group && /* @__PURE__ */ jsxs(Flex, {
|
|
142
|
+
gap: "2",
|
|
143
|
+
align: "center",
|
|
144
|
+
children: [/* @__PURE__ */ jsx(Badge, {
|
|
145
|
+
size: "1",
|
|
146
|
+
style: group.color ? softBadgeStyle(group.color) : void 0,
|
|
147
|
+
children: group.label
|
|
148
|
+
}), group.caption && /* @__PURE__ */ jsx(Text, {
|
|
149
|
+
size: "1",
|
|
150
|
+
color: "gray",
|
|
151
|
+
children: group.caption
|
|
152
|
+
})]
|
|
153
|
+
}), /* @__PURE__ */ jsx(FrequencyPicker, {
|
|
154
|
+
items: options.map((option) => ({
|
|
155
|
+
key: option.label,
|
|
156
|
+
count: option.count ?? 0
|
|
157
|
+
})),
|
|
158
|
+
value: new Set(pickedLabels),
|
|
159
|
+
onChange: (next) => {
|
|
160
|
+
if (disabled) return;
|
|
161
|
+
const values = [...next].flatMap((label) => {
|
|
162
|
+
const option = byLabel.get(label);
|
|
163
|
+
return option ? [option.value] : [];
|
|
164
|
+
});
|
|
165
|
+
if (!model.multiple) {
|
|
166
|
+
const fresh = values.find((value) => !model.pickedIds.has(model.idOf(value)));
|
|
167
|
+
return model.set(fresh !== void 0 ? [fresh] : values);
|
|
168
|
+
}
|
|
169
|
+
model.set([...model.picked.filter(({ id }) => !groupIds.has(id)).map(({ value }) => value), ...values]);
|
|
170
|
+
},
|
|
171
|
+
mode: model.multiple ? "multi" : "single",
|
|
172
|
+
searchable: !onSearch && options.length > SEARCH_FROM,
|
|
173
|
+
showBars: bars,
|
|
174
|
+
showCounts: counts,
|
|
175
|
+
showCutoff: cutoff,
|
|
176
|
+
sort,
|
|
177
|
+
colorOf: (_, key) => byLabel.get(key)?.color,
|
|
178
|
+
autoFocus,
|
|
179
|
+
emptyText: "Nothing matches"
|
|
180
|
+
})]
|
|
181
|
+
}, group?.label ?? "");
|
|
182
|
+
});
|
|
183
|
+
return groups.length > 1 ? /* @__PURE__ */ jsx(Flex, {
|
|
184
|
+
direction: "column",
|
|
185
|
+
gap: "3",
|
|
186
|
+
ref: groupsRef,
|
|
187
|
+
style: {
|
|
188
|
+
maxHeight: GROUPS_HEIGHT,
|
|
189
|
+
overflowY: "auto",
|
|
190
|
+
overflowX: "hidden"
|
|
191
|
+
},
|
|
192
|
+
children: lists
|
|
193
|
+
}) : lists;
|
|
194
|
+
};
|
|
195
|
+
return /* @__PURE__ */ jsxs(Flex, {
|
|
196
|
+
direction: "column",
|
|
197
|
+
gap: "2",
|
|
198
|
+
className: [!model.multiple || total !== void 0 ? ListSelect_module_default.hideCount : "", model.multiple ? "" : ListSelect_module_default.single].join(" "),
|
|
199
|
+
children: [
|
|
200
|
+
onSearch && /* @__PURE__ */ jsxs(TextField.Root, {
|
|
201
|
+
size: "2",
|
|
202
|
+
value: search ?? "",
|
|
203
|
+
placeholder: "Search…",
|
|
204
|
+
autoFocus,
|
|
205
|
+
disabled: disabled || !!missing,
|
|
206
|
+
onChange: (event) => onSearch(event.currentTarget.value),
|
|
207
|
+
children: [/* @__PURE__ */ jsx(TextField.Slot, { children: /* @__PURE__ */ jsx(SearchIcon, {
|
|
208
|
+
size: 14,
|
|
209
|
+
"aria-hidden": true
|
|
210
|
+
}) }), loading && /* @__PURE__ */ jsx(TextField.Slot, {
|
|
211
|
+
side: "right",
|
|
212
|
+
children: /* @__PURE__ */ jsx(Spinner, { size: "1" })
|
|
213
|
+
})]
|
|
214
|
+
}),
|
|
215
|
+
model.multiple && total !== void 0 && /* @__PURE__ */ jsxs(Text, {
|
|
216
|
+
size: "1",
|
|
217
|
+
color: "gray",
|
|
218
|
+
children: [
|
|
219
|
+
model.picked.length,
|
|
220
|
+
" of ",
|
|
221
|
+
total.toLocaleString(),
|
|
222
|
+
" selected"
|
|
223
|
+
]
|
|
224
|
+
}),
|
|
225
|
+
/* @__PURE__ */ jsx(PickedBadges, {
|
|
226
|
+
picked: offList,
|
|
227
|
+
onRemove: model.remove,
|
|
228
|
+
disabled
|
|
229
|
+
}),
|
|
230
|
+
content()
|
|
231
|
+
]
|
|
232
|
+
});
|
|
233
|
+
};
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/components/Pickers/internal/DropdownSelect.tsx
|
|
236
|
+
/**
|
|
237
|
+
* A field that names what is picked and opens the list in a popover, so both
|
|
238
|
+
* variants are the same list.
|
|
239
|
+
*/
|
|
240
|
+
const DropdownSelect = (props) => {
|
|
241
|
+
const { model, label, placeholder, disabled, missing, loading } = props;
|
|
242
|
+
const [open, setOpen] = useState(props.autoFocus ?? false);
|
|
243
|
+
const [first, ...more] = model.picked;
|
|
244
|
+
const total = props.total ?? model.options.length;
|
|
245
|
+
const picked = more.length === 0 ? first?.label : `${model.picked.length} of ${total.toLocaleString()} selected`;
|
|
246
|
+
return /* @__PURE__ */ jsxs(Popover.Root, {
|
|
247
|
+
open,
|
|
248
|
+
onOpenChange: setOpen,
|
|
249
|
+
children: [/* @__PURE__ */ jsx(Popover.Trigger, {
|
|
250
|
+
disabled: disabled || !!missing,
|
|
251
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
252
|
+
variant: "surface",
|
|
253
|
+
color: "gray",
|
|
254
|
+
"aria-label": label ?? placeholder,
|
|
255
|
+
style: {
|
|
256
|
+
width: "100%",
|
|
257
|
+
justifyContent: "space-between",
|
|
258
|
+
fontWeight: "normal"
|
|
259
|
+
},
|
|
260
|
+
children: [/* @__PURE__ */ jsxs(Flex, {
|
|
261
|
+
gap: "2",
|
|
262
|
+
align: "center",
|
|
263
|
+
minWidth: "0",
|
|
264
|
+
children: [more.length === 0 && /* @__PURE__ */ jsx(Swatch, { color: first?.color }), /* @__PURE__ */ jsx(Text, {
|
|
265
|
+
truncate: true,
|
|
266
|
+
highContrast: !!picked && !missing,
|
|
267
|
+
children: missing ?? (picked || placeholder || "Choose…")
|
|
268
|
+
})]
|
|
269
|
+
}), loading ? /* @__PURE__ */ jsx(Spinner, { size: "1" }) : /* @__PURE__ */ jsx(ChevronsUpDownIcon, {
|
|
270
|
+
size: 14,
|
|
271
|
+
"aria-hidden": true,
|
|
272
|
+
style: { flex: "none" }
|
|
273
|
+
})]
|
|
274
|
+
})
|
|
275
|
+
}), /* @__PURE__ */ jsx(Popover.Content, {
|
|
276
|
+
size: "1",
|
|
277
|
+
align: "start",
|
|
278
|
+
style: {
|
|
279
|
+
width: "var(--radix-popover-trigger-width)",
|
|
280
|
+
minWidth: 260,
|
|
281
|
+
maxHeight: "var(--radix-popover-content-available-height)",
|
|
282
|
+
zIndex: 400
|
|
283
|
+
},
|
|
284
|
+
children: /* @__PURE__ */ jsx(ListSelect, {
|
|
285
|
+
...props,
|
|
286
|
+
autoFocus: true,
|
|
287
|
+
model: model.multiple ? model : {
|
|
288
|
+
...model,
|
|
289
|
+
set: (values) => {
|
|
290
|
+
model.set(values);
|
|
291
|
+
setOpen(false);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
})
|
|
295
|
+
})]
|
|
296
|
+
});
|
|
297
|
+
};
|
|
298
|
+
//#endregion
|
|
299
|
+
//#region src/components/Pickers/internal/usePickerModel.ts
|
|
300
|
+
const usePickerModel = (props) => {
|
|
301
|
+
const { options, sort = "count", idOf = defaultIdOf, labelOf } = props;
|
|
302
|
+
const sorted = useMemo(() => groupOptions(options).flatMap((group) => sortOptions(group.options, sort)), [options, sort]);
|
|
303
|
+
const byId = useMemo(() => new Map(sorted.map((option) => [idOf(option.value), option])), [sorted, idOf]);
|
|
304
|
+
const picked = pickedValues(props).map((value) => {
|
|
305
|
+
const id = idOf(value);
|
|
306
|
+
const option = byId.get(id);
|
|
307
|
+
const label = option?.label ?? labelOf?.(value) ?? id;
|
|
308
|
+
return {
|
|
309
|
+
id,
|
|
310
|
+
value,
|
|
311
|
+
label: option?.group ? `${label} (${option.group.label})` : label,
|
|
312
|
+
color: option?.color ?? option?.group?.color
|
|
313
|
+
};
|
|
314
|
+
});
|
|
315
|
+
const pickedIds = new Set(picked.map(({ id }) => id));
|
|
316
|
+
const set = (values) => report(props, values);
|
|
317
|
+
return {
|
|
318
|
+
options: sorted,
|
|
319
|
+
idOf,
|
|
320
|
+
multiple: props.multiple === true,
|
|
321
|
+
picked,
|
|
322
|
+
pickedIds,
|
|
323
|
+
set,
|
|
324
|
+
remove: (id) => set(picked.filter((entry) => entry.id !== id).map((p) => p.value))
|
|
325
|
+
};
|
|
326
|
+
};
|
|
327
|
+
//#endregion
|
|
328
|
+
//#region src/components/Pickers/OptionPicker.tsx
|
|
329
|
+
/**
|
|
330
|
+
* Picking values out of a list of options, as a dropdown or as a list.
|
|
331
|
+
*
|
|
332
|
+
* Presentational: handed the options, it reports what was picked. Every OCEL
|
|
333
|
+
* picker is this, wrapped around an endpoint; use it directly for choices
|
|
334
|
+
* that come from elsewhere.
|
|
335
|
+
*/
|
|
336
|
+
const OptionPicker = (props) => {
|
|
337
|
+
const model = usePickerModel(props);
|
|
338
|
+
return /* @__PURE__ */ jsx(Field, {
|
|
339
|
+
label: props.label,
|
|
340
|
+
description: props.description,
|
|
341
|
+
children: props.variant === "list" ? /* @__PURE__ */ jsx(ListSelect, {
|
|
342
|
+
...props,
|
|
343
|
+
model
|
|
344
|
+
}) : /* @__PURE__ */ jsx(DropdownSelect, {
|
|
345
|
+
...props,
|
|
346
|
+
model
|
|
347
|
+
})
|
|
348
|
+
});
|
|
349
|
+
};
|
|
350
|
+
//#endregion
|
|
351
|
+
export { OptionPicker };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import {
|
|
3
|
-
import { n as toSeries, t as paint } from "./series-
|
|
2
|
+
import { n as Plot, t as useChart } from "./useChart-jzzXgs0j.js";
|
|
3
|
+
import { n as toSeries, t as paint } from "./series-W1jsVape.js";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/charts/PieChart.tsx
|
|
6
6
|
var PieChart_exports = /* @__PURE__ */ __exportAll({ PieChart: () => PieChart });
|
|
7
7
|
/** Shares of a whole, one slice per category. */
|
|
8
|
-
const PieChart = ({ hole = .5, ...
|
|
8
|
+
const PieChart = ({ hole = .5, ...given }) => {
|
|
9
|
+
const props = useChart(given);
|
|
9
10
|
const [slices] = toSeries(props);
|
|
10
11
|
const colors = slices && paint(slices, props.colorOf, true);
|
|
11
12
|
const total = slices?.values.reduce((sum, value) => sum + (typeof value === "number" ? value : 0), 0);
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import {
|
|
3
|
-
import { n as traceCount, t as cartesian } from "./cartesian-
|
|
2
|
+
import { a as measureOf, n as Plot, r as axis, t as useChart } from "./useChart-jzzXgs0j.js";
|
|
3
|
+
import { n as traceCount, t as cartesian } from "./cartesian-Dt7weMqK.js";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/charts/ScatterChart.tsx
|
|
6
6
|
var ScatterChart_exports = /* @__PURE__ */ __exportAll({ ScatterChart: () => ScatterChart });
|
|
7
7
|
/** A point per row, for values that have no order to follow. */
|
|
8
|
-
const ScatterChart = ({ xRange, ...
|
|
8
|
+
const ScatterChart = ({ xRange, ...given }) => {
|
|
9
|
+
const props = useChart(given);
|
|
9
10
|
const measure = measureOf(props.y);
|
|
10
11
|
return /* @__PURE__ */ jsx(Plot, {
|
|
11
12
|
traces: cartesian(props, {
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { t as AreaChart } from "./AreaChart-
|
|
2
|
-
import { t as BarChart } from "./BarChart-
|
|
3
|
-
import { t as
|
|
4
|
-
import { t as
|
|
5
|
-
import { t as
|
|
6
|
-
import { t as
|
|
7
|
-
import {
|
|
1
|
+
import { t as AreaChart } from "./AreaChart-q6rVcUIp.js";
|
|
2
|
+
import { t as BarChart } from "./BarChart-BLZS87ex.js";
|
|
3
|
+
import { t as HistogramChart } from "./HistogramChart-GgiQdlsk.js";
|
|
4
|
+
import { t as LineChart } from "./LineChart-Cq935Tk2.js";
|
|
5
|
+
import { t as PieChart } from "./PieChart-DZFHaTXD.js";
|
|
6
|
+
import { t as ScatterChart } from "./ScatterChart-DJfJmABJ.js";
|
|
7
|
+
import { t as SunburstChart } from "./SunburstChart-CMNYlKon.js";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import {
|
|
9
|
+
import { Flex, SegmentedControl, Text } from "@r4pm/components/ui";
|
|
10
|
+
import { EmptyState, useViewSetting } from "@r4pm/components";
|
|
10
11
|
//#region src/components/charts/SqlChart.tsx
|
|
11
12
|
/**
|
|
12
13
|
* A query's result, drawn.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* ambient `ViewerConfig`,
|
|
15
|
+
* It reads the result's own column types to decide what goes across and what
|
|
16
|
+
* goes up, and hands the rows to one of the charts; colours and selection
|
|
17
|
+
* reach them from the ambient `ViewerConfig`, or from the props given here.
|
|
17
18
|
*/
|
|
18
|
-
const SqlChart = ({ data, type: initialType = "bar", types = [], x, y, series, path, stacked = false, horizontal = false, yAxes = "shared", colorScope, title, height = "100%",
|
|
19
|
-
const { colorOf, onSelect } = useViewerConfig(config);
|
|
19
|
+
const SqlChart = ({ data, type: initialType = "bar", types = [], x, xEnd, y, series, path, stacked = false, horizontal = false, yAxes = "shared", colorScope, title, height = "100%", colorOf, onSelect }) => {
|
|
20
20
|
const [type, setType] = useViewSetting(`chartType:${title ?? ""}`, initialType);
|
|
21
21
|
const { category, measures } = columns(data, {
|
|
22
22
|
x,
|
|
@@ -28,12 +28,9 @@ const SqlChart = ({ data, type: initialType = "bar", types = [], x, y, series, p
|
|
|
28
28
|
x: category,
|
|
29
29
|
y: measures,
|
|
30
30
|
series,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
key: name,
|
|
35
|
-
data: point
|
|
36
|
-
})
|
|
31
|
+
colorScope,
|
|
32
|
+
colorOf,
|
|
33
|
+
onSelect
|
|
37
34
|
};
|
|
38
35
|
return /* @__PURE__ */ jsxs("div", {
|
|
39
36
|
style: {
|
|
@@ -42,27 +39,27 @@ const SqlChart = ({ data, type: initialType = "bar", types = [], x, y, series, p
|
|
|
42
39
|
width: "100%",
|
|
43
40
|
height
|
|
44
41
|
},
|
|
45
|
-
children: [(title || types.length > 1) && /* @__PURE__ */ jsxs(
|
|
46
|
-
gap: "
|
|
47
|
-
mb: "
|
|
48
|
-
pr:
|
|
49
|
-
|
|
42
|
+
children: [(title || types.length > 1) && /* @__PURE__ */ jsxs(Flex, {
|
|
43
|
+
gap: "2",
|
|
44
|
+
mb: "2",
|
|
45
|
+
pr: "8",
|
|
46
|
+
align: "center",
|
|
50
47
|
wrap: "wrap",
|
|
51
48
|
children: [title && /* @__PURE__ */ jsx(Text, {
|
|
52
|
-
size: "
|
|
53
|
-
|
|
49
|
+
size: "2",
|
|
50
|
+
weight: "bold",
|
|
54
51
|
truncate: true,
|
|
55
52
|
children: title
|
|
56
|
-
}), types.length > 1 && /* @__PURE__ */ jsx(SegmentedControl, {
|
|
53
|
+
}), types.length > 1 && /* @__PURE__ */ jsx(SegmentedControl.Root, {
|
|
57
54
|
"data-export-ignore": true,
|
|
58
|
-
size: "
|
|
59
|
-
radius: "
|
|
55
|
+
size: "1",
|
|
56
|
+
radius: "full",
|
|
60
57
|
value: type,
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
onValueChange: (value) => setType(value),
|
|
59
|
+
children: types.map((option) => /* @__PURE__ */ jsx(SegmentedControl.Item, {
|
|
63
60
|
value: option,
|
|
64
|
-
|
|
65
|
-
}))
|
|
61
|
+
children: option[0]?.toUpperCase() + option.slice(1)
|
|
62
|
+
}, option))
|
|
66
63
|
})]
|
|
67
64
|
}), /* @__PURE__ */ jsx("div", {
|
|
68
65
|
style: {
|
|
@@ -76,6 +73,9 @@ const SqlChart = ({ data, type: initialType = "bar", types = [], x, y, series, p
|
|
|
76
73
|
...chart,
|
|
77
74
|
stacked,
|
|
78
75
|
horizontal
|
|
76
|
+
}) : type === "histogram" && xEnd ? /* @__PURE__ */ jsx(HistogramChart, {
|
|
77
|
+
...chart,
|
|
78
|
+
xEnd
|
|
79
79
|
}) : type === "line" ? /* @__PURE__ */ jsx(LineChart, {
|
|
80
80
|
...chart,
|
|
81
81
|
yAxes
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import {
|
|
2
|
+
import { a as measureOf, i as label, n as Plot, t as useChart } from "./useChart-jzzXgs0j.js";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
//#region src/components/charts/SunburstChart.tsx
|
|
5
5
|
var SunburstChart_exports = /* @__PURE__ */ __exportAll({ SunburstChart: () => SunburstChart });
|
|
6
6
|
/** A hierarchy as rings, each one a column of the path. */
|
|
7
|
-
const SunburstChart = ({ path, ...
|
|
7
|
+
const SunburstChart = ({ path, ...given }) => {
|
|
8
|
+
const props = useChart(given);
|
|
8
9
|
const rings = path ?? [props.x, props.series].filter(named);
|
|
9
10
|
return /* @__PURE__ */ jsx(Plot, {
|
|
10
11
|
traces: [nest(props.rows, rings, measureOf(props.y), props.colorOf)],
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//#region src/components/Pickers/internal/attributeOptions.ts
|
|
2
|
+
/**
|
|
3
|
+
* Attributes as options: one per name, with its value types as description
|
|
4
|
+
* and its distinct values as count.
|
|
5
|
+
*
|
|
6
|
+
* Without a type filter the endpoints return an attribute once per event or
|
|
7
|
+
* object type that carries it, so "status" on two object types is merged.
|
|
8
|
+
*/
|
|
9
|
+
const attributeOptions = (attributes, valueTypes, toValue, group) => {
|
|
10
|
+
const merged = /* @__PURE__ */ new Map();
|
|
11
|
+
for (const attribute of attributes ?? []) {
|
|
12
|
+
if (valueTypes && !valueTypes.includes(attribute.type)) continue;
|
|
13
|
+
const entry = merged.get(attribute.name) ?? {
|
|
14
|
+
types: /* @__PURE__ */ new Set(),
|
|
15
|
+
count: 0
|
|
16
|
+
};
|
|
17
|
+
entry.types.add(attribute.type);
|
|
18
|
+
entry.count = Math.max(entry.count, attribute.distinct_values);
|
|
19
|
+
merged.set(attribute.name, entry);
|
|
20
|
+
}
|
|
21
|
+
return [...merged].map(([name, { types, count }]) => ({
|
|
22
|
+
value: toValue(name),
|
|
23
|
+
label: name,
|
|
24
|
+
description: [...types].join(", "),
|
|
25
|
+
count,
|
|
26
|
+
group
|
|
27
|
+
}));
|
|
28
|
+
};
|
|
29
|
+
/** Distinct values say how varied an attribute is, not how often it occurs,
|
|
30
|
+
* so by default they neither sort the choices nor draw bars. */
|
|
31
|
+
const attributeDefaults = {
|
|
32
|
+
sort: "name",
|
|
33
|
+
bars: false,
|
|
34
|
+
counts: false
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
|
37
|
+
export { attributeOptions as n, attributeDefaults as t };
|