routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+60
@@ -0,0 +1,60 @@
|
||||
@layer vuetify-components {
|
||||
.v-slider .v-slider__container input {
|
||||
cursor: default;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
display: none;
|
||||
}
|
||||
.v-slider > .v-input__append,
|
||||
.v-slider > .v-input__prepend {
|
||||
padding: 0;
|
||||
}
|
||||
.v-slider__container {
|
||||
position: relative;
|
||||
min-height: inherit;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.v-input--disabled .v-slider__container {
|
||||
opacity: var(--v-disabled-opacity);
|
||||
}
|
||||
.v-input--error:not(.v-input--disabled) .v-slider__container {
|
||||
color: rgb(var(--v-theme-error));
|
||||
}
|
||||
.v-slider.v-input--horizontal {
|
||||
align-items: center;
|
||||
}
|
||||
.v-slider.v-input--horizontal > .v-input__prepend {
|
||||
margin-inline-end: 8px;
|
||||
}
|
||||
.v-slider.v-input--horizontal > .v-input__append {
|
||||
margin-inline-start: 8px;
|
||||
}
|
||||
.v-slider.v-input--horizontal > .v-input__control {
|
||||
margin-inline: 8px 8px;
|
||||
min-height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.v-slider.v-input--vertical {
|
||||
justify-content: center;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.v-slider.v-input--vertical > .v-input__control {
|
||||
min-height: 300px;
|
||||
}
|
||||
.v-slider.v-input--disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
.v-slider--has-labels > .v-input__control {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.v-slider__label {
|
||||
margin-inline-end: 12px;
|
||||
}
|
||||
}
|
||||
+1999
File diff suppressed because it is too large
Load Diff
+162
@@ -0,0 +1,162 @@
|
||||
import { Fragment as _Fragment, createVNode as _createVNode, createElementVNode as _createElementVNode, mergeProps as _mergeProps } from "vue";
|
||||
// Styles
|
||||
import "./VSlider.css";
|
||||
|
||||
// Components
|
||||
import { VSliderThumb } from "./VSliderThumb.js";
|
||||
import { VSliderTrack } from "./VSliderTrack.js";
|
||||
import { makeVInputProps, VInput } from "../VInput/VInput.js";
|
||||
import { VLabel } from "../VLabel/index.js"; // Composables
|
||||
import { makeSliderProps, useSlider, useSteps } from "./slider.js";
|
||||
import { makeFocusProps, useFocus } from "../../composables/focus.js";
|
||||
import { forwardRefs } from "../../composables/forwardRefs.js";
|
||||
import { useRtl } from "../../composables/locale.js";
|
||||
import { useProxiedModel } from "../../composables/proxiedModel.js"; // Utilities
|
||||
import { computed, ref } from 'vue';
|
||||
import { filterInputAttrs, genericComponent, propsFactory, useRender } from "../../util/index.js"; // Types
|
||||
export const makeVSliderProps = propsFactory({
|
||||
...makeFocusProps(),
|
||||
...makeSliderProps(),
|
||||
...makeVInputProps(),
|
||||
modelValue: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
}
|
||||
}, 'VSlider');
|
||||
export const VSlider = genericComponent()({
|
||||
name: 'VSlider',
|
||||
inheritAttrs: false,
|
||||
props: makeVSliderProps(),
|
||||
emits: {
|
||||
'update:focused': value => true,
|
||||
'update:modelValue': v => true,
|
||||
start: value => true,
|
||||
end: value => true
|
||||
},
|
||||
setup(props, {
|
||||
slots,
|
||||
emit,
|
||||
attrs
|
||||
}) {
|
||||
const thumbContainerRef = ref();
|
||||
const inputRef = ref();
|
||||
const {
|
||||
rtlClasses
|
||||
} = useRtl();
|
||||
const steps = useSteps(props);
|
||||
const model = useProxiedModel(props, 'modelValue', undefined, value => {
|
||||
return steps.roundValue(value == null ? steps.min.value : value);
|
||||
});
|
||||
const {
|
||||
min,
|
||||
max,
|
||||
mousePressed,
|
||||
roundValue,
|
||||
onSliderMousedown,
|
||||
onSliderTouchstart,
|
||||
trackContainerRef,
|
||||
position,
|
||||
hasLabels,
|
||||
disabled,
|
||||
readonly,
|
||||
noKeyboard
|
||||
} = useSlider({
|
||||
props,
|
||||
steps,
|
||||
onSliderStart: () => {
|
||||
if (!disabled.value && !readonly.value) {
|
||||
emit('start', model.value);
|
||||
}
|
||||
},
|
||||
onSliderEnd: ({
|
||||
value
|
||||
}) => {
|
||||
const roundedValue = roundValue(value);
|
||||
if (!disabled.value && !readonly.value) {
|
||||
model.value = roundedValue;
|
||||
}
|
||||
emit('end', roundedValue);
|
||||
},
|
||||
onSliderMove: ({
|
||||
value
|
||||
}) => {
|
||||
if (!disabled.value && !readonly.value) {
|
||||
model.value = roundValue(value);
|
||||
}
|
||||
},
|
||||
getActiveThumb: () => thumbContainerRef.value?.$el
|
||||
});
|
||||
const {
|
||||
isFocused,
|
||||
focus,
|
||||
blur
|
||||
} = useFocus(props);
|
||||
const trackStop = computed(() => position(model.value));
|
||||
useRender(() => {
|
||||
const inputProps = VInput.filterProps(props);
|
||||
const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
|
||||
const hasPrepend = !!(props.label || slots.label || slots.prepend);
|
||||
return _createVNode(VInput, _mergeProps({
|
||||
"ref": inputRef,
|
||||
"class": ['v-slider', {
|
||||
'v-slider--has-labels': !!slots['tick-label'] || hasLabels.value,
|
||||
'v-slider--focused': isFocused.value,
|
||||
'v-slider--pressed': mousePressed.value,
|
||||
'v-slider--disabled': disabled.value
|
||||
}, rtlClasses.value, props.class],
|
||||
"style": props.style
|
||||
}, inputProps, rootAttrs, {
|
||||
"focused": isFocused.value
|
||||
}), {
|
||||
...slots,
|
||||
prepend: hasPrepend ? slotProps => _createElementVNode(_Fragment, null, [slots.label?.(slotProps) ?? (props.label ? _createVNode(VLabel, {
|
||||
"id": slotProps.id.value,
|
||||
"class": "v-slider__label",
|
||||
"text": props.label
|
||||
}, null) : undefined), slots.prepend?.(slotProps)]) : undefined,
|
||||
default: ({
|
||||
id,
|
||||
messagesId
|
||||
}) => _createElementVNode("div", {
|
||||
"class": "v-slider__container",
|
||||
"onMousedown": !readonly.value ? onSliderMousedown : undefined,
|
||||
"onTouchstartPassive": !readonly.value ? onSliderTouchstart : undefined
|
||||
}, [_createElementVNode("input", {
|
||||
"id": id.value,
|
||||
"name": props.name || id.value,
|
||||
"disabled": disabled.value,
|
||||
"readonly": readonly.value,
|
||||
"tabindex": "-1",
|
||||
"value": model.value
|
||||
}, null), _createVNode(VSliderTrack, {
|
||||
"ref": trackContainerRef,
|
||||
"start": 0,
|
||||
"stop": trackStop.value
|
||||
}, {
|
||||
'tick-label': slots['tick-label']
|
||||
}), _createVNode(VSliderThumb, _mergeProps({
|
||||
"ref": thumbContainerRef,
|
||||
"aria-describedby": messagesId.value,
|
||||
"focused": isFocused.value,
|
||||
"noKeyboard": noKeyboard.value,
|
||||
"min": min.value,
|
||||
"max": max.value,
|
||||
"modelValue": model.value,
|
||||
"onUpdate:modelValue": v => model.value = v,
|
||||
"position": trackStop.value,
|
||||
"elevation": props.elevation,
|
||||
"onFocus": focus,
|
||||
"onBlur": blur,
|
||||
"ripple": props.ripple,
|
||||
"name": props.name
|
||||
}, inputAttrs), {
|
||||
'thumb-label': slots['thumb-label']
|
||||
})])
|
||||
});
|
||||
});
|
||||
return forwardRefs({
|
||||
focus: () => thumbContainerRef.value?.$el.focus()
|
||||
}, inputRef);
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=VSlider.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+71
@@ -0,0 +1,71 @@
|
||||
@use 'sass:map'
|
||||
@use 'sass:selector'
|
||||
@forward '../VInput/variables'
|
||||
@use '../../styles/settings'
|
||||
@use '../../styles/tools'
|
||||
@use './variables' as *
|
||||
@use '../VInput/variables' as *
|
||||
|
||||
@include tools.layer('components')
|
||||
// Block
|
||||
.v-slider
|
||||
.v-slider__container
|
||||
input
|
||||
cursor: default
|
||||
padding: 0
|
||||
width: 100%
|
||||
display: none
|
||||
|
||||
> .v-input__append,
|
||||
> .v-input__prepend
|
||||
padding: 0
|
||||
|
||||
// Elements
|
||||
.v-slider__container
|
||||
position: relative
|
||||
min-height: inherit
|
||||
width: 100%
|
||||
height: 100%
|
||||
display: flex
|
||||
justify-content: center
|
||||
align-items: center
|
||||
cursor: pointer
|
||||
|
||||
.v-input--disabled &
|
||||
opacity: var(--v-disabled-opacity)
|
||||
|
||||
.v-input--error:not(.v-input--disabled) &
|
||||
color: rgb(var(--v-theme-error))
|
||||
|
||||
// Modifiers
|
||||
.v-slider.v-input--horizontal
|
||||
align-items: center
|
||||
|
||||
> .v-input__prepend
|
||||
margin-inline-end: max(0px, calc($input-affix-margin-inside - $slider-horizontal-start))
|
||||
|
||||
> .v-input__append
|
||||
margin-inline-start: max(0px, calc($input-affix-margin-inside - $slider-horizontal-end))
|
||||
|
||||
> .v-input__control
|
||||
margin-inline: $slider-horizontal-start $slider-horizontal-end
|
||||
min-height: $slider-horizontal-min-height
|
||||
display: flex
|
||||
align-items: center
|
||||
|
||||
.v-slider.v-input--vertical
|
||||
justify-content: center
|
||||
margin-top: $slider-vertical-margin-top
|
||||
margin-bottom: $slider-vertical-margin-bottom
|
||||
|
||||
> .v-input__control
|
||||
min-height: $slider-vertical-min-height
|
||||
|
||||
.v-slider.v-input--disabled
|
||||
pointer-events: none
|
||||
|
||||
.v-slider--has-labels > .v-input__control
|
||||
margin-bottom: $slider-tick-label-margin-top * .5
|
||||
|
||||
.v-slider__label
|
||||
margin-inline-end: $slider-label-margin-end
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
@layer vuetify-components {
|
||||
.v-slider-thumb {
|
||||
touch-action: none;
|
||||
color: rgb(var(--v-theme-surface-variant));
|
||||
}
|
||||
.v-input--error:not(.v-input--disabled) .v-slider-thumb {
|
||||
color: inherit;
|
||||
}
|
||||
.v-slider-thumb__label {
|
||||
background: color-mix(in srgb, rgb(var(--v-theme-surface-variant)) 70%, transparent);
|
||||
color: rgb(var(--v-theme-on-surface-variant));
|
||||
}
|
||||
.v-slider-thumb__label > .v-slider-thumb__label-wedge {
|
||||
background: inherit;
|
||||
}
|
||||
.v-slider-thumb {
|
||||
outline: none;
|
||||
position: absolute;
|
||||
transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1);
|
||||
}
|
||||
.v-slider-thumb__surface {
|
||||
cursor: pointer;
|
||||
width: var(--v-slider-thumb-size);
|
||||
height: var(--v-slider-thumb-size);
|
||||
border-radius: 50%;
|
||||
user-select: none;
|
||||
background-color: currentColor;
|
||||
}
|
||||
@media (forced-colors: active) {
|
||||
.v-slider-thumb__surface {
|
||||
background-color: highlight;
|
||||
}
|
||||
}
|
||||
.v-slider-thumb__surface::before {
|
||||
transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
content: "";
|
||||
color: inherit;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
}
|
||||
.v-slider-thumb__surface::after {
|
||||
content: "";
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.v-slider-thumb__label-container {
|
||||
position: absolute;
|
||||
transition: 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||
}
|
||||
.v-slider-thumb__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.6875rem;
|
||||
min-width: 35px;
|
||||
height: 25px;
|
||||
border-radius: 4px;
|
||||
padding: 6px;
|
||||
position: absolute;
|
||||
user-select: none;
|
||||
transition: 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||
}
|
||||
.v-slider-thumb__label > .v-slider-thumb__label-wedge {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
position: absolute;
|
||||
}
|
||||
.v-slider-thumb__ripple {
|
||||
position: absolute;
|
||||
left: calc(var(--v-slider-thumb-size) / -2);
|
||||
top: calc(var(--v-slider-thumb-size) / -2);
|
||||
width: calc(var(--v-slider-thumb-size) * 2);
|
||||
height: calc(var(--v-slider-thumb-size) * 2);
|
||||
background: inherit;
|
||||
}
|
||||
.v-slider.v-input--horizontal .v-slider-thumb {
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
inset-inline-start: calc(var(--v-slider-thumb-position) - var(--v-slider-thumb-size) / 2);
|
||||
}
|
||||
.v-slider.v-input--horizontal .v-slider-thumb__label-container {
|
||||
left: calc(var(--v-slider-thumb-size) / 2);
|
||||
top: 0;
|
||||
}
|
||||
.v-slider.v-input--horizontal .v-slider-thumb__label {
|
||||
bottom: calc(var(--v-slider-thumb-size) / 2);
|
||||
}
|
||||
.v-locale--is-ltr.v-slider.v-input--horizontal .v-slider-thumb__label, .v-locale--is-ltr .v-slider.v-input--horizontal .v-slider-thumb__label {
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.v-locale--is-rtl.v-slider.v-input--horizontal .v-slider-thumb__label, .v-locale--is-rtl .v-slider.v-input--horizontal .v-slider-thumb__label {
|
||||
transform: translateX(50%);
|
||||
}
|
||||
.v-slider.v-input--horizontal .v-slider-thumb__label > .v-slider-thumb__label-wedge {
|
||||
clip-path: polygon(50% 100%, 0 50%, 100% 50%);
|
||||
bottom: calc(-6px + 0.2px);
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-thumb {
|
||||
top: calc(var(--v-slider-thumb-position) - var(--v-slider-thumb-size) / 2);
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-thumb__label-container {
|
||||
top: calc(var(--v-slider-thumb-size) / 2);
|
||||
right: 0;
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-thumb__label {
|
||||
top: -12.5px;
|
||||
left: calc(var(--v-slider-thumb-size) / 2);
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-thumb__label > .v-slider-thumb__label-wedge {
|
||||
clip-path: polygon(0 50%, 50% 0, 50% 100%);
|
||||
left: calc(-6px + 0.2px);
|
||||
}
|
||||
.v-slider-thumb--focused .v-slider-thumb__surface::before {
|
||||
transform: scale(2);
|
||||
opacity: var(--v-focus-opacity);
|
||||
}
|
||||
.v-slider-thumb--pressed {
|
||||
transition: none;
|
||||
}
|
||||
.v-slider-thumb--pressed .v-slider-thumb__surface::before {
|
||||
opacity: var(--v-pressed-opacity);
|
||||
}
|
||||
@media (hover: hover) {
|
||||
.v-slider-thumb:hover .v-slider-thumb__surface::before {
|
||||
transform: scale(2);
|
||||
}
|
||||
.v-slider-thumb:hover:not(.v-slider-thumb--focused) .v-slider-thumb__surface::before {
|
||||
opacity: var(--v-hover-opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
|
||||
import type { PropType } from 'vue';
|
||||
import type { RippleDirectiveBinding } from '../../directives/ripple/index.js';
|
||||
export type VSliderThumbSlots = {
|
||||
'thumb-label': {
|
||||
modelValue: number;
|
||||
};
|
||||
};
|
||||
export declare const makeVSliderThumbProps: <Defaults extends {
|
||||
class?: unknown;
|
||||
style?: unknown;
|
||||
focused?: unknown;
|
||||
max?: unknown;
|
||||
min?: unknown;
|
||||
modelValue?: unknown;
|
||||
position?: unknown;
|
||||
ripple?: unknown;
|
||||
name?: unknown;
|
||||
noKeyboard?: unknown;
|
||||
} = {}>(defaults?: Defaults | undefined) => {
|
||||
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>;
|
||||
};
|
||||
focused: unknown extends Defaults["focused"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["focused"] ? boolean : boolean | Defaults["focused"]>;
|
||||
default: unknown extends Defaults["focused"] ? boolean : boolean | Defaults["focused"];
|
||||
};
|
||||
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"];
|
||||
};
|
||||
modelValue: unknown extends Defaults["modelValue"] ? {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
} : Omit<{
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["modelValue"] ? number : number | Defaults["modelValue"]>;
|
||||
default: unknown extends Defaults["modelValue"] ? number : number | Defaults["modelValue"];
|
||||
};
|
||||
position: unknown extends Defaults["position"] ? {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
} : Omit<{
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["position"] ? number : number | Defaults["position"]>;
|
||||
default: unknown extends Defaults["position"] ? number : number | Defaults["position"];
|
||||
};
|
||||
ripple: unknown extends Defaults["ripple"] ? {
|
||||
type: PropType<RippleDirectiveBinding['value']>;
|
||||
default: boolean;
|
||||
} : Omit<{
|
||||
type: PropType<RippleDirectiveBinding['value']>;
|
||||
default: boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["ripple"] ? boolean | {
|
||||
class?: string;
|
||||
keys?: string[];
|
||||
} | undefined : boolean | {
|
||||
class?: string;
|
||||
keys?: string[];
|
||||
} | Defaults["ripple"] | undefined>;
|
||||
default: unknown extends Defaults["ripple"] ? boolean | {
|
||||
class?: string;
|
||||
keys?: string[];
|
||||
} | undefined : Defaults["ripple"] | NonNullable<boolean | {
|
||||
class?: string;
|
||||
keys?: string[];
|
||||
} | undefined>;
|
||||
};
|
||||
name: unknown extends Defaults["name"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["name"] ? string : string | Defaults["name"]>;
|
||||
default: unknown extends Defaults["name"] ? string : string | Defaults["name"];
|
||||
};
|
||||
noKeyboard: unknown extends Defaults["noKeyboard"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["noKeyboard"] ? boolean : boolean | Defaults["noKeyboard"]>;
|
||||
default: unknown extends Defaults["noKeyboard"] ? boolean : boolean | Defaults["noKeyboard"];
|
||||
};
|
||||
};
|
||||
export declare const VSliderThumb: {
|
||||
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<{
|
||||
style: string | false | import("vue").StyleValue[] | import("vue").CSSProperties | null;
|
||||
focused: boolean;
|
||||
max: number;
|
||||
min: number;
|
||||
modelValue: number;
|
||||
position: number;
|
||||
ripple: boolean | {
|
||||
class?: string;
|
||||
keys?: string[];
|
||||
};
|
||||
noKeyboard: boolean;
|
||||
} & {
|
||||
class?: any;
|
||||
name?: string | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
'thumb-label'?: ((arg: {
|
||||
modelValue: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | {} | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
'thumb-label'?: false | ((arg: {
|
||||
modelValue: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:thumb-label"?: false | ((arg: {
|
||||
modelValue: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
"onUpdate:modelValue"?: ((v: number) => any) | undefined;
|
||||
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
'update:modelValue': (v: number) => true;
|
||||
}, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, {
|
||||
style: import("vue").StyleValue;
|
||||
focused: boolean;
|
||||
ripple: boolean | {
|
||||
class?: string;
|
||||
keys?: string[];
|
||||
} | undefined;
|
||||
noKeyboard: boolean;
|
||||
}, true, {}, import("vue").SlotsType<Partial<{
|
||||
'thumb-label': (arg: {
|
||||
modelValue: number;
|
||||
}) => 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;
|
||||
focused: boolean;
|
||||
max: number;
|
||||
min: number;
|
||||
modelValue: number;
|
||||
position: number;
|
||||
ripple: boolean | {
|
||||
class?: string;
|
||||
keys?: string[];
|
||||
};
|
||||
noKeyboard: boolean;
|
||||
} & {
|
||||
class?: any;
|
||||
name?: string | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
'thumb-label'?: ((arg: {
|
||||
modelValue: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | {} | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
'thumb-label'?: false | ((arg: {
|
||||
modelValue: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:thumb-label"?: false | ((arg: {
|
||||
modelValue: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
"onUpdate:modelValue"?: ((v: number) => any) | undefined;
|
||||
}, {}, {}, {}, {}, {
|
||||
style: import("vue").StyleValue;
|
||||
focused: boolean;
|
||||
ripple: boolean | {
|
||||
class?: string;
|
||||
keys?: string[];
|
||||
} | undefined;
|
||||
noKeyboard: boolean;
|
||||
}>;
|
||||
__isFragment?: never;
|
||||
__isTeleport?: never;
|
||||
__isSuspense?: never;
|
||||
} & import("vue").ComponentOptionsBase<{
|
||||
style: string | false | import("vue").StyleValue[] | import("vue").CSSProperties | null;
|
||||
focused: boolean;
|
||||
max: number;
|
||||
min: number;
|
||||
modelValue: number;
|
||||
position: number;
|
||||
ripple: boolean | {
|
||||
class?: string;
|
||||
keys?: string[];
|
||||
};
|
||||
noKeyboard: boolean;
|
||||
} & {
|
||||
class?: any;
|
||||
name?: string | undefined;
|
||||
} & {
|
||||
$children?: {
|
||||
'thumb-label'?: ((arg: {
|
||||
modelValue: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | {} | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
'thumb-label'?: false | ((arg: {
|
||||
modelValue: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:thumb-label"?: false | ((arg: {
|
||||
modelValue: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} & {
|
||||
"onUpdate:modelValue"?: ((v: number) => any) | undefined;
|
||||
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
||||
'update:modelValue': (v: number) => true;
|
||||
}, string, {
|
||||
style: import("vue").StyleValue;
|
||||
focused: boolean;
|
||||
ripple: boolean | {
|
||||
class?: string;
|
||||
keys?: string[];
|
||||
} | undefined;
|
||||
noKeyboard: boolean;
|
||||
}, {}, string, import("vue").SlotsType<Partial<{
|
||||
'thumb-label': (arg: {
|
||||
modelValue: number;
|
||||
}) => 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<{
|
||||
class: PropType<import("../../composables/component.js").ClassValue>;
|
||||
style: {
|
||||
type: PropType<import("vue").StyleValue>;
|
||||
default: null;
|
||||
};
|
||||
focused: BooleanConstructor;
|
||||
max: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
min: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
modelValue: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
position: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
ripple: {
|
||||
type: PropType<RippleDirectiveBinding['value']>;
|
||||
default: boolean;
|
||||
};
|
||||
name: StringConstructor;
|
||||
noKeyboard: BooleanConstructor;
|
||||
}, import("vue").ExtractPropTypes<{
|
||||
class: PropType<import("../../composables/component.js").ClassValue>;
|
||||
style: {
|
||||
type: PropType<import("vue").StyleValue>;
|
||||
default: null;
|
||||
};
|
||||
focused: BooleanConstructor;
|
||||
max: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
min: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
modelValue: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
position: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
ripple: {
|
||||
type: PropType<RippleDirectiveBinding['value']>;
|
||||
default: boolean;
|
||||
};
|
||||
name: StringConstructor;
|
||||
noKeyboard: BooleanConstructor;
|
||||
}>>;
|
||||
export type VSliderThumb = InstanceType<typeof VSliderThumb>;
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
import { normalizeClass as _normalizeClass, normalizeStyle as _normalizeStyle, createElementVNode as _createElementVNode, withDirectives as _withDirectives, vShow as _vShow, createVNode as _createVNode } from "vue";
|
||||
// Styles
|
||||
import "./VSliderThumb.css";
|
||||
|
||||
// Components
|
||||
import { VSliderSymbol } from "./slider.js";
|
||||
import { VScaleTransition } from "../transitions/index.js"; // Composables
|
||||
import { useBackgroundColor, useTextColor } from "../../composables/color.js";
|
||||
import { makeComponentProps } from "../../composables/component.js";
|
||||
import { useElevation } from "../../composables/elevation.js";
|
||||
import { useRtl } from "../../composables/locale.js"; // Directives
|
||||
import vRipple from "../../directives/ripple/index.js"; // Utilities
|
||||
import { computed, inject, shallowRef, watch } from 'vue';
|
||||
import { convertToUnit, genericComponent, keyValues, propsFactory, useRender } from "../../util/index.js"; // Types
|
||||
export const makeVSliderThumbProps = propsFactory({
|
||||
focused: Boolean,
|
||||
max: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
modelValue: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
position: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
ripple: {
|
||||
type: [Boolean, Object],
|
||||
default: true
|
||||
},
|
||||
name: String,
|
||||
noKeyboard: Boolean,
|
||||
...makeComponentProps()
|
||||
}, 'VSliderThumb');
|
||||
export const VSliderThumb = genericComponent()({
|
||||
name: 'VSliderThumb',
|
||||
directives: {
|
||||
vRipple
|
||||
},
|
||||
props: makeVSliderThumbProps(),
|
||||
emits: {
|
||||
'update:modelValue': v => true
|
||||
},
|
||||
setup(props, {
|
||||
slots,
|
||||
emit
|
||||
}) {
|
||||
const slider = inject(VSliderSymbol);
|
||||
const {
|
||||
isRtl,
|
||||
rtlClasses
|
||||
} = useRtl();
|
||||
if (!slider) throw new Error('[Vuetify] v-slider-thumb must be used inside v-slider or v-range-slider');
|
||||
const {
|
||||
min,
|
||||
max,
|
||||
thumbColor,
|
||||
thumbLabelColor,
|
||||
step,
|
||||
disabled,
|
||||
thumbSize,
|
||||
thumbLabel,
|
||||
direction,
|
||||
isReversed,
|
||||
vertical,
|
||||
readonly,
|
||||
elevation,
|
||||
mousePressed,
|
||||
decimals,
|
||||
indexFromEnd
|
||||
} = slider;
|
||||
const isHovered = shallowRef(false);
|
||||
const isHidden = shallowRef(false);
|
||||
const elevationProps = computed(() => !disabled.value ? elevation.value : undefined);
|
||||
const {
|
||||
elevationClasses
|
||||
} = useElevation(elevationProps);
|
||||
const {
|
||||
textColorClasses,
|
||||
textColorStyles
|
||||
} = useTextColor(thumbColor);
|
||||
const {
|
||||
backgroundColorClasses,
|
||||
backgroundColorStyles
|
||||
} = useBackgroundColor(thumbLabelColor);
|
||||
const {
|
||||
pageup,
|
||||
pagedown,
|
||||
end,
|
||||
home,
|
||||
left,
|
||||
right,
|
||||
down,
|
||||
up
|
||||
} = keyValues;
|
||||
const relevantKeys = [pageup, pagedown, end, home, left, right, down, up];
|
||||
const multipliers = computed(() => {
|
||||
if (step.value) return [1, 2, 3];else return [1, 5, 10];
|
||||
});
|
||||
function parseKeydown(e, value) {
|
||||
if (props.noKeyboard || disabled.value) return;
|
||||
if (!relevantKeys.includes(e.key)) return;
|
||||
e.preventDefault();
|
||||
const _step = step.value || 0.1;
|
||||
const steps = (max.value - min.value) / _step;
|
||||
if ([left, right, down, up].includes(e.key)) {
|
||||
const increase = vertical.value ? [isRtl.value ? left : right, isReversed.value ? down : up] : indexFromEnd.value !== isRtl.value ? [left, up] : [right, up];
|
||||
const direction = increase.includes(e.key) ? 1 : -1;
|
||||
const multiplier = e.shiftKey ? 2 : e.ctrlKey ? 1 : 0;
|
||||
if (direction === -1 && value === max.value && !multiplier && !Number.isInteger(steps)) {
|
||||
value = value - steps % 1 * _step;
|
||||
} else {
|
||||
value = value + direction * _step * multipliers.value[multiplier];
|
||||
}
|
||||
} else if (e.key === home) {
|
||||
value = min.value;
|
||||
} else if (e.key === end) {
|
||||
value = max.value;
|
||||
} else {
|
||||
const direction = e.key === pagedown ? 1 : -1;
|
||||
value = value - direction * _step * (steps > 100 ? steps / 10 : 10);
|
||||
}
|
||||
return Math.max(props.min, Math.min(props.max, value));
|
||||
}
|
||||
function onKeydown(e) {
|
||||
const newValue = parseKeydown(e, props.modelValue);
|
||||
if (newValue != null) {
|
||||
isHidden.value = false;
|
||||
emit('update:modelValue', newValue);
|
||||
}
|
||||
}
|
||||
watch(() => props.focused, val => {
|
||||
if (val) {
|
||||
isHidden.value = false;
|
||||
}
|
||||
});
|
||||
useRender(() => {
|
||||
const positionPercentage = convertToUnit(indexFromEnd.value ? 100 - props.position : props.position, '%');
|
||||
const thumbLabelVisible = thumbLabel.value === 'always' || thumbLabel.value === true && props.focused || thumbLabel.value === 'hover' && (isHovered.value || props.focused && !isHidden.value);
|
||||
return _createElementVNode("div", {
|
||||
"class": _normalizeClass(['v-slider-thumb', {
|
||||
'v-slider-thumb--focused': props.focused,
|
||||
'v-slider-thumb--pressed': props.focused && mousePressed.value
|
||||
}, props.class, rtlClasses.value]),
|
||||
"style": _normalizeStyle([{
|
||||
'--v-slider-thumb-position': positionPercentage,
|
||||
'--v-slider-thumb-size': convertToUnit(thumbSize.value)
|
||||
}, props.style]),
|
||||
"role": "slider",
|
||||
"tabindex": disabled.value ? -1 : 0,
|
||||
"aria-label": props.name,
|
||||
"aria-valuemin": min.value,
|
||||
"aria-valuemax": max.value,
|
||||
"aria-valuenow": props.modelValue,
|
||||
"aria-readonly": !!readonly.value,
|
||||
"aria-orientation": direction.value,
|
||||
"onKeydown": !readonly.value ? onKeydown : undefined,
|
||||
"onMouseenter": () => {
|
||||
isHovered.value = true;
|
||||
},
|
||||
"onMouseleave": () => {
|
||||
isHovered.value = false;
|
||||
isHidden.value = true;
|
||||
}
|
||||
}, [_createElementVNode("div", {
|
||||
"class": _normalizeClass(['v-slider-thumb__surface', textColorClasses.value, elevationClasses.value]),
|
||||
"style": _normalizeStyle(textColorStyles.value)
|
||||
}, null), _withDirectives(_createElementVNode("div", {
|
||||
"class": _normalizeClass(['v-slider-thumb__ripple', textColorClasses.value]),
|
||||
"style": _normalizeStyle(textColorStyles.value)
|
||||
}, null), [[vRipple, props.ripple, null, {
|
||||
circle: true,
|
||||
center: true
|
||||
}]]), _createVNode(VScaleTransition, {
|
||||
"origin": "bottom center"
|
||||
}, {
|
||||
default: () => [_withDirectives(_createElementVNode("div", {
|
||||
"class": "v-slider-thumb__label-container"
|
||||
}, [_createElementVNode("div", {
|
||||
"class": _normalizeClass(['v-slider-thumb__label', backgroundColorClasses.value]),
|
||||
"style": _normalizeStyle(backgroundColorStyles.value)
|
||||
}, [_createElementVNode("div", null, [slots['thumb-label']?.({
|
||||
modelValue: props.modelValue
|
||||
}) ?? props.modelValue.toFixed(step.value ? decimals.value : 1)]), _createElementVNode("div", {
|
||||
"class": "v-slider-thumb__label-wedge"
|
||||
}, null)])]), [[_vShow, thumbLabelVisible]])]
|
||||
})]);
|
||||
});
|
||||
return {};
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=VSliderThumb.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+153
@@ -0,0 +1,153 @@
|
||||
@use 'sass:map'
|
||||
@use 'sass:selector'
|
||||
@use 'sass:math'
|
||||
@use '../../styles/settings'
|
||||
@use '../../styles/tools'
|
||||
@use './variables' as *
|
||||
|
||||
@include tools.layer('components')
|
||||
// Theme
|
||||
.v-slider-thumb
|
||||
touch-action: none
|
||||
color: rgb(var(--v-theme-surface-variant))
|
||||
|
||||
.v-input--error:not(.v-input--disabled) &
|
||||
color: inherit
|
||||
|
||||
.v-slider-thumb__label
|
||||
background: tools.theme-color('surface-variant', .7)
|
||||
color: rgb(var(--v-theme-on-surface-variant))
|
||||
|
||||
> .v-slider-thumb__label-wedge
|
||||
background: inherit
|
||||
|
||||
// Block
|
||||
.v-slider-thumb
|
||||
outline: none
|
||||
position: absolute
|
||||
transition: $slider-transition
|
||||
|
||||
.v-slider-thumb__surface
|
||||
cursor: pointer
|
||||
width: var(--v-slider-thumb-size)
|
||||
height: var(--v-slider-thumb-size)
|
||||
border-radius: $slider-thumb-border-radius
|
||||
user-select: none
|
||||
background-color: currentColor
|
||||
|
||||
@media (forced-colors: active)
|
||||
background-color: highlight
|
||||
|
||||
&::before
|
||||
transition: 0.3s settings.$standard-easing
|
||||
content: ''
|
||||
color: inherit
|
||||
top: 0
|
||||
left: 0
|
||||
width: 100%
|
||||
height: 100%
|
||||
border-radius: $slider-thumb-border-radius
|
||||
background: currentColor
|
||||
position: absolute
|
||||
pointer-events: none
|
||||
opacity: 0
|
||||
|
||||
&::after
|
||||
content: ''
|
||||
width: $slider-thumb-touch-size
|
||||
height: $slider-thumb-touch-size
|
||||
position: absolute
|
||||
top: 50%
|
||||
left: 50%
|
||||
transform: translate(-50%, -50%)
|
||||
|
||||
.v-slider-thumb__label-container
|
||||
position: absolute
|
||||
transition: $slider-thumb-label-transition
|
||||
|
||||
.v-slider-thumb__label
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
font-size: $slider-thumb-label-font-size
|
||||
min-width: $slider-thumb-label-min-width
|
||||
height: $slider-thumb-label-height
|
||||
border-radius: $slider-thumb-label-border-radius
|
||||
padding: $slider-thumb-label-padding
|
||||
position: absolute
|
||||
user-select: none
|
||||
transition: $slider-thumb-label-transition
|
||||
|
||||
> .v-slider-thumb__label-wedge
|
||||
width: $slider-thumb-label-wedge-size * 2
|
||||
height: $slider-thumb-label-wedge-size * 2
|
||||
position: absolute
|
||||
|
||||
.v-slider-thumb__ripple
|
||||
position: absolute
|
||||
left: calc(var(--v-slider-thumb-size) / -2)
|
||||
top: calc(var(--v-slider-thumb-size) / -2)
|
||||
width: calc(var(--v-slider-thumb-size) * 2)
|
||||
height: calc(var(--v-slider-thumb-size) * 2)
|
||||
background: inherit
|
||||
|
||||
// Horizontal
|
||||
.v-slider.v-input--horizontal
|
||||
.v-slider-thumb
|
||||
top: 50%
|
||||
transform: translateY(-50%)
|
||||
inset-inline-start: calc(var(--v-slider-thumb-position) - var(--v-slider-thumb-size) / 2)
|
||||
|
||||
.v-slider-thumb__label-container
|
||||
left: calc(var(--v-slider-thumb-size) / 2)
|
||||
top: 0
|
||||
|
||||
.v-slider-thumb__label
|
||||
bottom: $slider-thumb-label-offset
|
||||
|
||||
@include tools.ltr()
|
||||
transform: translateX(-50%)
|
||||
@include tools.rtl()
|
||||
transform: translateX(50%)
|
||||
|
||||
> .v-slider-thumb__label-wedge
|
||||
clip-path: polygon(50% 100%, 0 50%, 100% 50%)
|
||||
bottom: calc(#{-$slider-thumb-label-wedge-size} + 0.2px)
|
||||
|
||||
// Vertical
|
||||
.v-slider.v-input--vertical
|
||||
.v-slider-thumb
|
||||
top: calc(var(--v-slider-thumb-position) - var(--v-slider-thumb-size) / 2)
|
||||
|
||||
.v-slider-thumb__label-container
|
||||
top: calc(var(--v-slider-thumb-size) / 2)
|
||||
right: 0
|
||||
|
||||
.v-slider-thumb__label
|
||||
top: math.div($slider-thumb-label-height, -2)
|
||||
left: $slider-thumb-label-offset
|
||||
|
||||
> .v-slider-thumb__label-wedge
|
||||
clip-path: polygon(0 50%, 50% 0, 50% 100%)
|
||||
left: calc(#{-$slider-thumb-label-wedge-size} + 0.2px)
|
||||
|
||||
// Modifiers
|
||||
.v-slider-thumb--focused
|
||||
.v-slider-thumb__surface::before
|
||||
transform: scale(2)
|
||||
opacity: $slider-thumb-focus-opacity
|
||||
|
||||
.v-slider-thumb--pressed
|
||||
transition: none
|
||||
|
||||
.v-slider-thumb__surface::before
|
||||
opacity: $slider-thumb-pressed-opacity
|
||||
|
||||
@media (hover: hover)
|
||||
.v-slider-thumb:hover
|
||||
.v-slider-thumb__surface::before
|
||||
transform: scale(2)
|
||||
|
||||
.v-slider-thumb:hover:not(.v-slider-thumb--focused)
|
||||
.v-slider-thumb__surface::before
|
||||
opacity: $slider-thumb-hover-opacity
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
@layer vuetify-components {
|
||||
.v-slider-track__background {
|
||||
background-color: rgb(var(--v-theme-surface-variant));
|
||||
}
|
||||
@media (forced-colors: active) {
|
||||
.v-slider-track__background {
|
||||
background-color: highlight;
|
||||
}
|
||||
}
|
||||
.v-slider-track__fill {
|
||||
background-color: rgb(var(--v-theme-surface-variant));
|
||||
}
|
||||
@media (forced-colors: active) {
|
||||
.v-slider-track__fill {
|
||||
background-color: highlight;
|
||||
}
|
||||
}
|
||||
.v-slider-track__tick {
|
||||
background-color: rgb(var(--v-theme-surface-variant));
|
||||
}
|
||||
.v-slider-track__tick--filled {
|
||||
background-color: rgb(var(--v-theme-surface-light));
|
||||
}
|
||||
.v-slider-track {
|
||||
border-radius: 6px;
|
||||
}
|
||||
@media (forced-colors: active) {
|
||||
.v-slider-track {
|
||||
border: thin solid buttontext;
|
||||
}
|
||||
}
|
||||
.v-slider-track__background, .v-slider-track__fill {
|
||||
position: absolute;
|
||||
transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1);
|
||||
border-radius: inherit;
|
||||
}
|
||||
.v-slider--pressed .v-slider-track__background, .v-slider--pressed .v-slider-track__fill {
|
||||
transition: none;
|
||||
}
|
||||
.v-input--error:not(.v-input--disabled) .v-slider-track__background, .v-input--error:not(.v-input--disabled) .v-slider-track__fill {
|
||||
background-color: currentColor;
|
||||
}
|
||||
.v-slider-track__ticks {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.v-slider-track__tick {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
transition: 0.2s opacity cubic-bezier(0.4, 0, 0.2, 1);
|
||||
border-radius: 2px;
|
||||
width: var(--v-slider-tick-size);
|
||||
height: var(--v-slider-tick-size);
|
||||
transform: translate(calc(var(--v-slider-tick-size) / -2), calc(var(--v-slider-tick-size) / -2));
|
||||
}
|
||||
.v-locale--is-ltr.v-slider-track__tick--first .v-slider-track__tick-label, .v-locale--is-ltr .v-slider-track__tick--first .v-slider-track__tick-label {
|
||||
transform: none;
|
||||
}
|
||||
.v-locale--is-rtl.v-slider-track__tick--first .v-slider-track__tick-label, .v-locale--is-rtl .v-slider-track__tick--first .v-slider-track__tick-label {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
.v-locale--is-ltr.v-slider-track__tick--last .v-slider-track__tick-label, .v-locale--is-ltr .v-slider-track__tick--last .v-slider-track__tick-label {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
.v-locale--is-rtl.v-slider-track__tick--last .v-slider-track__tick-label, .v-locale--is-rtl .v-slider-track__tick--last .v-slider-track__tick-label {
|
||||
transform: none;
|
||||
}
|
||||
.v-slider-track__tick-label {
|
||||
position: absolute;
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.v-slider.v-input--horizontal .v-slider-track {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: calc(var(--v-slider-track-size) + 2px);
|
||||
touch-action: pan-y;
|
||||
}
|
||||
.v-slider.v-input--horizontal .v-slider-track__background {
|
||||
height: var(--v-slider-track-size);
|
||||
}
|
||||
.v-slider.v-input--horizontal .v-slider-track__fill {
|
||||
height: inherit;
|
||||
}
|
||||
.v-slider.v-input--horizontal .v-slider-track__tick {
|
||||
margin-top: calc(calc(var(--v-slider-track-size) + 2px) / 2);
|
||||
}
|
||||
.v-locale--is-rtl.v-slider.v-input--horizontal .v-slider-track__tick, .v-locale--is-rtl .v-slider.v-input--horizontal .v-slider-track__tick {
|
||||
transform: translate(calc(var(--v-slider-tick-size) / 2), calc(var(--v-slider-tick-size) / -2));
|
||||
}
|
||||
.v-slider.v-input--horizontal .v-slider-track__tick .v-slider-track__tick-label {
|
||||
margin-top: calc(var(--v-slider-track-size) / 2 + 8px);
|
||||
}
|
||||
.v-locale--is-ltr.v-slider.v-input--horizontal .v-slider-track__tick .v-slider-track__tick-label, .v-locale--is-ltr .v-slider.v-input--horizontal .v-slider-track__tick .v-slider-track__tick-label {
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.v-locale--is-rtl.v-slider.v-input--horizontal .v-slider-track__tick .v-slider-track__tick-label, .v-locale--is-rtl .v-slider.v-input--horizontal .v-slider-track__tick .v-slider-track__tick-label {
|
||||
transform: translateX(50%);
|
||||
}
|
||||
.v-slider.v-input--horizontal .v-slider-track__tick--first {
|
||||
margin-inline-start: calc(var(--v-slider-tick-size) + 1px);
|
||||
}
|
||||
.v-locale--is-ltr.v-slider.v-input--horizontal .v-slider-track__tick--first .v-slider-track__tick-label, .v-locale--is-ltr .v-slider.v-input--horizontal .v-slider-track__tick--first .v-slider-track__tick-label {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
.v-locale--is-rtl.v-slider.v-input--horizontal .v-slider-track__tick--first .v-slider-track__tick-label, .v-locale--is-rtl .v-slider.v-input--horizontal .v-slider-track__tick--first .v-slider-track__tick-label {
|
||||
transform: translateX(0%);
|
||||
}
|
||||
.v-slider.v-input--horizontal .v-slider-track__tick--last {
|
||||
margin-inline-start: calc(100% - var(--v-slider-tick-size) - 1px);
|
||||
}
|
||||
.v-locale--is-ltr.v-slider.v-input--horizontal .v-slider-track__tick--last .v-slider-track__tick-label, .v-locale--is-ltr .v-slider.v-input--horizontal .v-slider-track__tick--last .v-slider-track__tick-label {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
.v-locale--is-rtl.v-slider.v-input--horizontal .v-slider-track__tick--last .v-slider-track__tick-label, .v-locale--is-rtl .v-slider.v-input--horizontal .v-slider-track__tick--last .v-slider-track__tick-label {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-track {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: calc(var(--v-slider-track-size) + 2px);
|
||||
touch-action: pan-x;
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-track__background {
|
||||
width: var(--v-slider-track-size);
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-track__fill {
|
||||
width: inherit;
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-track__ticks {
|
||||
height: 100%;
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-track__tick {
|
||||
margin-inline-start: calc(calc(var(--v-slider-track-size) + 2px) / 2);
|
||||
transform: translate(calc(var(--v-slider-tick-size) / -2), calc(var(--v-slider-tick-size) / 2));
|
||||
}
|
||||
.v-locale--is-rtl.v-slider.v-input--vertical .v-slider-track__tick, .v-locale--is-rtl .v-slider.v-input--vertical .v-slider-track__tick {
|
||||
transform: translate(calc(var(--v-slider-tick-size) / 2), calc(var(--v-slider-tick-size) / 2));
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-track__tick--first {
|
||||
bottom: calc(0% + var(--v-slider-tick-size) + 1px);
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-track__tick--last {
|
||||
bottom: calc(100% - var(--v-slider-tick-size) - 1px);
|
||||
}
|
||||
.v-slider.v-input--vertical .v-slider-track__tick .v-slider-track__tick-label {
|
||||
margin-inline-start: calc(var(--v-slider-track-size) / 2 + 12px);
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.v-slider-track__ticks--always-show .v-slider-track__tick, .v-slider--focused .v-slider-track__tick {
|
||||
opacity: 1;
|
||||
}
|
||||
.v-slider-track__background--opacity {
|
||||
opacity: 0.38;
|
||||
}
|
||||
}
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
|
||||
import type { Tick } from './slider.js';
|
||||
export type VSliderTrackSlots = {
|
||||
'tick-label': {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
};
|
||||
};
|
||||
export declare const makeVSliderTrackProps: <Defaults extends {
|
||||
class?: unknown;
|
||||
style?: unknown;
|
||||
start?: unknown;
|
||||
stop?: unknown;
|
||||
} = {}>(defaults?: Defaults | undefined) => {
|
||||
class: unknown extends Defaults["class"] ? import("vue").PropType<any> : {
|
||||
type: import("vue").PropType<unknown extends Defaults["class"] ? any : any>;
|
||||
default: unknown extends Defaults["class"] ? any : any;
|
||||
};
|
||||
style: unknown extends Defaults["style"] ? {
|
||||
type: import("vue").PropType<import("vue").StyleValue>;
|
||||
default: null;
|
||||
} : Omit<{
|
||||
type: import("vue").PropType<import("vue").StyleValue>;
|
||||
default: null;
|
||||
}, "default" | "type"> & {
|
||||
type: import("vue").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>;
|
||||
};
|
||||
start: unknown extends Defaults["start"] ? {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
} : Omit<{
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
}, "default" | "type"> & {
|
||||
type: import("vue").PropType<unknown extends Defaults["start"] ? number : number | Defaults["start"]>;
|
||||
default: unknown extends Defaults["start"] ? number : number | Defaults["start"];
|
||||
};
|
||||
stop: unknown extends Defaults["stop"] ? {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
} : Omit<{
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
}, "default" | "type"> & {
|
||||
type: import("vue").PropType<unknown extends Defaults["stop"] ? number : number | Defaults["stop"]>;
|
||||
default: unknown extends Defaults["stop"] ? number : number | Defaults["stop"];
|
||||
};
|
||||
};
|
||||
export declare const VSliderTrack: {
|
||||
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<{
|
||||
style: string | false | import("vue").StyleValue[] | import("vue").CSSProperties | null;
|
||||
start: number;
|
||||
stop: number;
|
||||
} & {
|
||||
class?: any;
|
||||
} & {
|
||||
$children?: {
|
||||
'tick-label'?: ((arg: {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | {} | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
'tick-label'?: false | ((arg: {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:tick-label"?: false | ((arg: {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, {
|
||||
style: import("vue").StyleValue;
|
||||
}, true, {}, import("vue").SlotsType<Partial<{
|
||||
'tick-label': (arg: {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
}) => 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;
|
||||
start: number;
|
||||
stop: number;
|
||||
} & {
|
||||
class?: any;
|
||||
} & {
|
||||
$children?: {
|
||||
'tick-label'?: ((arg: {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | {} | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
'tick-label'?: false | ((arg: {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:tick-label"?: false | ((arg: {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
}, {}, {}, {}, {}, {
|
||||
style: import("vue").StyleValue;
|
||||
}>;
|
||||
__isFragment?: never;
|
||||
__isTeleport?: never;
|
||||
__isSuspense?: never;
|
||||
} & import("vue").ComponentOptionsBase<{
|
||||
style: string | false | import("vue").StyleValue[] | import("vue").CSSProperties | null;
|
||||
start: number;
|
||||
stop: number;
|
||||
} & {
|
||||
class?: any;
|
||||
} & {
|
||||
$children?: {
|
||||
'tick-label'?: ((arg: {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | {
|
||||
$stable?: boolean;
|
||||
} | {} | import("vue").VNodeChild;
|
||||
'v-slots'?: {
|
||||
'tick-label'?: false | ((arg: {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
} | undefined;
|
||||
} & {
|
||||
"v-slot:tick-label"?: false | ((arg: {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
}) => import("vue").VNodeChild) | undefined;
|
||||
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, {
|
||||
style: import("vue").StyleValue;
|
||||
}, {}, string, import("vue").SlotsType<Partial<{
|
||||
'tick-label': (arg: {
|
||||
tick: Tick;
|
||||
index: number;
|
||||
}) => 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<{
|
||||
class: import("vue").PropType<any>;
|
||||
style: {
|
||||
type: import("vue").PropType<import("vue").StyleValue>;
|
||||
default: null;
|
||||
};
|
||||
start: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
stop: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
}, import("vue").ExtractPropTypes<{
|
||||
class: import("vue").PropType<any>;
|
||||
style: {
|
||||
type: import("vue").PropType<import("vue").StyleValue>;
|
||||
default: null;
|
||||
};
|
||||
start: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
stop: {
|
||||
type: NumberConstructor;
|
||||
required: true;
|
||||
};
|
||||
}>>;
|
||||
export type VSliderTrack = InstanceType<typeof VSliderTrack>;
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
import { createElementVNode as _createElementVNode, normalizeClass as _normalizeClass, normalizeStyle as _normalizeStyle } from "vue";
|
||||
// Styles
|
||||
import "./VSliderTrack.css";
|
||||
|
||||
// Components
|
||||
import { VSliderSymbol } from "./slider.js"; // Composables
|
||||
import { useBackgroundColor } from "../../composables/color.js";
|
||||
import { makeComponentProps } from "../../composables/component.js";
|
||||
import { useRounded } from "../../composables/rounded.js"; // Utilities
|
||||
import { computed, inject } from 'vue';
|
||||
import { convertToUnit, genericComponent, propsFactory, useRender } from "../../util/index.js"; // Types
|
||||
export const makeVSliderTrackProps = propsFactory({
|
||||
start: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
stop: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
...makeComponentProps()
|
||||
}, 'VSliderTrack');
|
||||
export const VSliderTrack = genericComponent()({
|
||||
name: 'VSliderTrack',
|
||||
props: makeVSliderTrackProps(),
|
||||
emits: {},
|
||||
setup(props, {
|
||||
slots
|
||||
}) {
|
||||
const slider = inject(VSliderSymbol);
|
||||
if (!slider) throw new Error('[Vuetify] v-slider-track must be inside v-slider or v-range-slider');
|
||||
const {
|
||||
color,
|
||||
parsedTicks,
|
||||
rounded,
|
||||
showTicks,
|
||||
tickSize,
|
||||
trackColor,
|
||||
trackFillColor,
|
||||
trackSize,
|
||||
vertical,
|
||||
min,
|
||||
max,
|
||||
indexFromEnd
|
||||
} = slider;
|
||||
const {
|
||||
roundedClasses
|
||||
} = useRounded(rounded);
|
||||
const {
|
||||
backgroundColorClasses: trackFillColorClasses,
|
||||
backgroundColorStyles: trackFillColorStyles
|
||||
} = useBackgroundColor(trackFillColor);
|
||||
const {
|
||||
backgroundColorClasses: trackColorClasses,
|
||||
backgroundColorStyles: trackColorStyles
|
||||
} = useBackgroundColor(trackColor);
|
||||
const startDir = computed(() => `inset-${vertical.value ? 'block' : 'inline'}-${indexFromEnd.value ? 'end' : 'start'}`);
|
||||
const endDir = computed(() => vertical.value ? 'height' : 'width');
|
||||
const backgroundStyles = computed(() => {
|
||||
return {
|
||||
[startDir.value]: '0%',
|
||||
[endDir.value]: '100%'
|
||||
};
|
||||
});
|
||||
const trackFillWidth = computed(() => props.stop - props.start);
|
||||
const trackFillStyles = computed(() => {
|
||||
return {
|
||||
[startDir.value]: convertToUnit(props.start, '%'),
|
||||
[endDir.value]: convertToUnit(trackFillWidth.value, '%')
|
||||
};
|
||||
});
|
||||
const computedTicks = computed(() => {
|
||||
if (!showTicks.value) return [];
|
||||
const ticks = vertical.value ? parsedTicks.value.slice().reverse() : parsedTicks.value;
|
||||
return ticks.map((tick, index) => {
|
||||
const directionValue = tick.value !== min.value && tick.value !== max.value ? convertToUnit(tick.position, '%') : undefined;
|
||||
return _createElementVNode("div", {
|
||||
"key": tick.value,
|
||||
"class": _normalizeClass(['v-slider-track__tick', {
|
||||
'v-slider-track__tick--filled': tick.position >= props.start && tick.position <= props.stop,
|
||||
'v-slider-track__tick--first': tick.value === min.value,
|
||||
'v-slider-track__tick--last': tick.value === max.value
|
||||
}]),
|
||||
"style": {
|
||||
[startDir.value]: directionValue
|
||||
}
|
||||
}, [(tick.label || slots['tick-label']) && _createElementVNode("div", {
|
||||
"class": "v-slider-track__tick-label"
|
||||
}, [slots['tick-label']?.({
|
||||
tick,
|
||||
index
|
||||
}) ?? tick.label])]);
|
||||
});
|
||||
});
|
||||
useRender(() => {
|
||||
return _createElementVNode("div", {
|
||||
"class": _normalizeClass(['v-slider-track', roundedClasses.value, props.class]),
|
||||
"style": _normalizeStyle([{
|
||||
'--v-slider-track-size': convertToUnit(trackSize.value),
|
||||
'--v-slider-tick-size': convertToUnit(tickSize.value)
|
||||
}, props.style])
|
||||
}, [_createElementVNode("div", {
|
||||
"class": _normalizeClass(['v-slider-track__background', trackColorClasses.value, {
|
||||
'v-slider-track__background--opacity': !!color.value || !trackFillColor.value
|
||||
}]),
|
||||
"style": {
|
||||
...backgroundStyles.value,
|
||||
...trackColorStyles.value
|
||||
}
|
||||
}, null), _createElementVNode("div", {
|
||||
"class": _normalizeClass(['v-slider-track__fill', trackFillColorClasses.value]),
|
||||
"style": {
|
||||
...trackFillStyles.value,
|
||||
...trackFillColorStyles.value
|
||||
}
|
||||
}, null), showTicks.value && _createElementVNode("div", {
|
||||
"class": _normalizeClass(['v-slider-track__ticks', {
|
||||
'v-slider-track__ticks--always-show': showTicks.value === 'always'
|
||||
}])
|
||||
}, [computedTicks.value])]);
|
||||
});
|
||||
return {};
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=VSliderTrack.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+169
@@ -0,0 +1,169 @@
|
||||
@use 'sass:map'
|
||||
@use 'sass:selector'
|
||||
@use '../../styles/settings'
|
||||
@use '../../styles/tools'
|
||||
@use './variables' as *
|
||||
|
||||
@include tools.layer('components')
|
||||
// Theme
|
||||
.v-slider-track__background
|
||||
background-color: rgb(var(--v-theme-surface-variant))
|
||||
|
||||
@media (forced-colors: active)
|
||||
background-color: highlight
|
||||
|
||||
.v-slider-track__fill
|
||||
background-color: rgb(var(--v-theme-surface-variant))
|
||||
|
||||
@media (forced-colors: active)
|
||||
background-color: highlight
|
||||
|
||||
.v-slider-track__tick
|
||||
background-color: rgb(var(--v-theme-surface-variant))
|
||||
|
||||
&--filled
|
||||
background-color: $slider-tick-background
|
||||
|
||||
// Elements
|
||||
.v-slider-track
|
||||
border-radius: $slider-track-border-radius
|
||||
|
||||
@media (forced-colors: active)
|
||||
border: thin solid buttontext
|
||||
|
||||
.v-slider-track
|
||||
&__background, &__fill
|
||||
position: absolute
|
||||
transition: $slider-transition
|
||||
border-radius: inherit
|
||||
|
||||
.v-slider--pressed &
|
||||
transition: none
|
||||
|
||||
.v-input--error:not(.v-input--disabled) &
|
||||
background-color: currentColor
|
||||
|
||||
.v-slider-track__ticks
|
||||
height: 100%
|
||||
width: 100%
|
||||
position: relative
|
||||
|
||||
.v-slider-track__tick
|
||||
position: absolute
|
||||
opacity: 0
|
||||
transition: 0.2s opacity settings.$standard-easing
|
||||
border-radius: $slider-tick-border-radius
|
||||
width: var(--v-slider-tick-size)
|
||||
height: var(--v-slider-tick-size)
|
||||
transform: translate(calc(var(--v-slider-tick-size) / -2), calc(var(--v-slider-tick-size) / -2))
|
||||
|
||||
&--first .v-slider-track__tick-label
|
||||
@include tools.ltr()
|
||||
transform: none
|
||||
|
||||
@include tools.rtl()
|
||||
transform: translateX(100%)
|
||||
|
||||
&--last .v-slider-track__tick-label
|
||||
@include tools.ltr()
|
||||
transform: translateX(-100%)
|
||||
|
||||
@include tools.rtl()
|
||||
transform: none
|
||||
|
||||
.v-slider-track__tick-label
|
||||
position: absolute
|
||||
user-select: none
|
||||
white-space: nowrap
|
||||
|
||||
// Horizontal
|
||||
.v-slider.v-input--horizontal
|
||||
.v-slider-track
|
||||
display: flex
|
||||
align-items: center
|
||||
width: 100%
|
||||
height: $slider-track-active-size
|
||||
touch-action: pan-y
|
||||
|
||||
&__background
|
||||
height: var(--v-slider-track-size)
|
||||
|
||||
&__fill
|
||||
height: inherit
|
||||
|
||||
.v-slider-track__tick
|
||||
margin-top: calc(#{$slider-track-active-size} / 2)
|
||||
|
||||
@include tools.rtl()
|
||||
transform: translate(calc(var(--v-slider-tick-size) / 2), calc(var(--v-slider-tick-size) / -2))
|
||||
|
||||
.v-slider-track__tick-label
|
||||
margin-top: calc(var(--v-slider-track-size) / 2 + #{$slider-tick-label-margin-top})
|
||||
|
||||
@include tools.ltr()
|
||||
transform: translateX(-50%)
|
||||
|
||||
@include tools.rtl()
|
||||
transform: translateX(50%)
|
||||
|
||||
&--first
|
||||
margin-inline-start: calc(var(--v-slider-tick-size) + 1px)
|
||||
|
||||
.v-slider-track__tick-label
|
||||
@include tools.ltr()
|
||||
transform: translateX(0%)
|
||||
|
||||
@include tools.rtl()
|
||||
transform: translateX(0%)
|
||||
|
||||
&--last
|
||||
margin-inline-start: calc(100% - var(--v-slider-tick-size) - 1px)
|
||||
|
||||
.v-slider-track__tick-label
|
||||
@include tools.ltr()
|
||||
transform: translateX(-100%)
|
||||
|
||||
@include tools.rtl()
|
||||
transform: translateX(100%)
|
||||
|
||||
// Vertical
|
||||
.v-slider.v-input--vertical
|
||||
.v-slider-track
|
||||
height: 100%
|
||||
display: flex
|
||||
justify-content: center
|
||||
width: $slider-track-active-size
|
||||
touch-action: pan-x
|
||||
|
||||
&__background
|
||||
width: var(--v-slider-track-size)
|
||||
|
||||
&__fill
|
||||
width: inherit
|
||||
|
||||
.v-slider-track__ticks
|
||||
height: 100%
|
||||
|
||||
.v-slider-track__tick
|
||||
margin-inline-start: calc(#{$slider-track-active-size} / 2)
|
||||
transform: translate(calc(var(--v-slider-tick-size) / -2), calc(var(--v-slider-tick-size) / 2))
|
||||
|
||||
@include tools.rtl()
|
||||
transform: translate(calc(var(--v-slider-tick-size) / 2), calc(var(--v-slider-tick-size) / 2))
|
||||
|
||||
&--first
|
||||
bottom: calc(0% + var(--v-slider-tick-size) + 1px)
|
||||
&--last
|
||||
bottom: calc(100% - var(--v-slider-tick-size) - 1px)
|
||||
|
||||
.v-slider-track__tick-label
|
||||
margin-inline-start: calc(var(--v-slider-track-size) / 2 + #{$slider-tick-label-margin-start})
|
||||
transform: translateY(-50%)
|
||||
|
||||
// Modifiers
|
||||
.v-slider-track__ticks--always-show, .v-slider--focused
|
||||
.v-slider-track__tick
|
||||
opacity: 1
|
||||
|
||||
.v-slider-track__background--opacity
|
||||
opacity: 0.38
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
@use '../../styles/settings';
|
||||
@use '../../styles/tools';
|
||||
|
||||
$slider-horizontal-start: 8px !default;
|
||||
$slider-horizontal-min-height: 32px !default;
|
||||
$slider-horizontal-end: 8px !default;
|
||||
$slider-label-margin-end: 12px !default;
|
||||
$slider-label-margin-start: 12px !default;
|
||||
$slider-state-track-background-opacity: 0.4 !default;
|
||||
$slider-thumb-hover-opacity: var(--v-hover-opacity) !default;
|
||||
$slider-thumb-focus-opacity: var(--v-focus-opacity) !default;
|
||||
$slider-thumb-pressed-opacity: var(--v-pressed-opacity) !default;
|
||||
$slider-thumb-border-radius: 50% !default;
|
||||
$slider-thumb-focused-size-increase: 24px !default;
|
||||
$slider-thumb-label-font-size: tools.map-deep-get(settings.$typography, 'label-small', 'size') !default;
|
||||
$slider-thumb-label-border-radius: 4px !default;
|
||||
$slider-thumb-label-height: 25px !default;
|
||||
$slider-thumb-label-min-width: 35px !default;
|
||||
$slider-thumb-label-wedge-size: 6px !default;
|
||||
$slider-thumb-label-offset: calc(var(--v-slider-thumb-size) / 2) !default;
|
||||
$slider-thumb-label-transition: .2s settings.$accelerated-easing !default;
|
||||
$slider-thumb-label-padding: 6px !default;
|
||||
$slider-thumb-touch-size: 42px !default;
|
||||
$slider-tick-background: rgb(var(--v-theme-surface-light)) !default;
|
||||
$slider-tick-border-radius: 2px !default;
|
||||
$slider-tick-label-margin-top: 8px !default;
|
||||
$slider-tick-label-margin-start: 12px !default;
|
||||
$slider-track-border-radius: 6px !default;
|
||||
$slider-track-active-size-offset: 2px !default;
|
||||
$slider-transition: .3s cubic-bezier(0.25, 0.8, 0.5, 1) !default;
|
||||
$slider-vertical-margin-bottom: 12px !default;
|
||||
$slider-vertical-margin-top: 12px !default;
|
||||
$slider-vertical-min-height: 300px !default;
|
||||
|
||||
$slider-track-active-size: calc(var(--v-slider-track-size) + #{$slider-track-active-size-offset}) !default;
|
||||
+1
@@ -0,0 +1 @@
|
||||
export { VSlider } from './VSlider.js';
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export { VSlider } from "./VSlider.js";
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","names":["VSlider"],"sources":["../../../src/components/VSlider/index.ts"],"sourcesContent":["export { VSlider } from './VSlider'\n"],"mappings":"SAASA,OAAO","ignoreList":[]}
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
import type { ExtractPropTypes, InjectionKey, PropType, Ref } from 'vue';
|
||||
import type { VSliderTrack } from './VSliderTrack.js';
|
||||
export type Tick = {
|
||||
value: number;
|
||||
position: number;
|
||||
label?: string;
|
||||
};
|
||||
type SliderProvide = {
|
||||
activeThumbRef: Ref<HTMLElement | undefined>;
|
||||
color: Ref<string | undefined>;
|
||||
decimals: Ref<number>;
|
||||
direction: Ref<'vertical' | 'horizontal'>;
|
||||
disabled: Ref<boolean>;
|
||||
elevation: Ref<number | string | undefined>;
|
||||
min: Ref<number>;
|
||||
max: Ref<number>;
|
||||
mousePressed: Ref<boolean>;
|
||||
noKeyboard: Ref<boolean>;
|
||||
numTicks: Ref<number>;
|
||||
onSliderMousedown: (e: MouseEvent) => void;
|
||||
onSliderTouchstart: (e: TouchEvent) => void;
|
||||
parseMouseMove: (e: MouseEvent | TouchEvent) => number | void;
|
||||
position: (val: number) => number;
|
||||
readonly: Ref<boolean>;
|
||||
rounded: Ref<boolean | number | string | undefined>;
|
||||
roundValue: (value: number) => number;
|
||||
thumbLabel: Ref<boolean | string | undefined>;
|
||||
showTicks: Ref<boolean | 'always'>;
|
||||
startOffset: Ref<number>;
|
||||
step: Ref<number>;
|
||||
thumbSize: Ref<number>;
|
||||
thumbColor: Ref<string | undefined>;
|
||||
thumbLabelColor: Ref<string | undefined>;
|
||||
trackColor: Ref<string | undefined>;
|
||||
trackFillColor: Ref<string | undefined>;
|
||||
trackSize: Ref<number>;
|
||||
ticks: Ref<readonly number[] | Record<string, string> | undefined>;
|
||||
tickSize: Ref<number>;
|
||||
trackContainerRef: Ref<VSliderTrack | undefined>;
|
||||
vertical: Ref<boolean>;
|
||||
parsedTicks: Ref<Tick[]>;
|
||||
hasLabels: Ref<boolean>;
|
||||
isReversed: Ref<boolean>;
|
||||
indexFromEnd: Ref<boolean>;
|
||||
};
|
||||
export declare const VSliderSymbol: InjectionKey<SliderProvide>;
|
||||
export declare function getOffset(e: MouseEvent | TouchEvent, el: HTMLElement, direction: string): number;
|
||||
export declare const makeSliderProps: <Defaults extends {
|
||||
elevation?: unknown;
|
||||
rounded?: unknown;
|
||||
tile?: unknown;
|
||||
disabled?: unknown;
|
||||
error?: unknown;
|
||||
readonly?: unknown;
|
||||
max?: unknown;
|
||||
min?: unknown;
|
||||
step?: unknown;
|
||||
thumbColor?: unknown;
|
||||
thumbLabel?: unknown;
|
||||
thumbSize?: unknown;
|
||||
showTicks?: unknown;
|
||||
ticks?: unknown;
|
||||
tickSize?: unknown;
|
||||
color?: unknown;
|
||||
trackColor?: unknown;
|
||||
trackFillColor?: unknown;
|
||||
trackSize?: unknown;
|
||||
direction?: unknown;
|
||||
reverse?: unknown;
|
||||
noKeyboard?: unknown;
|
||||
ripple?: unknown;
|
||||
} = {}>(defaults?: Defaults | undefined) => {
|
||||
elevation: unknown extends Defaults["elevation"] ? Omit<{
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
validator: (value: string | number) => boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<string | number>;
|
||||
default: NonNullable<string | number>;
|
||||
} : Omit<Omit<{
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
validator: (value: string | number) => boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<string | number>;
|
||||
default: NonNullable<string | number>;
|
||||
}, "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"];
|
||||
};
|
||||
disabled: unknown extends Defaults["disabled"] ? {
|
||||
type: PropType<boolean | null>;
|
||||
default: null;
|
||||
} : Omit<{
|
||||
type: PropType<boolean | null>;
|
||||
default: null;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["disabled"] ? boolean | null : boolean | Defaults["disabled"] | null>;
|
||||
default: unknown extends Defaults["disabled"] ? boolean | null : Defaults["disabled"] | NonNullable<boolean | null>;
|
||||
};
|
||||
error: unknown extends Defaults["error"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["error"] ? boolean : boolean | Defaults["error"]>;
|
||||
default: unknown extends Defaults["error"] ? boolean : boolean | Defaults["error"];
|
||||
};
|
||||
readonly: unknown extends Defaults["readonly"] ? {
|
||||
type: PropType<boolean | null>;
|
||||
default: null;
|
||||
} : Omit<{
|
||||
type: PropType<boolean | null>;
|
||||
default: null;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["readonly"] ? boolean | null : boolean | Defaults["readonly"] | null>;
|
||||
default: unknown extends Defaults["readonly"] ? boolean | null : Defaults["readonly"] | NonNullable<boolean | null>;
|
||||
};
|
||||
max: unknown extends Defaults["max"] ? {
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
} : Omit<{
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["max"] ? string | number : string | number | Defaults["max"]>;
|
||||
default: unknown extends Defaults["max"] ? string | number : Defaults["max"] | NonNullable<string | number>;
|
||||
};
|
||||
min: unknown extends Defaults["min"] ? {
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
} : Omit<{
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["min"] ? string | number : string | number | Defaults["min"]>;
|
||||
default: unknown extends Defaults["min"] ? string | number : Defaults["min"] | NonNullable<string | number>;
|
||||
};
|
||||
step: unknown extends Defaults["step"] ? {
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
} : Omit<{
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["step"] ? string | number : string | number | Defaults["step"]>;
|
||||
default: unknown extends Defaults["step"] ? string | number : Defaults["step"] | NonNullable<string | number>;
|
||||
};
|
||||
thumbColor: unknown extends Defaults["thumbColor"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["thumbColor"] ? string : string | Defaults["thumbColor"]>;
|
||||
default: unknown extends Defaults["thumbColor"] ? string : string | Defaults["thumbColor"];
|
||||
};
|
||||
thumbLabel: unknown extends Defaults["thumbLabel"] ? {
|
||||
type: PropType<boolean | 'always' | 'hover' | undefined>;
|
||||
default: undefined;
|
||||
validator: (v: any) => boolean;
|
||||
} : Omit<{
|
||||
type: PropType<boolean | 'always' | 'hover' | undefined>;
|
||||
default: undefined;
|
||||
validator: (v: any) => boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["thumbLabel"] ? "always" | "hover" | boolean | undefined : "always" | "hover" | boolean | Defaults["thumbLabel"] | undefined>;
|
||||
default: unknown extends Defaults["thumbLabel"] ? "always" | "hover" | boolean | undefined : Defaults["thumbLabel"] | NonNullable<"always" | "hover" | boolean | undefined>;
|
||||
};
|
||||
thumbSize: unknown extends Defaults["thumbSize"] ? {
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
} : Omit<{
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["thumbSize"] ? string | number : string | number | Defaults["thumbSize"]>;
|
||||
default: unknown extends Defaults["thumbSize"] ? string | number : Defaults["thumbSize"] | NonNullable<string | number>;
|
||||
};
|
||||
showTicks: unknown extends Defaults["showTicks"] ? {
|
||||
type: PropType<boolean | 'always'>;
|
||||
default: boolean;
|
||||
validator: (v: any) => boolean;
|
||||
} : Omit<{
|
||||
type: PropType<boolean | 'always'>;
|
||||
default: boolean;
|
||||
validator: (v: any) => boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["showTicks"] ? "always" | boolean : "always" | boolean | Defaults["showTicks"]>;
|
||||
default: unknown extends Defaults["showTicks"] ? "always" | boolean : Defaults["showTicks"] | NonNullable<"always" | boolean>;
|
||||
};
|
||||
ticks: unknown extends Defaults["ticks"] ? {
|
||||
type: PropType<readonly number[] | Record<number, string>>;
|
||||
} : Omit<{
|
||||
type: PropType<readonly number[] | Record<number, string>>;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["ticks"] ? readonly number[] | Record<number, string> : readonly number[] | Record<number, string> | Defaults["ticks"]>;
|
||||
default: unknown extends Defaults["ticks"] ? readonly number[] | Record<number, string> : Defaults["ticks"] | NonNullable<readonly number[] | Record<number, string>>;
|
||||
};
|
||||
tickSize: unknown extends Defaults["tickSize"] ? {
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
} : Omit<{
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["tickSize"] ? string | number : string | number | Defaults["tickSize"]>;
|
||||
default: unknown extends Defaults["tickSize"] ? string | number : Defaults["tickSize"] | NonNullable<string | number>;
|
||||
};
|
||||
color: unknown extends Defaults["color"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["color"] ? string : string | Defaults["color"]>;
|
||||
default: unknown extends Defaults["color"] ? string : string | Defaults["color"];
|
||||
};
|
||||
trackColor: unknown extends Defaults["trackColor"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["trackColor"] ? string : string | Defaults["trackColor"]>;
|
||||
default: unknown extends Defaults["trackColor"] ? string : string | Defaults["trackColor"];
|
||||
};
|
||||
trackFillColor: unknown extends Defaults["trackFillColor"] ? StringConstructor : {
|
||||
type: PropType<unknown extends Defaults["trackFillColor"] ? string : string | Defaults["trackFillColor"]>;
|
||||
default: unknown extends Defaults["trackFillColor"] ? string : string | Defaults["trackFillColor"];
|
||||
};
|
||||
trackSize: unknown extends Defaults["trackSize"] ? {
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
} : Omit<{
|
||||
type: (NumberConstructor | StringConstructor)[];
|
||||
default: number;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["trackSize"] ? string | number : string | number | Defaults["trackSize"]>;
|
||||
default: unknown extends Defaults["trackSize"] ? string | number : Defaults["trackSize"] | NonNullable<string | number>;
|
||||
};
|
||||
direction: unknown extends Defaults["direction"] ? {
|
||||
type: PropType<'horizontal' | 'vertical'>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
} : Omit<{
|
||||
type: PropType<'horizontal' | 'vertical'>;
|
||||
default: string;
|
||||
validator: (v: any) => boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["direction"] ? "horizontal" | "vertical" : "horizontal" | "vertical" | Defaults["direction"]>;
|
||||
default: unknown extends Defaults["direction"] ? "horizontal" | "vertical" : Defaults["direction"] | NonNullable<"horizontal" | "vertical">;
|
||||
};
|
||||
reverse: unknown extends Defaults["reverse"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["reverse"] ? boolean : boolean | Defaults["reverse"]>;
|
||||
default: unknown extends Defaults["reverse"] ? boolean : boolean | Defaults["reverse"];
|
||||
};
|
||||
noKeyboard: unknown extends Defaults["noKeyboard"] ? BooleanConstructor : {
|
||||
type: PropType<unknown extends Defaults["noKeyboard"] ? boolean : boolean | Defaults["noKeyboard"]>;
|
||||
default: unknown extends Defaults["noKeyboard"] ? boolean : boolean | Defaults["noKeyboard"];
|
||||
};
|
||||
ripple: unknown extends Defaults["ripple"] ? {
|
||||
type: BooleanConstructor;
|
||||
default: boolean;
|
||||
} : Omit<{
|
||||
type: BooleanConstructor;
|
||||
default: boolean;
|
||||
}, "default" | "type"> & {
|
||||
type: PropType<unknown extends Defaults["ripple"] ? boolean : boolean | Defaults["ripple"]>;
|
||||
default: unknown extends Defaults["ripple"] ? boolean : boolean | Defaults["ripple"];
|
||||
};
|
||||
};
|
||||
type SliderProps = ExtractPropTypes<ReturnType<typeof makeSliderProps>>;
|
||||
type SliderData = {
|
||||
value: number;
|
||||
};
|
||||
export declare const useSteps: (props: SliderProps) => {
|
||||
min: import("vue").ComputedRef<number>;
|
||||
max: import("vue").ComputedRef<number>;
|
||||
step: import("vue").ComputedRef<number>;
|
||||
decimals: import("vue").ComputedRef<number>;
|
||||
roundValue: (value: string | number) => number;
|
||||
};
|
||||
export declare const useSlider: ({ props, steps, onSliderStart, onSliderMove, onSliderEnd, getActiveThumb, }: {
|
||||
props: SliderProps;
|
||||
steps: ReturnType<typeof useSteps>;
|
||||
onSliderEnd: (data: SliderData) => void;
|
||||
onSliderStart: (data: SliderData) => void;
|
||||
onSliderMove: (data: SliderData) => void;
|
||||
getActiveThumb: (e: MouseEvent | TouchEvent) => HTMLElement;
|
||||
}) => SliderProvide;
|
||||
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
/* eslint-disable max-statements */
|
||||
// Composables
|
||||
import { makeElevationProps } from "../../composables/elevation.js";
|
||||
import { useForm } from "../../composables/form.js";
|
||||
import { useRtl } from "../../composables/locale.js";
|
||||
import { makeRoundedProps } from "../../composables/rounded.js"; // Utilities
|
||||
import { computed, nextTick, onScopeDispose, provide, ref, shallowRef, toRef } from 'vue';
|
||||
import { clamp, createRange, getDecimals, IN_BROWSER, propsFactory } from "../../util/index.js"; // Types
|
||||
export const VSliderSymbol = Symbol.for('vuetify:v-slider');
|
||||
export function getOffset(e, el, direction) {
|
||||
const vertical = direction === 'vertical';
|
||||
const rect = el.getBoundingClientRect();
|
||||
const touch = 'touches' in e ? e.touches[0] : e;
|
||||
return vertical ? touch.clientY - (rect.top + rect.height / 2) : touch.clientX - (rect.left + rect.width / 2);
|
||||
}
|
||||
function getPosition(e, position) {
|
||||
if ('touches' in e && e.touches.length) return e.touches[0][position];else if ('changedTouches' in e && e.changedTouches.length) return e.changedTouches[0][position];else return e[position];
|
||||
}
|
||||
export const makeSliderProps = propsFactory({
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: null
|
||||
},
|
||||
error: Boolean,
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: null
|
||||
},
|
||||
max: {
|
||||
type: [Number, String],
|
||||
default: 100
|
||||
},
|
||||
min: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
step: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
thumbColor: String,
|
||||
thumbLabel: {
|
||||
type: [Boolean, String],
|
||||
default: undefined,
|
||||
validator: v => typeof v === 'boolean' || v === 'always' || v === 'hover'
|
||||
},
|
||||
thumbSize: {
|
||||
type: [Number, String],
|
||||
default: 20
|
||||
},
|
||||
showTicks: {
|
||||
type: [Boolean, String],
|
||||
default: false,
|
||||
validator: v => typeof v === 'boolean' || v === 'always'
|
||||
},
|
||||
ticks: {
|
||||
type: [Array, Object]
|
||||
},
|
||||
tickSize: {
|
||||
type: [Number, String],
|
||||
default: 2
|
||||
},
|
||||
color: String,
|
||||
trackColor: String,
|
||||
trackFillColor: String,
|
||||
trackSize: {
|
||||
type: [Number, String],
|
||||
default: 4
|
||||
},
|
||||
direction: {
|
||||
type: String,
|
||||
default: 'horizontal',
|
||||
validator: v => ['vertical', 'horizontal'].includes(v)
|
||||
},
|
||||
reverse: Boolean,
|
||||
noKeyboard: Boolean,
|
||||
...makeRoundedProps(),
|
||||
...makeElevationProps({
|
||||
elevation: 1
|
||||
}),
|
||||
ripple: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
}, 'Slider');
|
||||
export const useSteps = props => {
|
||||
const min = computed(() => parseFloat(props.min));
|
||||
const max = computed(() => parseFloat(props.max));
|
||||
const step = computed(() => Number(props.step) > 0 ? parseFloat(props.step) : 0);
|
||||
const decimals = computed(() => Math.max(getDecimals(step.value), getDecimals(min.value)));
|
||||
function roundValue(value) {
|
||||
value = parseFloat(value);
|
||||
if (step.value <= 0) return value;
|
||||
const clamped = clamp(value, min.value, max.value);
|
||||
const offset = min.value % step.value;
|
||||
let newValue = Math.round((clamped - offset) / step.value) * step.value + offset;
|
||||
if (clamped > newValue && newValue + step.value > max.value) {
|
||||
newValue = max.value;
|
||||
}
|
||||
return parseFloat(Math.min(newValue, max.value).toFixed(decimals.value));
|
||||
}
|
||||
return {
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
decimals,
|
||||
roundValue
|
||||
};
|
||||
};
|
||||
export const useSlider = ({
|
||||
props,
|
||||
steps,
|
||||
onSliderStart,
|
||||
onSliderMove,
|
||||
onSliderEnd,
|
||||
getActiveThumb
|
||||
}) => {
|
||||
const form = useForm(props);
|
||||
const {
|
||||
isRtl
|
||||
} = useRtl();
|
||||
const isReversed = toRef(() => props.reverse);
|
||||
const vertical = computed(() => props.direction === 'vertical');
|
||||
const indexFromEnd = computed(() => vertical.value !== isReversed.value);
|
||||
const {
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
decimals,
|
||||
roundValue
|
||||
} = steps;
|
||||
const thumbSize = computed(() => parseInt(props.thumbSize, 10));
|
||||
const tickSize = computed(() => parseInt(props.tickSize, 10));
|
||||
const trackSize = computed(() => parseInt(props.trackSize, 10));
|
||||
const numTicks = computed(() => (max.value - min.value) / step.value);
|
||||
const thumbColor = computed(() => props.error || form.isDisabled.value ? undefined : props.thumbColor ?? props.color);
|
||||
const thumbLabelColor = computed(() => props.error || form.isDisabled.value ? undefined : props.thumbColor);
|
||||
const trackColor = computed(() => props.error || form.isDisabled.value ? undefined : props.trackColor ?? props.color);
|
||||
const trackFillColor = computed(() => props.error || form.isDisabled.value ? undefined : props.trackFillColor ?? props.color);
|
||||
const mousePressed = shallowRef(false);
|
||||
const startOffset = shallowRef(0);
|
||||
const trackContainerRef = ref();
|
||||
const activeThumbRef = ref();
|
||||
function parseMouseMove(e) {
|
||||
const el = trackContainerRef.value?.$el;
|
||||
if (!el) return;
|
||||
const vertical = props.direction === 'vertical';
|
||||
const start = vertical ? 'top' : 'left';
|
||||
const length = vertical ? 'height' : 'width';
|
||||
const position = vertical ? 'clientY' : 'clientX';
|
||||
const {
|
||||
[start]: trackStart,
|
||||
[length]: trackLength
|
||||
} = el.getBoundingClientRect();
|
||||
const clickOffset = getPosition(e, position);
|
||||
|
||||
// It is possible for left to be NaN, force to number
|
||||
let clickPos = clamp((clickOffset - trackStart - startOffset.value) / trackLength) || 0;
|
||||
if (vertical ? indexFromEnd.value : indexFromEnd.value !== isRtl.value) clickPos = 1 - clickPos;
|
||||
return roundValue(min.value + clickPos * (max.value - min.value));
|
||||
}
|
||||
const handleStop = e => {
|
||||
const value = parseMouseMove(e);
|
||||
if (value != null) {
|
||||
onSliderEnd({
|
||||
value
|
||||
});
|
||||
}
|
||||
mousePressed.value = false;
|
||||
startOffset.value = 0;
|
||||
};
|
||||
const handleStart = e => {
|
||||
const value = parseMouseMove(e);
|
||||
activeThumbRef.value = getActiveThumb(e);
|
||||
if (!activeThumbRef.value) return;
|
||||
mousePressed.value = true;
|
||||
if (activeThumbRef.value.contains(e.target)) {
|
||||
startOffset.value = getOffset(e, activeThumbRef.value, props.direction);
|
||||
} else {
|
||||
startOffset.value = 0;
|
||||
if (value != null) {
|
||||
onSliderMove({
|
||||
value
|
||||
});
|
||||
}
|
||||
}
|
||||
if (value != null) {
|
||||
onSliderStart({
|
||||
value
|
||||
});
|
||||
}
|
||||
nextTick(() => activeThumbRef.value?.focus());
|
||||
};
|
||||
const moveListenerOptions = {
|
||||
passive: true,
|
||||
capture: true
|
||||
};
|
||||
function onMouseMove(e) {
|
||||
const value = parseMouseMove(e);
|
||||
if (value != null) {
|
||||
onSliderMove({
|
||||
value
|
||||
});
|
||||
}
|
||||
}
|
||||
function onSliderMouseUp(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
handleStop(e);
|
||||
window.removeEventListener('mousemove', onMouseMove, moveListenerOptions);
|
||||
window.removeEventListener('mouseup', onSliderMouseUp);
|
||||
}
|
||||
function onSliderTouchend(e) {
|
||||
handleStop(e);
|
||||
window.removeEventListener('touchmove', onMouseMove, moveListenerOptions);
|
||||
e.target?.removeEventListener('touchend', onSliderTouchend);
|
||||
}
|
||||
function onSliderTouchstart(e) {
|
||||
handleStart(e);
|
||||
window.addEventListener('touchmove', onMouseMove, moveListenerOptions);
|
||||
e.target?.addEventListener('touchend', onSliderTouchend, {
|
||||
passive: false
|
||||
});
|
||||
}
|
||||
function onSliderMousedown(e) {
|
||||
if (e.button !== 0) return;
|
||||
e.preventDefault();
|
||||
handleStart(e);
|
||||
window.addEventListener('mousemove', onMouseMove, moveListenerOptions);
|
||||
window.addEventListener('mouseup', onSliderMouseUp, {
|
||||
passive: false
|
||||
});
|
||||
}
|
||||
onScopeDispose(() => {
|
||||
if (!IN_BROWSER) return;
|
||||
window.removeEventListener('touchmove', onMouseMove);
|
||||
window.removeEventListener('mousemove', onMouseMove);
|
||||
window.removeEventListener('mouseup', onSliderMouseUp);
|
||||
});
|
||||
const position = val => {
|
||||
const percentage = (val - min.value) / (max.value - min.value) * 100;
|
||||
return clamp(isNaN(percentage) ? 0 : percentage, 0, 100);
|
||||
};
|
||||
const showTicks = toRef(() => props.showTicks);
|
||||
const parsedTicks = computed(() => {
|
||||
if (!showTicks.value) return [];
|
||||
if (!props.ticks) {
|
||||
return numTicks.value !== Infinity ? createRange(numTicks.value + 1).map(t => {
|
||||
const value = min.value + t * step.value;
|
||||
return {
|
||||
value,
|
||||
position: position(value)
|
||||
};
|
||||
}) : [];
|
||||
}
|
||||
if (Array.isArray(props.ticks)) return props.ticks.map(t => ({
|
||||
value: t,
|
||||
position: position(t),
|
||||
label: t.toString()
|
||||
}));
|
||||
return Object.keys(props.ticks).map(key => ({
|
||||
value: parseFloat(key),
|
||||
position: position(parseFloat(key)),
|
||||
label: props.ticks[key]
|
||||
}));
|
||||
});
|
||||
const hasLabels = computed(() => parsedTicks.value.some(({
|
||||
label
|
||||
}) => !!label));
|
||||
const data = {
|
||||
activeThumbRef,
|
||||
color: toRef(() => props.color),
|
||||
decimals,
|
||||
disabled: form.isDisabled,
|
||||
direction: toRef(() => props.direction),
|
||||
elevation: toRef(() => props.elevation),
|
||||
hasLabels,
|
||||
isReversed,
|
||||
indexFromEnd,
|
||||
min,
|
||||
max,
|
||||
mousePressed,
|
||||
noKeyboard: toRef(() => props.noKeyboard),
|
||||
numTicks,
|
||||
onSliderMousedown,
|
||||
onSliderTouchstart,
|
||||
parsedTicks,
|
||||
parseMouseMove,
|
||||
position,
|
||||
readonly: form.isReadonly,
|
||||
rounded: toRef(() => props.rounded),
|
||||
roundValue,
|
||||
showTicks,
|
||||
startOffset,
|
||||
step,
|
||||
thumbSize,
|
||||
thumbColor,
|
||||
thumbLabelColor,
|
||||
thumbLabel: toRef(() => props.thumbLabel),
|
||||
ticks: toRef(() => props.ticks),
|
||||
tickSize,
|
||||
trackColor,
|
||||
trackContainerRef,
|
||||
trackFillColor,
|
||||
trackSize,
|
||||
vertical
|
||||
};
|
||||
provide(VSliderSymbol, data);
|
||||
return data;
|
||||
};
|
||||
//# sourceMappingURL=slider.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user