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,110 @@
@layer vuetify-components {
.v-navigation-drawer {
-webkit-overflow-scrolling: touch;
background: rgb(var(--v-theme-surface));
display: flex;
flex-direction: column;
height: 100%;
max-width: 100%;
pointer-events: auto;
transition-duration: 0.2s;
transition-property: box-shadow, transform, visibility, width, height, left, right, top, bottom;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
position: absolute;
}
.v-navigation-drawer {
border-color: rgba(var(--v-border-color), var(--v-border-opacity));
border-style: solid;
border-width: 0;
}
.v-navigation-drawer--border {
border-width: thin;
box-shadow: none;
}
.v-navigation-drawer {
box-shadow: 0px 0px 0px 0px rgba(var(--v-shadow-color), var(--v-shadow-key-opacity, 0.3)), 0px 0px 0px 0px rgba(var(--v-shadow-color), var(--v-shadow-ambient-opacity, 0.15));
--v-elevation-overlay: color-mix(in srgb, var(--v-elevation-overlay-color) 0%, transparent);
}
.v-navigation-drawer {
background: rgb(var(--v-theme-surface));
color: color-mix(in srgb, rgb(var(--v-theme-on-surface)) calc(var(--v-high-emphasis-opacity) * 100%), transparent);
}
@media (prefers-reduced-motion: reduce) {
.v-navigation-drawer {
transition: none;
}
}
.v-navigation-drawer--rounded {
border-radius: 4px;
}
.v-navigation-drawer--top {
top: 0;
border-bottom-width: thin;
}
.v-navigation-drawer--bottom {
left: 0;
border-top-width: thin;
}
.v-navigation-drawer--left {
top: 0;
left: 0;
right: auto;
border-right-width: thin;
}
.v-navigation-drawer--right {
top: 0;
left: auto;
right: 0;
border-left-width: thin;
}
.v-navigation-drawer--floating {
border: none;
}
.v-navigation-drawer--temporary.v-navigation-drawer--active {
box-shadow: 0px 2px 3px 0px rgba(var(--v-shadow-color), var(--v-shadow-key-opacity, 0.3)), 0px 6px 10px 4px rgba(var(--v-shadow-color), var(--v-shadow-ambient-opacity, 0.15));
--v-elevation-overlay: color-mix(in srgb, var(--v-elevation-overlay-color) 8%, transparent);
}
.v-navigation-drawer--sticky {
height: auto;
transition: box-shadow, transform, visibility, width, height, left, right;
}
.v-navigation-drawer .v-list {
overflow: hidden;
}
.v-navigation-drawer__content {
flex: 0 1 auto;
height: 100%;
max-width: 100%;
overflow-x: hidden;
overflow-y: auto;
}
.v-navigation-drawer__img {
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
z-index: -1;
}
.v-navigation-drawer__img img:not(.v-img__img) {
height: inherit;
object-fit: cover;
width: inherit;
}
.v-navigation-drawer__scrim {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: black;
opacity: 0.2;
transition: opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 1;
}
.v-navigation-drawer__prepend,
.v-navigation-drawer__append {
flex: none;
overflow: hidden;
}
}
@@ -0,0 +1,740 @@
import type { PropType } from 'vue';
export type VNavigationDrawerImageSlot = {
image: string | undefined;
};
export type VNavigationDrawerSlots = {
default: never;
prepend: never;
append: never;
image: VNavigationDrawerImageSlot;
};
declare const locations: readonly ['start', 'end', 'left', 'right', 'top', 'bottom'];
export declare const makeVNavigationDrawerProps: <Defaults extends {
theme?: unknown;
class?: unknown;
style?: unknown;
mobile?: unknown;
mobileBreakpoint?: unknown;
name?: unknown;
order?: unknown;
absolute?: unknown;
border?: unknown;
elevation?: unknown;
rounded?: unknown;
tile?: unknown;
tag?: unknown;
closeDelay?: unknown;
openDelay?: unknown;
retainFocus?: unknown;
captureFocus?: unknown;
color?: unknown;
disableResizeWatcher?: unknown;
disableRouteWatcher?: unknown;
expandOnHover?: unknown;
floating?: unknown;
modelValue?: unknown;
permanent?: unknown;
rail?: unknown;
railWidth?: unknown;
scrim?: unknown;
image?: unknown;
temporary?: unknown;
persistent?: unknown;
touchless?: unknown;
width?: unknown;
location?: unknown;
sticky?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
theme: unknown extends Defaults["theme"] ? StringConstructor : {
type: PropType<unknown extends Defaults["theme"] ? string : string | Defaults["theme"]>;
default: unknown extends Defaults["theme"] ? string : string | Defaults["theme"];
};
class: unknown extends Defaults["class"] ? PropType<any> : {
type: PropType<unknown extends Defaults["class"] ? any : any>;
default: unknown extends Defaults["class"] ? any : any;
};
style: unknown extends Defaults["style"] ? {
type: PropType<import("vue").StyleValue>;
default: null;
} : Omit<{
type: PropType<import("vue").StyleValue>;
default: null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["style"] ? import("vue").StyleValue : Defaults["style"] | import("vue").StyleValue>;
default: unknown extends Defaults["style"] ? import("vue").StyleValue : Defaults["style"] | NonNullable<import("vue").StyleValue>;
};
mobile: unknown extends Defaults["mobile"] ? Omit<{
type: PropType<boolean | null>;
default: boolean;
}, "default" | "type"> & {
type: PropType<boolean | null>;
default: NonNullable<boolean | null> | null;
} : Omit<Omit<{
type: PropType<boolean | null>;
default: boolean;
}, "default" | "type"> & {
type: PropType<boolean | null>;
default: NonNullable<boolean | null> | null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["mobile"] ? boolean | null : boolean | Defaults["mobile"] | null>;
default: unknown extends Defaults["mobile"] ? boolean | null : Defaults["mobile"] | NonNullable<boolean | null>;
};
mobileBreakpoint: unknown extends Defaults["mobileBreakpoint"] ? PropType<number | import("../../types.js").DisplayBreakpoint> : {
type: PropType<unknown extends Defaults["mobileBreakpoint"] ? number | import("../../types.js").DisplayBreakpoint : number | Defaults["mobileBreakpoint"] | import("../../types.js").DisplayBreakpoint>;
default: unknown extends Defaults["mobileBreakpoint"] ? number | import("../../types.js").DisplayBreakpoint : Defaults["mobileBreakpoint"] | NonNullable<number | import("../../types.js").DisplayBreakpoint>;
};
name: unknown extends Defaults["name"] ? {
type: StringConstructor;
} : Omit<{
type: StringConstructor;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["name"] ? string : string | Defaults["name"]>;
default: unknown extends Defaults["name"] ? string : string | Defaults["name"];
};
order: unknown extends Defaults["order"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["order"] ? string | number : string | number | Defaults["order"]>;
default: unknown extends Defaults["order"] ? string | number : Defaults["order"] | NonNullable<string | number>;
};
absolute: unknown extends Defaults["absolute"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["absolute"] ? boolean : boolean | Defaults["absolute"]>;
default: unknown extends Defaults["absolute"] ? boolean : boolean | Defaults["absolute"];
};
border: unknown extends Defaults["border"] ? (BooleanConstructor | NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["border"] ? string | number | boolean : string | number | boolean | Defaults["border"]>;
default: unknown extends Defaults["border"] ? string | number | boolean : Defaults["border"] | NonNullable<string | number | boolean>;
};
elevation: unknown extends Defaults["elevation"] ? {
type: (NumberConstructor | StringConstructor)[];
validator: (value: string | number) => boolean;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
validator: (value: string | number) => boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["elevation"] ? string | number : string | number | Defaults["elevation"]>;
default: unknown extends Defaults["elevation"] ? string | number : Defaults["elevation"] | NonNullable<string | number>;
};
rounded: unknown extends Defaults["rounded"] ? {
type: (BooleanConstructor | NumberConstructor | StringConstructor)[];
default: undefined;
} : Omit<{
type: (BooleanConstructor | NumberConstructor | StringConstructor)[];
default: undefined;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["rounded"] ? string | number | boolean : string | number | boolean | Defaults["rounded"]>;
default: unknown extends Defaults["rounded"] ? string | number | boolean : Defaults["rounded"] | NonNullable<string | number | boolean>;
};
tile: unknown extends Defaults["tile"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["tile"] ? boolean : boolean | Defaults["tile"]>;
default: unknown extends Defaults["tile"] ? boolean : boolean | Defaults["tile"];
};
tag: unknown extends Defaults["tag"] ? Omit<{
type: PropType<string | import("../../util/index.js").JSXComponent>;
default: string;
}, "default" | "type"> & {
type: PropType<string | import("../../util/index.js").JSXComponent>;
default: NonNullable<string | import("../../util/index.js").JSXComponent>;
} : Omit<Omit<{
type: PropType<string | import("../../util/index.js").JSXComponent>;
default: string;
}, "default" | "type"> & {
type: PropType<string | import("../../util/index.js").JSXComponent>;
default: NonNullable<string | import("../../util/index.js").JSXComponent>;
}, "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>;
};
closeDelay: unknown extends Defaults["closeDelay"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["closeDelay"] ? string | number : string | number | Defaults["closeDelay"]>;
default: unknown extends Defaults["closeDelay"] ? string | number : Defaults["closeDelay"] | NonNullable<string | number>;
};
openDelay: unknown extends Defaults["openDelay"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["openDelay"] ? string | number : string | number | Defaults["openDelay"]>;
default: unknown extends Defaults["openDelay"] ? string | number : Defaults["openDelay"] | NonNullable<string | number>;
};
retainFocus: unknown extends Defaults["retainFocus"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["retainFocus"] ? boolean : boolean | Defaults["retainFocus"]>;
default: unknown extends Defaults["retainFocus"] ? boolean : boolean | Defaults["retainFocus"];
};
captureFocus: unknown extends Defaults["captureFocus"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["captureFocus"] ? boolean : boolean | Defaults["captureFocus"]>;
default: unknown extends Defaults["captureFocus"] ? boolean : boolean | Defaults["captureFocus"];
};
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"];
};
disableResizeWatcher: unknown extends Defaults["disableResizeWatcher"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["disableResizeWatcher"] ? boolean : boolean | Defaults["disableResizeWatcher"]>;
default: unknown extends Defaults["disableResizeWatcher"] ? boolean : boolean | Defaults["disableResizeWatcher"];
};
disableRouteWatcher: unknown extends Defaults["disableRouteWatcher"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["disableRouteWatcher"] ? boolean : boolean | Defaults["disableRouteWatcher"]>;
default: unknown extends Defaults["disableRouteWatcher"] ? boolean : boolean | Defaults["disableRouteWatcher"];
};
expandOnHover: unknown extends Defaults["expandOnHover"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["expandOnHover"] ? boolean : boolean | Defaults["expandOnHover"]>;
default: unknown extends Defaults["expandOnHover"] ? boolean : boolean | Defaults["expandOnHover"];
};
floating: unknown extends Defaults["floating"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["floating"] ? boolean : boolean | Defaults["floating"]>;
default: unknown extends Defaults["floating"] ? boolean : boolean | Defaults["floating"];
};
modelValue: unknown extends Defaults["modelValue"] ? {
type: PropType<boolean | null>;
default: null;
} : Omit<{
type: PropType<boolean | null>;
default: null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["modelValue"] ? boolean | null : boolean | Defaults["modelValue"] | null>;
default: unknown extends Defaults["modelValue"] ? boolean | null : Defaults["modelValue"] | NonNullable<boolean | null>;
};
permanent: unknown extends Defaults["permanent"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["permanent"] ? boolean : boolean | Defaults["permanent"]>;
default: unknown extends Defaults["permanent"] ? boolean : boolean | Defaults["permanent"];
};
rail: unknown extends Defaults["rail"] ? {
type: PropType<boolean | null>;
default: null;
} : Omit<{
type: PropType<boolean | null>;
default: null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["rail"] ? boolean | null : boolean | Defaults["rail"] | null>;
default: unknown extends Defaults["rail"] ? boolean | null : Defaults["rail"] | NonNullable<boolean | null>;
};
railWidth: unknown extends Defaults["railWidth"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["railWidth"] ? string | number : string | number | Defaults["railWidth"]>;
default: unknown extends Defaults["railWidth"] ? string | number : Defaults["railWidth"] | NonNullable<string | number>;
};
scrim: unknown extends Defaults["scrim"] ? {
type: (BooleanConstructor | StringConstructor)[];
default: boolean;
} : Omit<{
type: (BooleanConstructor | StringConstructor)[];
default: boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["scrim"] ? string | boolean : string | boolean | Defaults["scrim"]>;
default: unknown extends Defaults["scrim"] ? string | boolean : Defaults["scrim"] | NonNullable<string | boolean>;
};
image: unknown extends Defaults["image"] ? StringConstructor : {
type: PropType<unknown extends Defaults["image"] ? string : string | Defaults["image"]>;
default: unknown extends Defaults["image"] ? string : string | Defaults["image"];
};
temporary: unknown extends Defaults["temporary"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["temporary"] ? boolean : boolean | Defaults["temporary"]>;
default: unknown extends Defaults["temporary"] ? boolean : boolean | Defaults["temporary"];
};
persistent: unknown extends Defaults["persistent"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["persistent"] ? boolean : boolean | Defaults["persistent"]>;
default: unknown extends Defaults["persistent"] ? boolean : boolean | Defaults["persistent"];
};
touchless: unknown extends Defaults["touchless"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["touchless"] ? boolean : boolean | Defaults["touchless"]>;
default: unknown extends Defaults["touchless"] ? boolean : boolean | Defaults["touchless"];
};
width: unknown extends Defaults["width"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["width"] ? string | number : string | number | Defaults["width"]>;
default: unknown extends Defaults["width"] ? string | number : Defaults["width"] | NonNullable<string | number>;
};
location: unknown extends Defaults["location"] ? {
type: PropType<(typeof locations)[number]>;
default: string;
validator: (value: any) => boolean;
} : Omit<{
type: PropType<(typeof locations)[number]>;
default: string;
validator: (value: any) => boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["location"] ? "bottom" | "end" | "left" | "right" | "start" | "top" : "bottom" | "end" | "left" | "right" | "start" | "top" | Defaults["location"]>;
default: unknown extends Defaults["location"] ? "bottom" | "end" | "left" | "right" | "start" | "top" : Defaults["location"] | NonNullable<"bottom" | "end" | "left" | "right" | "start" | "top">;
};
sticky: unknown extends Defaults["sticky"] ? BooleanConstructor : {
type: PropType<unknown extends Defaults["sticky"] ? boolean : boolean | Defaults["sticky"]>;
default: unknown extends Defaults["sticky"] ? boolean : boolean | Defaults["sticky"];
};
};
export declare const VNavigationDrawer: {
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<{
style: string | false | import("vue").StyleValue[] | import("vue").CSSProperties | null;
mobile: boolean | null;
order: string | number;
absolute: boolean;
tile: boolean;
tag: string | import("../../util/index.js").JSXComponent;
retainFocus: boolean;
captureFocus: boolean;
disableResizeWatcher: boolean;
disableRouteWatcher: boolean;
expandOnHover: boolean;
floating: boolean;
modelValue: boolean | null;
permanent: boolean;
rail: boolean | null;
railWidth: string | number;
scrim: string | boolean;
temporary: boolean;
persistent: boolean;
touchless: boolean;
width: string | number;
location: "bottom" | "end" | "left" | "right" | "start" | "top";
sticky: boolean;
} & {
theme?: string | undefined;
class?: any;
mobileBreakpoint?: number | import("../../types.js").DisplayBreakpoint | undefined;
name?: string | undefined;
border?: string | number | boolean | undefined;
elevation?: string | number | undefined;
rounded?: string | number | boolean | undefined;
closeDelay?: string | number | undefined;
openDelay?: string | number | undefined;
color?: string | undefined;
image?: string | undefined;
} & {
$children?: {
default?: (() => import("vue").VNodeChild) | undefined;
prepend?: (() => import("vue").VNodeChild) | undefined;
append?: (() => import("vue").VNodeChild) | undefined;
image?: ((arg: VNavigationDrawerImageSlot) => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
'v-slots'?: {
default?: false | (() => import("vue").VNodeChild) | undefined;
prepend?: false | (() => import("vue").VNodeChild) | undefined;
append?: false | (() => import("vue").VNodeChild) | undefined;
image?: false | ((arg: VNavigationDrawerImageSlot) => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:append"?: false | (() => import("vue").VNodeChild) | undefined;
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
"v-slot:image"?: false | ((arg: VNavigationDrawerImageSlot) => import("vue").VNodeChild) | undefined;
"v-slot:prepend"?: false | (() => import("vue").VNodeChild) | undefined;
} & {
"onUpdate:modelValue"?: ((val: boolean) => any) | undefined;
"onUpdate:rail"?: ((val: boolean) => any) | undefined;
}, {
isStuck: import("vue").ShallowRef<"bottom" | "top" | boolean, "bottom" | "top" | boolean>;
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
'update:modelValue': (val: boolean) => true;
'update:rail': (val: boolean) => true;
}, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, {
style: import("vue").StyleValue;
mobile: boolean | null;
order: string | number;
absolute: boolean;
rounded: string | number | boolean;
tile: boolean;
tag: string | import("../../util/index.js").JSXComponent;
retainFocus: boolean;
captureFocus: boolean;
disableResizeWatcher: boolean;
disableRouteWatcher: boolean;
expandOnHover: boolean;
floating: boolean;
modelValue: boolean | null;
permanent: boolean;
rail: boolean | null;
railWidth: string | number;
scrim: string | boolean;
temporary: boolean;
persistent: boolean;
touchless: boolean;
width: string | number;
location: "bottom" | "end" | "left" | "right" | "start" | "top";
sticky: boolean;
}, true, {}, import("vue").SlotsType<Partial<{
default: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
prepend: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
append: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
image: (arg: VNavigationDrawerImageSlot) => 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: {};
}, {
style: string | false | import("vue").StyleValue[] | import("vue").CSSProperties | null;
mobile: boolean | null;
order: string | number;
absolute: boolean;
tile: boolean;
tag: string | import("../../util/index.js").JSXComponent;
retainFocus: boolean;
captureFocus: boolean;
disableResizeWatcher: boolean;
disableRouteWatcher: boolean;
expandOnHover: boolean;
floating: boolean;
modelValue: boolean | null;
permanent: boolean;
rail: boolean | null;
railWidth: string | number;
scrim: string | boolean;
temporary: boolean;
persistent: boolean;
touchless: boolean;
width: string | number;
location: "bottom" | "end" | "left" | "right" | "start" | "top";
sticky: boolean;
} & {
theme?: string | undefined;
class?: any;
mobileBreakpoint?: number | import("../../types.js").DisplayBreakpoint | undefined;
name?: string | undefined;
border?: string | number | boolean | undefined;
elevation?: string | number | undefined;
rounded?: string | number | boolean | undefined;
closeDelay?: string | number | undefined;
openDelay?: string | number | undefined;
color?: string | undefined;
image?: string | undefined;
} & {
$children?: {
default?: (() => import("vue").VNodeChild) | undefined;
prepend?: (() => import("vue").VNodeChild) | undefined;
append?: (() => import("vue").VNodeChild) | undefined;
image?: ((arg: VNavigationDrawerImageSlot) => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
'v-slots'?: {
default?: false | (() => import("vue").VNodeChild) | undefined;
prepend?: false | (() => import("vue").VNodeChild) | undefined;
append?: false | (() => import("vue").VNodeChild) | undefined;
image?: false | ((arg: VNavigationDrawerImageSlot) => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:append"?: false | (() => import("vue").VNodeChild) | undefined;
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
"v-slot:image"?: false | ((arg: VNavigationDrawerImageSlot) => import("vue").VNodeChild) | undefined;
"v-slot:prepend"?: false | (() => import("vue").VNodeChild) | undefined;
} & {
"onUpdate:modelValue"?: ((val: boolean) => any) | undefined;
"onUpdate:rail"?: ((val: boolean) => any) | undefined;
}, {
isStuck: import("vue").ShallowRef<"bottom" | "top" | boolean, "bottom" | "top" | boolean>;
}, {}, {}, {}, {
style: import("vue").StyleValue;
mobile: boolean | null;
order: string | number;
absolute: boolean;
rounded: string | number | boolean;
tile: boolean;
tag: string | import("../../util/index.js").JSXComponent;
retainFocus: boolean;
captureFocus: boolean;
disableResizeWatcher: boolean;
disableRouteWatcher: boolean;
expandOnHover: boolean;
floating: boolean;
modelValue: boolean | null;
permanent: boolean;
rail: boolean | null;
railWidth: string | number;
scrim: string | boolean;
temporary: boolean;
persistent: boolean;
touchless: boolean;
width: string | number;
location: "bottom" | "end" | "left" | "right" | "start" | "top";
sticky: boolean;
}>;
__isFragment?: never;
__isTeleport?: never;
__isSuspense?: never;
} & import("vue").ComponentOptionsBase<{
style: string | false | import("vue").StyleValue[] | import("vue").CSSProperties | null;
mobile: boolean | null;
order: string | number;
absolute: boolean;
tile: boolean;
tag: string | import("../../util/index.js").JSXComponent;
retainFocus: boolean;
captureFocus: boolean;
disableResizeWatcher: boolean;
disableRouteWatcher: boolean;
expandOnHover: boolean;
floating: boolean;
modelValue: boolean | null;
permanent: boolean;
rail: boolean | null;
railWidth: string | number;
scrim: string | boolean;
temporary: boolean;
persistent: boolean;
touchless: boolean;
width: string | number;
location: "bottom" | "end" | "left" | "right" | "start" | "top";
sticky: boolean;
} & {
theme?: string | undefined;
class?: any;
mobileBreakpoint?: number | import("../../types.js").DisplayBreakpoint | undefined;
name?: string | undefined;
border?: string | number | boolean | undefined;
elevation?: string | number | undefined;
rounded?: string | number | boolean | undefined;
closeDelay?: string | number | undefined;
openDelay?: string | number | undefined;
color?: string | undefined;
image?: string | undefined;
} & {
$children?: {
default?: (() => import("vue").VNodeChild) | undefined;
prepend?: (() => import("vue").VNodeChild) | undefined;
append?: (() => import("vue").VNodeChild) | undefined;
image?: ((arg: VNavigationDrawerImageSlot) => import("vue").VNodeChild) | undefined;
} | {
$stable?: boolean;
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
'v-slots'?: {
default?: false | (() => import("vue").VNodeChild) | undefined;
prepend?: false | (() => import("vue").VNodeChild) | undefined;
append?: false | (() => import("vue").VNodeChild) | undefined;
image?: false | ((arg: VNavigationDrawerImageSlot) => import("vue").VNodeChild) | undefined;
} | undefined;
} & {
"v-slot:append"?: false | (() => import("vue").VNodeChild) | undefined;
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
"v-slot:image"?: false | ((arg: VNavigationDrawerImageSlot) => import("vue").VNodeChild) | undefined;
"v-slot:prepend"?: false | (() => import("vue").VNodeChild) | undefined;
} & {
"onUpdate:modelValue"?: ((val: boolean) => any) | undefined;
"onUpdate:rail"?: ((val: boolean) => any) | undefined;
}, {
isStuck: import("vue").ShallowRef<"bottom" | "top" | boolean, "bottom" | "top" | boolean>;
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
'update:modelValue': (val: boolean) => true;
'update:rail': (val: boolean) => true;
}, string, {
style: import("vue").StyleValue;
mobile: boolean | null;
order: string | number;
absolute: boolean;
rounded: string | number | boolean;
tile: boolean;
tag: string | import("../../util/index.js").JSXComponent;
retainFocus: boolean;
captureFocus: boolean;
disableResizeWatcher: boolean;
disableRouteWatcher: boolean;
expandOnHover: boolean;
floating: boolean;
modelValue: boolean | null;
permanent: boolean;
rail: boolean | null;
railWidth: string | number;
scrim: string | boolean;
temporary: boolean;
persistent: boolean;
touchless: boolean;
width: string | number;
location: "bottom" | "end" | "left" | "right" | "start" | "top";
sticky: boolean;
}, {}, string, import("vue").SlotsType<Partial<{
default: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
prepend: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
append: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
[key: string]: any;
}>[];
image: (arg: VNavigationDrawerImageSlot) => 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<{
theme: StringConstructor;
class: PropType<import("../../composables/component.js").ClassValue>;
style: {
type: PropType<import("vue").StyleValue>;
default: null;
};
mobile: Omit<{
type: PropType<boolean | null>;
default: boolean;
}, "default" | "type"> & {
type: PropType<boolean | null>;
default: NonNullable<boolean | null> | null;
};
mobileBreakpoint: PropType<number | import("../../types.js").DisplayBreakpoint>;
name: {
type: StringConstructor;
};
order: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
absolute: BooleanConstructor;
border: (BooleanConstructor | NumberConstructor | StringConstructor)[];
elevation: {
type: (NumberConstructor | StringConstructor)[];
validator: (value: string | number) => boolean;
};
rounded: {
type: (BooleanConstructor | NumberConstructor | StringConstructor)[];
default: undefined;
};
tile: BooleanConstructor;
tag: Omit<{
type: PropType<string | import("../../util/index.js").JSXComponent>;
default: string;
}, "default" | "type"> & {
type: PropType<string | import("../../util/index.js").JSXComponent>;
default: NonNullable<string | import("../../util/index.js").JSXComponent>;
};
closeDelay: (NumberConstructor | StringConstructor)[];
openDelay: (NumberConstructor | StringConstructor)[];
retainFocus: BooleanConstructor;
captureFocus: BooleanConstructor;
color: StringConstructor;
disableResizeWatcher: BooleanConstructor;
disableRouteWatcher: BooleanConstructor;
expandOnHover: BooleanConstructor;
floating: BooleanConstructor;
modelValue: {
type: PropType<boolean | null>;
default: null;
};
permanent: BooleanConstructor;
rail: {
type: PropType<boolean | null>;
default: null;
};
railWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
scrim: {
type: (BooleanConstructor | StringConstructor)[];
default: boolean;
};
image: StringConstructor;
temporary: BooleanConstructor;
persistent: BooleanConstructor;
touchless: BooleanConstructor;
width: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
location: {
type: PropType<(typeof locations)[number]>;
default: string;
validator: (value: any) => boolean;
};
sticky: BooleanConstructor;
}, import("vue").ExtractPropTypes<{
theme: StringConstructor;
class: PropType<import("../../composables/component.js").ClassValue>;
style: {
type: PropType<import("vue").StyleValue>;
default: null;
};
mobile: Omit<{
type: PropType<boolean | null>;
default: boolean;
}, "default" | "type"> & {
type: PropType<boolean | null>;
default: NonNullable<boolean | null> | null;
};
mobileBreakpoint: PropType<number | import("../../types.js").DisplayBreakpoint>;
name: {
type: StringConstructor;
};
order: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
absolute: BooleanConstructor;
border: (BooleanConstructor | NumberConstructor | StringConstructor)[];
elevation: {
type: (NumberConstructor | StringConstructor)[];
validator: (value: string | number) => boolean;
};
rounded: {
type: (BooleanConstructor | NumberConstructor | StringConstructor)[];
default: undefined;
};
tile: BooleanConstructor;
tag: Omit<{
type: PropType<string | import("../../util/index.js").JSXComponent>;
default: string;
}, "default" | "type"> & {
type: PropType<string | import("../../util/index.js").JSXComponent>;
default: NonNullable<string | import("../../util/index.js").JSXComponent>;
};
closeDelay: (NumberConstructor | StringConstructor)[];
openDelay: (NumberConstructor | StringConstructor)[];
retainFocus: BooleanConstructor;
captureFocus: BooleanConstructor;
color: StringConstructor;
disableResizeWatcher: BooleanConstructor;
disableRouteWatcher: BooleanConstructor;
expandOnHover: BooleanConstructor;
floating: BooleanConstructor;
modelValue: {
type: PropType<boolean | null>;
default: null;
};
permanent: BooleanConstructor;
rail: {
type: PropType<boolean | null>;
default: null;
};
railWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
scrim: {
type: (BooleanConstructor | StringConstructor)[];
default: boolean;
};
image: StringConstructor;
temporary: BooleanConstructor;
persistent: BooleanConstructor;
touchless: BooleanConstructor;
width: {
type: (NumberConstructor | StringConstructor)[];
default: number;
};
location: {
type: PropType<(typeof locations)[number]>;
default: string;
validator: (value: any) => boolean;
};
sticky: BooleanConstructor;
}>>;
export type VNavigationDrawer = InstanceType<typeof VNavigationDrawer>;
@@ -0,0 +1,280 @@
import { Fragment as _Fragment, createVNode as _createVNode, createElementVNode as _createElementVNode, mergeProps as _mergeProps } from "vue";
// Styles
import "./VNavigationDrawer.css";
// Components
import { VDefaultsProvider } from "../VDefaultsProvider/index.js";
import { VImg } from "../VImg/index.js"; // Composables
import { useSticky } from "./sticky.js";
import { useTouch } from "./touch.js";
import { useRtl } from "../../composables/index.js";
import { makeBorderProps, useBorder } from "../../composables/border.js";
import { useBackgroundColor } from "../../composables/color.js";
import { makeComponentProps } from "../../composables/component.js";
import { provideDefaults } from "../../composables/defaults.js";
import { makeDelayProps, useDelay } from "../../composables/delay.js";
import { makeDisplayProps, useDisplay } from "../../composables/display.js";
import { makeElevationProps, useElevation } from "../../composables/elevation.js";
import { makeFocusTrapProps, useFocusTrap } from "../../composables/focusTrap.js";
import { makeLayoutItemProps, useLayoutItem } from "../../composables/layout.js";
import { useProxiedModel } from "../../composables/proxiedModel.js";
import { makeRoundedProps, useRounded } from "../../composables/rounded.js";
import { useRouter } from "../../composables/router.js";
import { useScopeId } from "../../composables/scopeId.js";
import { useSsrBoot } from "../../composables/ssrBoot.js";
import { makeTagProps } from "../../composables/tag.js";
import { makeThemeProps, provideTheme } from "../../composables/theme.js";
import { useToggleScope } from "../../composables/toggleScope.js"; // Utilities
import { computed, nextTick, readonly, ref, shallowRef, toRef, Transition, watch } from 'vue';
import { genericComponent, omit, propsFactory, toPhysical, useRender } from "../../util/index.js"; // Types
const locations = ['start', 'end', 'left', 'right', 'top', 'bottom'];
export const makeVNavigationDrawerProps = propsFactory({
color: String,
disableResizeWatcher: Boolean,
disableRouteWatcher: Boolean,
expandOnHover: Boolean,
floating: Boolean,
modelValue: {
type: Boolean,
default: null
},
permanent: Boolean,
rail: {
type: Boolean,
default: null
},
railWidth: {
type: [Number, String],
default: 56
},
scrim: {
type: [Boolean, String],
default: true
},
image: String,
temporary: Boolean,
persistent: Boolean,
touchless: Boolean,
width: {
type: [Number, String],
default: 256
},
location: {
type: String,
default: 'start',
validator: value => locations.includes(value)
},
sticky: Boolean,
...makeBorderProps(),
...makeComponentProps(),
...makeDelayProps(),
...makeDisplayProps({
mobile: null
}),
...makeElevationProps(),
...makeLayoutItemProps(),
...makeRoundedProps(),
...omit(makeFocusTrapProps(), ['disableInitialFocus']),
...makeTagProps({
tag: 'nav'
}),
...makeThemeProps()
}, 'VNavigationDrawer');
export const VNavigationDrawer = genericComponent()({
name: 'VNavigationDrawer',
props: makeVNavigationDrawerProps(),
emits: {
'update:modelValue': val => true,
'update:rail': val => true
},
setup(props, {
attrs,
emit,
slots
}) {
const {
isRtl
} = useRtl();
const {
themeClasses
} = provideTheme(props);
const {
borderClasses
} = useBorder(props);
const {
backgroundColorClasses,
backgroundColorStyles
} = useBackgroundColor(() => props.color);
const {
elevationClasses
} = useElevation(props);
const {
displayClasses,
mobile
} = useDisplay(props);
const {
roundedClasses
} = useRounded(props);
const router = useRouter();
const isActive = useProxiedModel(props, 'modelValue', null, v => !!v);
const {
ssrBootStyles
} = useSsrBoot();
const {
scopeId
} = useScopeId();
const rootEl = ref();
const isHovering = shallowRef(false);
const {
runOpenDelay,
runCloseDelay
} = useDelay(props, value => {
isHovering.value = value;
});
const width = computed(() => {
return props.rail && props.expandOnHover && isHovering.value ? Number(props.width) : Number(props.rail ? props.railWidth : props.width);
});
const location = computed(() => {
return toPhysical(props.location, isRtl.value);
});
const isPersistent = toRef(() => props.persistent);
const isTemporary = computed(() => !props.permanent && (mobile.value || props.temporary));
const isSticky = computed(() => props.sticky && !isTemporary.value && location.value !== 'bottom');
useFocusTrap(props, {
isActive,
localTop: isTemporary,
contentEl: rootEl
});
useToggleScope(() => props.expandOnHover && props.rail != null, () => {
watch(isHovering, val => emit('update:rail', !val));
});
useToggleScope(() => !props.disableResizeWatcher, () => {
watch(isTemporary, val => !props.permanent && nextTick(() => isActive.value = !val));
});
useToggleScope(() => !props.disableRouteWatcher && !!router, () => {
watch(router.currentRoute, () => isTemporary.value && (isActive.value = false));
});
watch(() => props.permanent, val => {
if (val) isActive.value = true;
});
if (props.modelValue == null && !isTemporary.value) {
isActive.value = props.permanent || !mobile.value;
}
const {
isDragging,
dragProgress
} = useTouch({
el: rootEl,
isActive,
isTemporary,
width,
touchless: toRef(() => props.touchless),
position: location
});
const layoutSize = computed(() => {
const size = isTemporary.value ? 0 : props.rail && props.expandOnHover ? Number(props.railWidth) : width.value;
return isDragging.value ? size * dragProgress.value : size;
});
const {
layoutItemStyles,
layoutItemScrimStyles
} = useLayoutItem({
id: props.name,
order: computed(() => parseInt(props.order, 10)),
position: location,
layoutSize,
elementSize: width,
active: readonly(isActive),
disableTransitions: toRef(() => isDragging.value),
absolute: computed(() =>
// eslint-disable-next-line @typescript-eslint/no-use-before-define
props.absolute || isSticky.value && typeof isStuck.value !== 'string')
});
const {
isStuck,
stickyStyles
} = useSticky({
rootEl,
isSticky,
layoutItemStyles
});
const scrimColor = useBackgroundColor(() => {
return typeof props.scrim === 'string' ? props.scrim : null;
});
const scrimStyles = computed(() => ({
...(isDragging.value ? {
opacity: dragProgress.value * 0.2,
transition: 'none'
} : undefined),
...layoutItemScrimStyles.value
}));
provideDefaults({
VList: {
bgColor: 'transparent'
}
});
useRender(() => {
const hasImage = slots.image || props.image;
return _createElementVNode(_Fragment, null, [_createVNode(props.tag, _mergeProps({
"ref": rootEl,
"onMouseenter": runOpenDelay,
"onMouseleave": runCloseDelay,
"class": ['v-navigation-drawer', `v-navigation-drawer--${location.value}`, {
'v-navigation-drawer--expand-on-hover': props.expandOnHover,
'v-navigation-drawer--floating': props.floating,
'v-navigation-drawer--is-hovering': isHovering.value,
'v-navigation-drawer--rail': props.rail,
'v-navigation-drawer--temporary': isTemporary.value,
'v-navigation-drawer--persistent': isPersistent.value,
'v-navigation-drawer--active': isActive.value,
'v-navigation-drawer--sticky': isSticky.value
}, themeClasses.value, backgroundColorClasses.value, borderClasses.value, displayClasses.value, elevationClasses.value, roundedClasses.value, props.class],
"style": [backgroundColorStyles.value, layoutItemStyles.value, ssrBootStyles.value, stickyStyles.value, props.style],
"inert": !isActive.value
}, scopeId, attrs), {
default: () => [hasImage && _createElementVNode("div", {
"key": "image",
"class": "v-navigation-drawer__img"
}, [!slots.image ? _createVNode(VImg, {
"key": "image-img",
"alt": "",
"cover": true,
"height": "inherit",
"src": props.image
}, null) : _createVNode(VDefaultsProvider, {
"key": "image-defaults",
"disabled": !props.image,
"defaults": {
VImg: {
alt: '',
cover: true,
height: 'inherit',
src: props.image
}
}
}, slots.image)]), slots.prepend && _createElementVNode("div", {
"class": "v-navigation-drawer__prepend"
}, [slots.prepend?.()]), _createElementVNode("div", {
"class": "v-navigation-drawer__content"
}, [slots.default?.()]), slots.append && _createElementVNode("div", {
"class": "v-navigation-drawer__append"
}, [slots.append?.()])]
}), _createVNode(Transition, {
"name": "fade-transition"
}, {
default: () => [isTemporary.value && (isDragging.value || isActive.value) && !!props.scrim && _createElementVNode("div", _mergeProps({
"class": ['v-navigation-drawer__scrim', scrimColor.backgroundColorClasses.value],
"style": [scrimStyles.value, scrimColor.backgroundColorStyles.value],
"onClick": () => {
if (isPersistent.value) return;
isActive.value = false;
}
}, scopeId), null)]
})]);
});
return {
isStuck
};
}
});
//# sourceMappingURL=VNavigationDrawer.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,97 @@
@use '../../styles/tools'
@use './variables' as *
@include tools.layer('components')
.v-navigation-drawer
-webkit-overflow-scrolling: $navigation-drawer-overflow-scrolling
background: $navigation-drawer-background
display: flex
flex-direction: column
height: $navigation-drawer-height
max-width: 100%
pointer-events: auto
transition-duration: $navigation-drawer-transition-duration
transition-property: $navigation-drawer-transition-property
transition-timing-function: $navigation-drawer-transition-timing-function
position: absolute
@include tools.border($navigation-drawer-border...)
@include tools.elevation($navigation-drawer-elevation)
@include tools.rounded($navigation-drawer-border-radius)
@include tools.theme($navigation-drawer-theme...)
@media (prefers-reduced-motion: reduce)
transition: none
&--rounded
@include tools.rounded($navigation-drawer-rounded-border-radius)
&--top
top: 0
border-bottom-width: $navigation-drawer-border-thin-width
&--bottom
left: 0
border-top-width: $navigation-drawer-border-thin-width
&--left
top: 0
left: 0
right: auto
border-right-width: $navigation-drawer-border-thin-width
&--right
top: 0
left: auto
right: 0
border-left-width: $navigation-drawer-border-thin-width
&--floating
border: none
&--temporary.v-navigation-drawer--active
@include tools.elevation($navigation-drawer-temporary-elevation)
&--sticky
height: auto
transition: box-shadow, transform, visibility, width, height, left, right
.v-list
overflow: hidden
.v-navigation-drawer__content
flex: 0 1 auto
height: $navigation-drawer-content-height
max-width: 100%
overflow-x: $navigation-drawer-content-overflow-x
overflow-y: $navigation-drawer-content-overflow-y
.v-navigation-drawer__img
height: 100%
left: 0
position: absolute
top: 0
width: 100%
z-index: -1
// TODO: remove in v4
img:not(.v-img__img)
height: $navigation-drawer-img-height
object-fit: $navigation-drawer-img-object-fit
width: $navigation-drawer-img-width
.v-navigation-drawer__scrim
position: absolute
top: 0
left: 0
width: 100%
height: 100%
background: black
opacity: $navigation-drawer-scrim-opacity
transition: opacity $navigation-drawer-transition-duration $navigation-drawer-transition-timing-function
z-index: 1
.v-navigation-drawer__prepend,
.v-navigation-drawer__append
flex: none
overflow: hidden
@@ -0,0 +1,40 @@
@use 'sass:map';
@use '../../styles/settings';
@use '../../styles/tools';
// VNavigationDrawer
$navigation-drawer-background: rgb(var(--v-theme-surface)) !default;
$navigation-drawer-border-color: settings.$border-color-root !default;
$navigation-drawer-border-radius: map.get(settings.$rounded, '0') !default;
$navigation-drawer-border-style: settings.$border-style-root !default;
$navigation-drawer-border-thin-width: thin !default;
$navigation-drawer-border-width: 0 !default;
$navigation-drawer-color: tools.theme-color('on-surface', var(--v-high-emphasis-opacity)) !default;
$navigation-drawer-content-height: 100% !default;
$navigation-drawer-content-overflow-x: hidden !default;
$navigation-drawer-content-overflow-y: auto !default;
$navigation-drawer-elevation: 0 !default;
$navigation-drawer-height: 100% !default;
$navigation-drawer-img-height: inherit !default;
$navigation-drawer-img-object-fit: cover !default;
$navigation-drawer-img-width: inherit !default;
$navigation-drawer-overflow-scrolling: touch !default;
$navigation-drawer-rounded-border-radius: settings.$border-radius-root !default;
$navigation-drawer-temporary-elevation: 4 !default;
$navigation-drawer-transition-duration: 0.2s !default;
$navigation-drawer-transition-property: box-shadow, transform, visibility, width, height, left, right, top, bottom !default;
$navigation-drawer-transition-timing-function: settings.$standard-easing !default;
$navigation-drawer-scrim-opacity: .2 !default;
// Lists
$navigation-drawer-border: (
$navigation-drawer-border-color,
$navigation-drawer-border-style,
$navigation-drawer-border-width,
$navigation-drawer-border-thin-width
) !default;
$navigation-drawer-theme: (
$navigation-drawer-background,
$navigation-drawer-color
) !default;
@@ -0,0 +1 @@
export { VNavigationDrawer } from './VNavigationDrawer.js';
@@ -0,0 +1,2 @@
export { VNavigationDrawer } from "./VNavigationDrawer.js";
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["VNavigationDrawer"],"sources":["../../../src/components/VNavigationDrawer/index.ts"],"sourcesContent":["export { VNavigationDrawer } from './VNavigationDrawer'\n"],"mappings":"SAASA,iBAAiB","ignoreList":[]}
@@ -0,0 +1,11 @@
import type { CSSProperties, Ref, StyleValue } from 'vue';
interface StickyProps {
rootEl: Ref<HTMLElement | undefined>;
isSticky: Ref<boolean>;
layoutItemStyles: Ref<CSSProperties>;
}
export declare function useSticky({ rootEl, isSticky, layoutItemStyles }: StickyProps): {
isStuck: import("vue").ShallowRef<"bottom" | "top" | boolean, "bottom" | "top" | boolean>;
stickyStyles: import("vue").ComputedRef<StyleValue>;
};
@@ -0,0 +1,72 @@
// Utilities
import { computed, onBeforeUnmount, onMounted, shallowRef, watch } from 'vue';
import { convertToUnit } from "../../util/index.js"; // Types
export function useSticky({
rootEl,
isSticky,
layoutItemStyles
}) {
const isStuck = shallowRef(false);
const stuckPosition = shallowRef(0);
const stickyStyles = computed(() => {
const side = typeof isStuck.value === 'boolean' ? 'top' : isStuck.value;
return [isSticky.value ? {
top: 'auto',
bottom: 'auto',
height: undefined
} : undefined, isStuck.value ? {
[side]: convertToUnit(stuckPosition.value)
} : {
top: layoutItemStyles.value.top
}];
});
onMounted(() => {
watch(isSticky, val => {
if (val) {
window.addEventListener('scroll', onScroll, {
passive: true
});
} else {
window.removeEventListener('scroll', onScroll);
}
}, {
immediate: true
});
});
onBeforeUnmount(() => {
window.removeEventListener('scroll', onScroll);
});
let lastScrollTop = 0;
function onScroll() {
const direction = lastScrollTop > window.scrollY ? 'up' : 'down';
const rect = rootEl.value.getBoundingClientRect();
const layoutTop = parseFloat(layoutItemStyles.value.top ?? 0);
const top = window.scrollY - Math.max(0, stuckPosition.value - layoutTop);
const bottom = rect.height + Math.max(stuckPosition.value, layoutTop) - window.scrollY - window.innerHeight;
const bodyScroll = parseFloat(getComputedStyle(rootEl.value).getPropertyValue('--v-body-scroll-y')) || 0;
if (rect.height < window.innerHeight - layoutTop) {
isStuck.value = 'top';
stuckPosition.value = layoutTop;
} else if (direction === 'up' && isStuck.value === 'bottom' || direction === 'down' && isStuck.value === 'top') {
stuckPosition.value = window.scrollY + rect.top - bodyScroll;
isStuck.value = true;
} else if (direction === 'down' && bottom <= 0) {
stuckPosition.value = 0;
isStuck.value = 'bottom';
} else if (direction === 'up' && top <= 0) {
if (!bodyScroll) {
stuckPosition.value = rect.top + top;
isStuck.value = 'top';
} else if (isStuck.value !== 'top') {
stuckPosition.value = -top + bodyScroll + layoutTop;
isStuck.value = 'top';
}
}
lastScrollTop = window.scrollY;
}
return {
isStuck,
stickyStyles
};
}
//# sourceMappingURL=sticky.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
import type { Ref } from 'vue';
export declare function useTouch({ el, isActive, isTemporary, width, touchless, position }: {
el: Ref<HTMLElement | undefined>;
isActive: Ref<boolean>;
isTemporary: Ref<boolean>;
width: Ref<number>;
touchless: Ref<boolean>;
position: Ref<'left' | 'right' | 'top' | 'bottom'>;
}): {
isDragging: import("vue").ShallowRef<boolean, boolean>;
dragProgress: import("vue").ShallowRef<number, number>;
dragStyles: import("vue").ComputedRef<{
transform: string;
transition: string;
} | undefined>;
};
+140
View File
@@ -0,0 +1,140 @@
// Composables
import { useToggleScope } from "../../composables/toggleScope.js";
import { useVelocity } from "../../composables/touch.js"; // Utilities
import { computed, onBeforeUnmount, onMounted, onScopeDispose, shallowRef, watchEffect } from 'vue';
import { clamp } from "../../util/index.js"; // Types
export function useTouch({
el,
isActive,
isTemporary,
width,
touchless,
position
}) {
onMounted(() => {
window.addEventListener('touchstart', onTouchstart, {
passive: true
});
window.addEventListener('touchmove', onTouchmove, {
passive: false
});
window.addEventListener('touchend', onTouchend, {
passive: true
});
});
onBeforeUnmount(() => {
window.removeEventListener('touchstart', onTouchstart);
window.removeEventListener('touchmove', onTouchmove);
window.removeEventListener('touchend', onTouchend);
});
const isHorizontal = computed(() => ['left', 'right'].includes(position.value));
const {
addMovement,
endTouch,
getVelocity
} = useVelocity();
let maybeDragging = false;
const isDragging = shallowRef(false);
const dragProgress = shallowRef(0);
const offset = shallowRef(0);
let start;
function getOffset(pos, active) {
return (position.value === 'left' ? pos : position.value === 'right' ? document.documentElement.clientWidth - pos : position.value === 'top' ? pos : position.value === 'bottom' ? document.documentElement.clientHeight - pos : oops()) - (active ? width.value : 0);
}
function getProgress(pos, limit = true) {
const progress = position.value === 'left' ? (pos - offset.value) / width.value : position.value === 'right' ? (document.documentElement.clientWidth - pos - offset.value) / width.value : position.value === 'top' ? (pos - offset.value) / width.value : position.value === 'bottom' ? (document.documentElement.clientHeight - pos - offset.value) / width.value : oops();
return limit ? clamp(progress) : progress;
}
function onTouchstart(e) {
if (touchless.value) return;
const touchX = e.changedTouches[0].clientX;
const touchY = e.changedTouches[0].clientY;
const touchZone = 25;
const inTouchZone = position.value === 'left' ? touchX < touchZone : position.value === 'right' ? touchX > document.documentElement.clientWidth - touchZone : position.value === 'top' ? touchY < touchZone : position.value === 'bottom' ? touchY > document.documentElement.clientHeight - touchZone : oops();
const inElement = isActive.value && (position.value === 'left' ? touchX < width.value : position.value === 'right' ? touchX > document.documentElement.clientWidth - width.value : position.value === 'top' ? touchY < width.value : position.value === 'bottom' ? touchY > document.documentElement.clientHeight - width.value : oops());
if (inTouchZone || inElement || isActive.value && isTemporary.value) {
start = [touchX, touchY];
offset.value = getOffset(isHorizontal.value ? touchX : touchY, isActive.value);
dragProgress.value = getProgress(isHorizontal.value ? touchX : touchY);
maybeDragging = offset.value > -20 && offset.value < 80;
endTouch(e);
addMovement(e);
}
}
function onTouchmove(e) {
const touchX = e.changedTouches[0].clientX;
const touchY = e.changedTouches[0].clientY;
if (maybeDragging) {
if (!e.cancelable) {
maybeDragging = false;
return;
}
const dx = Math.abs(touchX - start[0]);
const dy = Math.abs(touchY - start[1]);
const thresholdMet = isHorizontal.value ? dx > dy && dx > 3 : dy > dx && dy > 3;
if (thresholdMet) {
isDragging.value = true;
maybeDragging = false;
} else if ((isHorizontal.value ? dy : dx) > 3) {
maybeDragging = false;
}
}
if (!isDragging.value) return;
e.preventDefault();
addMovement(e);
const progress = getProgress(isHorizontal.value ? touchX : touchY, false);
dragProgress.value = Math.max(0, Math.min(1, progress));
if (progress > 1) {
offset.value = getOffset(isHorizontal.value ? touchX : touchY, true);
} else if (progress < 0) {
offset.value = getOffset(isHorizontal.value ? touchX : touchY, false);
}
}
function onTouchend(e) {
maybeDragging = false;
if (!isDragging.value) return;
addMovement(e);
isDragging.value = false;
const velocity = getVelocity(e.changedTouches[0].identifier);
const vx = Math.abs(velocity.x);
const vy = Math.abs(velocity.y);
const thresholdMet = isHorizontal.value ? vx > vy && vx > 400 : vy > vx && vy > 3;
if (thresholdMet) {
isActive.value = velocity.direction === ({
left: 'right',
right: 'left',
top: 'down',
bottom: 'up'
}[position.value] || oops());
} else {
isActive.value = dragProgress.value > 0.5;
}
}
const dragStyles = computed(() => {
return isDragging.value ? {
transform: position.value === 'left' ? `translateX(calc(-100% + ${dragProgress.value * width.value}px))` : position.value === 'right' ? `translateX(calc(100% - ${dragProgress.value * width.value}px))` : position.value === 'top' ? `translateY(calc(-100% + ${dragProgress.value * width.value}px))` : position.value === 'bottom' ? `translateY(calc(100% - ${dragProgress.value * width.value}px))` : oops(),
transition: 'none'
} : undefined;
});
useToggleScope(isDragging, () => {
const transform = el.value?.style.transform ?? null;
const transition = el.value?.style.transition ?? null;
watchEffect(() => {
el.value?.style.setProperty('transform', dragStyles.value?.transform || 'none');
el.value?.style.setProperty('transition', dragStyles.value?.transition || null);
});
onScopeDispose(() => {
el.value?.style.setProperty('transform', transform);
el.value?.style.setProperty('transition', transition);
});
});
return {
isDragging,
dragProgress,
dragStyles
};
}
function oops() {
throw new Error();
}
//# sourceMappingURL=touch.js.map
File diff suppressed because one or more lines are too long