routie dev init since i didn't adhere to any proper guidance up until now

This commit is contained in:
2026-04-29 22:27:29 -06:00
commit e1dabb71e2
15301 changed files with 3562618 additions and 0 deletions
@@ -0,0 +1,55 @@
import type { InjectionKey, PropType, Ref } from 'vue';
import type { DataTableItem } from '../types.js';
export declare const makeDataTableExpandProps: <Defaults extends {
expandOnClick?: unknown;
showExpand?: unknown;
expanded?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
expandOnClick: unknown extends Defaults["expandOnClick"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["expandOnClick"] ? boolean : boolean | Defaults["expandOnClick"]>;
default: unknown extends Defaults["expandOnClick"] ? boolean : boolean | Defaults["expandOnClick"];
};
showExpand: unknown extends Defaults["showExpand"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["showExpand"] ? boolean : boolean | Defaults["showExpand"]>;
default: unknown extends Defaults["showExpand"] ? boolean : boolean | Defaults["showExpand"];
};
expanded: unknown extends Defaults["expanded"] ? {
type: PropType<readonly string[]>;
default: () => never[];
} : Omit<{
type: PropType<readonly string[]>;
default: () => never[];
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["expanded"] ? readonly string[] : readonly string[] | Defaults["expanded"]>;
default: unknown extends Defaults["expanded"] ? readonly string[] : readonly string[] | Defaults["expanded"];
};
};
export declare const VDataTableExpandedKey: InjectionKey<{
expand: (item: DataTableItem, value: boolean) => void;
expanded: Ref<Set<string>>;
expandOnClick: Ref<boolean | undefined>;
isExpanded: (item: DataTableItem) => boolean;
toggleExpand: (item: DataTableItem) => void;
}>;
type ExpandProps = {
expandOnClick: boolean;
expanded: readonly string[];
'onUpdate:expanded': ((value: any[]) => void) | undefined;
};
export declare function provideExpanded(props: ExpandProps): {
expand: (item: DataTableItem, value: boolean) => void;
expanded: Ref<Set<string>, Set<string>> & {
readonly externalValue: readonly string[];
};
expandOnClick: Readonly<Ref<boolean, boolean>>;
isExpanded: (item: DataTableItem) => boolean;
toggleExpand: (item: DataTableItem) => void;
};
export declare function useExpanded(): {
expand: (item: DataTableItem, value: boolean) => void;
expanded: Ref<Set<string>>;
expandOnClick: Ref<boolean | undefined>;
isExpanded: (item: DataTableItem) => boolean;
toggleExpand: (item: DataTableItem) => void;
};
@@ -0,0 +1,54 @@
// Composables
import { useProxiedModel } from "../../../composables/proxiedModel.js"; // Utilities
import { inject, provide, toRaw, toRef } from 'vue';
import { propsFactory } from "../../../util/index.js"; // Types
export const makeDataTableExpandProps = propsFactory({
expandOnClick: Boolean,
showExpand: Boolean,
expanded: {
type: Array,
default: () => []
}
}, 'DataTable-expand');
export const VDataTableExpandedKey = Symbol.for('vuetify:datatable:expanded');
export function provideExpanded(props) {
const expandOnClick = toRef(() => props.expandOnClick);
const expanded = useProxiedModel(props, 'expanded', props.expanded, v => {
return new Set(v);
}, v => {
return [...v.values()];
});
function expand(item, value) {
const newExpanded = new Set(expanded.value);
const rawValue = toRaw(item.value);
if (!value) {
const item = [...expanded.value].find(x => toRaw(x) === rawValue);
newExpanded.delete(item);
} else {
newExpanded.add(item.value);
}
expanded.value = newExpanded;
}
function isExpanded(item) {
const rawValue = toRaw(item.value);
return [...expanded.value].some(x => toRaw(x) === rawValue);
}
function toggleExpand(item) {
expand(item, !isExpanded(item));
}
const data = {
expand,
expanded,
expandOnClick,
isExpanded,
toggleExpand
};
provide(VDataTableExpandedKey, data);
return data;
}
export function useExpanded() {
const data = inject(VDataTableExpandedKey);
if (!data) throw new Error('foo');
return data;
}
//# sourceMappingURL=expand.js.map
@@ -0,0 +1 @@
{"version":3,"file":"expand.js","names":["useProxiedModel","inject","provide","toRaw","toRef","propsFactory","makeDataTableExpandProps","expandOnClick","Boolean","showExpand","expanded","type","Array","default","VDataTableExpandedKey","Symbol","for","provideExpanded","props","v","Set","values","expand","item","value","newExpanded","rawValue","find","x","delete","add","isExpanded","some","toggleExpand","data","useExpanded","Error"],"sources":["../../../../src/components/VDataTable/composables/expand.ts"],"sourcesContent":["// Composables\nimport { useProxiedModel } from '@/composables/proxiedModel'\n\n// Utilities\nimport { inject, provide, toRaw, toRef } from 'vue'\nimport { propsFactory } from '@/util'\n\n// Types\nimport type { InjectionKey, PropType, Ref } from 'vue'\nimport type { DataTableItem } from '../types'\n\nexport const makeDataTableExpandProps = propsFactory({\n expandOnClick: Boolean,\n showExpand: Boolean,\n expanded: {\n type: Array as PropType<readonly string[]>,\n default: () => ([]),\n },\n}, 'DataTable-expand')\n\nexport const VDataTableExpandedKey: InjectionKey<{\n expand: (item: DataTableItem, value: boolean) => void\n expanded: Ref<Set<string>>\n expandOnClick: Ref<boolean | undefined>\n isExpanded: (item: DataTableItem) => boolean\n toggleExpand: (item: DataTableItem) => void\n}> = Symbol.for('vuetify:datatable:expanded')\n\ntype ExpandProps = {\n expandOnClick: boolean\n expanded: readonly string[]\n 'onUpdate:expanded': ((value: any[]) => void) | undefined\n}\n\nexport function provideExpanded (props: ExpandProps) {\n const expandOnClick = toRef(() => props.expandOnClick)\n const expanded = useProxiedModel(props, 'expanded', props.expanded, v => {\n return new Set(v)\n }, v => {\n return [...v.values()]\n })\n\n function expand (item: DataTableItem, value: boolean) {\n const newExpanded = new Set(expanded.value)\n const rawValue = toRaw(item.value)\n\n if (!value) {\n const item = [...expanded.value].find(x => toRaw(x) === rawValue)!\n newExpanded.delete(item)\n } else {\n newExpanded.add(item.value)\n }\n\n expanded.value = newExpanded\n }\n\n function isExpanded (item: DataTableItem) {\n const rawValue = toRaw(item.value)\n return [...expanded.value].some(x => toRaw(x) === rawValue)\n }\n\n function toggleExpand (item: DataTableItem) {\n expand(item, !isExpanded(item))\n }\n\n const data = { expand, expanded, expandOnClick, isExpanded, toggleExpand }\n\n provide(VDataTableExpandedKey, data)\n\n return data\n}\n\nexport function useExpanded () {\n const data = inject(VDataTableExpandedKey)\n\n if (!data) throw new Error('foo')\n\n return data\n}\n"],"mappings":"AAAA;AAAA,SACSA,eAAe,gDAExB;AACA,SAASC,MAAM,EAAEC,OAAO,EAAEC,KAAK,EAAEC,KAAK,QAAQ,KAAK;AAAA,SAC1CC,YAAY,kCAErB;AAIA,OAAO,MAAMC,wBAAwB,GAAGD,YAAY,CAAC;EACnDE,aAAa,EAAEC,OAAO;EACtBC,UAAU,EAAED,OAAO;EACnBE,QAAQ,EAAE;IACRC,IAAI,EAAEC,KAAoC;IAC1CC,OAAO,EAAEA,CAAA,KAAO;EAClB;AACF,CAAC,EAAE,kBAAkB,CAAC;AAEtB,OAAO,MAAMC,qBAMX,GAAGC,MAAM,CAACC,GAAG,CAAC,4BAA4B,CAAC;AAQ7C,OAAO,SAASC,eAAeA,CAAEC,KAAkB,EAAE;EACnD,MAAMX,aAAa,GAAGH,KAAK,CAAC,MAAMc,KAAK,CAACX,aAAa,CAAC;EACtD,MAAMG,QAAQ,GAAGV,eAAe,CAACkB,KAAK,EAAE,UAAU,EAAEA,KAAK,CAACR,QAAQ,EAAES,CAAC,IAAI;IACvE,OAAO,IAAIC,GAAG,CAACD,CAAC,CAAC;EACnB,CAAC,EAAEA,CAAC,IAAI;IACN,OAAO,CAAC,GAAGA,CAAC,CAACE,MAAM,CAAC,CAAC,CAAC;EACxB,CAAC,CAAC;EAEF,SAASC,MAAMA,CAAEC,IAAmB,EAAEC,KAAc,EAAE;IACpD,MAAMC,WAAW,GAAG,IAAIL,GAAG,CAACV,QAAQ,CAACc,KAAK,CAAC;IAC3C,MAAME,QAAQ,GAAGvB,KAAK,CAACoB,IAAI,CAACC,KAAK,CAAC;IAElC,IAAI,CAACA,KAAK,EAAE;MACV,MAAMD,IAAI,GAAG,CAAC,GAAGb,QAAQ,CAACc,KAAK,CAAC,CAACG,IAAI,CAACC,CAAC,IAAIzB,KAAK,CAACyB,CAAC,CAAC,KAAKF,QAAQ,CAAE;MAClED,WAAW,CAACI,MAAM,CAACN,IAAI,CAAC;IAC1B,CAAC,MAAM;MACLE,WAAW,CAACK,GAAG,CAACP,IAAI,CAACC,KAAK,CAAC;IAC7B;IAEAd,QAAQ,CAACc,KAAK,GAAGC,WAAW;EAC9B;EAEA,SAASM,UAAUA,CAAER,IAAmB,EAAE;IACxC,MAAMG,QAAQ,GAAGvB,KAAK,CAACoB,IAAI,CAACC,KAAK,CAAC;IAClC,OAAO,CAAC,GAAGd,QAAQ,CAACc,KAAK,CAAC,CAACQ,IAAI,CAACJ,CAAC,IAAIzB,KAAK,CAACyB,CAAC,CAAC,KAAKF,QAAQ,CAAC;EAC7D;EAEA,SAASO,YAAYA,CAAEV,IAAmB,EAAE;IAC1CD,MAAM,CAACC,IAAI,EAAE,CAACQ,UAAU,CAACR,IAAI,CAAC,CAAC;EACjC;EAEA,MAAMW,IAAI,GAAG;IAAEZ,MAAM;IAAEZ,QAAQ;IAAEH,aAAa;IAAEwB,UAAU;IAAEE;EAAa,CAAC;EAE1E/B,OAAO,CAACY,qBAAqB,EAAEoB,IAAI,CAAC;EAEpC,OAAOA,IAAI;AACb;AAEA,OAAO,SAASC,WAAWA,CAAA,EAAI;EAC7B,MAAMD,IAAI,GAAGjC,MAAM,CAACa,qBAAqB,CAAC;EAE1C,IAAI,CAACoB,IAAI,EAAE,MAAM,IAAIE,KAAK,CAAC,KAAK,CAAC;EAEjC,OAAOF,IAAI;AACb","ignoreList":[]}
@@ -0,0 +1,71 @@
import type { MaybeRefOrGetter, PropType, Ref } from 'vue';
import type { SortItem } from './sort.js';
import type { DataTableItem } from '../types.js';
export interface GroupableItem<T = any> {
type: 'item';
raw: T;
}
export interface Group<T = any> {
type: 'group';
depth: number;
id: string;
key: string;
value: any;
items: readonly (T | Group<T> | GroupSummary<T>)[];
}
export interface GroupSummary<T = any> {
type: 'group-summary';
depth: number;
id: string;
key: string;
value: any;
items: readonly (T | Group<T> | GroupSummary<T>)[];
}
export declare const makeDataTableGroupProps: <Defaults extends {
groupBy?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
groupBy: unknown extends Defaults["groupBy"] ? {
type: PropType<readonly SortItem[]>;
default: () => never[];
} : Omit<{
type: PropType<readonly SortItem[]>;
default: () => never[];
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["groupBy"] ? readonly SortItem[] : readonly SortItem[] | Defaults["groupBy"]>;
default: unknown extends Defaults["groupBy"] ? readonly SortItem[] : readonly SortItem[] | Defaults["groupBy"];
};
};
type GroupProps = {
groupBy: readonly SortItem[];
'onUpdate:groupBy': ((value: SortItem[]) => void) | undefined;
};
export declare function createGroupBy(props: GroupProps): {
groupBy: Ref<readonly SortItem[], readonly SortItem[]> & {
readonly externalValue: readonly SortItem[];
};
};
export declare function provideGroupBy(options: {
groupBy: Ref<readonly SortItem[]>;
sortBy: Ref<readonly SortItem[]>;
disableSort?: Ref<boolean>;
}): {
sortByWithGroups: import("vue").ComputedRef<SortItem[]>;
toggleGroup: (group: Group) => void;
opened: Ref<Set<string> & Omit<Set<string>, keyof Set<any>>, Set<string> | (Set<string> & Omit<Set<string>, keyof Set<any>>)>;
groupBy: Ref<readonly SortItem[], readonly SortItem[]>;
extractRows: <T extends GroupableItem>(items: readonly (T | Group<T> | GroupSummary<T>)[]) => T[];
isGroupOpen: (group: Group) => boolean;
};
export declare function useGroupBy(): {
opened: Ref<Set<string>>;
toggleGroup: (group: Group) => void;
isGroupOpen: (group: Group) => boolean;
sortByWithGroups: Ref<SortItem[]>;
groupBy: Ref<readonly SortItem[]>;
extractRows: (items: (DataTableItem | Group<DataTableItem>)[]) => DataTableItem[];
};
export declare function useGroupedItems<T extends GroupableItem>(items: MaybeRefOrGetter<readonly T[]>, groupBy: Ref<readonly SortItem[]>, opened: Ref<Set<string>>, hasSummary: MaybeRefOrGetter<boolean>): {
groups: import("vue").ComputedRef<Group<T>[]>;
flatItems: import("vue").ComputedRef<readonly (T | Group<T> | GroupSummary<T>)[]>;
};
@@ -0,0 +1,151 @@
// Composables
import { useProxiedModel } from "../../../composables/proxiedModel.js"; // Utilities
import { computed, inject, provide, ref, toValue } from 'vue';
import { getObjectValueByPath, propsFactory } from "../../../util/index.js"; // Types
export const makeDataTableGroupProps = propsFactory({
groupBy: {
type: Array,
default: () => []
}
}, 'DataTable-group');
const VDataTableGroupSymbol = Symbol.for('vuetify:data-table-group');
export function createGroupBy(props) {
const groupBy = useProxiedModel(props, 'groupBy');
return {
groupBy
};
}
export function provideGroupBy(options) {
const {
disableSort,
groupBy,
sortBy
} = options;
const opened = ref(new Set());
const sortByWithGroups = computed(() => {
return groupBy.value.map(val => ({
...val,
order: val.order ?? false
})).concat(disableSort?.value ? [] : sortBy.value);
});
function isGroupOpen(group) {
return opened.value.has(group.id);
}
function toggleGroup(group) {
const newOpened = new Set(opened.value);
if (!isGroupOpen(group)) newOpened.add(group.id);else newOpened.delete(group.id);
opened.value = newOpened;
}
function extractRows(items) {
function dive(group) {
const arr = [];
for (const item of group.items) {
if ('type' in item && item.type === 'group') {
arr.push(...dive(item));
} else {
arr.push(item);
}
}
return [...new Set(arr)];
}
return dive({
type: 'group',
items,
id: 'dummy',
key: 'dummy',
value: 'dummy',
depth: 0
});
}
// onBeforeMount(() => {
// for (const key of groupedItems.value.keys()) {
// opened.value.add(key)
// }
// })
const data = {
sortByWithGroups,
toggleGroup,
opened,
groupBy,
extractRows,
isGroupOpen
};
provide(VDataTableGroupSymbol, data);
return data;
}
export function useGroupBy() {
const data = inject(VDataTableGroupSymbol);
if (!data) throw new Error('Missing group!');
return data;
}
function groupItemsByProperty(items, groupBy) {
if (!items.length) return [];
const groups = new Map();
for (const item of items) {
const value = getObjectValueByPath(item.raw, groupBy);
if (!groups.has(value)) {
groups.set(value, []);
}
groups.get(value).push(item);
}
return groups;
}
function groupItems(items, groupBy, depth = 0, prefix = 'root') {
if (!groupBy.length) return [];
const groupedItems = groupItemsByProperty(items, groupBy[0]);
const groups = [];
const rest = groupBy.slice(1);
groupedItems.forEach((items, value) => {
const key = groupBy[0];
const id = `${prefix}_${key}_${value}`;
groups.push({
depth,
id,
key,
value,
items: rest.length ? groupItems(items, rest, depth + 1, id) : items,
type: 'group'
});
});
return groups;
}
function flattenItems(items, opened, hasSummary) {
const flatItems = [];
for (const item of items) {
// TODO: make this better
if ('type' in item && item.type === 'group') {
if (item.value != null) {
flatItems.push(item);
}
if (opened.has(item.id) || item.value == null) {
flatItems.push(...flattenItems(item.items, opened, hasSummary));
if (hasSummary) {
flatItems.push({
...item,
type: 'group-summary'
});
}
}
} else {
flatItems.push(item);
}
}
return flatItems;
}
export function useGroupedItems(items, groupBy, opened, hasSummary) {
const groups = computed(() => {
if (!groupBy.value.length) return [];
return groupItems(toValue(items), groupBy.value.map(item => item.key));
});
const flatItems = computed(() => {
if (!groupBy.value.length) return toValue(items);
return flattenItems(groups.value, opened.value, toValue(hasSummary));
});
return {
groups,
flatItems
};
}
//# sourceMappingURL=group.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,352 @@
import type { DeepReadonly, InjectionKey, PropType, Ref } from 'vue';
import type { SortItem } from './sort.js';
import type { DataTableCompareFunction, DataTableHeader, InternalDataTableHeader } from '../types.js';
import type { FilterKeyFunctions } from '../../../composables/filter.js';
export declare const makeDataTableHeaderProps: <Defaults extends {
headers?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
headers: unknown extends Defaults["headers"] ? PropType<readonly {
readonly key?: 'data-table-group' | 'data-table-select' | 'data-table-expand' | (string & {});
readonly value?: import("../../../util/index.js").SelectItemKey<Record<string, any>>;
readonly title?: string;
readonly fixed?: boolean | 'start' | 'end';
readonly align?: 'start' | 'end' | 'center';
readonly width?: number | string;
readonly minWidth?: number | string;
readonly maxWidth?: number | string;
readonly nowrap?: boolean;
readonly indent?: number;
readonly headerProps?: {
readonly [x: string]: any;
} | undefined;
readonly cellProps?: import("../../../types.js").DataTableHeaderCellPropsFunction | {
readonly [x: string]: any;
} | undefined;
readonly sortable?: boolean;
readonly sort?: DataTableCompareFunction;
readonly sortRaw?: DataTableCompareFunction;
readonly filter?: import("../../../types.js").FilterFunction;
readonly children?: readonly {
readonly key?: 'data-table-group' | 'data-table-select' | 'data-table-expand' | (string & {});
readonly value?: import("../../../util/index.js").SelectItemKey<Record<string, any>>;
readonly title?: string;
readonly fixed?: boolean | 'start' | 'end';
readonly align?: 'start' | 'end' | 'center';
readonly width?: number | string;
readonly minWidth?: number | string;
readonly maxWidth?: number | string;
readonly nowrap?: boolean;
readonly indent?: number;
readonly headerProps?: {
readonly [x: string]: any;
} | undefined;
readonly cellProps?: import("../../../types.js").DataTableHeaderCellPropsFunction | {
readonly [x: string]: any;
} | undefined;
readonly sortable?: boolean;
readonly sort?: DataTableCompareFunction;
readonly sortRaw?: DataTableCompareFunction;
readonly filter?: import("../../../types.js").FilterFunction;
readonly children?: readonly /*elided*/ any[] | undefined;
}[] | undefined;
}[]> : {
type: PropType<unknown extends Defaults["headers"] ? readonly {
readonly key?: 'data-table-group' | 'data-table-select' | 'data-table-expand' | (string & {});
readonly value?: import("../../../util/index.js").SelectItemKey<Record<string, any>>;
readonly title?: string;
readonly fixed?: boolean | 'start' | 'end';
readonly align?: 'start' | 'end' | 'center';
readonly width?: number | string;
readonly minWidth?: number | string;
readonly maxWidth?: number | string;
readonly nowrap?: boolean;
readonly indent?: number;
readonly headerProps?: {
readonly [x: string]: any;
} | undefined;
readonly cellProps?: import("../../../types.js").DataTableHeaderCellPropsFunction | {
readonly [x: string]: any;
} | undefined;
readonly sortable?: boolean;
readonly sort?: DataTableCompareFunction;
readonly sortRaw?: DataTableCompareFunction;
readonly filter?: import("../../../types.js").FilterFunction;
readonly children?: readonly {
readonly key?: 'data-table-group' | 'data-table-select' | 'data-table-expand' | (string & {});
readonly value?: import("../../../util/index.js").SelectItemKey<Record<string, any>>;
readonly title?: string;
readonly fixed?: boolean | 'start' | 'end';
readonly align?: 'start' | 'end' | 'center';
readonly width?: number | string;
readonly minWidth?: number | string;
readonly maxWidth?: number | string;
readonly nowrap?: boolean;
readonly indent?: number;
readonly headerProps?: {
readonly [x: string]: any;
} | undefined;
readonly cellProps?: import("../../../types.js").DataTableHeaderCellPropsFunction | {
readonly [x: string]: any;
} | undefined;
readonly sortable?: boolean;
readonly sort?: DataTableCompareFunction;
readonly sortRaw?: DataTableCompareFunction;
readonly filter?: import("../../../types.js").FilterFunction;
readonly children?: readonly any[] | undefined;
}[] | undefined;
}[] : readonly {
readonly key?: 'data-table-group' | 'data-table-select' | 'data-table-expand' | (string & {});
readonly value?: import("../../../util/index.js").SelectItemKey<Record<string, any>>;
readonly title?: string;
readonly fixed?: boolean | 'start' | 'end';
readonly align?: 'start' | 'end' | 'center';
readonly width?: number | string;
readonly minWidth?: number | string;
readonly maxWidth?: number | string;
readonly nowrap?: boolean;
readonly indent?: number;
readonly headerProps?: {
readonly [x: string]: any;
} | undefined;
readonly cellProps?: import("../../../types.js").DataTableHeaderCellPropsFunction | {
readonly [x: string]: any;
} | undefined;
readonly sortable?: boolean;
readonly sort?: DataTableCompareFunction;
readonly sortRaw?: DataTableCompareFunction;
readonly filter?: import("../../../types.js").FilterFunction;
readonly children?: readonly {
readonly key?: 'data-table-group' | 'data-table-select' | 'data-table-expand' | (string & {});
readonly value?: import("../../../util/index.js").SelectItemKey<Record<string, any>>;
readonly title?: string;
readonly fixed?: boolean | 'start' | 'end';
readonly align?: 'start' | 'end' | 'center';
readonly width?: number | string;
readonly minWidth?: number | string;
readonly maxWidth?: number | string;
readonly nowrap?: boolean;
readonly indent?: number;
readonly headerProps?: {
readonly [x: string]: any;
} | undefined;
readonly cellProps?: import("../../../types.js").DataTableHeaderCellPropsFunction | {
readonly [x: string]: any;
} | undefined;
readonly sortable?: boolean;
readonly sort?: DataTableCompareFunction;
readonly sortRaw?: DataTableCompareFunction;
readonly filter?: import("../../../types.js").FilterFunction;
readonly children?: readonly any[] | undefined;
}[] | undefined;
}[] | Defaults["headers"]>;
default: unknown extends Defaults["headers"] ? readonly {
readonly key?: 'data-table-group' | 'data-table-select' | 'data-table-expand' | (string & {});
readonly value?: import("../../../util/index.js").SelectItemKey<Record<string, any>>;
readonly title?: string;
readonly fixed?: boolean | 'start' | 'end';
readonly align?: 'start' | 'end' | 'center';
readonly width?: number | string;
readonly minWidth?: number | string;
readonly maxWidth?: number | string;
readonly nowrap?: boolean;
readonly indent?: number;
readonly headerProps?: {
readonly [x: string]: any;
} | undefined;
readonly cellProps?: import("../../../types.js").DataTableHeaderCellPropsFunction | {
readonly [x: string]: any;
} | undefined;
readonly sortable?: boolean;
readonly sort?: DataTableCompareFunction;
readonly sortRaw?: DataTableCompareFunction;
readonly filter?: import("../../../types.js").FilterFunction;
readonly children?: readonly {
readonly key?: 'data-table-group' | 'data-table-select' | 'data-table-expand' | (string & {});
readonly value?: import("../../../util/index.js").SelectItemKey<Record<string, any>>;
readonly title?: string;
readonly fixed?: boolean | 'start' | 'end';
readonly align?: 'start' | 'end' | 'center';
readonly width?: number | string;
readonly minWidth?: number | string;
readonly maxWidth?: number | string;
readonly nowrap?: boolean;
readonly indent?: number;
readonly headerProps?: {
readonly [x: string]: any;
} | undefined;
readonly cellProps?: import("../../../types.js").DataTableHeaderCellPropsFunction | {
readonly [x: string]: any;
} | undefined;
readonly sortable?: boolean;
readonly sort?: DataTableCompareFunction;
readonly sortRaw?: DataTableCompareFunction;
readonly filter?: import("../../../types.js").FilterFunction;
readonly children?: readonly any[] | undefined;
}[] | undefined;
}[] : readonly {
readonly key?: 'data-table-group' | 'data-table-select' | 'data-table-expand' | (string & {});
readonly value?: import("../../../util/index.js").SelectItemKey<Record<string, any>>;
readonly title?: string;
readonly fixed?: boolean | 'start' | 'end';
readonly align?: 'start' | 'end' | 'center';
readonly width?: number | string;
readonly minWidth?: number | string;
readonly maxWidth?: number | string;
readonly nowrap?: boolean;
readonly indent?: number;
readonly headerProps?: {
readonly [x: string]: any;
} | undefined;
readonly cellProps?: import("../../../types.js").DataTableHeaderCellPropsFunction | {
readonly [x: string]: any;
} | undefined;
readonly sortable?: boolean;
readonly sort?: DataTableCompareFunction;
readonly sortRaw?: DataTableCompareFunction;
readonly filter?: import("../../../types.js").FilterFunction;
readonly children?: readonly {
readonly key?: 'data-table-group' | 'data-table-select' | 'data-table-expand' | (string & {});
readonly value?: import("../../../util/index.js").SelectItemKey<Record<string, any>>;
readonly title?: string;
readonly fixed?: boolean | 'start' | 'end';
readonly align?: 'start' | 'end' | 'center';
readonly width?: number | string;
readonly minWidth?: number | string;
readonly maxWidth?: number | string;
readonly nowrap?: boolean;
readonly indent?: number;
readonly headerProps?: {
readonly [x: string]: any;
} | undefined;
readonly cellProps?: import("../../../types.js").DataTableHeaderCellPropsFunction | {
readonly [x: string]: any;
} | undefined;
readonly sortable?: boolean;
readonly sort?: DataTableCompareFunction;
readonly sortRaw?: DataTableCompareFunction;
readonly filter?: import("../../../types.js").FilterFunction;
readonly children?: readonly any[] | undefined;
}[] | undefined;
}[] | Defaults["headers"];
};
};
export declare const VDataTableHeadersSymbol: InjectionKey<{
headers: Ref<InternalDataTableHeader[][]>;
columns: Ref<InternalDataTableHeader[]>;
}>;
type HeaderProps = {
headers: DeepReadonly<DataTableHeader[]> | undefined;
items: any[];
};
export declare function createHeaders(props: HeaderProps, options?: {
groupBy?: Ref<readonly SortItem[]>;
showSelect?: Ref<boolean>;
showExpand?: Ref<boolean>;
}): {
headers: Ref<{
title?: string;
fixed?: boolean | 'start' | 'end';
align?: 'start' | 'end' | 'center';
width?: number | string;
minWidth?: number | string;
maxWidth?: number | string;
nowrap?: boolean;
indent?: number;
headerProps?: Record<string, any>;
cellProps?: import("../types.js").HeaderCellProps;
sortable: boolean;
sort?: DataTableCompareFunction;
sortRaw?: DataTableCompareFunction;
filter?: import("../../../types.js").FilterFunction;
key: string | null;
value: import("../../../util/index.js").SelectItemKey | null;
fixedOffset?: number;
fixedEndOffset?: number;
lastFixed?: boolean;
firstFixedEnd?: boolean;
colspan?: number;
rowspan?: number;
children?: /*elided*/ any[] | undefined;
}[][], {
title?: string;
fixed?: boolean | 'start' | 'end';
align?: 'start' | 'end' | 'center';
width?: number | string;
minWidth?: number | string;
maxWidth?: number | string;
nowrap?: boolean;
indent?: number;
headerProps?: Record<string, any>;
cellProps?: import("../types.js").HeaderCellProps;
sortable: boolean;
sort?: DataTableCompareFunction;
sortRaw?: DataTableCompareFunction;
filter?: import("../../../types.js").FilterFunction;
key: string | null;
value: import("../../../util/index.js").SelectItemKey | null;
fixedOffset?: number;
fixedEndOffset?: number;
lastFixed?: boolean;
firstFixedEnd?: boolean;
colspan?: number;
rowspan?: number;
children?: any[] | undefined;
}[][] | InternalDataTableHeader[][]>;
columns: Ref<{
title?: string;
fixed?: boolean | 'start' | 'end';
align?: 'start' | 'end' | 'center';
width?: number | string;
minWidth?: number | string;
maxWidth?: number | string;
nowrap?: boolean;
indent?: number;
headerProps?: Record<string, any>;
cellProps?: import("../types.js").HeaderCellProps;
sortable: boolean;
sort?: DataTableCompareFunction;
sortRaw?: DataTableCompareFunction;
filter?: import("../../../types.js").FilterFunction;
key: string | null;
value: import("../../../util/index.js").SelectItemKey | null;
fixedOffset?: number;
fixedEndOffset?: number;
lastFixed?: boolean;
firstFixedEnd?: boolean;
colspan?: number;
rowspan?: number;
children?: any[] | undefined;
}[], {
title?: string;
fixed?: boolean | 'start' | 'end';
align?: 'start' | 'end' | 'center';
width?: number | string;
minWidth?: number | string;
maxWidth?: number | string;
nowrap?: boolean;
indent?: number;
headerProps?: Record<string, any>;
cellProps?: import("../types.js").HeaderCellProps;
sortable: boolean;
sort?: DataTableCompareFunction;
sortRaw?: DataTableCompareFunction;
filter?: import("../../../types.js").FilterFunction;
key: string | null;
value: import("../../../util/index.js").SelectItemKey | null;
fixedOffset?: number;
fixedEndOffset?: number;
lastFixed?: boolean;
firstFixedEnd?: boolean;
colspan?: number;
rowspan?: number;
children?: any[] | undefined;
}[] | InternalDataTableHeader[]>;
sortFunctions: Ref<Record<string, DataTableCompareFunction>, Record<string, DataTableCompareFunction>>;
sortRawFunctions: Ref<Record<string, DataTableCompareFunction>, Record<string, DataTableCompareFunction>>;
filterFunctions: Ref<FilterKeyFunctions, FilterKeyFunctions>;
};
export declare function useHeaders(): {
headers: Ref<InternalDataTableHeader[][]>;
columns: Ref<InternalDataTableHeader[]>;
};
@@ -0,0 +1,300 @@
// Utilities
import { capitalize, inject, provide, ref, watchEffect } from 'vue';
import { consoleError, propsFactory } from "../../../util/index.js"; // Types
export const makeDataTableHeaderProps = propsFactory({
headers: Array
}, 'DataTable-header');
export const VDataTableHeadersSymbol = Symbol.for('vuetify:data-table-headers');
const defaultHeader = {
title: '',
sortable: false
};
const defaultActionHeader = {
...defaultHeader,
width: 48
};
function priorityQueue(arr = []) {
const queue = arr.map(element => ({
element,
priority: 0
}));
return {
enqueue: (element, priority) => {
let added = false;
for (let i = 0; i < queue.length; i++) {
const item = queue[i];
if (item.priority > priority) {
queue.splice(i, 0, {
element,
priority
});
added = true;
break;
}
}
if (!added) queue.push({
element,
priority
});
},
size: () => queue.length,
count: () => {
let count = 0;
if (!queue.length) return 0;
const whole = Math.floor(queue[0].priority);
for (let i = 0; i < queue.length; i++) {
if (Math.floor(queue[i].priority) === whole) count += 1;
}
return count;
},
dequeue: () => {
return queue.shift();
}
};
}
function extractLeaves(item, columns = []) {
if (!item.children) {
columns.push(item);
} else {
for (const child of item.children) {
extractLeaves(child, columns);
}
}
return columns;
}
function extractKeys(headers, keys = new Set()) {
for (const item of headers) {
if (item.key) keys.add(item.key);
if (item.children) {
extractKeys(item.children, keys);
}
}
return keys;
}
function getDefaultItem(item) {
if (!item.key) return undefined;
if (item.key === 'data-table-group') return defaultHeader;
if (['data-table-expand', 'data-table-select'].includes(item.key)) return defaultActionHeader;
return undefined;
}
function getDepth(item, depth = 0) {
if (!item.children) return depth;
return Math.max(depth, ...item.children.map(child => getDepth(child, depth + 1)));
}
function parseFixedColumns(items) {
let seenFixed = false;
function setFixed(item, side, parentFixedSide = 'none') {
if (!item) return;
if (parentFixedSide !== 'none') {
item.fixed = parentFixedSide;
}
// normalize to simplify logic below
if (item.fixed === true) {
item.fixed = 'start';
}
if (item.fixed === side) {
if (item.children) {
if (side === 'start') {
for (let i = item.children.length - 1; i >= 0; i--) {
setFixed(item.children[i], side, side);
}
} else {
for (let i = 0; i < item.children.length; i++) {
setFixed(item.children[i], side, side);
}
}
} else {
if (!seenFixed && side === 'start') {
item.lastFixed = true;
} else if (!seenFixed && side === 'end') {
item.firstFixedEnd = true;
} else if (isNaN(Number(item.width))) {
consoleError(`Multiple fixed columns should have a static width (key: ${item.key})`);
} else {
item.minWidth = Math.max(Number(item.width) || 0, Number(item.minWidth) || 0);
}
seenFixed = true;
}
} else {
if (item.children) {
if (side === 'start') {
for (let i = item.children.length - 1; i >= 0; i--) {
setFixed(item.children[i], side);
}
} else {
for (let i = 0; i < item.children.length; i++) {
setFixed(item.children[i], side);
}
}
} else {
seenFixed = false;
}
}
}
for (let i = items.length - 1; i >= 0; i--) {
setFixed(items[i], 'start');
}
for (let i = 0; i < items.length; i++) {
setFixed(items[i], 'end');
}
let fixedOffset = 0;
for (let i = 0; i < items.length; i++) {
fixedOffset = setFixedOffset(items[i], fixedOffset);
}
let fixedEndOffset = 0;
for (let i = items.length - 1; i >= 0; i--) {
fixedEndOffset = setFixedEndOffset(items[i], fixedEndOffset);
}
}
function setFixedOffset(item, offset = 0) {
if (!item) return offset;
if (item.children) {
item.fixedOffset = offset;
for (const child of item.children) {
offset = setFixedOffset(child, offset);
}
} else if (item.fixed && item.fixed !== 'end') {
item.fixedOffset = offset;
offset += parseFloat(item.width || '0') || 0;
}
return offset;
}
function setFixedEndOffset(item, offset = 0) {
if (!item) return offset;
if (item.children) {
item.fixedEndOffset = offset;
for (const child of item.children) {
offset = setFixedEndOffset(child, offset);
}
} else if (item.fixed === 'end') {
item.fixedEndOffset = offset;
offset += parseFloat(item.width || '0') || 0;
}
return offset;
}
function parse(items, maxDepth) {
const headers = [];
let currentDepth = 0;
const queue = priorityQueue(items);
while (queue.size() > 0) {
let rowSize = queue.count();
const row = [];
let fraction = 1;
while (rowSize > 0) {
const {
element: item,
priority
} = queue.dequeue();
const diff = maxDepth - currentDepth - getDepth(item);
row.push({
...item,
rowspan: diff ?? 1,
colspan: item.children ? extractLeaves(item).length : 1
});
if (item.children) {
for (const child of item.children) {
// This internally sorts items that are on the same priority "row"
const sort = priority % 1 + fraction / Math.pow(10, currentDepth + 2);
queue.enqueue(child, currentDepth + diff + sort);
}
}
fraction += 1;
rowSize -= 1;
}
currentDepth += 1;
headers.push(row);
}
const columns = items.map(item => extractLeaves(item)).flat();
return {
columns,
headers
};
}
function convertToInternalHeaders(items) {
const internalHeaders = [];
for (const item of items) {
const defaultItem = {
...getDefaultItem(item),
...item
};
const key = defaultItem.key ?? (typeof defaultItem.value === 'string' ? defaultItem.value : null);
const value = defaultItem.value ?? key ?? null;
const internalItem = {
...defaultItem,
key,
value,
sortable: defaultItem.sortable ?? (defaultItem.key != null || !!defaultItem.sort),
children: defaultItem.children ? convertToInternalHeaders(defaultItem.children) : undefined
};
internalHeaders.push(internalItem);
}
return internalHeaders;
}
export function createHeaders(props, options) {
const headers = ref([]);
const columns = ref([]);
const sortFunctions = ref({});
const sortRawFunctions = ref({});
const filterFunctions = ref({});
watchEffect(() => {
const _headers = props.headers || Object.keys(props.items[0] ?? {}).map(key => ({
key,
title: capitalize(key)
}));
const items = _headers.slice();
const keys = extractKeys(items);
if (options?.groupBy?.value.length && !keys.has('data-table-group')) {
items.unshift({
key: 'data-table-group',
title: 'Group'
});
}
if (options?.showSelect?.value && !keys.has('data-table-select')) {
items.unshift({
key: 'data-table-select'
});
}
if (options?.showExpand?.value && !keys.has('data-table-expand')) {
items.push({
key: 'data-table-expand'
});
}
const internalHeaders = convertToInternalHeaders(items);
parseFixedColumns(internalHeaders);
const maxDepth = Math.max(...internalHeaders.map(item => getDepth(item))) + 1;
const parsed = parse(internalHeaders, maxDepth);
headers.value = parsed.headers;
columns.value = parsed.columns;
const flatHeaders = parsed.headers.flat(1);
for (const header of flatHeaders) {
if (!header.key) continue;
if (header.sortable) {
if (header.sort) {
sortFunctions.value[header.key] = header.sort;
}
if (header.sortRaw) {
sortRawFunctions.value[header.key] = header.sortRaw;
}
}
if (header.filter) {
filterFunctions.value[header.key] = header.filter;
}
}
});
const data = {
headers,
columns,
sortFunctions,
sortRawFunctions,
filterFunctions
};
provide(VDataTableHeadersSymbol, data);
return data;
}
export function useHeaders() {
const data = inject(VDataTableHeadersSymbol);
if (!data) throw new Error('Missing headers!');
return data;
}
//# sourceMappingURL=headers.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,65 @@
import type { PropType, Ref } from 'vue';
import type { CellProps, DataTableItem, InternalDataTableHeader, RowProps } from '../types.js';
import type { SelectItemKey } from '../../../util/index.js';
export interface DataTableItemProps {
items: any[];
itemValue: SelectItemKey;
itemSelectable: SelectItemKey;
returnObject: boolean;
}
export declare const makeDataTableItemsProps: <Defaults extends {
items?: unknown;
itemValue?: unknown;
itemSelectable?: unknown;
rowProps?: unknown;
cellProps?: unknown;
returnObject?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
items: unknown extends Defaults["items"] ? {
type: PropType<DataTableItemProps['items']>;
default: () => never[];
} : Omit<{
type: PropType<DataTableItemProps['items']>;
default: () => never[];
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["items"] ? any[] : any[] | Defaults["items"]>;
default: unknown extends Defaults["items"] ? any[] : any[] | Defaults["items"];
};
itemValue: unknown extends Defaults["itemValue"] ? {
type: PropType<SelectItemKey>;
default: string;
} : Omit<{
type: PropType<SelectItemKey>;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["itemValue"] ? SelectItemKey : Defaults["itemValue"] | SelectItemKey>;
default: unknown extends Defaults["itemValue"] ? SelectItemKey : Defaults["itemValue"] | NonNullable<SelectItemKey>;
};
itemSelectable: unknown extends Defaults["itemSelectable"] ? {
type: PropType<SelectItemKey>;
default: null;
} : Omit<{
type: PropType<SelectItemKey>;
default: null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["itemSelectable"] ? SelectItemKey : Defaults["itemSelectable"] | SelectItemKey>;
default: unknown extends Defaults["itemSelectable"] ? SelectItemKey : Defaults["itemSelectable"] | NonNullable<SelectItemKey>;
};
rowProps: unknown extends Defaults["rowProps"] ? PropType<RowProps<any>> : {
type: PropType<unknown extends Defaults["rowProps"] ? RowProps<any> : Defaults["rowProps"] | RowProps<any>>;
default: unknown extends Defaults["rowProps"] ? RowProps<any> : Defaults["rowProps"] | NonNullable<RowProps<any>>;
};
cellProps: unknown extends Defaults["cellProps"] ? PropType<CellProps<any>> : {
type: PropType<unknown extends Defaults["cellProps"] ? CellProps<any> : Defaults["cellProps"] | CellProps<any>>;
default: unknown extends Defaults["cellProps"] ? CellProps<any> : Defaults["cellProps"] | NonNullable<CellProps<any>>;
};
returnObject: unknown extends Defaults["returnObject"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["returnObject"] ? boolean : boolean | Defaults["returnObject"]>;
default: unknown extends Defaults["returnObject"] ? boolean : boolean | Defaults["returnObject"];
};
};
export declare function transformItem(props: Omit<DataTableItemProps, 'items'>, item: any, index: number, columns: InternalDataTableHeader[]): DataTableItem;
export declare function transformItems(props: Omit<DataTableItemProps, 'items'>, items: DataTableItemProps['items'], columns: InternalDataTableHeader[]): DataTableItem[];
export declare function useDataTableItems(props: DataTableItemProps, columns: Ref<InternalDataTableHeader[]>): {
items: import("vue").ComputedRef<DataTableItem<any>[]>;
};
@@ -0,0 +1,48 @@
// Utilities
import { computed } from 'vue';
import { getPropertyFromItem, propsFactory } from "../../../util/index.js"; // Types
// Composables
export const makeDataTableItemsProps = propsFactory({
items: {
type: Array,
default: () => []
},
itemValue: {
type: [String, Array, Function],
default: 'id'
},
itemSelectable: {
type: [String, Array, Function],
default: null
},
rowProps: [Object, Function],
cellProps: [Object, Function],
returnObject: Boolean
}, 'DataTable-items');
export function transformItem(props, item, index, columns) {
const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue);
const selectable = getPropertyFromItem(item, props.itemSelectable, true);
const itemColumns = columns.reduce((obj, column) => {
if (column.key != null) obj[column.key] = getPropertyFromItem(item, column.value);
return obj;
}, {});
return {
type: 'item',
key: props.returnObject ? getPropertyFromItem(item, props.itemValue) : value,
index,
value,
selectable,
columns: itemColumns,
raw: item
};
}
export function transformItems(props, items, columns) {
return items.map((item, index) => transformItem(props, item, index, columns));
}
export function useDataTableItems(props, columns) {
const items = computed(() => transformItems(props, props.items, columns.value));
return {
items
};
}
//# sourceMappingURL=items.js.map
@@ -0,0 +1 @@
{"version":3,"file":"items.js","names":["computed","getPropertyFromItem","propsFactory","makeDataTableItemsProps","items","type","Array","default","itemValue","String","Function","itemSelectable","rowProps","Object","cellProps","returnObject","Boolean","transformItem","props","item","index","columns","value","selectable","itemColumns","reduce","obj","column","key","raw","transformItems","map","useDataTableItems"],"sources":["../../../../src/components/VDataTable/composables/items.ts"],"sourcesContent":["// Utilities\nimport { computed } from 'vue'\nimport { getPropertyFromItem, propsFactory } from '@/util'\n\n// Types\nimport type { PropType, Ref } from 'vue'\nimport type { CellProps, DataTableItem, InternalDataTableHeader, RowProps } from '../types'\nimport type { SelectItemKey } from '@/util'\n\nexport interface DataTableItemProps {\n items: any[]\n itemValue: SelectItemKey\n itemSelectable: SelectItemKey\n returnObject: boolean\n}\n\n// Composables\nexport const makeDataTableItemsProps = propsFactory({\n items: {\n type: Array as PropType<DataTableItemProps['items']>,\n default: () => ([]),\n },\n itemValue: {\n type: [String, Array, Function] as PropType<SelectItemKey>,\n default: 'id',\n },\n itemSelectable: {\n type: [String, Array, Function] as PropType<SelectItemKey>,\n default: null,\n },\n rowProps: [Object, Function] as PropType<RowProps<any>>,\n cellProps: [Object, Function] as PropType<CellProps<any>>,\n returnObject: Boolean,\n}, 'DataTable-items')\n\nexport function transformItem (\n props: Omit<DataTableItemProps, 'items'>,\n item: any,\n index: number,\n columns: InternalDataTableHeader[]\n): DataTableItem {\n const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue)\n const selectable = getPropertyFromItem(item, props.itemSelectable, true)\n const itemColumns = columns.reduce((obj, column) => {\n if (column.key != null) obj[column.key] = getPropertyFromItem(item, column.value!)\n return obj\n }, {} as Record<string, unknown>)\n\n return {\n type: 'item',\n key: props.returnObject ? getPropertyFromItem(item, props.itemValue) : value,\n index,\n value,\n selectable,\n columns: itemColumns,\n raw: item,\n }\n}\n\nexport function transformItems (\n props: Omit<DataTableItemProps, 'items'>,\n items: DataTableItemProps['items'],\n columns: InternalDataTableHeader[]\n): DataTableItem[] {\n return items.map((item, index) => transformItem(props, item, index, columns))\n}\n\nexport function useDataTableItems (props: DataTableItemProps, columns: Ref<InternalDataTableHeader[]>) {\n const items = computed(() => transformItems(props, props.items, columns.value))\n\n return { items }\n}\n"],"mappings":"AAAA;AACA,SAASA,QAAQ,QAAQ,KAAK;AAAA,SACrBC,mBAAmB,EAAEC,YAAY,kCAE1C;AAYA;AACA,OAAO,MAAMC,uBAAuB,GAAGD,YAAY,CAAC;EAClDE,KAAK,EAAE;IACLC,IAAI,EAAEC,KAA8C;IACpDC,OAAO,EAAEA,CAAA,KAAO;EAClB,CAAC;EACDC,SAAS,EAAE;IACTH,IAAI,EAAE,CAACI,MAAM,EAAEH,KAAK,EAAEI,QAAQ,CAA4B;IAC1DH,OAAO,EAAE;EACX,CAAC;EACDI,cAAc,EAAE;IACdN,IAAI,EAAE,CAACI,MAAM,EAAEH,KAAK,EAAEI,QAAQ,CAA4B;IAC1DH,OAAO,EAAE;EACX,CAAC;EACDK,QAAQ,EAAE,CAACC,MAAM,EAAEH,QAAQ,CAA4B;EACvDI,SAAS,EAAE,CAACD,MAAM,EAAEH,QAAQ,CAA6B;EACzDK,YAAY,EAAEC;AAChB,CAAC,EAAE,iBAAiB,CAAC;AAErB,OAAO,SAASC,aAAaA,CAC3BC,KAAwC,EACxCC,IAAS,EACTC,KAAa,EACbC,OAAkC,EACnB;EACf,MAAMC,KAAK,GAAGJ,KAAK,CAACH,YAAY,GAAGI,IAAI,GAAGlB,mBAAmB,CAACkB,IAAI,EAAED,KAAK,CAACV,SAAS,CAAC;EACpF,MAAMe,UAAU,GAAGtB,mBAAmB,CAACkB,IAAI,EAAED,KAAK,CAACP,cAAc,EAAE,IAAI,CAAC;EACxE,MAAMa,WAAW,GAAGH,OAAO,CAACI,MAAM,CAAC,CAACC,GAAG,EAAEC,MAAM,KAAK;IAClD,IAAIA,MAAM,CAACC,GAAG,IAAI,IAAI,EAAEF,GAAG,CAACC,MAAM,CAACC,GAAG,CAAC,GAAG3B,mBAAmB,CAACkB,IAAI,EAAEQ,MAAM,CAACL,KAAM,CAAC;IAClF,OAAOI,GAAG;EACZ,CAAC,EAAE,CAAC,CAA4B,CAAC;EAEjC,OAAO;IACLrB,IAAI,EAAE,MAAM;IACZuB,GAAG,EAAEV,KAAK,CAACH,YAAY,GAAGd,mBAAmB,CAACkB,IAAI,EAAED,KAAK,CAACV,SAAS,CAAC,GAAGc,KAAK;IAC5EF,KAAK;IACLE,KAAK;IACLC,UAAU;IACVF,OAAO,EAAEG,WAAW;IACpBK,GAAG,EAAEV;EACP,CAAC;AACH;AAEA,OAAO,SAASW,cAAcA,CAC5BZ,KAAwC,EACxCd,KAAkC,EAClCiB,OAAkC,EACjB;EACjB,OAAOjB,KAAK,CAAC2B,GAAG,CAAC,CAACZ,IAAI,EAAEC,KAAK,KAAKH,aAAa,CAACC,KAAK,EAAEC,IAAI,EAAEC,KAAK,EAAEC,OAAO,CAAC,CAAC;AAC/E;AAEA,OAAO,SAASW,iBAAiBA,CAAEd,KAAyB,EAAEG,OAAuC,EAAE;EACrG,MAAMjB,KAAK,GAAGJ,QAAQ,CAAC,MAAM8B,cAAc,CAACZ,KAAK,EAAEA,KAAK,CAACd,KAAK,EAAEiB,OAAO,CAACC,KAAK,CAAC,CAAC;EAE/E,OAAO;IAAElB;EAAM,CAAC;AAClB","ignoreList":[]}
@@ -0,0 +1,9 @@
import type { Ref } from 'vue';
import type { SortItem } from './sort.js';
export declare function useOptions({ page, itemsPerPage, sortBy, groupBy, search }: {
page: Ref<number>;
itemsPerPage: Ref<number>;
sortBy: Ref<readonly SortItem[]>;
groupBy: Ref<readonly SortItem[]>;
search: Ref<string | undefined>;
}): void;
@@ -0,0 +1,34 @@
// Utilities
import { watch } from 'vue';
import { deepEqual, getCurrentInstance } from "../../../util/index.js"; // Types
export function useOptions({
page,
itemsPerPage,
sortBy,
groupBy,
search
}) {
const vm = getCurrentInstance('VDataTable');
const options = () => ({
page: page.value,
itemsPerPage: itemsPerPage.value,
sortBy: sortBy.value,
groupBy: groupBy.value,
search: search.value
});
let oldOptions = null;
watch(options, value => {
if (deepEqual(oldOptions, value)) return;
// Reset page when searching
if (oldOptions && oldOptions.search !== value.search) {
page.value = 1;
}
vm.emit('update:options', value);
oldOptions = value;
}, {
deep: true,
immediate: true
});
}
//# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
{"version":3,"file":"options.js","names":["watch","deepEqual","getCurrentInstance","useOptions","page","itemsPerPage","sortBy","groupBy","search","vm","options","value","oldOptions","emit","deep","immediate"],"sources":["../../../../src/components/VDataTable/composables/options.ts"],"sourcesContent":["// Utilities\nimport { watch } from 'vue'\nimport { deepEqual, getCurrentInstance } from '@/util'\n\n// Types\nimport type { Ref } from 'vue'\nimport type { SortItem } from './sort'\n\nexport function useOptions ({\n page,\n itemsPerPage,\n sortBy,\n groupBy,\n search,\n}: {\n page: Ref<number>\n itemsPerPage: Ref<number>\n sortBy: Ref<readonly SortItem[]>\n groupBy: Ref<readonly SortItem[]>\n search: Ref<string | undefined>\n}) {\n const vm = getCurrentInstance('VDataTable')\n\n const options = () => ({\n page: page.value,\n itemsPerPage: itemsPerPage.value,\n sortBy: sortBy.value,\n groupBy: groupBy.value,\n search: search.value,\n })\n\n let oldOptions: ReturnType<typeof options> | null = null\n watch(options, value => {\n if (deepEqual(oldOptions, value)) return\n\n // Reset page when searching\n if (oldOptions && oldOptions.search !== value.search) {\n page.value = 1\n }\n\n vm.emit('update:options', value)\n oldOptions = value\n }, { deep: true, immediate: true })\n}\n"],"mappings":"AAAA;AACA,SAASA,KAAK,QAAQ,KAAK;AAAA,SAClBC,SAAS,EAAEC,kBAAkB,kCAEtC;AAIA,OAAO,SAASC,UAAUA,CAAE;EAC1BC,IAAI;EACJC,YAAY;EACZC,MAAM;EACNC,OAAO;EACPC;AAOF,CAAC,EAAE;EACD,MAAMC,EAAE,GAAGP,kBAAkB,CAAC,YAAY,CAAC;EAE3C,MAAMQ,OAAO,GAAGA,CAAA,MAAO;IACrBN,IAAI,EAAEA,IAAI,CAACO,KAAK;IAChBN,YAAY,EAAEA,YAAY,CAACM,KAAK;IAChCL,MAAM,EAAEA,MAAM,CAACK,KAAK;IACpBJ,OAAO,EAAEA,OAAO,CAACI,KAAK;IACtBH,MAAM,EAAEA,MAAM,CAACG;EACjB,CAAC,CAAC;EAEF,IAAIC,UAA6C,GAAG,IAAI;EACxDZ,KAAK,CAACU,OAAO,EAAEC,KAAK,IAAI;IACtB,IAAIV,SAAS,CAACW,UAAU,EAAED,KAAK,CAAC,EAAE;;IAElC;IACA,IAAIC,UAAU,IAAIA,UAAU,CAACJ,MAAM,KAAKG,KAAK,CAACH,MAAM,EAAE;MACpDJ,IAAI,CAACO,KAAK,GAAG,CAAC;IAChB;IAEAF,EAAE,CAACI,IAAI,CAAC,gBAAgB,EAAEF,KAAK,CAAC;IAChCC,UAAU,GAAGD,KAAK;EACpB,CAAC,EAAE;IAAEG,IAAI,EAAE,IAAI;IAAEC,SAAS,EAAE;EAAK,CAAC,CAAC;AACrC","ignoreList":[]}
@@ -0,0 +1,115 @@
import type { ComputedRef, MaybeRefOrGetter, PropType, Ref } from 'vue';
import type { Group, GroupableItem, GroupSummary } from './group.js';
import type { EventProp } from '../../../util/index.js';
export declare const makeDataTablePaginateProps: <Defaults extends {
page?: unknown;
itemsPerPage?: unknown;
pageBy?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
page: unknown extends Defaults["page"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["page"] ? string | number : string | number | Defaults["page"]>;
default: unknown extends Defaults["page"] ? string | number : Defaults["page"] | NonNullable<string | number>;
};
itemsPerPage: unknown extends Defaults["itemsPerPage"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["itemsPerPage"] ? string | number : string | number | Defaults["itemsPerPage"]>;
default: unknown extends Defaults["itemsPerPage"] ? string | number : Defaults["itemsPerPage"] | NonNullable<string | number>;
};
pageBy: unknown extends Defaults["pageBy"] ? {
type: PropType<'item' | 'any' | 'auto'>;
default: string;
} : Omit<{
type: PropType<'item' | 'any' | 'auto'>;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["pageBy"] ? "any" | "auto" | "item" : "any" | "auto" | "item" | Defaults["pageBy"]>;
default: unknown extends Defaults["pageBy"] ? "any" | "auto" | "item" : Defaults["pageBy"] | NonNullable<"any" | "auto" | "item">;
};
};
export type VDataTablePaginationInjectionData = {
page: Ref<number>;
itemsPerPage: Ref<number>;
startIndex: Ref<number>;
stopIndex: Ref<number>;
pageCount: Ref<number>;
itemsLength: Ref<number>;
prevPage: () => void;
nextPage: () => void;
setPage: (value: number) => void;
setItemsPerPage: (value: number) => void;
};
type PaginationProps = {
page: number | string;
'onUpdate:page': EventProp | undefined;
itemsPerPage: number | string;
'onUpdate:itemsPerPage': EventProp | undefined;
itemsLength?: number | string;
};
export declare function createPagination(props: PaginationProps): {
page: Ref<number, number> & {
readonly externalValue: string | number;
};
itemsPerPage: Ref<number, number> & {
readonly externalValue: string | number;
};
};
export declare function providePagination(options: {
page: Ref<number>;
itemsPerPage: Ref<number>;
itemsLength: Ref<number>;
}): {
page: Ref<number, number>;
itemsPerPage: Ref<number, number>;
startIndex: ComputedRef<number>;
stopIndex: ComputedRef<number>;
pageCount: ComputedRef<number>;
itemsLength: Ref<number, number>;
nextPage: () => void;
prevPage: () => void;
setPage: (value: number) => void;
setItemsPerPage: (value: number) => void;
};
export declare function usePagination(): VDataTablePaginationInjectionData;
export declare function usePaginatedItems<T>(options: {
items: MaybeRefOrGetter<readonly T[]>;
startIndex: Ref<number>;
stopIndex: Ref<number>;
itemsPerPage: Ref<number>;
}): {
paginatedItems: ComputedRef<readonly T[]>;
};
export declare function usePaginatedGroups<T extends GroupableItem>(options: {
pageBy: ComputedRef<'item' | 'group' | 'any'>;
sortedItems: Ref<readonly T[]>;
paginate: <TItem>(items: MaybeRefOrGetter<readonly TItem[]>) => {
paginatedItems: ComputedRef<readonly TItem[]>;
pageCount: ComputedRef<number>;
setItemsPerPage: (value: number) => void;
prevPage: () => void;
nextPage: () => void;
setPage: (value: number) => void;
};
group: (items: MaybeRefOrGetter<readonly T[]>) => {
flatItems: ComputedRef<readonly (T | Group<T> | GroupSummary<T>)[]>;
groups: ComputedRef<readonly Group<T>[]>;
};
}): {
pageCount: ComputedRef<number>;
setItemsPerPage: (value: number) => void;
prevPage: () => void;
nextPage: () => void;
setPage: (value: number) => void;
paginatedItems: ComputedRef<readonly (T | Group<T> | GroupSummary<T>)[]>;
};
@@ -0,0 +1,190 @@
// Composables
import { useProxiedModel } from "../../../composables/proxiedModel.js"; // Utilities
import { computed, inject, provide, toValue, watch } from 'vue';
import { clamp, getCurrentInstance, propsFactory } from "../../../util/index.js"; // Types
export const makeDataTablePaginateProps = propsFactory({
page: {
type: [Number, String],
default: 1
},
itemsPerPage: {
type: [Number, String],
default: 10
},
pageBy: {
type: String,
default: 'any'
}
}, 'DataTable-paginate');
const VDataTablePaginationSymbol = Symbol.for('vuetify:data-table-pagination');
export function createPagination(props) {
const page = useProxiedModel(props, 'page', undefined, value => Number(value ?? 1));
const itemsPerPage = useProxiedModel(props, 'itemsPerPage', undefined, value => Number(value ?? 10));
return {
page,
itemsPerPage
};
}
export function providePagination(options) {
const {
page,
itemsPerPage,
itemsLength
} = options;
const startIndex = computed(() => {
if (itemsPerPage.value === -1) return 0;
return itemsPerPage.value * (page.value - 1);
});
const stopIndex = computed(() => {
if (itemsPerPage.value === -1) return itemsLength.value;
return Math.min(itemsLength.value, startIndex.value + itemsPerPage.value);
});
const pageCount = computed(() => {
if (itemsPerPage.value === -1 || itemsLength.value === 0) return 1;
return Math.ceil(itemsLength.value / itemsPerPage.value);
});
// Don't run immediately, items may not have been loaded yet: #17966
watch([page, pageCount], () => {
if (page.value > pageCount.value) {
page.value = pageCount.value;
}
});
function setItemsPerPage(value) {
itemsPerPage.value = value;
page.value = 1;
}
function nextPage() {
page.value = clamp(page.value + 1, 1, pageCount.value);
}
function prevPage() {
page.value = clamp(page.value - 1, 1, pageCount.value);
}
function setPage(value) {
page.value = clamp(value, 1, pageCount.value);
}
const data = {
page,
itemsPerPage,
startIndex,
stopIndex,
pageCount,
itemsLength,
nextPage,
prevPage,
setPage,
setItemsPerPage
};
provide(VDataTablePaginationSymbol, data);
return data;
}
export function usePagination() {
const data = inject(VDataTablePaginationSymbol);
if (!data) throw new Error('Missing pagination!');
return data;
}
export function usePaginatedItems(options) {
const vm = getCurrentInstance('usePaginatedItems');
const {
items,
startIndex,
stopIndex,
itemsPerPage
} = options;
const paginatedItems = computed(() => {
if (itemsPerPage.value <= 0) return toValue(items);
return toValue(items).slice(startIndex.value, stopIndex.value);
});
watch(paginatedItems, val => {
vm.emit('update:currentItems', val);
}, {
immediate: true
});
return {
paginatedItems
};
}
export function usePaginatedGroups(options) {
const {
sortedItems,
paginate,
group
} = options;
const pageBy = toValue(options.pageBy); // TODO: make reactive
if (pageBy === 'item') {
const {
paginatedItems,
pageCount,
setItemsPerPage,
prevPage,
nextPage,
setPage
} = paginate(sortedItems);
const {
flatItems: paginatedItemsWithGroups
} = group(paginatedItems);
return {
pageCount,
setItemsPerPage,
prevPage,
nextPage,
setPage,
paginatedItems: paginatedItemsWithGroups
};
}
if (pageBy === 'group') {
const {
flatItems,
groups
} = group(sortedItems);
const {
paginatedItems: paginatedGroups,
pageCount,
setItemsPerPage,
prevPage,
nextPage,
setPage
} = paginate(groups);
const paginatedItemsWithGroups = computed(() => {
if (!paginatedGroups.value.length) return [];
const firstGroupId = paginatedGroups.value.at(0).id;
const lastGroupId = paginatedGroups.value.at(-1).id;
const start = flatItems.value.findIndex(item => item.type === 'group' && item.id === firstGroupId);
const lastGroupIndex = flatItems.value.findIndex(item => item.type === 'group' && item.id === lastGroupId);
const stop = flatItems.value.findIndex((item, i) => i > lastGroupIndex && item.type === 'group' && item.depth === 0);
return flatItems.value.slice(start, stop === -1 ? undefined : stop);
});
return {
pageCount,
setItemsPerPage,
prevPage,
nextPage,
setPage,
paginatedItems: paginatedItemsWithGroups
};
}
if (pageBy === 'any') {
const {
flatItems
} = group(sortedItems);
const {
paginatedItems: paginatedItemsWithGroups,
pageCount,
setItemsPerPage,
prevPage,
nextPage,
setPage
} = paginate(flatItems);
return {
pageCount,
setItemsPerPage,
prevPage,
nextPage,
setPage,
paginatedItems: paginatedItemsWithGroups
};
}
throw new Error(`Unrecognized pagination target ${pageBy}`);
}
//# sourceMappingURL=paginate.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,95 @@
import type { InjectionKey, MaybeRefOrGetter, PropType, Ref } from 'vue';
import type { DataTableItemProps } from './items.js';
import type { EventProp, ValueComparator } from '../../../util/index.js';
export interface SelectableItem {
value: any;
selectable: boolean;
}
export interface DataTableSelectStrategy {
showSelectAll: boolean;
allSelected: (data: {
allItems: SelectableItem[];
currentPage: SelectableItem[];
}) => SelectableItem[];
select: (data: {
items: SelectableItem[];
value: boolean;
selected: Set<unknown>;
}) => Set<unknown>;
selectAll: (data: {
value: boolean;
allItems: SelectableItem[];
currentPage: SelectableItem[];
selected: Set<unknown>;
}) => Set<unknown>;
}
type SelectionProps = Pick<DataTableItemProps, 'itemValue'> & {
modelValue: readonly any[];
selectStrategy: 'single' | 'page' | 'all';
valueComparator?: ValueComparator;
'onUpdate:modelValue': EventProp<[any[]]> | undefined;
};
export declare const makeDataTableSelectProps: <Defaults extends {
showSelect?: unknown;
selectStrategy?: unknown;
modelValue?: unknown;
valueComparator?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
showSelect: unknown extends Defaults["showSelect"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["showSelect"] ? boolean : boolean | Defaults["showSelect"]>;
default: unknown extends Defaults["showSelect"] ? boolean : boolean | Defaults["showSelect"];
};
selectStrategy: unknown extends Defaults["selectStrategy"] ? {
type: PropType<'single' | 'page' | 'all'>;
default: string;
} : Omit<{
type: PropType<'single' | 'page' | 'all'>;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["selectStrategy"] ? "all" | "page" | "single" : "all" | "page" | "single" | Defaults["selectStrategy"]>;
default: unknown extends Defaults["selectStrategy"] ? "all" | "page" | "single" : Defaults["selectStrategy"] | NonNullable<"all" | "page" | "single">;
};
modelValue: unknown extends Defaults["modelValue"] ? {
type: PropType<readonly any[]>;
default: () => never[];
} : Omit<{
type: PropType<readonly any[]>;
default: () => never[];
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["modelValue"] ? readonly any[] : readonly any[] | Defaults["modelValue"]>;
default: unknown extends Defaults["modelValue"] ? readonly any[] : readonly any[] | Defaults["modelValue"];
};
valueComparator: unknown extends Defaults["valueComparator"] ? PropType<ValueComparator> : {
type: PropType<unknown extends Defaults["valueComparator"] ? ValueComparator : ValueComparator | Defaults["valueComparator"]>;
default: unknown extends Defaults["valueComparator"] ? ValueComparator : ValueComparator | Defaults["valueComparator"];
};
};
export declare const VDataTableSelectionSymbol: InjectionKey<ReturnType<typeof provideSelection>>;
export declare function provideSelection(props: SelectionProps, { allItems, currentPage }: {
allItems: Ref<SelectableItem[]>;
currentPage: MaybeRefOrGetter<readonly SelectableItem[]>;
}): {
toggleSelect: (item: SelectableItem, index?: number, event?: MouseEvent) => void;
select: (items: SelectableItem[], value: boolean) => void;
selectAll: (value: boolean) => void;
isSelected: (items: SelectableItem | SelectableItem[]) => boolean;
isSomeSelected: (items: SelectableItem | SelectableItem[]) => boolean;
someSelected: import("vue").ComputedRef<boolean>;
allSelected: import("vue").ComputedRef<boolean>;
showSelectAll: Readonly<Ref<boolean, boolean>>;
lastSelectedIndex: import("vue").ShallowRef<number | null, number | null>;
selectStrategy: import("vue").ComputedRef<DataTableSelectStrategy>;
};
export declare function useSelection(): {
toggleSelect: (item: SelectableItem, index?: number, event?: MouseEvent) => void;
select: (items: SelectableItem[], value: boolean) => void;
selectAll: (value: boolean) => void;
isSelected: (items: SelectableItem | SelectableItem[]) => boolean;
isSomeSelected: (items: SelectableItem | SelectableItem[]) => boolean;
someSelected: import("vue").ComputedRef<boolean>;
allSelected: import("vue").ComputedRef<boolean>;
showSelectAll: Readonly<Ref<boolean, boolean>>;
lastSelectedIndex: import("vue").ShallowRef<number | null, number | null>;
selectStrategy: import("vue").ComputedRef<DataTableSelectStrategy>;
};
@@ -0,0 +1,175 @@
// Composables
import { useProxiedModel } from "../../../composables/proxiedModel.js"; // Utilities
import { computed, inject, provide, shallowRef, toRef, toValue } from 'vue';
import { deepEqual, isPrimitive, propsFactory, wrapInArray } from "../../../util/index.js"; // Types
const singleSelectStrategy = {
showSelectAll: false,
allSelected: () => [],
select: ({
items,
value
}) => {
return new Set(value ? [items[0]?.value] : []);
},
selectAll: ({
selected
}) => selected
};
const pageSelectStrategy = {
showSelectAll: true,
allSelected: ({
currentPage
}) => currentPage,
select: ({
items,
value,
selected
}) => {
for (const item of items) {
if (value) selected.add(item.value);else selected.delete(item.value);
}
return selected;
},
selectAll: ({
value,
currentPage,
selected
}) => pageSelectStrategy.select({
items: currentPage,
value,
selected
})
};
const allSelectStrategy = {
showSelectAll: true,
allSelected: ({
allItems
}) => allItems,
select: ({
items,
value,
selected
}) => {
for (const item of items) {
if (value) selected.add(item.value);else selected.delete(item.value);
}
return selected;
},
selectAll: ({
value,
allItems
}) => {
return new Set(value ? allItems.map(item => item.value) : []);
}
};
export const makeDataTableSelectProps = propsFactory({
showSelect: Boolean,
selectStrategy: {
type: [String, Object],
default: 'page'
},
modelValue: {
type: Array,
default: () => []
},
valueComparator: Function
}, 'DataTable-select');
export const VDataTableSelectionSymbol = Symbol.for('vuetify:data-table-selection');
export function provideSelection(props, {
allItems,
currentPage
}) {
const selected = useProxiedModel(props, 'modelValue', props.modelValue, v => {
const customComparator = props.valueComparator;
if (customComparator) {
return new Set(wrapInArray(v).map(v => {
return allItems.value.find(item => customComparator(v, item.value))?.value ?? v;
}));
}
return new Set(wrapInArray(v).map(v => {
return isPrimitive(v) ? allItems.value.find(item => v === item.value)?.value ?? v : allItems.value.find(item => deepEqual(v, item.value))?.value ?? v;
}));
}, v => {
return [...v.values()];
});
const allSelectable = computed(() => allItems.value.filter(item => item.selectable));
const currentPageSelectable = computed(() => toValue(currentPage).filter(item => item.selectable));
const selectStrategy = computed(() => {
if (typeof props.selectStrategy === 'object') return props.selectStrategy;
switch (props.selectStrategy) {
case 'single':
return singleSelectStrategy;
case 'all':
return allSelectStrategy;
case 'page':
default:
return pageSelectStrategy;
}
});
const lastSelectedIndex = shallowRef(null);
function isSelected(items) {
return wrapInArray(items).every(item => selected.value.has(item.value));
}
function isSomeSelected(items) {
return wrapInArray(items).some(item => selected.value.has(item.value));
}
function select(items, value) {
const newSelected = selectStrategy.value.select({
items,
value,
selected: new Set(selected.value)
});
selected.value = newSelected;
}
function toggleSelect(item, index, event) {
const items = [];
const pageItems = toValue(currentPage);
index = index ?? pageItems.findIndex(i => i.value === item.value);
if (props.selectStrategy !== 'single' && event?.shiftKey && lastSelectedIndex.value !== null) {
const [start, end] = [lastSelectedIndex.value, index].sort((a, b) => a - b);
items.push(...pageItems.slice(start, end + 1).filter(item => item.selectable));
} else {
items.push(item);
lastSelectedIndex.value = index;
}
select(items, !isSelected([item]));
}
function selectAll(value) {
const newSelected = selectStrategy.value.selectAll({
value,
allItems: allSelectable.value,
currentPage: currentPageSelectable.value,
selected: new Set(selected.value)
});
selected.value = newSelected;
}
const someSelected = computed(() => selected.value.size > 0);
const allSelected = computed(() => {
const items = selectStrategy.value.allSelected({
allItems: allSelectable.value,
currentPage: currentPageSelectable.value
});
return !!items.length && isSelected(items);
});
const showSelectAll = toRef(() => selectStrategy.value.showSelectAll);
const data = {
toggleSelect,
select,
selectAll,
isSelected,
isSomeSelected,
someSelected,
allSelected,
showSelectAll,
lastSelectedIndex,
selectStrategy
};
provide(VDataTableSelectionSymbol, data);
return data;
}
export function useSelection() {
const data = inject(VDataTableSelectionSymbol);
if (!data) throw new Error('Missing selection!');
return data;
}
//# sourceMappingURL=select.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,107 @@
import type { PropType, Ref } from 'vue';
import type { DataTableCompareFunction, InternalDataTableHeader } from '../types.js';
import type { InternalItem } from '../../../composables/filter.js';
export declare const makeDataTableSortProps: <Defaults extends {
initialSortOrder?: unknown;
sortBy?: unknown;
customKeySort?: unknown;
multiSort?: unknown;
mustSort?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
initialSortOrder: unknown extends Defaults["initialSortOrder"] ? {
type: PropType<'asc' | 'desc'>;
default: string;
validator: (v: any) => boolean;
} : Omit<{
type: PropType<'asc' | 'desc'>;
default: string;
validator: (v: any) => boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["initialSortOrder"] ? "asc" | "desc" : "asc" | "desc" | Defaults["initialSortOrder"]>;
default: unknown extends Defaults["initialSortOrder"] ? "asc" | "desc" : Defaults["initialSortOrder"] | NonNullable<"asc" | "desc">;
};
sortBy: unknown extends Defaults["sortBy"] ? {
type: PropType<readonly SortItem[]>;
default: () => never[];
} : Omit<{
type: PropType<readonly SortItem[]>;
default: () => never[];
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["sortBy"] ? readonly SortItem[] : readonly SortItem[] | Defaults["sortBy"]>;
default: unknown extends Defaults["sortBy"] ? readonly SortItem[] : readonly SortItem[] | Defaults["sortBy"];
};
customKeySort: unknown extends Defaults["customKeySort"] ? PropType<Record<string, DataTableCompareFunction>> : {
type: PropType<unknown extends Defaults["customKeySort"] ? Record<string, DataTableCompareFunction> : Record<string, DataTableCompareFunction> | Defaults["customKeySort"]>;
default: unknown extends Defaults["customKeySort"] ? Record<string, DataTableCompareFunction> : Record<string, DataTableCompareFunction> | Defaults["customKeySort"];
};
multiSort: unknown extends Defaults["multiSort"] ? {
type: PropType<boolean | MultiSortProps>;
default: boolean;
} : Omit<{
type: PropType<boolean | MultiSortProps>;
default: boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["multiSort"] ? boolean | MultiSortProps : boolean | MultiSortProps | Defaults["multiSort"]>;
default: unknown extends Defaults["multiSort"] ? boolean | MultiSortProps : Defaults["multiSort"] | NonNullable<boolean | MultiSortProps>;
};
mustSort: unknown extends Defaults["mustSort"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["mustSort"] ? boolean : boolean | Defaults["mustSort"]>;
default: unknown extends Defaults["mustSort"] ? boolean : boolean | Defaults["mustSort"];
};
};
export type SortItem = {
key: string;
order?: boolean | 'asc' | 'desc';
};
export type MultiSortProps = {
key?: 'ctrl';
mode?: MultiSortMode;
modifier?: 'alt' | 'shift';
};
export type MultiSortMode = 'append' | 'prepend';
type SortProps = {
initialSortOrder: 'asc' | 'desc';
sortBy: readonly SortItem[];
'onUpdate:sortBy': ((value: any) => void) | undefined;
multiSort: boolean | MultiSortProps;
mustSort: boolean;
};
export declare function createSort(props: SortProps): {
initialSortOrder: Readonly<Ref<"asc" | "desc", "asc" | "desc">>;
sortBy: Ref<readonly SortItem[], readonly SortItem[]> & {
readonly externalValue: readonly SortItem[];
};
multiSort: Readonly<Ref<boolean | MultiSortProps, boolean | MultiSortProps>>;
mustSort: Readonly<Ref<boolean, boolean>>;
};
export declare function provideSort(options: {
initialSortOrder: Ref<'asc' | 'desc'>;
sortBy: Ref<readonly SortItem[]>;
multiSort: Ref<boolean | MultiSortProps>;
mustSort: Ref<boolean>;
page?: Ref<number>;
}): {
sortBy: Ref<readonly SortItem[], readonly SortItem[]>;
toggleSort: (column: InternalDataTableHeader, event?: KeyboardEvent | PointerEvent, mandatory?: boolean) => void;
isSorted: (column: InternalDataTableHeader) => boolean;
};
export declare function useSort(): {
sortBy: Ref<readonly SortItem[]>;
toggleSort: (column: InternalDataTableHeader, event?: KeyboardEvent | PointerEvent, mandatory?: boolean) => void;
isSorted: (column: InternalDataTableHeader) => boolean;
};
export declare function useSortedItems<T extends InternalItem>(props: {
customKeySort: Record<string, DataTableCompareFunction> | undefined;
}, items: Ref<T[]>, sortBy: Ref<readonly SortItem[]>, options?: {
transform?: (item: T) => {};
sortFunctions?: Ref<Record<string, DataTableCompareFunction> | undefined>;
sortRawFunctions?: Ref<Record<string, DataTableCompareFunction> | undefined>;
}): {
sortedItems: import("vue").ComputedRef<T[]>;
};
export declare function sortItems<T extends InternalItem>(items: T[], sortByItems: readonly SortItem[], locale: string, options?: {
transform?: (item: T) => Record<string, any>;
sortFunctions?: Record<string, DataTableCompareFunction>;
sortRawFunctions?: Record<string, DataTableCompareFunction>;
}): T[];
@@ -0,0 +1,190 @@
// Composables
import { useLocale } from "../../../composables/locale.js";
import { useProxiedModel } from "../../../composables/proxiedModel.js"; // Utilities
import { computed, inject, provide, toRef } from 'vue';
import { getObjectValueByPath, isEmpty, isObject, propsFactory } from "../../../util/index.js"; // Types
export const makeDataTableSortProps = propsFactory({
initialSortOrder: {
type: String,
default: 'asc',
validator: v => !v || ['asc', 'desc'].includes(v)
},
sortBy: {
type: Array,
default: () => []
},
customKeySort: Object,
multiSort: {
type: [Boolean, Object],
default: false
},
mustSort: Boolean
}, 'DataTable-sort');
const VDataTableSortSymbol = Symbol.for('vuetify:data-table-sort');
export function createSort(props) {
const initialSortOrder = toRef(() => props.initialSortOrder);
const sortBy = useProxiedModel(props, 'sortBy');
const mustSort = toRef(() => props.mustSort);
const multiSort = toRef(() => props.multiSort);
return {
initialSortOrder,
sortBy,
multiSort,
mustSort
};
}
function resolveMultiSort(multiSort, event) {
if (!isObject(multiSort)) {
return {
active: !!multiSort
};
}
const {
key,
mode,
modifier
} = multiSort;
const reverseMode = modifier === 'alt' && event?.altKey || modifier === 'shift' && event?.shiftKey;
return {
active: !key || event?.ctrlKey || event?.metaKey || false,
mode: reverseMode ? mode === 'append' ? 'prepend' : 'append' : mode
};
}
export function provideSort(options) {
const {
initialSortOrder,
sortBy,
mustSort,
multiSort,
page
} = options;
const toggleSort = (column, event, mandatory = false) => {
if (column.key == null) return;
let newSortBy = sortBy.value.map(x => ({
...x
})) ?? [];
const item = newSortBy.find(x => x.key === column.key);
const initialOrder = initialSortOrder.value;
const secondaryOrder = initialSortOrder.value === 'desc' ? 'asc' : 'desc';
if (!item) {
const {
active,
mode
} = resolveMultiSort(multiSort.value, event);
if (active) {
if (mode === 'prepend') {
newSortBy.unshift({
key: column.key,
order: initialOrder
});
} else {
newSortBy.push({
key: column.key,
order: initialOrder
});
}
} else {
newSortBy = [{
key: column.key,
order: initialOrder
}];
}
} else if (item.order === secondaryOrder) {
if (mandatory || mustSort.value && newSortBy.length === 1) {
item.order = initialSortOrder.value;
} else {
newSortBy = newSortBy.filter(x => x.key !== column.key);
}
} else {
item.order = secondaryOrder;
}
sortBy.value = newSortBy;
if (page) page.value = 1;
};
function isSorted(column) {
return !!sortBy.value.find(item => item.key === column.key);
}
const data = {
sortBy,
toggleSort,
isSorted
};
provide(VDataTableSortSymbol, data);
return data;
}
export function useSort() {
const data = inject(VDataTableSortSymbol);
if (!data) throw new Error('Missing sort!');
return data;
}
// TODO: abstract into project composable
export function useSortedItems(props, items, sortBy, options) {
const locale = useLocale();
const sortedItems = computed(() => {
if (!sortBy.value.length) return items.value;
return sortItems(items.value, sortBy.value, locale.current.value, {
transform: options?.transform,
sortFunctions: {
...props.customKeySort,
...options?.sortFunctions?.value
},
sortRawFunctions: options?.sortRawFunctions?.value
});
});
return {
sortedItems
};
}
export function sortItems(items, sortByItems, locale, options) {
const stringCollator = new Intl.Collator(locale, {
sensitivity: 'accent',
usage: 'sort'
});
const transformedItems = items.map(item => [item, options?.transform ? options.transform(item) : item]);
return transformedItems.sort((a, b) => {
for (let i = 0; i < sortByItems.length; i++) {
let hasCustomResult = false;
const sortKey = sortByItems[i].key;
const sortOrder = sortByItems[i].order ?? 'asc';
if (sortOrder === false) continue;
let sortA = getObjectValueByPath(a[1], sortKey);
let sortB = getObjectValueByPath(b[1], sortKey);
let sortARaw = a[0].raw;
let sortBRaw = b[0].raw;
if (sortOrder === 'desc') {
[sortA, sortB] = [sortB, sortA];
[sortARaw, sortBRaw] = [sortBRaw, sortARaw];
}
if (options?.sortRawFunctions?.[sortKey]) {
const customResult = options.sortRawFunctions[sortKey](sortARaw, sortBRaw);
if (customResult == null) continue;
hasCustomResult = true;
if (customResult) return customResult;
}
if (options?.sortFunctions?.[sortKey]) {
const customResult = options.sortFunctions[sortKey](sortA, sortB);
if (customResult == null) continue;
hasCustomResult = true;
if (customResult) return customResult;
}
if (hasCustomResult) continue;
// Dates should be compared numerically
if (sortA instanceof Date && sortB instanceof Date) {
sortA = sortA.getTime();
sortB = sortB.getTime();
}
[sortA, sortB] = [sortA, sortB].map(s => s != null ? s.toString().toLocaleLowerCase() : s);
if (sortA !== sortB) {
if (isEmpty(sortA) && isEmpty(sortB)) return 0;
if (isEmpty(sortA)) return -1;
if (isEmpty(sortB)) return 1;
if (!isNaN(sortA) && !isNaN(sortB)) return Number(sortA) - Number(sortB);
return stringCollator.compare(sortA, sortB);
}
}
return 0;
}).map(([item]) => item);
}
//# sourceMappingURL=sort.js.map
File diff suppressed because one or more lines are too long