@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.
- package/README.md +1 -0
- package/dist/components/admin/fields/api-key-field.vue.d.ts +1 -1
- package/dist/components/admin/fields/api-key-field.vue.js +2 -12
- package/dist/components/index.d.ts +0 -2
- package/dist/components/kanban/kanban-board.vue.js +260 -0
- package/dist/components/kanban/kanban-draggable-card.vue.d.ts +18 -0
- package/dist/components/kanban/kanban-draggable-card.vue.js +32 -0
- package/dist/components/kanban/kanban-draggable-card2.vue.js +4 -0
- package/dist/components/kanban/kanban-drop-area.vue.d.ts +15 -0
- package/dist/components/kanban/kanban-drop-area.vue.js +29 -0
- package/dist/components/kanban/kanban-drop-area2.vue.js +4 -0
- package/dist/components/ui/chart/chart-container.vue.d.ts +18 -0
- package/dist/components/ui/chart/chart-container.vue.js +40 -0
- package/dist/components/ui/chart/chart-container2.vue.js +4 -0
- package/dist/components/ui/chart/chart-legend-content.vue.d.ts +9 -0
- package/dist/components/ui/chart/chart-legend-content.vue.js +56 -0
- package/dist/components/ui/chart/chart-legend-content2.vue.js +4 -0
- package/dist/components/ui/chart/chart-style.vue.d.ts +7 -0
- package/dist/components/ui/chart/chart-style.vue.js +43 -0
- package/dist/components/ui/chart/chart-style2.vue.js +4 -0
- package/dist/components/ui/chart/chart-tooltip-content.vue.d.ts +7 -0
- package/dist/components/ui/chart/chart-tooltip-content.vue.js +122 -0
- package/dist/components/ui/chart/chart-tooltip-content2.vue.js +4 -0
- package/dist/components/ui/chart/index.d.ts +11 -0
- package/dist/components/ui/chart/utils.d.ts +81 -0
- package/dist/components/ui/chart/utils.js +52 -0
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/data/create-chelone-hooks.d.ts +2 -1
- package/dist/data/queries.d.ts +6 -3
- package/dist/data/queries.js +8 -4
- package/dist/index.js +398 -387
- package/dist/kanban.d.ts +1 -0
- package/dist/kanban.js +4 -0
- package/package.json +18 -4
- package/dist/components/admin/list/kanban-board.vue.js +0 -275
- /package/dist/components/{admin/list → kanban}/kanban-board.vue.d.ts +0 -0
- /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
|
|
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(
|
|
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,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,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,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,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,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;
|