Files
routie/frontend/node_modules/.vite/deps/vuetify_components_VSelect.js
T

2041 lines
70 KiB
JavaScript

import { $ as createTextVNode, C as vShow, Cn as withDirectives, Dt as mergeProps, Ft as onMounted, Kn as ref, M as Fragment, Ot as nextTick, Qn as toRef, U as computed, V as cloneVNode, Vn as onScopeDispose, W as createBaseVNode, Yn as shallowRef, _n as watchEffect, ar as normalizeClass, cn as useId, cr as toDisplayString, er as toValue, et as createVNode, gn as watch, nr as unref, sr as normalizeStyle } from "./vue.runtime.esm-bundler-BvoXUmaf.js";
import { $ as PREFERS_REDUCED_MOTION, B as matchesSelector, H as omit, O as focusableChildren, Q as IN_BROWSER, S as ensureValidVNode, Z as wrapInArray, _ as convertToUnit, a as provideDefaults, d as EventProp, f as callEvent, g as clamp, j as getPropertyFromItem, l as propsFactory, m as checkPrintable, n as genericComponent, p as camelizeProps, s as getCurrentInstance, w as filterInputAttrs, y as debounce } from "./defineComponent-DB6xIcDy.js";
import { t as Box } from "./box-BNWMOtF7.js";
import { a as VSlideYTransition, c as nullifyTransforms, n as VExpandXTransition, o as VDialogTransition, s as animate } from "./transitions-DCQ3sjjZ.js";
import { t as makeComponentProps } from "./component-DdiwBe6i.js";
import { t as deepEqual } from "./deepEqual-DDqmGqyF.js";
import { i as standardEasing } from "./easing-DfcvkbkS.js";
import { t as getScrollParent } from "./getScrollParent-DuXs8SPu.js";
import { t as useRender } from "./useRender-fVtVsZgv.js";
import { a as makeItemsProps, c as VListItem, i as VList, o as useItems, s as VListSubheader } from "./VList-DkWOjB0M.js";
import { r as useTextColor, t as useBackgroundColor } from "./color-B6vuQruj.js";
import { i as provideTheme, r as makeThemeProps } from "./theme-Cx5kFg0-.js";
import { t as VDivider } from "./VDivider-BJiijT0J.js";
import { n as IconValue } from "./icons-k2ZLE_i8.js";
import { n as useToggleScope, t as useProxiedModel } from "./proxiedModel-DSlSIQ0y.js";
import { i as useRtl, r as useLocale } from "./locale-DDGMqzqb.js";
import { a as useDisplay } from "./display-DKaCj-_K.js";
import { t as useResizeObserver } from "./resizeObserver-C12jWpYk.js";
import { t as makeTagProps } from "./tag-C_KkCPzB.js";
import { t as VDefaultsProvider } from "./VDefaultsProvider-C09t4-My.js";
import { n as useDimension, t as makeDimensionProps } from "./dimensions-BDdmuRdK.js";
import { n as Intersect } from "./VImg-DaEUT7gG.js";
import { n as useRounded, t as makeRoundedProps } from "./rounded-BuPGKRa9.js";
import { n as makeTransitionProps, t as MaybeTransition } from "./transition-DqoZ8fA1.js";
import { n as useBorder, t as makeBorderProps } from "./border-jCmRyoxP.js";
import { n as useElevation, t as makeElevationProps } from "./elevation-B0TH2wU6.js";
import { n as useDensity, t as makeDensityProps } from "./density-CpKZ5PhP.js";
import { n as makeVariantProps, r as useVariant, t as genOverlays } from "./variant-CqXtG9Ih.js";
import { i as useGroupItem, n as makeGroupProps, r as useGroup, t as makeGroupItemProps } from "./group-Cm2viEWK.js";
import { n as makeSizeProps, r as useSize, t as VIcon } from "./VIcon-1CJH_3Uo.js";
import { n as makeLoaderProps, r as useLoader, t as LoaderSlot } from "./loader-CV4sMFhE.js";
import { r as useLink, t as makeRouterProps } from "./router-D_jP4Uwb.js";
import { t as Ripple } from "./ripple-Z40rPDte.js";
import { t as VAvatar } from "./VAvatar-CA-KqvIX.js";
import { t as forwardRefs } from "./forwardRefs-CW3d8km7.js";
import { t as VMenu } from "./VMenu-DCQFp-2Y.js";
import { a as useFocus, c as makeVSelectionControlProps, i as makeFocusProps, l as VLabel, n as makeVInputProps, o as useInputIcon, r as useForm, s as VSelectionControl, t as VInput } from "./VInput-BxI8SL-_.js";
import { n as VSlideGroupSymbol, r as makeVSlideGroupProps, t as VSlideGroup } from "./VSlideGroup-TpMGTwfd.js";
import { t as VSheet } from "./VSheet-CLHX3uIJ.js";
import "/Users/thackmaster/Development/routie2/frontend/node_modules/vuetify/lib/components/VSelect/VSelect.css";
import "/Users/thackmaster/Development/routie2/frontend/node_modules/vuetify/lib/components/VChip/VChip.css";
import "/Users/thackmaster/Development/routie2/frontend/node_modules/vuetify/lib/components/VChipGroup/VChipGroup.css";
import "/Users/thackmaster/Development/routie2/frontend/node_modules/vuetify/lib/components/VTextField/VTextField.css";
import "/Users/thackmaster/Development/routie2/frontend/node_modules/vuetify/lib/components/VCounter/VCounter.css";
import "/Users/thackmaster/Development/routie2/frontend/node_modules/vuetify/lib/components/VField/VField.css";
import "/Users/thackmaster/Development/routie2/frontend/node_modules/vuetify/lib/components/VVirtualScroll/VVirtualScroll.css";
//#region node_modules/vuetify/lib/components/VCheckbox/VCheckboxBtn.js
var makeVCheckboxBtnProps = propsFactory({
indeterminate: Boolean,
indeterminateIcon: {
type: IconValue,
default: "$checkboxIndeterminate"
},
...makeVSelectionControlProps({
falseIcon: "$checkboxOff",
trueIcon: "$checkboxOn"
})
}, "VCheckboxBtn");
var VCheckboxBtn = genericComponent()({
name: "VCheckboxBtn",
props: makeVCheckboxBtnProps(),
emits: {
"update:modelValue": (value) => true,
"update:indeterminate": (value) => true
},
setup(props, { slots }) {
const indeterminate = useProxiedModel(props, "indeterminate");
const model = useProxiedModel(props, "modelValue");
function onChange(v) {
if (indeterminate.value) indeterminate.value = false;
}
const falseIcon = toRef(() => {
return indeterminate.value ? props.indeterminateIcon : props.falseIcon;
});
const trueIcon = toRef(() => {
return indeterminate.value ? props.indeterminateIcon : props.trueIcon;
});
useRender(() => {
return createVNode(VSelectionControl, mergeProps(omit(VSelectionControl.filterProps(props), ["modelValue"]), {
"modelValue": model.value,
"onUpdate:modelValue": [($event) => model.value = $event, onChange],
"class": ["v-checkbox-btn", props.class],
"style": props.style,
"type": "checkbox",
"falseIcon": falseIcon.value,
"trueIcon": trueIcon.value,
"aria-checked": indeterminate.value ? "mixed" : void 0
}), slots);
});
return {};
}
});
//#endregion
//#region node_modules/vuetify/lib/components/VChipGroup/VChipGroup.js
var VChipGroupSymbol = Symbol.for("vuetify:v-chip-group");
var makeVChipGroupProps = propsFactory({
baseColor: String,
column: Boolean,
filter: Boolean,
valueComparator: {
type: Function,
default: deepEqual
},
...makeVSlideGroupProps({ scrollToActive: false }),
...makeComponentProps(),
...makeGroupProps({ selectedClass: "v-chip--selected" }),
...makeTagProps(),
...makeThemeProps(),
...makeVariantProps({ variant: "tonal" })
}, "VChipGroup");
genericComponent()({
name: "VChipGroup",
props: makeVChipGroupProps(),
emits: { "update:modelValue": (value) => true },
setup(props, { slots }) {
const { themeClasses } = provideTheme(props);
const { isSelected, select, next, prev, selected } = useGroup(props, VChipGroupSymbol);
provideDefaults({ VChip: {
baseColor: toRef(() => props.baseColor),
color: toRef(() => props.color),
disabled: toRef(() => props.disabled),
filter: toRef(() => props.filter),
variant: toRef(() => props.variant)
} });
useRender(() => {
return createVNode(VSlideGroup, mergeProps(VSlideGroup.filterProps(props), {
"class": [
"v-chip-group",
{ "v-chip-group--column": props.column },
themeClasses.value,
props.class
],
"style": props.style
}), { default: () => [slots.default?.({
isSelected,
select,
next,
prev,
selected: selected.value
})] });
});
return {};
}
});
//#endregion
//#region node_modules/vuetify/lib/components/VChip/VChip.js
var makeVChipProps = propsFactory({
activeClass: String,
appendAvatar: String,
appendIcon: IconValue,
baseColor: String,
closable: Boolean,
closeIcon: {
type: IconValue,
default: "$delete"
},
closeLabel: {
type: String,
default: "$vuetify.close"
},
draggable: Boolean,
filter: Boolean,
filterIcon: {
type: IconValue,
default: "$complete"
},
label: Boolean,
link: {
type: Boolean,
default: void 0
},
pill: Boolean,
prependAvatar: String,
prependIcon: IconValue,
ripple: {
type: [Boolean, Object],
default: true
},
text: {
type: [
String,
Number,
Boolean
],
default: void 0
},
modelValue: {
type: Boolean,
default: true
},
onClick: EventProp(),
onClickOnce: EventProp(),
...makeBorderProps(),
...makeComponentProps(),
...makeDensityProps(),
...makeElevationProps(),
...makeGroupItemProps(),
...makeRoundedProps(),
...makeRouterProps(),
...makeSizeProps(),
...makeTagProps({ tag: "span" }),
...makeThemeProps(),
...makeVariantProps({ variant: "tonal" })
}, "VChip");
var VChip = genericComponent()({
name: "VChip",
directives: { vRipple: Ripple },
props: makeVChipProps(),
emits: {
"click:close": (e) => true,
"update:modelValue": (value) => true,
"group:selected": (val) => true,
click: (e) => true
},
setup(props, { attrs, emit, slots }) {
const { t } = useLocale();
const { borderClasses } = useBorder(props);
const { densityClasses } = useDensity(props);
const { elevationClasses } = useElevation(props);
const { roundedClasses } = useRounded(props);
const { sizeClasses } = useSize(props);
const { themeClasses } = provideTheme(props);
const isActive = useProxiedModel(props, "modelValue");
const group = useGroupItem(props, VChipGroupSymbol, false);
const slideGroup = useGroupItem(props, VSlideGroupSymbol, false);
const link = useLink(props, attrs);
const isLink = toRef(() => props.link !== false && link.isLink.value);
const isClickable = computed(() => !props.disabled && props.link !== false && (!!group || props.link || link.isClickable.value));
const closeProps = toRef(() => ({
"aria-label": t(props.closeLabel),
disabled: props.disabled,
onClick(e) {
e.preventDefault();
e.stopPropagation();
isActive.value = false;
emit("click:close", e);
}
}));
watch(isActive, (val) => {
if (val) {
group?.register();
slideGroup?.register();
} else {
group?.unregister();
slideGroup?.unregister();
}
});
const { colorClasses, colorStyles, variantClasses } = useVariant(() => {
return {
color: !group || group.isSelected.value ? props.color ?? props.baseColor : props.baseColor,
variant: props.variant
};
});
function onClick(e) {
emit("click", e);
if (!isClickable.value) return;
link.navigate.value?.(e);
group?.toggle();
}
function onKeyDown(e) {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
onClick(e);
}
}
return () => {
const Tag = link.isLink.value ? "a" : props.tag;
const hasAppendMedia = !!(props.appendIcon || props.appendAvatar);
const hasAppend = !!(hasAppendMedia || slots.append);
const hasClose = !!(slots.close || props.closable);
const hasFilter = !!(slots.filter || props.filter) && group;
const hasPrependMedia = !!(props.prependIcon || props.prependAvatar);
const hasPrepend = !!(hasPrependMedia || slots.prepend);
return isActive.value && withDirectives(createVNode(Tag, mergeProps(link.linkProps, {
"class": [
"v-chip",
{
"v-chip--disabled": props.disabled,
"v-chip--label": props.label,
"v-chip--link": isClickable.value,
"v-chip--filter": hasFilter,
"v-chip--pill": props.pill,
[`${props.activeClass}`]: props.activeClass && link.isActive?.value
},
themeClasses.value,
borderClasses.value,
colorClasses.value,
densityClasses.value,
elevationClasses.value,
roundedClasses.value,
sizeClasses.value,
variantClasses.value,
group?.selectedClass.value,
props.class
],
"style": [colorStyles.value, props.style],
"disabled": props.disabled || void 0,
"draggable": props.draggable,
"tabindex": isClickable.value ? 0 : void 0,
"onClick": onClick,
"onKeydown": isClickable.value && !isLink.value && onKeyDown
}), { default: () => [
genOverlays(isClickable.value, "v-chip"),
hasFilter && createVNode(VExpandXTransition, { "key": "filter" }, { default: () => [withDirectives(createBaseVNode("div", { "class": "v-chip__filter" }, [!slots.filter ? createVNode(VIcon, {
"key": "filter-icon",
"icon": props.filterIcon
}, null) : createVNode(VDefaultsProvider, {
"key": "filter-defaults",
"disabled": !props.filterIcon,
"defaults": { VIcon: { icon: props.filterIcon } }
}, slots.filter)]), [[vShow, group.isSelected.value]])] }),
hasPrepend && createBaseVNode("div", {
"key": "prepend",
"class": "v-chip__prepend"
}, [!slots.prepend ? createBaseVNode(Fragment, null, [props.prependIcon && createVNode(VIcon, {
"key": "prepend-icon",
"icon": props.prependIcon,
"start": true
}, null), props.prependAvatar && createVNode(VAvatar, {
"key": "prepend-avatar",
"image": props.prependAvatar,
"start": true
}, null)]) : createVNode(VDefaultsProvider, {
"key": "prepend-defaults",
"disabled": !hasPrependMedia,
"defaults": {
VAvatar: {
image: props.prependAvatar,
start: true
},
VIcon: {
icon: props.prependIcon,
start: true
}
}
}, slots.prepend)]),
createBaseVNode("div", {
"class": "v-chip__content",
"data-no-activator": ""
}, [slots.default?.({
isSelected: group?.isSelected.value,
selectedClass: group?.selectedClass.value,
select: group?.select,
toggle: group?.toggle,
value: group?.value.value,
disabled: props.disabled
}) ?? toDisplayString(props.text)]),
hasAppend && createBaseVNode("div", {
"key": "append",
"class": "v-chip__append"
}, [!slots.append ? createBaseVNode(Fragment, null, [props.appendIcon && createVNode(VIcon, {
"key": "append-icon",
"end": true,
"icon": props.appendIcon
}, null), props.appendAvatar && createVNode(VAvatar, {
"key": "append-avatar",
"end": true,
"image": props.appendAvatar
}, null)]) : createVNode(VDefaultsProvider, {
"key": "append-defaults",
"disabled": !hasAppendMedia,
"defaults": {
VAvatar: {
end: true,
image: props.appendAvatar
},
VIcon: {
end: true,
icon: props.appendIcon
}
}
}, slots.append)]),
hasClose && createBaseVNode("button", mergeProps({
"key": "close",
"class": "v-chip__close",
"type": "button",
"data-testid": "close-chip"
}, closeProps.value), [!slots.close ? createVNode(VIcon, {
"key": "close-icon",
"icon": props.closeIcon,
"size": "x-small"
}, null) : createVNode(VDefaultsProvider, {
"key": "close-defaults",
"defaults": { VIcon: {
icon: props.closeIcon,
size: "x-small"
} }
}, slots.close)])
] }), [[
Ripple,
isClickable.value && props.ripple,
null
]]);
};
}
});
//#endregion
//#region node_modules/vuetify/lib/components/VCounter/VCounter.js
var makeVCounterProps = propsFactory({
active: Boolean,
disabled: Boolean,
max: [Number, String],
value: {
type: [Number, String],
default: 0
},
...makeComponentProps(),
...makeTransitionProps({ transition: { component: VSlideYTransition } })
}, "VCounter");
var VCounter = genericComponent()({
name: "VCounter",
functional: true,
props: makeVCounterProps(),
setup(props, { slots }) {
const counter = toRef(() => {
return props.max ? `${props.value} / ${props.max}` : String(props.value);
});
useRender(() => createVNode(MaybeTransition, { "transition": props.transition }, { default: () => [withDirectives(createBaseVNode("div", {
"class": normalizeClass([
"v-counter",
{ "text-error": props.max && !props.disabled && parseFloat(props.value) > parseFloat(props.max) },
props.class
]),
"style": normalizeStyle(props.style)
}, [slots.default ? slots.default({
counter: counter.value,
max: props.max,
value: props.value
}) : counter.value]), [[vShow, props.active]])] }));
return {};
}
});
//#endregion
//#region node_modules/vuetify/lib/components/VField/VFieldLabel.js
var makeVFieldLabelProps = propsFactory({
floating: Boolean,
...makeComponentProps()
}, "VFieldLabel");
var VFieldLabel = genericComponent()({
name: "VFieldLabel",
props: makeVFieldLabelProps(),
setup(props, { slots }) {
useRender(() => createVNode(VLabel, {
"class": normalizeClass([
"v-field-label",
{ "v-field-label--floating": props.floating },
props.class
]),
"style": normalizeStyle(props.style)
}, slots));
return {};
}
});
//#endregion
//#region node_modules/vuetify/lib/components/VField/VField.js
var allowedVariants = [
"underlined",
"outlined",
"filled",
"solo",
"solo-inverted",
"solo-filled",
"plain"
];
var makeVFieldProps = propsFactory({
appendInnerIcon: IconValue,
bgColor: String,
clearable: Boolean,
clearIcon: {
type: IconValue,
default: "$clear"
},
active: Boolean,
centerAffix: {
type: Boolean,
default: void 0
},
color: String,
baseColor: String,
dirty: Boolean,
disabled: {
type: Boolean,
default: null
},
glow: Boolean,
error: Boolean,
flat: Boolean,
iconColor: [Boolean, String],
label: String,
persistentClear: Boolean,
prependInnerIcon: IconValue,
reverse: Boolean,
singleLine: Boolean,
variant: {
type: String,
default: "filled",
validator: (v) => allowedVariants.includes(v)
},
"onClick:clear": EventProp(),
"onClick:appendInner": EventProp(),
"onClick:prependInner": EventProp(),
...makeComponentProps(),
...makeLoaderProps(),
...makeRoundedProps(),
...makeThemeProps()
}, "VField");
var VField = genericComponent()({
name: "VField",
inheritAttrs: false,
props: {
id: String,
details: Boolean,
labelId: String,
...makeFocusProps(),
...makeVFieldProps()
},
emits: {
"update:focused": (focused) => true,
"update:modelValue": (value) => true
},
setup(props, { attrs, emit, slots }) {
const { themeClasses } = provideTheme(props);
const { loaderClasses } = useLoader(props);
const { focusClasses, isFocused, focus, blur } = useFocus(props);
const { InputIcon } = useInputIcon(props);
const { roundedClasses } = useRounded(props);
const { rtlClasses } = useRtl();
const isActive = toRef(() => props.dirty || props.active);
const hasLabel = toRef(() => !!(props.label || slots.label));
const hasFloatingLabel = toRef(() => !props.singleLine && hasLabel.value);
const uid = useId();
const id = computed(() => props.id || `input-${uid}`);
const messagesId = toRef(() => !props.details ? void 0 : `${id.value}-messages`);
const labelRef = ref();
const floatingLabelRef = ref();
const controlRef = ref();
const isPlainOrUnderlined = computed(() => ["plain", "underlined"].includes(props.variant));
const color = computed(() => {
return props.error || props.disabled ? void 0 : isActive.value && isFocused.value ? props.color : props.baseColor;
});
const iconColor = computed(() => {
if (props.iconColor === true || !props.iconColor && props.glow && isFocused.value) return color.value;
if (!props.iconColor || props.glow && !isFocused.value) return void 0;
return props.iconColor;
});
const { backgroundColorClasses, backgroundColorStyles } = useBackgroundColor(() => props.bgColor);
const { textColorClasses, textColorStyles } = useTextColor(color);
watch(isActive, (val) => {
if (hasFloatingLabel.value && !PREFERS_REDUCED_MOTION()) {
const el = labelRef.value.$el;
const targetEl = floatingLabelRef.value.$el;
requestAnimationFrame(() => {
const rect = nullifyTransforms(el);
const targetRect = new Box(targetEl);
const x = targetRect.x - rect.x;
const y = targetRect.y - rect.y - (rect.height / 2 - targetRect.height / 2);
const targetWidth = targetRect.width / .75;
const width = Math.abs(targetWidth - rect.width) > 1 ? { maxWidth: convertToUnit(targetWidth) } : void 0;
const style = getComputedStyle(el);
const targetStyle = getComputedStyle(targetEl);
const duration = parseFloat(style.transitionDuration) * 1e3 || 150;
const scale = parseFloat(targetStyle.getPropertyValue("--v-field-label-scale"));
const color = targetStyle.getPropertyValue("color");
el.style.visibility = "visible";
targetEl.style.visibility = "hidden";
animate(el, {
transform: `translate(${x}px, ${y}px) scale(${scale})`,
color,
...width
}, {
duration,
easing: standardEasing,
direction: val ? "normal" : "reverse"
}).finished.then(() => {
el.style.removeProperty("visibility");
targetEl.style.removeProperty("visibility");
});
});
}
}, { flush: "post" });
const slotProps = computed(() => ({
isActive,
isFocused,
controlRef,
iconColor,
blur,
focus
}));
const floatingLabelProps = toRef(() => {
const ariaHidden = !isActive.value;
return {
"aria-hidden": ariaHidden,
for: ariaHidden ? void 0 : id.value
};
});
const mainLabelProps = toRef(() => {
const ariaHidden = hasFloatingLabel.value && isActive.value;
return {
"aria-hidden": ariaHidden,
for: ariaHidden ? void 0 : id.value
};
});
function onClick(e) {
if (e.target !== document.activeElement) e.preventDefault();
}
useRender(() => {
const isOutlined = props.variant === "outlined";
const hasPrepend = !!(slots["prepend-inner"] || props.prependInnerIcon);
const hasClear = !!(props.clearable || slots.clear) && !props.disabled;
const hasAppend = !!(slots["append-inner"] || props.appendInnerIcon || hasClear);
const label = () => slots.label ? slots.label({
...slotProps.value,
label: props.label,
props: { for: id.value }
}) : props.label;
return createBaseVNode("div", mergeProps({
"class": [
"v-field",
{
"v-field--active": isActive.value,
"v-field--appended": hasAppend,
"v-field--center-affix": props.centerAffix ?? !isPlainOrUnderlined.value,
"v-field--disabled": props.disabled,
"v-field--dirty": props.dirty,
"v-field--error": props.error,
"v-field--glow": props.glow,
"v-field--flat": props.flat,
"v-field--has-background": !!props.bgColor,
"v-field--persistent-clear": props.persistentClear,
"v-field--prepended": hasPrepend,
"v-field--reverse": props.reverse,
"v-field--single-line": props.singleLine,
"v-field--no-label": !label(),
[`v-field--variant-${props.variant}`]: true
},
themeClasses.value,
backgroundColorClasses.value,
focusClasses.value,
loaderClasses.value,
roundedClasses.value,
rtlClasses.value,
props.class
],
"style": [backgroundColorStyles.value, props.style],
"onClick": onClick
}, attrs), [
createBaseVNode("div", { "class": "v-field__overlay" }, null),
createVNode(LoaderSlot, {
"name": "v-field",
"active": !!props.loading,
"color": props.error ? "error" : typeof props.loading === "string" ? props.loading : props.color
}, { default: slots.loader }),
hasPrepend && createBaseVNode("div", {
"key": "prepend",
"class": "v-field__prepend-inner"
}, [slots["prepend-inner"] ? slots["prepend-inner"](slotProps.value) : props.prependInnerIcon && createVNode(InputIcon, {
"key": "prepend-icon",
"name": "prependInner",
"color": iconColor.value
}, null)]),
createBaseVNode("div", {
"class": "v-field__field",
"data-no-activator": ""
}, [
[
"filled",
"solo",
"solo-inverted",
"solo-filled"
].includes(props.variant) && hasFloatingLabel.value && createVNode(VFieldLabel, mergeProps({
"key": "floating-label",
"ref": floatingLabelRef,
"class": [textColorClasses.value],
"floating": true
}, floatingLabelProps.value, { "style": textColorStyles.value }), { default: () => [label()] }),
hasLabel.value && createVNode(VFieldLabel, mergeProps({
"key": "label",
"ref": labelRef,
"id": props.labelId
}, mainLabelProps.value), { default: () => [label()] }),
slots.default?.({
...slotProps.value,
props: {
id: id.value,
class: "v-field__input",
"aria-describedby": messagesId.value
},
focus,
blur
}) ?? createBaseVNode("div", {
"id": id.value,
"class": "v-field__input",
"aria-describedby": messagesId.value
}, null)
]),
hasClear && createVNode(VExpandXTransition, { "key": "clear" }, { default: () => [withDirectives(createBaseVNode("div", {
"class": "v-field__clearable",
"onMousedown": (e) => {
e.preventDefault();
e.stopPropagation();
}
}, [createVNode(VDefaultsProvider, { "defaults": { VIcon: { icon: props.clearIcon } } }, { default: () => [slots.clear ? slots.clear({
...slotProps.value,
props: {
onFocus: focus,
onBlur: blur,
onClick: props["onClick:clear"],
tabindex: -1
}
}) : createVNode(InputIcon, {
"name": "clear",
"onFocus": focus,
"onBlur": blur,
"tabindex": -1
}, null)] })]), [[vShow, props.dirty]])] }),
hasAppend && createBaseVNode("div", {
"key": "append",
"class": "v-field__append-inner"
}, [slots["append-inner"] ? slots["append-inner"](slotProps.value) : props.appendInnerIcon && createVNode(InputIcon, {
"key": "append-icon",
"name": "appendInner",
"color": iconColor.value
}, null)]),
createBaseVNode("div", {
"class": normalizeClass(["v-field__outline", textColorClasses.value]),
"style": normalizeStyle(textColorStyles.value)
}, [isOutlined && createBaseVNode(Fragment, null, [
createBaseVNode("div", { "class": "v-field__outline__start" }, null),
hasFloatingLabel.value && createBaseVNode("div", { "class": "v-field__outline__notch" }, [createVNode(VFieldLabel, mergeProps({
"ref": floatingLabelRef,
"floating": true
}, floatingLabelProps.value), { default: () => [label()] })]),
createBaseVNode("div", { "class": "v-field__outline__end" }, null)
]), isPlainOrUnderlined.value && hasFloatingLabel.value && createVNode(VFieldLabel, mergeProps({
"ref": floatingLabelRef,
"floating": true
}, floatingLabelProps.value), { default: () => [label()] })])
]);
});
return {
controlRef,
fieldIconColor: iconColor
};
}
});
//#endregion
//#region node_modules/vuetify/lib/composables/autocomplete.js
var makeAutocompleteProps = propsFactory({ autocomplete: String }, "autocomplete");
function useAutocomplete(props) {
const uniqueId = useId();
const reloadTrigger = shallowRef(0);
const isSuppressing = toRef(() => props.autocomplete === "suppress");
const fieldName = toRef(() => {
if (!props.name) return void 0;
return isSuppressing.value ? `${props.name}-${uniqueId}-${reloadTrigger.value}` : props.name;
});
return {
isSuppressing,
fieldAutocomplete: toRef(() => {
return isSuppressing.value ? "off" : props.autocomplete;
}),
fieldName,
update: () => reloadTrigger.value = (/* @__PURE__ */ new Date()).getTime()
};
}
//#endregion
//#region node_modules/vuetify/lib/composables/autofocus.js
function useAutofocus(props) {
function onIntersect(isIntersecting, entries) {
if (!props.autofocus || !isIntersecting) return;
const el = entries[0].target;
(el.matches("input,textarea") ? el : el.querySelector("input,textarea"))?.focus();
}
return { onIntersect };
}
//#endregion
//#region node_modules/vuetify/lib/components/VTextField/VTextField.js
var activeTypes = [
"color",
"file",
"time",
"date",
"datetime-local",
"week",
"month"
];
var makeVTextFieldProps = propsFactory({
autofocus: Boolean,
counter: [
Boolean,
Number,
String
],
counterValue: [Number, Function],
prefix: String,
placeholder: String,
persistentPlaceholder: Boolean,
persistentCounter: Boolean,
suffix: String,
role: String,
type: {
type: String,
default: "text"
},
modelModifiers: Object,
...makeAutocompleteProps(),
...omit(makeVInputProps(), ["direction"]),
...makeVFieldProps()
}, "VTextField");
var VTextField = genericComponent()({
name: "VTextField",
directives: { vIntersect: Intersect },
inheritAttrs: false,
props: makeVTextFieldProps(),
emits: {
"click:control": (e) => true,
"mousedown:control": (e) => true,
"update:focused": (focused) => true,
"update:modelValue": (val) => true
},
setup(props, { attrs, emit, slots }) {
const model = useProxiedModel(props, "modelValue", void 0, (v) => {
if (Object.is(v, -0)) return "-0";
return v;
});
const { isFocused, focus, blur } = useFocus(props);
const { onIntersect } = useAutofocus(props);
const counterValue = computed(() => {
return typeof props.counterValue === "function" ? props.counterValue(model.value) : typeof props.counterValue === "number" ? props.counterValue : (model.value ?? "").toString().length;
});
const max = computed(() => {
if (attrs.maxlength) return attrs.maxlength;
if (!props.counter || typeof props.counter !== "number" && typeof props.counter !== "string") return void 0;
return props.counter;
});
const isPlainOrUnderlined = computed(() => ["plain", "underlined"].includes(props.variant));
const vInputRef = ref();
const vFieldRef = ref();
const inputRef = ref();
const autocomplete = useAutocomplete(props);
const isActive = computed(() => activeTypes.includes(props.type) || props.persistentPlaceholder || isFocused.value || props.active);
function onFocus() {
if (autocomplete.isSuppressing.value) autocomplete.update();
if (!isFocused.value) focus();
nextTick(() => {
if (inputRef.value !== document.activeElement) inputRef.value?.focus();
});
}
function onControlMousedown(e) {
emit("mousedown:control", e);
if (e.target === inputRef.value) return;
onFocus();
e.preventDefault();
}
function onControlClick(e) {
emit("click:control", e);
}
function onClear(e, reset) {
e.stopPropagation();
onFocus();
nextTick(() => {
reset();
callEvent(props["onClick:clear"], e);
});
}
function onInput(e) {
const el = e.target;
if (!(props.modelModifiers?.trim && [
"text",
"search",
"password",
"tel",
"url"
].includes(props.type))) {
model.value = el.value;
return;
}
const value = el.value;
const start = el.selectionStart;
const end = el.selectionEnd;
model.value = value;
nextTick(() => {
let offset = 0;
if (value.trimStart().length === el.value.length) offset = value.length - el.value.length;
if (start != null) el.selectionStart = start - offset;
if (end != null) el.selectionEnd = end - offset;
});
}
useRender(() => {
const hasCounter = !!(slots.counter || props.counter !== false && props.counter != null);
const hasDetails = !!(hasCounter || slots.details);
const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
const { modelValue: _, ...inputProps } = VInput.filterProps(props);
const fieldProps = VField.filterProps(props);
return createVNode(VInput, mergeProps({
"ref": vInputRef,
"modelValue": model.value,
"onUpdate:modelValue": ($event) => model.value = $event,
"class": [
"v-text-field",
{
"v-text-field--prefixed": props.prefix,
"v-text-field--suffixed": props.suffix,
"v-input--plain-underlined": isPlainOrUnderlined.value
},
props.class
],
"style": props.style
}, rootAttrs, inputProps, {
"centerAffix": !isPlainOrUnderlined.value,
"focused": isFocused.value,
"indentDetails": props.indentDetails ?? !isPlainOrUnderlined.value
}), {
...slots,
default: ({ id, isDisabled, isDirty, isReadonly, isValid, hasDetails, reset }) => createVNode(VField, mergeProps({
"ref": vFieldRef,
"onMousedown": onControlMousedown,
"onClick": onControlClick,
"onClick:clear": (e) => onClear(e, reset),
"role": props.role
}, omit(fieldProps, ["onClick:clear"]), {
"id": id.value,
"labelId": `${id.value}-label`,
"active": isActive.value || isDirty.value,
"dirty": isDirty.value || props.dirty,
"disabled": isDisabled.value,
"focused": isFocused.value,
"details": hasDetails.value,
"error": isValid.value === false
}), {
...slots,
default: ({ props: { class: fieldClass, ...slotProps }, controlRef }) => {
const inputNode = createBaseVNode("input", mergeProps({
"ref": (val) => inputRef.value = controlRef.value = val,
"value": model.value,
"onInput": onInput,
"autofocus": props.autofocus,
"readonly": isReadonly.value,
"disabled": isDisabled.value,
"name": autocomplete.fieldName.value,
"autocomplete": autocomplete.fieldAutocomplete.value,
"placeholder": props.placeholder,
"size": 1,
"role": props.role,
"type": props.type,
"onFocus": focus,
"onBlur": blur,
"aria-labelledby": `${id.value}-label`
}, slotProps, inputAttrs), null);
return createBaseVNode(Fragment, null, [
props.prefix && createBaseVNode("span", { "class": "v-text-field__prefix" }, [createBaseVNode("span", { "class": "v-text-field__prefix__text" }, [props.prefix])]),
withDirectives(slots.default ? createBaseVNode("div", {
"class": normalizeClass(fieldClass),
"data-no-activator": ""
}, [slots.default({ id }), inputNode]) : cloneVNode(inputNode, { class: fieldClass }), [[
Intersect,
onIntersect,
null,
{ once: true }
]]),
props.suffix && createBaseVNode("span", { "class": "v-text-field__suffix" }, [createBaseVNode("span", { "class": "v-text-field__suffix__text" }, [props.suffix])])
]);
}
}),
details: hasDetails ? (slotProps) => createBaseVNode(Fragment, null, [slots.details?.(slotProps), hasCounter && createBaseVNode(Fragment, null, [createBaseVNode("span", null, null), createVNode(VCounter, {
"active": props.persistentCounter || isFocused.value,
"value": counterValue.value,
"max": max.value,
"disabled": props.disabled
}, slots.counter)])]) : void 0
});
});
return forwardRefs({}, vInputRef, vFieldRef, inputRef);
}
});
//#endregion
//#region node_modules/vuetify/lib/components/VVirtualScroll/VVirtualScrollItem.js
var makeVVirtualScrollItemProps = propsFactory({
renderless: Boolean,
...makeComponentProps()
}, "VVirtualScrollItem");
var VVirtualScrollItem = genericComponent()({
name: "VVirtualScrollItem",
inheritAttrs: false,
props: makeVVirtualScrollItemProps(),
emits: { "update:height": (height) => true },
setup(props, { attrs, emit, slots }) {
const { resizeRef, contentRect } = useResizeObserver(void 0, "border");
watch(() => contentRect.value?.height, (height) => {
if (height != null) emit("update:height", height);
});
useRender(() => props.renderless ? createBaseVNode(Fragment, null, [slots.default?.({ itemRef: resizeRef })]) : createBaseVNode("div", mergeProps({
"ref": resizeRef,
"class": ["v-virtual-scroll__item", props.class],
"style": props.style
}, attrs), [slots.default?.()]));
}
});
//#endregion
//#region node_modules/vuetify/lib/composables/virtual.js
var UP = -1;
var DOWN = 1;
/** Determines how large each batch of items should be */
var BUFFER_PX = 100;
var makeVirtualProps = propsFactory({
itemHeight: {
type: [Number, String],
default: null
},
itemKey: {
type: [
String,
Array,
Function
],
default: null
},
height: [Number, String]
}, "virtual");
function useVirtual(props, items) {
const display = useDisplay();
const itemHeight = shallowRef(0);
watchEffect(() => {
itemHeight.value = parseFloat(props.itemHeight || 0);
});
const first = shallowRef(0);
const last = shallowRef(Math.ceil((parseInt(props.height) || display.height.value) / (itemHeight.value || 16)) || 1);
const paddingTop = shallowRef(0);
const paddingBottom = shallowRef(0);
/** The scrollable element */
const containerRef = ref();
/** An element marking the top of the scrollable area,
* used to add an offset if there's padding or other elements above the virtual list */
const markerRef = ref();
/** markerRef's offsetTop, lazily evaluated */
let markerOffset = 0;
const { resizeRef, contentRect } = useResizeObserver();
watchEffect(() => {
resizeRef.value = containerRef.value;
});
const viewportHeight = computed(() => {
return containerRef.value === document.documentElement ? display.height.value : contentRect.value?.height || parseInt(props.height) || 0;
});
/** All static elements have been rendered and we have an assumed item height */
const hasInitialRender = computed(() => {
return !!(containerRef.value && markerRef.value && viewportHeight.value && itemHeight.value);
});
let sizes = Array.from({ length: items.value.length });
let offsets = Array.from({ length: items.value.length });
const updateTime = shallowRef(0);
let targetScrollIndex = -1;
function getSize(index) {
return sizes[index] || itemHeight.value;
}
const updateOffsets = debounce(() => {
const start = performance.now();
offsets[0] = 0;
const length = items.value.length;
for (let i = 1; i <= length; i++) offsets[i] = (offsets[i - 1] || 0) + getSize(i - 1);
updateTime.value = Math.max(updateTime.value, performance.now() - start);
}, updateTime);
const unwatch = watch(hasInitialRender, (v) => {
if (!v) return;
unwatch();
markerOffset = markerRef.value.offsetTop;
updateOffsets.immediate();
calculateVisibleItems();
if (!~targetScrollIndex) return;
nextTick(() => {
IN_BROWSER && window.requestAnimationFrame(() => {
scrollToIndex(targetScrollIndex);
targetScrollIndex = -1;
});
});
});
onScopeDispose(() => {
updateOffsets.clear();
});
function handleItemResize(index, height) {
const prevHeight = sizes[index];
const prevMinHeight = itemHeight.value;
itemHeight.value = prevMinHeight ? Math.min(itemHeight.value, height) : height;
if (prevHeight !== height || prevMinHeight !== itemHeight.value) {
sizes[index] = height;
updateOffsets();
}
}
function calculateOffset(index) {
index = clamp(index, 0, items.value.length);
const whole = Math.floor(index);
const fraction = index % 1;
const next = whole + 1;
const wholeOffset = offsets[whole] || 0;
return wholeOffset + ((offsets[next] || wholeOffset) - wholeOffset) * fraction;
}
function calculateIndex(scrollTop) {
return binaryClosest(offsets, scrollTop);
}
let lastScrollTop = 0;
let scrollVelocity = 0;
let lastScrollTime = 0;
watch(viewportHeight, (val, oldVal) => {
calculateVisibleItems();
if (val < oldVal) requestAnimationFrame(() => {
scrollVelocity = 0;
calculateVisibleItems();
});
});
let scrollTimeout = -1;
function handleScroll() {
if (!containerRef.value || !markerRef.value) return;
const scrollTop = containerRef.value.scrollTop;
const scrollTime = performance.now();
if (scrollTime - lastScrollTime > 500) {
scrollVelocity = Math.sign(scrollTop - lastScrollTop);
markerOffset = markerRef.value.offsetTop;
} else scrollVelocity = scrollTop - lastScrollTop;
lastScrollTop = scrollTop;
lastScrollTime = scrollTime;
window.clearTimeout(scrollTimeout);
scrollTimeout = window.setTimeout(handleScrollend, 500);
calculateVisibleItems();
}
function handleScrollend() {
if (!containerRef.value || !markerRef.value) return;
scrollVelocity = 0;
lastScrollTime = 0;
window.clearTimeout(scrollTimeout);
calculateVisibleItems();
}
let raf = -1;
function calculateVisibleItems() {
cancelAnimationFrame(raf);
raf = requestAnimationFrame(_calculateVisibleItems);
}
function _calculateVisibleItems() {
if (!containerRef.value || !viewportHeight.value || !itemHeight.value) return;
const scrollTop = lastScrollTop - markerOffset;
const direction = Math.sign(scrollVelocity);
const start = clamp(calculateIndex(Math.max(0, scrollTop - BUFFER_PX)), 0, items.value.length);
const end = clamp(calculateIndex(scrollTop + viewportHeight.value + BUFFER_PX) + 1, start + 1, items.value.length);
if ((direction !== UP || start < first.value) && (direction !== DOWN || end > last.value)) {
const topOverflow = calculateOffset(first.value) - calculateOffset(start);
const bottomOverflow = calculateOffset(end) - calculateOffset(last.value);
if (Math.max(topOverflow, bottomOverflow) > BUFFER_PX) {
first.value = start;
last.value = end;
} else {
if (start <= 0) first.value = start;
if (end >= items.value.length) last.value = end;
}
}
paddingTop.value = calculateOffset(first.value);
paddingBottom.value = calculateOffset(items.value.length) - calculateOffset(last.value);
}
function scrollToIndex(index) {
const offset = calculateOffset(index);
if (!containerRef.value || index && !offset) targetScrollIndex = index;
else containerRef.value.scrollTop = offset;
}
const computedItems = computed(() => {
return items.value.slice(first.value, last.value).map((item, index) => {
const _index = index + first.value;
return {
raw: item,
index: _index,
key: getPropertyFromItem(item, props.itemKey, _index)
};
});
});
watch(items, () => {
sizes = Array.from({ length: items.value.length });
offsets = Array.from({ length: items.value.length });
updateOffsets.immediate();
calculateVisibleItems();
}, { deep: 1 });
return {
calculateVisibleItems,
containerRef,
markerRef,
computedItems,
paddingTop,
paddingBottom,
scrollToIndex,
handleScroll,
handleScrollend,
handleItemResize
};
}
function binaryClosest(arr, val) {
let high = arr.length - 1;
let low = 0;
let mid = 0;
let item = null;
let target = -1;
if (arr[high] < val) return high;
while (low <= high) {
mid = low + high >> 1;
item = arr[mid];
if (item > val) high = mid - 1;
else if (item < val) {
target = mid;
low = mid + 1;
} else if (item === val) return mid;
else return low;
}
return target;
}
//#endregion
//#region node_modules/vuetify/lib/components/VVirtualScroll/VVirtualScroll.js
var makeVVirtualScrollProps = propsFactory({
items: {
type: Array,
default: () => []
},
renderless: Boolean,
...makeVirtualProps(),
...makeComponentProps(),
...makeDimensionProps()
}, "VVirtualScroll");
var VVirtualScroll = genericComponent()({
name: "VVirtualScroll",
props: makeVVirtualScrollProps(),
setup(props, { slots }) {
const vm = getCurrentInstance("VVirtualScroll");
const { dimensionStyles } = useDimension(props);
const { calculateVisibleItems, containerRef, markerRef, handleScroll, handleScrollend, handleItemResize, scrollToIndex, paddingTop, paddingBottom, computedItems } = useVirtual(props, toRef(() => props.items));
useToggleScope(() => props.renderless, () => {
function handleListeners(add = false) {
const method = add ? "addEventListener" : "removeEventListener";
if (!IN_BROWSER) return;
if (containerRef.value === document.documentElement) {
document[method]("scroll", handleScroll, { passive: true });
document[method]("scrollend", handleScrollend);
} else {
containerRef.value?.[method]("scroll", handleScroll, { passive: true });
containerRef.value?.[method]("scrollend", handleScrollend);
}
}
onMounted(() => {
containerRef.value = getScrollParent(vm.vnode.el, true);
handleListeners(true);
});
onScopeDispose(handleListeners);
});
useRender(() => {
const children = computedItems.value.map((item) => createVNode(VVirtualScrollItem, {
"key": item.key,
"renderless": props.renderless,
"onUpdate:height": (height) => handleItemResize(item.index, height)
}, { default: (slotProps) => slots.default?.({
item: item.raw,
index: item.index,
...slotProps
}) }));
return props.renderless ? createBaseVNode(Fragment, null, [
createBaseVNode("div", {
"ref": markerRef,
"class": "v-virtual-scroll__spacer",
"style": { paddingTop: convertToUnit(paddingTop.value) }
}, null),
children,
createBaseVNode("div", {
"class": "v-virtual-scroll__spacer",
"style": { paddingBottom: convertToUnit(paddingBottom.value) }
}, null)
]) : createBaseVNode("div", {
"ref": containerRef,
"class": normalizeClass(["v-virtual-scroll", props.class]),
"onScrollPassive": handleScroll,
"onScrollend": handleScrollend,
"style": normalizeStyle([dimensionStyles.value, props.style])
}, [createBaseVNode("div", {
"ref": markerRef,
"class": "v-virtual-scroll__container",
"style": {
paddingTop: convertToUnit(paddingTop.value),
paddingBottom: convertToUnit(paddingBottom.value)
}
}, [children])]);
});
return {
calculateVisibleItems,
scrollToIndex
};
}
});
//#endregion
//#region node_modules/vuetify/lib/components/VSelect/useScrolling.js
function useScrolling(listRef, textFieldRef) {
const isScrolling = shallowRef(false);
let scrollTimeout;
function onListScroll(e) {
cancelAnimationFrame(scrollTimeout);
isScrolling.value = true;
scrollTimeout = requestAnimationFrame(() => {
scrollTimeout = requestAnimationFrame(() => {
isScrolling.value = false;
});
});
}
async function finishScrolling() {
await new Promise((resolve) => requestAnimationFrame(resolve));
await new Promise((resolve) => requestAnimationFrame(resolve));
await new Promise((resolve) => requestAnimationFrame(resolve));
await new Promise((resolve) => {
if (isScrolling.value) {
const stop = watch(isScrolling, () => {
stop();
resolve();
});
} else resolve();
});
}
async function onListKeydown(e) {
if (e.key === "Tab") textFieldRef.value?.focus();
if (![
"PageDown",
"PageUp",
"Home",
"End"
].includes(e.key)) return;
const el = listRef.value?.$el;
if (!el) return;
if (e.key === "Home" || e.key === "End") el.scrollTo({
top: e.key === "Home" ? 0 : el.scrollHeight,
behavior: "smooth"
});
await finishScrolling();
const children = el.querySelectorAll(":scope > :not(.v-virtual-scroll__spacer)");
if (e.key === "PageDown" || e.key === "Home") {
const top = el.getBoundingClientRect().top;
for (const child of children) if (child.getBoundingClientRect().top >= top) {
child.focus();
break;
}
} else {
const bottom = el.getBoundingClientRect().bottom;
for (const child of [...children].reverse()) if (child.getBoundingClientRect().bottom <= bottom) {
child.focus();
break;
}
}
}
return {
onScrollPassive: onListScroll,
onKeydown: onListKeydown
};
}
//#endregion
//#region node_modules/vuetify/lib/composables/focusGroups.js
function useFocusGroups({ groups, onLeave }) {
function getContentRef(group) {
return group.type === "list" ? group.contentRef.value?.$el : group.contentRef.value;
}
function getChildren(group) {
const contentRef = getContentRef(group);
return contentRef ? focusableChildren(contentRef) : [];
}
function onTabKeydown(e) {
const target = e.target;
const direction = e.shiftKey ? "backward" : "forward";
const children = groups.map(getChildren);
const currentGroupIndex = groups.map((g) => g.type === "list" ? g.contentRef.value?.$el : g.contentRef.value).findIndex((el) => el?.contains(target));
const nextIndex = nextFocusGroup(children, currentGroupIndex, direction, target);
if (nextIndex === null) {
const originGroup = groups[currentGroupIndex];
const origin = children[currentGroupIndex];
if (originGroup.type === "list" || (direction === "forward" ? origin.at(-1) === e.target : origin.at(0) === e.target)) onLeave();
} else {
e.preventDefault();
e.stopImmediatePropagation();
const nextGroup = groups[nextIndex];
if (nextGroup.type === "list" && toValue(nextGroup.displayItemsCount) > 0) nextGroup.contentRef.value?.focus(0);
else {
const fromBefore = direction === "forward";
children[nextIndex].at(fromBefore ? 0 : -1).focus();
}
}
}
function nextFocusGroup(children, currentIndex, direction, target) {
const originGroup = groups[currentIndex];
const origin = children[currentIndex];
if (originGroup.type !== "list") {
if (!(direction === "forward" ? origin.at(-1) === target : origin.at(0) === target)) return null;
}
const step = direction === "forward" ? 1 : -1;
for (let i = currentIndex + step; i >= 0 && i < groups.length; i += step) {
const group = groups[i];
if (children[i].length > 0 || group.type === "list" && toValue(group.displayItemsCount) > 0) return i;
}
return null;
}
return { onTabKeydown };
}
//#endregion
//#region node_modules/vuetify/lib/composables/filter.js
/**
* - boolean: match without highlight
* - number: single match (index), length already known
* - []: single match (start, end)
* - [][]: multiple matches (start, end), shouldn't overlap
*/
var defaultFilter = (value, query, item) => {
if (value == null || query == null) return -1;
if (!query.length) return 0;
value = value.toString().toLocaleLowerCase();
query = query.toString().toLocaleLowerCase();
const result = [];
let idx = value.indexOf(query);
while (~idx) {
result.push([idx, idx + query.length]);
idx = value.indexOf(query, idx + query.length);
}
return result.length ? result : -1;
};
function normaliseMatch(match, query) {
if (match == null || typeof match === "boolean" || match === -1) return;
if (typeof match === "number") return [[match, match + query.length]];
if (Array.isArray(match[0])) return match;
return [match];
}
var makeFilterProps = propsFactory({
customFilter: Function,
customKeyFilter: Object,
filterKeys: [Array, String],
filterMode: {
type: String,
default: "intersection"
},
noFilter: Boolean
}, "filter");
function filterItems(items, query, options) {
const array = [];
const filter = options?.default ?? defaultFilter;
const keys = options?.filterKeys ? wrapInArray(options.filterKeys) : false;
const customFiltersLength = Object.keys(options?.customKeyFilter ?? {}).length;
if (!items?.length) return array;
let lookAheadItems = [];
loop: for (let i = 0; i < items.length; i++) {
const [item, transformed = item] = wrapInArray(items[i]);
const customMatches = {};
const defaultMatches = {};
let match = -1;
if ((query || customFiltersLength > 0) && !options?.noFilter) {
let hasOnlyCustomFilters = false;
if (typeof item === "object") {
if (item.type === "divider" || item.type === "subheader") {
if (lookAheadItems.at(-1)?.type !== "divider" || item.type !== "subheader") lookAheadItems = [];
lookAheadItems.push({
index: i,
matches: {},
type: item.type
});
continue;
}
const filterKeys = keys || Object.keys(transformed);
hasOnlyCustomFilters = filterKeys.length === customFiltersLength;
for (const key of filterKeys) {
const value = getPropertyFromItem(transformed, key);
const keyFilter = options?.customKeyFilter?.[key];
match = keyFilter ? keyFilter(value, query, item) : filter(value, query, item);
if (match !== -1 && match !== false) if (keyFilter) customMatches[key] = normaliseMatch(match, query);
else defaultMatches[key] = normaliseMatch(match, query);
else if (options?.filterMode === "every") continue loop;
}
} else {
match = filter(item, query, item);
if (match !== -1 && match !== false) defaultMatches.title = normaliseMatch(match, query);
}
const defaultMatchesLength = Object.keys(defaultMatches).length;
const customMatchesLength = Object.keys(customMatches).length;
if (!defaultMatchesLength && !customMatchesLength) continue;
if (options?.filterMode === "union" && customMatchesLength !== customFiltersLength && !defaultMatchesLength) continue;
if (options?.filterMode === "intersection" && (customMatchesLength !== customFiltersLength || !defaultMatchesLength && customFiltersLength > 0 && !hasOnlyCustomFilters)) continue;
}
if (lookAheadItems.length) {
array.push(...lookAheadItems);
lookAheadItems = [];
}
array.push({
index: i,
matches: {
...defaultMatches,
...customMatches
}
});
}
return array;
}
function useFilter(props, items, query, options) {
const filteredItems = shallowRef([]);
const filteredMatches = shallowRef(/* @__PURE__ */ new Map());
const transformedItems = computed(() => options?.transform ? unref(items).map((item) => [item, options.transform(item)]) : unref(items));
watchEffect(() => {
const _query = typeof query === "function" ? query() : unref(query);
const strQuery = typeof _query !== "string" && typeof _query !== "number" ? "" : String(_query);
const results = filterItems(transformedItems.value, strQuery, {
customKeyFilter: {
...props.customKeyFilter,
...unref(options?.customKeyFilter)
},
default: props.customFilter,
filterKeys: props.filterKeys,
filterMode: props.filterMode,
noFilter: props.noFilter
});
const originalItems = unref(items);
const _filteredItems = [];
const _filteredMatches = /* @__PURE__ */ new Map();
results.forEach(({ index, matches }) => {
const item = originalItems[index];
_filteredItems.push(item);
_filteredMatches.set(item.value, matches);
});
filteredItems.value = _filteredItems;
filteredMatches.value = _filteredMatches;
});
function getMatches(item) {
return filteredMatches.value.get(item.value);
}
return {
filteredItems,
filteredMatches,
getMatches
};
}
function highlightResult(name, text, matches) {
if (matches == null || !matches.length) return text;
return matches.map((match, i) => {
const start = i === 0 ? 0 : matches[i - 1][1];
const result = [createBaseVNode("span", { "class": normalizeClass(`${name}__unmask`) }, [text.slice(start, match[0])]), createBaseVNode("span", { "class": normalizeClass(`${name}__mask`) }, [text.slice(match[0], match[1])])];
if (i === matches.length - 1) result.push(createBaseVNode("span", { "class": normalizeClass(`${name}__unmask`) }, [text.slice(match[1])]));
return createBaseVNode(Fragment, null, [result]);
});
}
//#endregion
//#region node_modules/vuetify/lib/composables/menuActivator.js
var makeMenuActivatorProps = propsFactory({
closeText: {
type: String,
default: "$vuetify.close"
},
openText: {
type: String,
default: "$vuetify.open"
}
}, "autocomplete");
function useMenuActivator(props, isOpen) {
const uid = useId();
const menuId = computed(() => `menu-${uid}`);
return {
menuId,
ariaExpanded: toRef(() => toValue(isOpen)),
ariaControls: toRef(() => menuId.value)
};
}
//#endregion
//#region node_modules/vuetify/lib/components/VSelect/VSelect.js
var makeSelectProps = propsFactory({
chips: Boolean,
closableChips: Boolean,
eager: Boolean,
hideNoData: Boolean,
hideSelected: Boolean,
listProps: { type: Object },
menu: Boolean,
menuElevation: [Number, String],
menuIcon: {
type: IconValue,
default: "$dropdown"
},
menuProps: { type: Object },
multiple: Boolean,
noDataText: {
type: String,
default: "$vuetify.noDataText"
},
openOnClear: Boolean,
itemColor: String,
noAutoScroll: Boolean,
...makeMenuActivatorProps(),
...makeItemsProps({ itemChildren: false })
}, "Select");
var makeVSelectProps = propsFactory({
search: String,
...makeFilterProps({ filterKeys: ["title"] }),
...makeSelectProps(),
...omit(makeVTextFieldProps({
modelValue: null,
role: "combobox"
}), ["validationValue", "dirty"]),
...makeTransitionProps({ transition: { component: VDialogTransition } })
}, "VSelect");
var VSelect = genericComponent()({
name: "VSelect",
props: makeVSelectProps(),
emits: {
"update:focused": (focused) => true,
"update:modelValue": (value) => true,
"update:menu": (ue) => true,
"update:search": (value) => true
},
setup(props, { slots }) {
const { t } = useLocale();
const vTextFieldRef = ref();
const vMenuRef = ref();
const headerRef = ref();
const footerRef = ref();
const vVirtualScrollRef = ref();
const { items, transformIn, transformOut } = useItems(props);
const search = useProxiedModel(props, "search", "");
const { filteredItems, getMatches } = useFilter(props, items, () => search.value);
const model = useProxiedModel(props, "modelValue", [], (v) => transformIn(v === null ? [null] : wrapInArray(v)), (v) => {
const transformed = transformOut(v);
return props.multiple ? transformed : transformed[0] ?? null;
});
const counterValue = computed(() => {
return typeof props.counterValue === "function" ? props.counterValue(model.value) : typeof props.counterValue === "number" ? props.counterValue : model.value.length;
});
const form = useForm(props);
const autocomplete = useAutocomplete(props);
const selectedValues = computed(() => model.value.map((selection) => selection.value));
const isFocused = shallowRef(false);
const closableChips = toRef(() => props.closableChips && !form.isReadonly.value && !form.isDisabled.value);
const { InputIcon } = useInputIcon(props);
let keyboardLookupPrefix = "";
let keyboardLookupIndex = 0;
let keyboardLookupLastTime;
const displayItems = computed(() => {
const baseItems = search.value ? filteredItems.value : items.value;
if (props.hideSelected) return baseItems.filter((item) => !model.value.some((s) => (props.valueComparator || deepEqual)(s, item)));
return baseItems;
});
const menuDisabled = computed(() => props.hideNoData && !displayItems.value.length || form.isReadonly.value || form.isDisabled.value);
const _menu = useProxiedModel(props, "menu");
const menu = computed({
get: () => _menu.value,
set: (v) => {
if (_menu.value && !v && vMenuRef.value?.ΨopenChildren.size) return;
if (v && menuDisabled.value) return;
_menu.value = v;
}
});
const { menuId, ariaExpanded, ariaControls } = useMenuActivator(props, menu);
const computedMenuProps = computed(() => {
return {
...props.menuProps,
activatorProps: {
...props.menuProps?.activatorProps || {},
"aria-haspopup": "listbox"
}
};
});
const listRef = ref();
const listEvents = useScrolling(listRef, vTextFieldRef);
const { onTabKeydown } = useFocusGroups({
groups: [
{
type: "element",
contentRef: headerRef
},
{
type: "list",
contentRef: listRef,
displayItemsCount: () => displayItems.value.length
},
{
type: "element",
contentRef: footerRef
}
],
onLeave: () => {
menu.value = false;
vTextFieldRef.value?.focus();
}
});
function onClear(e) {
if (props.openOnClear) menu.value = true;
}
function onMousedownControl() {
if (menuDisabled.value) return;
menu.value = !menu.value;
}
function onMenuKeydown(e) {
if (e.key === "Tab") onTabKeydown(e);
if (listRef.value?.$el.contains(e.target) && checkPrintable(e)) onKeydown(e);
}
function onKeydown(e) {
if (!e.key || form.isReadonly.value) return;
if ([
"Enter",
" ",
"ArrowDown",
"ArrowUp",
"Home",
"End"
].includes(e.key)) e.preventDefault();
if ([
"Enter",
"ArrowDown",
" "
].includes(e.key)) menu.value = true;
if (["Escape", "Tab"].includes(e.key)) menu.value = false;
if (props.clearable && e.key === "Backspace") {
e.preventDefault();
model.value = [];
onClear(e);
return;
}
if (e.key === "Home") listRef.value?.focus("first");
else if (e.key === "End") listRef.value?.focus("last");
const KEYBOARD_LOOKUP_THRESHOLD = 1e3;
if (!checkPrintable(e)) return;
const now = performance.now();
if (now - keyboardLookupLastTime > KEYBOARD_LOOKUP_THRESHOLD) {
keyboardLookupPrefix = "";
keyboardLookupIndex = 0;
}
keyboardLookupPrefix += e.key.toLowerCase();
keyboardLookupLastTime = now;
const items = displayItems.value;
function findItem() {
let result = findItemBase();
if (result) return result;
if (keyboardLookupPrefix.at(-1) === keyboardLookupPrefix.at(-2)) {
keyboardLookupPrefix = keyboardLookupPrefix.slice(0, -1);
keyboardLookupIndex++;
result = findItemBase();
if (result) return result;
}
keyboardLookupIndex = 0;
result = findItemBase();
if (result) return result;
keyboardLookupPrefix = e.key.toLowerCase();
return findItemBase();
}
function findItemBase() {
for (let i = keyboardLookupIndex; i < items.length; i++) {
const _item = items[i];
if (_item.title.toLowerCase().startsWith(keyboardLookupPrefix)) return [_item, i];
}
}
const result = findItem();
if (!result) return;
const [item, index] = result;
keyboardLookupIndex = index;
listRef.value?.focus(index);
if (!props.multiple) model.value = [item];
}
/** @param set - null means toggle */
function select(item, set = true) {
if (item.props.disabled) return;
if (props.multiple) {
const index = model.value.findIndex((selection) => (props.valueComparator || deepEqual)(selection.value, item.value));
const add = set == null ? !~index : set;
if (~index) {
const value = add ? [...model.value, item] : [...model.value];
value.splice(index, 1);
model.value = value;
} else if (add) model.value = [...model.value, item];
} else {
model.value = set !== false ? [item] : [];
nextTick(() => {
menu.value = false;
});
}
}
function onBlur(e) {
const target = e.target;
if (!vTextFieldRef.value?.$el.contains(target)) menu.value = false;
}
function getSelectedIndex() {
return displayItems.value.findIndex((item) => model.value.some((s) => (props.valueComparator || deepEqual)(s.value, item.value)));
}
function getSelectedFocusableIndex() {
if (!model.value.length) return -1;
const comparator = props.valueComparator || deepEqual;
let focusableIndex = 0;
for (const item of displayItems.value) {
if (model.value.some((s) => comparator(s.value, item.value))) return item.props.disabled ? -1 : focusableIndex;
if (!item.props.disabled) focusableIndex++;
}
return -1;
}
function onAfterEnter() {
if (props.eager) vVirtualScrollRef.value?.calculateVisibleItems();
if (listRef.value && isFocused.value) {
const index = getSelectedFocusableIndex();
listRef.value.focus(index >= 0 ? index : "first");
}
}
function onAfterLeave() {
search.value = "";
if (isFocused.value) vTextFieldRef.value?.focus();
}
function onFocusin(e) {
isFocused.value = true;
}
function onFocusout(e) {
if (!vTextFieldRef.value?.$el.contains(e.relatedTarget) && !e.currentTarget.contains(e.relatedTarget)) isFocused.value = false;
}
function onModelUpdate(v) {
if (v == null) model.value = [];
else if (matchesSelector(vTextFieldRef.value, ":autofill") || matchesSelector(vTextFieldRef.value, ":-webkit-autofill")) {
const item = items.value.find((item) => item.title === v);
if (item) select(item);
} else if (vTextFieldRef.value) vTextFieldRef.value.value = "";
}
watch(menu, () => {
if (!props.hideSelected && menu.value && model.value.length) {
const index = getSelectedIndex();
IN_BROWSER && !props.noAutoScroll && window.requestAnimationFrame(() => {
index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
});
}
});
watch(items, (newVal, oldVal) => {
if (menu.value) return;
if (isFocused.value && props.hideNoData && !oldVal.length && newVal.length) menu.value = true;
});
useRender(() => {
const hasChips = !!(props.chips || slots.chip);
const hasList = !!(!props.hideNoData || displayItems.value.length || slots["prepend-item"] || slots["append-item"] || slots["no-data"]);
const isDirty = model.value.length > 0;
const textFieldProps = VTextField.filterProps(props);
const placeholder = isDirty || !isFocused.value && props.label && !props.persistentPlaceholder ? void 0 : props.placeholder;
const menuSlotProps = {
search,
filteredItems: filteredItems.value
};
return createVNode(VTextField, mergeProps({ "ref": vTextFieldRef }, textFieldProps, {
"modelValue": model.value.map((v) => v.props.title).join(", "),
"name": void 0,
"onUpdate:modelValue": onModelUpdate,
"focused": isFocused.value,
"onUpdate:focused": ($event) => isFocused.value = $event,
"validationValue": model.externalValue,
"counterValue": counterValue.value,
"dirty": isDirty,
"class": [
"v-select",
{
"v-select--active-menu": menu.value,
"v-select--chips": !!props.chips,
[`v-select--${props.multiple ? "multiple" : "single"}`]: true,
"v-select--selected": model.value.length,
"v-select--selection-slot": !!slots.selection
},
props.class
],
"style": props.style,
"inputmode": "none",
"placeholder": placeholder,
"onClick:clear": onClear,
"onMousedown:control": onMousedownControl,
"onBlur": onBlur,
"onKeydown": onKeydown,
"aria-expanded": ariaExpanded.value,
"aria-controls": ariaControls.value
}), {
...slots,
default: ({ id }) => createBaseVNode(Fragment, null, [
createBaseVNode("select", {
"hidden": true,
"multiple": props.multiple,
"name": autocomplete.fieldName.value
}, [items.value.map((item) => createBaseVNode("option", {
"key": item.value,
"value": item.value,
"selected": selectedValues.value.includes(item.value)
}, null))]),
createVNode(VMenu, mergeProps({
"id": menuId.value,
"ref": vMenuRef,
"modelValue": menu.value,
"onUpdate:modelValue": ($event) => menu.value = $event,
"activator": "parent",
"contentClass": "v-select__content",
"disabled": menuDisabled.value,
"eager": props.eager,
"maxHeight": 310,
"openOnClick": false,
"closeOnContentClick": false,
"transition": props.transition,
"onAfterEnter": onAfterEnter,
"onAfterLeave": onAfterLeave
}, computedMenuProps.value), { default: () => [createVNode(VSheet, {
"elevation": props.menuElevation,
"onFocusin": onFocusin,
"onFocusout": onFocusout,
"onKeydown": onMenuKeydown
}, { default: () => [
slots["menu-header"] && createBaseVNode("header", { "ref": headerRef }, [slots["menu-header"](menuSlotProps)]),
hasList && createVNode(VList, mergeProps({
"key": "select-list",
"ref": listRef,
"selected": selectedValues.value,
"selectStrategy": props.multiple ? "independent" : "single-independent",
"tabindex": "-1",
"selectable": !!displayItems.value.length,
"aria-live": "polite",
"aria-labelledby": `${id.value}-label`,
"aria-multiselectable": props.multiple,
"color": props.itemColor ?? props.color
}, listEvents, props.listProps), { default: () => [
slots["prepend-item"]?.(),
!displayItems.value.length && !props.hideNoData && (slots["no-data"]?.() ?? createVNode(VListItem, {
"key": "no-data",
"title": t(props.noDataText)
}, null)),
createVNode(VVirtualScroll, {
"ref": vVirtualScrollRef,
"renderless": true,
"items": displayItems.value,
"itemKey": "value"
}, { default: ({ item, index, itemRef }) => {
const camelizedProps = camelizeProps(item.props);
const itemProps = mergeProps(item.props, {
ref: itemRef,
key: item.value,
onClick: () => select(item, null),
"aria-posinset": index + 1,
"aria-setsize": displayItems.value.length
});
if (item.type === "divider") return slots.divider?.({
props: item.raw,
index
}) ?? createVNode(VDivider, mergeProps(item.props, { "key": `divider-${index}` }), null);
if (item.type === "subheader") return slots.subheader?.({
props: item.raw,
index
}) ?? createVNode(VListSubheader, mergeProps(item.props, { "key": `subheader-${index}` }), null);
return slots.item?.({
item: item.raw,
internalItem: item,
index,
props: itemProps
}) ?? createVNode(VListItem, mergeProps(itemProps, { "role": "option" }), {
prepend: ({ isSelected }) => createBaseVNode(Fragment, null, [
props.multiple && !props.hideSelected ? createVNode(VCheckboxBtn, {
"key": item.value,
"modelValue": isSelected,
"ripple": false,
"tabindex": "-1",
"aria-hidden": true,
"onClick": (event) => event.preventDefault()
}, null) : void 0,
camelizedProps.prependAvatar && createVNode(VAvatar, { "image": camelizedProps.prependAvatar }, null),
camelizedProps.prependIcon && createVNode(VIcon, { "icon": camelizedProps.prependIcon }, null)
]),
title: () => {
return search.value ? highlightResult("v-select", item.title, getMatches(item)?.title) : item.title;
}
});
} }),
slots["append-item"]?.()
] }),
slots["menu-footer"] && createBaseVNode("footer", { "ref": footerRef }, [slots["menu-footer"](menuSlotProps)])
] })] }),
model.value.map((item, index) => {
function onChipClose(e) {
e.stopPropagation();
e.preventDefault();
select(item, false);
}
const slotProps = mergeProps(VChip.filterProps(item.props), {
"onClick:close": onChipClose,
onKeydown(e) {
if (e.key !== "Enter" && e.key !== " ") return;
e.preventDefault();
e.stopPropagation();
onChipClose(e);
},
onMousedown(e) {
e.preventDefault();
e.stopPropagation();
},
modelValue: true,
"onUpdate:modelValue": void 0
});
const hasSlot = hasChips ? !!slots.chip : !!slots.selection;
const slotContent = hasSlot ? ensureValidVNode(hasChips ? slots.chip({
item: item.raw,
internalItem: item,
index,
props: slotProps
}) : slots.selection({
item: item.raw,
internalItem: item,
index
})) : void 0;
if (hasSlot && !slotContent) return void 0;
return createBaseVNode("div", {
"key": item.value,
"class": "v-select__selection"
}, [hasChips ? !slots.chip ? createVNode(VChip, mergeProps({
"key": "chip",
"closable": closableChips.value,
"size": "small",
"text": item.title,
"disabled": item.props.disabled
}, slotProps), null) : createVNode(VDefaultsProvider, {
"key": "chip-defaults",
"defaults": { VChip: {
closable: closableChips.value,
size: "small",
text: item.title
} }
}, { default: () => [slotContent] }) : slotContent ?? createBaseVNode("span", { "class": "v-select__selection-text" }, [item.title, props.multiple && index < model.value.length - 1 && createBaseVNode("span", { "class": "v-select__selection-comma" }, [createTextVNode(",")])])]);
})
]),
"append-inner": (...args) => createBaseVNode(Fragment, null, [
slots["append-inner"]?.(...args),
props.menuIcon ? createVNode(VIcon, {
"class": "v-select__menu-icon",
"color": vTextFieldRef.value?.fieldIconColor,
"icon": props.menuIcon,
"aria-hidden": true
}, null) : void 0,
props.appendInnerIcon && createVNode(InputIcon, {
"key": "append-icon",
"name": "appendInner",
"color": args[0].iconColor.value
}, null)
])
});
});
return forwardRefs({
isFocused,
menu,
search,
filteredItems,
select
}, vTextFieldRef);
}
});
//#endregion
export { VSelect };
//# sourceMappingURL=vuetify_components_VSelect.js.map