@ocelescope/core 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/ActivityPicker-CtFSu1YR.js +31 -0
- package/dist/{AreaChart-DoD3LM50.js → AreaChart-BSwN1fMp.js} +6 -6
- package/dist/AttributePicker-Cq7luTEi.js +94 -0
- package/dist/{BarChart-Cixo5Okd.js → BarChart-CyMePf1z.js} +6 -6
- package/dist/E2ORelationPicker-C8EmrbFx.js +45 -0
- package/dist/EventAttributePicker-BgEdydek.js +26 -0
- package/dist/EventPicker-D5uNOTw1.js +38 -0
- package/dist/HistogramChart-CJwvvDUu.js +86 -0
- package/dist/{LineChart-CVz-dkJI.js → LineChart-Cbxnm338.js} +6 -6
- package/dist/O2ORelationPicker-CryAxxUo.js +43 -0
- package/dist/ObjectAttributePicker-D_I3LQsY.js +26 -0
- package/dist/ObjectPicker-D-ksQveT.js +38 -0
- package/dist/ObjectTypePicker-Bw8Fsktx.js +45 -0
- package/dist/{OcelChart-DvGTjJXo.js → OcelChart-DJNM5peW.js} +3 -4
- package/dist/OptionPicker-DQ-WYFQZ.js +344 -0
- package/dist/{PieChart-DBiASngC.js → PieChart-BmMoI0TY.js} +6 -6
- package/dist/{ScatterChart-jIQOjQes.js → ScatterChart-CASPRlZU.js} +6 -6
- package/dist/{SqlChart-bwDArK2l.js → SqlChart-cxKpWkyh.js} +34 -35
- package/dist/{SunburstChart-D6FhYBHI.js → SunburstChart-Ddx9EaL-.js} +5 -5
- package/dist/attributeOptions-COiWnKUS.js +36 -0
- package/dist/{cartesian-5TPNWjl_.js → cartesian-CtdS2iZb.js} +2 -3
- package/dist/index.d.ts +228 -209
- package/dist/index.js +83 -172
- package/dist/relationOptions-hEEsEQrx.js +32 -0
- package/dist/{rolldown-runtime-D7D4PA-g.js → rolldown-runtime-D8jQpDG7.js} +1 -2
- package/dist/{series-BBXVjHHY.js → series-Bx0HVnSy.js} +2 -3
- package/dist/style.css +630 -745
- package/dist/{Plot-CxHHyXot.js → useChart-BK4pjGal.js} +29 -5
- package/dist/{useCurrentOCEL-BeBa7K0g.js → useCurrentOCEL-BUH5XGje.js} +2 -4
- package/dist/useOcelId-BEC6_yRa.js +8 -0
- package/dist/{useOcelQuery-D1QM-Zgv.js → useOcelQuery-6vtgZNzz.js} +2 -3
- package/dist/useSearch-CdXjjv-a.js +18 -0
- package/package.json +25 -26
- 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
- package/dist/useOcelId-BSU0-Srk.js +0 -6
|
@@ -0,0 +1,344 @@
|
|
|
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
|
+
// 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
|
+
// src/components/Pickers/internal/ListSelect.module.css
|
|
74
|
+
var ListSelect_module_default = {
|
|
75
|
+
"hideCount": "wENrqW_hideCount",
|
|
76
|
+
"single": "wENrqW_single"
|
|
77
|
+
};
|
|
78
|
+
// src/components/Pickers/internal/options.ts
|
|
79
|
+
const defaultIdOf = (value) => typeof value === "string" ? value : JSON.stringify(value);
|
|
80
|
+
/** The picked values, however the caller holds them. */
|
|
81
|
+
const pickedValues = (selection) => selection.multiple ? [...selection.value] : selection.value == null ? [] : [selection.value];
|
|
82
|
+
/** Report values back as the one value, or the list, the caller asked for. */
|
|
83
|
+
const report = (selection, values) => {
|
|
84
|
+
if (selection.multiple) selection.onChange(values);
|
|
85
|
+
else selection.onChange(values[0]);
|
|
86
|
+
};
|
|
87
|
+
/** Options in groups, in first-seen order. Ungrouped options form one group. */
|
|
88
|
+
const groupOptions = (options) => {
|
|
89
|
+
const groups = /* @__PURE__ */ new Map();
|
|
90
|
+
for (const option of options) {
|
|
91
|
+
const key = option.group?.label ?? "";
|
|
92
|
+
const entry = groups.get(key) ?? {
|
|
93
|
+
group: option.group,
|
|
94
|
+
options: []
|
|
95
|
+
};
|
|
96
|
+
entry.options.push(option);
|
|
97
|
+
groups.set(key, entry);
|
|
98
|
+
}
|
|
99
|
+
return [...groups.values()];
|
|
100
|
+
};
|
|
101
|
+
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));
|
|
102
|
+
// src/components/Pickers/internal/ListSelect.tsx
|
|
103
|
+
/** Lists at most this long get no search box of their own. */
|
|
104
|
+
const SEARCH_FROM = 8;
|
|
105
|
+
/** One r4pm list scrolls after eight rows; several groups of them share
|
|
106
|
+
* this height, so a grouped picker stays as compact. */
|
|
107
|
+
const GROUPS_HEIGHT = 320;
|
|
108
|
+
/**
|
|
109
|
+
* Every choice at once, one r4pm `FrequencyPicker` per group, so choices
|
|
110
|
+
* keep the colour and frequency bars they have in the viewers.
|
|
111
|
+
*/
|
|
112
|
+
const ListSelect = ({ model, counts = true, bars = true, cutoff = false, sort = "count", emptyText, disabled, autoFocus, loading, error, missing, search, onSearch, total }) => {
|
|
113
|
+
const groups = groupOptions(model.options);
|
|
114
|
+
const groupsRef = useRef(null);
|
|
115
|
+
const groupCount = groups.length;
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
if (groupCount < 2) return;
|
|
118
|
+
const frame = requestAnimationFrame(() => groupsRef.current?.scrollTo({ top: 0 }));
|
|
119
|
+
return () => cancelAnimationFrame(frame);
|
|
120
|
+
}, [groupCount]);
|
|
121
|
+
const shownIds = new Set(model.options.map((o) => model.idOf(o.value)));
|
|
122
|
+
const offList = model.picked.filter(({ id }) => !shownIds.has(id));
|
|
123
|
+
const content = () => {
|
|
124
|
+
if (missing) return /* @__PURE__ */ jsx(EmptyState, { title: missing });
|
|
125
|
+
if (error) return /* @__PURE__ */ jsx(ErrorState, {
|
|
126
|
+
error,
|
|
127
|
+
title: "Couldn't load"
|
|
128
|
+
});
|
|
129
|
+
if (loading && model.options.length === 0) return /* @__PURE__ */ jsx(SkeletonList, { rows: 4 });
|
|
130
|
+
if (model.options.length === 0) return /* @__PURE__ */ jsx(EmptyState, { title: emptyText ?? "Nothing to choose from" });
|
|
131
|
+
const lists = groups.map(({ group, options }) => {
|
|
132
|
+
const byLabel = new Map(options.map((option) => [option.label, option]));
|
|
133
|
+
const groupIds = new Set(options.map((o) => model.idOf(o.value)));
|
|
134
|
+
const pickedLabels = options.filter((option) => model.pickedIds.has(model.idOf(option.value))).map((option) => option.label);
|
|
135
|
+
return /* @__PURE__ */ jsxs(Flex, {
|
|
136
|
+
direction: "column",
|
|
137
|
+
gap: "1",
|
|
138
|
+
children: [group && /* @__PURE__ */ jsxs(Flex, {
|
|
139
|
+
gap: "2",
|
|
140
|
+
align: "center",
|
|
141
|
+
children: [/* @__PURE__ */ jsx(Badge, {
|
|
142
|
+
size: "1",
|
|
143
|
+
style: group.color ? softBadgeStyle(group.color) : void 0,
|
|
144
|
+
children: group.label
|
|
145
|
+
}), group.caption && /* @__PURE__ */ jsx(Text, {
|
|
146
|
+
size: "1",
|
|
147
|
+
color: "gray",
|
|
148
|
+
children: group.caption
|
|
149
|
+
})]
|
|
150
|
+
}), /* @__PURE__ */ jsx(FrequencyPicker, {
|
|
151
|
+
items: options.map((option) => ({
|
|
152
|
+
key: option.label,
|
|
153
|
+
count: option.count ?? 0
|
|
154
|
+
})),
|
|
155
|
+
value: new Set(pickedLabels),
|
|
156
|
+
onChange: (next) => {
|
|
157
|
+
if (disabled) return;
|
|
158
|
+
const values = [...next].flatMap((label) => {
|
|
159
|
+
const option = byLabel.get(label);
|
|
160
|
+
return option ? [option.value] : [];
|
|
161
|
+
});
|
|
162
|
+
if (!model.multiple) {
|
|
163
|
+
const fresh = values.find((value) => !model.pickedIds.has(model.idOf(value)));
|
|
164
|
+
return model.set(fresh !== void 0 ? [fresh] : values);
|
|
165
|
+
}
|
|
166
|
+
model.set([...model.picked.filter(({ id }) => !groupIds.has(id)).map(({ value }) => value), ...values]);
|
|
167
|
+
},
|
|
168
|
+
mode: model.multiple ? "multi" : "single",
|
|
169
|
+
searchable: !onSearch && options.length > SEARCH_FROM,
|
|
170
|
+
showBars: bars,
|
|
171
|
+
showCounts: counts,
|
|
172
|
+
showCutoff: cutoff,
|
|
173
|
+
sort,
|
|
174
|
+
colorOf: (_, key) => byLabel.get(key)?.color,
|
|
175
|
+
autoFocus,
|
|
176
|
+
emptyText: "Nothing matches"
|
|
177
|
+
})]
|
|
178
|
+
}, group?.label ?? "");
|
|
179
|
+
});
|
|
180
|
+
return groups.length > 1 ? /* @__PURE__ */ jsx(Flex, {
|
|
181
|
+
direction: "column",
|
|
182
|
+
gap: "3",
|
|
183
|
+
ref: groupsRef,
|
|
184
|
+
style: {
|
|
185
|
+
maxHeight: GROUPS_HEIGHT,
|
|
186
|
+
overflowY: "auto",
|
|
187
|
+
overflowX: "hidden"
|
|
188
|
+
},
|
|
189
|
+
children: lists
|
|
190
|
+
}) : lists;
|
|
191
|
+
};
|
|
192
|
+
return /* @__PURE__ */ jsxs(Flex, {
|
|
193
|
+
direction: "column",
|
|
194
|
+
gap: "2",
|
|
195
|
+
className: [!model.multiple || total !== void 0 ? ListSelect_module_default.hideCount : "", model.multiple ? "" : ListSelect_module_default.single].join(" "),
|
|
196
|
+
children: [
|
|
197
|
+
onSearch && /* @__PURE__ */ jsxs(TextField.Root, {
|
|
198
|
+
size: "2",
|
|
199
|
+
value: search ?? "",
|
|
200
|
+
placeholder: "Search…",
|
|
201
|
+
autoFocus,
|
|
202
|
+
disabled: disabled || !!missing,
|
|
203
|
+
onChange: (event) => onSearch(event.currentTarget.value),
|
|
204
|
+
children: [/* @__PURE__ */ jsx(TextField.Slot, { children: /* @__PURE__ */ jsx(SearchIcon, {
|
|
205
|
+
size: 14,
|
|
206
|
+
"aria-hidden": true
|
|
207
|
+
}) }), loading && /* @__PURE__ */ jsx(TextField.Slot, {
|
|
208
|
+
side: "right",
|
|
209
|
+
children: /* @__PURE__ */ jsx(Spinner, { size: "1" })
|
|
210
|
+
})]
|
|
211
|
+
}),
|
|
212
|
+
model.multiple && total !== void 0 && /* @__PURE__ */ jsxs(Text, {
|
|
213
|
+
size: "1",
|
|
214
|
+
color: "gray",
|
|
215
|
+
children: [
|
|
216
|
+
model.picked.length,
|
|
217
|
+
" of ",
|
|
218
|
+
total.toLocaleString(),
|
|
219
|
+
" selected"
|
|
220
|
+
]
|
|
221
|
+
}),
|
|
222
|
+
/* @__PURE__ */ jsx(PickedBadges, {
|
|
223
|
+
picked: offList,
|
|
224
|
+
onRemove: model.remove,
|
|
225
|
+
disabled
|
|
226
|
+
}),
|
|
227
|
+
content()
|
|
228
|
+
]
|
|
229
|
+
});
|
|
230
|
+
};
|
|
231
|
+
// src/components/Pickers/internal/DropdownSelect.tsx
|
|
232
|
+
/**
|
|
233
|
+
* A field that names what is picked and opens the list in a popover, so both
|
|
234
|
+
* variants are the same list.
|
|
235
|
+
*/
|
|
236
|
+
const DropdownSelect = (props) => {
|
|
237
|
+
const { model, label, placeholder, disabled, missing, loading } = props;
|
|
238
|
+
const [open, setOpen] = useState(props.autoFocus ?? false);
|
|
239
|
+
const [first, ...more] = model.picked;
|
|
240
|
+
const total = props.total ?? model.options.length;
|
|
241
|
+
const picked = more.length === 0 ? first?.label : `${model.picked.length} of ${total.toLocaleString()} selected`;
|
|
242
|
+
return /* @__PURE__ */ jsxs(Popover.Root, {
|
|
243
|
+
open,
|
|
244
|
+
onOpenChange: setOpen,
|
|
245
|
+
children: [/* @__PURE__ */ jsx(Popover.Trigger, {
|
|
246
|
+
disabled: disabled || !!missing,
|
|
247
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
248
|
+
variant: "surface",
|
|
249
|
+
color: "gray",
|
|
250
|
+
"aria-label": label ?? placeholder,
|
|
251
|
+
style: {
|
|
252
|
+
width: "100%",
|
|
253
|
+
justifyContent: "space-between",
|
|
254
|
+
fontWeight: "normal"
|
|
255
|
+
},
|
|
256
|
+
children: [/* @__PURE__ */ jsxs(Flex, {
|
|
257
|
+
gap: "2",
|
|
258
|
+
align: "center",
|
|
259
|
+
minWidth: "0",
|
|
260
|
+
children: [more.length === 0 && /* @__PURE__ */ jsx(Swatch, { color: first?.color }), /* @__PURE__ */ jsx(Text, {
|
|
261
|
+
truncate: true,
|
|
262
|
+
highContrast: !!picked && !missing,
|
|
263
|
+
children: missing ?? (picked || placeholder || "Choose…")
|
|
264
|
+
})]
|
|
265
|
+
}), loading ? /* @__PURE__ */ jsx(Spinner, { size: "1" }) : /* @__PURE__ */ jsx(ChevronsUpDownIcon, {
|
|
266
|
+
size: 14,
|
|
267
|
+
"aria-hidden": true,
|
|
268
|
+
style: { flex: "none" }
|
|
269
|
+
})]
|
|
270
|
+
})
|
|
271
|
+
}), /* @__PURE__ */ jsx(Popover.Content, {
|
|
272
|
+
size: "1",
|
|
273
|
+
align: "start",
|
|
274
|
+
style: {
|
|
275
|
+
width: "var(--radix-popover-trigger-width)",
|
|
276
|
+
minWidth: 260,
|
|
277
|
+
maxHeight: "var(--radix-popover-content-available-height)",
|
|
278
|
+
zIndex: 400
|
|
279
|
+
},
|
|
280
|
+
children: /* @__PURE__ */ jsx(ListSelect, {
|
|
281
|
+
...props,
|
|
282
|
+
autoFocus: true,
|
|
283
|
+
model: model.multiple ? model : {
|
|
284
|
+
...model,
|
|
285
|
+
set: (values) => {
|
|
286
|
+
model.set(values);
|
|
287
|
+
setOpen(false);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
})
|
|
291
|
+
})]
|
|
292
|
+
});
|
|
293
|
+
};
|
|
294
|
+
// src/components/Pickers/internal/usePickerModel.ts
|
|
295
|
+
const usePickerModel = (props) => {
|
|
296
|
+
const { options, sort = "count", idOf = defaultIdOf, labelOf } = props;
|
|
297
|
+
const sorted = useMemo(() => groupOptions(options).flatMap((group) => sortOptions(group.options, sort)), [options, sort]);
|
|
298
|
+
const byId = useMemo(() => new Map(sorted.map((option) => [idOf(option.value), option])), [sorted, idOf]);
|
|
299
|
+
const picked = pickedValues(props).map((value) => {
|
|
300
|
+
const id = idOf(value);
|
|
301
|
+
const option = byId.get(id);
|
|
302
|
+
const label = option?.label ?? labelOf?.(value) ?? id;
|
|
303
|
+
return {
|
|
304
|
+
id,
|
|
305
|
+
value,
|
|
306
|
+
label: option?.group ? `${label} (${option.group.label})` : label,
|
|
307
|
+
color: option?.color ?? option?.group?.color
|
|
308
|
+
};
|
|
309
|
+
});
|
|
310
|
+
const pickedIds = new Set(picked.map(({ id }) => id));
|
|
311
|
+
const set = (values) => report(props, values);
|
|
312
|
+
return {
|
|
313
|
+
options: sorted,
|
|
314
|
+
idOf,
|
|
315
|
+
multiple: props.multiple === true,
|
|
316
|
+
picked,
|
|
317
|
+
pickedIds,
|
|
318
|
+
set,
|
|
319
|
+
remove: (id) => set(picked.filter((entry) => entry.id !== id).map((p) => p.value))
|
|
320
|
+
};
|
|
321
|
+
};
|
|
322
|
+
// src/components/Pickers/OptionPicker.tsx
|
|
323
|
+
/**
|
|
324
|
+
* Picking values out of a list of options, as a dropdown or as a list.
|
|
325
|
+
*
|
|
326
|
+
* Presentational: handed the options, it reports what was picked. Every OCEL
|
|
327
|
+
* picker is this, wrapped around an endpoint; use it directly for choices
|
|
328
|
+
* that come from elsewhere.
|
|
329
|
+
*/
|
|
330
|
+
const OptionPicker = (props) => {
|
|
331
|
+
const model = usePickerModel(props);
|
|
332
|
+
return /* @__PURE__ */ jsx(Field, {
|
|
333
|
+
label: props.label,
|
|
334
|
+
description: props.description,
|
|
335
|
+
children: props.variant === "list" ? /* @__PURE__ */ jsx(ListSelect, {
|
|
336
|
+
...props,
|
|
337
|
+
model
|
|
338
|
+
}) : /* @__PURE__ */ jsx(DropdownSelect, {
|
|
339
|
+
...props,
|
|
340
|
+
model
|
|
341
|
+
})
|
|
342
|
+
});
|
|
343
|
+
};
|
|
344
|
+
export { OptionPicker };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
2
|
-
import {
|
|
3
|
-
import { n as toSeries, t as paint } from "./series-
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D8jQpDG7.js";
|
|
2
|
+
import { n as Plot, t as useChart } from "./useChart-BK4pjGal.js";
|
|
3
|
+
import { n as toSeries, t as paint } from "./series-Bx0HVnSy.js";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
|
-
|
|
5
|
+
// 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);
|
|
@@ -58,5 +59,4 @@ const PieChart = ({ hole = .5, ...props }) => {
|
|
|
58
59
|
}
|
|
59
60
|
});
|
|
60
61
|
};
|
|
61
|
-
//#endregion
|
|
62
62
|
export { PieChart_exports as n, PieChart as t };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
2
|
-
import {
|
|
3
|
-
import { n as traceCount, t as cartesian } from "./cartesian-
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D8jQpDG7.js";
|
|
2
|
+
import { a as measureOf, n as Plot, r as axis, t as useChart } from "./useChart-BK4pjGal.js";
|
|
3
|
+
import { n as traceCount, t as cartesian } from "./cartesian-CtdS2iZb.js";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
|
-
|
|
5
|
+
// 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, {
|
|
@@ -32,5 +33,4 @@ const ScatterChart = ({ xRange, ...props }) => {
|
|
|
32
33
|
}
|
|
33
34
|
});
|
|
34
35
|
};
|
|
35
|
-
//#endregion
|
|
36
36
|
export { ScatterChart_exports as n, ScatterChart as t };
|
|
@@ -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-BSwN1fMp.js";
|
|
2
|
+
import { t as BarChart } from "./BarChart-CyMePf1z.js";
|
|
3
|
+
import { t as HistogramChart } from "./HistogramChart-CJwvvDUu.js";
|
|
4
|
+
import { t as LineChart } from "./LineChart-Cbxnm338.js";
|
|
5
|
+
import { t as PieChart } from "./PieChart-BmMoI0TY.js";
|
|
6
|
+
import { t as ScatterChart } from "./ScatterChart-CASPRlZU.js";
|
|
7
|
+
import { t as SunburstChart } from "./SunburstChart-Ddx9EaL-.js";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import {
|
|
10
|
-
|
|
9
|
+
import { Flex, SegmentedControl, Text } from "@r4pm/components/ui";
|
|
10
|
+
import { EmptyState, useViewSetting } from "@r4pm/components";
|
|
11
|
+
// 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
|
|
@@ -97,5 +97,4 @@ const columns = (result, { x, y, series }) => {
|
|
|
97
97
|
measures: (named.length > 0 ? named : result.columns.map((column) => column.name).filter((name) => numeric(name) && name !== category)).filter((name) => name !== series)
|
|
98
98
|
};
|
|
99
99
|
};
|
|
100
|
-
//#endregion
|
|
101
100
|
export { SqlChart };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
2
|
-
import {
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D8jQpDG7.js";
|
|
2
|
+
import { a as measureOf, i as label, n as Plot, t as useChart } from "./useChart-BK4pjGal.js";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
|
-
|
|
4
|
+
// 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)],
|
|
@@ -69,5 +70,4 @@ const nest = (rows, path, measure, colorOf) => {
|
|
|
69
70
|
};
|
|
70
71
|
};
|
|
71
72
|
const named = (column) => Boolean(column);
|
|
72
|
-
//#endregion
|
|
73
73
|
export { SunburstChart_exports as n, SunburstChart as t };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// 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
|
+
export { attributeOptions as n, attributeDefaults as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as toSeries, t as paint } from "./series-
|
|
2
|
-
|
|
1
|
+
import { n as toSeries, t as paint } from "./series-Bx0HVnSy.js";
|
|
2
|
+
// src/components/charts/internal/cartesian.ts
|
|
3
3
|
/**
|
|
4
4
|
* Traces for the charts drawn against two axes.
|
|
5
5
|
*
|
|
@@ -37,5 +37,4 @@ const cartesian = ({ rows, x, y, series, colorOf }, mark, horizontal = false, co
|
|
|
37
37
|
};
|
|
38
38
|
/** How many traces a chart will draw, which decides whether it needs a legend. */
|
|
39
39
|
const traceCount = (props) => toSeries(props).length;
|
|
40
|
-
//#endregion
|
|
41
40
|
export { traceCount as n, cartesian as t };
|