routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+44
@@ -0,0 +1,44 @@
|
||||
@layer vuetify-components {
|
||||
.v-infinite-scroll--horizontal {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow-x: auto;
|
||||
}
|
||||
.v-infinite-scroll--horizontal .v-infinite-scroll-intersect {
|
||||
height: 100%;
|
||||
width: var(--v-infinite-margin-size, 1px);
|
||||
}
|
||||
.v-infinite-scroll--vertical {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.v-infinite-scroll--vertical .v-infinite-scroll-intersect {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
}
|
||||
.v-infinite-scroll-intersect {
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
margin-top: var(--v-infinite-margin);
|
||||
margin-bottom: calc(var(--v-infinite-margin) * -1);
|
||||
}
|
||||
.v-infinite-scroll-intersect:nth-child(2) {
|
||||
--v-infinite-margin: var(--v-infinite-margin-size, 1px);
|
||||
}
|
||||
.v-infinite-scroll-intersect:nth-last-child(2) {
|
||||
--v-infinite-margin: calc(var(--v-infinite-margin-size, 1px) * -1);
|
||||
}
|
||||
.v-infinite-scroll__side {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 8px;
|
||||
transition-property: padding;
|
||||
transition-duration: 0.3s;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.v-infinite-scroll__side:empty, .v-infinite-scroll__side:has(> div:only-child:empty) {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+464
@@ -0,0 +1,464 @@
|
||||
|
||||
import type { PropType } from 'vue';
|
||||
export type InfiniteScrollSide = 'start' | 'end' | 'both';
|
||||
export type InfiniteScrollStatus = 'ok' | 'empty' | 'loading' | 'error';
|
||||
type InfiniteScrollSlot = {
|
||||
side: InfiniteScrollSide;
|
||||
props: Record<string, any>;
|
||||
};
|
||||
export declare const makeVInfiniteScrollProps: <Defaults extends {
|
||||
tag?: unknown;
|
||||
height?: unknown;
|
||||
maxHeight?: unknown;
|
||||
maxWidth?: unknown;
|
||||
minHeight?: unknown;
|
||||
minWidth?: unknown;
|
||||
width?: unknown;
|
||||
color?: unknown;
|
||||
direction?: unknown;
|
||||
side?: unknown;
|
||||
mode?: unknown;
|
||||
margin?: unknown;
|
||||
loadMoreText?: unknown;
|
||||
emptyText?: unknown;
|
||||
} = {}>(defaults?: Defaults | undefined) => {
|
||||
tag: unknown extends Defaults["tag"] ? {
|
||||
type: PropType<string | import("../../util/index.js").JSXComponent>;
|
||||
default: string;
|
||||
} : Omit<{
|
||||
type: PropType<string | import("../../util/index.js").JSXComponent>;
|
||||
default: string;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["tag"] ? string | import("../../util/index.js").JSXComponent : string | Defaults["tag"] | import("../../util/index.js").JSXComponent>;
|
||||
default: unknown extends Defaults["tag"] ? string | import("../../util/index.js").JSXComponent : Defaults["tag"] | NonNullable<string | import("../../util/index.js").JSXComponent>;
|
||||
};
|
||||
height: unknown extends Defaults["height"] ? (NumberConstructor | StringConstructor)[] : {
|
||||
type: PropType<unknown extends Defaults["height"] ? string | number : string | number | Defaults["height"]>;
|
||||
default: unknown extends Defaults["height"] ? string | number : Defaults["height"] | NonNullable<string | number>;
|
||||
};
|
||||
maxHeight: unknown extends Defaults["maxHeight"] ? (NumberConstructor | StringConstructor)[] : {
|
||||
type: PropType<unknown extends Defaults["maxHeight"] ? string | number : string | number | Defaults["maxHeight"]>;
|
||||
default: unknown extends Defaults["maxHeight"] ? string | number : Defaults["maxHeight"] | NonNullable<string | number>;
|
||||
};
|
||||
maxWidth: unknown extends Defaults["maxWidth"] ? (NumberConstructor | StringConstructor)[] : {
|
||||
type: PropType<unknown extends Defaults["maxWidth"] ? string | number : string | number | Defaults["maxWidth"]>;
|
||||
default: unknown extends Defaults["maxWidth"] ? string | number : Defaults["maxWidth"] | NonNullable<string | number>;
|
||||
};
|
||||
minHeight: unknown extends Defaults["minHeight"] ? (NumberConstructor | StringConstructor)[] : {
|
||||
type: PropType<unknown extends Defaults["minHeight"] ? string | number : string | number | Defaults["minHeight"]>;
|
||||
default: unknown extends Defaults["minHeight"] ? string | number : Defaults["minHeight"] | NonNullable<string | number>;
|
||||
};
|
||||
minWidth: unknown extends Defaults["minWidth"] ? (NumberConstructor | StringConstructor)[] : {
|
||||
type: PropType<unknown extends Defaults["minWidth"] ? string | number : string | number | Defaults["minWidth"]>;
|
||||
default: unknown extends Defaults["minWidth"] ? string | number : Defaults["minWidth"] | NonNullable<string | number>;
|
||||
};
|
||||
width: unknown extends Defaults["width"] ? (NumberConstructor | StringConstructor)[] : {
|
||||
type: PropType<unknown extends Defaults["width"] ? string | number : string | number | Defaults["width"]>;
|
||||
default: unknown extends Defaults["width"] ? string | number : Defaults["width"] | NonNullable<string | number>;
|
||||
};
|
||||
color: unknown extends Defaults["color"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["color"] ? string : string | Defaults["color"]>;
|
||||
default: unknown extends Defaults["color"] ? string : string | Defaults["color"];
|
||||
};
|
||||
direction: unknown extends Defaults["direction"] ? {
|
||||
type: PropType<'vertical' | 'horizontal'>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
} : Omit<{
|
||||
type: PropType<'vertical' | 'horizontal'>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["direction"] ? "horizontal" | "vertical" : "horizontal" | "vertical" | Defaults["direction"]>;
|
||||
default: unknown extends Defaults["direction"] ? "horizontal" | "vertical" : Defaults["direction"] | NonNullable<"horizontal" | "vertical">;
|
||||
};
|
||||
side: unknown extends Defaults["side"] ? {
|
||||
type: PropType<InfiniteScrollSide>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
} : Omit<{
|
||||
type: PropType<InfiniteScrollSide>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["side"] ? InfiniteScrollSide : Defaults["side"] | InfiniteScrollSide>;
|
||||
default: unknown extends Defaults["side"] ? InfiniteScrollSide : Defaults["side"] | NonNullable<InfiniteScrollSide>;
|
||||
};
|
||||
mode: unknown extends Defaults["mode"] ? {
|
||||
type: PropType<'intersect' | 'manual'>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
} : Omit<{
|
||||
type: PropType<'intersect' | 'manual'>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["mode"] ? "intersect" | "manual" : "intersect" | "manual" | Defaults["mode"]>;
|
||||
default: unknown extends Defaults["mode"] ? "intersect" | "manual" : Defaults["mode"] | NonNullable<"intersect" | "manual">;
|
||||
};
|
||||
margin: unknown extends Defaults["margin"] ? (NumberConstructor | StringConstructor)[] : {
|
||||
type: PropType<unknown extends Defaults["margin"] ? string | number : string | number | Defaults["margin"]>;
|
||||
default: unknown extends Defaults["margin"] ? string | number : Defaults["margin"] | NonNullable<string | number>;
|
||||
};
|
||||
loadMoreText: unknown extends Defaults["loadMoreText"] ? {
|
||||
type: StringConstructor;
|
||||
default: string;
|
||||
} : Omit<{
|
||||
type: StringConstructor;
|
||||
default: string;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["loadMoreText"] ? string : string | Defaults["loadMoreText"]>;
|
||||
default: unknown extends Defaults["loadMoreText"] ? string : string | Defaults["loadMoreText"];
|
||||
};
|
||||
emptyText: unknown extends Defaults["emptyText"] ? {
|
||||
type: StringConstructor;
|
||||
default: string;
|
||||
} : Omit<{
|
||||
type: StringConstructor;
|
||||
default: string;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["emptyText"] ? string : string | Defaults["emptyText"]>;
|
||||
default: unknown extends Defaults["emptyText"] ? string : string | Defaults["emptyText"];
|
||||
};
|
||||
};
|
||||
export declare const VInfiniteScrollIntersect: {
|
||||
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("vue").ExtractPropTypes<{
|
||||
side: {
|
||||
type: PropType<InfiniteScrollSide>;
|
||||
required: true;
|
||||
};
|
||||
rootMargin: StringConstructor;
|
||||
}>> & {
|
||||
onIntersect?: ((side: InfiniteScrollSide, isIntersecting: boolean) => any) | undefined;
|
||||
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
intersect: (side: InfiniteScrollSide, isIntersecting: boolean) => true;
|
||||
}, import("vue").PublicProps, {}, true, {}, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
|
||||
P: {};
|
||||
B: {};
|
||||
D: {};
|
||||
C: {};
|
||||
M: {};
|
||||
Defaults: {};
|
||||
}, Readonly<import("vue").ExtractPropTypes<{
|
||||
side: {
|
||||
type: PropType<InfiniteScrollSide>;
|
||||
required: true;
|
||||
};
|
||||
rootMargin: StringConstructor;
|
||||
}>> & {
|
||||
onIntersect?: ((side: InfiniteScrollSide, isIntersecting: boolean) => any) | undefined;
|
||||
}, {}, {}, {}, {}, {}>;
|
||||
__isFragment?: never;
|
||||
__isTeleport?: never;
|
||||
__isSuspense?: never;
|
||||
} & import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
|
||||
side: {
|
||||
type: PropType<InfiniteScrollSide>;
|
||||
required: true;
|
||||
};
|
||||
rootMargin: StringConstructor;
|
||||
}>> & {
|
||||
onIntersect?: ((side: InfiniteScrollSide, isIntersecting: boolean) => any) | undefined;
|
||||
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
intersect: (side: InfiniteScrollSide, isIntersecting: boolean) => true;
|
||||
}, string, {}, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & import("../../util/index.js").FilterPropsOptions<{
|
||||
side: {
|
||||
type: PropType<InfiniteScrollSide>;
|
||||
required: true;
|
||||
};
|
||||
rootMargin: StringConstructor;
|
||||
}, import("vue").ExtractPropTypes<{
|
||||
side: {
|
||||
type: PropType<InfiniteScrollSide>;
|
||||
required: true;
|
||||
};
|
||||
rootMargin: StringConstructor;
|
||||
}>>;
|
||||
export declare const VInfiniteScroll: {
|
||||
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<{
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
direction: "horizontal" | "vertical";
|
||||
side: InfiniteScrollSide;
|
||||
mode: "intersect" | "manual";
|
||||
loadMoreText: string;
|
||||
emptyText: string;
|
||||
} & {
|
||||
height?: string | number | undefined;
|
||||
maxHeight?: string | number | undefined;
|
||||
maxWidth?: string | number | undefined;
|
||||
minHeight?: string | number | undefined;
|
||||
minWidth?: string | number | undefined;
|
||||
width?: string | number | undefined;
|
||||
color?: string | undefined;
|
||||
margin?: string | number | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
loading?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
error?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
empty?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
'load-more'?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
loading?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
error?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
empty?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
'load-more'?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:empty"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:error"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:load-more"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:loading"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
onLoad?: ((options: {
|
||||
side: InfiniteScrollSide;
|
||||
done: (status: InfiniteScrollStatus) => void;
|
||||
}) => any) | undefined;
|
||||
}, {
|
||||
reset: (side?: InfiniteScrollSide) => void;
|
||||
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
load: (options: {
|
||||
side: InfiniteScrollSide;
|
||||
done: (status: InfiniteScrollStatus) => void;
|
||||
}) => true;
|
||||
}, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, {
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
direction: "horizontal" | "vertical";
|
||||
side: InfiniteScrollSide;
|
||||
mode: "intersect" | "manual";
|
||||
loadMoreText: string;
|
||||
emptyText: string;
|
||||
}, true, {}, import("vue").SlotsType<Partial<{
|
||||
default: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
loading: (arg: InfiniteScrollSlot) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
error: (arg: InfiniteScrollSlot) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
empty: (arg: InfiniteScrollSlot) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
'load-more': (arg: InfiniteScrollSlot) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
}>>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
|
||||
P: {};
|
||||
B: {};
|
||||
D: {};
|
||||
C: {};
|
||||
M: {};
|
||||
Defaults: {};
|
||||
}, {
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
direction: "horizontal" | "vertical";
|
||||
side: InfiniteScrollSide;
|
||||
mode: "intersect" | "manual";
|
||||
loadMoreText: string;
|
||||
emptyText: string;
|
||||
} & {
|
||||
height?: string | number | undefined;
|
||||
maxHeight?: string | number | undefined;
|
||||
maxWidth?: string | number | undefined;
|
||||
minHeight?: string | number | undefined;
|
||||
minWidth?: string | number | undefined;
|
||||
width?: string | number | undefined;
|
||||
color?: string | undefined;
|
||||
margin?: string | number | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
loading?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
error?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
empty?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
'load-more'?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
loading?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
error?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
empty?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
'load-more'?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:empty"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:error"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:load-more"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:loading"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
onLoad?: ((options: {
|
||||
side: InfiniteScrollSide;
|
||||
done: (status: InfiniteScrollStatus) => void;
|
||||
}) => any) | undefined;
|
||||
}, {
|
||||
reset: (side?: InfiniteScrollSide) => void;
|
||||
}, {}, {}, {}, {
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
direction: "horizontal" | "vertical";
|
||||
side: InfiniteScrollSide;
|
||||
mode: "intersect" | "manual";
|
||||
loadMoreText: string;
|
||||
emptyText: string;
|
||||
}>;
|
||||
__isFragment?: never;
|
||||
__isTeleport?: never;
|
||||
__isSuspense?: never;
|
||||
} & import("vue").ComponentOptionsBase<{
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
direction: "horizontal" | "vertical";
|
||||
side: InfiniteScrollSide;
|
||||
mode: "intersect" | "manual";
|
||||
loadMoreText: string;
|
||||
emptyText: string;
|
||||
} & {
|
||||
height?: string | number | undefined;
|
||||
maxHeight?: string | number | undefined;
|
||||
maxWidth?: string | number | undefined;
|
||||
minHeight?: string | number | undefined;
|
||||
minWidth?: string | number | undefined;
|
||||
width?: string | number | undefined;
|
||||
color?: string | undefined;
|
||||
margin?: string | number | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
loading?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
error?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
empty?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
'load-more'?: ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
loading?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
error?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
empty?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
'load-more'?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:empty"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:error"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:load-more"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:loading"?: false | ((arg: InfiniteScrollSlot) => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
onLoad?: ((options: {
|
||||
side: InfiniteScrollSide;
|
||||
done: (status: InfiniteScrollStatus) => void;
|
||||
}) => any) | undefined;
|
||||
}, {
|
||||
reset: (side?: InfiniteScrollSide) => void;
|
||||
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
load: (options: {
|
||||
side: InfiniteScrollSide;
|
||||
done: (status: InfiniteScrollStatus) => void;
|
||||
}) => true;
|
||||
}, string, {
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
direction: "horizontal" | "vertical";
|
||||
side: InfiniteScrollSide;
|
||||
mode: "intersect" | "manual";
|
||||
loadMoreText: string;
|
||||
emptyText: string;
|
||||
}, {}, string, import("vue").SlotsType<Partial<{
|
||||
default: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
loading: (arg: InfiniteScrollSlot) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
error: (arg: InfiniteScrollSlot) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
empty: (arg: InfiniteScrollSlot) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
'load-more': (arg: InfiniteScrollSlot) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
}>>, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & import("../../util/index.js").FilterPropsOptions<{
|
||||
tag: {
|
||||
type: PropType<string | import("../../util/index.js").JSXComponent>;
|
||||
default: string;
|
||||
};
|
||||
height: (NumberConstructor | StringConstructor)[];
|
||||
maxHeight: (NumberConstructor | StringConstructor)[];
|
||||
maxWidth: (NumberConstructor | StringConstructor)[];
|
||||
minHeight: (NumberConstructor | StringConstructor)[];
|
||||
minWidth: (NumberConstructor | StringConstructor)[];
|
||||
width: (NumberConstructor | StringConstructor)[];
|
||||
color: StringConstructor;
|
||||
direction: {
|
||||
type: PropType<'vertical' | 'horizontal'>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
side: {
|
||||
type: PropType<InfiniteScrollSide>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
mode: {
|
||||
type: PropType<'intersect' | 'manual'>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
margin: (NumberConstructor | StringConstructor)[];
|
||||
loadMoreText: {
|
||||
type: StringConstructor;
|
||||
default: string;
|
||||
};
|
||||
emptyText: {
|
||||
type: StringConstructor;
|
||||
default: string;
|
||||
};
|
||||
}, import("vue").ExtractPropTypes<{
|
||||
tag: {
|
||||
type: PropType<string | import("../../util/index.js").JSXComponent>;
|
||||
default: string;
|
||||
};
|
||||
height: (NumberConstructor | StringConstructor)[];
|
||||
maxHeight: (NumberConstructor | StringConstructor)[];
|
||||
maxWidth: (NumberConstructor | StringConstructor)[];
|
||||
minHeight: (NumberConstructor | StringConstructor)[];
|
||||
minWidth: (NumberConstructor | StringConstructor)[];
|
||||
width: (NumberConstructor | StringConstructor)[];
|
||||
color: StringConstructor;
|
||||
direction: {
|
||||
type: PropType<'vertical' | 'horizontal'>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
side: {
|
||||
type: PropType<InfiniteScrollSide>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
mode: {
|
||||
type: PropType<'intersect' | 'manual'>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
margin: (NumberConstructor | StringConstructor)[];
|
||||
loadMoreText: {
|
||||
type: StringConstructor;
|
||||
default: string;
|
||||
};
|
||||
emptyText: {
|
||||
type: StringConstructor;
|
||||
default: string;
|
||||
};
|
||||
}>>;
|
||||
export type VInfiniteScroll = InstanceType<typeof VInfiniteScroll>;
|
||||
|
||||
+271
@@ -0,0 +1,271 @@
|
||||
import { createTextVNode as _createTextVNode, createElementVNode as _createElementVNode, createVNode as _createVNode, normalizeClass as _normalizeClass, normalizeStyle as _normalizeStyle } from "vue";
|
||||
// Styles
|
||||
import "./VInfiniteScroll.css";
|
||||
|
||||
// Components
|
||||
import { VBtn } from "../VBtn/index.js";
|
||||
import { VProgressCircular } from "../VProgressCircular/index.js"; // Composables
|
||||
import { makeDimensionProps, useDimension } from "../../composables/dimensions.js";
|
||||
import { useIntersectionObserver } from "../../composables/intersectionObserver.js";
|
||||
import { useLocale } from "../../composables/locale.js";
|
||||
import { makeTagProps } from "../../composables/tag.js"; // Utilities
|
||||
import { computed, nextTick, onMounted, ref, shallowRef, watch } from 'vue';
|
||||
import { convertToUnit, defineComponent, genericComponent, propsFactory, useRender } from "../../util/index.js"; // Types
|
||||
export const makeVInfiniteScrollProps = propsFactory({
|
||||
color: String,
|
||||
direction: {
|
||||
type: String,
|
||||
default: 'vertical',
|
||||
validator: v => ['vertical', 'horizontal'].includes(v)
|
||||
},
|
||||
side: {
|
||||
type: String,
|
||||
default: 'end',
|
||||
validator: v => ['start', 'end', 'both'].includes(v)
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'intersect',
|
||||
validator: v => ['intersect', 'manual'].includes(v)
|
||||
},
|
||||
margin: [Number, String],
|
||||
loadMoreText: {
|
||||
type: String,
|
||||
default: '$vuetify.infiniteScroll.loadMore'
|
||||
},
|
||||
emptyText: {
|
||||
type: String,
|
||||
default: '$vuetify.infiniteScroll.empty'
|
||||
},
|
||||
...makeDimensionProps(),
|
||||
...makeTagProps()
|
||||
}, 'VInfiniteScroll');
|
||||
export const VInfiniteScrollIntersect = defineComponent({
|
||||
name: 'VInfiniteScrollIntersect',
|
||||
props: {
|
||||
side: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
rootMargin: String
|
||||
},
|
||||
emits: {
|
||||
intersect: (side, isIntersecting) => true
|
||||
},
|
||||
setup(props, {
|
||||
emit
|
||||
}) {
|
||||
const {
|
||||
intersectionRef,
|
||||
isIntersecting
|
||||
} = useIntersectionObserver();
|
||||
watch(isIntersecting, async val => {
|
||||
emit('intersect', props.side, val);
|
||||
});
|
||||
useRender(() => _createElementVNode("div", {
|
||||
"class": "v-infinite-scroll-intersect",
|
||||
"style": {
|
||||
'--v-infinite-margin-size': props.rootMargin
|
||||
},
|
||||
"ref": intersectionRef
|
||||
}, [_createTextVNode("\xA0")]));
|
||||
return {};
|
||||
}
|
||||
});
|
||||
export const VInfiniteScroll = genericComponent()({
|
||||
name: 'VInfiniteScroll',
|
||||
props: makeVInfiniteScrollProps(),
|
||||
emits: {
|
||||
load: options => true
|
||||
},
|
||||
setup(props, {
|
||||
slots,
|
||||
emit
|
||||
}) {
|
||||
const rootEl = ref();
|
||||
const startStatus = shallowRef('ok');
|
||||
const endStatus = shallowRef('ok');
|
||||
const margin = computed(() => convertToUnit(props.margin));
|
||||
const isIntersecting = shallowRef(false);
|
||||
function setScrollAmount(amount) {
|
||||
if (!rootEl.value) return;
|
||||
const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
|
||||
rootEl.value[property] = amount;
|
||||
}
|
||||
function getScrollAmount() {
|
||||
if (!rootEl.value) return 0;
|
||||
const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
|
||||
return rootEl.value[property];
|
||||
}
|
||||
function getScrollSize() {
|
||||
if (!rootEl.value) return 0;
|
||||
const property = props.direction === 'vertical' ? 'scrollHeight' : 'scrollWidth';
|
||||
return rootEl.value[property];
|
||||
}
|
||||
function getContainerSize() {
|
||||
if (!rootEl.value) return 0;
|
||||
const property = props.direction === 'vertical' ? 'clientHeight' : 'clientWidth';
|
||||
return rootEl.value[property];
|
||||
}
|
||||
onMounted(() => {
|
||||
if (!rootEl.value) return;
|
||||
if (props.side === 'start') {
|
||||
setScrollAmount(getScrollSize());
|
||||
} else if (props.side === 'both') {
|
||||
setScrollAmount(getScrollSize() / 2 - getContainerSize() / 2);
|
||||
}
|
||||
});
|
||||
function setStatus(side, status) {
|
||||
if (side === 'start') {
|
||||
startStatus.value = status;
|
||||
} else if (side === 'end') {
|
||||
endStatus.value = status;
|
||||
} else if (side === 'both') {
|
||||
startStatus.value = status;
|
||||
endStatus.value = status;
|
||||
}
|
||||
}
|
||||
function getStatus(side) {
|
||||
return side === 'start' ? startStatus.value : endStatus.value;
|
||||
}
|
||||
let previousScrollSize = 0;
|
||||
function handleIntersect(side, _isIntersecting) {
|
||||
isIntersecting.value = _isIntersecting;
|
||||
if (isIntersecting.value) {
|
||||
intersecting(side);
|
||||
}
|
||||
}
|
||||
function intersecting(side) {
|
||||
if (props.mode !== 'manual' && !isIntersecting.value) return;
|
||||
const status = getStatus(side);
|
||||
if (!rootEl.value || ['empty', 'loading'].includes(status)) return;
|
||||
previousScrollSize = getScrollSize();
|
||||
setStatus(side, 'loading');
|
||||
function done(status) {
|
||||
setStatus(side, status);
|
||||
nextTick(() => {
|
||||
if (status === 'empty' || status === 'error') return;
|
||||
if (status === 'ok' && side === 'start') {
|
||||
setScrollAmount(getScrollSize() - previousScrollSize + getScrollAmount());
|
||||
}
|
||||
if (props.mode !== 'manual') {
|
||||
nextTick(() => {
|
||||
// Browser takes 2 - 3 animation frames to trigger IntersectionObserver after
|
||||
// VInfiniteScrollIntersect leaves the viewpoint. So far I couldn't come up
|
||||
// with a better solution than using 3 nested window.requestAnimationFrame. (#17475)
|
||||
window.requestAnimationFrame(() => {
|
||||
window.requestAnimationFrame(() => {
|
||||
window.requestAnimationFrame(() => {
|
||||
intersecting(side);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
emit('load', {
|
||||
side,
|
||||
done
|
||||
});
|
||||
}
|
||||
const {
|
||||
t
|
||||
} = useLocale();
|
||||
function renderSide(side, status) {
|
||||
if (props.side !== side && props.side !== 'both') return;
|
||||
const onClick = () => intersecting(side);
|
||||
const slotProps = {
|
||||
side,
|
||||
props: {
|
||||
onClick,
|
||||
color: props.color
|
||||
}
|
||||
};
|
||||
if (status === 'error') return slots.error?.(slotProps);
|
||||
if (status === 'empty') return slots.empty?.(slotProps) ?? _createElementVNode("div", null, [t(props.emptyText)]);
|
||||
if (props.mode === 'manual') {
|
||||
if (status === 'loading') {
|
||||
return slots.loading?.(slotProps) ?? _createVNode(VProgressCircular, {
|
||||
"indeterminate": true,
|
||||
"color": props.color
|
||||
}, null);
|
||||
}
|
||||
return slots['load-more']?.(slotProps) ?? _createVNode(VBtn, {
|
||||
"variant": "outlined",
|
||||
"color": props.color,
|
||||
"onClick": onClick
|
||||
}, {
|
||||
default: () => [t(props.loadMoreText)]
|
||||
});
|
||||
}
|
||||
return slots.loading?.(slotProps) ?? _createVNode(VProgressCircular, {
|
||||
"indeterminate": true,
|
||||
"color": props.color
|
||||
}, null);
|
||||
}
|
||||
const {
|
||||
dimensionStyles
|
||||
} = useDimension(props);
|
||||
useRender(() => {
|
||||
const Tag = props.tag;
|
||||
const hasStartIntersect = props.side === 'start' || props.side === 'both';
|
||||
const hasEndIntersect = props.side === 'end' || props.side === 'both';
|
||||
const intersectMode = props.mode === 'intersect';
|
||||
return _createVNode(Tag, {
|
||||
"ref": rootEl,
|
||||
"class": _normalizeClass(['v-infinite-scroll', `v-infinite-scroll--${props.direction}`, {
|
||||
'v-infinite-scroll--start': hasStartIntersect,
|
||||
'v-infinite-scroll--end': hasEndIntersect
|
||||
}]),
|
||||
"style": _normalizeStyle(dimensionStyles.value)
|
||||
}, {
|
||||
default: () => [_createElementVNode("div", {
|
||||
"class": "v-infinite-scroll__side"
|
||||
}, [renderSide('start', startStatus.value)]), hasStartIntersect && intersectMode && _createVNode(VInfiniteScrollIntersect, {
|
||||
"key": "start",
|
||||
"side": "start",
|
||||
"onIntersect": handleIntersect,
|
||||
"rootMargin": margin.value
|
||||
}, null), slots.default?.(), hasEndIntersect && intersectMode && _createVNode(VInfiniteScrollIntersect, {
|
||||
"key": "end",
|
||||
"side": "end",
|
||||
"onIntersect": handleIntersect,
|
||||
"rootMargin": margin.value
|
||||
}, null), _createElementVNode("div", {
|
||||
"class": "v-infinite-scroll__side"
|
||||
}, [renderSide('end', endStatus.value)])]
|
||||
});
|
||||
});
|
||||
function reset(side) {
|
||||
const effectiveSide = side ?? props.side;
|
||||
setStatus(effectiveSide, 'ok');
|
||||
nextTick(() => {
|
||||
if (effectiveSide !== 'end') {
|
||||
setScrollAmount(getScrollSize() - previousScrollSize + getScrollAmount());
|
||||
}
|
||||
if (props.mode !== 'manual') {
|
||||
nextTick(() => {
|
||||
// See #17475
|
||||
window.requestAnimationFrame(() => {
|
||||
window.requestAnimationFrame(() => {
|
||||
window.requestAnimationFrame(() => {
|
||||
if (effectiveSide === 'both') {
|
||||
intersecting('start');
|
||||
intersecting('end');
|
||||
} else {
|
||||
intersecting(effectiveSide);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return {
|
||||
reset
|
||||
};
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=VInfiniteScroll.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+46
@@ -0,0 +1,46 @@
|
||||
@use '../../styles/settings'
|
||||
@use '../../styles/tools'
|
||||
@use './variables' as *
|
||||
|
||||
@include tools.layer('components')
|
||||
.v-infinite-scroll--horizontal
|
||||
display: flex
|
||||
flex-direction: row
|
||||
overflow-x: auto
|
||||
|
||||
.v-infinite-scroll-intersect
|
||||
height: 100%
|
||||
width: var(--v-infinite-margin-size, 1px)
|
||||
|
||||
.v-infinite-scroll--vertical
|
||||
display: flex
|
||||
flex-direction: column
|
||||
overflow-y: auto
|
||||
|
||||
.v-infinite-scroll-intersect
|
||||
height: 1px
|
||||
width: 100%
|
||||
|
||||
.v-infinite-scroll-intersect
|
||||
overflow: hidden
|
||||
pointer-events: none
|
||||
margin-top: var(--v-infinite-margin)
|
||||
margin-bottom: calc(var(--v-infinite-margin) * -1)
|
||||
|
||||
&:nth-child(2) // TODO: "1 of &" would be more stable if structure changes
|
||||
--v-infinite-margin: var(--v-infinite-margin-size, 1px)
|
||||
&:nth-last-child(2)
|
||||
--v-infinite-margin: calc(var(--v-infinite-margin-size, 1px) * -1)
|
||||
|
||||
.v-infinite-scroll__side
|
||||
align-items: center
|
||||
display: flex
|
||||
justify-content: center
|
||||
padding: $infinite-scroll-side-padding
|
||||
transition-property: padding
|
||||
transition-duration: settings.$transition-duration-root
|
||||
transition-timing-function: settings.$standard-easing
|
||||
|
||||
&:empty,
|
||||
&:has(> div:only-child:empty)
|
||||
padding: 0
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
@use '../../styles/settings';
|
||||
|
||||
$infinite-scroll-side-padding: 8px !default;
|
||||
+1
@@ -0,0 +1 @@
|
||||
export { VInfiniteScroll } from './VInfiniteScroll.js';
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export { VInfiniteScroll } from "./VInfiniteScroll.js";
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","names":["VInfiniteScroll"],"sources":["../../../src/components/VInfiniteScroll/index.ts"],"sourcesContent":["export { VInfiniteScroll } from './VInfiniteScroll'\n"],"mappings":"SAASA,eAAe","ignoreList":[]}
|
||||
Reference in New Issue
Block a user