routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+25
@@ -0,0 +1,25 @@
|
||||
@layer vuetify-components {
|
||||
.v-time-picker.v-picker {
|
||||
min-width: 328px;
|
||||
}
|
||||
.v-time-picker .v-picker__body, .v-time-picker-controls__field-label,
|
||||
.v-time-picker .v-field {
|
||||
transition-duration: 0.25s;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-property: transform, max-height, opacity, font-size;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.v-time-picker .v-picker__body, .v-time-picker-controls__field-label,
|
||||
.v-time-picker .v-field {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
.v-time-picker .v-picker__body {
|
||||
transition-behavior: allow-discrete;
|
||||
max-height: calc-size(max-content, size);
|
||||
}
|
||||
.v-time-picker--variant-input .v-picker__body {
|
||||
transform: scale(0);
|
||||
max-height: 0;
|
||||
}
|
||||
}
|
||||
+702
@@ -0,0 +1,702 @@
|
||||
|
||||
import type { PropType } from 'vue';
|
||||
import type { Period, VTimePickerViewMode } from './shared.js';
|
||||
import type { VPickerSlots } from '../../labs/VPicker/VPicker.js';
|
||||
export type VTimePickerSlots = Omit<VPickerSlots, 'header'>;
|
||||
type Variant = 'dial' | 'input';
|
||||
export declare const makeVTimePickerProps: <Defaults extends {
|
||||
theme?: unknown;
|
||||
class?: unknown;
|
||||
style?: unknown;
|
||||
border?: unknown;
|
||||
density?: unknown;
|
||||
elevation?: unknown;
|
||||
rounded?: unknown;
|
||||
tile?: unknown;
|
||||
tag?: unknown;
|
||||
height?: unknown;
|
||||
maxHeight?: unknown;
|
||||
maxWidth?: unknown;
|
||||
minHeight?: unknown;
|
||||
minWidth?: unknown;
|
||||
width?: unknown;
|
||||
location?: unknown;
|
||||
position?: unknown;
|
||||
color?: unknown;
|
||||
bgColor?: unknown;
|
||||
divided?: unknown;
|
||||
title?: unknown;
|
||||
hideHeader?: unknown;
|
||||
hideTitle?: unknown;
|
||||
allowedHours?: unknown;
|
||||
allowedMinutes?: unknown;
|
||||
allowedSeconds?: unknown;
|
||||
max?: unknown;
|
||||
min?: unknown;
|
||||
disabled?: unknown;
|
||||
format?: unknown;
|
||||
viewMode?: unknown;
|
||||
period?: unknown;
|
||||
modelValue?: unknown;
|
||||
readonly?: unknown;
|
||||
scrollable?: unknown;
|
||||
useSeconds?: unknown;
|
||||
variant?: 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>;
|
||||
};
|
||||
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>;
|
||||
};
|
||||
density: unknown extends Defaults["density"] ? {
|
||||
type: PropType<import("../../composables/density.js").Density>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
} : Omit<{
|
||||
type: PropType<import("../../composables/density.js").Density>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["density"] ? import("../../composables/density.js").Density : Defaults["density"] | import("../../composables/density.js").Density>;
|
||||
default: unknown extends Defaults["density"] ? import("../../composables/density.js").Density : Defaults["density"] | NonNullable<import("../../composables/density.js").Density>;
|
||||
};
|
||||
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"] ? {
|
||||
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>;
|
||||
};
|
||||
location: unknown extends Defaults["location"] ? PropType<import("../../util/index.js").Anchor | null> : {
|
||||
type: PropType<unknown extends Defaults["location"] ? import("../../util/index.js").Anchor | null : Defaults["location"] | import("../../util/index.js").Anchor | null>;
|
||||
default: unknown extends Defaults["location"] ? import("../../util/index.js").Anchor | null : Defaults["location"] | NonNullable<import("../../util/index.js").Anchor | null>;
|
||||
};
|
||||
position: unknown extends Defaults["position"] ? {
|
||||
type: PropType<"absolute" | "fixed" | "relative" | "static" | "sticky">;
|
||||
validator: (v: any) => boolean;
|
||||
} : Omit<{
|
||||
type: PropType<"absolute" | "fixed" | "relative" | "static" | "sticky">;
|
||||
validator: (v: any) => boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["position"] ? "absolute" | "fixed" | "relative" | "static" | "sticky" : "absolute" | "fixed" | "relative" | "static" | "sticky" | Defaults["position"]>;
|
||||
default: unknown extends Defaults["position"] ? "absolute" | "fixed" | "relative" | "static" | "sticky" : Defaults["position"] | NonNullable<"absolute" | "fixed" | "relative" | "static" | "sticky">;
|
||||
};
|
||||
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"];
|
||||
};
|
||||
bgColor: unknown extends Defaults["bgColor"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["bgColor"] ? string : string | Defaults["bgColor"]>;
|
||||
default: unknown extends Defaults["bgColor"] ? string : string | Defaults["bgColor"];
|
||||
};
|
||||
divided: unknown extends Defaults["divided"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["divided"] ? boolean : boolean | Defaults["divided"]>;
|
||||
default: unknown extends Defaults["divided"] ? boolean : boolean | Defaults["divided"];
|
||||
};
|
||||
title: unknown extends Defaults["title"] ? {
|
||||
type: PropType<string>;
|
||||
default: string;
|
||||
} : Omit<{
|
||||
type: PropType<string>;
|
||||
default: string;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["title"] ? string : string | Defaults["title"]>;
|
||||
default: unknown extends Defaults["title"] ? string : string | Defaults["title"];
|
||||
};
|
||||
hideHeader: unknown extends Defaults["hideHeader"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["hideHeader"] ? boolean : boolean | Defaults["hideHeader"]>;
|
||||
default: unknown extends Defaults["hideHeader"] ? boolean : boolean | Defaults["hideHeader"];
|
||||
};
|
||||
hideTitle: unknown extends Defaults["hideTitle"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["hideTitle"] ? boolean : boolean | Defaults["hideTitle"]>;
|
||||
default: unknown extends Defaults["hideTitle"] ? boolean : boolean | Defaults["hideTitle"];
|
||||
};
|
||||
allowedHours: unknown extends Defaults["allowedHours"] ? PropType<import("./useTimeValidation.js").AllowFunction | number[]> : {
|
||||
type: PropType<unknown extends Defaults["allowedHours"] ? import("./useTimeValidation.js").AllowFunction | number[] : import("./useTimeValidation.js").AllowFunction | number[] | Defaults["allowedHours"]>;
|
||||
default: unknown extends Defaults["allowedHours"] ? import("./useTimeValidation.js").AllowFunction | number[] : Defaults["allowedHours"] | NonNullable<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
};
|
||||
allowedMinutes: unknown extends Defaults["allowedMinutes"] ? PropType<import("./useTimeValidation.js").AllowFunction | number[]> : {
|
||||
type: PropType<unknown extends Defaults["allowedMinutes"] ? import("./useTimeValidation.js").AllowFunction | number[] : import("./useTimeValidation.js").AllowFunction | number[] | Defaults["allowedMinutes"]>;
|
||||
default: unknown extends Defaults["allowedMinutes"] ? import("./useTimeValidation.js").AllowFunction | number[] : Defaults["allowedMinutes"] | NonNullable<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
};
|
||||
allowedSeconds: unknown extends Defaults["allowedSeconds"] ? PropType<import("./useTimeValidation.js").AllowFunction | number[]> : {
|
||||
type: PropType<unknown extends Defaults["allowedSeconds"] ? import("./useTimeValidation.js").AllowFunction | number[] : import("./useTimeValidation.js").AllowFunction | number[] | Defaults["allowedSeconds"]>;
|
||||
default: unknown extends Defaults["allowedSeconds"] ? import("./useTimeValidation.js").AllowFunction | number[] : Defaults["allowedSeconds"] | NonNullable<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
};
|
||||
max: unknown extends Defaults["max"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["max"] ? string : string | Defaults["max"]>;
|
||||
default: unknown extends Defaults["max"] ? string : string | Defaults["max"];
|
||||
};
|
||||
min: unknown extends Defaults["min"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["min"] ? string : string | Defaults["min"]>;
|
||||
default: unknown extends Defaults["min"] ? string : string | Defaults["min"];
|
||||
};
|
||||
disabled: unknown extends Defaults["disabled"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["disabled"] ? boolean : boolean | Defaults["disabled"]>;
|
||||
default: unknown extends Defaults["disabled"] ? boolean : boolean | Defaults["disabled"];
|
||||
};
|
||||
format: unknown extends Defaults["format"] ? {
|
||||
type: PropType<'ampm' | '24hr'>;
|
||||
default: string;
|
||||
} : Omit<{
|
||||
type: PropType<'ampm' | '24hr'>;
|
||||
default: string;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["format"] ? "24hr" | "ampm" : "24hr" | "ampm" | Defaults["format"]>;
|
||||
default: unknown extends Defaults["format"] ? "24hr" | "ampm" : Defaults["format"] | NonNullable<"24hr" | "ampm">;
|
||||
};
|
||||
viewMode: unknown extends Defaults["viewMode"] ? {
|
||||
type: PropType<VTimePickerViewMode>;
|
||||
default: string;
|
||||
} : Omit<{
|
||||
type: PropType<VTimePickerViewMode>;
|
||||
default: string;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["viewMode"] ? VTimePickerViewMode : Defaults["viewMode"] | VTimePickerViewMode>;
|
||||
default: unknown extends Defaults["viewMode"] ? VTimePickerViewMode : Defaults["viewMode"] | NonNullable<VTimePickerViewMode>;
|
||||
};
|
||||
period: unknown extends Defaults["period"] ? {
|
||||
type: PropType<Period>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
} : Omit<{
|
||||
type: PropType<Period>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["period"] ? Period : Defaults["period"] | Period>;
|
||||
default: unknown extends Defaults["period"] ? Period : Defaults["period"] | NonNullable<Period>;
|
||||
};
|
||||
modelValue: unknown extends Defaults["modelValue"] ? PropType<any> : {
|
||||
type: PropType<unknown extends Defaults["modelValue"] ? any : any>;
|
||||
default: unknown extends Defaults["modelValue"] ? any : any;
|
||||
};
|
||||
readonly: unknown extends Defaults["readonly"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["readonly"] ? boolean : boolean | Defaults["readonly"]>;
|
||||
default: unknown extends Defaults["readonly"] ? boolean : boolean | Defaults["readonly"];
|
||||
};
|
||||
scrollable: unknown extends Defaults["scrollable"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["scrollable"] ? boolean : boolean | Defaults["scrollable"]>;
|
||||
default: unknown extends Defaults["scrollable"] ? boolean : boolean | Defaults["scrollable"];
|
||||
};
|
||||
useSeconds: unknown extends Defaults["useSeconds"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["useSeconds"] ? boolean : boolean | Defaults["useSeconds"]>;
|
||||
default: unknown extends Defaults["useSeconds"] ? boolean : boolean | Defaults["useSeconds"];
|
||||
};
|
||||
variant: unknown extends Defaults["variant"] ? {
|
||||
type: PropType<Variant>;
|
||||
default: string;
|
||||
} : Omit<{
|
||||
type: PropType<Variant>;
|
||||
default: string;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["variant"] ? Variant : Defaults["variant"] | Variant>;
|
||||
default: unknown extends Defaults["variant"] ? Variant : Defaults["variant"] | NonNullable<Variant>;
|
||||
};
|
||||
};
|
||||
export declare const VTimePicker: {
|
||||
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<{
|
||||
style: string | false | import("vue").StyleValue[] | import("vue").CSSProperties | null;
|
||||
density: import("../../composables/density.js").Density;
|
||||
tile: boolean;
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
divided: boolean;
|
||||
title: string;
|
||||
hideHeader: boolean;
|
||||
hideTitle: boolean;
|
||||
disabled: boolean;
|
||||
format: "24hr" | "ampm";
|
||||
viewMode: VTimePickerViewMode;
|
||||
period: Period;
|
||||
readonly: boolean;
|
||||
scrollable: boolean;
|
||||
useSeconds: boolean;
|
||||
variant: Variant;
|
||||
} & {
|
||||
theme?: string | undefined;
|
||||
class?: any;
|
||||
border?: string | number | boolean | undefined;
|
||||
elevation?: string | number | undefined;
|
||||
rounded?: string | number | boolean | undefined;
|
||||
height?: string | number | undefined;
|
||||
maxHeight?: string | number | undefined;
|
||||
maxWidth?: string | number | undefined;
|
||||
minHeight?: string | number | undefined;
|
||||
minWidth?: string | number | undefined;
|
||||
width?: string | number | undefined;
|
||||
location?: import("../../util/index.js").Anchor | null | undefined;
|
||||
position?: "absolute" | "fixed" | "relative" | "static" | "sticky" | undefined;
|
||||
color?: string | undefined;
|
||||
bgColor?: string | undefined;
|
||||
allowedHours?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedMinutes?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedSeconds?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
max?: string | undefined;
|
||||
min?: string | undefined;
|
||||
modelValue?: any;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
actions?: (() => import("vue").VNodeChild) | undefined;
|
||||
title?: (() => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
actions?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
title?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:actions"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:title"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
"onUpdate:hour"?: ((val: number) => any) | undefined;
|
||||
"onUpdate:minute"?: ((val: number) => any) | undefined;
|
||||
"onUpdate:modelValue"?: ((val: string | null) => any) | undefined;
|
||||
"onUpdate:period"?: ((val: Period) => any) | undefined;
|
||||
"onUpdate:second"?: ((val: number) => any) | undefined;
|
||||
"onUpdate:viewMode"?: ((val: VTimePickerViewMode) => any) | undefined;
|
||||
}, void, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
'update:hour': (val: number) => true;
|
||||
'update:minute': (val: number) => true;
|
||||
'update:period': (val: Period) => true;
|
||||
'update:second': (val: number) => true;
|
||||
'update:modelValue': (val: string | null) => true;
|
||||
'update:viewMode': (val: VTimePickerViewMode) => true;
|
||||
}, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, {
|
||||
style: import("vue").StyleValue;
|
||||
density: import("../../composables/density.js").Density;
|
||||
rounded: string | number | boolean;
|
||||
tile: boolean;
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
divided: boolean;
|
||||
title: string;
|
||||
hideHeader: boolean;
|
||||
hideTitle: boolean;
|
||||
disabled: boolean;
|
||||
format: "24hr" | "ampm";
|
||||
viewMode: VTimePickerViewMode;
|
||||
period: Period;
|
||||
readonly: boolean;
|
||||
scrollable: boolean;
|
||||
useSeconds: boolean;
|
||||
variant: Variant;
|
||||
}, true, {}, import("vue").SlotsType<Partial<{
|
||||
default: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
actions: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
title: () => 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;
|
||||
density: import("../../composables/density.js").Density;
|
||||
tile: boolean;
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
divided: boolean;
|
||||
title: string;
|
||||
hideHeader: boolean;
|
||||
hideTitle: boolean;
|
||||
disabled: boolean;
|
||||
format: "24hr" | "ampm";
|
||||
viewMode: VTimePickerViewMode;
|
||||
period: Period;
|
||||
readonly: boolean;
|
||||
scrollable: boolean;
|
||||
useSeconds: boolean;
|
||||
variant: Variant;
|
||||
} & {
|
||||
theme?: string | undefined;
|
||||
class?: any;
|
||||
border?: string | number | boolean | undefined;
|
||||
elevation?: string | number | undefined;
|
||||
rounded?: string | number | boolean | undefined;
|
||||
height?: string | number | undefined;
|
||||
maxHeight?: string | number | undefined;
|
||||
maxWidth?: string | number | undefined;
|
||||
minHeight?: string | number | undefined;
|
||||
minWidth?: string | number | undefined;
|
||||
width?: string | number | undefined;
|
||||
location?: import("../../util/index.js").Anchor | null | undefined;
|
||||
position?: "absolute" | "fixed" | "relative" | "static" | "sticky" | undefined;
|
||||
color?: string | undefined;
|
||||
bgColor?: string | undefined;
|
||||
allowedHours?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedMinutes?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedSeconds?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
max?: string | undefined;
|
||||
min?: string | undefined;
|
||||
modelValue?: any;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
actions?: (() => import("vue").VNodeChild) | undefined;
|
||||
title?: (() => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
actions?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
title?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:actions"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:title"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
"onUpdate:hour"?: ((val: number) => any) | undefined;
|
||||
"onUpdate:minute"?: ((val: number) => any) | undefined;
|
||||
"onUpdate:modelValue"?: ((val: string | null) => any) | undefined;
|
||||
"onUpdate:period"?: ((val: Period) => any) | undefined;
|
||||
"onUpdate:second"?: ((val: number) => any) | undefined;
|
||||
"onUpdate:viewMode"?: ((val: VTimePickerViewMode) => any) | undefined;
|
||||
}, {}, {}, {}, {}, {
|
||||
style: import("vue").StyleValue;
|
||||
density: import("../../composables/density.js").Density;
|
||||
rounded: string | number | boolean;
|
||||
tile: boolean;
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
divided: boolean;
|
||||
title: string;
|
||||
hideHeader: boolean;
|
||||
hideTitle: boolean;
|
||||
disabled: boolean;
|
||||
format: "24hr" | "ampm";
|
||||
viewMode: VTimePickerViewMode;
|
||||
period: Period;
|
||||
readonly: boolean;
|
||||
scrollable: boolean;
|
||||
useSeconds: boolean;
|
||||
variant: Variant;
|
||||
}>;
|
||||
__isFragment?: never;
|
||||
__isTeleport?: never;
|
||||
__isSuspense?: never;
|
||||
} & import("vue").ComponentOptionsBase<{
|
||||
style: string | false | import("vue").StyleValue[] | import("vue").CSSProperties | null;
|
||||
density: import("../../composables/density.js").Density;
|
||||
tile: boolean;
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
divided: boolean;
|
||||
title: string;
|
||||
hideHeader: boolean;
|
||||
hideTitle: boolean;
|
||||
disabled: boolean;
|
||||
format: "24hr" | "ampm";
|
||||
viewMode: VTimePickerViewMode;
|
||||
period: Period;
|
||||
readonly: boolean;
|
||||
scrollable: boolean;
|
||||
useSeconds: boolean;
|
||||
variant: Variant;
|
||||
} & {
|
||||
theme?: string | undefined;
|
||||
class?: any;
|
||||
border?: string | number | boolean | undefined;
|
||||
elevation?: string | number | undefined;
|
||||
rounded?: string | number | boolean | undefined;
|
||||
height?: string | number | undefined;
|
||||
maxHeight?: string | number | undefined;
|
||||
maxWidth?: string | number | undefined;
|
||||
minHeight?: string | number | undefined;
|
||||
minWidth?: string | number | undefined;
|
||||
width?: string | number | undefined;
|
||||
location?: import("../../util/index.js").Anchor | null | undefined;
|
||||
position?: "absolute" | "fixed" | "relative" | "static" | "sticky" | undefined;
|
||||
color?: string | undefined;
|
||||
bgColor?: string | undefined;
|
||||
allowedHours?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedMinutes?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedSeconds?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
max?: string | undefined;
|
||||
min?: string | undefined;
|
||||
modelValue?: any;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
actions?: (() => import("vue").VNodeChild) | undefined;
|
||||
title?: (() => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
actions?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
title?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:actions"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
"v-slot:title"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
"onUpdate:hour"?: ((val: number) => any) | undefined;
|
||||
"onUpdate:minute"?: ((val: number) => any) | undefined;
|
||||
"onUpdate:modelValue"?: ((val: string | null) => any) | undefined;
|
||||
"onUpdate:period"?: ((val: Period) => any) | undefined;
|
||||
"onUpdate:second"?: ((val: number) => any) | undefined;
|
||||
"onUpdate:viewMode"?: ((val: VTimePickerViewMode) => any) | undefined;
|
||||
}, void, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
'update:hour': (val: number) => true;
|
||||
'update:minute': (val: number) => true;
|
||||
'update:period': (val: Period) => true;
|
||||
'update:second': (val: number) => true;
|
||||
'update:modelValue': (val: string | null) => true;
|
||||
'update:viewMode': (val: VTimePickerViewMode) => true;
|
||||
}, string, {
|
||||
style: import("vue").StyleValue;
|
||||
density: import("../../composables/density.js").Density;
|
||||
rounded: string | number | boolean;
|
||||
tile: boolean;
|
||||
tag: string | import("../../util/index.js").JSXComponent;
|
||||
divided: boolean;
|
||||
title: string;
|
||||
hideHeader: boolean;
|
||||
hideTitle: boolean;
|
||||
disabled: boolean;
|
||||
format: "24hr" | "ampm";
|
||||
viewMode: VTimePickerViewMode;
|
||||
period: Period;
|
||||
readonly: boolean;
|
||||
scrollable: boolean;
|
||||
useSeconds: boolean;
|
||||
variant: Variant;
|
||||
}, {}, string, import("vue").SlotsType<Partial<{
|
||||
default: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
actions: () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
||||
[key: string]: any;
|
||||
}>[];
|
||||
title: () => 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;
|
||||
};
|
||||
border: (BooleanConstructor | NumberConstructor | StringConstructor)[];
|
||||
density: {
|
||||
type: PropType<import("../../composables/density.js").Density>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
elevation: {
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
validator: (value: string | number) => boolean;
|
||||
};
|
||||
rounded: {
|
||||
type: (BooleanConstructor | NumberConstructor | StringConstructor)[];
|
||||
default: undefined;
|
||||
};
|
||||
tile: BooleanConstructor;
|
||||
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)[];
|
||||
location: PropType<import("../../util/index.js").Anchor | null>;
|
||||
position: {
|
||||
type: PropType<"absolute" | "fixed" | "relative" | "static" | "sticky">;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
color: StringConstructor;
|
||||
bgColor: StringConstructor;
|
||||
divided: BooleanConstructor;
|
||||
title: {
|
||||
type: PropType<string>;
|
||||
default: string;
|
||||
};
|
||||
hideHeader: BooleanConstructor;
|
||||
hideTitle: BooleanConstructor;
|
||||
allowedHours: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
allowedMinutes: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
allowedSeconds: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
max: StringConstructor;
|
||||
min: StringConstructor;
|
||||
disabled: BooleanConstructor;
|
||||
format: {
|
||||
type: PropType<'ampm' | '24hr'>;
|
||||
default: string;
|
||||
};
|
||||
viewMode: {
|
||||
type: PropType<VTimePickerViewMode>;
|
||||
default: string;
|
||||
};
|
||||
period: {
|
||||
type: PropType<Period>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
modelValue: PropType<any>;
|
||||
readonly: BooleanConstructor;
|
||||
scrollable: BooleanConstructor;
|
||||
useSeconds: BooleanConstructor;
|
||||
variant: {
|
||||
type: PropType<Variant>;
|
||||
default: string;
|
||||
};
|
||||
}, import("vue").ExtractPropTypes<{
|
||||
theme: StringConstructor;
|
||||
class: PropType<import("../../composables/component.js").ClassValue>;
|
||||
style: {
|
||||
type: PropType<import("vue").StyleValue>;
|
||||
default: null;
|
||||
};
|
||||
border: (BooleanConstructor | NumberConstructor | StringConstructor)[];
|
||||
density: {
|
||||
type: PropType<import("../../composables/density.js").Density>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
elevation: {
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
validator: (value: string | number) => boolean;
|
||||
};
|
||||
rounded: {
|
||||
type: (BooleanConstructor | NumberConstructor | StringConstructor)[];
|
||||
default: undefined;
|
||||
};
|
||||
tile: BooleanConstructor;
|
||||
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)[];
|
||||
location: PropType<import("../../util/index.js").Anchor | null>;
|
||||
position: {
|
||||
type: PropType<"absolute" | "fixed" | "relative" | "static" | "sticky">;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
color: StringConstructor;
|
||||
bgColor: StringConstructor;
|
||||
divided: BooleanConstructor;
|
||||
title: {
|
||||
type: PropType<string>;
|
||||
default: string;
|
||||
};
|
||||
hideHeader: BooleanConstructor;
|
||||
hideTitle: BooleanConstructor;
|
||||
allowedHours: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
allowedMinutes: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
allowedSeconds: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
max: StringConstructor;
|
||||
min: StringConstructor;
|
||||
disabled: BooleanConstructor;
|
||||
format: {
|
||||
type: PropType<'ampm' | '24hr'>;
|
||||
default: string;
|
||||
};
|
||||
viewMode: {
|
||||
type: PropType<VTimePickerViewMode>;
|
||||
default: string;
|
||||
};
|
||||
period: {
|
||||
type: PropType<Period>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
};
|
||||
modelValue: PropType<any>;
|
||||
readonly: BooleanConstructor;
|
||||
scrollable: BooleanConstructor;
|
||||
useSeconds: BooleanConstructor;
|
||||
variant: {
|
||||
type: PropType<Variant>;
|
||||
default: string;
|
||||
};
|
||||
}>>;
|
||||
export type VTimePicker = InstanceType<typeof VTimePicker>;
|
||||
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
import { createElementVNode as _createElementVNode, mergeProps as _mergeProps, createVNode as _createVNode } from "vue";
|
||||
// Styles
|
||||
import "./VTimePicker.css";
|
||||
|
||||
// Components
|
||||
import { VTimePickerClock } from "./VTimePickerClock.js";
|
||||
import { VTimePickerControls } from "./VTimePickerControls.js";
|
||||
import { makeVPickerProps, VPicker } from "../../labs/VPicker/VPicker.js"; // Composables
|
||||
import { makeDensityProps, useDensity } from "../../composables/density.js";
|
||||
import { useLocale } from "../../composables/locale.js";
|
||||
import { useProxiedModel } from "../../composables/proxiedModel.js"; // Utilities
|
||||
import { computed, onMounted, ref, toRef, watch } from 'vue';
|
||||
import { makeTimeValidationProps, useTimeValidation } from "./useTimeValidation.js";
|
||||
import { convert12to24, convert24to12, pad } from "./util.js";
|
||||
import { genericComponent, omit, propsFactory, useRender } from "../../util/index.js"; // Types
|
||||
export const makeVTimePickerProps = propsFactory({
|
||||
disabled: Boolean,
|
||||
format: {
|
||||
type: String,
|
||||
default: 'ampm'
|
||||
},
|
||||
viewMode: {
|
||||
type: String,
|
||||
default: 'hour'
|
||||
},
|
||||
period: {
|
||||
type: String,
|
||||
default: 'am',
|
||||
validator: v => ['am', 'pm'].includes(v)
|
||||
},
|
||||
modelValue: null,
|
||||
readonly: Boolean,
|
||||
scrollable: Boolean,
|
||||
useSeconds: Boolean,
|
||||
variant: {
|
||||
type: String,
|
||||
default: 'dial'
|
||||
},
|
||||
...makeTimeValidationProps(),
|
||||
...omit(makeVPickerProps({
|
||||
title: '$vuetify.timePicker.title'
|
||||
}), ['landscape']),
|
||||
...makeDensityProps()
|
||||
}, 'VTimePicker');
|
||||
export const VTimePicker = genericComponent()({
|
||||
name: 'VTimePicker',
|
||||
props: makeVTimePickerProps(),
|
||||
emits: {
|
||||
'update:hour': val => true,
|
||||
'update:minute': val => true,
|
||||
'update:period': val => true,
|
||||
'update:second': val => true,
|
||||
'update:modelValue': val => true,
|
||||
'update:viewMode': val => true
|
||||
},
|
||||
setup(props, {
|
||||
emit,
|
||||
slots
|
||||
}) {
|
||||
const {
|
||||
t
|
||||
} = useLocale();
|
||||
const {
|
||||
densityClasses
|
||||
} = useDensity(props);
|
||||
const inputHour = ref(null);
|
||||
const inputMinute = ref(null);
|
||||
const inputSecond = ref(null);
|
||||
const lazyInputHour = ref(null);
|
||||
const lazyInputMinute = ref(null);
|
||||
const lazyInputSecond = ref(null);
|
||||
const period = useProxiedModel(props, 'period', 'am');
|
||||
const viewMode = useProxiedModel(props, 'viewMode', 'hour');
|
||||
const controlsRef = ref(null);
|
||||
const clockRef = ref(null);
|
||||
const isAmPm = computed(() => {
|
||||
return props.format === 'ampm';
|
||||
});
|
||||
const {
|
||||
isAllowedHour,
|
||||
isAllowedMinute,
|
||||
isAllowedSecond
|
||||
} = useTimeValidation(props);
|
||||
const shouldClear = toRef(() => {
|
||||
return props.modelValue !== null && inputHour.value === null && inputMinute.value === null && (!props.useSeconds || inputSecond.value === null);
|
||||
});
|
||||
function emitValue() {
|
||||
const value = genValue();
|
||||
if (value !== null && value !== props.modelValue) {
|
||||
emit('update:modelValue', value);
|
||||
}
|
||||
if (shouldClear.value) {
|
||||
emit('update:modelValue', null);
|
||||
}
|
||||
}
|
||||
watch(inputHour, emitValue);
|
||||
watch(inputMinute, emitValue);
|
||||
watch(inputSecond, emitValue);
|
||||
watch(period, (newPeriod, oldPeriod) => {
|
||||
if (inputHour.value == null || newPeriod === oldPeriod) return;
|
||||
if (newPeriod === 'pm' && inputHour.value < 12) {
|
||||
inputHour.value = inputHour.value + 12;
|
||||
} else if (newPeriod === 'am' && inputHour.value >= 12) {
|
||||
inputHour.value = inputHour.value - 12;
|
||||
}
|
||||
});
|
||||
watch(() => props.modelValue, val => setInputData(val));
|
||||
watch(() => props.useSeconds, (val, old) => {
|
||||
if (old && !val && viewMode.value === 'second') {
|
||||
viewMode.value = 'minute';
|
||||
}
|
||||
if (!val && inputSecond.value !== null) {
|
||||
inputSecond.value = null;
|
||||
}
|
||||
});
|
||||
onMounted(() => {
|
||||
setInputData(props.modelValue);
|
||||
});
|
||||
function genValue() {
|
||||
if (inputHour.value != null && inputMinute.value != null && (!props.useSeconds || inputSecond.value != null)) {
|
||||
return `${pad(inputHour.value)}:${pad(inputMinute.value)}` + (props.useSeconds ? `:${pad(inputSecond.value)}` : '');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function setInputData(value) {
|
||||
if (value == null || value === '') {
|
||||
inputHour.value = null;
|
||||
inputMinute.value = null;
|
||||
inputSecond.value = null;
|
||||
} else if (value instanceof Date) {
|
||||
inputHour.value = value.getHours();
|
||||
inputMinute.value = value.getMinutes();
|
||||
inputSecond.value = value.getSeconds();
|
||||
} else {
|
||||
const [hour,, minute,, second, period] = value.trim().toLowerCase().match(/^(\d+):(\d+)(:(\d+))?([ap]m)?$/) || new Array(6);
|
||||
inputHour.value = period ? convert12to24(parseInt(hour, 10), period) : parseInt(hour, 10);
|
||||
inputMinute.value = parseInt(minute, 10);
|
||||
inputSecond.value = parseInt(second || 0, 10);
|
||||
}
|
||||
period.value = inputHour.value == null || inputHour.value < 12 ? 'am' : 'pm';
|
||||
}
|
||||
function onInput(value) {
|
||||
if (viewMode.value === 'hour') {
|
||||
inputHour.value = isAmPm.value ? convert12to24(value, period.value) : value;
|
||||
} else if (viewMode.value === 'minute') {
|
||||
inputMinute.value = value;
|
||||
} else {
|
||||
inputSecond.value = value;
|
||||
}
|
||||
}
|
||||
function onChange(value) {
|
||||
switch (viewMode.value || 'hour') {
|
||||
case 'hour':
|
||||
emit('update:hour', value);
|
||||
break;
|
||||
case 'minute':
|
||||
emit('update:minute', value);
|
||||
break;
|
||||
case 'second':
|
||||
emit('update:second', value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const emitChange = inputHour.value !== null && inputMinute.value !== null && (props.useSeconds ? inputSecond.value !== null : true);
|
||||
if (viewMode.value === 'hour') {
|
||||
viewMode.value = 'minute';
|
||||
} else if (props.useSeconds && viewMode.value === 'minute') {
|
||||
viewMode.value = 'second';
|
||||
}
|
||||
if (inputHour.value === lazyInputHour.value && inputMinute.value === lazyInputMinute.value && (!props.useSeconds || inputSecond.value === lazyInputSecond.value)) return;
|
||||
const time = genValue();
|
||||
if (time === null) return;
|
||||
lazyInputHour.value = inputHour.value;
|
||||
lazyInputMinute.value = inputMinute.value;
|
||||
props.useSeconds && (lazyInputSecond.value = inputSecond.value);
|
||||
emitChange && emitValue();
|
||||
}
|
||||
useRender(() => {
|
||||
const pickerProps = omit(VPicker.filterProps(props), ['hideHeader']);
|
||||
const timePickerControlsProps = VTimePickerControls.filterProps(props);
|
||||
const timePickerClockProps = VTimePickerClock.filterProps(omit(props, ['format', 'modelValue', 'min', 'max']));
|
||||
const clockValidation = viewMode.value === 'hour' ? isAllowedHour.value : viewMode.value === 'minute' ? v => isAllowedMinute.value(inputHour.value, v) : v => isAllowedSecond.value(inputHour.value, inputMinute.value, v);
|
||||
return _createVNode(VPicker, _mergeProps(pickerProps, {
|
||||
"color": undefined,
|
||||
"class": ['v-time-picker', `v-time-picker--variant-${props.variant}`, props.class, densityClasses.value],
|
||||
"hideHeader": props.hideHeader && props.variant !== 'input',
|
||||
"style": props.style
|
||||
}), {
|
||||
title: () => slots.title?.() ?? _createElementVNode("div", {
|
||||
"class": "v-time-picker__title"
|
||||
}, [t(props.title)]),
|
||||
header: () => _createVNode(VTimePickerControls, _mergeProps(timePickerControlsProps, {
|
||||
"ampm": isAmPm.value,
|
||||
"hour": inputHour.value,
|
||||
"minute": inputMinute.value,
|
||||
"period": period.value,
|
||||
"second": inputSecond.value,
|
||||
"viewMode": viewMode.value,
|
||||
"inputHints": props.variant === 'input',
|
||||
"onUpdate:hour": val => inputHour.value = val,
|
||||
"onUpdate:minute": val => inputMinute.value = val,
|
||||
"onUpdate:second": val => inputSecond.value = val,
|
||||
"onUpdate:period": val => period.value = val,
|
||||
"onUpdate:viewMode": value => viewMode.value = value,
|
||||
"ref": controlsRef
|
||||
}), null),
|
||||
default: () => _createVNode(VTimePickerClock, _mergeProps(timePickerClockProps, {
|
||||
"allowedValues": clockValidation,
|
||||
"double": viewMode.value === 'hour' && !isAmPm.value,
|
||||
"format": viewMode.value === 'hour' ? isAmPm.value ? convert24to12 : val => val : val => pad(val, 2),
|
||||
"max": viewMode.value === 'hour' ? isAmPm.value && period.value === 'am' ? 11 : 23 : 59,
|
||||
"min": viewMode.value === 'hour' && isAmPm.value && period.value === 'pm' ? 12 : 0,
|
||||
"size": 20,
|
||||
"step": viewMode.value === 'hour' ? 1 : 5,
|
||||
"modelValue": viewMode.value === 'hour' ? inputHour.value : viewMode.value === 'minute' ? inputMinute.value : inputSecond.value,
|
||||
"onChange": onChange,
|
||||
"onInput": onInput,
|
||||
"ref": clockRef
|
||||
}), null),
|
||||
actions: slots.actions
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=VTimePicker.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+27
@@ -0,0 +1,27 @@
|
||||
@use '../../styles/tools'
|
||||
@use '../../styles/settings'
|
||||
@use './variables' as *
|
||||
|
||||
@include tools.layer('components')
|
||||
.v-time-picker
|
||||
&.v-picker
|
||||
min-width: $time-picker-width
|
||||
|
||||
.v-picker__body,
|
||||
&-controls__field-label,
|
||||
.v-field
|
||||
transition-duration: .25s
|
||||
transition-timing-function: settings.$standard-easing
|
||||
transition-property: transform, max-height, opacity, font-size
|
||||
|
||||
@media (prefers-reduced-motion: reduce)
|
||||
transition: none
|
||||
|
||||
.v-picker__body
|
||||
transition-behavior: allow-discrete
|
||||
max-height: calc-size(max-content, size)
|
||||
|
||||
&--variant-input
|
||||
.v-picker__body
|
||||
transform: scale(0)
|
||||
max-height: 0
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
@layer vuetify-components {
|
||||
.v-time-picker-clock {
|
||||
background: rgb(var(--v-theme-background));
|
||||
color: rgb(var(--v-theme-on-background));
|
||||
}
|
||||
.v-time-picker-clock:after {
|
||||
color: rgb(var(--v-theme-primary));
|
||||
}
|
||||
.v-time-picker-clock .v-time-picker-clock__item--active {
|
||||
background-color: rgb(var(--v-theme-surface-variant));
|
||||
color: rgb(var(--v-theme-on-surface-variant));
|
||||
}
|
||||
.v-time-picker-clock {
|
||||
margin: 24px;
|
||||
background: rgb(var(--v-theme-surface-light));
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
transition: none;
|
||||
user-select: none;
|
||||
max-width: 256px;
|
||||
aspect-ratio: 1;
|
||||
flex: 100%;
|
||||
}
|
||||
.v-time-picker-clock__container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-basis: 290px;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
}
|
||||
.v-time-picker-clock__hand {
|
||||
background-color: currentColor;
|
||||
height: calc(50% - 4px);
|
||||
width: 2px;
|
||||
bottom: 50%;
|
||||
left: calc(50% - 1px);
|
||||
transform-origin: center bottom;
|
||||
position: absolute;
|
||||
will-change: transform;
|
||||
z-index: 1;
|
||||
}
|
||||
.v-time-picker-clock__hand:before {
|
||||
background: transparent;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-color: currentColor;
|
||||
border-radius: 100%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.v-time-picker-clock__hand:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
border-radius: 100%;
|
||||
background-color: currentColor;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.v-time-picker-clock__hand--inner:after {
|
||||
height: 14px;
|
||||
}
|
||||
.v-time-picker-clock--readonly {
|
||||
pointer-events: none;
|
||||
}
|
||||
.v-time-picker-clock .v-time-picker-clock__item--disabled {
|
||||
opacity: var(--v-disabled-opacity);
|
||||
}
|
||||
.v-picker--full-width .v-time-picker-clock__container {
|
||||
max-width: 290px;
|
||||
}
|
||||
.v-time-picker-clock__inner {
|
||||
position: absolute;
|
||||
bottom: 27px;
|
||||
left: 27px;
|
||||
right: 27px;
|
||||
top: 27px;
|
||||
}
|
||||
.v-time-picker-clock__item {
|
||||
align-items: center;
|
||||
border-radius: 100%;
|
||||
cursor: default;
|
||||
display: flex;
|
||||
font-size: 16px;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 40px;
|
||||
user-select: none;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.v-time-picker-clock__item > span {
|
||||
z-index: 1;
|
||||
}
|
||||
.v-time-picker-clock__item:before, .v-time-picker-clock__item:after {
|
||||
content: "";
|
||||
border-radius: 100%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.v-time-picker-clock__item:after, .v-time-picker-clock__item:before {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
}
|
||||
.v-time-picker-clock__item--active {
|
||||
cursor: default;
|
||||
z-index: 2;
|
||||
}
|
||||
.v-time-picker-clock__item--disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
.v-picker--landscape .v-time-picker-clock__container {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
@layer vuetify-final.trumps {
|
||||
@media (forced-colors: active) {
|
||||
.v-time-picker-clock__hand {
|
||||
background-color: highlight;
|
||||
}
|
||||
.v-time-picker-clock__hand:before {
|
||||
border-color: highlight;
|
||||
}
|
||||
.v-time-picker-clock__hand:after {
|
||||
background-color: highlight;
|
||||
}
|
||||
.v-time-picker-clock__item--active {
|
||||
outline: 2px solid highlight;
|
||||
}
|
||||
}
|
||||
}
|
||||
+318
@@ -0,0 +1,318 @@
|
||||
|
||||
import type { PropType } from 'vue';
|
||||
export declare const makeVTimePickerClockProps: <Defaults extends {
|
||||
allowedValues?: unknown;
|
||||
ampm?: unknown;
|
||||
color?: unknown;
|
||||
disabled?: unknown;
|
||||
displayedValue?: unknown;
|
||||
double?: unknown;
|
||||
format?: unknown;
|
||||
max?: unknown;
|
||||
min?: unknown;
|
||||
scrollable?: unknown;
|
||||
readonly?: unknown;
|
||||
rotate?: unknown;
|
||||
step?: unknown;
|
||||
modelValue?: unknown;
|
||||
} = {}>(defaults?: Defaults | undefined) => {
|
||||
allowedValues: unknown extends Defaults["allowedValues"] ? PropType<(value: number) => boolean> : {
|
||||
type: PropType<unknown extends Defaults["allowedValues"] ? (value: number) => boolean : ((value: number) => boolean) | Defaults["allowedValues"]>;
|
||||
default: unknown extends Defaults["allowedValues"] ? (value: number) => boolean : ((value: number) => boolean) | Defaults["allowedValues"];
|
||||
};
|
||||
ampm: unknown extends Defaults["ampm"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["ampm"] ? boolean : boolean | Defaults["ampm"]>;
|
||||
default: unknown extends Defaults["ampm"] ? boolean : boolean | Defaults["ampm"];
|
||||
};
|
||||
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"];
|
||||
};
|
||||
disabled: unknown extends Defaults["disabled"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["disabled"] ? boolean : boolean | Defaults["disabled"]>;
|
||||
default: unknown extends Defaults["disabled"] ? boolean : boolean | Defaults["disabled"];
|
||||
};
|
||||
displayedValue: unknown extends Defaults["displayedValue"] ? null : {
|
||||
type: PropType<unknown extends Defaults["displayedValue"] ? any : any>;
|
||||
default: unknown extends Defaults["displayedValue"] ? any : any;
|
||||
};
|
||||
double: unknown extends Defaults["double"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["double"] ? boolean : boolean | Defaults["double"]>;
|
||||
default: unknown extends Defaults["double"] ? boolean : boolean | Defaults["double"];
|
||||
};
|
||||
format: unknown extends Defaults["format"] ? {
|
||||
type: FunctionConstructor;
|
||||
default: (val: string | number) => string | number;
|
||||
} : Omit<{
|
||||
type: FunctionConstructor;
|
||||
default: (val: string | number) => string | number;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["format"] ? Function : Function | Defaults["format"]>;
|
||||
default: unknown extends Defaults["format"] ? Function : Function | Defaults["format"];
|
||||
};
|
||||
max: unknown extends Defaults["max"] ? {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
} : Omit<{
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["max"] ? number : number | Defaults["max"]>;
|
||||
default: unknown extends Defaults["max"] ? number : number | Defaults["max"];
|
||||
};
|
||||
min: unknown extends Defaults["min"] ? {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
} : Omit<{
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["min"] ? number : number | Defaults["min"]>;
|
||||
default: unknown extends Defaults["min"] ? number : number | Defaults["min"];
|
||||
};
|
||||
scrollable: unknown extends Defaults["scrollable"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["scrollable"] ? boolean : boolean | Defaults["scrollable"]>;
|
||||
default: unknown extends Defaults["scrollable"] ? boolean : boolean | Defaults["scrollable"];
|
||||
};
|
||||
readonly: unknown extends Defaults["readonly"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["readonly"] ? boolean : boolean | Defaults["readonly"]>;
|
||||
default: unknown extends Defaults["readonly"] ? boolean : boolean | Defaults["readonly"];
|
||||
};
|
||||
rotate: unknown extends Defaults["rotate"] ? {
|
||||
type: NumberConstructor;
|
||||
default: number;
|
||||
} : Omit<{
|
||||
type: NumberConstructor;
|
||||
default: number;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["rotate"] ? number : number | Defaults["rotate"]>;
|
||||
default: unknown extends Defaults["rotate"] ? number : number | Defaults["rotate"];
|
||||
};
|
||||
step: unknown extends Defaults["step"] ? {
|
||||
type: NumberConstructor;
|
||||
default: number;
|
||||
} : Omit<{
|
||||
type: NumberConstructor;
|
||||
default: number;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["step"] ? number : number | Defaults["step"]>;
|
||||
default: unknown extends Defaults["step"] ? number : number | Defaults["step"];
|
||||
};
|
||||
modelValue: unknown extends Defaults["modelValue"] ? {
|
||||
type: NumberConstructor;
|
||||
} : Omit<{
|
||||
type: NumberConstructor;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["modelValue"] ? number : number | Defaults["modelValue"]>;
|
||||
default: unknown extends Defaults["modelValue"] ? number : number | Defaults["modelValue"];
|
||||
};
|
||||
};
|
||||
export declare const VTimePickerClock: {
|
||||
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<{
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
double: boolean;
|
||||
format: Function;
|
||||
max: number;
|
||||
min: number;
|
||||
scrollable: boolean;
|
||||
readonly: boolean;
|
||||
rotate: number;
|
||||
step: number;
|
||||
} & {
|
||||
allowedValues?: ((value: number) => boolean) | undefined;
|
||||
color?: string | undefined;
|
||||
displayedValue?: any;
|
||||
modelValue?: number | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
onChange?: ((val: number) => any) | undefined;
|
||||
onInput?: ((val: number) => any) | undefined;
|
||||
}, void, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
change: (val: number) => true;
|
||||
input: (val: number) => true;
|
||||
}, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, {
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
double: boolean;
|
||||
format: Function;
|
||||
scrollable: boolean;
|
||||
readonly: boolean;
|
||||
rotate: number;
|
||||
step: number;
|
||||
}, true, {}, import("vue").SlotsType<Partial<{
|
||||
default: () => 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: {};
|
||||
}, {
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
double: boolean;
|
||||
format: Function;
|
||||
max: number;
|
||||
min: number;
|
||||
scrollable: boolean;
|
||||
readonly: boolean;
|
||||
rotate: number;
|
||||
step: number;
|
||||
} & {
|
||||
allowedValues?: ((value: number) => boolean) | undefined;
|
||||
color?: string | undefined;
|
||||
displayedValue?: any;
|
||||
modelValue?: number | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
onChange?: ((val: number) => any) | undefined;
|
||||
onInput?: ((val: number) => any) | undefined;
|
||||
}, {}, {}, {}, {}, {
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
double: boolean;
|
||||
format: Function;
|
||||
scrollable: boolean;
|
||||
readonly: boolean;
|
||||
rotate: number;
|
||||
step: number;
|
||||
}>;
|
||||
__isFragment?: never;
|
||||
__isTeleport?: never;
|
||||
__isSuspense?: never;
|
||||
} & import("vue").ComponentOptionsBase<{
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
double: boolean;
|
||||
format: Function;
|
||||
max: number;
|
||||
min: number;
|
||||
scrollable: boolean;
|
||||
readonly: boolean;
|
||||
rotate: number;
|
||||
step: number;
|
||||
} & {
|
||||
allowedValues?: ((value: number) => boolean) | undefined;
|
||||
color?: string | undefined;
|
||||
displayedValue?: any;
|
||||
modelValue?: number | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
onChange?: ((val: number) => any) | undefined;
|
||||
onInput?: ((val: number) => any) | undefined;
|
||||
}, void, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
change: (val: number) => true;
|
||||
input: (val: number) => true;
|
||||
}, string, {
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
double: boolean;
|
||||
format: Function;
|
||||
scrollable: boolean;
|
||||
readonly: boolean;
|
||||
rotate: number;
|
||||
step: number;
|
||||
}, {}, string, import("vue").SlotsType<Partial<{
|
||||
default: () => 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<{
|
||||
allowedValues: PropType<(value: number) => boolean>;
|
||||
ampm: BooleanConstructor;
|
||||
color: StringConstructor;
|
||||
disabled: BooleanConstructor;
|
||||
displayedValue: null;
|
||||
double: BooleanConstructor;
|
||||
format: {
|
||||
type: FunctionConstructor;
|
||||
default: (val: string | number) => string | number;
|
||||
};
|
||||
max: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
min: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
scrollable: BooleanConstructor;
|
||||
readonly: BooleanConstructor;
|
||||
rotate: {
|
||||
type: NumberConstructor;
|
||||
default: number;
|
||||
};
|
||||
step: {
|
||||
type: NumberConstructor;
|
||||
default: number;
|
||||
};
|
||||
modelValue: {
|
||||
type: NumberConstructor;
|
||||
};
|
||||
}, import("vue").ExtractPropTypes<{
|
||||
allowedValues: PropType<(value: number) => boolean>;
|
||||
ampm: BooleanConstructor;
|
||||
color: StringConstructor;
|
||||
disabled: BooleanConstructor;
|
||||
displayedValue: null;
|
||||
double: BooleanConstructor;
|
||||
format: {
|
||||
type: FunctionConstructor;
|
||||
default: (val: string | number) => string | number;
|
||||
};
|
||||
max: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
min: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
scrollable: BooleanConstructor;
|
||||
readonly: BooleanConstructor;
|
||||
rotate: {
|
||||
type: NumberConstructor;
|
||||
default: number;
|
||||
};
|
||||
step: {
|
||||
type: NumberConstructor;
|
||||
default: number;
|
||||
};
|
||||
modelValue: {
|
||||
type: NumberConstructor;
|
||||
};
|
||||
}>>;
|
||||
export type VTimePickerClock = InstanceType<typeof VTimePickerClock>;
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
import { normalizeClass as _normalizeClass, normalizeStyle as _normalizeStyle, createElementVNode as _createElementVNode } from "vue";
|
||||
// Styles
|
||||
import "./VTimePickerClock.css";
|
||||
|
||||
// Composables
|
||||
import { useBackgroundColor, useTextColor } from "../../composables/color.js"; // Utilities
|
||||
import { computed, onScopeDispose, ref, watch } from 'vue';
|
||||
import { debounce, genericComponent, IN_BROWSER, propsFactory, useRender } from "../../util/index.js"; // Types
|
||||
export const makeVTimePickerClockProps = propsFactory({
|
||||
allowedValues: Function,
|
||||
ampm: Boolean,
|
||||
color: String,
|
||||
disabled: Boolean,
|
||||
displayedValue: null,
|
||||
double: Boolean,
|
||||
format: {
|
||||
type: Function,
|
||||
default: val => val
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
scrollable: Boolean,
|
||||
readonly: Boolean,
|
||||
rotate: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
modelValue: {
|
||||
type: Number
|
||||
}
|
||||
}, 'VTimePickerClock');
|
||||
export const VTimePickerClock = genericComponent()({
|
||||
name: 'VTimePickerClock',
|
||||
props: makeVTimePickerClockProps(),
|
||||
emits: {
|
||||
change: val => true,
|
||||
input: val => true
|
||||
},
|
||||
setup(props, {
|
||||
emit
|
||||
}) {
|
||||
const clockRef = ref(null);
|
||||
const innerClockRef = ref(null);
|
||||
const inputValue = ref(undefined);
|
||||
const isDragging = ref(false);
|
||||
const valueOnMouseDown = ref(null);
|
||||
const valueOnMouseUp = ref(null);
|
||||
const emitChangeDebounced = debounce(value => emit('change', value), 750);
|
||||
const {
|
||||
textColorClasses,
|
||||
textColorStyles
|
||||
} = useTextColor(() => props.color);
|
||||
const {
|
||||
backgroundColorClasses,
|
||||
backgroundColorStyles
|
||||
} = useBackgroundColor(() => props.color);
|
||||
const count = computed(() => props.max - props.min + 1);
|
||||
const roundCount = computed(() => props.double ? count.value / 2 : count.value);
|
||||
const degreesPerUnit = computed(() => 360 / roundCount.value);
|
||||
const degrees = computed(() => degreesPerUnit.value * Math.PI / 180);
|
||||
const displayedValue = computed(() => props.modelValue == null ? props.min : props.modelValue);
|
||||
const innerRadiusScale = computed(() => 0.62);
|
||||
const genChildren = computed(() => {
|
||||
const children = [];
|
||||
for (let value = props.min; value <= props.max; value = value + props.step) {
|
||||
children.push(value);
|
||||
}
|
||||
return children;
|
||||
});
|
||||
watch(() => props.modelValue, val => {
|
||||
inputValue.value = val;
|
||||
});
|
||||
function update(value) {
|
||||
if (inputValue.value !== value) {
|
||||
inputValue.value = value;
|
||||
}
|
||||
emit('input', value);
|
||||
}
|
||||
function isAllowed(value) {
|
||||
return !props.allowedValues || props.allowedValues(value);
|
||||
}
|
||||
function wheel(e) {
|
||||
if (!props.scrollable || props.disabled) return;
|
||||
e.preventDefault();
|
||||
const delta = Math.sign(-e.deltaY || 1);
|
||||
let value = displayedValue.value;
|
||||
do {
|
||||
value = value + delta;
|
||||
value = (value - props.min + count.value) % count.value + props.min;
|
||||
} while (!isAllowed(value) && value !== displayedValue.value);
|
||||
if (value !== props.displayedValue) {
|
||||
update(value);
|
||||
}
|
||||
emitChangeDebounced(value);
|
||||
}
|
||||
function isInner(value) {
|
||||
return props.double && value - props.min >= roundCount.value;
|
||||
}
|
||||
function handScale(value) {
|
||||
return isInner(value) ? innerRadiusScale.value : 1;
|
||||
}
|
||||
function getPosition(value) {
|
||||
const rotateRadians = props.rotate * Math.PI / 180;
|
||||
return {
|
||||
x: Math.sin((value - props.min) * degrees.value + rotateRadians) * handScale(value),
|
||||
y: -Math.cos((value - props.min) * degrees.value + rotateRadians) * handScale(value)
|
||||
};
|
||||
}
|
||||
function angleToValue(angle, insideClick) {
|
||||
const value = (Math.round(angle / degreesPerUnit.value) + (insideClick ? roundCount.value : 0)) % count.value + props.min;
|
||||
|
||||
// Necessary to fix edge case when selecting left part of the value(s) at 12 o'clock
|
||||
if (angle < 360 - degreesPerUnit.value / 2) return value;
|
||||
return insideClick ? props.max - roundCount.value + 1 : props.min;
|
||||
}
|
||||
function getTransform(i) {
|
||||
const {
|
||||
x,
|
||||
y
|
||||
} = getPosition(i);
|
||||
return {
|
||||
left: `${Math.round(50 + x * 50)}%`,
|
||||
top: `${Math.round(50 + y * 50)}%`
|
||||
};
|
||||
}
|
||||
function euclidean(p0, p1) {
|
||||
const dx = p1.x - p0.x;
|
||||
const dy = p1.y - p0.y;
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
function angle(center, p1) {
|
||||
const value = 2 * Math.atan2(p1.y - center.y - euclidean(center, p1), p1.x - center.x);
|
||||
return Math.abs(value * 180 / Math.PI);
|
||||
}
|
||||
function setMouseDownValue(value) {
|
||||
if (valueOnMouseDown.value === null) {
|
||||
valueOnMouseDown.value = value;
|
||||
}
|
||||
valueOnMouseUp.value = value;
|
||||
update(value);
|
||||
}
|
||||
function onDragMove(e) {
|
||||
e.preventDefault();
|
||||
if (!isDragging.value && e.type !== 'click' || !clockRef.value) return;
|
||||
const {
|
||||
width,
|
||||
top,
|
||||
left
|
||||
} = clockRef.value?.getBoundingClientRect();
|
||||
const {
|
||||
width: innerWidth
|
||||
} = innerClockRef.value?.getBoundingClientRect() ?? {
|
||||
width: 0
|
||||
};
|
||||
const {
|
||||
clientX,
|
||||
clientY
|
||||
} = 'touches' in e ? e.touches[0] : e;
|
||||
const center = {
|
||||
x: width / 2,
|
||||
y: -width / 2
|
||||
};
|
||||
const coords = {
|
||||
x: clientX - left,
|
||||
y: top - clientY
|
||||
};
|
||||
const handAngle = Math.round(angle(center, coords) - props.rotate + 360) % 360;
|
||||
const insideClick = props.double && euclidean(center, coords) < (innerWidth + innerWidth * innerRadiusScale.value) / 4;
|
||||
const checksCount = Math.ceil(15 / degreesPerUnit.value);
|
||||
let value;
|
||||
for (let i = 0; i < checksCount; i++) {
|
||||
value = angleToValue(handAngle + i * degreesPerUnit.value, insideClick);
|
||||
if (isAllowed(value)) return setMouseDownValue(value);
|
||||
value = angleToValue(handAngle - i * degreesPerUnit.value, insideClick);
|
||||
if (isAllowed(value)) return setMouseDownValue(value);
|
||||
}
|
||||
}
|
||||
function onMouseDown(e) {
|
||||
if (props.disabled) return;
|
||||
e.preventDefault();
|
||||
window.addEventListener('mousemove', onDragMove);
|
||||
window.addEventListener('touchmove', onDragMove);
|
||||
window.addEventListener('mouseup', onMouseUp);
|
||||
window.addEventListener('touchend', onMouseUp);
|
||||
valueOnMouseDown.value = null;
|
||||
valueOnMouseUp.value = null;
|
||||
isDragging.value = true;
|
||||
onDragMove(e);
|
||||
}
|
||||
function onMouseUp(e) {
|
||||
e.stopPropagation();
|
||||
removeListeners();
|
||||
isDragging.value = false;
|
||||
if (valueOnMouseUp.value !== null && isAllowed(valueOnMouseUp.value)) {
|
||||
emit('change', valueOnMouseUp.value);
|
||||
}
|
||||
}
|
||||
function removeListeners() {
|
||||
if (!IN_BROWSER) return;
|
||||
window.removeEventListener('mousemove', onDragMove);
|
||||
window.removeEventListener('touchmove', onDragMove);
|
||||
window.removeEventListener('mouseup', onMouseUp);
|
||||
window.removeEventListener('touchend', onMouseUp);
|
||||
}
|
||||
onScopeDispose(removeListeners);
|
||||
useRender(() => {
|
||||
return _createElementVNode("div", {
|
||||
"class": _normalizeClass([{
|
||||
'v-time-picker-clock': true,
|
||||
'v-time-picker-clock--indeterminate': props.modelValue == null,
|
||||
'v-time-picker-clock--readonly': props.readonly
|
||||
}]),
|
||||
"onMousedown": onMouseDown,
|
||||
"onTouchstart": onMouseDown,
|
||||
"onWheel": wheel,
|
||||
"ref": clockRef
|
||||
}, [_createElementVNode("div", {
|
||||
"class": "v-time-picker-clock__inner",
|
||||
"ref": innerClockRef
|
||||
}, [_createElementVNode("div", {
|
||||
"class": _normalizeClass([{
|
||||
'v-time-picker-clock__hand': true,
|
||||
'v-time-picker-clock__hand--inner': isInner(props.modelValue)
|
||||
}, textColorClasses.value]),
|
||||
"style": _normalizeStyle([{
|
||||
transform: `rotate(${props.rotate + degreesPerUnit.value * (displayedValue.value - props.min)}deg) scaleY(${handScale(displayedValue.value)})`
|
||||
}, textColorStyles.value])
|
||||
}, null), genChildren.value.map(value => {
|
||||
const isActive = value === displayedValue.value;
|
||||
return _createElementVNode("div", {
|
||||
"class": _normalizeClass([{
|
||||
'v-time-picker-clock__item': true,
|
||||
'v-time-picker-clock__item--active': isActive,
|
||||
'v-time-picker-clock__item--disabled': props.disabled || !isAllowed(value)
|
||||
}, isActive && backgroundColorClasses.value]),
|
||||
"style": _normalizeStyle([getTransform(value), isActive && backgroundColorStyles.value])
|
||||
}, [_createElementVNode("span", null, [props.format(value)])]);
|
||||
})])]);
|
||||
});
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=VTimePickerClock.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+145
@@ -0,0 +1,145 @@
|
||||
@use '../../styles/tools'
|
||||
@use './variables' as *
|
||||
|
||||
@include tools.layer('components')
|
||||
// Theme
|
||||
.v-time-picker-clock
|
||||
background: rgb(var(--v-theme-background))
|
||||
color: rgb(var(--v-theme-on-background))
|
||||
|
||||
&:after
|
||||
color: rgb(var(--v-theme-primary))
|
||||
|
||||
.v-time-picker-clock__item--active
|
||||
background-color: rgb(var(--v-theme-surface-variant))
|
||||
color: rgb(var(--v-theme-on-surface-variant))
|
||||
|
||||
.v-time-picker-clock
|
||||
margin: $time-picker-padding
|
||||
background: rgb(var(--v-theme-surface-light))
|
||||
border-radius: 50%
|
||||
position: relative
|
||||
transition: none
|
||||
user-select: none
|
||||
max-width: 256px
|
||||
aspect-ratio: 1
|
||||
flex: 100%
|
||||
|
||||
&__container
|
||||
display: flex
|
||||
flex-direction: column
|
||||
flex-basis: 290px
|
||||
justify-content: center
|
||||
padding: $time-picker-clock-padding
|
||||
|
||||
&__hand
|
||||
background-color: currentColor
|
||||
height: $time-picker-clock-hand-height
|
||||
width: $time-picker-clock-hand-width
|
||||
bottom: 50%
|
||||
left: $time-picker-clock-hand-left
|
||||
transform-origin: center bottom
|
||||
position: absolute
|
||||
will-change: transform
|
||||
z-index: 1
|
||||
|
||||
&:before
|
||||
background: transparent
|
||||
border-width: $time-picker-clock-end-border-width
|
||||
border-style: $time-picker-clock-end-border-style
|
||||
border-color: $time-picker-clock-end-border-color
|
||||
border-radius: 100%
|
||||
width: $time-picker-clock-end-size
|
||||
height: $time-picker-clock-end-size
|
||||
content: ''
|
||||
position: absolute
|
||||
top: $time-picker-clock-end-top
|
||||
left: 50%
|
||||
transform: translate(-50%, -50%)
|
||||
|
||||
&:after
|
||||
content: ''
|
||||
position: absolute
|
||||
height: $time-picker-clock-center-size
|
||||
width: $time-picker-clock-center-size
|
||||
top: 100%
|
||||
left: 50%
|
||||
border-radius: 100%
|
||||
background-color: currentColor
|
||||
transform: translate(-50%, -50%)
|
||||
|
||||
&--inner:after
|
||||
height: $time-picker-clock-inner-hand-height
|
||||
|
||||
&--readonly
|
||||
pointer-events: none
|
||||
|
||||
.v-time-picker-clock__item--disabled
|
||||
opacity: var(--v-disabled-opacity)
|
||||
|
||||
.v-picker--full-width
|
||||
.v-time-picker-clock__container
|
||||
max-width: $time-picker-clock-max-width
|
||||
|
||||
.v-time-picker-clock__inner
|
||||
position: absolute
|
||||
bottom: $time-picker-clock-inner-offset
|
||||
left: $time-picker-clock-inner-offset
|
||||
right: $time-picker-clock-inner-offset
|
||||
top: $time-picker-clock-inner-offset
|
||||
|
||||
.v-time-picker-clock__item
|
||||
align-items: center
|
||||
border-radius: 100%
|
||||
cursor: default
|
||||
display: flex
|
||||
font-size: $time-picker-number-font-size
|
||||
justify-content: center
|
||||
height: $time-picker-indicator-size
|
||||
position: absolute
|
||||
text-align: center
|
||||
width: $time-picker-indicator-size
|
||||
user-select: none
|
||||
transform: translate(-50%, -50%)
|
||||
|
||||
> span
|
||||
z-index: 1
|
||||
|
||||
&:before, &:after
|
||||
content: ''
|
||||
border-radius: 100%
|
||||
position: absolute
|
||||
top: 50%
|
||||
left: 50%
|
||||
height: 14px
|
||||
width: 14px
|
||||
transform: translate(-50%, -50%)
|
||||
|
||||
&:after, &:before
|
||||
height: $time-picker-indicator-size
|
||||
width: $time-picker-indicator-size
|
||||
|
||||
&--active
|
||||
cursor: default
|
||||
z-index: 2
|
||||
|
||||
&--disabled
|
||||
pointer-events: none
|
||||
|
||||
.v-picker--landscape
|
||||
.v-time-picker-clock
|
||||
&__container
|
||||
flex-direction: row
|
||||
|
||||
@include tools.layer('trumps')
|
||||
@media (forced-colors: active)
|
||||
.v-time-picker-clock
|
||||
&__hand
|
||||
background-color: highlight
|
||||
&:before
|
||||
border-color: highlight
|
||||
&:after
|
||||
background-color: highlight
|
||||
|
||||
&__item--active
|
||||
outline: 2px solid highlight
|
||||
+257
@@ -0,0 +1,257 @@
|
||||
@layer vuetify-components {
|
||||
.v-time-picker-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.875rem;
|
||||
margin-inline: 24px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.v-time-picker-controls__text {
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
.v-time-picker-controls__time {
|
||||
display: flex;
|
||||
white-space: nowrap;
|
||||
direction: ltr;
|
||||
justify-content: center;
|
||||
align-items: start;
|
||||
}
|
||||
.v-time-picker-controls__time__separator {
|
||||
width: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
.v-time-picker--density-compact .v-time-picker-controls__time__separator {
|
||||
font-weight: bold;
|
||||
}
|
||||
.v-time-picker--density-default .v-time-picker-controls__time__separator {
|
||||
font-size: 56px;
|
||||
line-height: 74px;
|
||||
}
|
||||
.v-time-picker--variant-input .v-time-picker--density-default .v-time-picker-controls__time__separator {
|
||||
line-height: 64px;
|
||||
}
|
||||
.v-time-picker-controls__time--with-seconds .v-time-picker--density-default .v-time-picker-controls__time__separator {
|
||||
height: 80px;
|
||||
font-size: 56px;
|
||||
}
|
||||
.v-time-picker--density-comfortable .v-time-picker-controls__time__separator {
|
||||
font-size: 40px;
|
||||
line-height: 58px;
|
||||
}
|
||||
.v-time-picker--variant-input .v-time-picker--density-comfortable .v-time-picker-controls__time__separator {
|
||||
line-height: 48px;
|
||||
}
|
||||
.v-time-picker-controls__time--with-seconds .v-time-picker--density-comfortable .v-time-picker-controls__time__separator {
|
||||
height: 64px;
|
||||
font-size: 40px;
|
||||
}
|
||||
.v-time-picker--density-compact .v-time-picker-controls__time__separator {
|
||||
font-size: 32px;
|
||||
line-height: 50px;
|
||||
}
|
||||
.v-time-picker--variant-input .v-time-picker--density-compact .v-time-picker-controls__time__separator {
|
||||
line-height: 40px;
|
||||
}
|
||||
.v-time-picker-controls__time--with-seconds .v-time-picker--density-compact .v-time-picker-controls__time__separator {
|
||||
height: 56px;
|
||||
font-size: 32px;
|
||||
}
|
||||
.v-time-picker-controls__time__field {
|
||||
width: 96px;
|
||||
}
|
||||
.v-time-picker-controls__time__field .v-field {
|
||||
width: 96px;
|
||||
background-color: rgb(var(--v-theme-surface-light));
|
||||
color: inherit;
|
||||
transition: color 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.v-time-picker-controls__time__field .v-field > .v-field__overlay {
|
||||
opacity: 0.04;
|
||||
}
|
||||
.v-time-picker-controls__time__field--active .v-field > .v-field__overlay {
|
||||
opacity: calc((0.04 + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier));
|
||||
}
|
||||
.v-time-picker--variant-input .v-time-picker-controls__time__field {
|
||||
width: 96px;
|
||||
}
|
||||
.v-time-picker--variant-input .v-time-picker-controls__time__field .v-field {
|
||||
width: 96px;
|
||||
}
|
||||
.v-time-picker-controls__time--with-seconds .v-time-picker-controls__time__field {
|
||||
width: 64px;
|
||||
}
|
||||
.v-time-picker--variant-input .v-time-picker-controls__time--with-seconds .v-time-picker-controls__time__field {
|
||||
width: 64px;
|
||||
}
|
||||
.v-time-picker-controls__time__field .v-field__input {
|
||||
padding: 0;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
align-self: center;
|
||||
}
|
||||
.v-time-picker-controls__time__field .v-field__input:focus::placeholder {
|
||||
opacity: 0;
|
||||
}
|
||||
.v-time-picker-controls__time__field.v-input > .v-input__details {
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.0333333333em;
|
||||
padding-inline: 0;
|
||||
white-space: normal;
|
||||
}
|
||||
.v-time-picker-controls__time__field.v-input > .v-input__details > .v-messages {
|
||||
opacity: 1;
|
||||
}
|
||||
.v-time-picker-controls__time__field.v-input--error .v-field__input {
|
||||
color: rgb(var(--v-theme-error));
|
||||
}
|
||||
.v-time-picker-controls__ampm {
|
||||
margin-left: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.v-time-picker-controls__ampm--readonly {
|
||||
pointer-events: none;
|
||||
}
|
||||
.v-time-picker-controls__ampm--readonly .v-picker__title__btn.v-picker__title__btn--active {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.v-time-picker-controls__ampm__btn.v-btn {
|
||||
min-width: 52px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
.v-time-picker-controls__ampm__btn.v-btn.v-time-picker-controls__ampm__am {
|
||||
border-radius: 4px 4px 0 0;
|
||||
border: 1px solid;
|
||||
}
|
||||
.v-time-picker-controls__ampm__btn.v-btn.v-time-picker-controls__ampm__pm {
|
||||
border-radius: 0 0 4px 4px;
|
||||
border: 1px solid;
|
||||
border-top: none;
|
||||
}
|
||||
.v-time-picker-controls__ampm__btn.v-btn__active {
|
||||
background: rgb(var(--v-theme-primary));
|
||||
}
|
||||
.v-time-picker--density-default .v-time-picker-controls__time__field .v-input__control {
|
||||
height: 80px;
|
||||
}
|
||||
.v-time-picker--density-default .v-time-picker-controls__time__field .v-input__control .v-field {
|
||||
font-size: 56px;
|
||||
}
|
||||
.v-time-picker--density-default .v-time-picker-controls__time__field .v-input__control .v-field .v-field__input {
|
||||
min-height: 80px;
|
||||
}
|
||||
.v-time-picker--density-default.v-time-picker--variant-input .v-time-picker-controls__time__field .v-input__control {
|
||||
height: 72px;
|
||||
}
|
||||
.v-time-picker--density-default.v-time-picker--variant-input .v-time-picker-controls__time__field .v-input__control .v-field {
|
||||
font-size: 44px;
|
||||
}
|
||||
.v-time-picker--density-default.v-time-picker--variant-input .v-time-picker-controls__time__field .v-input__control .v-field .v-field__input {
|
||||
min-height: 72px;
|
||||
}
|
||||
.v-time-picker--density-default .v-time-picker-controls__time--with-seconds .v-time-picker-controls__time__field .v-field {
|
||||
font-size: 40px;
|
||||
}
|
||||
.v-time-picker--density-default .v-time-picker-controls__ampm__btn.v-btn {
|
||||
font-size: 18px;
|
||||
height: 40px;
|
||||
}
|
||||
.v-time-picker--density-default.v-time-picker--variant-input .v-time-picker-controls__ampm__btn.v-btn {
|
||||
height: 36px;
|
||||
}
|
||||
.v-time-picker--density-comfortable .v-time-picker-controls__time__field .v-input__control {
|
||||
height: 64px;
|
||||
}
|
||||
.v-time-picker--density-comfortable .v-time-picker-controls__time__field .v-input__control .v-field {
|
||||
font-size: 40px;
|
||||
}
|
||||
.v-time-picker--density-comfortable .v-time-picker-controls__time__field .v-input__control .v-field .v-field__input {
|
||||
min-height: 64px;
|
||||
}
|
||||
.v-time-picker--density-comfortable.v-time-picker--variant-input .v-time-picker-controls__time__field .v-input__control {
|
||||
height: 56px;
|
||||
}
|
||||
.v-time-picker--density-comfortable.v-time-picker--variant-input .v-time-picker-controls__time__field .v-input__control .v-field {
|
||||
font-size: 32px;
|
||||
}
|
||||
.v-time-picker--density-comfortable.v-time-picker--variant-input .v-time-picker-controls__time__field .v-input__control .v-field .v-field__input {
|
||||
min-height: 56px;
|
||||
}
|
||||
.v-time-picker--density-comfortable .v-time-picker-controls__time--with-seconds .v-time-picker-controls__time__field .v-field {
|
||||
font-size: 32px;
|
||||
}
|
||||
.v-time-picker--density-comfortable .v-time-picker-controls__ampm__btn.v-btn {
|
||||
font-size: 14px;
|
||||
height: 32px;
|
||||
}
|
||||
.v-time-picker--density-comfortable.v-time-picker--variant-input .v-time-picker-controls__ampm__btn.v-btn {
|
||||
height: 28px;
|
||||
}
|
||||
.v-time-picker--density-compact .v-time-picker-controls__time__field .v-input__control {
|
||||
height: 56px;
|
||||
}
|
||||
.v-time-picker--density-compact .v-time-picker-controls__time__field .v-input__control .v-field {
|
||||
font-size: 32px;
|
||||
}
|
||||
.v-time-picker--density-compact .v-time-picker-controls__time__field .v-input__control .v-field .v-field__input {
|
||||
min-height: 56px;
|
||||
}
|
||||
.v-time-picker--density-compact.v-time-picker--variant-input .v-time-picker-controls__time__field .v-input__control {
|
||||
height: 48px;
|
||||
}
|
||||
.v-time-picker--density-compact.v-time-picker--variant-input .v-time-picker-controls__time__field .v-input__control .v-field {
|
||||
font-size: 26px;
|
||||
}
|
||||
.v-time-picker--density-compact.v-time-picker--variant-input .v-time-picker-controls__time__field .v-input__control .v-field .v-field__input {
|
||||
min-height: 48px;
|
||||
}
|
||||
.v-time-picker--density-compact .v-time-picker-controls__time--with-seconds .v-time-picker-controls__time__field .v-field {
|
||||
font-size: 28px;
|
||||
}
|
||||
.v-time-picker--density-compact .v-time-picker-controls__ampm__btn.v-btn {
|
||||
font-size: 12px;
|
||||
height: 28px;
|
||||
}
|
||||
.v-time-picker--density-compact.v-time-picker--variant-input .v-time-picker-controls__ampm__btn.v-btn {
|
||||
height: 24px;
|
||||
}
|
||||
.v-picker__title--landscape .v-time-picker-controls {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
.v-picker__title--landscape .v-time-picker-controls__time {
|
||||
text-align: right;
|
||||
}
|
||||
.v-picker__title--landscape .v-time-picker-controls__time .v-picker__title__btn,
|
||||
.v-picker__title--landscape .v-time-picker-controls__time span {
|
||||
height: 55px;
|
||||
font-size: 55px;
|
||||
}
|
||||
.v-picker__title--landscape .v-time-picker-controls__ampm {
|
||||
margin: 16px 0 0;
|
||||
align-self: initial;
|
||||
text-align: center;
|
||||
}
|
||||
.v-picker--time .v-picker__title--landscape {
|
||||
padding: 0;
|
||||
}
|
||||
.v-picker--time .v-picker__title--landscape .v-time-picker-controls__time {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
@layer vuetify-final.trumps {
|
||||
@media (forced-colors: active) {
|
||||
.v-time-picker-controls__time__field:has(input:focus-visible) {
|
||||
outline: 2px solid highlight;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.v-time-picker-controls__ampm__btn.v-btn--active {
|
||||
color: highlight;
|
||||
forced-color-adjust: preserve-parent-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+287
@@ -0,0 +1,287 @@
|
||||
|
||||
import type { PropType } from 'vue';
|
||||
import type { Period, VTimePickerViewMode } from './shared.js';
|
||||
export declare const makeVTimePickerControlsProps: <Defaults extends {
|
||||
allowedHours?: unknown;
|
||||
allowedMinutes?: unknown;
|
||||
allowedSeconds?: unknown;
|
||||
max?: unknown;
|
||||
min?: unknown;
|
||||
ampm?: unknown;
|
||||
color?: unknown;
|
||||
disabled?: unknown;
|
||||
inputHints?: unknown;
|
||||
hour?: unknown;
|
||||
minute?: unknown;
|
||||
second?: unknown;
|
||||
period?: unknown;
|
||||
readonly?: unknown;
|
||||
useSeconds?: unknown;
|
||||
value?: unknown;
|
||||
viewMode?: unknown;
|
||||
} = {}>(defaults?: Defaults | undefined) => {
|
||||
allowedHours: unknown extends Defaults["allowedHours"] ? PropType<import("./useTimeValidation.js").AllowFunction | number[]> : {
|
||||
type: PropType<unknown extends Defaults["allowedHours"] ? import("./useTimeValidation.js").AllowFunction | number[] : import("./useTimeValidation.js").AllowFunction | number[] | Defaults["allowedHours"]>;
|
||||
default: unknown extends Defaults["allowedHours"] ? import("./useTimeValidation.js").AllowFunction | number[] : Defaults["allowedHours"] | NonNullable<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
};
|
||||
allowedMinutes: unknown extends Defaults["allowedMinutes"] ? PropType<import("./useTimeValidation.js").AllowFunction | number[]> : {
|
||||
type: PropType<unknown extends Defaults["allowedMinutes"] ? import("./useTimeValidation.js").AllowFunction | number[] : import("./useTimeValidation.js").AllowFunction | number[] | Defaults["allowedMinutes"]>;
|
||||
default: unknown extends Defaults["allowedMinutes"] ? import("./useTimeValidation.js").AllowFunction | number[] : Defaults["allowedMinutes"] | NonNullable<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
};
|
||||
allowedSeconds: unknown extends Defaults["allowedSeconds"] ? PropType<import("./useTimeValidation.js").AllowFunction | number[]> : {
|
||||
type: PropType<unknown extends Defaults["allowedSeconds"] ? import("./useTimeValidation.js").AllowFunction | number[] : import("./useTimeValidation.js").AllowFunction | number[] | Defaults["allowedSeconds"]>;
|
||||
default: unknown extends Defaults["allowedSeconds"] ? import("./useTimeValidation.js").AllowFunction | number[] : Defaults["allowedSeconds"] | NonNullable<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
};
|
||||
max: unknown extends Defaults["max"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["max"] ? string : string | Defaults["max"]>;
|
||||
default: unknown extends Defaults["max"] ? string : string | Defaults["max"];
|
||||
};
|
||||
min: unknown extends Defaults["min"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["min"] ? string : string | Defaults["min"]>;
|
||||
default: unknown extends Defaults["min"] ? string : string | Defaults["min"];
|
||||
};
|
||||
ampm: unknown extends Defaults["ampm"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["ampm"] ? boolean : boolean | Defaults["ampm"]>;
|
||||
default: unknown extends Defaults["ampm"] ? boolean : boolean | Defaults["ampm"];
|
||||
};
|
||||
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"];
|
||||
};
|
||||
disabled: unknown extends Defaults["disabled"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["disabled"] ? boolean : boolean | Defaults["disabled"]>;
|
||||
default: unknown extends Defaults["disabled"] ? boolean : boolean | Defaults["disabled"];
|
||||
};
|
||||
inputHints: unknown extends Defaults["inputHints"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["inputHints"] ? boolean : boolean | Defaults["inputHints"]>;
|
||||
default: unknown extends Defaults["inputHints"] ? boolean : boolean | Defaults["inputHints"];
|
||||
};
|
||||
hour: unknown extends Defaults["hour"] ? PropType<string | number | null> : {
|
||||
type: PropType<unknown extends Defaults["hour"] ? string | number | null : string | number | Defaults["hour"] | null>;
|
||||
default: unknown extends Defaults["hour"] ? string | number | null : Defaults["hour"] | NonNullable<string | number | null>;
|
||||
};
|
||||
minute: unknown extends Defaults["minute"] ? PropType<string | number | null> : {
|
||||
type: PropType<unknown extends Defaults["minute"] ? string | number | null : string | number | Defaults["minute"] | null>;
|
||||
default: unknown extends Defaults["minute"] ? string | number | null : Defaults["minute"] | NonNullable<string | number | null>;
|
||||
};
|
||||
second: unknown extends Defaults["second"] ? PropType<string | number | null> : {
|
||||
type: PropType<unknown extends Defaults["second"] ? string | number | null : string | number | Defaults["second"] | null>;
|
||||
default: unknown extends Defaults["second"] ? string | number | null : Defaults["second"] | NonNullable<string | number | null>;
|
||||
};
|
||||
period: unknown extends Defaults["period"] ? PropType<Period> : {
|
||||
type: PropType<unknown extends Defaults["period"] ? Period : Defaults["period"] | Period>;
|
||||
default: unknown extends Defaults["period"] ? Period : Defaults["period"] | NonNullable<Period>;
|
||||
};
|
||||
readonly: unknown extends Defaults["readonly"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["readonly"] ? boolean : boolean | Defaults["readonly"]>;
|
||||
default: unknown extends Defaults["readonly"] ? boolean : boolean | Defaults["readonly"];
|
||||
};
|
||||
useSeconds: unknown extends Defaults["useSeconds"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["useSeconds"] ? boolean : boolean | Defaults["useSeconds"]>;
|
||||
default: unknown extends Defaults["useSeconds"] ? boolean : boolean | Defaults["useSeconds"];
|
||||
};
|
||||
value: unknown extends Defaults["value"] ? NumberConstructor : {
|
||||
type: PropType<unknown extends Defaults["value"] ? number : number | Defaults["value"]>;
|
||||
default: unknown extends Defaults["value"] ? number : number | Defaults["value"];
|
||||
};
|
||||
viewMode: unknown extends Defaults["viewMode"] ? PropType<VTimePickerViewMode> : {
|
||||
type: PropType<unknown extends Defaults["viewMode"] ? VTimePickerViewMode : Defaults["viewMode"] | VTimePickerViewMode>;
|
||||
default: unknown extends Defaults["viewMode"] ? VTimePickerViewMode : Defaults["viewMode"] | NonNullable<VTimePickerViewMode>;
|
||||
};
|
||||
};
|
||||
export declare const VTimePickerControls: {
|
||||
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<{
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
inputHints: boolean;
|
||||
readonly: boolean;
|
||||
useSeconds: boolean;
|
||||
} & {
|
||||
allowedHours?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedMinutes?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedSeconds?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
max?: string | undefined;
|
||||
min?: string | undefined;
|
||||
color?: string | undefined;
|
||||
hour?: string | number | null | undefined;
|
||||
minute?: string | number | null | undefined;
|
||||
second?: string | number | null | undefined;
|
||||
period?: Period | undefined;
|
||||
value?: number | undefined;
|
||||
viewMode?: VTimePickerViewMode | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
"onUpdate:hour"?: ((v: number) => any) | undefined;
|
||||
"onUpdate:minute"?: ((v: number) => any) | undefined;
|
||||
"onUpdate:period"?: ((data: Period) => any) | undefined;
|
||||
"onUpdate:second"?: ((v: number) => any) | undefined;
|
||||
"onUpdate:viewMode"?: ((data: VTimePickerViewMode) => any) | undefined;
|
||||
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
'update:period': (data: Period) => true;
|
||||
'update:viewMode': (data: VTimePickerViewMode) => true;
|
||||
'update:hour': (v: number) => true;
|
||||
'update:minute': (v: number) => true;
|
||||
'update:second': (v: number) => true;
|
||||
}, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, {
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
inputHints: boolean;
|
||||
readonly: boolean;
|
||||
useSeconds: boolean;
|
||||
}, true, {}, import("vue").SlotsType<Partial<{
|
||||
default: () => 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: {};
|
||||
}, {
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
inputHints: boolean;
|
||||
readonly: boolean;
|
||||
useSeconds: boolean;
|
||||
} & {
|
||||
allowedHours?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedMinutes?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedSeconds?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
max?: string | undefined;
|
||||
min?: string | undefined;
|
||||
color?: string | undefined;
|
||||
hour?: string | number | null | undefined;
|
||||
minute?: string | number | null | undefined;
|
||||
second?: string | number | null | undefined;
|
||||
period?: Period | undefined;
|
||||
value?: number | undefined;
|
||||
viewMode?: VTimePickerViewMode | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
"onUpdate:hour"?: ((v: number) => any) | undefined;
|
||||
"onUpdate:minute"?: ((v: number) => any) | undefined;
|
||||
"onUpdate:period"?: ((data: Period) => any) | undefined;
|
||||
"onUpdate:second"?: ((v: number) => any) | undefined;
|
||||
"onUpdate:viewMode"?: ((data: VTimePickerViewMode) => any) | undefined;
|
||||
}, {}, {}, {}, {}, {
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
inputHints: boolean;
|
||||
readonly: boolean;
|
||||
useSeconds: boolean;
|
||||
}>;
|
||||
__isFragment?: never;
|
||||
__isTeleport?: never;
|
||||
__isSuspense?: never;
|
||||
} & import("vue").ComponentOptionsBase<{
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
inputHints: boolean;
|
||||
readonly: boolean;
|
||||
useSeconds: boolean;
|
||||
} & {
|
||||
allowedHours?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedMinutes?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
allowedSeconds?: import("./useTimeValidation.js").AllowFunction | number[] | undefined;
|
||||
max?: string | undefined;
|
||||
min?: string | undefined;
|
||||
color?: string | undefined;
|
||||
hour?: string | number | null | undefined;
|
||||
minute?: string | number | null | undefined;
|
||||
second?: string | number | null | undefined;
|
||||
period?: Period | undefined;
|
||||
value?: number | undefined;
|
||||
viewMode?: VTimePickerViewMode | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
default?: (() => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | (() => import("vue").VNodeChild) | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
default?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:default"?: false | (() => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
"onUpdate:hour"?: ((v: number) => any) | undefined;
|
||||
"onUpdate:minute"?: ((v: number) => any) | undefined;
|
||||
"onUpdate:period"?: ((data: Period) => any) | undefined;
|
||||
"onUpdate:second"?: ((v: number) => any) | undefined;
|
||||
"onUpdate:viewMode"?: ((data: VTimePickerViewMode) => any) | undefined;
|
||||
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
'update:period': (data: Period) => true;
|
||||
'update:viewMode': (data: VTimePickerViewMode) => true;
|
||||
'update:hour': (v: number) => true;
|
||||
'update:minute': (v: number) => true;
|
||||
'update:second': (v: number) => true;
|
||||
}, string, {
|
||||
ampm: boolean;
|
||||
disabled: boolean;
|
||||
inputHints: boolean;
|
||||
readonly: boolean;
|
||||
useSeconds: boolean;
|
||||
}, {}, string, import("vue").SlotsType<Partial<{
|
||||
default: () => 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<{
|
||||
allowedHours: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
allowedMinutes: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
allowedSeconds: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
max: StringConstructor;
|
||||
min: StringConstructor;
|
||||
ampm: BooleanConstructor;
|
||||
color: StringConstructor;
|
||||
disabled: BooleanConstructor;
|
||||
inputHints: BooleanConstructor;
|
||||
hour: PropType<number | string | null>;
|
||||
minute: PropType<number | string | null>;
|
||||
second: PropType<number | string | null>;
|
||||
period: PropType<Period>;
|
||||
readonly: BooleanConstructor;
|
||||
useSeconds: BooleanConstructor;
|
||||
value: NumberConstructor;
|
||||
viewMode: PropType<VTimePickerViewMode>;
|
||||
}, import("vue").ExtractPropTypes<{
|
||||
allowedHours: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
allowedMinutes: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
allowedSeconds: PropType<import("./useTimeValidation.js").AllowFunction | number[]>;
|
||||
max: StringConstructor;
|
||||
min: StringConstructor;
|
||||
ampm: BooleanConstructor;
|
||||
color: StringConstructor;
|
||||
disabled: BooleanConstructor;
|
||||
inputHints: BooleanConstructor;
|
||||
hour: PropType<number | string | null>;
|
||||
minute: PropType<number | string | null>;
|
||||
second: PropType<number | string | null>;
|
||||
period: PropType<Period>;
|
||||
readonly: BooleanConstructor;
|
||||
useSeconds: BooleanConstructor;
|
||||
value: NumberConstructor;
|
||||
viewMode: PropType<VTimePickerViewMode>;
|
||||
}>>;
|
||||
export type VTimePickerControls = InstanceType<typeof VTimePickerControls>;
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
import { createVNode as _createVNode, createTextVNode as _createTextVNode, createElementVNode as _createElementVNode, Fragment as _Fragment, normalizeClass as _normalizeClass } from "vue";
|
||||
// Styles
|
||||
import "./VTimePickerControls.css";
|
||||
|
||||
// Components
|
||||
import { VTimePickerField } from "./VTimePickerField.js";
|
||||
import { VBtn } from "../VBtn/index.js"; // Composables
|
||||
import { useLocale } from "../../composables/locale.js";
|
||||
import { useProxiedModel } from "../../composables/proxiedModel.js"; // Utilities
|
||||
import { computed, nextTick, ref, watch } from 'vue';
|
||||
import { makeTimeValidationProps, useTimeValidation } from "./useTimeValidation.js";
|
||||
import { convert12to24, convert24to12, extractInteger, pad } from "./util.js";
|
||||
import { clamp, genericComponent, propsFactory, useRender } from "../../util/index.js"; // Types
|
||||
export const makeVTimePickerControlsProps = propsFactory({
|
||||
ampm: Boolean,
|
||||
color: String,
|
||||
disabled: Boolean,
|
||||
inputHints: Boolean,
|
||||
hour: [Number, String],
|
||||
minute: [Number, String],
|
||||
second: [Number, String],
|
||||
period: String,
|
||||
readonly: Boolean,
|
||||
useSeconds: Boolean,
|
||||
value: Number,
|
||||
viewMode: String,
|
||||
...makeTimeValidationProps()
|
||||
}, 'VTimePickerControls');
|
||||
export const VTimePickerControls = genericComponent()({
|
||||
name: 'VTimePickerControls',
|
||||
props: makeVTimePickerControlsProps(),
|
||||
emits: {
|
||||
'update:period': data => true,
|
||||
'update:viewMode': data => true,
|
||||
'update:hour': v => true,
|
||||
'update:minute': v => true,
|
||||
'update:second': v => true
|
||||
},
|
||||
setup(props, {
|
||||
emit
|
||||
}) {
|
||||
const {
|
||||
t
|
||||
} = useLocale();
|
||||
const {
|
||||
isAllowedHour,
|
||||
isAllowedMinute,
|
||||
isAllowedSecond,
|
||||
findNextAllowed
|
||||
} = useTimeValidation(props);
|
||||
const currentHour = computed(() => props.hour !== null ? props.ampm ? convert12to24(Number(props.hour), props.period ?? 'am') : Number(props.hour) : null);
|
||||
const currentMinute = computed(() => props.minute !== null ? Number(props.minute) : null);
|
||||
const isHourValid = computed(() => {
|
||||
if (props.hour === null) return true;
|
||||
return isAllowedHour.value?.(Number(currentHour.value)) ?? true;
|
||||
});
|
||||
const isMinuteValid = computed(() => {
|
||||
if (props.minute === null) return true;
|
||||
return isAllowedMinute.value?.(currentHour.value, Number(props.minute)) ?? true;
|
||||
});
|
||||
const isSecondValid = computed(() => {
|
||||
if (props.second === null) return true;
|
||||
return isAllowedSecond.value?.(currentHour.value, currentMinute.value, Number(props.second)) ?? true;
|
||||
});
|
||||
const transformHours = {
|
||||
in: v => {
|
||||
if (v == null || isNaN(Number(v))) return null;
|
||||
const val = Number(v);
|
||||
return props.ampm ? pad(convert24to12(val)) : pad(val);
|
||||
},
|
||||
out: v => {
|
||||
if (isNaN(Number(v)) || v == null || v === '') return null;
|
||||
const val = typeof v === 'string' ? extractInteger(v) : Number(v);
|
||||
if (val === null) return null;
|
||||
return props.ampm ? convert12to24(val, props.period ?? 'am') : clamp(val, 0, 23);
|
||||
}
|
||||
};
|
||||
const hour = useProxiedModel(props, 'hour', undefined, transformHours.in, transformHours.out);
|
||||
const transformMinutesOrSeconds = {
|
||||
in: v => v != null && !isNaN(Number(v)) ? pad(`${v}`) : null,
|
||||
out: v => {
|
||||
if (isNaN(Number(v)) || v == null || v === '') return null;
|
||||
const val = typeof v === 'string' ? extractInteger(v) : Number(v);
|
||||
return val !== null ? clamp(val, 0, 59) : null;
|
||||
}
|
||||
};
|
||||
const minute = useProxiedModel(props, 'minute', undefined, transformMinutesOrSeconds.in, transformMinutesOrSeconds.out);
|
||||
const second = useProxiedModel(props, 'second', undefined, transformMinutesOrSeconds.in, transformMinutesOrSeconds.out);
|
||||
function onHourFieldKeydown(e) {
|
||||
if (!['ArrowUp', 'ArrowDown'].includes(e.key)) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const isAm = props.period === 'am';
|
||||
const current = props.ampm ? convert12to24(Number(hour.value ?? 0), isAm ? 'am' : 'pm') : Number(hour.value ?? 0);
|
||||
const next = findNextAllowed('hour', current, e.key === 'ArrowUp');
|
||||
const togglePeriod = isAm && next >= 12 || !isAm && next < 12;
|
||||
if (props.ampm && togglePeriod) {
|
||||
emit('update:period', props.period === 'am' ? 'pm' : 'am');
|
||||
nextTick(() => hour.value = pad(next));
|
||||
} else {
|
||||
hour.value = pad(next);
|
||||
}
|
||||
}
|
||||
function onMinuteFieldKeydown(e) {
|
||||
if (!['ArrowUp', 'ArrowDown'].includes(e.key)) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const current = Number(minute.value ?? 0);
|
||||
const next = findNextAllowed('minute', current, e.key === 'ArrowUp', currentHour.value);
|
||||
minute.value = pad(next);
|
||||
}
|
||||
function onSecondFieldKeydown(e) {
|
||||
if (!['ArrowUp', 'ArrowDown'].includes(e.key)) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const current = Number(second.value ?? 0);
|
||||
const next = findNextAllowed('second', current, e.key === 'ArrowUp', currentHour.value, currentMinute.value);
|
||||
second.value = pad(next);
|
||||
}
|
||||
function createInputInterceptor(valueTransformOut, compare, apply) {
|
||||
return e => {
|
||||
if (!e.data) return;
|
||||
const inputElement = e.target;
|
||||
const {
|
||||
value: existingTxt,
|
||||
selectionStart,
|
||||
selectionEnd
|
||||
} = inputElement ?? {};
|
||||
if (extractInteger(e.data) === null) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
const potentialNewInputVal = existingTxt ? existingTxt.slice(0, selectionStart) + e.data + existingTxt.slice(selectionEnd) : e.data;
|
||||
if (potentialNewInputVal.length > 2) {
|
||||
if (selectionStart === selectionEnd && selectionEnd === 0 && e.data.trim().startsWith('0')) {
|
||||
e.preventDefault();
|
||||
inputElement.value = potentialNewInputVal.trim().substring(0, 2);
|
||||
apply(inputElement.value);
|
||||
if (e.data.trim().length === 1) {
|
||||
inputElement.setSelectionRange(1, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (selectionStart === selectionEnd && selectionEnd === 1 && existingTxt.startsWith('0')) {
|
||||
e.preventDefault();
|
||||
inputElement.value = potentialNewInputVal.trim().substring(0, 2);
|
||||
apply(inputElement.value);
|
||||
return;
|
||||
}
|
||||
const maxValue = props.viewMode === 'hour' ? props.ampm ? 12 : 23 : 59;
|
||||
const value = extractInteger(potentialNewInputVal);
|
||||
if (value > maxValue) {
|
||||
e.preventDefault();
|
||||
inputElement.value = pad(String(extractInteger(e.data)).substring(0, 2));
|
||||
apply(inputElement.value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const potentialNewNumber = valueTransformOut(potentialNewInputVal);
|
||||
if (compare(potentialNewNumber)) {
|
||||
// ignore input when results in the same number
|
||||
// prevents typing more digits
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
}
|
||||
function setPeriod(val) {
|
||||
emit('update:period', val);
|
||||
}
|
||||
const hourInputRef = ref();
|
||||
const minuteInputRef = ref();
|
||||
const secondInputRef = ref();
|
||||
watch(() => props.viewMode, (_, old) => {
|
||||
switch (old) {
|
||||
case 'hour':
|
||||
hourInputRef.value.blur();
|
||||
break;
|
||||
case 'minute':
|
||||
minuteInputRef.value.blur();
|
||||
break;
|
||||
case 'second':
|
||||
secondInputRef.value.blur();
|
||||
break;
|
||||
}
|
||||
});
|
||||
const hourInputFilter = createInputInterceptor(transformHours.out, v => transformHours.in(v) === hour.value, v => hour.value = v);
|
||||
const minuteInputFilter = createInputInterceptor(transformMinutesOrSeconds.out, v => transformMinutesOrSeconds.in(v) === minute.value, v => minute.value = v);
|
||||
const secondInputFilter = createInputInterceptor(transformMinutesOrSeconds.out, v => transformMinutesOrSeconds.in(v) === second.value, v => second.value = v);
|
||||
useRender(() => {
|
||||
return _createElementVNode("div", {
|
||||
"class": "v-time-picker-controls"
|
||||
}, [_createElementVNode("div", {
|
||||
"class": _normalizeClass({
|
||||
'v-time-picker-controls__time': true,
|
||||
'v-time-picker-controls__time--with-ampm': props.ampm,
|
||||
'v-time-picker-controls__time--with-seconds': props.useSeconds
|
||||
})
|
||||
}, [_createVNode(VTimePickerField, {
|
||||
"ref": hourInputRef,
|
||||
"active": props.viewMode === 'hour',
|
||||
"color": props.color,
|
||||
"disabled": props.disabled,
|
||||
"label": t('$vuetify.timePicker.hour'),
|
||||
"showHint": props.inputHints,
|
||||
"error": isHourValid.value ? undefined : t('$vuetify.timePicker.notAllowed'),
|
||||
"modelValue": hour.value,
|
||||
"onUpdate:modelValue": v => hour.value = v,
|
||||
"onKeydown": onHourFieldKeydown,
|
||||
"onBeforeinput": hourInputFilter,
|
||||
"onFocus": () => emit('update:viewMode', 'hour')
|
||||
}, null), _createElementVNode("span", {
|
||||
"class": "v-time-picker-controls__time__separator"
|
||||
}, [_createTextVNode(":")]), _createVNode(VTimePickerField, {
|
||||
"ref": minuteInputRef,
|
||||
"active": props.viewMode === 'minute',
|
||||
"color": props.color,
|
||||
"disabled": props.disabled,
|
||||
"label": t('$vuetify.timePicker.minute'),
|
||||
"showHint": props.inputHints,
|
||||
"error": isMinuteValid.value ? undefined : t('$vuetify.timePicker.notAllowed'),
|
||||
"modelValue": minute.value,
|
||||
"onUpdate:modelValue": v => minute.value = v,
|
||||
"onKeydown": onMinuteFieldKeydown,
|
||||
"onBeforeinput": minuteInputFilter,
|
||||
"onFocus": () => emit('update:viewMode', 'minute')
|
||||
}, null), props.useSeconds && _createElementVNode("span", {
|
||||
"key": "secondsDivider",
|
||||
"class": "v-time-picker-controls__time__separator"
|
||||
}, [_createTextVNode(":")]), props.useSeconds && _createElementVNode(_Fragment, null, [_createVNode(VTimePickerField, {
|
||||
"key": "secondsVal",
|
||||
"ref": secondInputRef,
|
||||
"active": props.viewMode === 'second',
|
||||
"color": props.color,
|
||||
"disabled": props.disabled,
|
||||
"label": t('$vuetify.timePicker.second'),
|
||||
"showHint": props.inputHints,
|
||||
"error": isSecondValid.value ? undefined : t('$vuetify.timePicker.notAllowed'),
|
||||
"modelValue": second.value,
|
||||
"onUpdate:modelValue": v => second.value = v,
|
||||
"onKeydown": onSecondFieldKeydown,
|
||||
"onBeforeinput": secondInputFilter,
|
||||
"onFocus": () => emit('update:viewMode', 'second')
|
||||
}, null)]), props.ampm && _createElementVNode("div", {
|
||||
"class": "v-time-picker-controls__ampm"
|
||||
}, [_createVNode(VBtn, {
|
||||
"active": props.period === 'am',
|
||||
"color": props.period === 'am' ? props.color : undefined,
|
||||
"class": _normalizeClass({
|
||||
'v-time-picker-controls__ampm__am': true,
|
||||
'v-time-picker-controls__ampm__btn': true,
|
||||
'v-time-picker-controls__ampm__btn__active': props.period === 'am'
|
||||
}),
|
||||
"disabled": props.disabled,
|
||||
"text": t('$vuetify.timePicker.am'),
|
||||
"variant": props.disabled && props.period === 'am' ? 'elevated' : 'tonal',
|
||||
"onClick": () => props.period !== 'am' ? setPeriod('am') : null
|
||||
}, null), _createVNode(VBtn, {
|
||||
"active": props.period === 'pm',
|
||||
"color": props.period === 'pm' ? props.color : undefined,
|
||||
"class": _normalizeClass({
|
||||
'v-time-picker-controls__ampm__pm': true,
|
||||
'v-time-picker-controls__ampm__btn': true,
|
||||
'v-time-picker-controls__ampm__btn__active': props.period === 'pm'
|
||||
}),
|
||||
"disabled": props.disabled,
|
||||
"text": t('$vuetify.timePicker.pm'),
|
||||
"variant": props.disabled && props.period === 'pm' ? 'elevated' : 'tonal',
|
||||
"onClick": () => props.period !== 'pm' ? setPeriod('pm') : null
|
||||
}, null)])])]);
|
||||
});
|
||||
return {};
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=VTimePickerControls.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+187
@@ -0,0 +1,187 @@
|
||||
@use 'sass:map'
|
||||
@use '../../styles/tools'
|
||||
@use '../../styles/settings'
|
||||
@use './variables' as *
|
||||
|
||||
@include tools.layer('components')
|
||||
.v-time-picker-controls
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
font-size: .875rem
|
||||
margin-inline: $time-picker-padding
|
||||
margin-bottom: 12px
|
||||
|
||||
&__text
|
||||
padding-bottom: 12px
|
||||
|
||||
&__time
|
||||
display: flex
|
||||
white-space: nowrap
|
||||
direction: ltr
|
||||
justify-content: center
|
||||
align-items: start
|
||||
|
||||
.v-time-picker-controls__time__separator
|
||||
width: $time-picker-controls-separator-width
|
||||
text-align: center
|
||||
|
||||
.v-time-picker--density-compact &
|
||||
font-weight: bold
|
||||
|
||||
@at-root
|
||||
@include tools.density('v-time-picker', $time-picker-controls-field-density) using ($modifier)
|
||||
.v-time-picker-controls__time__separator
|
||||
font-size: $time-picker-controls-btn-font + $modifier
|
||||
line-height: $time-picker-controls-separator-line-height + $modifier
|
||||
|
||||
.v-time-picker--variant-input &
|
||||
line-height: $time-picker-controls-input-separator-line-height + $modifier
|
||||
|
||||
.v-time-picker-controls__time--with-seconds &
|
||||
height: $time-picker-controls-seconds-btn-height + $modifier
|
||||
font-size: $time-picker-controls-btn-font + $modifier
|
||||
|
||||
.v-time-picker-controls__time__field
|
||||
width: $time-picker-controls-field-width
|
||||
|
||||
.v-field
|
||||
width: $time-picker-controls-field-width
|
||||
background-color: $time-picker-controls-field-background
|
||||
color: inherit
|
||||
transition: color .25s settings.$standard-easing
|
||||
|
||||
> .v-field__overlay
|
||||
opacity: $time-picker-controls-field-overlay-opacity
|
||||
|
||||
&--active .v-field > .v-field__overlay
|
||||
opacity: calc((#{$time-picker-controls-field-overlay-opacity} + #{map.get(settings.$states, 'focus')}) * var(--v-theme-overlay-multiplier))
|
||||
|
||||
.v-time-picker--variant-input &
|
||||
width: $time-picker-controls-input-field-width
|
||||
|
||||
.v-field
|
||||
width: $time-picker-controls-input-field-width
|
||||
|
||||
.v-time-picker-controls__time--with-seconds &
|
||||
width: $time-picker-controls-seconds-field-width
|
||||
|
||||
.v-time-picker--variant-input &
|
||||
width: $time-picker-controls-input-seconds-field-width
|
||||
|
||||
.v-field__input
|
||||
padding: 0
|
||||
font-weight: 500
|
||||
text-align: center
|
||||
line-height: 1
|
||||
align-self: center
|
||||
|
||||
&:focus::placeholder
|
||||
opacity: 0
|
||||
|
||||
&.v-input > .v-input__details
|
||||
font-size: $time-picker-field-label-font-size
|
||||
letter-spacing: $time-picker-field-label-letter-spacing
|
||||
padding-inline: 0
|
||||
white-space: normal
|
||||
|
||||
> .v-messages
|
||||
opacity: 1
|
||||
|
||||
&.v-input--error .v-field__input
|
||||
color: rgb(var(--v-theme-error))
|
||||
|
||||
.v-time-picker-controls__ampm
|
||||
margin-left: 12px
|
||||
display: flex
|
||||
flex-direction: column
|
||||
text-transform: uppercase
|
||||
|
||||
&--readonly
|
||||
pointer-events: none
|
||||
|
||||
&--readonly
|
||||
.v-picker__title__btn.v-picker__title__btn--active
|
||||
opacity: $picker-inactive-btn-opacity
|
||||
|
||||
&__btn.v-btn
|
||||
min-width: 52px
|
||||
padding: 0 8px
|
||||
|
||||
&.v-time-picker-controls__ampm__am
|
||||
border-radius: $time-picker-controls-ampm-am-border-radius
|
||||
border: 1px solid
|
||||
|
||||
&.v-time-picker-controls__ampm__pm
|
||||
border-radius: $time-picker-controls-ampm-pm-border-radius
|
||||
border: 1px solid
|
||||
border-top: none
|
||||
|
||||
&__active
|
||||
background: rgb(var(--v-theme-primary))
|
||||
|
||||
@at-root
|
||||
@include tools.density('v-time-picker', $time-picker-controls-field-density) using ($modifier)
|
||||
.v-time-picker-controls__time__field .v-input__control
|
||||
height: $time-picker-controls-field-height + $modifier
|
||||
|
||||
.v-field
|
||||
font-size: $time-picker-controls-field-font + $modifier
|
||||
|
||||
.v-field__input
|
||||
min-height: $time-picker-controls-field-height + $modifier
|
||||
|
||||
&.v-time-picker--variant-input .v-time-picker-controls__time__field .v-input__control
|
||||
height: $time-picker-controls-input-field-height + $modifier
|
||||
|
||||
.v-field
|
||||
font-size: $time-picker-controls-input-field-font + $modifier * .75
|
||||
|
||||
.v-field__input
|
||||
min-height: $time-picker-controls-input-field-height + $modifier
|
||||
|
||||
.v-time-picker-controls__time--with-seconds .v-time-picker-controls__time__field .v-field
|
||||
font-size: $time-picker-controls-seconds-field-font + $modifier * .5
|
||||
|
||||
.v-time-picker-controls__ampm__btn.v-btn
|
||||
font-size: $time-picker-ampm-title-font-size + $modifier * .25
|
||||
height: $time-picker-controls-ampm-height + $modifier * .5
|
||||
|
||||
&.v-time-picker--variant-input .v-time-picker-controls__ampm__btn.v-btn
|
||||
height: $time-picker-controls-input-ampm-height + $modifier * .5
|
||||
|
||||
.v-picker__title--landscape
|
||||
.v-time-picker-controls
|
||||
flex-direction: column
|
||||
justify-content: center
|
||||
height: 100%
|
||||
|
||||
.v-time-picker-controls__time
|
||||
text-align: right
|
||||
|
||||
.v-picker__title__btn,
|
||||
span
|
||||
height: $time-picker-landscape-title-btn-height
|
||||
font-size: $time-picker-landscape-title-btn-height
|
||||
|
||||
.v-time-picker-controls__ampm
|
||||
margin: $time-picker-landscape-ampm-title-margin
|
||||
align-self: initial
|
||||
text-align: center
|
||||
|
||||
.v-picker--time .v-picker__title--landscape
|
||||
padding: 0
|
||||
|
||||
.v-time-picker-controls__time
|
||||
text-align: center
|
||||
|
||||
@include tools.layer('trumps')
|
||||
@media (forced-colors: active)
|
||||
.v-time-picker-controls
|
||||
&__time__field:has(input:focus-visible)
|
||||
outline: 2px solid highlight
|
||||
outline-offset: 2px
|
||||
|
||||
&__ampm__btn.v-btn--active
|
||||
color: highlight
|
||||
forced-color-adjust: preserve-parent-color
|
||||
+6760
File diff suppressed because one or more lines are too long
+71
@@ -0,0 +1,71 @@
|
||||
import { normalizeClass as _normalizeClass, normalizeStyle as _normalizeStyle, createVNode as _createVNode } from "vue";
|
||||
// Components
|
||||
import { VTextField } from "../VTextField/index.js"; // Composables
|
||||
import { useTextColor } from "../../composables/color.js";
|
||||
import { forwardRefs } from "../../composables/forwardRefs.js"; // Utilities
|
||||
import { ref, shallowRef } from 'vue';
|
||||
import { genericComponent, propsFactory, useRender } from "../../util/index.js"; // Types
|
||||
export const makeVTimePickerFieldProps = propsFactory({
|
||||
active: Boolean,
|
||||
color: String,
|
||||
disabled: Boolean,
|
||||
label: String,
|
||||
modelValue: String,
|
||||
error: String,
|
||||
showHint: Boolean,
|
||||
readonly: Boolean
|
||||
}, 'VTimePickerField');
|
||||
export const VTimePickerField = genericComponent()({
|
||||
name: 'VTimePickerField',
|
||||
props: makeVTimePickerFieldProps(),
|
||||
emits: {
|
||||
'update:modelValue': v => true
|
||||
},
|
||||
setup(props, {
|
||||
emit
|
||||
}) {
|
||||
const {
|
||||
textColorClasses,
|
||||
textColorStyles
|
||||
} = useTextColor(() => props.color);
|
||||
const vTextInputRef = ref();
|
||||
const isFocused = shallowRef(false);
|
||||
function onKeydown(e) {
|
||||
if (['Backspace', 'Delete'].includes(e.key)) {
|
||||
e.preventDefault();
|
||||
const target = e.target;
|
||||
target.value = '';
|
||||
emit('update:modelValue', null);
|
||||
}
|
||||
}
|
||||
useRender(() => {
|
||||
return _createVNode(VTextField, {
|
||||
"ref": vTextInputRef,
|
||||
"_as": "VTimePickerField",
|
||||
"autocomplete": "off",
|
||||
"class": _normalizeClass(['v-time-picker-controls__time__field', {
|
||||
'v-time-picker-controls__time__field--active': props.active
|
||||
}, props.active ? textColorClasses.value : []]),
|
||||
"style": _normalizeStyle(props.active ? textColorStyles.value : []),
|
||||
"disabled": props.disabled,
|
||||
"variant": "solo-filled",
|
||||
"inputmode": "numeric",
|
||||
"hideDetails": "auto",
|
||||
"aria-label": props.label,
|
||||
"aria-invalid": !!props.error,
|
||||
"aria-errormessage": props.error,
|
||||
"error": !!props.error,
|
||||
"hint": props.showHint ? props.label : undefined,
|
||||
"persistentHint": true,
|
||||
"flat": true,
|
||||
"modelValue": props.modelValue ?? (isFocused.value ? '' : '--'),
|
||||
"onUpdate:modelValue": v => emit('update:modelValue', v),
|
||||
"onKeydown": onKeydown,
|
||||
"onFocus": () => isFocused.value = true,
|
||||
"onBlur": () => isFocused.value = false
|
||||
}, null);
|
||||
});
|
||||
return forwardRefs({}, vTextInputRef);
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=VTimePickerField.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+57
@@ -0,0 +1,57 @@
|
||||
@forward '../../labs/VPicker/variables';
|
||||
|
||||
$time-picker-padding: 24px !default;
|
||||
$time-picker-controls-btn-font: 56px !default;
|
||||
$time-picker-controls-btn-height: 80px !default;
|
||||
$time-picker-controls-btn-width: 96px !default;
|
||||
$time-picker-controls-seconds-btn-width: 64px !default;
|
||||
$time-picker-controls-seconds-btn-height: 80px !default;
|
||||
$time-picker-controls-seconds-btn-font: 40px !default;
|
||||
$time-picker-controls-separator-width: 24px !default;
|
||||
$time-picker-controls-separator-line-height: 74px !default;
|
||||
$time-picker-controls-ampm-btn-width: 96px !default;
|
||||
$time-picker-controls-ampm-btn-height: 80px !default;
|
||||
$time-picker-controls-ampm-height: 40px !default;
|
||||
|
||||
$time-picker-controls-field-background: rgb(var(--v-theme-surface-light)) !default;
|
||||
$time-picker-controls-field-overlay-opacity: 0.04 !default;
|
||||
|
||||
$time-picker-controls-field-font: 56px !default;
|
||||
$time-picker-controls-field-height: 80px !default;
|
||||
$time-picker-controls-field-width: 96px !default;
|
||||
$time-picker-controls-seconds-field-width: 64px !default;
|
||||
$time-picker-controls-seconds-field-font: 40px !default;
|
||||
$time-picker-controls-field-density: ('default': 0, 'comfortable': -4, 'compact': -6) !default;
|
||||
|
||||
$time-picker-controls-input-field-font: 44px !default;
|
||||
$time-picker-controls-input-field-height: 72px !default;
|
||||
$time-picker-controls-input-field-width: 96px !default;
|
||||
$time-picker-controls-input-seconds-field-width: 64px !default;
|
||||
$time-picker-controls-input-seconds-field-font: 40px !default;
|
||||
|
||||
$time-picker-controls-input-separator-line-height: 64px !default;
|
||||
$time-picker-controls-input-ampm-height: 36px !default;
|
||||
|
||||
$time-picker-controls-ampm-am-border-radius: 4px 4px 0 0 !default;
|
||||
$time-picker-controls-ampm-pm-border-radius: 0 0 4px 4px !default;
|
||||
$time-picker-ampm-title-font-size: 18px !default;
|
||||
$time-picker-number-font-size: 16px !default;
|
||||
$time-picker-field-label-font-size: 12px !default;
|
||||
$time-picker-field-label-letter-spacing: .0333333333em !default;
|
||||
$time-picker-indicator-size: 40px !default;
|
||||
$time-picker-clock-padding: 10px !default;
|
||||
$time-picker-clock-max-width: 290px !default;
|
||||
$time-picker-clock-hand-height: calc(50% - 4px) !default;
|
||||
$time-picker-clock-hand-width: 2px !default;
|
||||
$time-picker-clock-hand-left: calc(50% - 1px) !default;
|
||||
$time-picker-clock-center-size: 8px !default;
|
||||
$time-picker-clock-end-size: 10px !default;
|
||||
$time-picker-clock-end-top: -4px !default;
|
||||
$time-picker-clock-inner-hand-height: 14px !default;
|
||||
$time-picker-clock-inner-offset: 27px !default;
|
||||
$time-picker-clock-end-border-width: 2px !default;
|
||||
$time-picker-clock-end-border-style: solid !default;
|
||||
$time-picker-clock-end-border-color: currentColor !default;
|
||||
$time-picker-width: 328px !default;
|
||||
$time-picker-landscape-title-btn-height: 55px !default;
|
||||
$time-picker-landscape-ampm-title-margin: 16px 0 0 !default;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export { VTimePicker } from './VTimePicker.js';
|
||||
export { VTimePickerClock } from './VTimePickerClock.js';
|
||||
export { VTimePickerControls } from './VTimePickerControls.js';
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export { VTimePicker } from "./VTimePicker.js";
|
||||
export { VTimePickerClock } from "./VTimePickerClock.js";
|
||||
export { VTimePickerControls } from "./VTimePickerControls.js";
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","names":["VTimePicker","VTimePickerClock","VTimePickerControls"],"sources":["../../../src/components/VTimePicker/index.ts"],"sourcesContent":["export { VTimePicker } from './VTimePicker'\nexport { VTimePickerClock } from './VTimePickerClock'\nexport { VTimePickerControls } from './VTimePickerControls'\n"],"mappings":"SAASA,WAAW;AAAA,SACXC,gBAAgB;AAAA,SAChBC,mBAAmB","ignoreList":[]}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export type Period = 'am' | 'pm';
|
||||
export type VTimePickerViewMode = 'hour' | 'minute' | 'second';
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=shared.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"shared.js","names":[],"sources":["../../../src/components/VTimePicker/shared.ts"],"sourcesContent":["export type Period = 'am' | 'pm'\nexport type VTimePickerViewMode = 'hour' | 'minute' | 'second'\n"],"mappings":"","ignoreList":[]}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
import type { PropType } from 'vue';
|
||||
import type { VTimePickerViewMode } from './shared.js';
|
||||
export type AllowFunction = (val: number) => boolean;
|
||||
export declare const makeTimeValidationProps: <Defaults extends {
|
||||
allowedHours?: unknown;
|
||||
allowedMinutes?: unknown;
|
||||
allowedSeconds?: unknown;
|
||||
max?: unknown;
|
||||
min?: unknown;
|
||||
} = {}>(defaults?: Defaults | undefined) => {
|
||||
allowedHours: unknown extends Defaults["allowedHours"] ? PropType<AllowFunction | number[]> : {
|
||||
type: PropType<unknown extends Defaults["allowedHours"] ? AllowFunction | number[] : AllowFunction | number[] | Defaults["allowedHours"]>;
|
||||
default: unknown extends Defaults["allowedHours"] ? AllowFunction | number[] : Defaults["allowedHours"] | NonNullable<AllowFunction | number[]>;
|
||||
};
|
||||
allowedMinutes: unknown extends Defaults["allowedMinutes"] ? PropType<AllowFunction | number[]> : {
|
||||
type: PropType<unknown extends Defaults["allowedMinutes"] ? AllowFunction | number[] : AllowFunction | number[] | Defaults["allowedMinutes"]>;
|
||||
default: unknown extends Defaults["allowedMinutes"] ? AllowFunction | number[] : Defaults["allowedMinutes"] | NonNullable<AllowFunction | number[]>;
|
||||
};
|
||||
allowedSeconds: unknown extends Defaults["allowedSeconds"] ? PropType<AllowFunction | number[]> : {
|
||||
type: PropType<unknown extends Defaults["allowedSeconds"] ? AllowFunction | number[] : AllowFunction | number[] | Defaults["allowedSeconds"]>;
|
||||
default: unknown extends Defaults["allowedSeconds"] ? AllowFunction | number[] : Defaults["allowedSeconds"] | NonNullable<AllowFunction | number[]>;
|
||||
};
|
||||
max: unknown extends Defaults["max"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["max"] ? string : string | Defaults["max"]>;
|
||||
default: unknown extends Defaults["max"] ? string : string | Defaults["max"];
|
||||
};
|
||||
min: unknown extends Defaults["min"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["min"] ? string : string | Defaults["min"]>;
|
||||
default: unknown extends Defaults["min"] ? string : string | Defaults["min"];
|
||||
};
|
||||
};
|
||||
export interface TimeValidationProps {
|
||||
allowedHours?: AllowFunction | number[];
|
||||
allowedMinutes?: AllowFunction | number[];
|
||||
allowedSeconds?: AllowFunction | number[];
|
||||
min?: string;
|
||||
max?: string;
|
||||
}
|
||||
export declare function useTimeValidation(props: TimeValidationProps): {
|
||||
isAllowedHour: import("vue").ComputedRef<(val: number) => boolean>;
|
||||
isAllowedMinute: import("vue").ComputedRef<(hour24hr: number | null, val: number) => boolean>;
|
||||
isAllowedSecond: import("vue").ComputedRef<(hour24hr: number | null, minute: number | null, val: number) => boolean>;
|
||||
findNextAllowed: (type: VTimePickerViewMode, value: number, increment: boolean, currentHour?: number | null, currentMinute?: number | null) => number;
|
||||
};
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
// Utilities
|
||||
import { computed } from 'vue';
|
||||
import { incrementHour, incrementMinuteOrSecond } from "./util.js";
|
||||
import { propsFactory } from "../../util/index.js"; // Types
|
||||
export const makeTimeValidationProps = propsFactory({
|
||||
allowedHours: [Function, Array],
|
||||
allowedMinutes: [Function, Array],
|
||||
allowedSeconds: [Function, Array],
|
||||
max: String,
|
||||
min: String
|
||||
}, 'time-validation');
|
||||
export function useTimeValidation(props) {
|
||||
const isAllowedHour = computed(() => {
|
||||
const minHour = props.min ? Number(props.min.split(':')[0]) : 0;
|
||||
const maxHour = props.max ? Number(props.max.split(':')[0]) : 23;
|
||||
return val => {
|
||||
if (val < minHour) return false;
|
||||
if (val > maxHour) return false;
|
||||
if (Array.isArray(props.allowedHours)) return props.allowedHours.includes(val);
|
||||
if (typeof props.allowedHours === 'function') return props.allowedHours(val);
|
||||
return true;
|
||||
};
|
||||
});
|
||||
const isAllowedMinute = computed(() => {
|
||||
const [minHour, minMinute] = props.min ? props.min.split(':').map(Number) : [0, 0];
|
||||
const [maxHour, maxMinute] = props.max ? props.max.split(':').map(Number) : [23, 59];
|
||||
const minTime = minHour * 60 + minMinute;
|
||||
const maxTime = maxHour * 60 + maxMinute;
|
||||
return (hour24hr, val) => {
|
||||
if (hour24hr !== null) {
|
||||
const time = 60 * hour24hr + val;
|
||||
if (time < minTime) return false;
|
||||
if (time > maxTime) return false;
|
||||
}
|
||||
if (Array.isArray(props.allowedMinutes)) return props.allowedMinutes.includes(val);
|
||||
if (typeof props.allowedMinutes === 'function') return props.allowedMinutes(val);
|
||||
return true;
|
||||
};
|
||||
});
|
||||
const isAllowedSecond = computed(() => {
|
||||
const [minHour, minMinute, minSecond] = props.min ? props.min.split(':').map(Number) : [0, 0, 0];
|
||||
const [maxHour, maxMinute, maxSecond] = props.max ? props.max.split(':').map(Number) : [23, 59, 59];
|
||||
const minTime = minHour * 3600 + minMinute * 60 + (minSecond || 0);
|
||||
const maxTime = maxHour * 3600 + maxMinute * 60 + (maxSecond || 0);
|
||||
return (hour24hr, minute, val) => {
|
||||
if (hour24hr !== null && minute !== null) {
|
||||
const time = 3600 * hour24hr + 60 * minute + val;
|
||||
if (time < minTime) return false;
|
||||
if (time > maxTime) return false;
|
||||
}
|
||||
if (Array.isArray(props.allowedSeconds)) return props.allowedSeconds.includes(val);
|
||||
if (typeof props.allowedSeconds === 'function') return props.allowedSeconds(val);
|
||||
return true;
|
||||
};
|
||||
});
|
||||
function findNextAllowed(type, value, increment, currentHour = null, currentMinute = null) {
|
||||
const isAllowed = type === 'hour' ? isAllowedHour.value : type === 'minute' ? v => isAllowedMinute.value(currentHour, v) : v => isAllowedSecond.value(currentHour, currentMinute, v);
|
||||
const nextValue = type === 'hour' ? v => incrementHour(v, increment, null).value : v => incrementMinuteOrSecond(v, increment);
|
||||
const limit = type === 'hour' ? 24 : 60;
|
||||
for (let i = 1; i <= limit; i++) {
|
||||
value = nextValue(value);
|
||||
if (isAllowed(value)) break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
isAllowedHour,
|
||||
isAllowedMinute,
|
||||
isAllowedSecond,
|
||||
findNextAllowed
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=useTimeValidation.js.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
+13
@@ -0,0 +1,13 @@
|
||||
import type { Period } from './shared.js';
|
||||
export declare function pad(n: string | number, length?: number): string;
|
||||
export declare function convert24to12(hour: number): number;
|
||||
export declare function convert12to24(hour: number, period: Period): number;
|
||||
export declare function extractInteger(v: string): number | null;
|
||||
export declare function incrementHour(hour: number, increment: boolean, period: Period | null): {
|
||||
value: number;
|
||||
togglePeriod?: undefined;
|
||||
} | {
|
||||
value: number;
|
||||
togglePeriod: boolean;
|
||||
};
|
||||
export declare function incrementMinuteOrSecond(val: number, increment: boolean): number;
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// Types
|
||||
|
||||
export function pad(n, length = 2) {
|
||||
return String(n).padStart(length, '0');
|
||||
}
|
||||
export function convert24to12(hour) {
|
||||
return hour ? (hour - 1) % 12 + 1 : 12;
|
||||
}
|
||||
export function convert12to24(hour, period) {
|
||||
return hour % 12 + (period === 'pm' ? 12 : 0);
|
||||
}
|
||||
export function extractInteger(v) {
|
||||
const digits = v.replaceAll(/\D/g, '');
|
||||
return digits.length > 0 ? Number(digits) : null;
|
||||
}
|
||||
export function incrementHour(hour, increment, period) {
|
||||
if (period) {
|
||||
if (hour === 12 && increment) {
|
||||
return {
|
||||
value: 1
|
||||
};
|
||||
}
|
||||
if (hour === 11 && increment) {
|
||||
return {
|
||||
value: 12,
|
||||
togglePeriod: true
|
||||
};
|
||||
}
|
||||
if (hour === 12 && !increment) {
|
||||
return {
|
||||
value: 11,
|
||||
togglePeriod: true
|
||||
};
|
||||
}
|
||||
if (hour === 1 && !increment) {
|
||||
return {
|
||||
value: 12
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (hour === 23 && increment) {
|
||||
return {
|
||||
value: 0
|
||||
};
|
||||
}
|
||||
if (hour === 0 && !increment) {
|
||||
return {
|
||||
value: 23
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
value: hour + (increment ? 1 : -1)
|
||||
};
|
||||
}
|
||||
export function incrementMinuteOrSecond(val, increment) {
|
||||
if (val === 59 && increment) return 0;
|
||||
if (val === 0 && !increment) return 59;
|
||||
return val + (increment ? 1 : -1);
|
||||
}
|
||||
//# sourceMappingURL=util.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"util.js","names":["pad","n","length","String","padStart","convert24to12","hour","convert12to24","period","extractInteger","v","digits","replaceAll","Number","incrementHour","increment","value","togglePeriod","incrementMinuteOrSecond","val"],"sources":["../../../src/components/VTimePicker/util.ts"],"sourcesContent":["// Types\nimport type { Period } from './shared'\n\nexport function pad (n: string | number, length = 2) {\n return String(n).padStart(length, '0')\n}\n\nexport function convert24to12 (hour: number) {\n return hour ? ((hour - 1) % 12 + 1) : 12\n}\n\nexport function convert12to24 (hour: number, period: Period) {\n return hour % 12 + (period === 'pm' ? 12 : 0)\n}\n\nexport function extractInteger (v: string): number | null {\n const digits = v.replaceAll(/\\D/g, '')\n return digits.length > 0\n ? Number(digits)\n : null\n}\n\nexport function incrementHour (hour: number, increment: boolean, period: Period | null) {\n if (period) {\n if (hour === 12 && increment) { return { value: 1 } }\n if (hour === 11 && increment) { return { value: 12, togglePeriod: true } }\n if (hour === 12 && !increment) { return { value: 11, togglePeriod: true } }\n if (hour === 1 && !increment) { return { value: 12 } }\n } else {\n if (hour === 23 && increment) { return { value: 0 } }\n if (hour === 0 && !increment) { return { value: 23 } }\n }\n return { value: hour + (increment ? 1 : -1) }\n}\n\nexport function incrementMinuteOrSecond (val: number, increment: boolean) {\n if (val === 59 && increment) return 0\n if (val === 0 && !increment) return 59\n return val + (increment ? 1 : -1)\n}\n"],"mappings":"AAAA;;AAGA,OAAO,SAASA,GAAGA,CAAEC,CAAkB,EAAEC,MAAM,GAAG,CAAC,EAAE;EACnD,OAAOC,MAAM,CAACF,CAAC,CAAC,CAACG,QAAQ,CAACF,MAAM,EAAE,GAAG,CAAC;AACxC;AAEA,OAAO,SAASG,aAAaA,CAAEC,IAAY,EAAE;EAC3C,OAAOA,IAAI,GAAI,CAACA,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,GAAI,EAAE;AAC1C;AAEA,OAAO,SAASC,aAAaA,CAAED,IAAY,EAAEE,MAAc,EAAE;EAC3D,OAAOF,IAAI,GAAG,EAAE,IAAIE,MAAM,KAAK,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC;AAC/C;AAEA,OAAO,SAASC,cAAcA,CAAEC,CAAS,EAAiB;EACxD,MAAMC,MAAM,GAAGD,CAAC,CAACE,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC;EACtC,OAAOD,MAAM,CAACT,MAAM,GAAG,CAAC,GACpBW,MAAM,CAACF,MAAM,CAAC,GACd,IAAI;AACV;AAEA,OAAO,SAASG,aAAaA,CAAER,IAAY,EAAES,SAAkB,EAAEP,MAAqB,EAAE;EACtF,IAAIA,MAAM,EAAE;IACV,IAAIF,IAAI,KAAK,EAAE,IAAIS,SAAS,EAAE;MAAE,OAAO;QAAEC,KAAK,EAAE;MAAE,CAAC;IAAC;IACpD,IAAIV,IAAI,KAAK,EAAE,IAAIS,SAAS,EAAE;MAAE,OAAO;QAAEC,KAAK,EAAE,EAAE;QAAEC,YAAY,EAAE;MAAK,CAAC;IAAC;IACzE,IAAIX,IAAI,KAAK,EAAE,IAAI,CAACS,SAAS,EAAE;MAAE,OAAO;QAAEC,KAAK,EAAE,EAAE;QAAEC,YAAY,EAAE;MAAK,CAAC;IAAC;IAC1E,IAAIX,IAAI,KAAK,CAAC,IAAI,CAACS,SAAS,EAAE;MAAE,OAAO;QAAEC,KAAK,EAAE;MAAG,CAAC;IAAC;EACvD,CAAC,MAAM;IACL,IAAIV,IAAI,KAAK,EAAE,IAAIS,SAAS,EAAE;MAAE,OAAO;QAAEC,KAAK,EAAE;MAAE,CAAC;IAAC;IACpD,IAAIV,IAAI,KAAK,CAAC,IAAI,CAACS,SAAS,EAAE;MAAE,OAAO;QAAEC,KAAK,EAAE;MAAG,CAAC;IAAC;EACvD;EACA,OAAO;IAAEA,KAAK,EAAEV,IAAI,IAAIS,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC;EAAE,CAAC;AAC/C;AAEA,OAAO,SAASG,uBAAuBA,CAAEC,GAAW,EAAEJ,SAAkB,EAAE;EACxE,IAAII,GAAG,KAAK,EAAE,IAAIJ,SAAS,EAAE,OAAO,CAAC;EACrC,IAAII,GAAG,KAAK,CAAC,IAAI,CAACJ,SAAS,EAAE,OAAO,EAAE;EACtC,OAAOI,GAAG,IAAIJ,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACnC","ignoreList":[]}
|
||||
Reference in New Issue
Block a user