@dazzadev/vuetify-datatable 1.0.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 ADDED
@@ -0,0 +1,161 @@
1
+ # @dazza-dev/vuetify-datatable
2
+
3
+ Reusable server-side DataTable component for Vuetify 3. Includes action buttons (view, edit, delete), configurable icons, and a built-in confirmation modal.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @dazza-dev/vuetify-datatable
9
+ ```
10
+
11
+ ## Setup
12
+
13
+ ### Register globally (recommended)
14
+
15
+ ```ts
16
+ // main.ts
17
+ import { createApp } from 'vue';
18
+ import VuetifyDatatable from '@dazza-dev/vuetify-datatable';
19
+
20
+ const app = createApp(App);
21
+ app.use(VuetifyDatatable);
22
+ ```
23
+
24
+ ### Or import individually
25
+
26
+ ```ts
27
+ import { DataTable, ConfirmationModal } from '@dazza-dev/vuetify-datatable';
28
+ ```
29
+
30
+ ## Basic Usage
31
+
32
+ ```vue
33
+ <template>
34
+ <DataTable
35
+ :headers="headers"
36
+ :items="items"
37
+ :loading="loading"
38
+ :total-items="totalItems"
39
+ :search="search"
40
+ @onLoadData="loadData"
41
+ @editItem="editItem"
42
+ @deleteItem="deleteItem"
43
+ />
44
+ </template>
45
+ ```
46
+
47
+ ## Icon Configuration
48
+
49
+ Icons can be configured at 4 levels of priority (highest to lowest):
50
+
51
+ ### 1. Slots (full control per instance)
52
+
53
+ ```vue
54
+ <DataTable :headers="headers" :items="items">
55
+ <template #view-icon>
56
+ <MyCustomIcon />
57
+ </template>
58
+ <template #edit-icon>
59
+ <img src="/icons/edit.svg" width="20" />
60
+ </template>
61
+ <template #delete-icon>
62
+ <i class="fa-solid fa-trash"></i>
63
+ </template>
64
+ </DataTable>
65
+ ```
66
+
67
+ ### 2. Props (string override per instance)
68
+
69
+ ```vue
70
+ <DataTable
71
+ view-icon="mdi-magnify"
72
+ edit-icon="mdi-square-edit-outline"
73
+ delete-icon="mdi-delete"
74
+ />
75
+ ```
76
+
77
+ ### 3. Global plugin config (configure once, applies everywhere)
78
+
79
+ ```ts
80
+ // main.ts
81
+ import { createDataTableConfig } from '@dazza-dev/vuetify-datatable';
82
+ import { IconEye, IconPencil, IconTrash } from '@tabler/icons-vue';
83
+
84
+ app.use(createDataTableConfig({
85
+ icons: {
86
+ view: IconEye,
87
+ edit: IconPencil,
88
+ delete: IconTrash
89
+ },
90
+ iconProps: { 'stroke-width': 1.5 }
91
+ }));
92
+ ```
93
+
94
+ This works with any icon library: Tabler, FontAwesome, Heroicons, or any Vue component.
95
+
96
+ ### 4. MDI defaults (no config needed)
97
+
98
+ If no configuration is provided, the component uses Material Design Icons (included with Vuetify):
99
+
100
+ - View: `mdi-eye-outline`
101
+ - Edit: `mdi-pencil-outline`
102
+ - Delete: `mdi-trash-can-outline`
103
+
104
+ ## Props
105
+
106
+ | Prop | Type | Default | Description |
107
+ |------|------|---------|-------------|
108
+ | `headers` | `TableHeader[]` | `[]` | Table column headers |
109
+ | `items` | `T[]` | `[]` | Table row data |
110
+ | `loading` | `boolean` | `false` | Show loading state |
111
+ | `totalItems` | `number` | `0` | Total items for server-side pagination |
112
+ | `itemsPerPage` | `number` | `10` | Items per page |
113
+ | `search` | `string` | — | Search query |
114
+ | `itemValue` | `string` | `'id'` | Unique item identifier key |
115
+ | `tableClass` | `string` | `'border rounded-md mt-5'` | CSS class for the table |
116
+ | `showExpand` | `boolean` | `false` | Show expandable rows |
117
+ | `showViewButton` | `boolean` | `false` | Show view action button |
118
+ | `showEditButton` | `boolean` | `true` | Show edit action button |
119
+ | `showDeleteButton` | `boolean` | `true` | Show delete action button |
120
+ | `viewButtonText` | `string` | — | View button tooltip text |
121
+ | `editButtonText` | `string` | — | Edit button tooltip text |
122
+ | `deleteButtonText` | `string` | — | Delete button tooltip text |
123
+ | `deleteModalTitle` | `string` | — | Delete confirmation modal title |
124
+ | `deleteModalMessage` | `string` | — | Delete confirmation modal message |
125
+ | `deleteModalConfirmButtonText` | `string` | — | Confirm button text |
126
+ | `deleteModalCancelButtonText` | `string` | — | Cancel button text |
127
+ | `viewIcon` | `string` | — | View icon name override |
128
+ | `editIcon` | `string` | — | Edit icon name override |
129
+ | `deleteIcon` | `string` | — | Delete icon name override |
130
+
131
+ ## Events
132
+
133
+ | Event | Payload | Description |
134
+ |-------|---------|-------------|
135
+ | `onLoadData` | `LoadDataParams` | Triggered on pagination, sort, or search changes |
136
+ | `editItem` | `T` | Triggered when edit button is clicked |
137
+ | `deleteItem` | `T` | Triggered when delete is confirmed |
138
+ | `viewItem` | `T` | Triggered when view button is clicked |
139
+
140
+ ## Slots
141
+
142
+ | Slot | Description |
143
+ |------|-------------|
144
+ | `item.{key}` | Custom render for any column by header key |
145
+ | `expanded-row` | Content for expandable rows |
146
+ | `item.data-table-expand` | Custom expand toggle button |
147
+ | `before-actions` | Content before action buttons |
148
+ | `after-actions` | Content after action buttons |
149
+ | `view-icon` | Custom view icon |
150
+ | `edit-icon` | Custom edit icon |
151
+ | `delete-icon` | Custom delete icon |
152
+ | `item.tfoot` | Table footer content |
153
+
154
+ ## Peer Dependencies
155
+
156
+ - `vue` >= 3.3
157
+ - `vuetify` >= 3.0
158
+
159
+ ## License
160
+
161
+ MIT
@@ -0,0 +1,32 @@
1
+ declare var __VLS_18: {};
2
+ type __VLS_Slots = {} & {
3
+ description?: (props: typeof __VLS_18) => any;
4
+ };
5
+ declare const __VLS_component: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
6
+ show: BooleanConstructor;
7
+ title: StringConstructor;
8
+ description: StringConstructor;
9
+ confirmButtonText: StringConstructor;
10
+ cancelButtonText: StringConstructor;
11
+ }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ close: (...args: any[]) => void;
13
+ confirm: (...args: any[]) => void;
14
+ }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
15
+ show: BooleanConstructor;
16
+ title: StringConstructor;
17
+ description: StringConstructor;
18
+ confirmButtonText: StringConstructor;
19
+ cancelButtonText: StringConstructor;
20
+ }>> & Readonly<{
21
+ onClose?: ((...args: any[]) => any) | undefined;
22
+ onConfirm?: ((...args: any[]) => any) | undefined;
23
+ }>, {
24
+ show: boolean;
25
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
26
+ declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
27
+ export default _default;
28
+ type __VLS_WithSlots<T, S> = T & {
29
+ new (): {
30
+ $slots: S;
31
+ };
32
+ };
@@ -0,0 +1,75 @@
1
+ import type { TableHeader } from '../types';
2
+ declare const _default: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
3
+ props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{
4
+ readonly onOnLoadData?: ((...args: any[]) => any) | undefined;
5
+ readonly onEditItem?: ((...args: any[]) => any) | undefined;
6
+ readonly onDeleteItem?: ((...args: any[]) => any) | undefined;
7
+ readonly onViewItem?: ((...args: any[]) => any) | undefined;
8
+ } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, "onOnLoadData" | "onEditItem" | "onDeleteItem" | "onViewItem"> & {
9
+ tableClass?: string;
10
+ headers?: TableHeader[];
11
+ items?: T[];
12
+ loading?: boolean;
13
+ itemValue?: string;
14
+ totalItems?: number;
15
+ itemsPerPage?: number;
16
+ search?: string;
17
+ showExpand?: boolean;
18
+ showEditButton?: boolean;
19
+ showDeleteButton?: boolean;
20
+ showViewButton?: boolean;
21
+ viewButtonText?: string;
22
+ deleteButtonText?: string;
23
+ deleteModalTitle?: string;
24
+ deleteModalMessage?: string;
25
+ deleteModalConfirmButtonText?: string;
26
+ deleteModalCancelButtonText?: string;
27
+ editButtonText?: string;
28
+ viewIcon?: string;
29
+ editIcon?: string;
30
+ deleteIcon?: string;
31
+ } & Partial<{}>> & import("vue").PublicProps;
32
+ expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
33
+ attrs: any;
34
+ slots: {
35
+ [x: `item.${string}`]: ((props: {
36
+ item: any;
37
+ }) => any) | undefined;
38
+ } & {
39
+ "item.data-table-expand"?: ((props: {
40
+ internalItem: any;
41
+ isExpanded: any;
42
+ toggleExpand: any;
43
+ }) => any) | undefined;
44
+ } & {
45
+ "expanded-row"?: ((props: {
46
+ columns: any;
47
+ item: any;
48
+ }) => any) | undefined;
49
+ } & {
50
+ 'before-actions'?: (props: {
51
+ item: any;
52
+ }) => any;
53
+ } & {
54
+ 'view-icon'?: (props: {}) => any;
55
+ } & {
56
+ 'edit-icon'?: (props: {}) => any;
57
+ } & {
58
+ 'delete-icon'?: (props: {}) => any;
59
+ } & {
60
+ 'after-actions'?: (props: {
61
+ item: any;
62
+ }) => any;
63
+ } & {
64
+ 'item.tfoot'?: (props: {}) => any;
65
+ };
66
+ emit: (event: "onLoadData" | "editItem" | "deleteItem" | "viewItem", ...args: any[]) => void;
67
+ }>) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
68
+ [key: string]: any;
69
+ }> & {
70
+ __ctx?: Awaited<typeof __VLS_setup>;
71
+ };
72
+ export default _default;
73
+ type __VLS_PrettifyLocal<T> = {
74
+ [K in keyof T]: T[K];
75
+ } & {};
@@ -0,0 +1,6 @@
1
+ import type { InjectionKey, App } from 'vue';
2
+ import type { DataTableConfig } from './types';
3
+ export declare const DATA_TABLE_CONFIG_KEY: InjectionKey<DataTableConfig>;
4
+ export declare function createDataTableConfig(config: DataTableConfig): {
5
+ install(app: App): void;
6
+ };
@@ -0,0 +1,10 @@
1
+ import type { App } from 'vue';
2
+ import DataTable from './components/DataTable.vue';
3
+ import { createDataTableConfig, DATA_TABLE_CONFIG_KEY } from './config';
4
+ export { DataTable };
5
+ export { createDataTableConfig, DATA_TABLE_CONFIG_KEY };
6
+ export type { DataTableConfig, DataTableIconConfig, TableHeader, SortItem, LoadDataParams } from './types';
7
+ declare const _default: {
8
+ install(app: App): void;
9
+ };
10
+ export default _default;
@@ -0,0 +1,30 @@
1
+ import type { Component } from 'vue';
2
+ export interface TableHeader {
3
+ key: string;
4
+ title?: string;
5
+ align?: string;
6
+ sortable?: boolean;
7
+ fixed?: boolean;
8
+ }
9
+ export interface SortItem {
10
+ key: string;
11
+ order: 'asc' | 'desc';
12
+ }
13
+ export interface DataTableIconConfig {
14
+ view?: string | Component;
15
+ edit?: string | Component;
16
+ delete?: string | Component;
17
+ }
18
+ export interface DataTableConfig {
19
+ icons?: DataTableIconConfig;
20
+ iconProps?: Record<string, unknown>;
21
+ }
22
+ export interface LoadDataParams {
23
+ page: number;
24
+ itemsPerPage: number;
25
+ search?: string;
26
+ sortBy?: {
27
+ column: string;
28
+ direction: string;
29
+ }[];
30
+ }
@@ -0,0 +1,428 @@
1
+ import { defineComponent as q, computed as M, resolveComponent as y, openBlock as p, createBlock as x, withCtx as o, createVNode as c, createTextVNode as C, toDisplayString as T, renderSlot as h, createCommentVNode as j, inject as X, ref as V, onMounted as Z, watch as O, createElementBlock as ee, Fragment as te, normalizeClass as oe, createSlots as ne, createElementVNode as ae, mergeProps as $, resolveDynamicComponent as N, renderList as le } from "vue";
2
+ function se(e) {
3
+ return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
4
+ }
5
+ var z = { exports: {} }, F;
6
+ function ie() {
7
+ if (F) return z.exports;
8
+ F = 1;
9
+ function e(w, i = 100, m = {}) {
10
+ if (typeof w != "function")
11
+ throw new TypeError(`Expected the first parameter to be a function, got \`${typeof w}\`.`);
12
+ if (i < 0)
13
+ throw new RangeError("`wait` must not be negative.");
14
+ const { immediate: r } = typeof m == "boolean" ? { immediate: m } : m;
15
+ let f, b, a, B, v;
16
+ function d() {
17
+ const g = f, P = b;
18
+ return f = void 0, b = void 0, v = w.apply(g, P), v;
19
+ }
20
+ function k() {
21
+ const g = Date.now() - B;
22
+ g < i && g >= 0 ? a = setTimeout(k, i - g) : (a = void 0, r || (v = d()));
23
+ }
24
+ const l = function(...g) {
25
+ if (f && this !== f && Object.getPrototypeOf(this) === Object.getPrototypeOf(f))
26
+ throw new Error("Debounced method called with different contexts of the same prototype.");
27
+ f = this, b = g, B = Date.now();
28
+ const P = r && !a;
29
+ return a || (a = setTimeout(k, i)), P && (v = d()), v;
30
+ };
31
+ return Object.defineProperty(l, "isPending", {
32
+ get() {
33
+ return a !== void 0;
34
+ }
35
+ }), l.clear = () => {
36
+ a && (clearTimeout(a), a = void 0);
37
+ }, l.flush = () => {
38
+ a && l.trigger();
39
+ }, l.trigger = () => {
40
+ v = d(), l.clear();
41
+ }, l;
42
+ }
43
+ return z.exports.debounce = e, z.exports = e, z.exports;
44
+ }
45
+ var re = /* @__PURE__ */ ie();
46
+ const ce = /* @__PURE__ */ se(re), de = /* @__PURE__ */ q({
47
+ __name: "ConfirmationModal",
48
+ props: {
49
+ show: Boolean,
50
+ title: String,
51
+ description: String,
52
+ confirmButtonText: String,
53
+ cancelButtonText: String
54
+ },
55
+ emits: ["close", "confirm"],
56
+ setup(e) {
57
+ const w = e, i = M({
58
+ get: () => w.show,
59
+ set: () => {
60
+ }
61
+ });
62
+ return (m, r) => {
63
+ const f = y("v-card-title"), b = y("v-card-text"), a = y("v-spacer"), B = y("v-btn"), v = y("v-card-actions"), d = y("v-card"), k = y("v-dialog");
64
+ return p(), x(k, {
65
+ modelValue: i.value,
66
+ "onUpdate:modelValue": r[2] || (r[2] = (l) => i.value = l),
67
+ "max-width": "500px",
68
+ persistent: "",
69
+ "no-click-animation": ""
70
+ }, {
71
+ default: o(() => [
72
+ c(d, null, {
73
+ default: o(() => [
74
+ c(f, { class: "text-h5 text-center py-6" }, {
75
+ default: o(() => [
76
+ C(T(e.title), 1)
77
+ ]),
78
+ _: 1
79
+ }),
80
+ e.description ? (p(), x(b, {
81
+ key: 0,
82
+ class: "text-center px-0 py-0"
83
+ }, {
84
+ default: o(() => [
85
+ C(T(e.description) + " ", 1),
86
+ h(m.$slots, "description")
87
+ ]),
88
+ _: 3
89
+ })) : j("", !0),
90
+ c(v, null, {
91
+ default: o(() => [
92
+ c(a),
93
+ c(B, {
94
+ color: "error",
95
+ variant: "flat",
96
+ dark: "",
97
+ onClick: r[0] || (r[0] = (l) => m.$emit("close"))
98
+ }, {
99
+ default: o(() => [
100
+ C(T(e.cancelButtonText), 1)
101
+ ]),
102
+ _: 1
103
+ }),
104
+ c(B, {
105
+ color: "success",
106
+ variant: "flat",
107
+ dark: "",
108
+ onClick: r[1] || (r[1] = (l) => m.$emit("confirm"))
109
+ }, {
110
+ default: o(() => [
111
+ C(T(e.confirmButtonText), 1)
112
+ ]),
113
+ _: 1
114
+ }),
115
+ c(a)
116
+ ]),
117
+ _: 1
118
+ })
119
+ ]),
120
+ _: 3
121
+ })
122
+ ]),
123
+ _: 3
124
+ }, 8, ["modelValue"]);
125
+ };
126
+ }
127
+ }), U = Symbol("DataTableConfig");
128
+ function ve(e) {
129
+ return {
130
+ install(w) {
131
+ w.provide(U, e);
132
+ }
133
+ };
134
+ }
135
+ const ue = /* @__PURE__ */ q({
136
+ __name: "DataTable",
137
+ props: {
138
+ tableClass: { default: "border rounded-md mt-5" },
139
+ headers: { default: () => [] },
140
+ items: { default: () => [] },
141
+ loading: { type: Boolean, default: !1 },
142
+ itemValue: { default: "id" },
143
+ totalItems: { default: 0 },
144
+ itemsPerPage: { default: 10 },
145
+ search: {},
146
+ showExpand: { type: Boolean, default: !1 },
147
+ showEditButton: { type: Boolean, default: !0 },
148
+ showDeleteButton: { type: Boolean, default: !0 },
149
+ showViewButton: { type: Boolean, default: !1 },
150
+ viewButtonText: {},
151
+ deleteButtonText: {},
152
+ deleteModalTitle: {},
153
+ deleteModalMessage: {},
154
+ deleteModalConfirmButtonText: {},
155
+ deleteModalCancelButtonText: {},
156
+ editButtonText: {},
157
+ viewIcon: {},
158
+ editIcon: {},
159
+ deleteIcon: {}
160
+ },
161
+ emits: ["onLoadData", "editItem", "deleteItem", "viewItem"],
162
+ setup(e, { emit: w }) {
163
+ const i = e, m = w, r = X(U, { icons: {} }), f = M(() => {
164
+ var t;
165
+ return i.viewIcon ?? ((t = r.icons) == null ? void 0 : t.view) ?? "mdi-eye-outline";
166
+ }), b = M(() => {
167
+ var t;
168
+ return i.editIcon ?? ((t = r.icons) == null ? void 0 : t.edit) ?? "mdi-pencil-outline";
169
+ }), a = M(() => {
170
+ var t;
171
+ return i.deleteIcon ?? ((t = r.icons) == null ? void 0 : t.delete) ?? "mdi-trash-can-outline";
172
+ }), B = M(() => r.iconProps ?? {});
173
+ function v(t) {
174
+ return typeof t != "string";
175
+ }
176
+ const d = V(i.itemsPerPage), k = V([]), l = V(1), g = V(null), P = V(!1), R = M(() => {
177
+ var t;
178
+ return ((t = i.headers) == null ? void 0 : t.filter(
179
+ (s) => s.key !== "actions" && s.key !== "expanded-row" && s.key !== "data-table-expand"
180
+ )) || [];
181
+ });
182
+ Z(() => {
183
+ E({
184
+ page: l.value,
185
+ itemsPerPage: d.value
186
+ });
187
+ });
188
+ const _ = (t) => {
189
+ g.value = t, P.value = !0;
190
+ }, G = () => {
191
+ g.value = null, P.value = !1;
192
+ }, K = (t) => {
193
+ m("editItem", t);
194
+ }, Y = (t) => {
195
+ m("viewItem", t);
196
+ }, H = () => {
197
+ m("deleteItem", g.value), P.value = !1;
198
+ }, E = ({ page: t, itemsPerPage: s }) => {
199
+ const I = k.value.map((D) => ({
200
+ column: D.key,
201
+ direction: D.order
202
+ }));
203
+ m("onLoadData", {
204
+ page: t,
205
+ itemsPerPage: s,
206
+ search: i.search,
207
+ sortBy: I
208
+ });
209
+ };
210
+ function J() {
211
+ E({
212
+ page: 1,
213
+ itemsPerPage: d.value
214
+ });
215
+ }
216
+ const A = ce(J, 400), Q = () => {
217
+ A();
218
+ };
219
+ return O(
220
+ () => i.search,
221
+ (t, s) => {
222
+ t !== s && A();
223
+ }
224
+ ), O(d, (t, s) => {
225
+ t !== s && E({
226
+ page: 1,
227
+ itemsPerPage: t
228
+ });
229
+ }), O(k, () => {
230
+ E({
231
+ page: 1,
232
+ itemsPerPage: d.value
233
+ });
234
+ }), O(l, (t) => {
235
+ E({
236
+ page: t,
237
+ itemsPerPage: d.value
238
+ });
239
+ }), (t, s) => {
240
+ const I = y("v-icon"), D = y("v-btn"), L = y("v-tooltip"), W = y("v-data-table-server");
241
+ return p(), ee(te, null, [
242
+ c(W, {
243
+ headers: e.headers,
244
+ items: e.items,
245
+ loading: e.loading,
246
+ "items-length": e.totalItems,
247
+ "items-per-page": d.value,
248
+ "onUpdate:itemsPerPage": s[0] || (s[0] = (n) => d.value = n),
249
+ search: e.search,
250
+ onSearch: Q,
251
+ "sort-by": k.value,
252
+ "onUpdate:sortBy": s[1] || (s[1] = (n) => k.value = n),
253
+ page: l.value,
254
+ "onUpdate:page": s[2] || (s[2] = (n) => l.value = n),
255
+ "item-value": e.itemValue,
256
+ "show-expand": e.showExpand,
257
+ class: oe(e.tableClass)
258
+ }, ne({
259
+ "item.data-table-expand": o(({ internalItem: n, isExpanded: u, toggleExpand: S }) => [
260
+ h(t.$slots, "item.data-table-expand", {
261
+ internalItem: n,
262
+ isExpanded: u,
263
+ toggleExpand: S
264
+ }, () => [
265
+ c(D, {
266
+ onClick: (me) => S(n),
267
+ rounded: ""
268
+ }, {
269
+ default: o(() => [
270
+ c(I, null, {
271
+ default: o(() => [
272
+ C(T(u(n) ? "mdi-chevron-up" : "mdi-chevron-down"), 1)
273
+ ]),
274
+ _: 2
275
+ }, 1024)
276
+ ]),
277
+ _: 2
278
+ }, 1032, ["onClick"])
279
+ ])
280
+ ]),
281
+ "expanded-row": o(({ columns: n, item: u }) => [
282
+ h(t.$slots, "expanded-row", {
283
+ columns: n,
284
+ item: u
285
+ })
286
+ ]),
287
+ "item.actions": o(({ item: n }) => [
288
+ h(t.$slots, "before-actions", { item: n }),
289
+ e.showViewButton ? (p(), x(L, {
290
+ key: 0,
291
+ text: e.viewButtonText
292
+ }, {
293
+ activator: o(({ props: u }) => [
294
+ c(D, $({
295
+ icon: "",
296
+ flat: "",
297
+ onClick: (S) => Y(n)
298
+ }, u), {
299
+ default: o(() => [
300
+ h(t.$slots, "view-icon", {}, () => [
301
+ v(f.value) ? (p(), x(N(f.value), $({
302
+ key: 0,
303
+ size: 20,
304
+ class: "text-info"
305
+ }, B.value), null, 16)) : (p(), x(I, {
306
+ key: 1,
307
+ size: "20",
308
+ class: "text-info"
309
+ }, {
310
+ default: o(() => [
311
+ C(T(f.value), 1)
312
+ ]),
313
+ _: 1
314
+ }))
315
+ ])
316
+ ]),
317
+ _: 3
318
+ }, 16, ["onClick"])
319
+ ]),
320
+ _: 2
321
+ }, 1032, ["text"])) : j("", !0),
322
+ e.showEditButton ? (p(), x(L, {
323
+ key: 1,
324
+ text: e.editButtonText
325
+ }, {
326
+ activator: o(({ props: u }) => [
327
+ c(D, $({
328
+ icon: "",
329
+ flat: "",
330
+ onClick: (S) => K(n)
331
+ }, u), {
332
+ default: o(() => [
333
+ h(t.$slots, "edit-icon", {}, () => [
334
+ v(b.value) ? (p(), x(N(b.value), $({
335
+ key: 0,
336
+ size: 20,
337
+ class: "text-primary"
338
+ }, B.value), null, 16)) : (p(), x(I, {
339
+ key: 1,
340
+ size: "20",
341
+ class: "text-primary"
342
+ }, {
343
+ default: o(() => [
344
+ C(T(b.value), 1)
345
+ ]),
346
+ _: 1
347
+ }))
348
+ ])
349
+ ]),
350
+ _: 3
351
+ }, 16, ["onClick"])
352
+ ]),
353
+ _: 2
354
+ }, 1032, ["text"])) : j("", !0),
355
+ e.showDeleteButton ? (p(), x(L, {
356
+ key: 2,
357
+ text: e.deleteButtonText
358
+ }, {
359
+ activator: o(({ props: u }) => [
360
+ c(D, $({
361
+ icon: "",
362
+ flat: "",
363
+ onClick: (S) => _(n)
364
+ }, u), {
365
+ default: o(() => [
366
+ h(t.$slots, "delete-icon", {}, () => [
367
+ v(a.value) ? (p(), x(N(a.value), $({
368
+ key: 0,
369
+ size: 20,
370
+ class: "text-error"
371
+ }, B.value), null, 16)) : (p(), x(I, {
372
+ key: 1,
373
+ size: "20",
374
+ class: "text-error"
375
+ }, {
376
+ default: o(() => [
377
+ C(T(a.value), 1)
378
+ ]),
379
+ _: 1
380
+ }))
381
+ ])
382
+ ]),
383
+ _: 3
384
+ }, 16, ["onClick"])
385
+ ]),
386
+ _: 2
387
+ }, 1032, ["text"])) : j("", !0),
388
+ h(t.$slots, "after-actions", { item: n })
389
+ ]),
390
+ tfoot: o(() => [
391
+ ae("tfoot", null, [
392
+ h(t.$slots, "item.tfoot")
393
+ ])
394
+ ]),
395
+ _: 2
396
+ }, [
397
+ le(R.value, (n) => ({
398
+ name: `item.${n.key}`,
399
+ fn: o(({ item: u }) => [
400
+ h(t.$slots, `item.${n.key}`, { item: u }, () => [
401
+ C(T(u[n.key]), 1)
402
+ ])
403
+ ])
404
+ }))
405
+ ]), 1032, ["headers", "items", "loading", "items-length", "items-per-page", "search", "sort-by", "page", "item-value", "show-expand", "class"]),
406
+ c(de, {
407
+ show: P.value,
408
+ title: e.deleteModalTitle,
409
+ description: e.deleteModalMessage,
410
+ confirmButtonText: e.deleteModalConfirmButtonText,
411
+ cancelButtonText: e.deleteModalCancelButtonText,
412
+ onClose: G,
413
+ onConfirm: H
414
+ }, null, 8, ["show", "title", "description", "confirmButtonText", "cancelButtonText"])
415
+ ], 64);
416
+ };
417
+ }
418
+ }), pe = {
419
+ install(e) {
420
+ e.component("DataTable", ue);
421
+ }
422
+ };
423
+ export {
424
+ U as DATA_TABLE_CONFIG_KEY,
425
+ ue as DataTable,
426
+ ve as createDataTableConfig,
427
+ pe as default
428
+ };
@@ -0,0 +1 @@
1
+ (function(g,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(g=typeof globalThis<"u"?globalThis:g||self,e(g.VuetifyDatatable={},g.Vue))})(this,(function(g,e){"use strict";function $(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var D={exports:{}},S;function M(){if(S)return D.exports;S=1;function t(C,i=100,m={}){if(typeof C!="function")throw new TypeError(`Expected the first parameter to be a function, got \`${typeof C}\`.`);if(i<0)throw new RangeError("`wait` must not be negative.");const{immediate:c}=typeof m=="boolean"?{immediate:m}:m;let f,h,a,u,p;function s(){const x=f,y=h;return f=void 0,h=void 0,p=C.apply(x,y),p}function w(){const x=Date.now()-u;x<i&&x>=0?a=setTimeout(w,i-x):(a=void 0,c||(p=s()))}const l=function(...x){if(f&&this!==f&&Object.getPrototypeOf(this)===Object.getPrototypeOf(f))throw new Error("Debounced method called with different contexts of the same prototype.");f=this,h=x,u=Date.now();const y=c&&!a;return a||(a=setTimeout(w,i)),y&&(p=s()),p};return Object.defineProperty(l,"isPending",{get(){return a!==void 0}}),l.clear=()=>{a&&(clearTimeout(a),a=void 0)},l.flush=()=>{a&&l.trigger()},l.trigger=()=>{p=s(),l.clear()},l}return D.exports.debounce=t,D.exports=t,D.exports}var E=M();const O=$(E),j=e.defineComponent({__name:"ConfirmationModal",props:{show:Boolean,title:String,description:String,confirmButtonText:String,cancelButtonText:String},emits:["close","confirm"],setup(t){const C=t,i=e.computed({get:()=>C.show,set:()=>{}});return(m,c)=>{const f=e.resolveComponent("v-card-title"),h=e.resolveComponent("v-card-text"),a=e.resolveComponent("v-spacer"),u=e.resolveComponent("v-btn"),p=e.resolveComponent("v-card-actions"),s=e.resolveComponent("v-card"),w=e.resolveComponent("v-dialog");return e.openBlock(),e.createBlock(w,{modelValue:i.value,"onUpdate:modelValue":c[2]||(c[2]=l=>i.value=l),"max-width":"500px",persistent:"","no-click-animation":""},{default:e.withCtx(()=>[e.createVNode(s,null,{default:e.withCtx(()=>[e.createVNode(f,{class:"text-h5 text-center py-6"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(t.title),1)]),_:1}),t.description?(e.openBlock(),e.createBlock(h,{key:0,class:"text-center px-0 py-0"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(t.description)+" ",1),e.renderSlot(m.$slots,"description")]),_:3})):e.createCommentVNode("",!0),e.createVNode(p,null,{default:e.withCtx(()=>[e.createVNode(a),e.createVNode(u,{color:"error",variant:"flat",dark:"",onClick:c[0]||(c[0]=l=>m.$emit("close"))},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(t.cancelButtonText),1)]),_:1}),e.createVNode(u,{color:"success",variant:"flat",dark:"",onClick:c[1]||(c[1]=l=>m.$emit("confirm"))},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(t.confirmButtonText),1)]),_:1}),e.createVNode(a)]),_:1})]),_:3})]),_:3},8,["modelValue"])}}}),V=Symbol("DataTableConfig");function A(t){return{install(C){C.provide(V,t)}}}const N=e.defineComponent({__name:"DataTable",props:{tableClass:{default:"border rounded-md mt-5"},headers:{default:()=>[]},items:{default:()=>[]},loading:{type:Boolean,default:!1},itemValue:{default:"id"},totalItems:{default:0},itemsPerPage:{default:10},search:{},showExpand:{type:Boolean,default:!1},showEditButton:{type:Boolean,default:!0},showDeleteButton:{type:Boolean,default:!0},showViewButton:{type:Boolean,default:!1},viewButtonText:{},deleteButtonText:{},deleteModalTitle:{},deleteModalMessage:{},deleteModalConfirmButtonText:{},deleteModalCancelButtonText:{},editButtonText:{},viewIcon:{},editIcon:{},deleteIcon:{}},emits:["onLoadData","editItem","deleteItem","viewItem"],setup(t,{emit:C}){const i=t,m=C,c=e.inject(V,{icons:{}}),f=e.computed(()=>{var o;return i.viewIcon??((o=c.icons)==null?void 0:o.view)??"mdi-eye-outline"}),h=e.computed(()=>{var o;return i.editIcon??((o=c.icons)==null?void 0:o.edit)??"mdi-pencil-outline"}),a=e.computed(()=>{var o;return i.deleteIcon??((o=c.icons)==null?void 0:o.delete)??"mdi-trash-can-outline"}),u=e.computed(()=>c.iconProps??{});function p(o){return typeof o!="string"}const s=e.ref(i.itemsPerPage),w=e.ref([]),l=e.ref(1),x=e.ref(null),y=e.ref(!1),L=e.computed(()=>{var o;return((o=i.headers)==null?void 0:o.filter(r=>r.key!=="actions"&&r.key!=="expanded-row"&&r.key!=="data-table-expand"))||[]});e.onMounted(()=>{T({page:l.value,itemsPerPage:s.value})});const _=o=>{x.value=o,y.value=!0},F=()=>{x.value=null,y.value=!1},q=o=>{m("editItem",o)},U=o=>{m("viewItem",o)},R=()=>{m("deleteItem",x.value),y.value=!1},T=({page:o,itemsPerPage:r})=>{const k=w.value.map(B=>({column:B.key,direction:B.order}));m("onLoadData",{page:o,itemsPerPage:r,search:i.search,sortBy:k})};function G(){T({page:1,itemsPerPage:s.value})}const I=O(G,400),K=()=>{I()};return e.watch(()=>i.search,(o,r)=>{o!==r&&I()}),e.watch(s,(o,r)=>{o!==r&&T({page:1,itemsPerPage:o})}),e.watch(w,()=>{T({page:1,itemsPerPage:s.value})}),e.watch(l,o=>{T({page:o,itemsPerPage:s.value})}),(o,r)=>{const k=e.resolveComponent("v-icon"),B=e.resolveComponent("v-btn"),P=e.resolveComponent("v-tooltip"),Y=e.resolveComponent("v-data-table-server");return e.openBlock(),e.createElementBlock(e.Fragment,null,[e.createVNode(Y,{headers:t.headers,items:t.items,loading:t.loading,"items-length":t.totalItems,"items-per-page":s.value,"onUpdate:itemsPerPage":r[0]||(r[0]=n=>s.value=n),search:t.search,onSearch:K,"sort-by":w.value,"onUpdate:sortBy":r[1]||(r[1]=n=>w.value=n),page:l.value,"onUpdate:page":r[2]||(r[2]=n=>l.value=n),"item-value":t.itemValue,"show-expand":t.showExpand,class:e.normalizeClass(t.tableClass)},e.createSlots({"item.data-table-expand":e.withCtx(({internalItem:n,isExpanded:d,toggleExpand:b})=>[e.renderSlot(o.$slots,"item.data-table-expand",{internalItem:n,isExpanded:d,toggleExpand:b},()=>[e.createVNode(B,{onClick:H=>b(n),rounded:""},{default:e.withCtx(()=>[e.createVNode(k,null,{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(d(n)?"mdi-chevron-up":"mdi-chevron-down"),1)]),_:2},1024)]),_:2},1032,["onClick"])])]),"expanded-row":e.withCtx(({columns:n,item:d})=>[e.renderSlot(o.$slots,"expanded-row",{columns:n,item:d})]),"item.actions":e.withCtx(({item:n})=>[e.renderSlot(o.$slots,"before-actions",{item:n}),t.showViewButton?(e.openBlock(),e.createBlock(P,{key:0,text:t.viewButtonText},{activator:e.withCtx(({props:d})=>[e.createVNode(B,e.mergeProps({icon:"",flat:"",onClick:b=>U(n)},d),{default:e.withCtx(()=>[e.renderSlot(o.$slots,"view-icon",{},()=>[p(f.value)?(e.openBlock(),e.createBlock(e.resolveDynamicComponent(f.value),e.mergeProps({key:0,size:20,class:"text-info"},u.value),null,16)):(e.openBlock(),e.createBlock(k,{key:1,size:"20",class:"text-info"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(f.value),1)]),_:1}))])]),_:3},16,["onClick"])]),_:2},1032,["text"])):e.createCommentVNode("",!0),t.showEditButton?(e.openBlock(),e.createBlock(P,{key:1,text:t.editButtonText},{activator:e.withCtx(({props:d})=>[e.createVNode(B,e.mergeProps({icon:"",flat:"",onClick:b=>q(n)},d),{default:e.withCtx(()=>[e.renderSlot(o.$slots,"edit-icon",{},()=>[p(h.value)?(e.openBlock(),e.createBlock(e.resolveDynamicComponent(h.value),e.mergeProps({key:0,size:20,class:"text-primary"},u.value),null,16)):(e.openBlock(),e.createBlock(k,{key:1,size:"20",class:"text-primary"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(h.value),1)]),_:1}))])]),_:3},16,["onClick"])]),_:2},1032,["text"])):e.createCommentVNode("",!0),t.showDeleteButton?(e.openBlock(),e.createBlock(P,{key:2,text:t.deleteButtonText},{activator:e.withCtx(({props:d})=>[e.createVNode(B,e.mergeProps({icon:"",flat:"",onClick:b=>_(n)},d),{default:e.withCtx(()=>[e.renderSlot(o.$slots,"delete-icon",{},()=>[p(a.value)?(e.openBlock(),e.createBlock(e.resolveDynamicComponent(a.value),e.mergeProps({key:0,size:20,class:"text-error"},u.value),null,16)):(e.openBlock(),e.createBlock(k,{key:1,size:"20",class:"text-error"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(a.value),1)]),_:1}))])]),_:3},16,["onClick"])]),_:2},1032,["text"])):e.createCommentVNode("",!0),e.renderSlot(o.$slots,"after-actions",{item:n})]),tfoot:e.withCtx(()=>[e.createElementVNode("tfoot",null,[e.renderSlot(o.$slots,"item.tfoot")])]),_:2},[e.renderList(L.value,n=>({name:`item.${n.key}`,fn:e.withCtx(({item:d})=>[e.renderSlot(o.$slots,`item.${n.key}`,{item:d},()=>[e.createTextVNode(e.toDisplayString(d[n.key]),1)])])}))]),1032,["headers","items","loading","items-length","items-per-page","search","sort-by","page","item-value","show-expand","class"]),e.createVNode(j,{show:y.value,title:t.deleteModalTitle,description:t.deleteModalMessage,confirmButtonText:t.deleteModalConfirmButtonText,cancelButtonText:t.deleteModalCancelButtonText,onClose:F,onConfirm:R},null,8,["show","title","description","confirmButtonText","cancelButtonText"])],64)}}}),z={install(t){t.component("DataTable",N)}};g.DATA_TABLE_CONFIG_KEY=V,g.DataTable=N,g.createDataTableConfig=A,g.default=z,Object.defineProperties(g,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@dazzadev/vuetify-datatable",
3
+ "version": "1.0.0",
4
+ "description": "Reusable server-side DataTable component for Vuetify 3",
5
+ "type": "module",
6
+ "main": "./dist/vuetify-datatable.umd.cjs",
7
+ "module": "./dist/vuetify-datatable.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/vuetify-datatable.js",
13
+ "require": "./dist/vuetify-datatable.umd.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "vite build && vue-tsc --emitDeclarationOnly",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "peerDependencies": {
24
+ "vue": "^3.3.0",
25
+ "vuetify": "^3.0.0"
26
+ },
27
+ "dependencies": {
28
+ "debounce": "^2.0.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^25.5.2",
32
+ "@vitejs/plugin-vue": "^5.0.0",
33
+ "typescript": "~5.6.0",
34
+ "vite": "^6.0.0",
35
+ "vite-plugin-dts": "^4.0.0",
36
+ "vue": "^3.5.0",
37
+ "vue-tsc": "^2.0.0",
38
+ "vuetify": "^3.7.0"
39
+ },
40
+ "license": "MIT"
41
+ }