@bgottsch/d-naive 1.8.9

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.
@@ -0,0 +1,947 @@
1
+ <template>
2
+ <n-data-table
3
+ ref="originTable"
4
+ :data="items"
5
+ :columns="cols"
6
+ :pagination="page"
7
+ :row-class-name="getRowClass"
8
+ :row-props="rowProps"
9
+ style="height: '100%'"
10
+ :max-height="height"
11
+ :scroll-x="scrollX ? scrollX * columns.length : '100%'"
12
+ v-bind="$attrs"
13
+ @update:expanded-row-keys="expanded"
14
+ />
15
+ </template>
16
+
17
+ <script setup>
18
+ import { Icon } from "#components";
19
+ import {
20
+ NSpace,
21
+ NInput,
22
+ NButton,
23
+ NDatePicker,
24
+ NInputNumber,
25
+ NCheckbox,
26
+ NVirtualList,
27
+ createDiscreteApi,
28
+ NBadge
29
+ } from "naive-ui";
30
+ import { computed, ref, watch, useAttrs, h, toRaw, nextTick } from "vue";
31
+ import { formatValue, getValue, toDate } from "../utils";
32
+ import DInput from "./input.vue";
33
+ import { useThemeVars } from "naive-ui";
34
+ const themeVars = useThemeVars();
35
+ const { message, dialog } = createDiscreteApi(["message", "dialog"]);
36
+ const attrs = useAttrs();
37
+ const props = defineProps({
38
+ data: {
39
+ type: Array,
40
+ required: false,
41
+ default: () => []
42
+ },
43
+ columns: {
44
+ type: Array,
45
+ required: true
46
+ },
47
+ modelValue: {
48
+ required: false,
49
+ type: [Object, Number, String],
50
+ default: () => {
51
+ }
52
+ },
53
+ selectable: {
54
+ type: Boolean
55
+ },
56
+ pagination: {
57
+ type: [Object, Boolean],
58
+ required: false,
59
+ default: () => void 0
60
+ },
61
+ editable: {
62
+ type: Boolean,
63
+ required: false,
64
+ default: false
65
+ },
66
+ scrollX: {
67
+ type: [Number, String, Boolean],
68
+ required: false,
69
+ default: false
70
+ },
71
+ height: {
72
+ type: [String, Number],
73
+ default: "800px"
74
+ },
75
+ returnObject: { type: Boolean, required: false, default: false },
76
+ selectedClass: {
77
+ type: String,
78
+ default: "selectedRow"
79
+ },
80
+ sortable: { type: Boolean, required: false, default: true },
81
+ draggable: { type: Boolean, required: false, default: false },
82
+ resizable: { type: Boolean, required: false, default: true },
83
+ filterable: { type: Boolean, required: false, default: true }
84
+ });
85
+ const originTable = ref(null);
86
+ function resetFilters() {
87
+ sorterList.value = [];
88
+ cols.value.forEach((c) => {
89
+ if (c.filterOptionValue) c.filterOptionValue = null;
90
+ c.sortOrder = null;
91
+ });
92
+ }
93
+ function scrollTo(value) {
94
+ originTable.value.scrollTo(value);
95
+ }
96
+ function getData() {
97
+ return originTable.value.mainTableInstRef.bodyInstRef.rawPaginatedData;
98
+ }
99
+ const cols = ref([]);
100
+ let isDragging = null;
101
+ const sorterList = ref([]);
102
+ defineExpose({
103
+ sorterList,
104
+ resetFilters,
105
+ scrollTo,
106
+ getData,
107
+ cols
108
+ });
109
+ const universalSort = (a, b, sorter) => {
110
+ let v1 = getValue(a, sorter.key);
111
+ let v2 = getValue(b, sorter.key);
112
+ const order = sorter.order === "ascend" ? -1 : 1;
113
+ if (v1 === void 0 || v1 === null) v1 = "";
114
+ if (v2 === void 0 || v2 === null) v2 = "";
115
+ if (sorter.type === "number" || typeof v1 === "number") {
116
+ return (v1 - v2) * order;
117
+ } else if (["date", "datetime"].includes(sorter.type)) {
118
+ const date1 = toDate(v1);
119
+ const date2 = toDate(v2);
120
+ return sorter.order === "ascend" ? date1 - date2 : date2 - date1;
121
+ } else if (sorter.type == "bool") {
122
+ return (v1 === v2 ? 0 : v1 ? -1 : 1) * order;
123
+ } else
124
+ return sorter.order === "ascend" ? v1.localeCompare(v2) : v2.localeCompare(v1);
125
+ };
126
+ const items = computed(() => {
127
+ const temp = !props.data ? [] : props.data.map((item) => {
128
+ return { ...item };
129
+ });
130
+ const recursiveSort = (list, sorter) => {
131
+ list.sort((a, b) => {
132
+ return universalSort(a, b, sorter);
133
+ });
134
+ list.forEach((item) => {
135
+ if (item.children) recursiveSort(item.children, sorter);
136
+ });
137
+ };
138
+ sorterList.value.forEach((sorter) => {
139
+ recursiveSort(temp, sorter);
140
+ });
141
+ if (editedRow.value && editedIndex.value < 0) temp.unshift(editedRow.value);
142
+ return temp;
143
+ });
144
+ const page = computed(() => {
145
+ if (!props.pagination && props.pagination != false) {
146
+ return {
147
+ defaultPageSize: 15,
148
+ showSizePicker: true,
149
+ pageSizes: [10, 25, 50, items.value.length].sort((a, b) => a - b),
150
+ showQuickJumper: true,
151
+ disabled: props.editable && items.value.some((i) => i.editable)
152
+ };
153
+ }
154
+ return props.pagination;
155
+ });
156
+ const expandedKeys = ref([]);
157
+ const expanded = (data) => {
158
+ expandedKeys.value = data;
159
+ emit("update:expanded", data);
160
+ };
161
+ const selectedKey = ref(null);
162
+ const selectedItem = ref({});
163
+ const editedRow = ref(null);
164
+ const editedIndex = ref(null);
165
+ const emit = defineEmits([
166
+ "update:modelValue",
167
+ "update:expanded",
168
+ "put",
169
+ "delete",
170
+ "dragColumn"
171
+ ]);
172
+ window.addEventListener("mouseup", function() {
173
+ isDragging = null;
174
+ });
175
+ const rowProps = (rowData, rowIndex) => ({
176
+ onClick: () => {
177
+ if (props.selectable && rowData.selectable != false) {
178
+ let key = null;
179
+ if (attrs["row-key"]) {
180
+ key = attrs["row-key"](rowData);
181
+ } else {
182
+ key = rowIndex;
183
+ }
184
+ selectedItem.value = selectedKey.value == key ? null : rowData;
185
+ selectedKey.value = selectedKey.value == key ? null : key;
186
+ }
187
+ }
188
+ });
189
+ watch(
190
+ () => [...sorterList.value],
191
+ () => {
192
+ cols.value.forEach((field) => {
193
+ const sort = sorterList.value.find((s) => s.key == field.key);
194
+ if (sort) {
195
+ field.sortOrder = sort.order;
196
+ }
197
+ });
198
+ }
199
+ );
200
+ watch(selectedKey, (newValue) => {
201
+ if (!props.returnObject) emit("update:modelValue", newValue);
202
+ });
203
+ watch(
204
+ () => ({ ...selectedItem.value }),
205
+ () => {
206
+ if (props.returnObject) emit("update:modelValue", selectedItem.value);
207
+ },
208
+ { deep: true }
209
+ );
210
+ function getRowClass(rowData, index) {
211
+ let classes = "";
212
+ if (rowData.disabled) classes += " disabledRow ";
213
+ if (attrs["row-key"] && expandedKeys.value.indexOf(attrs["row-key"](rowData)) >= 0) {
214
+ classes += " font-weight-bold ";
215
+ }
216
+ if (!attrs["row-key"] && index == selectedKey.value || attrs["row-key"] && attrs["row-key"](rowData) == selectedKey.value) {
217
+ classes += " " + props.selectedClass + " ";
218
+ }
219
+ return classes;
220
+ }
221
+ const processColumns = () => {
222
+ const filters = {};
223
+ cols.value.forEach((c) => {
224
+ if (c.filterOptionValue) {
225
+ filters[c.key] = c.filterOptionValue;
226
+ }
227
+ });
228
+ const columns = ref(props.columns.map((c) => ({ ...c })));
229
+ columns.value.forEach((field) => {
230
+ if (props.sortable && field.sortable != false) field.sortable = true;
231
+ if (props.draggable && field.draggable != false) field.draggable = true;
232
+ if (field.type == "selection") field.sorter = void 0;
233
+ if (field.resizable != false) field.resizable = props.resizable;
234
+ field.defaultRender = field.render;
235
+ field.render = (row, index) => {
236
+ if (props.editable && (index == editedIndex.value || row.new) && (!field.pk || row.new) && !field.auto)
237
+ return h(DInput, {
238
+ modelValue: editedRow.value[field.key],
239
+ ...field,
240
+ disableLabel: true,
241
+ "onUpdate:modelValue": (value) => editedRow.value[field.key] = value
242
+ });
243
+ else if (field.defaultRender) return field.defaultRender(row, index);
244
+ else if (field.type == "bool") {
245
+ if (row[field.key] == true)
246
+ return h(Icon, {
247
+ style: `color: ${themeVars.value.successColor}`,
248
+ size: "18",
249
+ name: "gg:check-o"
250
+ });
251
+ else if (row[field.key] == false)
252
+ return h(Icon, {
253
+ style: `color: ${themeVars.value.errorColor}`,
254
+ size: "18",
255
+ name: "ion:ban-outline"
256
+ });
257
+ else
258
+ return h(Icon, {
259
+ style: `color: ${themeVars.value.warningColor}`,
260
+ size: "18",
261
+ name: "cil:warning"
262
+ });
263
+ }
264
+ return formatValue(row, field);
265
+ };
266
+ if (!field.filter && props.filterable && field.filter != false) {
267
+ if (field.type == "bool") {
268
+ field.filterOptionValue = [];
269
+ const options = {
270
+ true: { value: true, icon: "gg:check-o", color: themeVars.value.successColor },
271
+ false: { value: false, icon: "ion:ban-outline", color: themeVars.value.errorColor },
272
+ na: { value: null, icon: "cil:warning", color: themeVars.value.warningColor }
273
+ };
274
+ field.renderFilterMenu = ({ hide }) => {
275
+ return h(
276
+ NSpace,
277
+ { style: { padding: "12px" }, vertical: true },
278
+ {
279
+ default: () => [
280
+ ...Object.keys(options).map((key) => {
281
+ return h(
282
+ NCheckbox,
283
+ {
284
+ key,
285
+ value: key,
286
+ checked: field.filterOptionValue.includes(key),
287
+ onUpdateChecked: (value) => {
288
+ if (value) {
289
+ if (!field.filterOptionValue.includes(key))
290
+ field.filterOptionValue.push(key);
291
+ } else {
292
+ field.filterOptionValue.splice(
293
+ field.filterOptionValue.indexOf(key),
294
+ 1
295
+ );
296
+ }
297
+ if (field.onUpdateFilters)
298
+ field.onUpdateFilters(field.filterOptionValue);
299
+ }
300
+ },
301
+ {
302
+ default: () => h(Icon, {
303
+ name: options[key].icon,
304
+ style: `color:${options[key].color}; margin-bottom: -2.5px`
305
+ })
306
+ }
307
+ );
308
+ }),
309
+ h(
310
+ NSpace,
311
+ {},
312
+ {
313
+ default: () => [
314
+ h(
315
+ NButton,
316
+ {
317
+ size: "tiny",
318
+ onClick: () => {
319
+ field.filterOptionValue = [];
320
+ if (field.onUpdateFilters)
321
+ field.onUpdateFilters(field.filterOptionValue);
322
+ hide();
323
+ }
324
+ },
325
+ { default: () => "Clear" }
326
+ ),
327
+ h(
328
+ NButton,
329
+ {
330
+ size: "tiny",
331
+ type: "primary",
332
+ class: "text-white",
333
+ onClick: () => {
334
+ hide();
335
+ }
336
+ },
337
+ { default: () => "Ok" }
338
+ )
339
+ ]
340
+ }
341
+ )
342
+ ]
343
+ }
344
+ );
345
+ };
346
+ field.filter = (value, row) => {
347
+ const valBool = options[value].value;
348
+ return getValue(row, field) == valBool;
349
+ };
350
+ } else if (field.type == "select") {
351
+ let temp = field.options;
352
+ if (!temp)
353
+ temp = [...new Set(items.value.map((o) => getValue(o, field)))].sort().map((o) => {
354
+ return o ? {
355
+ label: typeof o === "string" ? o.charAt(0).toUpperCase() + o.slice(1) : "N/A",
356
+ value: o
357
+ } : {};
358
+ });
359
+ else if (temp.length > 0 && typeof temp[0] != "object")
360
+ temp = temp.map((t) => ({
361
+ label: t.charAt(0).toUpperCase() + t.slice(1),
362
+ value: t
363
+ }));
364
+ field.filterOptions = temp;
365
+ field.filter = (value, row) => {
366
+ return getValue(row, field) == value;
367
+ };
368
+ } else if (["date", "month", "year", "datetime"].indexOf(field.type) >= 0) {
369
+ field.filterOptionValue = null;
370
+ field.renderFilterIcon = () => {
371
+ return h(Icon, { name: "ph:calendar-duotone" });
372
+ };
373
+ field.filter = (value, row) => {
374
+ const v = getValue(row, field);
375
+ const d = toDate(v);
376
+ return !field.filterOptionValue || v && d >= toDate(field.filterOptionValue[0]) && d <= toDate(field.filterOptionValue[1]);
377
+ };
378
+ field.renderFilterMenu = ({ hide }) => {
379
+ return h(
380
+ NSpace,
381
+ { style: { padding: "12px" }, vertical: true },
382
+ {
383
+ default: () => [
384
+ h(NDatePicker, {
385
+ type: "daterange",
386
+ value: field.filterOptionValue,
387
+ format: "dd/MM/yyyy",
388
+ style: { color: "white" },
389
+ clearable: true,
390
+ onConfirm: ([min, max]) => {
391
+ field.filterOptionValue = [min, max];
392
+ if (field.onUpdateFilters)
393
+ field.onUpdateFilters(field.filterOptionValue);
394
+ hide();
395
+ },
396
+ onClear: () => {
397
+ field.filterOptionValue = null;
398
+ if (field.onUpdateFilters)
399
+ field.onUpdateFilters(field.filterOptionValue);
400
+ hide();
401
+ }
402
+ }),
403
+ h(
404
+ NButton,
405
+ {
406
+ size: "tiny",
407
+ onClick: () => {
408
+ field.filterOptionValue = null;
409
+ if (field.onUpdateFilters)
410
+ field.onUpdateFilters(field.filterOptionValue);
411
+ hide();
412
+ }
413
+ },
414
+ { default: () => "Clear" }
415
+ )
416
+ ]
417
+ }
418
+ );
419
+ };
420
+ } else if (field.type == "number") {
421
+ field.filterOptionValue = null;
422
+ field.renderFilterIcon = () => {
423
+ return h(Icon, { name: "ic:outline-expand" });
424
+ };
425
+ field.filter = (value, row) => {
426
+ const v = getValue(row, field);
427
+ return !field.filterOptionValue || !field.filterOptionValue[0] | v >= field.filterOptionValue[0] && !field.filterOptionValue[1] | v <= field.filterOptionValue[1];
428
+ };
429
+ field.renderFilterMenu = ({ hide }) => {
430
+ return h(
431
+ NSpace,
432
+ { style: { padding: "12px" }, vertical: true },
433
+ {
434
+ default: () => [
435
+ h(NInputNumber, {
436
+ placeholder: "Min",
437
+ value: field.filterOptionValue ? field.filterOptionValue[0] : null,
438
+ onKeyup: (key) => {
439
+ if (key.code == "Enter") hide();
440
+ },
441
+ onUpdateValue: (text) => {
442
+ if (!field.filterOptionValue)
443
+ field.filterOptionValue = [null, null];
444
+ field.filterOptionValue[0] = text;
445
+ if (!field.filterOptionValue[0] && field.filterOptionValue[1])
446
+ field.filterOptionValue = null;
447
+ if (field.onUpdateFilters)
448
+ field.onUpdateFilters(field.filterOptionValue);
449
+ }
450
+ }),
451
+ h(NInputNumber, {
452
+ placeholder: "Max",
453
+ value: field.filterOptionValue ? field.filterOptionValue[1] : null,
454
+ onKeyup: (key) => {
455
+ if (key.code == "Enter") hide();
456
+ },
457
+ onUpdateValue: (text) => {
458
+ if (!field.filterOptionValue)
459
+ field.filterOptionValue = [null, null];
460
+ field.filterOptionValue[1] = text;
461
+ if (!field.filterOptionValue[0] && field.filterOptionValue[1])
462
+ field.filterOptionValue = null;
463
+ if (field.onUpdateFilters)
464
+ field.onUpdateFilters(field.filterOptionValue);
465
+ }
466
+ }),
467
+ h(
468
+ NSpace,
469
+ {},
470
+ {
471
+ default: () => [
472
+ h(
473
+ NButton,
474
+ {
475
+ size: "tiny",
476
+ onClick: () => {
477
+ field.filterOptionValue = null;
478
+ if (field.onUpdateFilters)
479
+ field.onUpdateFilters(field.filterOptionValue);
480
+ hide();
481
+ }
482
+ },
483
+ { default: () => "Clear" }
484
+ ),
485
+ h(
486
+ NButton,
487
+ {
488
+ size: "tiny",
489
+ type: "primary",
490
+ class: "text-white",
491
+ onClick: () => {
492
+ hide();
493
+ }
494
+ },
495
+ { default: () => "Ok" }
496
+ )
497
+ ]
498
+ }
499
+ )
500
+ ]
501
+ }
502
+ );
503
+ };
504
+ } else if (field.type == "list") {
505
+ field.sortable = false;
506
+ } else {
507
+ field.filterOptionValue = null;
508
+ field.filterMutilple = true;
509
+ field.renderFilterIcon = () => {
510
+ return h(Icon, { name: "iconamoon:search" });
511
+ };
512
+ field.filterMode = "and";
513
+ field.filter = (value, row) => {
514
+ let v = getValue(row, field);
515
+ if (v === void 0 || v === null || v == "") v = "(blank)";
516
+ const f = field.filterOptionValue;
517
+ return !f || (!f.search || !field.filterOptions?.length > 0 || v?.toLowerCase().includes(f.search.toLowerCase())) && (!f.options.length > 0 || f.options.includes(v));
518
+ };
519
+ let options = [
520
+ ...new Set(items.value.map((o) => getValue(o, field)))
521
+ ].sort((a, b) => universalSort(a, b, { key: field.key, order: "ascend" }));
522
+ if (options.some((o) => o == void 0 || o == null || o == ""))
523
+ options.unshift("(blank)");
524
+ options = options.filter((o) => o);
525
+ const getOptions = (value) => options.filter((o) => {
526
+ let temp = o;
527
+ if (temp === void 0 || temp === null || temp == "")
528
+ temp = "(blank)";
529
+ return !value || !temp || temp.toLowerCase().includes(value.toLowerCase());
530
+ });
531
+ field.setFilter = (text) => {
532
+ field.filterOptions = getOptions(text);
533
+ field.filterOptionValue = {
534
+ search: text,
535
+ options: field.filterOptionValue?.options || []
536
+ };
537
+ if (!text && !field.filterOptionValue?.options.length > 0)
538
+ field.filterOptionValue = null;
539
+ };
540
+ field.filterOptions = getOptions(null);
541
+ field.renderFilterMenu = ({ hide }) => {
542
+ const inputRef = ref(null);
543
+ nextTick(() => {
544
+ if (inputRef.value) {
545
+ inputRef.value.focus();
546
+ }
547
+ });
548
+ return h(
549
+ NSpace,
550
+ { style: { padding: "12px" }, vertical: true, autoFocus: true },
551
+ {
552
+ default: () => [
553
+ h(NInput, {
554
+ ref: inputRef,
555
+ placeholder: "",
556
+ autofocus: true,
557
+ value: field.filterOptionValue?.search,
558
+ onKeyup: (key) => {
559
+ if (key.code == "Enter" || key.code == "Escape") hide();
560
+ },
561
+ onInput: (text) => {
562
+ field.setFilter(text);
563
+ if (field.onUpdateFilters)
564
+ field.onUpdateFilters(field.filterOptionValue);
565
+ }
566
+ }),
567
+ h(
568
+ NVirtualList,
569
+ {
570
+ items: field.filterOptions,
571
+ style: { maxHeight: "200px", maxWidth: "200px" },
572
+ itemSize: 24,
573
+ itemResizable: false
574
+ },
575
+ {
576
+ default: ({ item }) => {
577
+ return h(NCheckbox, {
578
+ key: item,
579
+ label: item,
580
+ value: item,
581
+ style: { width: "100%" },
582
+ checked: field.filterOptionValue && field.filterOptionValue.options.indexOf(item) >= 0,
583
+ onUpdateChecked: (value) => {
584
+ if (value) {
585
+ if (!field.filterOptionValue)
586
+ field.filterOptionValue = {
587
+ search: null,
588
+ options: []
589
+ };
590
+ field.filterOptionValue.options.push(item);
591
+ } else {
592
+ field.filterOptionValue.options.splice(
593
+ field.filterOptionValue.options.indexOf(item),
594
+ 1
595
+ );
596
+ if (!field.filterOptionValue?.search && !field.filterOptionValue?.options.length > 0)
597
+ field.filterOptionValue = null;
598
+ }
599
+ if (field.onUpdateFilters)
600
+ field.onUpdateFilters(field.filterOptionValue);
601
+ }
602
+ });
603
+ }
604
+ }
605
+ ),
606
+ h(
607
+ NSpace,
608
+ {},
609
+ {
610
+ default: () => [
611
+ h(
612
+ NButton,
613
+ {
614
+ size: "tiny",
615
+ onClick: () => {
616
+ field.filterOptionValue = null;
617
+ field.filterOptions = getOptions();
618
+ if (field.onUpdateFilters)
619
+ field.onUpdateFilters(field.filterOptionValue);
620
+ hide();
621
+ }
622
+ },
623
+ { default: () => "Clear" }
624
+ ),
625
+ h(
626
+ NButton,
627
+ {
628
+ size: "tiny",
629
+ onClick: () => {
630
+ if (!field.filterOptionValue)
631
+ field.filterOptionValue = {
632
+ search: null,
633
+ options: []
634
+ };
635
+ field.filterOptionValue.options = getOptions();
636
+ if (field.onUpdateFilters)
637
+ field.onUpdateFilters(field.filterOptionValue);
638
+ }
639
+ },
640
+ { default: () => "All" }
641
+ ),
642
+ h(
643
+ NButton,
644
+ {
645
+ size: "tiny",
646
+ type: "primary",
647
+ class: "text-white",
648
+ onClick: () => {
649
+ hide();
650
+ }
651
+ },
652
+ { default: () => "Ok" }
653
+ )
654
+ ]
655
+ }
656
+ )
657
+ ]
658
+ }
659
+ );
660
+ };
661
+ }
662
+ }
663
+ const sort = sorterList.value.find((s) => s.key == field.key);
664
+ if (sort) {
665
+ field.sortOrder = sort.order;
666
+ }
667
+ field.label = field.title;
668
+ field.title = () => {
669
+ return h(
670
+ NSpace,
671
+ {
672
+ style: field.draggable ? "user-select:none; cursor: pointer;" : "width: 100%; overflow: unset",
673
+ wrap: false,
674
+ justify: field.align == "center" ? "center" : "space-between",
675
+ align: "center",
676
+ onMousedown: () => {
677
+ if (field.draggable) isDragging = field.key;
678
+ },
679
+ onMouseup: () => {
680
+ if (field.draggable) isDragging = null;
681
+ },
682
+ onMouseover: () => {
683
+ if (props.draggable && isDragging && isDragging != field.key) {
684
+ const dragging = cols.value.findIndex((c) => c.key == isDragging);
685
+ const target = cols.value.findIndex((c) => c.key == field.key);
686
+ const draggedItem = cols.value.splice(dragging, 1)[0];
687
+ cols.value.splice(target, 0, draggedItem);
688
+ emit("dragColumn", cols.value);
689
+ }
690
+ }
691
+ },
692
+ {
693
+ default: () => [
694
+ h(
695
+ "div",
696
+ field.label instanceof Function ? field.label() : field.label
697
+ ),
698
+ field.sortable ? h(
699
+ NBadge,
700
+ {
701
+ style: "height: 10px; font-size: 10px;",
702
+ color: "grey",
703
+ offset: [0, -10],
704
+ value: field.sortOrder ? sorterList.value.length - sorterList.value.findIndex((s) => s.key == field.key) : 0
705
+ },
706
+ {
707
+ default: () => [
708
+ h(
709
+ NButton,
710
+ {
711
+ circle: true,
712
+ text: true,
713
+ size: "tiny",
714
+ onClick: () => {
715
+ if (!field.sortOrder) field.sortOrder = "ascend";
716
+ else if (field.sortOrder === "ascend")
717
+ field.sortOrder = "descend";
718
+ else if (field.sortOrder === "descend")
719
+ field.sortOrder = false;
720
+ if (field.sortOrder) {
721
+ const item = sorterList.value.find(
722
+ (s) => s.key == field.key
723
+ );
724
+ if (item) item.order = field.sortOrder;
725
+ else
726
+ sorterList.value.unshift({
727
+ key: field.key,
728
+ order: field.sortOrder,
729
+ type: field.type
730
+ });
731
+ } else
732
+ sorterList.value = sorterList.value.filter(
733
+ (s) => s.key != field.key
734
+ );
735
+ }
736
+ },
737
+ {
738
+ icon: () => h(Icon, {
739
+ name: "bi:arrow-down",
740
+ style: `color:${field.sortOrder ? themeVars.value.primaryColor : "grey"}; ${field.sortOrder === "descend" ? "transform: rotate(180deg);" : ""} `
741
+ })
742
+ }
743
+ )
744
+ ]
745
+ }
746
+ ) : null
747
+ ]
748
+ }
749
+ );
750
+ };
751
+ if (field.setFilter && filters[field.key]?.search) {
752
+ field.setFilter(filters[field.key].search);
753
+ }
754
+ if (filters[field.key]) field.filterOptionValue = filters[field.key];
755
+ });
756
+ if (props.editable) {
757
+ const col = {
758
+ key: "actions",
759
+ filter: false,
760
+ width: "140px",
761
+ title: () => {
762
+ return h(
763
+ NButton,
764
+ {
765
+ circle: true,
766
+ strong: true,
767
+ tertiary: true,
768
+ type: "success",
769
+ onClick: () => {
770
+ editedRow.value = { new: true };
771
+ editedIndex.value = -1;
772
+ }
773
+ },
774
+ {
775
+ icon: () => h(Icon, {
776
+ name: "mingcute:add-fill",
777
+ style: `color: ${themeVars.value.successColor}`
778
+ })
779
+ }
780
+ );
781
+ },
782
+ render: (row, index) => {
783
+ return editedIndex.value == index || row.new ? h(
784
+ NSpace,
785
+ { wrap: false },
786
+ {
787
+ default: () => [
788
+ h(
789
+ NButton,
790
+ {
791
+ circle: true,
792
+ strong: true,
793
+ tertiary: true,
794
+ type: "success",
795
+ onClick: () => {
796
+ dialog.warning({
797
+ title: `Confirma\xE7\xE3o de ${row.new ? "Inclus\xE3o" : "Altera\xE7\xE3o"}`,
798
+ content: `Tem certeza que deseja efetuar ${row.new ? "a Inclus\xE3o" : "as altera\xE7\xF5es"}?`,
799
+ positiveText: "SIM",
800
+ negativeText: "N\xC3O",
801
+ onPositiveClick: () => {
802
+ message.success(
803
+ `Item ${row.new ? "incluido" : "alterado"} com sucesso`
804
+ );
805
+ emit("put", editedRow.value);
806
+ editedIndex.value = null;
807
+ editedRow.value = -1;
808
+ }
809
+ });
810
+ }
811
+ },
812
+ {
813
+ icon: () => h(Icon, {
814
+ name: "mdi:success-bold",
815
+ style: `color: ${themeVars.value.successColor}`,
816
+ size: "22"
817
+ })
818
+ }
819
+ ),
820
+ h(
821
+ NButton,
822
+ {
823
+ circle: true,
824
+ strong: true,
825
+ tertiary: true,
826
+ type: "warning",
827
+ onClick: () => {
828
+ editedIndex.value = -1;
829
+ editedRow.value = null;
830
+ },
831
+ class: "mx-n2"
832
+ },
833
+ {
834
+ icon: () => h(Icon, {
835
+ name: "mdi:cancel-bold",
836
+ style: themeVars.value.warningColor,
837
+ size: "22"
838
+ })
839
+ }
840
+ ),
841
+ h(
842
+ NButton,
843
+ {
844
+ circle: true,
845
+ strong: true,
846
+ tertiary: true,
847
+ type: "error",
848
+ onClick: () => {
849
+ dialog.error({
850
+ title: "Confirma\xE7\xE3o de Exclus\xE3o",
851
+ content: "Tem certeza que deseja deletar este item?",
852
+ positiveText: "SIM",
853
+ negativeText: "N\xC3O",
854
+ onPositiveClick: () => {
855
+ message.success("Item removido com sucesso");
856
+ emit("delete", editedRow.value);
857
+ editedIndex.value = -1;
858
+ editedRow.value = null;
859
+ }
860
+ });
861
+ }
862
+ },
863
+ {
864
+ icon: () => h(Icon, {
865
+ name: "ic:baseline-delete",
866
+ style: `color: ${themeVars.value.errorColor}`,
867
+ size: "22"
868
+ })
869
+ }
870
+ )
871
+ ]
872
+ }
873
+ ) : h(
874
+ NButton,
875
+ {
876
+ circle: true,
877
+ strong: true,
878
+ tertiary: true,
879
+ type: "info",
880
+ onClick: () => {
881
+ editedIndex.value = index;
882
+ editedRow.value = ref(toRaw(row)).value;
883
+ }
884
+ },
885
+ {
886
+ icon: () => h(Icon, {
887
+ name: "material-symbols:edit-outline",
888
+ style: "color:blue",
889
+ size: "20"
890
+ })
891
+ }
892
+ );
893
+ }
894
+ };
895
+ if (columns.value.some((f) => f.key == "actions")) columns.value.splice(-1);
896
+ columns.value.push(col);
897
+ }
898
+ cols.value = columns.value;
899
+ };
900
+ const mainTable = ref("");
901
+ processColumns();
902
+ watch(
903
+ () => props.columns,
904
+ () => processColumns()
905
+ );
906
+ watch(
907
+ () => props.modelValue,
908
+ (newValue) => {
909
+ if (!newValue) {
910
+ selectedItem.value = null;
911
+ selectedKey.value = null;
912
+ } else if (typeof newValue != "object" && selectedKey.value != newValue) {
913
+ selectedKey.value = newValue;
914
+ selectedItem.value = items.value.find(
915
+ (i, idx) => attrs["row-key"] ? attrs["row-key"](i) == newValue : idx == newValue
916
+ );
917
+ }
918
+ }
919
+ );
920
+ watch(
921
+ () => props.data,
922
+ (newValue) => {
923
+ processColumns();
924
+ if (selectedKey.value) {
925
+ const newSelect = newValue.find(
926
+ (i, idx) => attrs["row-key"] ? attrs["row-key"](i) == selectedKey.value : idx == selectedKey.value
927
+ );
928
+ if (newSelect) selectedItem.value = newSelect;
929
+ else {
930
+ selectedItem.value = null;
931
+ selectedKey.value = null;
932
+ }
933
+ }
934
+ if (newValue.length >= 0) {
935
+ if (mainTable.value) mainTable.value.page(1);
936
+ }
937
+ }
938
+ );
939
+ </script>
940
+
941
+ <style scoped>
942
+ :deep(.selectedRow td){background-color:rgba(33,43,89,.2)!important}:deep(.disabledRow td){color:red!important}:deep(.n-data-table-th__title .n-ellipsis){display:block!important;overflow:unset!important}
943
+ </style>
944
+
945
+ <style>
946
+ .n-date-panel-actions__suffix .n-button--primary-type{color:#fff!important}.n-data-table-filter-menu .n-button--primary-type{color:#fff}
947
+ </style>