���Root Mod By V1rus_Alfa
User / IP
:
216.73.217.78
Host / Server
:
195.214.235.115 / npln.ir
System
:
Linux damavand.pws-dns.net 5.14.0-503.35.1.el9_5.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Apr 4 05:23:43 EDT 2025 x86_64
Command
|
Upload
|
Mass Deface
|
Create
:
/
home2
/
cutunixc
/
.trash
/
node_modules.2
/
@nuxt
/
ui
/
dist
/
runtime
/
components
/
data
/
Viewing: Table.vue
<template> <div :class="ui.wrapper" v-bind="attrs"> <table :class="[ui.base, ui.divide]"> <slot v-if="$slots.caption || caption" name="caption"> <caption :class="ui.caption"> {{ caption }} </caption> </slot> <thead :class="ui.thead"> <tr :class="ui.tr.base"> <th v-if="modelValue" scope="col" :class="ui.checkbox.padding"> <UCheckbox :model-value="indeterminate || selected.length === rows.length" :indeterminate="indeterminate" v-bind="ui.default.checkbox" aria-label="Select all" @change="onChange" /> </th> <th v-if="$slots.expand" scope="col" :class="ui.tr.base"> <span class="sr-only">Expand</span> </th> <th v-for="(column, index) in columns" :key="index" scope="col" :class="[ui.th.base, ui.th.padding, ui.th.color, ui.th.font, ui.th.size, column.class]" :aria-sort="getAriaSort(column)" > <slot :name="`${column.key}-header`" :column="column" :sort="sort" :on-sort="onSort"> <UButton v-if="column.sortable" v-bind="{ ...(ui.default.sortButton || {}), ...sortButton }" :icon="(!sort.column || sort.column !== column.key) ? (sortButton.icon || ui.default.sortButton.icon) : sort.direction === 'asc' ? sortAscIcon : sortDescIcon" :label="column[columnAttribute]" @click="onSort(column)" /> <span v-else>{{ column[columnAttribute] }}</span> </slot> </th> </tr> <tr v-if="loading && progress"> <td :colspan="0" :class="ui.progress.wrapper"> <UProgress v-bind="{ ...(ui.default.progress || {}), ...progress }" size="2xs" /> </td> </tr> </thead> <tbody :class="ui.tbody"> <tr v-if="loadingState && loading && !rows.length"> <td :colspan="columns.length + (modelValue ? 1 : 0)"> <slot name="loading-state"> <div :class="ui.loadingState.wrapper"> <UIcon v-if="loadingState.icon" :name="loadingState.icon" :class="ui.loadingState.icon" aria-hidden="true" /> <p :class="ui.loadingState.label"> {{ loadingState.label }} </p> </div> </slot> </td> </tr> <tr v-else-if="emptyState && !rows.length"> <td :colspan="columns.length + (modelValue ? 1 : 0)"> <slot name="empty-state"> <div :class="ui.emptyState.wrapper"> <UIcon v-if="emptyState.icon" :name="emptyState.icon" :class="ui.emptyState.icon" aria-hidden="true" /> <p :class="ui.emptyState.label"> {{ emptyState.label }} </p> </div> </slot> </td> </tr> <template v-else> <template v-for="(row, index) in rows" :key="index"> <tr :class="[ui.tr.base, isSelected(row) && ui.tr.selected, $attrs.onSelect && ui.tr.active, row?.class]" @click="() => onSelect(row)"> <td v-if="modelValue" :class="ui.checkbox.padding"> <UCheckbox v-model="selected" :value="row" v-bind="ui.default.checkbox" aria-label="Select row" @click.stop /> </td> <td v-if="$slots.expand" :class="[ui.td.base, ui.td.padding, ui.td.color, ui.td.font, ui.td.size]" > <UButton v-bind="{ ...(ui.default.expandButton || {}), ...expandButton }" :ui="{ icon: { base: [ui.expand.icon, openedRows.includes(index) && 'rotate-180'] } }" @click="toggleOpened(index)" /> </td> <td v-for="(column, subIndex) in columns" :key="subIndex" :class="[ui.td.base, ui.td.padding, ui.td.color, ui.td.font, ui.td.size, column?.rowClass, row[column.key]?.class]"> <slot :name="`${column.key}-data`" :column="column" :row="row" :index="index" :get-row-data="(defaultValue) => getRowData(row, column.key, defaultValue)"> {{ getRowData(row, column.key) }} </slot> </td> </tr> <tr v-if="openedRows.includes(index)"> <td colspan="100%"> <slot name="expand" :row="row" :index="index" /> </td> </tr> </template> </template> </tbody> </table> </div> </template> <script> import { ref, computed, defineComponent, toRaw, toRef } from "vue"; import { upperFirst } from "scule"; import { defu } from "defu"; import { useVModel } from "@vueuse/core"; import UIcon from "../elements/Icon.vue"; import UButton from "../elements/Button.vue"; import UProgress from "../elements/Progress.vue"; import UCheckbox from "../forms/Checkbox.vue"; import { useUI } from "../../composables/useUI"; import { mergeConfig, get } from "../../utils"; import appConfig from "#build/app.config"; import { table } from "#ui/ui.config"; const config = mergeConfig(appConfig.ui.strategy, appConfig.ui.table, table); function defaultComparator(a, z) { return a === z; } function defaultSort(a, b, direction) { if (a === b) { return 0; } if (direction === "asc") { return a < b ? -1 : 1; } else { return a > b ? -1 : 1; } } export default defineComponent({ components: { UIcon, UButton, UProgress, UCheckbox }, inheritAttrs: false, props: { modelValue: { type: Array, default: null }, by: { type: [String, Function], default: () => defaultComparator }, rows: { type: Array, default: () => [] }, columns: { type: Array, default: null }, columnAttribute: { type: String, default: "label" }, sort: { type: Object, default: () => ({}) }, sortMode: { type: String, default: "auto" }, sortButton: { type: Object, default: () => config.default.sortButton }, sortAscIcon: { type: String, default: () => config.default.sortAscIcon }, sortDescIcon: { type: String, default: () => config.default.sortDescIcon }, expandButton: { type: Object, default: () => config.default.expandButton }, loading: { type: Boolean, default: false }, loadingState: { type: Object, default: () => config.default.loadingState }, emptyState: { type: Object, default: () => config.default.emptyState }, caption: { type: String, default: null }, progress: { type: Object, default: () => config.default.progress }, class: { type: [String, Object, Array], default: () => "" }, ui: { type: Object, default: () => ({}) } }, emits: ["update:modelValue", "update:sort"], setup(props, { emit, attrs: $attrs }) { const { ui, attrs } = useUI("table", toRef(props, "ui"), config, toRef(props, "class")); const columns = computed(() => props.columns ?? Object.keys(props.rows[0] ?? {}).map((key) => ({ key, label: upperFirst(key), sortable: false, class: void 0, sort: defaultSort }))); const sort = useVModel(props, "sort", emit, { passive: true, defaultValue: defu({}, props.sort, { column: null, direction: "asc" }) }); const openedRows = ref([]); const savedSort = { column: sort.value.column, direction: null }; const rows = computed(() => { if (!sort.value?.column || props.sortMode === "manual") { return props.rows; } const { column, direction } = sort.value; return props.rows.slice().sort((a, b) => { const aValue = get(a, column); const bValue = get(b, column); const sort2 = columns.value.find((col) => col.key === column)?.sort ?? defaultSort; return sort2(aValue, bValue, direction); }); }); const selected = computed({ get() { return props.modelValue; }, set(value) { emit("update:modelValue", value); } }); const indeterminate = computed(() => selected.value && selected.value.length > 0 && selected.value.length < props.rows.length); const emptyState = computed(() => { if (props.emptyState === null) return null; return { ...ui.value.default.emptyState, ...props.emptyState }; }); const loadingState = computed(() => { if (props.loadingState === null) return null; return { ...ui.value.default.loadingState, ...props.loadingState }; }); function compare(a, z) { if (typeof props.by === "string") { const property = props.by; return a?.[property] === z?.[property]; } return props.by(a, z); } function isSelected(row) { if (!props.modelValue) { return false; } return selected.value.some((item) => compare(toRaw(item), toRaw(row))); } function onSort(column) { if (sort.value.column === column.key) { const direction = !column.direction || column.direction === "asc" ? "desc" : "asc"; if (sort.value.direction === direction) { sort.value = defu({}, savedSort, { column: null, direction: "asc" }); } else { sort.value = { column: sort.value.column, direction: sort.value.direction === "asc" ? "desc" : "asc" }; } } else { sort.value = { column: column.key, direction: column.direction || "asc" }; } } function onSelect(row) { if (!$attrs.onSelect) { return; } $attrs.onSelect(row); } function selectAllRows() { props.rows.forEach((row) => { if (isSelected(row)) { return; } selected.value.push(row); }); } function onChange(checked) { if (checked) { selectAllRows(); } else { selected.value = []; } } function getRowData(row, rowKey, defaultValue = "") { return get(row, rowKey, defaultValue); } function toggleOpened(index) { if (openedRows.value.includes(index)) { openedRows.value = openedRows.value.filter((i) => i !== index); } else { openedRows.value.push(index); } } function getAriaSort(column) { if (!column.sortable) { return void 0; } if (sort.value.column !== column.key) { return "none"; } if (sort.value.direction === "asc") { return "ascending"; } if (sort.value.direction === "desc") { return "descending"; } return void 0; } return { // eslint-disable-next-line vue/no-dupe-keys ui, attrs, // eslint-disable-next-line vue/no-dupe-keys sort, // eslint-disable-next-line vue/no-dupe-keys columns, // eslint-disable-next-line vue/no-dupe-keys rows, selected, indeterminate, // eslint-disable-next-line vue/no-dupe-keys emptyState, // eslint-disable-next-line vue/no-dupe-keys loadingState, openedRows, isSelected, onSort, onSelect, onChange, getRowData, toggleOpened, getAriaSort }; } }); </script>
Coded With 💗 by
0x6ick Mod By V1rus_Alfa