@chelone/vue 0.5.0 → 0.6.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.
Files changed (37) hide show
  1. package/README.md +1 -0
  2. package/dist/components/admin/fields/api-key-field.vue.d.ts +1 -1
  3. package/dist/components/admin/fields/api-key-field.vue.js +2 -12
  4. package/dist/components/index.d.ts +0 -2
  5. package/dist/components/kanban/kanban-board.vue.js +260 -0
  6. package/dist/components/kanban/kanban-draggable-card.vue.d.ts +18 -0
  7. package/dist/components/kanban/kanban-draggable-card.vue.js +32 -0
  8. package/dist/components/kanban/kanban-draggable-card2.vue.js +4 -0
  9. package/dist/components/kanban/kanban-drop-area.vue.d.ts +15 -0
  10. package/dist/components/kanban/kanban-drop-area.vue.js +29 -0
  11. package/dist/components/kanban/kanban-drop-area2.vue.js +4 -0
  12. package/dist/components/ui/chart/chart-container.vue.d.ts +18 -0
  13. package/dist/components/ui/chart/chart-container.vue.js +40 -0
  14. package/dist/components/ui/chart/chart-container2.vue.js +4 -0
  15. package/dist/components/ui/chart/chart-legend-content.vue.d.ts +9 -0
  16. package/dist/components/ui/chart/chart-legend-content.vue.js +56 -0
  17. package/dist/components/ui/chart/chart-legend-content2.vue.js +4 -0
  18. package/dist/components/ui/chart/chart-style.vue.d.ts +7 -0
  19. package/dist/components/ui/chart/chart-style.vue.js +43 -0
  20. package/dist/components/ui/chart/chart-style2.vue.js +4 -0
  21. package/dist/components/ui/chart/chart-tooltip-content.vue.d.ts +7 -0
  22. package/dist/components/ui/chart/chart-tooltip-content.vue.js +122 -0
  23. package/dist/components/ui/chart/chart-tooltip-content2.vue.js +4 -0
  24. package/dist/components/ui/chart/index.d.ts +11 -0
  25. package/dist/components/ui/chart/utils.d.ts +81 -0
  26. package/dist/components/ui/chart/utils.js +52 -0
  27. package/dist/components/ui/index.d.ts +1 -0
  28. package/dist/data/create-chelone-hooks.d.ts +2 -1
  29. package/dist/data/queries.d.ts +6 -3
  30. package/dist/data/queries.js +8 -4
  31. package/dist/index.js +398 -387
  32. package/dist/kanban.d.ts +1 -0
  33. package/dist/kanban.js +4 -0
  34. package/package.json +18 -4
  35. package/dist/components/admin/list/kanban-board.vue.js +0 -275
  36. /package/dist/components/{admin/list → kanban}/kanban-board.vue.d.ts +0 -0
  37. /package/dist/components/{admin/list → kanban}/kanban-board2.vue.js +0 -0
package/README.md CHANGED
@@ -13,6 +13,7 @@ Each entry below needs the peer dependencies listed beside it, and only that ent
13
13
  | Entry | Optional peers |
14
14
  | --- | --- |
15
15
  | `@chelone/vue/monaco` | `monaco-editor`, `@guolao/vue-monaco-editor` |
16
+ | `@chelone/vue/kanban` | `@dnd-kit/vue`, `@dnd-kit/dom` (needs Vue 3.5) |
16
17
  | `@chelone/vue/mdx-editor` | `@milkdown/crepe`, `@milkdown/kit` |
17
18
  | `@chelone/vue/csv-import` | `papaparse` |
18
19
  | `@chelone/vue/maps` | `maplibre-gl` |
@@ -1,4 +1,4 @@
1
- import type { LooseRecord, SourceKey, SourceProp } from "@chelone/core";
1
+ import { type LooseRecord, type SourceKey, type SourceProp } from "@chelone/core";
2
2
  /** Props for {@link ApiKeyField}. */
3
3
  export interface ApiKeyFieldProps<RecordType extends LooseRecord = LooseRecord> {
4
4
  source: SourceProp;
@@ -3,6 +3,7 @@ import { cn } from "../../../lib/utils.js";
3
3
  import _sfc_main$1 from "../../ui/button.vue.js";
4
4
  import { RecordContextKey } from "../../../record/record-context.js";
5
5
  import { useFieldValue } from "../../../record/use-field-value.js";
6
+ import { formatRelativeTime } from "@chelone/core";
6
7
  const _hoisted_1 = { class: "inline-flex items-center gap-2" };
7
8
  const _hoisted_2 = {
8
9
  "data-api-key": "",
@@ -82,17 +83,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
82
83
  if (!props.lastUsedSource || !rec) return void 0;
83
84
  return rec[props.lastUsedSource];
84
85
  });
85
- function formatRelative(iso) {
86
- if (!iso) return "Never";
87
- const delta = (new Date(iso).getTime() - Date.now()) / 1e3;
88
- const rtf = new Intl.RelativeTimeFormat(void 0, { numeric: "auto" });
89
- const abs = Math.abs(delta);
90
- if (abs < 60) return rtf.format(Math.round(delta), "second");
91
- if (abs < 3600) return rtf.format(Math.round(delta / 60), "minute");
92
- if (abs < 86400) return rtf.format(Math.round(delta / 3600), "hour");
93
- if (abs < 86400 * 30) return rtf.format(Math.round(delta / 86400), "day");
94
- return rtf.format(Math.round(delta / (86400 * 30)), "month");
95
- }
96
86
  async function handleCopy() {
97
87
  try {
98
88
  await navigator.clipboard.writeText(key.value ?? "");
@@ -182,7 +172,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
182
172
  }, toDisplayString(s), 1);
183
173
  }), 128))
184
174
  ])) : createCommentVNode("", true),
185
- __props.lastUsedSource ? (openBlock(), createElementBlock("span", _hoisted_7, "Last used: " + toDisplayString(formatRelative(lastUsed.value)), 1)) : createCommentVNode("", true)
175
+ __props.lastUsedSource ? (openBlock(), createElementBlock("span", _hoisted_7, "Last used: " + toDisplayString(lastUsed.value ? unref(formatRelativeTime)(new Date(lastUsed.value), /* @__PURE__ */ new Date()) : "Never"), 1)) : createCommentVNode("", true)
186
176
  ], 2)) : createCommentVNode("", true);
187
177
  };
188
178
  }
@@ -326,8 +326,6 @@ export type { FilterLiveSearchProps } from "./admin/list/filter-live-search.vue.
326
326
  export { default as FilterLiveSearch } from "./admin/list/filter-live-search.vue.js";
327
327
  export type { InfinitePaginationProps } from "./admin/list/infinite-pagination.vue.js";
328
328
  export { default as InfinitePagination } from "./admin/list/infinite-pagination.vue.js";
329
- export type { KanbanBoardProps } from "./admin/list/kanban-board.vue.js";
330
- export { default as KanbanBoard } from "./admin/list/kanban-board.vue.js";
331
329
  export type { ListActionsProps } from "./admin/list/list-actions.vue.js";
332
330
  export { default as ListActions } from "./admin/list/list-actions.vue.js";
333
331
  export type { ListNoResultsProps } from "./admin/list/list-no-results.vue.js";
@@ -0,0 +1,260 @@
1
+ import { defineComponent, computed, getCurrentInstance, openBlock, createBlock, unref, withCtx, createElementVNode, mergeProps, createElementBlock, Fragment, renderList, normalizeClass, toDisplayString, createVNode, createCommentVNode, renderSlot, withModifiers, createTextVNode } from "vue";
2
+ import { buildKanbanBuckets, planKanbanMove, getAtPath } from "@chelone/core";
3
+ import { PointerSensor } from "@dnd-kit/dom";
4
+ import { DragDropProvider } from "@dnd-kit/vue";
5
+ import { useResourceDefinition } from "../../admin/resource-registry.js";
6
+ import { useCheloneNotifications } from "../../context.js";
7
+ import { useUpdate } from "../../data/mutations.js";
8
+ import { useTranslate } from "../../i18n/use-translate.js";
9
+ import { useGetRecordRepresentation } from "../../label/use-get-record-representation.js";
10
+ import { cn } from "../../lib/utils.js";
11
+ import { useListContext } from "../../list/list-context.js";
12
+ import { useResourceContext } from "../../resource-context.js";
13
+ import _sfc_main$5 from "../ui/button.vue.js";
14
+ import { useMenuAccess } from "../admin/layout/use-menu-access.js";
15
+ import { ArrowRightLeftIcon } from "../admin/list/list-icons.js";
16
+ import _sfc_main$2 from "./kanban-draggable-card.vue.js";
17
+ import _sfc_main$1 from "./kanban-drop-area.vue.js";
18
+ import { useNavigate, useCreatePath } from "../../router/nav-composables.js";
19
+ import _sfc_main$3 from "../ui/dropdown-menu/dropdown-menu.vue.js";
20
+ import _sfc_main$4 from "../ui/dropdown-menu/dropdown-menu-trigger.vue.js";
21
+ import _sfc_main$6 from "../ui/dropdown-menu/dropdown-menu-content.vue.js";
22
+ import _sfc_main$7 from "../ui/dropdown-menu/dropdown-menu-item.vue.js";
23
+ const _hoisted_1 = ["aria-label", "data-column-id"];
24
+ const _hoisted_2 = { class: "flex items-center justify-between px-1 text-sm font-medium" };
25
+ const _hoisted_3 = {
26
+ "data-slot": "kanban-column-count",
27
+ class: "text-muted-foreground"
28
+ };
29
+ const _hoisted_4 = {
30
+ key: 0,
31
+ "data-slot": "kanban-empty",
32
+ class: "px-1 py-2 text-sm text-muted-foreground"
33
+ };
34
+ const _hoisted_5 = { class: "flex min-w-0 flex-1 flex-col gap-1" };
35
+ const _hoisted_6 = {
36
+ "data-slot": "kanban-card-title",
37
+ class: "font-medium"
38
+ };
39
+ const _hoisted_7 = {
40
+ key: 0,
41
+ "data-slot": "kanban-card-description",
42
+ class: "text-muted-foreground"
43
+ };
44
+ const _sfc_main = /* @__PURE__ */ defineComponent({
45
+ ...{ inheritAttrs: false },
46
+ __name: "kanban-board",
47
+ props: {
48
+ groupSource: {},
49
+ columns: {},
50
+ titleSource: { default: void 0 },
51
+ descriptionSource: { default: void 0 },
52
+ linkType: { type: [String, Boolean], default: void 0 },
53
+ class: {}
54
+ },
55
+ emits: ["select-card"],
56
+ setup(__props, { emit: __emit }) {
57
+ const sensors = [PointerSensor];
58
+ const props = __props;
59
+ const emit = __emit;
60
+ const list = useListContext();
61
+ const resource = useResourceContext();
62
+ const translate = useTranslate();
63
+ const getRepresentation = useGetRecordRepresentation(resource);
64
+ const navigate = useNavigate();
65
+ const createPath = useCreatePath();
66
+ const definition = useResourceDefinition(() => ({ resource }));
67
+ const notifications = useCheloneNotifications();
68
+ const { canAccess, isPending: isAccessPending } = useMenuAccess(
69
+ computed(() => ({
70
+ action: "edit",
71
+ resource: resource ?? ""
72
+ }))
73
+ );
74
+ const update = useUpdate(resource ?? "", { mutationMode: "optimistic" });
75
+ const draggable = computed(
76
+ () => !!resource && canAccess.value && !isAccessPending.value
77
+ );
78
+ const instance = getCurrentInstance();
79
+ const hasListener = () => {
80
+ const listeners = instance?.vnode.props;
81
+ return !!(listeners?.onSelectCard || listeners?.onSelectCardOnce);
82
+ };
83
+ const buckets = computed(
84
+ () => buildKanbanBuckets(list.data ?? [], props.groupSource, props.columns)
85
+ );
86
+ function move(record, targetColumnId) {
87
+ const plan = planKanbanMove(
88
+ record,
89
+ props.groupSource,
90
+ props.columns,
91
+ targetColumnId
92
+ );
93
+ if (!plan) return;
94
+ update.mutateAsync(plan).catch(() => {
95
+ notifications?.notify("chelone.notification.http_error", {
96
+ type: "error"
97
+ });
98
+ });
99
+ }
100
+ const type = computed(
101
+ () => props.linkType ?? (definition.value.hasEdit ? "edit" : definition.value.hasShow ? "show" : false)
102
+ );
103
+ const linkTo = (record) => resource && type.value ? createPath({ resource, id: record.id, type: type.value }) : void 0;
104
+ const selectable = computed(
105
+ () => hasListener() || !!resource && type.value !== false
106
+ );
107
+ function select(record) {
108
+ if (!selectable.value) return;
109
+ if (hasListener()) return emit("select-card", record);
110
+ const to = linkTo(record);
111
+ if (to) navigate(to);
112
+ }
113
+ function onCardKeydown(event, record) {
114
+ if (event.target !== event.currentTarget) return;
115
+ if (event.key !== "Enter" && event.key !== " ") return;
116
+ event.preventDefault();
117
+ select(record);
118
+ }
119
+ function onDragEnd(event) {
120
+ const { source, target } = event.operation;
121
+ if (event.canceled || !source || !target || !draggable.value) return;
122
+ const record = buckets.value.flatMap((bucket) => bucket.records).find((candidate) => String(candidate.id) === String(source.id));
123
+ if (record) move(record, String(target.id));
124
+ }
125
+ const isEmpty = (value) => value == null || value === "";
126
+ const textOf = (record, source) => source ? getAtPath(record, source) : void 0;
127
+ const titleOf = (record) => {
128
+ const value = textOf(record, props.titleSource);
129
+ return value == null ? getRepresentation(record) : String(value);
130
+ };
131
+ const othersOf = (columnId) => props.columns.filter((other) => other.id !== columnId);
132
+ const moveLabel = (record) => translate("chelone.kanban_board.move", {
133
+ title: titleOf(record),
134
+ _: "Move {title}"
135
+ });
136
+ const emptyLabel = computed(
137
+ () => translate("chelone.kanban_board.empty", { _: "No items" })
138
+ );
139
+ return (_ctx, _cache) => {
140
+ return openBlock(), createBlock(unref(DragDropProvider), {
141
+ sensors,
142
+ onDragEnd
143
+ }, {
144
+ default: withCtx(() => [
145
+ createElementVNode("div", mergeProps(_ctx.$attrs, {
146
+ "data-slot": "kanban-board",
147
+ class: unref(cn)("flex items-start gap-4 overflow-x-auto pb-2", props.class)
148
+ }), [
149
+ (openBlock(true), createElementBlock(Fragment, null, renderList(buckets.value, ({ column, records }) => {
150
+ return openBlock(), createElementBlock("div", {
151
+ key: column.id,
152
+ role: "group",
153
+ "aria-label": column.label,
154
+ "data-slot": "kanban-column",
155
+ "data-column-id": column.id,
156
+ class: normalizeClass(
157
+ unref(cn)(
158
+ "flex w-72 shrink-0 flex-col gap-2 rounded-lg bg-muted/50 p-2",
159
+ column.className
160
+ )
161
+ )
162
+ }, [
163
+ createElementVNode("div", _hoisted_2, [
164
+ createElementVNode("span", null, toDisplayString(column.label), 1),
165
+ createElementVNode("span", _hoisted_3, toDisplayString(records.length), 1)
166
+ ]),
167
+ createVNode(_sfc_main$1, {
168
+ "column-id": column.id,
169
+ "data-slot": "kanban-column-cards",
170
+ class: "flex min-h-16 flex-col gap-2 rounded-md data-[over]:bg-accent"
171
+ }, {
172
+ default: withCtx(() => [
173
+ records.length === 0 ? (openBlock(), createElementBlock("p", _hoisted_4, toDisplayString(emptyLabel.value), 1)) : createCommentVNode("", true),
174
+ (openBlock(true), createElementBlock(Fragment, null, renderList(records, (record) => {
175
+ return openBlock(), createBlock(_sfc_main$2, {
176
+ key: record.id,
177
+ id: String(record.id),
178
+ draggable: draggable.value,
179
+ role: "button",
180
+ tabindex: "0",
181
+ "data-slot": "kanban-card",
182
+ "data-record-id": String(record.id),
183
+ class: "flex cursor-pointer items-start gap-2 rounded-md border bg-card p-3 text-sm shadow-xs data-[dragging]:opacity-50",
184
+ onClick: ($event) => select(record),
185
+ onKeydown: ($event) => onCardKeydown($event, record)
186
+ }, {
187
+ default: withCtx(() => [
188
+ createElementVNode("div", _hoisted_5, [
189
+ _ctx.$slots.card ? renderSlot(_ctx.$slots, "card", {
190
+ key: 0,
191
+ record
192
+ }) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
193
+ createElementVNode("span", _hoisted_6, toDisplayString(titleOf(record)), 1),
194
+ !isEmpty(textOf(record, props.descriptionSource)) ? (openBlock(), createElementBlock("span", _hoisted_7, toDisplayString(String(textOf(record, props.descriptionSource))), 1)) : createCommentVNode("", true)
195
+ ], 64))
196
+ ]),
197
+ draggable.value ? (openBlock(), createElementBlock("div", {
198
+ key: 0,
199
+ onClick: _cache[0] || (_cache[0] = withModifiers(() => {
200
+ }, ["stop"]))
201
+ }, [
202
+ createVNode(unref(_sfc_main$3), null, {
203
+ default: withCtx(() => [
204
+ createVNode(unref(_sfc_main$4), null, {
205
+ default: withCtx(() => [
206
+ createVNode(_sfc_main$5, {
207
+ type: "button",
208
+ variant: "ghost",
209
+ size: "icon",
210
+ "data-slot": "kanban-card-move",
211
+ class: "size-6",
212
+ "aria-label": moveLabel(record)
213
+ }, {
214
+ default: withCtx(() => [
215
+ createVNode(unref(ArrowRightLeftIcon))
216
+ ]),
217
+ _: 1
218
+ }, 8, ["aria-label"])
219
+ ]),
220
+ _: 2
221
+ }, 1024),
222
+ createVNode(unref(_sfc_main$6), { align: "end" }, {
223
+ default: withCtx(() => [
224
+ (openBlock(true), createElementBlock(Fragment, null, renderList(othersOf(column.id), (other) => {
225
+ return openBlock(), createBlock(unref(_sfc_main$7), {
226
+ key: other.id,
227
+ onSelect: ($event) => move(record, other.id)
228
+ }, {
229
+ default: withCtx(() => [
230
+ createTextVNode(toDisplayString(other.label), 1)
231
+ ]),
232
+ _: 2
233
+ }, 1032, ["onSelect"]);
234
+ }), 128))
235
+ ]),
236
+ _: 2
237
+ }, 1024)
238
+ ]),
239
+ _: 2
240
+ }, 1024)
241
+ ])) : createCommentVNode("", true)
242
+ ]),
243
+ _: 2
244
+ }, 1032, ["id", "draggable", "data-record-id", "onClick", "onKeydown"]);
245
+ }), 128))
246
+ ]),
247
+ _: 2
248
+ }, 1032, ["column-id"])
249
+ ], 10, _hoisted_1);
250
+ }), 128))
251
+ ], 16)
252
+ ]),
253
+ _: 3
254
+ });
255
+ };
256
+ }
257
+ });
258
+ export {
259
+ _sfc_main as default
260
+ };
@@ -0,0 +1,18 @@
1
+ type __VLS_Props = {
2
+ /** The record id; the drag's source id. */
3
+ id: string;
4
+ /** False when the user may not edit: the card is no drag source then. */
5
+ draggable: boolean;
6
+ };
7
+ declare var __VLS_1: {};
8
+ type __VLS_Slots = {} & {
9
+ default?: (props: typeof __VLS_1) => any;
10
+ };
11
+ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
+ declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
13
+ export default _default;
14
+ type __VLS_WithSlots<T, S> = T & {
15
+ new (): {
16
+ $slots: S;
17
+ };
18
+ };
@@ -0,0 +1,32 @@
1
+ import { defineComponent, ref, openBlock, createElementBlock, unref, renderSlot } from "vue";
2
+ import { useDraggable } from "@dnd-kit/vue";
3
+ const _hoisted_1 = ["data-dragging", "data-draggable"];
4
+ const _sfc_main = /* @__PURE__ */ defineComponent({
5
+ __name: "kanban-draggable-card",
6
+ props: {
7
+ id: {},
8
+ draggable: { type: Boolean }
9
+ },
10
+ setup(__props) {
11
+ const props = __props;
12
+ const element = ref();
13
+ const { isDragging } = useDraggable({
14
+ id: () => props.id,
15
+ element,
16
+ disabled: () => !props.draggable
17
+ });
18
+ return (_ctx, _cache) => {
19
+ return openBlock(), createElementBlock("div", {
20
+ ref_key: "element",
21
+ ref: element,
22
+ "data-dragging": unref(isDragging) ? "" : void 0,
23
+ "data-draggable": __props.draggable ? "" : void 0
24
+ }, [
25
+ renderSlot(_ctx.$slots, "default")
26
+ ], 8, _hoisted_1);
27
+ };
28
+ }
29
+ });
30
+ export {
31
+ _sfc_main as default
32
+ };
@@ -0,0 +1,4 @@
1
+ import _sfc_main from "./kanban-draggable-card.vue.js";
2
+ export {
3
+ _sfc_main as default
4
+ };
@@ -0,0 +1,15 @@
1
+ type __VLS_Props = {
2
+ columnId: string;
3
+ };
4
+ declare var __VLS_1: {};
5
+ type __VLS_Slots = {} & {
6
+ default?: (props: typeof __VLS_1) => any;
7
+ };
8
+ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
10
+ export default _default;
11
+ type __VLS_WithSlots<T, S> = T & {
12
+ new (): {
13
+ $slots: S;
14
+ };
15
+ };
@@ -0,0 +1,29 @@
1
+ import { defineComponent, ref, openBlock, createElementBlock, unref, renderSlot } from "vue";
2
+ import { useDroppable } from "@dnd-kit/vue";
3
+ const _hoisted_1 = ["data-over"];
4
+ const _sfc_main = /* @__PURE__ */ defineComponent({
5
+ __name: "kanban-drop-area",
6
+ props: {
7
+ columnId: {}
8
+ },
9
+ setup(__props) {
10
+ const props = __props;
11
+ const element = ref();
12
+ const { isDropTarget } = useDroppable({
13
+ id: () => props.columnId,
14
+ element
15
+ });
16
+ return (_ctx, _cache) => {
17
+ return openBlock(), createElementBlock("div", {
18
+ ref_key: "element",
19
+ ref: element,
20
+ "data-over": unref(isDropTarget) ? "" : void 0
21
+ }, [
22
+ renderSlot(_ctx.$slots, "default")
23
+ ], 8, _hoisted_1);
24
+ };
25
+ }
26
+ });
27
+ export {
28
+ _sfc_main as default
29
+ };
@@ -0,0 +1,4 @@
1
+ import _sfc_main from "./kanban-drop-area.vue.js";
2
+ export {
3
+ _sfc_main as default
4
+ };
@@ -0,0 +1,18 @@
1
+ import { type ChartConfig } from "./utils.js";
2
+ type __VLS_Props = {
3
+ id?: string;
4
+ class?: string;
5
+ config: ChartConfig;
6
+ };
7
+ declare var __VLS_4: {};
8
+ type __VLS_Slots = {} & {
9
+ default?: (props: typeof __VLS_4) => any;
10
+ };
11
+ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
+ declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
13
+ export default _default;
14
+ type __VLS_WithSlots<T, S> = T & {
15
+ new (): {
16
+ $slots: S;
17
+ };
18
+ };
@@ -0,0 +1,40 @@
1
+ import { defineComponent, toRefs, openBlock, createElementBlock, normalizeClass, unref, createVNode, renderSlot } from "vue";
2
+ import { cn } from "../../../lib/utils.js";
3
+ import _sfc_main$1 from "./chart-style.vue.js";
4
+ import { useId, provideChartContext } from "./utils.js";
5
+ const _sfc_main = /* @__PURE__ */ defineComponent({
6
+ __name: "chart-container",
7
+ props: {
8
+ id: {},
9
+ class: {},
10
+ config: {}
11
+ },
12
+ setup(__props) {
13
+ const props = __props;
14
+ const { config } = toRefs(props);
15
+ const uniqueId = useId();
16
+ const chartId = `chart-${props.id || uniqueId}`;
17
+ provideChartContext({ id: uniqueId, config });
18
+ return (_ctx, _cache) => {
19
+ return openBlock(), createElementBlock("div", {
20
+ "data-slot": "chart",
21
+ "data-chart": chartId,
22
+ class: normalizeClass(
23
+ unref(cn)(
24
+ "[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
25
+ props.class
26
+ )
27
+ )
28
+ }, [
29
+ createVNode(_sfc_main$1, {
30
+ id: chartId,
31
+ config: unref(config)
32
+ }, null, 8, ["config"]),
33
+ renderSlot(_ctx.$slots, "default")
34
+ ], 2);
35
+ };
36
+ }
37
+ });
38
+ export {
39
+ _sfc_main as default
40
+ };
@@ -0,0 +1,4 @@
1
+ import _sfc_main from "./chart-container.vue.js";
2
+ export {
3
+ _sfc_main as default
4
+ };
@@ -0,0 +1,9 @@
1
+ type __VLS_Props = {
2
+ class?: string;
3
+ hideIcon?: boolean;
4
+ verticalAlign?: "top" | "bottom";
5
+ };
6
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
7
+ verticalAlign: "top" | "bottom";
8
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ export default _default;
@@ -0,0 +1,56 @@
1
+ import { defineComponent, computed, openBlock, createElementBlock, normalizeClass, unref, Fragment, renderList, createBlock, resolveDynamicComponent, normalizeStyle, createTextVNode, toDisplayString, createCommentVNode } from "vue";
2
+ import { cn } from "../../../lib/utils.js";
3
+ import { useChart } from "./utils.js";
4
+ const _sfc_main = /* @__PURE__ */ defineComponent({
5
+ __name: "chart-legend-content",
6
+ props: {
7
+ class: {},
8
+ hideIcon: { type: Boolean },
9
+ verticalAlign: { default: "bottom" }
10
+ },
11
+ setup(__props) {
12
+ const props = __props;
13
+ const { config } = useChart();
14
+ const items = computed(
15
+ () => Object.entries(config.value).map(([key, item]) => ({
16
+ key,
17
+ item,
18
+ // A themed entry has no single color; `ChartStyle` defines the variable.
19
+ color: item.color ?? `var(--color-${key})`,
20
+ label: item.label ?? key
21
+ }))
22
+ );
23
+ return (_ctx, _cache) => {
24
+ return items.value.length ? (openBlock(), createElementBlock("div", {
25
+ key: 0,
26
+ class: normalizeClass(
27
+ unref(cn)(
28
+ "flex items-center justify-center gap-4",
29
+ props.verticalAlign === "top" ? "pb-3" : "pt-3",
30
+ props.class
31
+ )
32
+ )
33
+ }, [
34
+ (openBlock(true), createElementBlock(Fragment, null, renderList(items.value, (entry) => {
35
+ return openBlock(), createElementBlock("div", {
36
+ key: entry.key,
37
+ "data-slot": "chart-legend-item",
38
+ class: "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
39
+ }, [
40
+ entry.item.icon && !props.hideIcon ? (openBlock(), createBlock(resolveDynamicComponent(entry.item.icon), { key: 0 })) : (openBlock(), createElementBlock("div", {
41
+ key: 1,
42
+ class: "h-2 w-2 shrink-0 rounded-[2px]",
43
+ style: normalizeStyle({ backgroundColor: entry.color })
44
+ }, null, 4)),
45
+ typeof entry.label !== "string" ? (openBlock(), createBlock(resolveDynamicComponent(entry.label), { key: 2 })) : (openBlock(), createElementBlock(Fragment, { key: 3 }, [
46
+ createTextVNode(toDisplayString(entry.label), 1)
47
+ ], 64))
48
+ ]);
49
+ }), 128))
50
+ ], 2)) : createCommentVNode("", true);
51
+ };
52
+ }
53
+ });
54
+ export {
55
+ _sfc_main as default
56
+ };
@@ -0,0 +1,4 @@
1
+ import _sfc_main from "./chart-legend-content.vue.js";
2
+ export {
3
+ _sfc_main as default
4
+ };
@@ -0,0 +1,7 @@
1
+ import { type ChartConfig } from "./utils.js";
2
+ type __VLS_Props = {
3
+ id: string;
4
+ config: ChartConfig;
5
+ };
6
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
+ export default _default;
@@ -0,0 +1,43 @@
1
+ import { defineComponent, computed, openBlock, createBlock, resolveDynamicComponent, withCtx, createTextVNode, toDisplayString, createCommentVNode } from "vue";
2
+ import { THEMES } from "./utils.js";
3
+ const _sfc_main = /* @__PURE__ */ defineComponent({
4
+ __name: "chart-style",
5
+ props: {
6
+ id: {},
7
+ config: {}
8
+ },
9
+ setup(__props) {
10
+ const props = __props;
11
+ const THEME_NAMES = ["light", "dark"];
12
+ const SAFE_TOKEN = /^[\w-]+$/;
13
+ const SAFE_COLOR = /^[^<>{};]+$/;
14
+ const css = computed(() => {
15
+ if (!SAFE_TOKEN.test(props.id)) return "";
16
+ const colored = Object.entries(props.config).filter(
17
+ ([key, item]) => SAFE_TOKEN.test(key) && (item.theme || item.color)
18
+ );
19
+ if (!colored.length) return "";
20
+ return THEME_NAMES.map((theme) => {
21
+ const prefix = THEMES[theme];
22
+ const lines = colored.flatMap(([key, item]) => {
23
+ const color = item.theme?.[theme] ?? item.color;
24
+ return color && SAFE_COLOR.test(color) ? [` --color-${key}: ${color};`] : [];
25
+ });
26
+ return `${prefix} [data-chart=${props.id}] {
27
+ ${lines.join("\n")}
28
+ }`;
29
+ }).join("\n");
30
+ });
31
+ return (_ctx, _cache) => {
32
+ return css.value ? (openBlock(), createBlock(resolveDynamicComponent("style"), { key: 0 }, {
33
+ default: withCtx(() => [
34
+ createTextVNode(toDisplayString(css.value), 1)
35
+ ]),
36
+ _: 1
37
+ })) : createCommentVNode("", true);
38
+ };
39
+ }
40
+ });
41
+ export {
42
+ _sfc_main as default
43
+ };
@@ -0,0 +1,4 @@
1
+ import _sfc_main from "./chart-style.vue.js";
2
+ export {
3
+ _sfc_main as default
4
+ };
@@ -0,0 +1,7 @@
1
+ import { type ChartTooltipOptions, type ChartTooltipRenderProps } from "./utils.js";
2
+ type __VLS_Props = ChartTooltipOptions & ChartTooltipRenderProps;
3
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
4
+ payload: import("./utils.js").ChartDatum;
5
+ indicator: "line" | "dot" | "dashed";
6
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
+ export default _default;