edvoyui-component-library-test-flight 0.0.39 → 0.0.41
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/dist/library-vue-ts.cjs.js +24 -24
- package/dist/library-vue-ts.es.js +7195 -7191
- package/dist/library-vue-ts.umd.js +25 -25
- package/dist/table/EUIDashboardTable.vue.d.ts +1 -1
- package/dist/table/EUITable.vue.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/HelloWorld.vue +49 -1
- package/src/components/dropdown/EUIMultiDropdown.stories.ts +4 -4
- package/src/components/table/EUIDashboardTable.vue +43 -54
- package/src/components/table/EUITable.vue +45 -55
- package/src/components/table/EUITableCheckbox.vue +41 -17
- package/src/components/table/UCheckbox.vue +167 -0
- package/src/components/table/UTable.vue +489 -0
- package/src/components/table/UTableview.vue +85 -0
- package/src/components/telephone/EUITelephone.vue +0 -1
- package/src/utils/helpers.ts +30 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from "/Volumes/work/repos/edvoy-ui-v2/src/components/table/EUIDashboardTable.vue?vue&type=script&setup=true&lang.ts";
|
|
2
|
-
import "/Volumes/work/repos/edvoy-ui-v2/src/components/table/EUIDashboardTable.vue?vue&type=style&index=0&scoped=
|
|
2
|
+
import "/Volumes/work/repos/edvoy-ui-v2/src/components/table/EUIDashboardTable.vue?vue&type=style&index=0&scoped=473ceac4&lang.scss";
|
|
3
3
|
declare const _default: any;
|
|
4
4
|
export default _default;
|
|
5
5
|
//# sourceMappingURL=EUIDashboardTable.vue.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from "/Volumes/work/repos/edvoy-ui-v2/src/components/table/EUITable.vue?vue&type=script&setup=true&lang.ts";
|
|
2
|
-
import "/Volumes/work/repos/edvoy-ui-v2/src/components/table/EUITable.vue?vue&type=style&index=0&scoped=
|
|
2
|
+
import "/Volumes/work/repos/edvoy-ui-v2/src/components/table/EUITable.vue?vue&type=style&index=0&scoped=e61ab458&lang.scss";
|
|
3
3
|
declare const _default: any;
|
|
4
4
|
export default _default;
|
|
5
5
|
//# sourceMappingURL=EUITable.vue.d.ts.map
|
package/package.json
CHANGED
|
@@ -2,16 +2,63 @@
|
|
|
2
2
|
<h1 class="my-10 text-2xl font-bold text-center text-gray-900 underline underline-offset-2 decoration-green-400 decoration-wavy">
|
|
3
3
|
Edvoy User Interface
|
|
4
4
|
</h1>
|
|
5
|
+
|
|
6
|
+
<UTableview />
|
|
5
7
|
</template>
|
|
6
8
|
<script setup lang="ts">
|
|
9
|
+
import UTableview from './table/UTableview.vue';
|
|
10
|
+
|
|
7
11
|
|
|
8
12
|
</script>
|
|
9
13
|
<style lang="scss"></style>
|
|
10
14
|
|
|
11
15
|
<!-- Development code here -->
|
|
12
|
-
<!--
|
|
16
|
+
<!-- <template>
|
|
13
17
|
<div class="h-[clac(100svh-64px)] w-full px-10 py-8 max-w-screen-xl mx-auto">
|
|
14
18
|
<h1 class="mb-2 font-semibold text-gray-900 tetx-lg">Edvoy UI Componnet</h1>
|
|
19
|
+
<div class="border border-red-400">
|
|
20
|
+
<pre class="text-[0.5rem] p-2 border border-gray-300 rounded-lg max-h-72 overflow-y-auto text-red-600">
|
|
21
|
+
{{ `Total Row:${selectedRows.length}` }}
|
|
22
|
+
{{ selectedRows.map(x => x?._id)}}
|
|
23
|
+
</pre>
|
|
24
|
+
|
|
25
|
+
<div class="py-4">
|
|
26
|
+
<EUITable
|
|
27
|
+
:checkable="true"
|
|
28
|
+
:table-loading="loading"
|
|
29
|
+
paginated
|
|
30
|
+
v-model:selectedRows.sync="selectedRows"
|
|
31
|
+
:checked-rows.sync="checkedRows"
|
|
32
|
+
backend-pagination
|
|
33
|
+
:per-page="10"
|
|
34
|
+
:headers="studentHeader"
|
|
35
|
+
:items="studentData"
|
|
36
|
+
:total="studentData.length"
|
|
37
|
+
:default-sort-direction="defaultSortOrder"
|
|
38
|
+
default-sort=""
|
|
39
|
+
:current-page="offset"
|
|
40
|
+
@changePage="onPageChange"
|
|
41
|
+
@sort="onSort"
|
|
42
|
+
@mouseenter="select"
|
|
43
|
+
@mouseleave="(selectedIndex = null), (selected = null)"
|
|
44
|
+
>
|
|
45
|
+
<template #[`item.firstName`]="{ row, rowIndex }">
|
|
46
|
+
<div class="space-y-0.5">
|
|
47
|
+
<div class="block text-sm font-medium leading-snug">
|
|
48
|
+
{{ capitalizeText(row?.firstName) + " " + capitalizeText(row?.lastName) }}
|
|
49
|
+
</div>
|
|
50
|
+
<div class="text-xs font-medium text-gray-900 leading-[normal]">
|
|
51
|
+
{{ row?.referenceId }}
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</template>
|
|
55
|
+
<template #[`item.activeUser`]="{ row, rowIndex }">
|
|
56
|
+
{{ row?.activeUser?.user?.firstName }}
|
|
57
|
+
{{ row?.activeUser?.user?.lastName }}
|
|
58
|
+
</template>
|
|
59
|
+
</EUITable>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
15
62
|
<Delete />
|
|
16
63
|
<div class="grid gap-4 sm:grid-cols-2 place-items-start">
|
|
17
64
|
<div
|
|
@@ -910,6 +957,7 @@ const form = reactive({
|
|
|
910
957
|
});
|
|
911
958
|
|
|
912
959
|
//TODO: Dashboard Table
|
|
960
|
+
const selectedRows = ref([])
|
|
913
961
|
const checkedRows = ref([]);
|
|
914
962
|
const defaultSortOrder = ref("asc");
|
|
915
963
|
const limit = ref(5);
|
|
@@ -50,12 +50,12 @@ const Template: StoryFn = (args) =>
|
|
|
50
50
|
defineComponent({
|
|
51
51
|
components: { EUIMultiDropdown, ChevronDownStroke },
|
|
52
52
|
setup() {
|
|
53
|
-
const handleMenuItem = (
|
|
54
|
-
console.log("Menu clicked:",
|
|
53
|
+
const handleMenuItem = (_item: any) => {
|
|
54
|
+
// console.log("Menu clicked:", _item);
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
const handleSubMenuItem = (
|
|
58
|
-
console.log("Submenu item clicked:",
|
|
57
|
+
const handleSubMenuItem = (_subItem: any) => {
|
|
58
|
+
// console.log("Submenu item clicked:", _subItem);
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
return { args, handleMenuItem, handleSubMenuItem };
|
|
@@ -177,6 +177,7 @@ import SortArrow from "../../assets/svg/SortArrow.vue";
|
|
|
177
177
|
import EUIPageLimit from "./EUIPageLimit.vue";
|
|
178
178
|
import { capitalizeText } from "../../utils/lodash";
|
|
179
179
|
import EUICircleLoader from "../loader/EUICircleLoader.vue";
|
|
180
|
+
import { indexOf, getValueByPath, defaultFilter } from "../../utils/helpers";
|
|
180
181
|
|
|
181
182
|
interface Header {
|
|
182
183
|
value: string;
|
|
@@ -232,7 +233,6 @@ const {
|
|
|
232
233
|
headers,
|
|
233
234
|
paginated,
|
|
234
235
|
isRowCheckable,
|
|
235
|
-
customIsChecked,
|
|
236
236
|
} = toRefs(props);
|
|
237
237
|
|
|
238
238
|
const currentSort = ref(defaultSort.value);
|
|
@@ -272,8 +272,8 @@ const computedItems = computed(() => {
|
|
|
272
272
|
return items;
|
|
273
273
|
});
|
|
274
274
|
|
|
275
|
-
const searchData = (
|
|
276
|
-
console.log(
|
|
275
|
+
const searchData = (_data:any) => {
|
|
276
|
+
// console.log(_data);
|
|
277
277
|
};
|
|
278
278
|
|
|
279
279
|
const sortClass = computed(() => (header: any) => {
|
|
@@ -295,13 +295,10 @@ const isIndeterminate = computed(() => {
|
|
|
295
295
|
});
|
|
296
296
|
|
|
297
297
|
const isAllChecked = computed(() => {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
return validVisibleData.every(
|
|
303
|
-
(row) => indexOf(newCheckedRows.value, row, customIsChecked.value) >= 0
|
|
304
|
-
);
|
|
298
|
+
return (
|
|
299
|
+
computedItems.value.length > 0 &&
|
|
300
|
+
computedItems.value.every(row => newCheckedRows.value.includes(row))
|
|
301
|
+
);
|
|
305
302
|
});
|
|
306
303
|
|
|
307
304
|
const isAllUncheckable = computed(() => {
|
|
@@ -311,35 +308,6 @@ const isAllUncheckable = computed(() => {
|
|
|
311
308
|
return validVisibleData.length === 0;
|
|
312
309
|
});
|
|
313
310
|
|
|
314
|
-
// methods
|
|
315
|
-
const defaultFilter = (value: any, search: any) => {
|
|
316
|
-
return value.toString().toLowerCase().includes(search);
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
const indexOf = (
|
|
320
|
-
array: any[],
|
|
321
|
-
obj: any,
|
|
322
|
-
fn: (item: any, obj: any) => boolean
|
|
323
|
-
): number => {
|
|
324
|
-
if (!array) return -1;
|
|
325
|
-
if (!fn || typeof fn !== "function") return array?.indexOf(obj);
|
|
326
|
-
for (let i = 0; i < array.length; i++) {
|
|
327
|
-
if (fn(array[i], obj)) {
|
|
328
|
-
return i;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
return -1;
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
const getValueByPath = (obj: any, path: string) => {
|
|
335
|
-
return path
|
|
336
|
-
.split(".")
|
|
337
|
-
.reduce(
|
|
338
|
-
(o: { [x: string]: any }, i: string | number) => (o ? o[i] : null),
|
|
339
|
-
obj
|
|
340
|
-
);
|
|
341
|
-
};
|
|
342
|
-
|
|
343
311
|
const emit = defineEmits([
|
|
344
312
|
"update:currentPage",
|
|
345
313
|
"changePage",
|
|
@@ -347,6 +315,7 @@ const emit = defineEmits([
|
|
|
347
315
|
"check",
|
|
348
316
|
"check-all",
|
|
349
317
|
"update:checkedRows",
|
|
318
|
+
"update:selectedRows",
|
|
350
319
|
"changeLimit",
|
|
351
320
|
"mouseenter",
|
|
352
321
|
"mouseleave",
|
|
@@ -374,24 +343,44 @@ const sortBy = (header: any, event: any) => {
|
|
|
374
343
|
emit("sort", currentSort.value, currentSortDir.value, event);
|
|
375
344
|
};
|
|
376
345
|
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
);
|
|
381
|
-
const allChecked = isAllChecked.value;
|
|
382
|
-
newCheckedRows.value = allChecked ? [] : allRowsCheckable.slice();
|
|
383
|
-
emit("check", newCheckedRows.value);
|
|
384
|
-
emit("check-all", newCheckedRows.value);
|
|
385
|
-
emit("update:checkedRows", newCheckedRows.value);
|
|
386
|
-
};
|
|
346
|
+
const isRowChecked = (row:any) => {
|
|
347
|
+
return indexOf(newCheckedRows.value, row) >= 0;
|
|
348
|
+
};
|
|
387
349
|
|
|
388
|
-
const
|
|
389
|
-
|
|
350
|
+
const removeCheckedRow = (row:any) => {
|
|
351
|
+
const index = indexOf(newCheckedRows.value, row);
|
|
352
|
+
if (index >= 0) {
|
|
353
|
+
newCheckedRows.value.splice(index, 1);
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
const checkAll = () => {
|
|
358
|
+
if (isAllChecked.value) {
|
|
359
|
+
// Uncheck all rows
|
|
360
|
+
newCheckedRows.value = []
|
|
361
|
+
} else {
|
|
362
|
+
// Check all rows
|
|
363
|
+
const rowsToCheck = computedItems.value.filter(
|
|
364
|
+
row => !newCheckedRows.value.includes(row)
|
|
365
|
+
);
|
|
366
|
+
newCheckedRows.value.push(...rowsToCheck);
|
|
367
|
+
}
|
|
368
|
+
emit('check', newCheckedRows.value);
|
|
369
|
+
emit("check-all", newCheckedRows.value);
|
|
370
|
+
emit("update:checkedRows", newCheckedRows.value);
|
|
371
|
+
emit("update:selectedRows", newCheckedRows.value);
|
|
390
372
|
};
|
|
391
373
|
|
|
392
|
-
const checkRow = (row: any,
|
|
393
|
-
|
|
394
|
-
|
|
374
|
+
const checkRow = (row: any, _rowIndex: number, _event:any) => {
|
|
375
|
+
const isChecked = newCheckedRows.value.includes(row);
|
|
376
|
+
if (_event && isChecked) {
|
|
377
|
+
removeCheckedRow(row);
|
|
378
|
+
} else {
|
|
379
|
+
newCheckedRows.value.push(row);
|
|
380
|
+
}
|
|
381
|
+
emit("check", newCheckedRows.value, row);
|
|
382
|
+
emit("update:checkedRows", newCheckedRows.value);
|
|
383
|
+
emit("update:selectedRows", newCheckedRows.value);
|
|
395
384
|
};
|
|
396
385
|
|
|
397
386
|
// watch
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
:indeterminate="isIndeterminate"
|
|
26
26
|
:disabled="isAllUncheckable"
|
|
27
27
|
class="flex justify-center mt-0"
|
|
28
|
-
@change="checkAll
|
|
28
|
+
@change="checkAll"
|
|
29
29
|
/>
|
|
30
30
|
</th>
|
|
31
31
|
</template>
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
<EUITableCheckbox
|
|
109
109
|
:disabled="!isRowCheckable(row)"
|
|
110
110
|
:checked="isRowChecked(row)"
|
|
111
|
-
@change="($event
|
|
111
|
+
@change.prevent.stop="($event) => checkRow(row, rowIndex, $event)"
|
|
112
112
|
/>
|
|
113
113
|
</td>
|
|
114
114
|
</template>
|
|
@@ -189,6 +189,7 @@ import EUIPageLimit from "./EUIPageLimit.vue";
|
|
|
189
189
|
import EUIStudentPagination from "./EUIStudentPagination.vue";
|
|
190
190
|
import { capitalizeText } from "../../utils/lodash";
|
|
191
191
|
import EUICircleLoader from "../loader/EUICircleLoader.vue";
|
|
192
|
+
import { indexOf, getValueByPath, defaultFilter } from "../../utils/helpers";
|
|
192
193
|
|
|
193
194
|
interface Header {
|
|
194
195
|
value: string;
|
|
@@ -241,7 +242,6 @@ const {
|
|
|
241
242
|
headers,
|
|
242
243
|
paginated,
|
|
243
244
|
isRowCheckable,
|
|
244
|
-
customIsChecked,
|
|
245
245
|
} = toRefs(props);
|
|
246
246
|
|
|
247
247
|
const currentSort = ref(defaultSort.value);
|
|
@@ -287,8 +287,8 @@ const computedItems = computed(() => {
|
|
|
287
287
|
});
|
|
288
288
|
|
|
289
289
|
|
|
290
|
-
const searchData = (
|
|
291
|
-
console.log(
|
|
290
|
+
const searchData = (_data:any) => {
|
|
291
|
+
// console.log(_data);
|
|
292
292
|
};
|
|
293
293
|
|
|
294
294
|
const isIndeterminate = computed(() => {
|
|
@@ -302,13 +302,10 @@ const isIndeterminate = computed(() => {
|
|
|
302
302
|
});
|
|
303
303
|
|
|
304
304
|
const isAllChecked = computed(() => {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
return validVisibleData.every(
|
|
310
|
-
(row) => indexOf(newCheckedRows.value, row, customIsChecked.value) >= 0
|
|
311
|
-
);
|
|
305
|
+
return (
|
|
306
|
+
computedItems.value.length > 0 &&
|
|
307
|
+
computedItems.value.every(row => newCheckedRows.value.includes(row))
|
|
308
|
+
);
|
|
312
309
|
});
|
|
313
310
|
|
|
314
311
|
const isAllUncheckable = computed(() => {
|
|
@@ -319,34 +316,6 @@ const isAllUncheckable = computed(() => {
|
|
|
319
316
|
});
|
|
320
317
|
|
|
321
318
|
// methods
|
|
322
|
-
const defaultFilter = (value:any, search:any) => {
|
|
323
|
-
return value.toString().toLowerCase().includes(search);
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
const indexOf = (
|
|
327
|
-
array: any[],
|
|
328
|
-
obj: any,
|
|
329
|
-
fn: (item: any, obj: any) => boolean
|
|
330
|
-
): number => {
|
|
331
|
-
if (!array) return -1;
|
|
332
|
-
if (!fn || typeof fn !== "function") return array?.indexOf(obj);
|
|
333
|
-
for (let i = 0; i < array.length; i++) {
|
|
334
|
-
if (fn(array[i], obj)) {
|
|
335
|
-
return i;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
return -1;
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
const getValueByPath = (obj: any, path: string) => {
|
|
342
|
-
return path
|
|
343
|
-
.split(".")
|
|
344
|
-
.reduce(
|
|
345
|
-
(o: { [x: string]: any }, i: string | number) => (o ? o[i] : null),
|
|
346
|
-
obj
|
|
347
|
-
);
|
|
348
|
-
};
|
|
349
|
-
|
|
350
319
|
const emit = defineEmits([
|
|
351
320
|
"update:currentPage",
|
|
352
321
|
"changePage",
|
|
@@ -354,6 +323,7 @@ const emit = defineEmits([
|
|
|
354
323
|
"check",
|
|
355
324
|
"check-all",
|
|
356
325
|
"update:checkedRows",
|
|
326
|
+
"update:selectedRows",
|
|
357
327
|
"changeLimit",
|
|
358
328
|
"mouseenter",
|
|
359
329
|
"mouseleave"
|
|
@@ -381,24 +351,44 @@ const sortBy = (header: any, event: any) => {
|
|
|
381
351
|
emit("sort", currentSort.value, currentSortDir.value, event);
|
|
382
352
|
};
|
|
383
353
|
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
);
|
|
388
|
-
const allChecked = isAllChecked.value;
|
|
389
|
-
newCheckedRows.value = allChecked ? [] : allRowsCheckable.slice();
|
|
390
|
-
emit("check", newCheckedRows.value);
|
|
391
|
-
emit("check-all", newCheckedRows.value);
|
|
392
|
-
emit("update:checkedRows", newCheckedRows.value);
|
|
393
|
-
};
|
|
354
|
+
const isRowChecked = (row:any) => {
|
|
355
|
+
return indexOf(newCheckedRows.value, row) >= 0;
|
|
356
|
+
};
|
|
394
357
|
|
|
395
|
-
const
|
|
396
|
-
|
|
358
|
+
const removeCheckedRow = (row:any) => {
|
|
359
|
+
const index = indexOf(newCheckedRows.value, row);
|
|
360
|
+
if (index >= 0) {
|
|
361
|
+
newCheckedRows.value.splice(index, 1);
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
const checkAll = () => {
|
|
366
|
+
if (isAllChecked.value) {
|
|
367
|
+
// Uncheck all rows
|
|
368
|
+
newCheckedRows.value = []
|
|
369
|
+
} else {
|
|
370
|
+
// Check all rows
|
|
371
|
+
const rowsToCheck = computedItems.value.filter(
|
|
372
|
+
row => !newCheckedRows.value.includes(row)
|
|
373
|
+
);
|
|
374
|
+
newCheckedRows.value.push(...rowsToCheck);
|
|
375
|
+
}
|
|
376
|
+
emit('check', newCheckedRows.value);
|
|
377
|
+
emit("check-all", newCheckedRows.value);
|
|
378
|
+
emit("update:checkedRows", newCheckedRows.value);
|
|
379
|
+
emit("update:selectedRows", newCheckedRows.value);
|
|
397
380
|
};
|
|
398
381
|
|
|
399
|
-
const checkRow = (row: any,
|
|
400
|
-
|
|
401
|
-
|
|
382
|
+
const checkRow = (row: any, _rowIndex: number, _event:any) => {
|
|
383
|
+
const isChecked = newCheckedRows.value.includes(row);
|
|
384
|
+
if (_event && isChecked) {
|
|
385
|
+
removeCheckedRow(row);
|
|
386
|
+
} else {
|
|
387
|
+
newCheckedRows.value.push(row);
|
|
388
|
+
}
|
|
389
|
+
emit("check", newCheckedRows.value, row);
|
|
390
|
+
emit("update:checkedRows", newCheckedRows.value);
|
|
391
|
+
emit("update:selectedRows", newCheckedRows.value);
|
|
402
392
|
};
|
|
403
393
|
|
|
404
394
|
// watch
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<label class="table-checkbox">
|
|
3
|
-
<input v-model="
|
|
3
|
+
<input v-model="selected" type="checkbox" :value="value" v-bind="mergedAttrs" @change="onChange" />
|
|
4
4
|
<span class="check-icon">
|
|
5
5
|
<svg
|
|
6
6
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -33,28 +33,52 @@ const props = defineProps({
|
|
|
33
33
|
default: null
|
|
34
34
|
}
|
|
35
35
|
})
|
|
36
|
-
const emit = defineEmits(['update:checked','change']);
|
|
37
|
-
const attrs = useAttrs();
|
|
38
36
|
|
|
39
|
-
const
|
|
37
|
+
const emit = defineEmits(['change', 'update:checked'])
|
|
38
|
+
const isIndeterminate = ref(props.indeterminate)
|
|
39
|
+
|
|
40
|
+
watch(() => props.indeterminate, (val) => {
|
|
41
|
+
isIndeterminate.value = val
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const selected = computed({
|
|
45
|
+
get() {
|
|
46
|
+
return props.checked
|
|
47
|
+
},
|
|
48
|
+
set(val) {
|
|
49
|
+
emit('update:checked', val)
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const onChange = (event: Event) => {
|
|
54
|
+
emit('change', event);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const isActive = computed(() => {
|
|
58
|
+
const modelIsArray = Array.isArray(props.checked) && props.checked.length !== 0
|
|
59
|
+
const sameValue = (element: any) => element === props.value
|
|
60
|
+
if (modelIsArray) {
|
|
61
|
+
return props.checked.some(sameValue)
|
|
62
|
+
}
|
|
63
|
+
return props.checked === true
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
const attrs = useAttrs()
|
|
67
|
+
const computedTabIndex = computed(() => (attrs.disabled ? -1 : 0))
|
|
68
|
+
|
|
40
69
|
const mergedAttrs = computed(() => ({
|
|
41
70
|
...attrs,
|
|
42
|
-
tabindex:
|
|
71
|
+
tabindex: computedTabIndex.value,
|
|
43
72
|
role: 'checkbox',
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
(newValue) => {
|
|
48
|
-
isChecked.value = newValue;
|
|
49
|
-
}
|
|
50
|
-
);
|
|
73
|
+
// "aria-checked": isIndeterminate.value ? "mixed" : isActive.value.toString(),
|
|
74
|
+
// "aria-disabled": attrs.disabled || undefined,
|
|
75
|
+
}))
|
|
51
76
|
|
|
52
|
-
|
|
53
|
-
if(
|
|
54
|
-
|
|
55
|
-
emit('change', isChecked.value)
|
|
77
|
+
watch(isActive, () => {
|
|
78
|
+
if (props.indeterminate) {
|
|
79
|
+
isIndeterminate.value = false
|
|
56
80
|
}
|
|
57
|
-
}
|
|
81
|
+
})
|
|
58
82
|
</script>
|
|
59
83
|
|
|
60
84
|
<style lang="scss">
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<label :class="classes">
|
|
3
|
+
<span class="text-[0.5rem] absolute z-20 top-0 text-gray-400">{{ selected }}</span>
|
|
4
|
+
<input
|
|
5
|
+
v-model="selected"
|
|
6
|
+
data-test="checkbox-toggle"
|
|
7
|
+
type="checkbox"
|
|
8
|
+
:value="value"
|
|
9
|
+
v-bind="attrs"
|
|
10
|
+
class="ui-checkbox__input"
|
|
11
|
+
/>
|
|
12
|
+
<span v-if="$slots.default || label" class="ui-checkbox__label">
|
|
13
|
+
<span v-if="label">
|
|
14
|
+
{{ label }}
|
|
15
|
+
</span>
|
|
16
|
+
<span v-if="$slots.default">
|
|
17
|
+
<slot />
|
|
18
|
+
</span>
|
|
19
|
+
</span>
|
|
20
|
+
</label>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script lang="ts">
|
|
24
|
+
import { computed, ref, watch } from "vue";
|
|
25
|
+
|
|
26
|
+
export default {
|
|
27
|
+
name: "UICheckbox",
|
|
28
|
+
inheritAttrs: false,
|
|
29
|
+
|
|
30
|
+
props: {
|
|
31
|
+
indeterminate: Boolean,
|
|
32
|
+
checked: {
|
|
33
|
+
type: Boolean,
|
|
34
|
+
default: false,
|
|
35
|
+
},
|
|
36
|
+
value: {
|
|
37
|
+
default: null,
|
|
38
|
+
},
|
|
39
|
+
label: {
|
|
40
|
+
type: String,
|
|
41
|
+
default: "",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
setup(props, { emit, attrs }) {
|
|
46
|
+
const isIndeterminate = ref(props.indeterminate);
|
|
47
|
+
const selected = computed({
|
|
48
|
+
get: () => props.checked,
|
|
49
|
+
set: (val) => emit("update:checked", val),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const isActive = computed(() => {
|
|
53
|
+
const modelIsArray = Array.isArray(props.checked) && props.checked.length !== 0;
|
|
54
|
+
const sameValue = (element:any) => element === props.value;
|
|
55
|
+
|
|
56
|
+
if (modelIsArray) {
|
|
57
|
+
return props.checked.some(sameValue);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return props.checked === true;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const classes = computed(() => ({
|
|
64
|
+
"ui-checkbox": true,
|
|
65
|
+
"ui-checkbox--indeterminate": isIndeterminate.value,
|
|
66
|
+
}));
|
|
67
|
+
|
|
68
|
+
const computedTabIndex = computed(() => (attrs.disabled ? -1 : 0));
|
|
69
|
+
|
|
70
|
+
const computedAttrs = computed(() => ({
|
|
71
|
+
...attrs,
|
|
72
|
+
tabindex: computedTabIndex.value,
|
|
73
|
+
role: "checkbox",
|
|
74
|
+
// "aria-checked": isIndeterminate.value ? "mixed" : isActive.value.toString(),
|
|
75
|
+
// "aria-disabled": attrs.disabled || undefined,
|
|
76
|
+
}));
|
|
77
|
+
watch(
|
|
78
|
+
() => props.indeterminate,
|
|
79
|
+
(val) => {
|
|
80
|
+
isIndeterminate.value = val;
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
watch(isActive, () => {
|
|
85
|
+
if (props.indeterminate) {
|
|
86
|
+
isIndeterminate.value = false;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
isIndeterminate,
|
|
92
|
+
selected,
|
|
93
|
+
isActive,
|
|
94
|
+
classes,
|
|
95
|
+
attrs: computedAttrs,
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
</script>
|
|
100
|
+
|
|
101
|
+
<style lang="scss">
|
|
102
|
+
.ui-checkbox {
|
|
103
|
+
@apply inline-flex items-center mt-3 cursor-pointer;
|
|
104
|
+
&__input {
|
|
105
|
+
@apply w-5 h-5 flex-shrink-0 border border-solid border-gray-50 bg-white appearance-none inline-block select-none cursor-pointer align-middle rounded relative;
|
|
106
|
+
&::after {
|
|
107
|
+
@apply absolute hidden border-solid inset-x-0 top-0 m-auto;
|
|
108
|
+
content: "";
|
|
109
|
+
width: 6px;
|
|
110
|
+
height: 10px;
|
|
111
|
+
bottom: 2px;
|
|
112
|
+
border-width: 0 3px 3px 0;
|
|
113
|
+
-webkit-transform: rotate(45deg);
|
|
114
|
+
-ms-transform: rotate(45deg);
|
|
115
|
+
transform: rotate(45deg);
|
|
116
|
+
}
|
|
117
|
+
&:hover {
|
|
118
|
+
@apply bg-gray-300;
|
|
119
|
+
}
|
|
120
|
+
&:checked {
|
|
121
|
+
@apply bg-white border-blue-600;
|
|
122
|
+
&::after {
|
|
123
|
+
@apply block border-blue-600;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
&:focus {
|
|
127
|
+
@apply outline-none border-2 border-blue-600 bg-gray-200;
|
|
128
|
+
}
|
|
129
|
+
&:disabled {
|
|
130
|
+
@apply bg-gray-300 border-gray-100 cursor-not-allowed;
|
|
131
|
+
& ~ span {
|
|
132
|
+
@apply cursor-not-allowed;
|
|
133
|
+
}
|
|
134
|
+
&:checked {
|
|
135
|
+
@apply bg-white border-white;
|
|
136
|
+
&::after {
|
|
137
|
+
@apply block border-gray-50;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
&__label {
|
|
143
|
+
@apply ml-2 text-gray-900;
|
|
144
|
+
}
|
|
145
|
+
&--invalid & {
|
|
146
|
+
&__input {
|
|
147
|
+
@apply border-red-400;
|
|
148
|
+
&:checked {
|
|
149
|
+
@apply border-red-400;
|
|
150
|
+
&::after {
|
|
151
|
+
@apply block border-red-400;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
&--indeterminate & {
|
|
157
|
+
&__input {
|
|
158
|
+
@apply border-blue-600;
|
|
159
|
+
&::after {
|
|
160
|
+
@apply block bg-blue-600 border-0 bottom-0 transform-none;
|
|
161
|
+
width: 10px;
|
|
162
|
+
height: 2px;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
</style>
|