UNPKG

vuetify

Version:

Vue Material Component Framework

46,153 lines 1.45 MB
/*!
* Vuetify v4.1.11
* Forged by John Leider
* Released under the MIT License.
*/

import { warn, shallowRef, reactive, watchEffect, toRef, capitalize, isRef, isReactive, isProxy, toRaw, unref, Fragment, camelize, isVNode, Comment, getCurrentInstance as getCurrentInstance$1, ref, computed, provide, inject as inject$1, defineComponent as defineComponent$1, h, toValue, watch, onBeforeUnmount, readonly, onMounted, useId, onDeactivated, onActivated, onScopeDispose, effectScope, getCurrentScope, createElementVNode, normalizeStyle, normalizeClass, createVNode, TransitionGroup, Transition, mergeProps, toRefs, onBeforeMount, nextTick, withDirectives, vShow, onUpdated, Text, resolveDynamicComponent, toDisplayString, markRaw, Teleport, cloneVNode, createTextVNode, normalizeProps, guardReactiveProps, onUnmounted, onBeforeUpdate, withModifiers, createCommentVNode, triggerRef, vModelText, resolveComponent, render } from 'vue';

// Types
// eslint-disable-line vue/prefer-import-from-vue

/**
 * Creates a factory function for props definitions.
 * This is used to define props in a composable then override
 * default values in an implementing component.
 *
 * @example Simplified signature
 * (props: Props) => (defaults?: Record<keyof props, any>) => Props
 *
 * @example Usage
 * const makeProps = propsFactory({
 *   foo: String,
 * })
 *
 * defineComponent({
 *   props: {
 *     ...makeProps({
 *       foo: 'a',
 *     }),
 *   },
 *   setup (props) {
 *     // would be "string | undefined", now "string" because a default has been provided
 *     props.foo
 *   },
 * }
 */

function propsFactory(props, source) {
  return defaults => {
    return Object.keys(props).reduce((obj, prop) => {
      const isObjectDefinition = typeof props[prop] === 'object' && props[prop] != null && !Array.isArray(props[prop]);
      const definition = isObjectDefinition ? props[prop] : {
        type: props[prop]
      };
      if (defaults && prop in defaults) {
        obj[prop] = {
          ...definition,
          default: defaults[prop]
        };
      } else {
        obj[prop] = definition;
      }
      if (source && !obj[prop].source) {
        obj[prop].source = source;
      }
      return obj;
    }, {});
  };
}

/**
 * Like `Partial<T>` but doesn't care what the value is
 */

// Copied from Vue

// Utilities

// Types

// TODO: import from vue once upstream PR is merged
// https://github.com/vuejs/core/pull/14441

// Composables
const makeComponentProps = propsFactory({
  class: [String, Array, Object],
  style: {
    type: [String, Array, Object],
    default: null
  }
}, 'component');

/* eslint-disable no-console */

function consoleWarn(message) {
  warn(`Vuetify: ${message}`);
}
function consoleError(message) {
  warn(`Vuetify error: ${message}`);
}
function deprecate(original, replacement) {
  replacement = Array.isArray(replacement) ? replacement.slice(0, -1).map(s => `'${s}'`).join(', ') + ` or '${replacement.at(-1)}'` : `'${replacement}'`;
  warn(`[Vuetify UPGRADE] '${original}' is deprecated, use ${replacement} instead.`);
}

const IN_BROWSER = typeof window !== 'undefined';
const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
const SUPPORTS_TOUCH = IN_BROWSER && ('ontouchstart' in window || window.navigator.maxTouchPoints > 0);
const SUPPORTS_EYE_DROPPER = IN_BROWSER && 'EyeDropper' in window;
const SUPPORTS_MATCH_MEDIA = IN_BROWSER && 'matchMedia' in window && typeof window.matchMedia === 'function';
const PREFERS_REDUCED_MOTION = () => SUPPORTS_MATCH_MEDIA && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const IS_WEBKIT = IN_BROWSER && CSS?.supports?.('-webkit-backdrop-filter', 'none');

// Utilities

// Types

function getNestedValue(obj, path, fallback) {
  const last = path.length - 1;
  if (last < 0) return obj === undefined ? fallback : obj;
  for (let i = 0; i < last; i++) {
    if (obj == null) {
      return fallback;
    }
    obj = obj[path[i]];
  }
  if (obj == null) return fallback;
  return obj[path[last]] === undefined ? fallback : obj[path[last]];
}
function getObjectValueByPath(obj, path, fallback) {
  // credit: http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key#comment55278413_6491621
  if (obj == null || !path || typeof path !== 'string') return fallback;
  if (obj[path] !== undefined) return obj[path];
  path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
  path = path.replace(/^\./, ''); // strip a leading dot
  return getNestedValue(obj, path.split('.'), fallback);
}
function getPropertyFromItem(item, property, fallback) {
  if (property === true) return item === undefined ? fallback : item;
  if (property == null || typeof property === 'boolean') return fallback;
  if (item !== Object(item)) {
    if (typeof property !== 'function') return fallback;
    const value = property(item, fallback);
    return typeof value === 'undefined' ? fallback : value;
  }
  if (typeof property === 'string') return getObjectValueByPath(item, property, fallback);
  if (Array.isArray(property)) return getNestedValue(item, property, fallback);
  if (typeof property !== 'function') return fallback;
  const value = property(item, fallback);
  return typeof value === 'undefined' ? fallback : value;
}
function createRange(length, start = 0) {
  return Array.from({
    length
  }, (v, k) => start + k);
}
function convertToUnit(str, unit = 'px') {
  if (str == null || str === '') {
    return undefined;
  }
  const num = Number(str);
  if (isNaN(num)) {
    return String(str);
  } else if (!isFinite(num)) {
    return undefined;
  } else {
    return `${num}${unit}`;
  }
}
function isObject(obj) {
  return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
}
function isPlainObject(obj) {
  let proto;
  return obj !== null && typeof obj === 'object' && ((proto = Object.getPrototypeOf(obj)) === Object.prototype || proto === null);
}
function refElement(obj) {
  if (obj && '$el' in obj) {
    const el = obj.$el;
    if (el?.nodeType === Node.TEXT_NODE) {
      // Multi-root component, use the first element
      return el.nextElementSibling;
    }
    return el;
  }
  return obj;
}
const keyValues = Object.freeze({
  enter: 'Enter',
  tab: 'Tab',
  delete: 'Delete',
  esc: 'Escape',
  space: 'Space',
  up: 'ArrowUp',
  down: 'ArrowDown',
  left: 'ArrowLeft',
  right: 'ArrowRight',
  end: 'End',
  home: 'Home',
  del: 'Delete',
  backspace: 'Backspace',
  insert: 'Insert',
  pageup: 'PageUp',
  pagedown: 'PageDown',
  shift: 'Shift'
});
function keys(o) {
  return Object.keys(o);
}
function has(obj, key) {
  return key.every(k => obj.hasOwnProperty(k));
}
// Array of keys
function pick(obj, paths) {
  const found = {};
  for (const key of paths) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      found[key] = obj[key];
    }
  }
  return found;
}

// Array of keys

// Array of keys or RegExp to test keys against

function pickWithRest(obj, paths, exclude) {
  const found = Object.create(null);
  const rest = Object.create(null);
  for (const key in obj) {
    if (paths.some(path => path instanceof RegExp ? path.test(key) : path === key) && true) {
      found[key] = obj[key];
    } else {
      rest[key] = obj[key];
    }
  }
  return [found, rest];
}
function omit(obj, exclude) {
  const clone = {
    ...obj
  };
  exclude.forEach(prop => delete clone[prop]);
  return clone;
}
const onRE = /^on[^a-z]/;
const isOn = key => onRE.test(key);
const bubblingEvents = ['onAfterscriptexecute', 'onAnimationcancel', 'onAnimationend', 'onAnimationiteration', 'onAnimationstart', 'onAuxclick', 'onBeforeinput', 'onBeforescriptexecute', 'onChange', 'onClick', 'onCompositionend', 'onCompositionstart', 'onCompositionupdate', 'onContextmenu', 'onCopy', 'onCut', 'onDblclick', 'onFocusin', 'onFocusout', 'onFullscreenchange', 'onFullscreenerror', 'onGesturechange', 'onGestureend', 'onGesturestart', 'onGotpointercapture', 'onInput', 'onKeydown', 'onKeypress', 'onKeyup', 'onLostpointercapture', 'onMousedown', 'onMousemove', 'onMouseout', 'onMouseover', 'onMouseup', 'onMousewheel', 'onPaste', 'onPointercancel', 'onPointerdown', 'onPointerenter', 'onPointerleave', 'onPointermove', 'onPointerout', 'onPointerover', 'onPointerup', 'onReset', 'onSelect', 'onSubmit', 'onTouchcancel', 'onTouchend', 'onTouchmove', 'onTouchstart', 'onTransitioncancel', 'onTransitionend', 'onTransitionrun', 'onTransitionstart', 'onWheel'];
const compositionIgnoreKeys = ['ArrowUp', 'ArrowDown', 'ArrowRight', 'ArrowLeft', 'Enter', 'Escape', 'Tab', ' '];
function isComposingIgnoreKey(e) {
  return e.isComposing && compositionIgnoreKeys.includes(e.key);
}

/**
 * Filter attributes that should be applied to
 * the root element of an input component. Remaining
 * attributes should be passed to the <input> element inside.
 */
function filterInputAttrs(attrs) {
  const [events, props] = pickWithRest(attrs, [onRE]);
  const inputEvents = omit(events, bubblingEvents);
  const [rootAttrs, inputAttrs] = pickWithRest(props, ['class', 'style', 'id', 'inert', /^data-/]);
  Object.assign(rootAttrs, events);
  Object.assign(inputAttrs, inputEvents);
  return [rootAttrs, inputAttrs];
}
function wrapInArray(v) {
  return v == null ? [] : Array.isArray(v) ? v : [v];
}
function debounce(fn, delay) {
  let timeoutId = 0;
  const wrap = (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => fn(...args), unref(delay));
  };
  wrap.clear = () => {
    clearTimeout(timeoutId);
  };
  wrap.immediate = fn;
  return wrap;
}
function clamp(value, min = 0, max = 1) {
  return Math.max(min, Math.min(max, value));
}
function getDecimals(value) {
  const trimmedStr = value.toString().trim();
  return trimmedStr.includes('.') ? trimmedStr.length - trimmedStr.indexOf('.') - 1 : 0;
}
function padEnd(str, length, char = '0') {
  return str + char.repeat(Math.max(0, length - str.length));
}
function padStart(str, length, char = '0') {
  return char.repeat(Math.max(0, length - str.length)) + str;
}
function chunk(str, size = 1) {
  const chunked = [];
  let index = 0;
  while (index < str.length) {
    chunked.push(str.substr(index, size));
    index += size;
  }
  return chunked;
}
function chunkArray(array, size = 1) {
  return Array.from({
    length: Math.ceil(array.length / size)
  }, (v, i) => array.slice(i * size, i * size + size));
}
function humanReadableFileSize(bytes, base = 1000) {
  if (bytes < base) {
    return `${bytes} B`;
  }
  const prefix = base === 1024 ? ['Ki', 'Mi', 'Gi'] : ['k', 'M', 'G'];
  let unit = -1;
  while (Math.abs(bytes) >= base && unit < prefix.length - 1) {
    bytes /= base;
    ++unit;
  }
  return `${bytes.toFixed(1)} ${prefix[unit]}B`;
}
function mergeDeep(source = {}, target = {}, arrayFn, targetCondition) {
  const out = {};
  for (const key in source) {
    out[key] = source[key];
  }
  for (const key in target) {
    const targetProperty = target[key];
    if (targetCondition && !targetCondition(key, targetProperty)) {
      continue;
    }
    const sourceProperty = source[key];

    // Only continue deep merging if
    // both properties are plain objects
    if (isPlainObject(sourceProperty) && isPlainObject(targetProperty)) {
      out[key] = mergeDeep(sourceProperty, targetProperty, arrayFn, targetCondition);
      continue;
    }
    out[key] = targetProperty;
  }
  return out;
}
function flattenFragments(nodes) {
  return nodes.map(node => {
    if (node.type === Fragment) {
      return flattenFragments(node.children);
    } else {
      return node;
    }
  }).flat();
}
function toKebabCase(str = '') {
  if (toKebabCase.cache.has(str)) return toKebabCase.cache.get(str);
  const kebab = str.replace(/[^a-z]/gi, '-').replace(/\B([A-Z])/g, '-$1').toLowerCase();
  toKebabCase.cache.set(str, kebab);
  return kebab;
}
toKebabCase.cache = new Map();
function findChildrenWithProvide(key, vnode) {
  if (!vnode || typeof vnode !== 'object') return [];
  if (Array.isArray(vnode)) {
    return vnode.map(child => findChildrenWithProvide(key, child)).flat(1);
  } else if (vnode.suspense) {
    return findChildrenWithProvide(key, vnode.ssContent);
  } else if (Array.isArray(vnode.children)) {
    return vnode.children.map(child => findChildrenWithProvide(key, child)).flat(1);
  } else if (vnode.component) {
    if (Object.getOwnPropertyDescriptor(vnode.component.provides, key)) {
      return [vnode.component];
    } else if (vnode.component.subTree) {
      return findChildrenWithProvide(key, vnode.component.subTree).flat(1);
    }
  }
  return [];
}
class CircularBuffer {
  #arr = [];
  #pointer = 0;
  constructor(size) {
    this.size = size;
  }
  get isFull() {
    return this.#arr.length === this.size;
  }
  push(val) {
    this.#arr[this.#pointer] = val;
    this.#pointer = (this.#pointer + 1) % this.size;
  }
  values() {
    return this.#arr.slice(this.#pointer).concat(this.#arr.slice(0, this.#pointer));
  }
  clear() {
    this.#arr.length = 0;
    this.#pointer = 0;
  }
}
function getEventCoordinates(e) {
  if ('touches' in e) {
    return {
      clientX: e.touches[0].clientX,
      clientY: e.touches[0].clientY
    };
  }
  return {
    clientX: e.clientX,
    clientY: e.clientY
  };
}

// Only allow a single return type

/**
 * Convert a computed ref to a record of refs.
 * The getter function must always return an object with the same keys.
 */

function destructComputed(getter) {
  const refs = reactive({});
  watchEffect(() => {
    const base = getter();
    for (const key in base) {
      refs[key] = base[key];
    }
  }, {
    flush: 'sync'
  });
  const obj = {};
  for (const key in refs) {
    obj[key] = toRef(() => refs[key]);
  }
  return obj;
}

/** Array.includes but value can be any type */
function includes(arr, val) {
  return arr.includes(val);
}
function eventName(propName) {
  return propName[2].toLowerCase() + propName.slice(3);
}

// TODO: this should be an array but vue's types don't accept arrays: vuejs/core#8025

const EventProp = () => [Function, Array];
function hasEvent(props, name) {
  name = 'on' + capitalize(name);
  return !!(props[name] || props[`${name}Once`] || props[`${name}Capture`] || props[`${name}OnceCapture`] || props[`${name}CaptureOnce`]);
}
function callEvent(handler, ...args) {
  if (Array.isArray(handler)) {
    for (const h of handler) {
      h(...args);
    }
  } else if (typeof handler === 'function') {
    handler(...args);
  }
}
function focusableChildren(el, filterByTabIndex = true) {
  const targets = ['button', '[href]', 'input:not([type="hidden"])', 'select', 'textarea', 'details:not(:has(> summary))', 'details > summary', '[tabindex]', '[contenteditable]:not([contenteditable="false"])', 'audio[controls]', 'video[controls]'].map(s => `${s}${filterByTabIndex ? ':not([tabindex="-1"])' : ''}:not([disabled], [inert])`).join(', ');
  let elements;
  try {
    elements = [...el.querySelectorAll(targets)];
  } catch (err) {
    consoleError(String(err));
    return [];
  }
  return elements.filter(x => !x.closest('[inert]')) // does not have inert parent
  .filter(x => !!x.offsetParent || x.getClientRects().length > 0) // is rendered
  .filter(x => !x.parentElement?.closest('details:not([open])') || x.tagName === 'SUMMARY' && x.parentElement?.tagName === 'DETAILS');
}
function getActiveElement() {
  let active = document.activeElement;
  while (active?.shadowRoot?.activeElement) {
    active = active.shadowRoot.activeElement;
  }
  return active;
}
function getNextElement(elements, location, condition) {
  let _el;
  let idx = elements.indexOf(getActiveElement());
  if (idx < 0) {
    idx = elements.findIndex(el => el.getAttribute('aria-selected') === 'true');
  }
  const inc = location === 'next' ? 1 : -1;
  do {
    idx += inc;
    _el = elements[idx];
  } while ((!_el || _el.offsetParent == null || !(condition?.(_el) ?? true)) && idx < elements.length && idx >= 0);
  return _el;
}
function focusChild(el, location, options) {
  const focusable = focusableChildren(el);
  if (location == null) {
    const active = getActiveElement();
    if (el === active || !el.contains(active)) {
      focusable[0]?.focus(options);
    }
  } else if (location === 'first') {
    focusable[0]?.focus(options);
  } else if (location === 'last') {
    focusable.at(-1)?.focus(options);
  } else if (typeof location === 'number') {
    focusable[location]?.focus(options);
  } else {
    const _el = getNextElement(focusable, location);
    if (_el) _el.focus();else focusChild(el, location === 'next' ? 'first' : 'last', options);
  }
}
function isEmpty(val) {
  return val === null || val === undefined || typeof val === 'string' && val.trim() === '';
}
function noop() {}

/** Returns null if the selector is not supported or we can't check */
function matchesSelector(el, selector) {
  const supportsSelector = IN_BROWSER && typeof CSS !== 'undefined' && typeof CSS.supports !== 'undefined' && CSS.supports(`selector(${selector})`);
  if (!supportsSelector) return null;
  try {
    return !!el && el.matches(selector);
  } catch (err) {
    return null;
  }
}
function ensureValidVNode(vnodes) {
  return vnodes.some(child => {
    if (!isVNode(child)) return true;
    if (child.type === Comment) return false;
    return child.type !== Fragment || ensureValidVNode(child.children);
  }) ? vnodes : null;
}
function renderSlot(slot, props, fallback) {
  // TODO: check if slot returns elements: #18308
  return slot?.(props) ?? fallback?.(props);
}
function defer(timeout, cb) {
  if (!IN_BROWSER || timeout === 0) {
    cb();
    return () => {};
  }
  const timeoutId = window.setTimeout(cb, timeout);
  return () => window.clearTimeout(timeoutId);
}
function templateRef() {
  const el = shallowRef();
  const fn = target => {
    el.value = target;
  };
  Object.defineProperty(fn, 'value', {
    enumerable: true,
    get: () => el.value,
    set: val => el.value = val
  });
  Object.defineProperty(fn, 'el', {
    enumerable: true,
    get: () => refElement(el.value)
  });
  return fn;
}
function checkPrintable(e) {
  const isPrintableChar = e.key.length === 1;
  const noModifier = !e.ctrlKey && !e.metaKey && !e.altKey;
  return isPrintableChar && noModifier;
}
function isPrimitive(value) {
  return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint';
}
function escapeForRegex(sign) {
  return '\\^$*+?.()|{}[]'.includes(sign) ? `\\${sign}` : sign;
}
function normalizeMinusSign(text) {
  return text.replace(/−/g, '-');
}
function extractNumber(text, decimalDigitsLimit, decimalSeparator) {
  const onlyValidCharacters = new RegExp(`[\\d\\-${escapeForRegex(decimalSeparator)}]`);
  const cleanText = normalizeMinusSign(text).split('').filter(x => onlyValidCharacters.test(x)).filter((x, i, all) => i === 0 && /[-]/.test(x) ||
  // sign allowed at the start
  x === decimalSeparator && i === all.indexOf(x) ||
  // decimal separator allowed only once
  /\d/.test(x)).join('');
  if (decimalDigitsLimit === 0) {
    return cleanText.split(decimalSeparator)[0];
  }
  const decimalPart = new RegExp(`${escapeForRegex(decimalSeparator)}\\d`);
  if (decimalDigitsLimit !== null && decimalPart.test(cleanText)) {
    const parts = cleanText.split(decimalSeparator);
    return [parts[0], parts[1].substring(0, decimalDigitsLimit)].join(decimalSeparator);
  }
  return cleanText;
}
function camelizeProps(props) {
  const out = {};
  for (const prop in props) {
    out[camelize(prop)] = props[prop];
  }
  return out;
}
function onlyDefinedProps(props) {
  const booleanAttributes = ['checked', 'disabled'];
  return Object.fromEntries(Object.entries(props).filter(([key, v]) => booleanAttributes.includes(key) ? !!v : v !== undefined));
}
function deepToRaw(value) {
  const objectIterator = input => {
    if (Array.isArray(input)) {
      return input.map(item => objectIterator(item));
    }
    if (isRef(input) || isReactive(input) || isProxy(input)) {
      return objectIterator(toRaw(input));
    }
    if (isPlainObject(input)) {
      return Object.keys(input).reduce((acc, key) => {
        acc[key] = objectIterator(input[key]);
        return acc;
      }, {});
    }
    return input;
  };
  return objectIterator(value);
}

// Utilities
const block = ['top', 'bottom'];
const inline = ['start', 'end', 'left', 'right'];
/** Parse a raw anchor string into an object */
function parseAnchor(anchor, isRtl) {
  let [side, align] = anchor.split(' ');
  if (!align) {
    align = includes(block, side) ? 'start' : includes(inline, side) ? 'top' : 'center';
  }
  return {
    side: toPhysical(side, isRtl),
    align: toPhysical(align, isRtl)
  };
}
function toPhysical(str, isRtl) {
  if (str === 'start') return isRtl ? 'right' : 'left';
  if (str === 'end') return isRtl ? 'left' : 'right';
  return str;
}
function flipSide(anchor) {
  return {
    side: {
      center: 'center',
      top: 'bottom',
      bottom: 'top',
      left: 'right',
      right: 'left'
    }[anchor.side],
    align: anchor.align
  };
}
function flipAlign(anchor) {
  return {
    side: anchor.side,
    align: {
      center: 'center',
      top: 'bottom',
      bottom: 'top',
      left: 'right',
      right: 'left'
    }[anchor.align]
  };
}
function flipCorner(anchor) {
  return {
    side: anchor.align,
    align: anchor.side
  };
}
function getAxis(anchor) {
  return includes(block, anchor.side) ? 'y' : 'x';
}

class Box {
  constructor(args) {
    const pageScale = document.body.currentCSSZoom ?? 1;
    const isElement = args instanceof Element;
    const factor = isElement ? 1 + (1 - pageScale) / pageScale : 1;
    const {
      x,
      y,
      width,
      height
    } = isElement ? args.getBoundingClientRect() : args;
    this.x = x * factor;
    this.y = y * factor;
    this.width = width * factor;
    this.height = height * factor;
  }
  get top() {
    return this.y;
  }
  get bottom() {
    return this.y + this.height;
  }
  get left() {
    return this.x;
  }
  get right() {
    return this.x + this.width;
  }
}
function getOverflow(a, b) {
  return {
    x: {
      before: Math.max(0, b.left - a.left),
      after: Math.max(0, a.right - b.right)
    },
    y: {
      before: Math.max(0, b.top - a.top),
      after: Math.max(0, a.bottom - b.bottom)
    }
  };
}
function getTargetBox(target) {
  if (Array.isArray(target)) {
    const pageScale = document.body.currentCSSZoom ?? 1;
    const factor = 1 + (1 - pageScale) / pageScale;
    return new Box({
      x: target[0] * factor,
      y: target[1] * factor,
      width: 0 * factor,
      height: 0 * factor
    });
  } else {
    return new Box(target);
  }
}
function getElementBox(el) {
  if (el === document.documentElement) {
    if (!visualViewport) {
      return new Box({
        x: 0,
        y: 0,
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight
      });
    } else {
      return new Box({
        x: visualViewport.scale > 1 || IS_WEBKIT ? 0 : visualViewport.offsetLeft,
        y: visualViewport.scale > 1 || IS_WEBKIT ? 0 : visualViewport.offsetTop,
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight
      });
    }
  } else {
    return new Box(el);
  }
}

// Utilities

/** @see https://stackoverflow.com/a/57876601/2074736 */
function nullifyTransforms(el) {
  const rect = new Box(el);
  const style = getComputedStyle(el);
  const tx = style.transform;
  if (tx) {
    let ta, sx, sy, dx, dy;
    if (tx.startsWith('matrix3d(')) {
      ta = tx.slice(9, -1).split(/, /);
      sx = Number(ta[0]);
      sy = Number(ta[5]);
      dx = Number(ta[12]);
      dy = Number(ta[13]);
    } else if (tx.startsWith('matrix(')) {
      ta = tx.slice(7, -1).split(/, /);
      sx = Number(ta[0]);
      sy = Number(ta[3]);
      dx = Number(ta[4]);
      dy = Number(ta[5]);
    } else {
      return new Box(rect);
    }
    const to = style.transformOrigin;
    const x = rect.x - dx - (1 - sx) * parseFloat(to);
    const y = rect.y - dy - (1 - sy) * parseFloat(to.slice(to.indexOf(' ') + 1));
    const w = sx ? rect.width / sx : el.offsetWidth + 1;
    const h = sy ? rect.height / sy : el.offsetHeight + 1;
    return new Box({
      x,
      y,
      width: w,
      height: h
    });
  } else {
    return new Box(rect);
  }
}
function animate(el, keyframes, options) {
  if (typeof el.animate === 'undefined') return {
    finished: Promise.resolve()
  };
  let animation;
  try {
    animation = el.animate(keyframes, options);
  } catch (err) {
    return {
      finished: Promise.resolve()
    };
  }
  if (typeof animation.finished === 'undefined') {
    animation.finished = new Promise(resolve => {
      animation.onfinish = () => {
        resolve(animation);
      };
    });
  }
  return animation;
}

// Utilities
const handlers = new WeakMap();
function bindProps(el, props) {
  Object.keys(props).forEach(k => {
    if (isOn(k)) {
      const name = eventName(k);
      const handler = handlers.get(el);
      if (props[k] == null) {
        handler?.forEach(v => {
          const [n, fn] = v;
          if (n === name) {
            el.removeEventListener(name, fn);
            handler.delete(v);
          }
        });
      } else if (!handler || ![...handler]?.some(v => v[0] === name && v[1] === props[k])) {
        el.addEventListener(name, props[k]);
        const _handler = handler || new Set();
        _handler.add([name, props[k]]);
        if (!handlers.has(el)) handlers.set(el, _handler);
      }
    } else {
      if (props[k] == null) {
        el.removeAttribute(k);
      } else {
        el.setAttribute(k, props[k]);
      }
    }
  });
}
function unbindProps(el, props) {
  Object.keys(props).forEach(k => {
    if (isOn(k)) {
      const name = eventName(k);
      const handler = handlers.get(el);
      handler?.forEach(v => {
        const [n, fn] = v;
        if (n === name) {
          el.removeEventListener(name, fn);
          handler.delete(v);
        }
      });
    } else {
      el.removeAttribute(k);
    }
  });
}

/**
 * WCAG 3.0 APCA perceptual contrast algorithm from https://github.com/Myndex/SAPC-APCA
 * @licence https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
 * @see https://www.w3.org/WAI/GL/task-forces/silver/wiki/Visual_Contrast_of_Text_Subgroup
 */
// Types

// MAGICAL NUMBERS

// sRGB Conversion to Relative Luminance (Y)

// Transfer Curve (aka "Gamma") for sRGB linearization
// Simple power curve vs piecewise described in docs
// Essentially, 2.4 best models actual display
// characteristics in combination with the total method
const mainTRC = 2.4;
const Rco = 0.2126729; // sRGB Red Coefficient (from matrix)
const Gco = 0.7151522; // sRGB Green Coefficient (from matrix)
const Bco = 0.0721750; // sRGB Blue Coefficient (from matrix)

// For Finding Raw SAPC Contrast from Relative Luminance (Y)

// Constants for SAPC Power Curve Exponents
// One pair for normal text, and one for reverse
// These are the "beating heart" of SAPC
const normBG = 0.55;
const normTXT = 0.58;
const revTXT = 0.57;
const revBG = 0.62;

// For Clamping and Scaling Values

const blkThrs = 0.03; // Level that triggers the soft black clamp
const blkClmp = 1.45; // Exponent for the soft black clamp curve
const deltaYmin = 0.0005; // Lint trap
const scaleBoW = 1.25; // Scaling for dark text on light
const scaleWoB = 1.25; // Scaling for light text on dark
const loConThresh = 0.078; // Threshold for new simple offset scale
const loConFactor = 12.82051282051282; // = 1/0.078,
const loConOffset = 0.06; // The simple offset
const loClip = 0.001; // Output clip (lint trap #2)

function APCAcontrast(text, background) {
  // Linearize sRGB
  const Rtxt = (text.r / 255) ** mainTRC;
  const Gtxt = (text.g / 255) ** mainTRC;
  const Btxt = (text.b / 255) ** mainTRC;
  const Rbg = (background.r / 255) ** mainTRC;
  const Gbg = (background.g / 255) ** mainTRC;
  const Bbg = (background.b / 255) ** mainTRC;

  // Apply the standard coefficients and sum to Y
  let Ytxt = Rtxt * Rco + Gtxt * Gco + Btxt * Bco;
  let Ybg = Rbg * Rco + Gbg * Gco + Bbg * Bco;

  // Soft clamp Y when near black.
  // Now clamping all colors to prevent crossover errors
  if (Ytxt <= blkThrs) Ytxt += (blkThrs - Ytxt) ** blkClmp;
  if (Ybg <= blkThrs) Ybg += (blkThrs - Ybg) ** blkClmp;

  // Return 0 Early for extremely low ∆Y (lint trap #1)
  if (Math.abs(Ybg - Ytxt) < deltaYmin) return 0.0;

  // SAPC CONTRAST

  let outputContrast; // For weighted final values
  if (Ybg > Ytxt) {
    // For normal polarity, black text on white
    // Calculate the SAPC contrast value and scale

    const SAPC = (Ybg ** normBG - Ytxt ** normTXT) * scaleBoW;

    // NEW! SAPC SmoothScale™
    // Low Contrast Smooth Scale Rollout to prevent polarity reversal
    // and also a low clip for very low contrasts (lint trap #2)
    // much of this is for very low contrasts, less than 10
    // therefore for most reversing needs, only loConOffset is important
    outputContrast = SAPC < loClip ? 0.0 : SAPC < loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC - loConOffset;
  } else {
    // For reverse polarity, light text on dark
    // WoB should always return negative value.

    const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB;
    outputContrast = SAPC > -loClip ? 0.0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
  }
  return outputContrast * 100;
}

// Types

const delta = 0.20689655172413793; // 6÷29

const cielabForwardTransform = t => t > delta ** 3 ? Math.cbrt(t) : t / (3 * delta ** 2) + 4 / 29;
const cielabReverseTransform = t => t > delta ? t ** 3 : 3 * delta ** 2 * (t - 4 / 29);
function fromXYZ$1(xyz) {
  const transform = cielabForwardTransform;
  const transformedY = transform(xyz[1]);
  return [116 * transformedY - 16, 500 * (transform(xyz[0] / 0.95047) - transformedY), 200 * (transformedY - transform(xyz[2] / 1.08883))];
}
function toXYZ$1(lab) {
  const transform = cielabReverseTransform;
  const Ln = (lab[0] + 16) / 116;
  return [transform(Ln + lab[1] / 500) * 0.95047, transform(Ln), transform(Ln - lab[2] / 200) * 1.08883];
}

// Utilities

// Types

// For converting XYZ to sRGB
const srgbForwardMatrix = [[3.2406, -1.5372, -0.4986], [-0.9689, 1.8758, 0.0415], [0.0557, -0.204, 1.0570]];

// Forward gamma adjust
const srgbForwardTransform = C => C <= 0.0031308 ? C * 12.92 : 1.055 * C ** (1 / 2.4) - 0.055;

// For converting sRGB to XYZ
const srgbReverseMatrix = [[0.4124, 0.3576, 0.1805], [0.2126, 0.7152, 0.0722], [0.0193, 0.1192, 0.9505]];

// Reverse gamma adjust
const srgbReverseTransform = C => C <= 0.04045 ? C / 12.92 : ((C + 0.055) / 1.055) ** 2.4;
function fromXYZ(xyz) {
  const rgb = Array(3);
  const transform = srgbForwardTransform;
  const matrix = srgbForwardMatrix;

  // Matrix transform, then gamma adjustment
  for (let i = 0; i < 3; ++i) {
    // Rescale back to [0, 255]
    rgb[i] = Math.round(clamp(transform(matrix[i][0] * xyz[0] + matrix[i][1] * xyz[1] + matrix[i][2] * xyz[2])) * 255);
  }
  return {
    r: rgb[0],
    g: rgb[1],
    b: rgb[2]
  };
}
function toXYZ({
  r,
  g,
  b
}) {
  const xyz = [0, 0, 0];
  const transform = srgbReverseTransform;
  const matrix = srgbReverseMatrix;

  // Rescale from [0, 255] to [0, 1] then adjust sRGB gamma to linear RGB
  r = transform(r / 255);
  g = transform(g / 255);
  b = transform(b / 255);

  // Matrix color space transform
  for (let i = 0; i < 3; ++i) {
    xyz[i] = matrix[i][0] * r + matrix[i][1] * g + matrix[i][2] * b;
  }
  return xyz;
}

// Utilities

// Types

function isCssColor(color) {
  return !!color && /^(#|var\(--|(rgb|hsl)a?\()/.test(color);
}
function isParsableColor(color) {
  return isCssColor(color) && !/^((rgb|hsl)a?\()?var\(--/.test(color);
}
const cssColorRe = /^(?<fn>(?:rgb|hsl)a?)\((?<values>.+)\)/;
const mappers = {
  rgb: (r, g, b, a) => ({
    r,
    g,
    b,
    a
  }),
  rgba: (r, g, b, a) => ({
    r,
    g,
    b,
    a
  }),
  hsl: (h, s, l, a) => HSLtoRGB({
    h,
    s,
    l,
    a
  }),
  hsla: (h, s, l, a) => HSLtoRGB({
    h,
    s,
    l,
    a
  }),
  hsv: (h, s, v, a) => HSVtoRGB({
    h,
    s,
    v,
    a
  }),
  hsva: (h, s, v, a) => HSVtoRGB({
    h,
    s,
    v,
    a
  })
};
function parseColor(color) {
  if (typeof color === 'number') {
    if (isNaN(color) || color < 0 || color > 0xFFFFFF) {
      // int can't have opacity
      consoleWarn(`'${color}' is not a valid hex color`);
    }
    return {
      r: (color & 0xFF0000) >> 16,
      g: (color & 0xFF00) >> 8,
      b: color & 0xFF
    };
  } else if (typeof color === 'string' && cssColorRe.test(color)) {
    const {
      groups
    } = color.match(cssColorRe);
    const {
      fn,
      values
    } = groups;
    const realValues = values.split(/,\s*|\s*\/\s*|\s+/).map((v, i) => {
      if (v.endsWith('%') ||
      // unitless slv are %
      i > 0 && i < 3 && ['hsl', 'hsla', 'hsv', 'hsva'].includes(fn)) {
        return parseFloat(v) / 100;
      } else {
        return parseFloat(v);
      }
    });
    return mappers[fn](...realValues);
  } else if (typeof color === 'string') {
    let hex = color.startsWith('#') ? color.slice(1) : color;
    if ([3, 4].includes(hex.length)) {
      hex = hex.split('').map(char => char + char).join('');
    } else if (![6, 8].includes(hex.length)) {
      consoleWarn(`'${color}' is not a valid hex(a) color`);
    }
    const int = parseInt(hex, 16);
    if (isNaN(int) || int < 0 || int > 0xFFFFFFFF) {
      consoleWarn(`'${color}' is not a valid hex(a) color`);
    }
    return HexToRGB(hex);
  } else if (typeof color === 'object') {
    if (has(color, ['r', 'g', 'b'])) {
      return color;
    } else if (has(color, ['h', 's', 'l'])) {
      return HSVtoRGB(HSLtoHSV(color));
    } else if (has(color, ['h', 's', 'v'])) {
      return HSVtoRGB(color);
    }
  }
  throw new TypeError(`Invalid color: ${color == null ? color : String(color) || color.constructor.name}\nExpected #hex, #hexa, rgb(), rgba(), hsl(), hsla(), object or number`);
}

/** Converts HSVA to RGBA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
function HSVtoRGB(hsva) {
  const {
    h,
    s,
    v,
    a
  } = hsva;
  const f = n => {
    const k = (n + h / 60) % 6;
    return v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
  };
  const rgb = [f(5), f(3), f(1)].map(v => Math.round(v * 255));
  return {
    r: rgb[0],
    g: rgb[1],
    b: rgb[2],
    a
  };
}
function HSLtoRGB(hsla) {
  return HSVtoRGB(HSLtoHSV(hsla));
}

/** Converts RGBA to HSVA. Based on formula from https://en.wikipedia.org/wiki/HSL_and_HSV */
function RGBtoHSV(rgba) {
  if (!rgba) return {
    h: 0,
    s: 1,
    v: 1,
    a: 1
  };
  const r = rgba.r / 255;
  const g = rgba.g / 255;
  const b = rgba.b / 255;
  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  let h = 0;
  if (max !== min) {
    if (max === r) {
      h = 60 * (0 + (g - b) / (max - min));
    } else if (max === g) {
      h = 60 * (2 + (b - r) / (max - min));
    } else if (max === b) {
      h = 60 * (4 + (r - g) / (max - min));
    }
  }
  if (h < 0) h = h + 360;
  const s = max === 0 ? 0 : (max - min) / max;
  const hsv = [h, s, max];
  return {
    h: hsv[0],
    s: hsv[1],
    v: hsv[2],
    a: rgba.a
  };
}
function HSVtoHSL(hsva) {
  const {
    h,
    s,
    v,
    a
  } = hsva;
  const l = v - v * s / 2;
  const sprime = l === 1 || l === 0 ? 0 : (v - l) / Math.min(l, 1 - l);
  return {
    h,
    s: sprime,
    l,
    a
  };
}
function HSLtoHSV(hsl) {
  const {
    h,
    s,
    l,
    a
  } = hsl;
  const v = l + s * Math.min(l, 1 - l);
  const sprime = v === 0 ? 0 : 2 - 2 * l / v;
  return {
    h,
    s: sprime,
    v,
    a
  };
}
function RGBtoCSS({
  r,
  g,
  b,
  a
}) {
  return a === undefined ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${a})`;
}
function HSVtoCSS(hsva) {
  return RGBtoCSS(HSVtoRGB(hsva));
}
function toHex(v) {
  const h = Math.round(v).toString(16);
  return ('00'.substr(0, 2 - h.length) + h).toUpperCase();
}
function RGBtoHex({
  r,
  g,
  b,
  a
}) {
  return `#${[toHex(r), toHex(g), toHex(b), a !== undefined ? toHex(Math.round(a * 255)) : ''].join('')}`;
}
function HexToRGB(hex) {
  hex = parseHex(hex);
  let [r, g, b, a] = chunk(hex, 2).map(c => parseInt(c, 16));
  a = a === undefined ? a : a / 255;
  return {
    r,
    g,
    b,
    a
  };
}
function HexToHSV(hex) {
  const rgb = HexToRGB(hex);
  return RGBtoHSV(rgb);
}
function HSVtoHex(hsva) {
  return RGBtoHex(HSVtoRGB(hsva));
}
function parseHex(hex) {
  if (hex.startsWith('#')) {
    hex = hex.slice(1);
  }
  hex = hex.replace(/([^0-9a-f])/gi, 'F');
  if (hex.length === 3 || hex.length === 4) {
    hex = hex.split('').map(x => x + x).join('');
  }
  if (hex.length !== 6) {
    hex = padEnd(padEnd(hex, 6), 8, 'F');
  }
  return hex;
}
function lighten(value, amount) {
  const lab = fromXYZ$1(toXYZ(value));
  lab[0] = lab[0] + amount * 10;
  return fromXYZ(toXYZ$1(lab));
}
function darken(value, amount) {
  const lab = fromXYZ$1(toXYZ(value));
  lab[0] = lab[0] - amount * 10;
  return fromXYZ(toXYZ$1(lab));
}

/**
 * Calculate the relative luminance of a given color
 * @see https://www.w3.org/TR/WCAG20/#relativeluminancedef
 */
function getLuma(color) {
  const rgb = parseColor(color);
  return toXYZ(rgb)[1];
}

/**
 * Returns the contrast ratio (1-21) between two colors.
 * @see https://www.w3.org/TR/WCAG20/#contrast-ratiodef
 */
function getContrast(first, second) {
  const l1 = getLuma(first);
  const l2 = getLuma(second);
  const light = Math.max(l1, l2);
  const dark = Math.min(l1, l2);
  return (light + 0.05) / (dark + 0.05);
}
function hasLightForeground(color) {
  const blackContrast = Math.abs(APCAcontrast(parseColor(0), parseColor(color)));
  const whiteContrast = Math.abs(APCAcontrast(parseColor(0xffffff), parseColor(color)));

  // TODO: warn about poor color selections
  // const contrastAsText = Math.abs(APCAcontrast(colorVal, colorToInt(theme.colors.background)))
  // const minContrast = Math.max(blackContrast, whiteContrast)
  // if (minContrast < 60) {
  //   consoleInfo(`${key} theme color ${color} has poor contrast (${minContrast.toFixed()}%)`)
  // } else if (contrastAsText < 60 && !['background', 'surface'].includes(color)) {
  //   consoleInfo(`${key} theme color ${color} has poor contrast as text (${contrastAsText.toFixed()}%)`)
  // }

  // Prefer white text if both have an acceptable contrast ratio
  return whiteContrast > Math.min(blackContrast, 50);
}

// Utilities
function getCurrentInstance(name, message) {
  const vm = getCurrentInstance$1();
  if (!vm) {
    throw new Error(`[Vuetify] ${name} ${'must be called from inside a setup function'}`);
  }
  return vm;
}
function getCurrentInstanceName(name = 'composables') {
  const vm = getCurrentInstance(name).type;
  return toKebabCase(vm?.aliasName || vm?.name);
}

// Utilities

// Types

function injectSelf(key, vm = getCurrentInstance('injectSelf')) {
  const {
    provides
  } = vm;
  if (provides && key in provides) {
    // TS doesn't allow symbol as index type
    return provides[key];
  }
  return undefined;
}

// Utilities

// Types

const DefaultsSymbol = Symbol.for('vuetify:defaults');
function createDefaults(options) {
  return ref(options);
}
function injectDefaults() {
  const defaults = inject$1(DefaultsSymbol);
  if (!defaults) throw new Error('[Vuetify] Could not find defaults instance');
  return defaults;
}
function provideDefaults(defaults, options) {
  const injectedDefaults = injectDefaults();
  const providedDefaults = ref(defaults);
  const newDefaults = computed(() => {
    const disabled = unref(options?.disabled);
    if (disabled) return injectedDefaults.value;
    const scoped = unref(options?.scoped);
    const reset = unref(options?.reset);
    const root = unref(options?.root);
    if (providedDefaults.value == null && !(scoped || reset || root)) return injectedDefaults.value;
    let properties = mergeDeep(providedDefaults.value, {
      prev: injectedDefaults.value
    });
    if (scoped) return properties;
    if (reset || root) {
      const len = Number(reset || Infinity);
      const rootDefaults = typeof root === 'string' ? properties.prev?.[root] : undefined;
      for (let i = 0; i <= len; i++) {
        if (!properties || !('prev' in properties)) {
          break;
        }
        properties = properties.prev;
      }
      if (properties && rootDefaults) {
        properties = mergeDeep(mergeDeep(properties, {
          prev: properties
        }), rootDefaults);
      }
      return properties;
    }
    return properties.prev ? mergeDeep(properties.prev, properties, undefined, (_, v) => v !== undefined) : properties;
  });
  provide(DefaultsSymbol, newDefaults);
  return newDefaults;
}
function propIsDefined(vnode, prop) {
  return vnode.props && (typeof vnode.props[prop] !== 'undefined' || typeof vnode.props[toKebabCase(prop)] !== 'undefined');
}
function internalUseDefaults(props = {}, name, defaults = injectDefaults()) {
  const vm = getCurrentInstance('useDefaults');
  name = name ?? vm.type.name ?? vm.type.__name;
  if (!name) {
    throw new Error('[Vuetify] Could not determine component name');
  }
  const componentDefaults = computed(() => defaults.value?.[props._as ?? name]);
  const _props = new Proxy(props, {
    get(target, prop) {
      const propValue = Reflect.get(target, prop);
      if (prop === 'class' || prop === 'style') {
        return [componentDefaults.value?.[prop], propValue].filter(v => v != null);
      }
      if (propIsDefined(vm.vnode, prop)) return propValue;
      const _componentDefault = componentDefaults.value?.[prop];
      if (_componentDefault !== undefined) return _componentDefault;
      const _globalDefault = defaults.value?.global?.[prop];
      if (_globalDefault !== undefined) return _globalDefault;
      return propValue;
    }
  });
  const _subcomponentDefaults = shallowRef();
  watchEffect(() => {
    if (componentDefaults.value) {
      const subComponents = Object.entries(componentDefaults.value).filter(([key]) => key.startsWith(key[0].toUpperCase()));
      _subcomponentDefaults.value = subComponents.length ? Object.fromEntries(subComponents) : undefined;
    } else {
      _subcomponentDefaults.value = undefined;
    }
  });
  function provideSubDefaults() {
    const injected = injectSelf(DefaultsSymbol, vm);
    provide(DefaultsSymbol, computed(() => {
      return _subcomponentDefaults.value ? mergeDeep(injected?.value ?? {}, _subcomponentDefaults.value) : injected?.value;
    }));
  }
  return {
    props: _props,
    provideSubDefaults
  };
}
function useDefaults(props = {}, name) {
  const {
    props: _props,
    provideSubDefaults
  } = internalUseDefaults(props, name);
  provideSubDefaults();
  return _props;
}

// Composables

// Types

// No props

// Object Props

// Implementation
function defineComponent(options) {
  options._setup = options._setup ?? options.setup;
  if (!options.name) {
    consoleWarn('The component is missing an explicit name, unable to generate default prop value');
    return options;
  }
  if (options._setup) {
    options.props = propsFactory(options.props ?? {}, options.name)();
    const propKeys = Object.keys(options.props).filter(key => key !== 'class' && key !== 'style');
    options.filterProps = function filterProps(props) {
      return pick(props, propKeys);
    };
    options.props._as = String;
    options.setup = function setup(props, ctx) {
      const defaults = injectDefaults();

      // Skip props proxy if defaults are not provided
      if (!defaults.value) return options._setup(props, ctx);
      const {
        props: _props,
        provideSubDefaults
      } = internalUseDefaults(props, props._as ?? options.name, defaults);
      const setupBindings = options._setup(_props, ctx);
      provideSubDefaults();
      return setupBindings;
    };
  }
  return options;
}

// No argument - simple default slot

// Generic constructor argument - generic props and slots

// Slots argument - simple slots

// Implementation
function genericComponent(exposeDefaults = true) {
  return options => (exposeDefaults ? defineComponent : defineComponent$1)(options);
}
function defineFunctionalComponent(props, render) {
  render.props = props;
  return render;
}

// Adds a filterProps method to the component options

// https://github.com/vuejs/core/pull/10557

// not a vue Component

// Composables
function createSimpleFunctional(klass, tag = 'div', name) {
  return genericComponent()({
    name: name ?? capitalize(camelize(klass.replace(/__/g, '-'))),
    props: {
      tag: {
        type: String,
        default: tag
      },
      ...makeComponentProps()
    },
    setup(props, {
      slots
    }) {
      return () => {
        return h(props.tag, {
          class: [klass, props.class],
          style: props.style
        }, slots.default?.());
      };
    }
  });
}

function updateRecursionCache(a, b, cache, result) {
  if (!cache || isPrimitive(a) || isPrimitive(b)) return;
  const visitedObject = cache.get(a);
  if (visitedObject) {
    visitedObject.set(b, result);
  } else {
    const newCacheItem = new WeakMap();
    newCacheItem.set(b, result);
    cache.set(a, newCacheItem);
  }
}
function findCachedComparison(a, b, cache) {
  if (!cache || isPrimitive(a) || isPrimitive(b)) return null;
  const r1 = cache.get(a)?.get(b);
  if (typeof r1 === 'boolean') return r1;
  const r2 = cache.get(b)?.get(a);
  if (typeof r2 === 'boolean') return r2;
  return null;
}
function deepEqual(a, b, recursionCache = new WeakMap()) {
  if (a === b) return true;
  if (a instanceof Date && b instanceof Date && a.getTime() !== b.getTime()) {
    // If the values are Date, compare them as timestamps
    return false;
  }
  if (a !== Object(a) || b !== Object(b)) {
    // If the values aren't objects, they were already checked for equality
    return false;
  }
  const props = Object.keys(a);
  if (props.length !== Object.keys(b).length) {
    // Different number of props, don't bother to check
    return false;
  }
  const cachedComparisonResult = findCachedComparison(a, b, recursionCache);
  if (cachedComparisonResult) {
    return cachedComparisonResult;
  }
  updateRecursionCache(a, b, recursionCache, true);
  return props.every(p => deepEqual(a[p], b[p], recursionCache));
}

/**
 * Returns:
 *  - 'null' if the node is not attached to the DOM
 *  - the root node (HTMLDocument | ShadowRoot) otherwise
 */
function attachedRoot(node) {
  /* istanbul ignore next */
  if (typeof node.getRootNode !== 'function') {
    // Shadow DOM not supported (IE11), lets find the root of this node
    while (node.parentNode) node = node.parentNode;

    // The root parent is the document if the node is attached to the DOM
    if (node !== document) return null;
    return document;
  }
  const root = node.getRootNode();

  // The composed root node is the document if the node is attached to the DOM
  if (root !== document && root.getRootNode({
    composed: true
  }) !== document) return null;
  return root;
}

// Utilities

// Types

const standardEasing = 'cubic-bezier(0.4, 0, 0.2, 1)';
const deceleratedEasing = 'cubic-bezier(0.0, 0, 0.2, 1)'; // Entering
const acceleratedEasing = 'cubic-bezier(0.4, 0, 1, 1)'; // Leaving

const easingPatterns = {
  linear: t => t,
  easeInQuad: t => t ** 2,
  easeOutQuad: t => t * (2 - t),
  easeInOutQuad: t => t < 0.5 ? 2 * t ** 2 : -1 + (4 - 2 * t) * t,
  easeInCubic: t => t ** 3,
  easeOutCubic: t => --t ** 3 + 1,
  easeInOutCubic: t => t < 0.5 ? 4 * t ** 3 : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
  easeInQuart: t => t ** 4,
  easeOutQuart: t => 1 - --t ** 4,
  easeInOutQuart: t => t < 0.5 ? 8 * t ** 4 : 1 - 8 * --t ** 4,
  easeInQuint: t => t ** 5,
  easeOutQuint: t => 1 + --t ** 5,
  easeInOutQuint: t => t < 0.5 ? 16 * t ** 5 : 1 + 16 * --t ** 5,
  instant: t => 1
};
function useTransition(source, options) {
  const defaultTransition = {
    duration: 300,
    transition: easingPatterns.easeInOutCubic
  };
  let raf = -1;
  const outputRef = shallowRef(toValue(source));
  watch(() => toValue(source), async to => {
    cancelAnimationFrame(raf);
    const easing = {
      ...defaultTransition,
      ...toValue(options)
    };
    await executeTransition(outputRef, outputRef.value, to, easing);
  });
  function executeTransition(out, from, to, options) {
    const startTime = performance.now();
    const ease = PREFERS_REDUCED_MOTION() ? easingPatterns.instant : options.transition ?? easingPatterns.easeInOutCubic;
    return new Promise(resolve => {
      raf = requestAnimationFrame(function step(currentTime) {
        const timeElapsed = currentTime - startTime;
        const progress = timeElapsed / options.duration;
        out.value = from + (to - from) * ease(clamp(progress, 0, 1));
        if (progress < 1) {
          raf = requestAnimationFrame(step);
        } else {
          out.value = to;
          resolve();
        }
      });
    });
  }
  return computed(() => outputRef.value);
}

// Utilities
function getPrefixedEventHandlers(attrs, suffix, getData) {
  return Object.keys(attrs).filter(key => isOn(key) && key.endsWith(suffix)).reduce((acc, key) => {
    acc[key.slice(0, -suffix.length)] = event => callEvent(attrs[key], event, getData(event));
    return acc;
  }, {});
}

function getScrollParent(el, includeHidden = false) {
  while (el) {
    if (includeHidden ? isPotentiallyScrollable(el) : hasScrollbar(el)) return el;
    el = el.parentElement;
  }
  return document.scrollingElement;
}
function getScrollParents(el, stopAt) {
  const elements = [];
  if (stopAt && el && !stopAt.contains(el)) return elements;
  while (el) {
    if (hasScrollbar(el)) elements.push(el);
    if (el === stopAt) break;
    el = el.parentElement;
  }
  return elements;
}
function hasScrollbar(el) {
  if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
  const style = window.getComputedStyle(el);
  const hasVerticalScrollbar = style.overflowY === 'scroll' || style.overflowY === 'auto' && el.scrollHeight > el.clientHeight;
  const hasHorizontalScrollbar = style.overflowX === 'scroll' || style.overflowX === 'auto' && el.scrollWidth > el.clientWidth;
  return hasVerticalScrollbar || hasHorizontalScrollbar;
}
function isPotentiallyScrollable(el) {
  if (!el || el.nodeType !== Node.ELEMENT_NODE) return false;
  const style = window.getComputedStyle(el);
  return ['scroll', 'auto'].includes(style.overflowY);
}

// Types

function getIndentLines({
  depth,
  isLast,
  isLastGroup,
  leafLinks,
  separateRoots,
  parentIndentLines,
  variant
}) {
  const isLastLeaf = isLast && (!isLastGroup || separateRoots || depth > 1);
  if (!parentIndentLines || !depth) {
    return {
      leaf: undefined,
      node: undefined,
      children: parentIndentLines,
      footer: parentIndentLines && (!isLastLeaf || variant === 'simple') ? [...parentIndentLines, separateRoots ? 'none' : 'line'] : ['none']
    };
  }
  if (variant === 'simple') {
    return {
      leaf: [...parentIndentLines, 'line'],
      node: [...parentIndentLines, 'line'],
      children: [...parentIndentLines, 'line'],
      footer: [...parentIndentLines, 'line', 'line']
    };
  }
  return {
    leaf: [...parentIndentLines, isLastLeaf ? 'last-leaf' : 'leaf', ...(leafLinks ? ['leaf-link'] : [])],
    node: [...parentIndentLines, isLastLeaf ? 'last-leaf' : 'leaf'],
    children: [...parentIndentLines, isLastLeaf ? 'none' : 'line'],
    footer: [...parentIndentLines, isLastLeaf ? 'none' : 'line']
  };
}

function isFixedPosition(el) {
  while (el) {
    if (window.getComputedStyle(el).position === 'fixed') {
      return true;
    }
    el = el.offsetParent;
  }
  return false;
}

// Utilities

// Types

function useRender(render) {
  const vm = getCurrentInstance('useRender');
  vm.render = render;
}

function formatTime(seconds) {
  return [Math.floor(seconds % 60), Math.floor(seconds / 60 % 60), Math.floor(seconds / 60 / 60 % 60)].filter((x, i) => i < 2 || x > 0).reverse().map(String).map((x, i) => i > 0 ? x.padStart(2, '0') : x).join(':');
}

function throttle(fn, delay, options = {
  leading: true,
  trailing: true
}) {
  let timeoutId = 0;
  let lastExec = 0;
  let throttling = false;
  let start = 0;
  function clear() {
    clearTimeout(timeoutId);
    throttling = false;
    start = 0;
  }
  const wrap = (...args) => {
    clearTimeout(timeoutId);
    const now = Date.now();
    if (!start) start = now;
    const elapsed = now - Math.max(start, lastExec);
    function invoke() {
      lastExec = Date.now();
      timeoutId = setTimeout(clear, delay);
      fn(...args);
    }
    if (!throttling) {
      throttling = true;
      if (options.leading) {
        invoke();
      }
    } else if (elapsed >= delay) {
      invoke();
    } else if (options.trailing) {
      timeoutId = setTimeout(invoke, delay - elapsed);
    }
  };
  wrap.clear = clear;
  wrap.immediate = fn;
  return wrap;
}

// Utilities

// Types

function useResizeObserver(callback, box = 'content') {
  const resizeRef = templateRef();
  const contentRect = ref();
  if (IN_BROWSER) {
    const observer = new ResizeObserver(entries => {
      callback?.(entries, observer);
      if (!entries.length) return;
      if (box === 'content') {
        contentRect.value = entries[0].contentRect;
      } else {
        // borderBoxSize ignores CSS transforms (e.g. VDialogTransition scale-in)
        const border = entries[0].borderBoxSize?.[0];
        const el = entries[0].target;
        contentRect.value = new Box({
          x: 0,
          y: 0,
          width: border?.inlineSize ?? el.offsetWidth,
          height: border?.blockSize ?? el.offsetHeight
        });
      }
    });
    onBeforeUnmount(() => {
      observer.disconnect();
    });
    watch(() => resizeRef.el, (newValue, oldValue) => {
      if (oldValue) {
        observer.unobserve(oldValue);
        contentRect.value = undefined;
      }
      if (newValue) observer.observe(newValue);
    }, {
      flush: 'post'
    });
  }
  return {
    resizeRef,
    contentRect: readonly(contentRect)
  };
}

// Composables

// Types

const VuetifyLayoutKey = Symbol.for('vuetify:layout');
const VuetifyLayoutItemKey = Symbol.for('vuetify:layout-item');
const ROOT_ZINDEX = 1000;
const makeLayoutProps = propsFactory({
  overlaps: {
    type: Array,
    default: () => []
  },
  fullHeight: Boolean
}, 'layout');

// Composables
const makeLayoutItemProps = propsFactory({
  name: {
    type: String
  },
  order: {
    type: [Number, String],
    default: 0
  },
  absolute: Boolean
}, 'layout-item');
function useLayout() {
  const layout = inject$1(VuetifyLayoutKey);
  if (!layout) throw new Error('[Vuetify] Could not find injected layout');
  return {
    getLayoutItem: layout.getLayoutItem,
    mainRect: layout.mainRect,
    mainStyles: layout.mainStyles
  };
}
function useLayoutItem(options) {
  const layout = inject$1(VuetifyLayoutKey);
  if (!layout) throw new Error('[Vuetify] Could not find injected layout');
  const id = options.id ?? `layout-item-${useId()}`;
  const vm = getCurrentInstance('useLayoutItem');
  provide(VuetifyLayoutItemKey, {
    id
  });
  const isKeptAlive = shallowRef(false);
  onDeactivated(() => isKeptAlive.value = true);
  onActivated(() => isKeptAlive.value = false);
  const {
    layoutItemStyles,
    layoutItemScrimStyles
  } = layout.register(vm, {
    ...options,
    active: computed(() => isKeptAlive.value ? false : options.active.value),
    id
  });
  onBeforeUnmount(() => layout.unregister(id));
  return {
    layoutItemStyles,
    layoutRect: layout.layoutRect,
    layoutItemScrimStyles
  };
}
const generateLayers = (layout, positions, layoutSizes, activeItems) => {
  let previousLayer = {
    top: 0,
    left: 0,
    right: 0,
    bottom: 0
  };
  const layers = [{
    id: '',
    layer: {
      ...previousLayer
    }
  }];
  for (const id of layout) {
    const position = positions.get(id);
    const amount = layoutSizes.get(id);
    const active = activeItems.get(id);
    if (!position || !amount || !active) continue;
    const layer = {
      ...previousLayer,
      [position.value]: parseInt(previousLayer[position.value], 10) + (active.value ? parseInt(amount.value, 10) : 0)
    };
    layers.push({
      id,
      layer
    });
    previousLayer = layer;
  }
  return layers;
};
function createLayout(props) {
  const parentLayout = inject$1(VuetifyLayoutKey, null);
  const rootZIndex = computed(() => parentLayout ? parentLayout.rootZIndex.value - 100 : ROOT_ZINDEX);
  const registered = ref([]);
  const positions = reactive(new Map());
  const layoutSizes = reactive(new Map());
  const priorities = reactive(new Map());
  const activeItems = reactive(new Map());
  const disabledTransitions = reactive(new Map());
  const {
    resizeRef,
    contentRect: layoutRect
  } = useResizeObserver();
  const computedOverlaps = computed(() => {
    const map = new Map();
    const overlaps = props.overlaps ?? [];
    for (const overlap of overlaps.filter(item => item.includes(':'))) {
      const [top, bottom] = overlap.split(':');
      if (!registered.value.includes(top) || !registered.value.includes(bottom)) continue;
      const topPosition = positions.get(top);
      const bottomPosition = positions.get(bottom);
      const topAmount = layoutSizes.get(top);
      const bottomAmount = layoutSizes.get(bottom);
      if (!topPosition || !bottomPosition || !topAmount || !bottomAmount) continue;
      map.set(bottom, {
        position: topPosition.value,
        amount: parseInt(topAmount.value, 10)
      });
      map.set(top, {
        position: bottomPosition.value,
        amount: -parseInt(bottomAmount.value, 10)
      });
    }
    return map;
  });
  const layers = computed(() => {
    const uniquePriorities = [...new Set([...priorities.values()].map(p => p.value))].sort((a, b) => a - b);
    const layout = [];
    for (const p of uniquePriorities) {
      const items = registered.value.filter(id => priorities.get(id)?.value === p);
      layout.push(...items);
    }
    return generateLayers(layout, positions, layoutSizes, activeItems);
  });
  const transitionsEnabled = computed(() => {
    return !Array.from(disabledTransitions.values()).some(ref => ref.value);
  });
  const mainRect = computed(() => {
    return layers.value[layers.value.length - 1].layer;
  });
  const mainStyles = toRef(() => {
    return {
      '--v-layout-left': convertToUnit(mainRect.value.left),
      '--v-layout-right': convertToUnit(mainRect.value.right),
      '--v-layout-top': convertToUnit(mainRect.value.top),
      '--v-layout-bottom': convertToUnit(mainRect.value.bottom),
      ...(transitionsEnabled.value ? undefined : {
        transition: 'none'
      })
    };
  });
  const items = computed(() => {
    return layers.value.slice(1).map(({
      id
    }, index) => {
      const {
        layer
      } = layers.value[index];
      const size = layoutSizes.get(id);
      const position = positions.get(id);
      return {
        id,
        ...layer,
        size: Number(size.value),
        position: position.value
      };
    });
  });
  const getLayoutItem = id => {
    return items.value.find(item => item.id === id);
  };
  const rootVm = getCurrentInstance('createLayout');
  const isMounted = shallowRef(false);
  onMounted(() => {
    isMounted.value = true;
  });
  provide(VuetifyLayoutKey, {
    register: (vm, {
      id,
      order,
      position,
      layoutSize,
      elementSize,
      active,
      disableTransitions,
      absolute
    }) => {
      priorities.set(id, order);
      positions.set(id, position);
      layoutSizes.set(id, layoutSize);
      activeItems.set(id, active);
      disableTransitions && disabledTransitions.set(id, disableTransitions);
      const instances = findChildrenWithProvide(VuetifyLayoutItemKey, rootVm?.vnode);
      const instanceIndex = instances.indexOf(vm);
      if (instanceIndex > -1) registered.value.splice(instanceIndex, 0, id);else registered.value.push(id);
      const index = computed(() => items.value.findIndex(i => i.id === id));
      const zIndex = computed(() => rootZIndex.value + layers.value.length * 2 - index.value * 2);
      const layoutItemStyles = computed(() => {
        const isHorizontal = position.value === 'left' || position.value === 'right';
        const isOppositeHorizontal = position.value === 'right';
        const isOppositeVertical = position.value === 'bottom';
        const size = Number(elementSize.value ?? layoutSize.value);
        const transformFunction = `translate${isHorizontal ? 'X' : 'Y'}`;
        const transformValue = active.value ? 0 : (size === 0 ? 100 : size + 1) * (isOppositeHorizontal || isOppositeVertical ? 1 : -1);
        const unit = size === 0 ? '%' : 'px';
        const styles = {
          [position.value]: 0,
          zIndex: zIndex.value,
          transform: `${transformFunction}(${transformValue}${unit})`,
          position: absolute.value || rootZIndex.value !== ROOT_ZINDEX ? 'absolute' : 'fixed',
          ...(transitionsEnabled.value ? undefined : {
            transition: 'none'
          })
        };
        if (!isMounted.value) return styles;
        const item = items.value[index.value];
        if (!item) consoleWarn(`[Vuetify] Could not find layout item "${id}"`);
        const overlap = computedOverlaps.value.get(id);
        if (overlap) {
          item[overlap.position] += overlap.amount;
        }
        return {
          ...styles,
          height: isHorizontal ? `calc(100% - ${item.top}px - ${item.bottom}px)` : elementSize.value ? `${elementSize.value}px` : undefined,
          left: isOppositeHorizontal ? undefined : `${item.left}px`,
          right: isOppositeHorizontal ? `${item.right}px` : undefined,
          top: position.value !== 'bottom' ? `${item.top}px` : undefined,
          bottom: position.value !== 'top' ? `${item.bottom}px` : undefined,
          width: !isHorizontal ? `calc(100% - ${item.left}px - ${item.right}px)` : elementSize.value ? `${elementSize.value}px` : undefined
        };
      });
      const layoutItemScrimStyles = computed(() => ({
        zIndex: zIndex.value - 1
      }));
      return {
        layoutItemStyles,
        layoutItemScrimStyles,
        zIndex
      };
    },
    unregister: id => {
      priorities.delete(id);
      positions.delete(id);
      layoutSizes.delete(id);
      activeItems.delete(id);
      disabledTransitions.delete(id);
      registered.value = registered.value.filter(v => v !== id);
    },
    mainRect,
    mainStyles,
    getLayoutItem,
    items,
    layoutRect,
    rootZIndex
  });
  const layoutClasses = toRef(() => ['v-layout', {
    'v-layout--full-height': props.fullHeight
  }]);
  const layoutStyles = toRef(() => ({
    zIndex: parentLayout ? rootZIndex.value : undefined,
    position: parentLayout ? 'relative' : undefined,
    overflow: parentLayout ? 'hidden' : undefined
  }));
  return {
    layoutClasses,
    layoutStyles,
    getLayoutItem,
    items,
    layoutRect,
    layoutRef: resizeRef
  };
}

// Utilities

// Types

function useToggleScope(source, fn) {
  let scope;
  function start() {
    scope = effectScope();
    scope.run(() => fn.length ? fn(() => {
      scope?.stop();
      start();
    }) : fn());
  }
  watch(source, active => {
    if (active && !scope) {
      start();
    } else if (!active) {
      scope?.stop();
      scope = undefined;
    }
  }, {
    immediate: true
  });
  onScopeDispose(() => {
    scope?.stop();
  });
}

// Composables

// Types

// Composables
function useProxiedModel(props, prop, defaultValue, transformIn = v => v, transformOut = v => v) {
  const vm = getCurrentInstance('useProxiedModel');
  const internal = ref(props[prop] !== undefined ? props[prop] : defaultValue);
  const kebabProp = toKebabCase(prop);
  const checkKebab = kebabProp !== prop;
  const isControlled = checkKebab ? computed(() => {
    void props[prop];
    return !!((vm.vnode.props?.hasOwnProperty(prop) || vm.vnode.props?.hasOwnProperty(kebabProp)) && (vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`) || vm.vnode.props?.hasOwnProperty(`onUpdate:${kebabProp}`)));
  }) : computed(() => {
    void props[prop];
    return !!(vm.vnode.props?.hasOwnProperty(prop) && vm.vnode.props?.hasOwnProperty(`onUpdate:${prop}`));
  });
  useToggleScope(() => !isControlled.value, () => {
    watch(() => props[prop], val => {
      internal.value = val;
    });
  });
  const model = computed({
    get() {
      const externalValue = props[prop];
      return transformIn(isControlled.value ? externalValue : internal.value);
    },
    set(internalValue) {
      const newValue = transformOut(internalValue);
      const value = toRaw(isControlled.value ? props[prop] : internal.value);
      if (value === newValue || transformIn(value) === internalValue) {
        return;
      }
      internal.value = newValue;
      vm?.emit(`update:${prop}`, newValue);
    }
  });
  Object.defineProperty(model, 'externalValue', {
    get: () => isControlled.value ? props[prop] : internal.value
  });
  return model;
}

var en = {
  badge: 'Badge',
  open: 'Open',
  close: 'Close',
  dismiss: 'Dismiss',
  confirmEdit: {
    ok: 'OK',
    cancel: 'Cancel'
  },
  dataIterator: {
    noResultsText: 'No matching records found',
    loadingText: 'Loading items...'
  },
  dataTable: {
    itemsPerPageText: 'Rows per page:',
    ariaLabel: {
      sortDescending: 'Sorted descending.',
      sortAscending: 'Sorted ascending.',
      sortNone: 'Not sorted.',
      activateNone: 'Activate to remove sorting.',
      activateDescending: 'Activate to sort descending.',
      activateAscending: 'Activate to sort ascending.',
      selectRow: 'Select row',
      selectAll: 'Select all',
      selectGroup: 'Select group'
    },
    sortBy: 'Sort by'
  },
  dataFooter: {
    itemsPerPageText: 'Items per page:',
    itemsPerPageAll: 'All',
    nextPage: 'Next page',
    prevPage: 'Previous page',
    firstPage: 'First page',
    lastPage: 'Last page',
    pageText: '{0}-{1} of {2}'
  },
  dateRangeInput: {
    divider: 'to'
  },
  monthPicker: {
    title: 'Select month',
    itemsSelected: '{0} selected',
    header: 'Enter month',
    range: {
      title: 'Enter months'
    },
    ariaLabel: {
      previousYear: 'Previous year',
      nextYear: 'Next year',
      selectYear: 'Select year',
      currentMonth: 'Current month, {0}'
    }
  },
  datePicker: {
    itemsSelected: '{0} selected',
    range: {
      title: 'Select dates',
      header: 'Enter dates'
    },
    title: 'Select date',
    header: 'Enter date',
    input: {
      placeholder: 'Enter date'
    },
    ariaLabel: {
      previousMonth: 'Previous month',
      nextMonth: 'Next month',
      selectYear: 'Select year',
      previousYear: 'Previous year',
      nextYear: 'Next year',
      selectMonth: 'Select month',
      selectDate: '{0}',
      // Full date format
      currentDate: 'Today, {0}'
    }
  },
  noDataText: 'No data available',
  carousel: {
    prev: 'Previous visual',
    next: 'Next visual',
    ariaLabel: {
      delimiter: 'Carousel slide {0} of {1}'
    }
  },
  calendar: {
    moreEvents: '{0} more',
    today: 'Today'
  },
  heatmap: {
    less: 'Less',
    more: 'More'
  },
  input: {
    clear: 'Clear {0}',
    prependAction: '{0} prepended action',
    appendAction: '{0} appended action',
    otp: 'Enter verification code'
  },
  fileInput: {
    counter: '{0} files',
    counterSize: '{0} files ({1} in total)'
  },
  fileUpload: {
    title: 'Drag and drop files here',
    divider: 'or',
    browse: 'Browse Files'
  },
  timePicker: {
    am: 'AM',
    pm: 'PM',
    title: 'Select Time',
    hour: 'Hour',
    minute: 'Minute',
    second: 'Second',
    notAllowed: 'Value is not allowed'
  },
  pagination: {
    ariaLabel: {
      root: 'Pagination Navigation',
      next: 'Next page',
      previous: 'Previous page',
      page: 'Go to page {0}',
      currentPage: 'Page {0}, Current page',
      first: 'First page',
      last: 'Last page'
    }
  },
  stepper: {
    next: 'Next',
    prev: 'Previous'
  },
  rating: {
    ariaLabel: {
      item: 'Rating {0} of {1}'
    }
  },
  loading: 'Loading...',
  infiniteScroll: {
    loadMore: 'Load more',
    empty: 'No more'
  },
  rules: {
    required: 'This field is required',
    email: 'Please enter a valid email',
    number: 'This field can only contain numbers',
    integer: 'This field can only contain integer values',
    capital: 'This field can only contain uppercase letters',
    maxLength: 'You must enter a maximum of {0} characters',
    minLength: 'You must enter a minimum of {0} characters',
    strictLength: 'The length of the entered field is invalid',
    exclude: 'The {0} character is not allowed',
    notEmpty: 'Please choose at least one value',
    pattern: 'Invalid format'
  },
  command: {
    search: 'Type a command or search...'
  },
  hotkey: {
    then: 'then',
    ctrl: 'Ctrl',
    command: 'Command',
    space: 'Space',
    shift: 'Shift',
    alt: 'Alt',
    enter: 'Enter',
    escape: 'Escape',
    upArrow: 'Up Arrow',
    downArrow: 'Down Arrow',
    leftArrow: 'Left Arrow',
    rightArrow: 'Right Arrow',
    backspace: 'Backspace',
    option: 'Option',
    plus: 'plus',
    shortcut: 'Keyboard shortcut: {0}',
    or: 'or'
  },
  video: {
    play: 'Play',
    pause: 'Pause',
    seek: 'Seek',
    volume: 'Volume',
    showVolume: 'Show volume control',
    mute: 'Mute',
    unmute: 'Unmute',
    enterFullscreen: 'Full screen',
    exitFullscreen: 'Exit full screen'
  },
  colorPicker: {
    ariaLabel: {
      eyedropper: 'Select color with eyedropper',
      hueSlider: 'Hue',
      alphaSlider: 'Alpha',
      redInput: 'Red value',
      greenInput: 'Green value',
      blueInput: 'Blue value',
      alphaInput: 'Alpha value',
      hueInput: 'Hue value',
      saturationInput: 'Saturation value',
      lightnessInput: 'Lightness value',
      hexInput: 'HEX value',
      hexaInput: 'HEX with alpha value',
      changeFormat: 'Change color format'
    }
  }
};

// Composables

// Types

const LANG_PREFIX = '$vuetify.';
const replace = (str, params) => {
  return str.replace(/\{(\d+)\}/g, (match, index) => {
    return String(params[Number(index)]);
  });
};
const createTranslateFunction = (current, fallback, messages) => {
  return (key, ...params) => {
    if (!key.startsWith(LANG_PREFIX)) {
      return replace(key, params);
    }
    const shortKey = key.replace(LANG_PREFIX, '');
    const currentLocale = current.value && messages.value[current.value];
    const fallbackLocale = fallback.value && messages.value[fallback.value];
    let str = getObjectValueByPath(currentLocale, shortKey, null);
    if (!str) {
      consoleWarn(`Translation key "${key}" not found in "${current.value}", trying fallback locale`);
      str = getObjectValueByPath(fallbackLocale, shortKey, null);
    }
    if (!str) {
      consoleError(`Translation key "${key}" not found in fallback`);
      str = key;
    }
    if (typeof str !== 'string') {
      consoleError(`Translation key "${key}" has a non-string value`);
      str = key;
    }
    return replace(str, params);
  };
};
function createNumberFunction(current, fallback) {
  return (value, options) => {
    const numberFormat = new Intl.NumberFormat([current.value, fallback.value], options);
    return numberFormat.format(value);
  };
}
function inferDecimalSeparator(current, fallback) {
  const format = createNumberFunction(current, fallback);
  return format(0.1).includes(',') ? ',' : '.';
}
function inferNumericGroupSeparator(current, fallback) {
  return new Intl.NumberFormat([current.value, fallback.value], {
    useGrouping: true
  }).formatToParts(10000).find(p => p.type === 'group')?.value ?? ' ';
}
function useProvided(props, prop, provided) {
  const internal = useProxiedModel(props, prop, props[prop] ?? provided.value);

  // TODO: Remove when defaultValue works
  internal.value = props[prop] ?? provided.value;
  watch(provided, v => {
    if (props[prop] == null) {
      internal.value = provided.value;
    }
  });
  return internal;
}
function createProvideFunction(state) {
  return props => {
    const current = useProvided(props, 'locale', state.current);
    const fallback = useProvided(props, 'fallback', state.fallback);
    const messages = useProvided(props, 'messages', state.messages);
    return {
      name: 'vuetify',
      current,
      fallback,
      messages,
      decimalSeparator: toRef(() => inferDecimalSeparator(current, fallback)),
      numericGroupSeparator: toRef(() => inferNumericGroupSeparator(current, fallback)),
      t: createTranslateFunction(current, fallback, messages),
      n: createNumberFunction(current, fallback),
      provide: createProvideFunction({
        current,
        fallback,
        messages
      })
    };
  };
}
function createVuetifyAdapter(options) {
  const current = shallowRef(options?.locale ?? 'en');
  const fallback = shallowRef(options?.fallback ?? 'en');
  const messages = ref({
    en,
    ...options?.messages
  });
  return {
    name: 'vuetify',
    current,
    fallback,
    messages,
    decimalSeparator: toRef(() => options?.decimalSeparator ?? inferDecimalSeparator(current, fallback)),
    numericGroupSeparator: toRef(() => options?.numericGroupSeparator ?? inferNumericGroupSeparator(current, fallback)),
    t: createTranslateFunction(current, fallback, messages),
    n: createNumberFunction(current, fallback),
    provide: createProvideFunction({
      current,
      fallback,
      messages
    })
  };
}

// Utilities

// Types

const LocaleSymbol = Symbol.for('vuetify:locale');
function isLocaleInstance(obj) {
  return obj.name != null;
}
function createLocale(options) {
  const i18n = options?.adapter && isLocaleInstance(options?.adapter) ? options?.adapter : createVuetifyAdapter(options);
  const rtl = createRtl(i18n, options);
  return {
    ...i18n,
    ...rtl
  };
}
function useLocale() {
  const locale = inject$1(LocaleSymbol);
  if (!locale) throw new Error('[Vuetify] Could not find injected locale instance');
  return locale;
}
function provideLocale(props) {
  const locale = inject$1(LocaleSymbol);
  if (!locale) throw new Error('[Vuetify] Could not find injected locale instance');
  const i18n = locale.provide(props);
  const rtl = provideRtl(i18n, locale.rtl, props);
  const data = {
    ...i18n,
    ...rtl
  };
  provide(LocaleSymbol, data);
  return data;
}
function genDefaults$3() {
  return {
    af: false,
    ar: true,
    bg: false,
    ca: false,
    ckb: true,
    cs: false,
    de: false,
    el: false,
    en: false,
    es: false,
    et: false,
    fa: true,
    fi: false,
    fr: false,
    hr: false,
    hu: false,
    he: true,
    id: false,
    it: false,
    ja: false,
    km: false,
    ko: false,
    lv: false,
    lt: false,
    nl: false,
    no: false,
    pl: false,
    pt: false,
    ro: false,
    ru: false,
    sk: false,
    sl: false,
    srCyrl: false,
    srLatn: false,
    sv: false,
    th: false,
    tr: false,
    az: false,
    uk: false,
    vi: false,
    zhHans: false,
    zhHant: false
  };
}
function createRtl(i18n, options) {
  const rtl = ref(options?.rtl ?? genDefaults$3());
  const isRtl = computed(() => rtl.value[i18n.current.value] ?? false);
  return {
    isRtl,
    rtl,
    rtlClasses: toRef(() => `v-locale--is-${isRtl.value ? 'rtl' : 'ltr'}`)
  };
}
function provideRtl(locale, rtl, props) {
  const isRtl = computed(() => props.rtl ?? rtl.value[locale.current.value] ?? false);
  return {
    isRtl,
    rtl,
    rtlClasses: toRef(() => `v-locale--is-${isRtl.value ? 'rtl' : 'ltr'}`)
  };
}
function useRtl() {
  const locale = inject$1(LocaleSymbol);
  if (!locale) throw new Error('[Vuetify] Could not find injected rtl instance');
  return {
    isRtl: locale.isRtl,
    rtlClasses: locale.rtlClasses
  };
}

// Utilities

// Types

const ThemeSymbol = Symbol.for('vuetify:theme');
const makeThemeProps = propsFactory({
  theme: String
}, 'theme');
function genDefaults$2() {
  return {
    defaultTheme: 'system',
    prefix: 'v-',
    variations: {
      colors: [],
      lighten: 0,
      darken: 0
    },
    themes: {
      light: {
        dark: false,
        colors: {
          background: '#FFFFFF',
          surface: '#FFFFFF',
          'surface-bright': '#FFFFFF',
          'surface-light': '#EEEEEE',
          'surface-variant': '#424242',
          'on-surface-variant': '#EEEEEE',
          primary: '#1867C0',
          'primary-darken-1': '#1F5592',
          secondary: '#48A9A6',
          'secondary-darken-1': '#018786',
          error: '#B00020',
          info: '#2196F3',
          success: '#4CAF50',
          warning: '#FB8C00'
        },
        variables: {
          'border-color': '#000000',
          'border-opacity': 0.12,
          'shadow-color': '#000000',
          'high-emphasis-opacity': 0.87,
          'medium-emphasis-opacity': 0.60,
          'disabled-opacity': 0.38,
          'idle-opacity': 0.04,
          'hover-opacity': 0.04,
          'focus-opacity': 0.12,
          'selected-opacity': 0.08,
          'activated-opacity': 0.12,
          'pressed-opacity': 0.12,
          'dragged-opacity': 0.08,
          'theme-kbd': '#EEEEEE',
          'theme-on-kbd': '#000000',
          'theme-code': '#F5F5F5',
          'theme-on-code': '#000000',
          'theme-on-dark': '#FFF',
          'theme-on-light': '#000',
          'elevation-overlay-color': 'black',
          'elevation-overlay-opacity-step': '2%',
          'highlight-opacity': '8%'
        }
      },
      dark: {
        dark: true,
        colors: {
          background: '#121212',
          surface: '#212121',
          'surface-bright': '#ccbfd6',
          'surface-light': '#424242',
          'surface-variant': '#c8c8c8',
          'on-surface-variant': '#000000',
          primary: '#2196F3',
          'primary-darken-1': '#277CC1',
          secondary: '#54B6B2',
          'secondary-darken-1': '#48A9A6',
          error: '#CF6679',
          info: '#2196F3',
          success: '#4CAF50',
          warning: '#FB8C00'
        },
        variables: {
          'border-color': '#FFFFFF',
          'border-opacity': 0.12,
          'shadow-color': '#000000',
          'high-emphasis-opacity': 1,
          'medium-emphasis-opacity': 0.70,
          'disabled-opacity': 0.50,
          'idle-opacity': 0.10,
          'hover-opacity': 0.04,
          'focus-opacity': 0.12,
          'selected-opacity': 0.08,
          'activated-opacity': 0.12,
          'pressed-opacity': 0.16,
          'dragged-opacity': 0.08,
          'theme-kbd': '#424242',
          'theme-on-kbd': '#FFFFFF',
          'theme-code': '#343434',
          'theme-on-code': '#CCCCCC',
          'theme-on-dark': '#FFF',
          'theme-on-light': '#000',
          'elevation-overlay-color': 'white',
          'elevation-overlay-opacity-step': '2%',
          'highlight-opacity': '20%'
        }
      }
    },
    stylesheetId: 'vuetify-theme-stylesheet',
    scoped: false,
    utilities: true,
    transition: false
  };
}
function parseThemeOptions(options = genDefaults$2()) {
  const defaults = genDefaults$2();
  if (!options) return {
    ...defaults,
    isDisabled: true
  };
  return mergeDeep(defaults, options);
}
function createCssClass(lines, selector, content, scope) {
  lines.push(`${getScopedSelector(selector, scope)} {\n`, ...content.map(line => `  ${line};\n`), '}\n');
}
function genCssVariables(theme, prefix) {
  const lightOverlay = theme.dark ? 2 : 1;
  const darkOverlay = theme.dark ? 1 : 2;
  const variables = [];
  for (const [key, value] of Object.entries(theme.colors)) {
    const rgb = parseColor(value);
    variables.push(`--${prefix}theme-${key}: ${rgb.r},${rgb.g},${rgb.b}` + (rgb.a == null ? '' : `,${rgb.a}`));
    if (!key.startsWith('on-')) {
      variables.push(`--${prefix}theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
    }
  }
  for (const [key, value] of Object.entries(theme.variables)) {
    const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
    const rgb = color ? `${color.r}, ${color.g}, ${color.b}` + (color.a == null ? '' : `, ${color.a}`) : undefined;
    variables.push(`--${prefix}${key}: ${rgb ?? value}`);
  }
  return variables;
}
function genVariation(name, color, variations) {
  const object = {};
  if (variations) {
    for (const variation of ['lighten', 'darken']) {
      const fn = variation === 'lighten' ? lighten : darken;
      for (const amount of createRange(variations[variation], 1)) {
        object[`${name}-${variation}-${amount}`] = RGBtoHex(fn(parseColor(color), amount));
      }
    }
  }
  return object;
}
function genVariations(colors, variations) {
  if (!variations) return {};
  let variationColors = {};
  for (const name of variations.colors) {
    const color = colors[name];
    if (!color) continue;
    variationColors = {
      ...variationColors,
      ...genVariation(name, color, variations)
    };
  }
  return variationColors;
}
function genOnColors(colors, variables) {
  const onColors = {};
  for (const color of Object.keys(colors)) {
    if (color.startsWith('on-') || colors[`on-${color}`]) continue;
    const onColor = `on-${color}`;
    const colorVal = parseColor(colors[color]);
    onColors[onColor] = hasLightForeground(colorVal) ? variables['theme-on-dark'] : variables['theme-on-light'];
  }
  return onColors;
}
function getScopedSelector(selector, scope) {
  if (!scope) return selector;
  const scopeSelector = `:where(${scope})`;
  return selector === ':root' ? scopeSelector : `${scopeSelector} ${selector}`;
}
function upsertStyles(id, cspNonce, styles) {
  const styleEl = getOrCreateStyleElement(id, cspNonce);
  if (!styleEl) return;
  styleEl.innerHTML = styles;
}
function getOrCreateStyleElement(id, cspNonce) {
  if (!IN_BROWSER) return null;
  let style = document.getElementById(id);
  if (!style) {
    style = document.createElement('style');
    style.id = id;
    style.type = 'text/css';
    if (cspNonce) style.setAttribute('nonce', cspNonce);
    document.head.appendChild(style);
  }
  return style;
}

// Composables
function createTheme(options) {
  const parsedOptions = parseThemeOptions(options);
  const _name = shallowRef(parsedOptions.defaultTheme);
  const themes = ref(parsedOptions.themes);
  const systemName = shallowRef('light');
  const name = computed({
    get() {
      return _name.value === 'system' ? systemName.value : _name.value;
    },
    set(val) {
      _name.value = val;
    }
  });
  const computedThemes = computed(() => {
    const acc = {};
    for (const [name, original] of Object.entries(themes.value)) {
      const defaultTheme = original.dark || name === 'dark' ? themes.value.dark : themes.value.light;
      const merged = mergeDeep(defaultTheme, original);
      const colors = {
        ...merged.colors,
        ...genVariations(merged.colors, parsedOptions.variations)
      };
      acc[name] = {
        ...merged,
        colors: {
          ...colors,
          ...genOnColors(colors, merged.variables)
        }
      };
    }
    return acc;
  });
  const current = toRef(() => computedThemes.value[name.value]);
  const isSystem = toRef(() => _name.value === 'system');
  const styles = computed(() => {
    const lines = [];
    const scoped = parsedOptions.scoped ? parsedOptions.prefix : '';
    lines.push('@layer theme-base {\n');
    createCssClass(lines, ':root', [`color-scheme: ${current.value?.dark ? 'dark' : 'light'}`], parsedOptions.scope);
    createCssClass(lines, ':root', genCssVariables(current.value, parsedOptions.prefix), parsedOptions.scope);
    for (const [themeName, theme] of Object.entries(computedThemes.value)) {
      createCssClass(lines, `.${parsedOptions.prefix}theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'light'}`, ...genCssVariables(theme, parsedOptions.prefix)], parsedOptions.scope);
    }
    lines.push('}\n');
    if (parsedOptions.utilities) {
      const bgLines = [];
      const fgLines = [];
      const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
      for (const key of colors) {
        if (key.startsWith('on-')) {
          createCssClass(fgLines, `.${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))`], parsedOptions.scope);
        } else {
          createCssClass(bgLines, `.${scoped}bg-${key}`, [`--${parsedOptions.prefix}theme-overlay-multiplier: var(--${parsedOptions.prefix}theme-${key}-overlay-multiplier)`, `background-color: rgb(var(--${parsedOptions.prefix}theme-${key}))`, `color: rgb(var(--${parsedOptions.prefix}theme-on-${key}))`], parsedOptions.scope);
          createCssClass(fgLines, `.${scoped}text-${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))`], parsedOptions.scope);
          createCssClass(fgLines, `.${scoped}border-${key}`, [`--${parsedOptions.prefix}border-color: var(--${parsedOptions.prefix}theme-${key})`], parsedOptions.scope);
        }
      }
      lines.push('@layer theme-background {\n', ...bgLines.map(v => `  ${v}`), '}\n', '@layer theme-foreground {\n', ...fgLines.map(v => `  ${v}`), '}\n');
    }
    return '@layer vuetify-utilities {\n' + lines.map(v => `  ${v}`).join('') + '\n}';
  });
  const themeClasses = toRef(() => parsedOptions.isDisabled ? undefined : `${parsedOptions.prefix}theme--${name.value}`);
  const themeNames = toRef(() => Object.keys(computedThemes.value));
  if (SUPPORTS_MATCH_MEDIA) {
    const media = window.matchMedia('(prefers-color-scheme: dark)');
    function updateSystemName() {
      systemName.value = media.matches ? 'dark' : 'light';
    }
    updateSystemName();
    media.addEventListener('change', updateSystemName, {
      passive: true
    });
    if (getCurrentScope()) {
      onScopeDispose(() => {
        media.removeEventListener('change', updateSystemName);
      });
    }
  }
  function install(app) {
    if (parsedOptions.isDisabled) return;
    const head = app._context.provides.usehead;
    if (head) {
      function getHead() {
        return {
          style: [{
            textContent: styles.value,
            id: parsedOptions.stylesheetId,
            nonce: parsedOptions.cspNonce || false,
            tagPosition: 'bodyOpen'
          }]
        };
      }
      if (head.push) {
        const entry = head.push(getHead);
        if (IN_BROWSER) {
          watch(styles, () => {
            entry.patch(getHead);
          });
        }
      } else {
        if (IN_BROWSER) {
          head.addHeadObjs(toRef(getHead));
          watchEffect(() => head.updateDOM());
        } else {
          head.addHeadObjs(getHead());
        }
      }
    } else {
      if (IN_BROWSER) {
        watch(styles, updateStyles, {
          immediate: true
        });
      } else {
        updateStyles();
      }
      function updateStyles() {
        upsertStyles(parsedOptions.stylesheetId, parsedOptions.cspNonce, styles.value);
      }
    }
  }
  let _transitionOrigin;
  function setTransitionOrigin(e) {
    if (!e) {
      _transitionOrigin = null;
      return;
    }
    let x;
    let y;
    if (e instanceof Element) {
      const box = new Box(e);
      x = box.left + box.width / 2;
      y = box.top + box.height / 2;
    } else {
      x = e.clientX;
      y = e.clientY;
    }
    const originX = Math.min(98.9, 100 * x / window.innerWidth); // clip to avoid glitches
    const originY = 100 * y / window.innerHeight;
    _transitionOrigin = `${originX.toFixed(2)}% ${originY.toFixed(2)}%`;
  }
  function resolveTransitionOptions(transition) {
    const opt = transition ?? parsedOptions.transition;
    if (!opt && !_transitionOrigin) return false;
    const global = typeof parsedOptions.transition === 'object' ? parsedOptions.transition : {};
    const local = typeof transition === 'object' ? transition : {};
    return {
      origin: local.origin ?? _transitionOrigin ?? global.origin,
      duration: local.duration ?? global.duration
    };
  }
  function withPageTransition(callback, options) {
    if (!IN_BROWSER || !document.startViewTransition || PREFERS_REDUCED_MOTION()) {
      callback();
      return Promise.resolve();
    }
    const origin = options.origin ?? '50% 0%';
    const duration = options.duration ?? '500ms';
    const style = document.createElement('style');
    style.textContent = `html:active-view-transition-type(vuetify-theme)::view-transition-old(root) { animation: none; }` + `html:active-view-transition-type(vuetify-theme)::view-transition-new(root) { animation: v-circle-in ${duration} ease-in-out; }` + `@keyframes v-circle-in {` + `  from { clip-path: circle(0% at ${origin}); }` + `  to { clip-path: circle(150% at ${origin}); }` + `}`;
    document.head.appendChild(style);
    const transition = document.startViewTransition({
      update: () => callback(),
      types: ['vuetify-theme']
    });
    transition.finished.then(() => {
      _transitionOrigin = null;
      style.remove();
    });
    return transition.updateCallbackDone;
  }
  function change(themeName, transition) {
    if (themeName !== 'system' && !themeNames.value.includes(themeName)) {
      consoleWarn(`Theme "${themeName}" not found on the Vuetify theme instance`);
      return Promise.resolve();
    }
    const apply = () => {
      name.value = themeName;
    };
    const transitionOptions = resolveTransitionOptions(transition);
    if (transitionOptions) {
      return withPageTransition(apply, transitionOptions);
    }
    apply();
    return Promise.resolve();
  }
  function cycle(themeArray = themeNames.value, transition) {
    const currentIndex = themeArray.indexOf(name.value);
    const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % themeArray.length;
    return change(themeArray[nextIndex], transition);
  }
  function toggle(themeArray = ['light', 'dark'], transition) {
    return cycle(themeArray, transition);
  }
  const globalName = new Proxy(name, {
    get(target, prop) {
      return Reflect.get(target, prop);
    },
    set(target, prop, val) {
      if (prop === 'value') {
        deprecate(`theme.global.name.value = ${val}`, `theme.change('${val}')`);
      }
      return Reflect.set(target, prop, val);
    }
  });
  return {
    install,
    change,
    cycle,
    toggle,
    setTransitionOrigin,
    isDisabled: parsedOptions.isDisabled,
    isSystem,
    name,
    themes,
    current,
    computedThemes,
    prefix: parsedOptions.prefix,
    themeClasses,
    styles,
    global: {
      name: globalName,
      current
    }
  };
}
function provideTheme(props) {
  getCurrentInstance('provideTheme');
  const theme = inject$1(ThemeSymbol, null);
  if (!theme) throw new Error('Could not find Vuetify theme injection');
  const name = toRef(() => props.theme ?? theme.name.value);
  const current = toRef(() => theme.computedThemes.value[name.value]);
  const themeClasses = toRef(() => theme.isDisabled ? undefined : `${theme.prefix}theme--${name.value}`);
  const newTheme = {
    ...theme,
    name,
    current,
    themeClasses
  };
  provide(ThemeSymbol, newTheme);
  return newTheme;
}
function useTheme() {
  getCurrentInstance('useTheme');
  const theme = inject$1(ThemeSymbol, null);
  if (!theme) throw new Error('Could not find Vuetify theme injection');
  return theme;
}

const makeVAppProps = propsFactory({
  ...makeComponentProps(),
  ...omit(makeLayoutProps(), ['fullHeight']),
  ...makeThemeProps()
}, 'VApp');
const VApp = genericComponent()({
  name: 'VApp',
  props: makeVAppProps(),
  setup(props, {
    slots
  }) {
    const theme = provideTheme(props);
    const {
      layoutClasses,
      getLayoutItem,
      items,
      layoutRef
    } = createLayout({
      ...props,
      fullHeight: true
    });
    const {
      rtlClasses
    } = useRtl();
    useRender(() => createElementVNode("div", {
      "ref": layoutRef,
      "class": normalizeClass(['v-application', theme.themeClasses.value, layoutClasses.value, rtlClasses.value, props.class]),
      "style": normalizeStyle([props.style])
    }, [createElementVNode("div", {
      "class": "v-application__wrap"
    }, [slots.default?.()])]));
    return {
      getLayoutItem,
      items,
      theme
    };
  }
});

// Utilities

// Types

// Types

// Composables
const makeTagProps = propsFactory({
  tag: {
    type: [String, Object, Function],
    default: 'div'
  }
}, 'tag');

const makeVToolbarTitleProps = propsFactory({
  text: String,
  ...makeComponentProps(),
  ...makeTagProps()
}, 'VToolbarTitle');
const VToolbarTitle = genericComponent()({
  name: 'VToolbarTitle',
  props: makeVToolbarTitleProps(),
  setup(props, {
    slots
  }) {
    useRender(() => {
      const hasText = !!(slots.default || slots.text || props.text);
      return createVNode(props.tag, {
        "class": normalizeClass(['v-toolbar-title', props.class]),
        "style": normalizeStyle(props.style)
      }, {
        default: () => [hasText && createElementVNode("div", {
          "class": "v-toolbar-title__placeholder"
        }, [slots.text ? slots.text() : props.text, slots.default?.()])]
      });
    });
    return {};
  }
});

// Utilities

// Types

const makeTransitionProps$1 = propsFactory({
  disabled: Boolean,
  group: Boolean,
  hideOnLeave: Boolean,
  leaveAbsolute: Boolean,
  mode: String,
  origin: String
}, 'transition');
function createCssTransition(name, origin, mode) {
  return genericComponent()({
    name,
    props: makeTransitionProps$1({
      mode,
      origin
    }),
    setup(props, {
      slots
    }) {
      const functions = {
        onBeforeEnter(el) {
          if (props.origin) {
            el.style.transformOrigin = props.origin;
          }
        },
        onLeave(el) {
          if (props.leaveAbsolute) {
            const {
              offsetTop,
              offsetLeft,
              offsetWidth,
              offsetHeight
            } = el;
            el._transitionInitialStyles = {
              position: el.style.position,
              top: el.style.top,
              left: el.style.left,
              width: el.style.width,
              height: el.style.height
            };
            el.style.position = 'absolute';
            el.style.top = `${offsetTop}px`;
            el.style.left = `${offsetLeft}px`;
            el.style.width = `${offsetWidth}px`;
            el.style.height = `${offsetHeight}px`;
          }
          if (props.hideOnLeave) {
            el.style.setProperty('display', 'none', 'important');
          }
        },
        onAfterLeave(el) {
          if (props.leaveAbsolute && el?._transitionInitialStyles) {
            const {
              position,
              top,
              left,
              width,
              height
            } = el._transitionInitialStyles;
            delete el._transitionInitialStyles;
            el.style.position = position || '';
            el.style.top = top || '';
            el.style.left = left || '';
            el.style.width = width || '';
            el.style.height = height || '';
          }
        }
      };
      return () => {
        const tag = props.group ? TransitionGroup : Transition;
        return h(tag, {
          name: props.disabled ? '' : name,
          css: !props.disabled,
          ...(props.group ? undefined : {
            mode: props.mode
          }),
          ...(props.disabled ? {} : functions)
        }, slots.default);
      };
    }
  });
}
function createJavascriptTransition(name, functions, mode = 'in-out') {
  return genericComponent()({
    name,
    props: {
      mode: {
        type: String,
        default: mode
      },
      disabled: {
        type: Boolean,
        default: PREFERS_REDUCED_MOTION()
      },
      group: Boolean,
      hideOnLeave: Boolean
    },
    setup(props, {
      slots
    }) {
      const tag = props.group ? TransitionGroup : Transition;
      return () => {
        return h(tag, {
          name: props.disabled ? '' : name,
          css: !props.disabled,
          // mode: props.mode, // TODO: vuejs/vue-next#3104
          ...(props.disabled ? {} : {
            ...functions,
            onLeave: el => {
              if (props.hideOnLeave) {
                el.style.setProperty('display', 'none', 'important');
              } else {
                functions.onLeave?.(el);
              }
            }
          })
        }, slots.default);
      };
    }
  });
}

function ExpandTransitionGenerator (expandedParentClass = '', type = 'y') {
  return {
    onBeforeEnter(el) {
      el._parent = el.parentNode;
      el._initialStyle = {
        transition: el.style.transition,
        overflow: el.style.overflow,
        width: el.style.width,
        height: el.style.height
      };
    },
    onEnter(el) {
      const initialStyle = el._initialStyle;
      if (!initialStyle) return;
      el.style.setProperty('transition', 'none', 'important');
      // Hide overflow to account for collapsed margins in the calculated height
      el.style.overflow = 'hidden';
      const offsetWidth = `${el.offsetWidth}px`;
      const offsetHeight = `${el.offsetHeight}px`;
      if (['x', 'both'].includes(type)) el.style.width = '0';
      if (['y', 'both'].includes(type)) el.style.height = '0';
      void el.offsetHeight; // force reflow

      el.style.transition = initialStyle.transition;
      if (expandedParentClass && el._parent) {
        el._parent.classList.add(expandedParentClass);
      }
      requestAnimationFrame(() => {
        if (['x', 'both'].includes(type)) el.style.width = offsetWidth;
        if (['y', 'both'].includes(type)) el.style.height = offsetHeight;
      });
    },
    onAfterEnter: resetStyles,
    onEnterCancelled: resetStyles,
    onLeave(el) {
      el._initialStyle = {
        transition: '',
        overflow: el.style.overflow,
        width: el.style.width,
        height: el.style.height
      };
      el.style.overflow = 'hidden';
      if (['x', 'both'].includes(type)) el.style.width = `${el.offsetWidth}px`;
      if (['y', 'both'].includes(type)) el.style.height = `${el.offsetHeight}px`;
      void el.offsetHeight; // force reflow

      requestAnimationFrame(() => {
        if (['x', 'both'].includes(type)) el.style.width = '0';
        if (['y', 'both'].includes(type)) el.style.height = '0';
      });
    },
    onAfterLeave,
    onLeaveCancelled: onAfterLeave
  };
  function onAfterLeave(el) {
    if (expandedParentClass && el._parent) {
      el._parent.classList.remove(expandedParentClass);
    }
    resetStyles(el);
  }
  function resetStyles(el) {
    if (!el._initialStyle) return;
    const {
      width: w,
      height: h
    } = el._initialStyle;
    el.style.overflow = el._initialStyle.overflow;
    if (w != null && ['x', 'both'].includes(type)) el.style.width = w;
    if (h != null && ['y', 'both'].includes(type)) el.style.height = h;
    delete el._initialStyle;
  }
}

// Utilities

// Types

const makeVDialogTransitionProps = propsFactory({
  target: [Object, Array]
}, 'v-dialog-transition');
const saved = new WeakMap();
const VDialogTransition = genericComponent()({
  name: 'VDialogTransition',
  props: makeVDialogTransitionProps(),
  setup(props, {
    slots
  }) {
    const functions = {
      onBeforeEnter(el) {
        el.style.pointerEvents = 'none';
        el.style.visibility = 'hidden';
      },
      async onEnter(el, done) {
        await new Promise(resolve => requestAnimationFrame(resolve));
        await new Promise(resolve => requestAnimationFrame(resolve));
        el.style.visibility = '';
        const dimensions = getDimensions(props.target, el);
        const {
          x,
          y,
          sx,
          sy,
          speed
        } = dimensions;
        saved.set(el, dimensions);
        if (PREFERS_REDUCED_MOTION()) {
          animate(el, [{
            opacity: 0
          }, {}], {
            duration: 125 * speed,
            easing: deceleratedEasing
          }).finished.then(() => done());
        } else {
          const animation = animate(el, [{
            transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
            opacity: 0
          }, {}], {
            duration: 225 * speed,
            easing: deceleratedEasing
          });
          getChildren(el)?.forEach(el => {
            animate(el, [{
              opacity: 0
            }, {
              opacity: 0,
              offset: 0.33
            }, {}], {
              duration: 225 * 2 * speed,
              easing: standardEasing
            });
          });
          animation.finished.then(() => done());
        }
      },
      onAfterEnter(el) {
        el.style.removeProperty('pointer-events');
      },
      onBeforeLeave(el) {
        el.style.pointerEvents = 'none';
      },
      async onLeave(el, done) {
        await new Promise(resolve => requestAnimationFrame(resolve));
        let dimensions;
        if (!saved.has(el) || Array.isArray(props.target) || props.target.offsetParent || props.target.getClientRects().length) {
          dimensions = getDimensions(props.target, el);
        } else {
          dimensions = saved.get(el);
        }
        const {
          x,
          y,
          sx,
          sy,
          speed
        } = dimensions;
        if (PREFERS_REDUCED_MOTION()) {
          animate(el, [{}, {
            opacity: 0
          }], {
            duration: 85 * speed,
            easing: acceleratedEasing
          }).finished.then(() => done());
        } else {
          const animation = animate(el, [{}, {
            transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
            opacity: 0
          }], {
            duration: 125 * speed,
            easing: acceleratedEasing
          });
          animation.finished.then(() => done());
          getChildren(el)?.forEach(el => {
            animate(el, [{}, {
              opacity: 0,
              offset: 0.2
            }, {
              opacity: 0
            }], {
              duration: 125 * 2 * speed,
              easing: standardEasing
            });
          });
        }
      },
      onAfterLeave(el) {
        el.style.removeProperty('pointer-events');
      }
    };
    return () => {
      return props.target ? createVNode(Transition, mergeProps({
        "name": "dialog-transition"
      }, functions, {
        "css": false
      }), slots) : createVNode(Transition, {
        "name": "dialog-transition"
      }, slots);
    };
  }
});

/** Animatable children (card, sheet, list) */
function getChildren(el) {
  const els = el.querySelector(':scope > .v-card, :scope > .v-sheet, :scope > .v-list')?.children;
  return els && [...els];
}
function getDimensions(target, el) {
  const targetBox = getTargetBox(target);
  const elBox = nullifyTransforms(el);
  const [originX, originY] = getComputedStyle(el).transformOrigin.split(' ').map(v => parseFloat(v));
  const [anchorSide, anchorOffset] = getComputedStyle(el).getPropertyValue('--v-overlay-anchor-origin').split(' ');
  let offsetX = targetBox.left + targetBox.width / 2;
  if (anchorSide === 'left' || anchorOffset === 'left') {
    offsetX -= targetBox.width / 2;
  } else if (anchorSide === 'right' || anchorOffset === 'right') {
    offsetX += targetBox.width / 2;
  }
  let offsetY = targetBox.top + targetBox.height / 2;
  if (anchorSide === 'top' || anchorOffset === 'top') {
    offsetY -= targetBox.height / 2;
  } else if (anchorSide === 'bottom' || anchorOffset === 'bottom') {
    offsetY += targetBox.height / 2;
  }
  const tsx = targetBox.width / elBox.width;
  const tsy = targetBox.height / elBox.height;
  const maxs = Math.max(1, tsx, tsy);
  const sx = tsx / maxs || 0;
  const sy = tsy / maxs || 0;

  // Animate elements larger than 12% of the screen area up to 1.5x slower
  const asa = elBox.width * elBox.height / (window.innerWidth * window.innerHeight);
  const speed = asa > 0.12 ? Math.min(1.5, (asa - 0.12) * 10 + 1) : 1;
  return {
    x: offsetX - (originX + elBox.left),
    y: offsetY - (originY + elBox.top),
    sx,
    sy,
    speed
  };
}

// Component specific transitions
const VFabTransition = createCssTransition('fab-transition', 'center center', 'out-in');

// Generic transitions
const VDialogBottomTransition = createCssTransition('dialog-bottom-transition');
const VDialogTopTransition = createCssTransition('dialog-top-transition');
const VFadeTransition = createCssTransition('fade-transition');
const VScaleTransition = createCssTransition('scale-transition');
const VScrollXTransition = createCssTransition('scroll-x-transition');
const VScrollXReverseTransition = createCssTransition('scroll-x-reverse-transition');
const VScrollYTransition = createCssTransition('scroll-y-transition');
const VScrollYReverseTransition = createCssTransition('scroll-y-reverse-transition');
const VSlideXTransition = createCssTransition('slide-x-transition');
const VSlideXReverseTransition = createCssTransition('slide-x-reverse-transition');
const VSlideYTransition = createCssTransition('slide-y-transition');
const VSlideYReverseTransition = createCssTransition('slide-y-reverse-transition');

// Javascript transitions
const VExpandTransition = createJavascriptTransition('expand-transition', ExpandTransitionGenerator());
const VExpandXTransition = createJavascriptTransition('expand-x-transition', ExpandTransitionGenerator('', 'x'));
const VExpandBothTransition = createJavascriptTransition('expand-both-transition', ExpandTransitionGenerator('', 'both'));

// Composables

// Types

const makeVDefaultsProviderProps = propsFactory({
  defaults: Object,
  disabled: Boolean,
  reset: [Number, String],
  root: [Boolean, String],
  scoped: Boolean
}, 'VDefaultsProvider');
const VDefaultsProvider = genericComponent(false)({
  name: 'VDefaultsProvider',
  props: makeVDefaultsProviderProps(),
  setup(props, {
    slots
  }) {
    const {
      defaults,
      disabled,
      reset,
      root,
      scoped
    } = toRefs(props);
    provideDefaults(defaults, {
      reset,
      root,
      scoped,
      disabled
    });
    return () => slots.default?.();
  }
});

// Utilities

// Types

// Composables
const makeDimensionProps = propsFactory({
  height: [Number, String],
  maxHeight: [Number, String],
  maxWidth: [Number, String],
  minHeight: [Number, String],
  minWidth: [Number, String],
  width: [Number, String]
}, 'dimension');
function useDimension(props) {
  const dimensionStyles = computed(() => {
    const styles = {};
    const height = convertToUnit(props.height);
    const maxHeight = convertToUnit(props.maxHeight);
    const maxWidth = convertToUnit(props.maxWidth);
    const minHeight = convertToUnit(props.minHeight);
    const minWidth = convertToUnit(props.minWidth);
    const width = convertToUnit(props.width);
    if (height != null) styles.height = height;
    if (maxHeight != null) styles.maxHeight = maxHeight;
    if (maxWidth != null) styles.maxWidth = maxWidth;
    if (minHeight != null) styles.minHeight = minHeight;
    if (minWidth != null) styles.minWidth = minWidth;
    if (width != null) styles.width = width;
    return styles;
  });
  return {
    dimensionStyles
  };
}

function useAspectStyles(props) {
  return {
    aspectStyles: computed(() => {
      const ratio = Number(props.aspectRatio);
      return ratio ? {
        paddingBottom: String(1 / ratio * 100) + '%'
      } : undefined;
    })
  };
}
const makeVResponsiveProps = propsFactory({
  aspectRatio: [String, Number],
  contentClass: null,
  inline: Boolean,
  ...makeComponentProps(),
  ...makeDimensionProps()
}, 'VResponsive');
const VResponsive = genericComponent()({
  name: 'VResponsive',
  props: makeVResponsiveProps(),
  setup(props, {
    slots
  }) {
    const {
      aspectStyles
    } = useAspectStyles(props);
    const {
      dimensionStyles
    } = useDimension(props);
    useRender(() => createElementVNode("div", {
      "class": normalizeClass(['v-responsive', {
        'v-responsive--inline': props.inline
      }, props.class]),
      "style": normalizeStyle([dimensionStyles.value, props.style])
    }, [createElementVNode("div", {
      "class": "v-responsive__sizer",
      "style": normalizeStyle(aspectStyles.value)
    }, null), slots.additional?.(), slots.default && createElementVNode("div", {
      "class": normalizeClass(['v-responsive__content', props.contentClass])
    }, [slots.default()])]));
    return {};
  }
});

// Utilities

// Types

// Composables
function useColor(colors) {
  return destructComputed(() => {
    const {
      class: colorClasses,
      style: colorStyles
    } = computeColor(colors);
    return {
      colorClasses,
      colorStyles
    };
  });
}
function useTextColor(color) {
  const {
    colorClasses: textColorClasses,
    colorStyles: textColorStyles
  } = useColor(() => ({
    text: toValue(color)
  }));
  return {
    textColorClasses,
    textColorStyles
  };
}
function useBackgroundColor(color) {
  const {
    colorClasses: backgroundColorClasses,
    colorStyles: backgroundColorStyles
  } = useColor(() => ({
    background: toValue(color)
  }));
  return {
    backgroundColorClasses,
    backgroundColorStyles
  };
}
function normalizeColors(colors) {
  return {
    text: typeof colors.text === 'string' ? colors.text.replace(/^text-/, '') : colors.text,
    background: typeof colors.background === 'string' ? colors.background.replace(/^bg-/, '') : colors.background
  };
}
function computeColor(colors) {
  const _colors = normalizeColors(toValue(colors));
  const classes = [];
  const styles = {};
  if (_colors.background) {
    if (isCssColor(_colors.background)) {
      styles.backgroundColor = _colors.background;
      if (!_colors.text && isParsableColor(_colors.background)) {
        const backgroundColor = parseColor(_colors.background);
        if (backgroundColor.a == null || backgroundColor.a === 1) {
          classes.push(hasLightForeground(backgroundColor) ? 'v-theme-on-dark' : 'v-theme-on-light');
        }
      }
    } else {
      classes.push(`bg-${_colors.background}`);
    }
  }
  if (_colors.text) {
    if (isCssColor(_colors.text)) {
      styles.color = _colors.text;
      styles.caretColor = _colors.text;
    } else {
      classes.push(`text-${_colors.text}`);
    }
  }
  return {
    class: classes,
    style: styles
  };
}

// Utilities

// Types

const CSS_LENGTH = /^-?\d*\.?\d+([a-z%]{0,4})$/i;
function splitTokens(v) {
  return String(v).trim().split(/\s+/);
}
function isCssLength(token) {
  return token.toLowerCase().match(CSS_LENGTH)?.at(1)?.startsWith('x') === false;
}
function isCssValue(v) {
  return typeof v === 'string' && !!v && (v.includes('(') || splitTokens(v).every(isCssLength));
}

// Composables
const makeRoundedProps = propsFactory({
  rounded: {
    type: [Boolean, Number, String],
    default: undefined
  },
  tile: Boolean
}, 'rounded');
function useRounded(props, name = getCurrentInstanceName()) {
  const roundedClasses = computed(() => {
    const rounded = isRef(props) ? props.value : props.rounded;
    const tile = isRef(props) ? false : props.tile;
    const classes = [];
    if (tile || rounded === false || String(rounded) === '0') {
      classes.push('rounded-0');
    } else if (rounded === true || rounded === '') {
      classes.push(`${name}--rounded`);
    } else if (typeof rounded === 'string' && !isCssValue(rounded)) {
      for (const value of splitTokens(rounded)) {
        classes.push(`rounded-${value}`);
      }
    }
    return classes;
  });
  const roundedStyles = computed(() => {
    const rounded = isRef(props) ? props.value : props.rounded;
    if ((!isCssValue(rounded) || String(rounded) === '0') && !(typeof rounded === 'number' && rounded !== 0)) {
      return {};
    }
    return {
      borderRadius: convertToUnit(rounded)
    };
  });
  return {
    roundedClasses,
    roundedStyles
  };
}

// Utilities

// Types

const makeTransitionProps = propsFactory({
  transition: {
    type: null,
    default: 'fade-transition',
    validator: val => val !== true
  }
}, 'transition');
const MaybeTransition = (props, {
  slots
}) => {
  const {
    transition,
    disabled,
    group,
    target,
    ...rest
  } = props;
  const {
    component = group ? TransitionGroup : Transition,
    ...customProps
  } = isObject(transition) ? transition : {};
  let transitionProps;
  if (isObject(transition)) {
    transitionProps = mergeProps(customProps, onlyDefinedProps({
      disabled,
      group,
      target
    }), rest);
  } else {
    transitionProps = mergeProps({
      name: disabled || !transition ? '' : transition
    }, rest);
  }
  return h(component, transitionProps, slots);
};

// Utilities

// Types

function mounted$5(el, binding) {
  if (!SUPPORTS_INTERSECTION) return;
  const modifiers = binding.modifiers || {};
  const value = binding.value;
  const {
    handler,
    options
  } = typeof value === 'object' ? value : {
    handler: value,
    options: {}
  };
  const observer = new IntersectionObserver((entries = [], observer) => {
    const _observe = el._observe?.[binding.instance.$.uid];
    if (!_observe) return; // Just in case, should never fire

    const isIntersecting = entries.some(entry => entry.isIntersecting);

    // If is not quiet or has already been
    // initted, invoke the user callback
    if (handler && (!modifiers.quiet || _observe.init) && (!modifiers.once || isIntersecting || _observe.init)) {
      handler(isIntersecting, entries, observer);
    }
    if (isIntersecting && modifiers.once) unmounted$5(el, binding);else _observe.init = true;
  }, options);
  el._observe = Object(el._observe);
  el._observe[binding.instance.$.uid] = {
    init: false,
    observer
  };
  observer.observe(el);
}
function unmounted$5(el, binding) {
  const observe = el._observe?.[binding.instance.$.uid];
  if (!observe) return;
  observe.observer.unobserve(el);
  delete el._observe[binding.instance.$.uid];
}
const Intersect = {
  mounted: mounted$5,
  unmounted: unmounted$5,
  updated: (el, binding) => {
    if (el._observe?.[binding.instance.$.uid]) {
      unmounted$5(el, binding);
      mounted$5(el, binding);
    }
  }
};

// Types

// not intended for public use, this is passed in by vuetify-loader

const makeVImgProps = propsFactory({
  absolute: Boolean,
  alt: String,
  cover: Boolean,
  color: String,
  draggable: {
    type: [Boolean, String],
    default: undefined
  },
  eager: Boolean,
  gradient: String,
  imageClass: null,
  lazySrc: String,
  options: {
    type: Object,
    // For more information on types, navigate to:
    // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
    default: () => ({
      root: undefined,
      rootMargin: undefined,
      threshold: undefined
    })
  },
  sizes: String,
  src: {
    type: [String, Object],
    default: ''
  },
  crossorigin: String,
  referrerpolicy: String,
  srcset: String,
  position: String,
  ...makeVResponsiveProps(),
  ...makeComponentProps(),
  ...makeRoundedProps(),
  ...makeTransitionProps()
}, 'VImg');
const VImg = genericComponent()({
  name: 'VImg',
  directives: {
    vIntersect: Intersect
  },
  inheritAttrs: false,
  props: makeVImgProps(),
  emits: {
    loadstart: value => true,
    load: value => true,
    error: value => true
  },
  setup(props, {
    attrs,
    emit,
    slots
  }) {
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const vm = getCurrentInstance('VImg');
    const currentSrc = shallowRef(''); // Set from srcset
    const image = ref();
    const state = shallowRef(props.eager ? 'loading' : 'idle');
    const naturalWidth = shallowRef();
    const naturalHeight = shallowRef();
    let deferredLoadEmit = false;
    const normalisedSrc = computed(() => {
      return props.src && typeof props.src === 'object' ? {
        src: props.src.src,
        srcset: props.srcset || props.src.srcset,
        lazySrc: props.lazySrc || props.src.lazySrc,
        aspect: Number(props.aspectRatio || props.src.aspect || 0)
      } : {
        src: props.src,
        srcset: props.srcset,
        lazySrc: props.lazySrc,
        aspect: Number(props.aspectRatio || 0)
      };
    });
    const aspectRatio = computed(() => {
      return normalisedSrc.value.aspect || naturalWidth.value / naturalHeight.value || 0;
    });
    watch(() => props.src, () => {
      init(state.value !== 'idle');
    });
    watch(aspectRatio, (val, oldVal) => {
      if (!val && oldVal && image.value) {
        pollForSize(image.value);
      }
    });
    watch(image, img => {
      if (!img || state.value === 'idle') return;
      if (!aspectRatio.value) pollForSize(img);
      getSrc(img);
      if (deferredLoadEmit) {
        deferredLoadEmit = false;
        emit('load', img.currentSrc || normalisedSrc.value.src);
      }
    });

    // TODO: getSrc when window width changes

    onBeforeMount(() => init());
    function init(isIntersecting) {
      if (props.eager && isIntersecting) return;
      if (SUPPORTS_INTERSECTION && !isIntersecting && !props.eager) return;
      state.value = 'loading';
      if (normalisedSrc.value.lazySrc) {
        const lazyImg = new Image();
        lazyImg.src = normalisedSrc.value.lazySrc;
        pollForSize(lazyImg, null);
      }
      if (!normalisedSrc.value.src) return;
      nextTick(() => {
        emit('loadstart', image.value?.currentSrc || normalisedSrc.value.src);
        setTimeout(() => {
          if (vm.isUnmounted) return;
          if (image.value?.complete) {
            if (!image.value.naturalWidth) {
              onError();
            }
            if (state.value === 'error') return;
            if (!aspectRatio.value) pollForSize(image.value, null);
            if (state.value === 'loading') onLoad();
          } else if (image.value) {
            if (!aspectRatio.value) pollForSize(image.value);
            getSrc(image.value);
          }
        });
      });
    }
    function onLoad() {
      if (vm.isUnmounted) return;
      if (image.value) {
        getSrc(image.value);
        pollForSize(image.value);
        emit('load', image.value.currentSrc || normalisedSrc.value.src);
      } else {
        deferredLoadEmit = true;
      }
      state.value = 'loaded';
    }
    function onError() {
      if (vm.isUnmounted) return;
      state.value = 'error';
      emit('error', image.value?.currentSrc || normalisedSrc.value.src);
    }
    function getSrc(img) {
      currentSrc.value = img.currentSrc || img.src;
    }
    let timer = -1;
    onBeforeUnmount(() => {
      clearTimeout(timer);
    });
    function pollForSize(img, timeout = 100) {
      const poll = () => {
        clearTimeout(timer);
        if (vm.isUnmounted) return;
        const {
          naturalHeight: imgHeight,
          naturalWidth: imgWidth
        } = img;
        if (imgHeight || imgWidth) {
          naturalWidth.value = imgWidth;
          naturalHeight.value = imgHeight;
        } else if (!img.complete && state.value === 'loading' && timeout != null) {
          timer = window.setTimeout(poll, timeout);
        } else if (img.currentSrc.endsWith('.svg') || img.currentSrc.startsWith('data:image/svg+xml')) {
          naturalWidth.value = 1;
          naturalHeight.value = 1;
        }
      };
      poll();
    }
    const containClasses = toRef(() => ({
      'v-img__img--cover': props.cover,
      'v-img__img--contain': !props.cover
    }));
    const __image = () => {
      if (!normalisedSrc.value.src || state.value === 'idle') return null;
      const img = createElementVNode("img", {
        "class": normalizeClass(['v-img__img', containClasses.value, props.imageClass]),
        "style": {
          objectPosition: props.position
        },
        "crossorigin": props.crossorigin,
        "src": normalisedSrc.value.src,
        "srcset": normalisedSrc.value.srcset,
        "alt": props.alt,
        "referrerpolicy": props.referrerpolicy,
        "draggable": props.draggable,
        "sizes": props.sizes,
        "ref": image,
        "onLoad": onLoad,
        "onError": onError
      }, null);
      const sources = slots.sources?.();
      return createVNode(MaybeTransition, {
        "transition": props.transition,
        "appear": true
      }, {
        default: () => [withDirectives(sources ? createElementVNode("picture", {
          "class": "v-img__picture"
        }, [sources, img]) : img, [[vShow, state.value === 'loaded']])]
      });
    };
    const __preloadImage = () => createVNode(MaybeTransition, {
      "transition": props.transition
    }, {
      default: () => [normalisedSrc.value.lazySrc && state.value !== 'loaded' && createElementVNode("img", {
        "class": normalizeClass(['v-img__img', 'v-img__img--preload', containClasses.value]),
        "style": {
          objectPosition: props.position
        },
        "crossorigin": props.crossorigin,
        "src": normalisedSrc.value.lazySrc,
        "alt": props.alt,
        "referrerpolicy": props.referrerpolicy,
        "draggable": props.draggable
      }, null)]
    });
    const __placeholder = () => {
      if (!slots.placeholder) return null;
      return createVNode(MaybeTransition, {
        "transition": props.transition,
        "appear": true
      }, {
        default: () => [(state.value === 'loading' || state.value === 'error' && !slots.error) && createElementVNode("div", {
          "class": "v-img__placeholder"
        }, [slots.placeholder()])]
      });
    };
    const __error = () => {
      if (!slots.error) return null;
      return createVNode(MaybeTransition, {
        "transition": props.transition,
        "appear": true
      }, {
        default: () => [state.value === 'error' && createElementVNode("div", {
          "class": "v-img__error"
        }, [slots.error()])]
      });
    };
    const __gradient = () => {
      if (!props.gradient) return null;
      return createElementVNode("div", {
        "class": "v-img__gradient",
        "style": {
          backgroundImage: `linear-gradient(${props.gradient})`
        }
      }, null);
    };
    const isBooted = shallowRef(false);
    {
      const stop = watch(aspectRatio, val => {
        if (val) {
          // Doesn't work with nextTick, idk why
          requestAnimationFrame(() => {
            requestAnimationFrame(() => {
              isBooted.value = true;
            });
          });
          stop();
        }
      });
    }
    useRender(() => {
      const responsiveProps = VResponsive.filterProps(props);
      const [rootAttrs, imageAttrs] = filterInputAttrs(attrs);
      return withDirectives(createVNode(VResponsive, mergeProps({
        "class": ['v-img', {
          'v-img--absolute': props.absolute,
          'v-img--booting': !isBooted.value,
          'v-img--fit-content': props.width === 'fit-content'
        }, backgroundColorClasses.value, roundedClasses.value, props.class],
        "style": [{
          width: convertToUnit(props.width === 'auto' ? naturalWidth.value : props.width)
        }, backgroundColorStyles.value, roundedStyles.value, props.style]
      }, responsiveProps, rootAttrs, {
        "aspectRatio": aspectRatio.value,
        "aria-label": props.alt || undefined,
        "role": props.alt ? 'img' : undefined
      }), {
        additional: () => createElementVNode(Fragment, null, [createVNode(__image, imageAttrs, null), createVNode(__preloadImage, null, null), createVNode(__gradient, null, null), createVNode(__placeholder, null, null), createVNode(__error, null, null)]),
        default: slots.default
      }), [[Intersect, {
        handler: init,
        options: props.options
      }, null, {
        once: true
      }]]);
    });
    return {
      currentSrc,
      image,
      state,
      naturalWidth,
      naturalHeight
    };
  }
});

// Utilities

// Types

// Composables
const makeBorderProps = propsFactory({
  border: [Boolean, Number, String]
}, 'border');
function useBorder(props, name = getCurrentInstanceName()) {
  const borderClasses = computed(() => {
    const border = props.border;
    if (border === true || border === '') {
      return `${name}--border`;
    } else if (typeof border === 'string' || border === 0) {
      return String(border).split(' ').map(v => `border-${v}`);
    }
    return [];
  });
  return {
    borderClasses
  };
}

// Utilities

// Types

// Composables
const makeElevationProps = propsFactory({
  elevation: {
    type: [Number, String],
    // no limit to allow both 0-6 (MD3) and legacy 0-24 (MD2)
    validator: value => parseInt(value) >= 0
  },
  hoverElevation: {
    type: [Number, String],
    validator: value => parseInt(value) >= 0
  }
}, 'elevation');
function useElevation(props) {
  const elevationClasses = toRef(() => {
    const elevation = isRef(props) ? props.value : props.elevation;
    const hoverElevation = isRef(props) ? null : props.hoverElevation;
    return [...(elevation == null ? [] : [`elevation-${parseInt(elevation)}`]), ...(hoverElevation == null ? [] : [`hover-elevation-${parseInt(hoverElevation)}`])];
  });
  return {
    elevationClasses
  };
}

// Composables

// Types

const oppositeMap = {
  center: 'center',
  top: 'bottom',
  bottom: 'top',
  left: 'right',
  right: 'left'
};
const makeLocationProps = propsFactory({
  location: String
}, 'location');
function useLocation(props, opposite = false, offset) {
  const {
    isRtl
  } = useRtl();
  const locationStyles = computed(() => {
    if (!props.location) return {};
    const {
      side,
      align
    } = parseAnchor(props.location.split(' ').length > 1 ? props.location : `${props.location} center`, isRtl.value);
    function getOffset(side) {
      return offset ? offset(side) : 0;
    }
    const styles = {};
    if (side !== 'center') {
      if (opposite) styles[oppositeMap[side]] = `calc(100% - ${getOffset(side)}px)`;else styles[side] = 0;
    }
    if (align !== 'center') {
      if (opposite) styles[oppositeMap[align]] = `calc(100% - ${getOffset(align)}px)`;else styles[align] = 0;
    } else {
      if (side === 'center') styles.top = styles.left = '50%';else {
        styles[{
          top: 'left',
          bottom: 'left',
          left: 'top',
          right: 'top'
        }[side]] = '50%';
      }
      styles.transform = {
        top: 'translateX(-50%)',
        bottom: 'translateX(-50%)',
        left: 'translateY(-50%)',
        right: 'translateY(-50%)',
        center: 'translate(-50%, -50%)'
      }[side];
    }
    return styles;
  });
  return {
    locationStyles
  };
}

// Types

const allowedDensities$1 = [null, 'prominent', 'default', 'comfortable', 'compact'];
const makeVToolbarProps = propsFactory({
  absolute: Boolean,
  collapse: Boolean,
  collapsePosition: {
    type: String,
    default: 'start'
  },
  color: String,
  density: {
    type: String,
    default: 'default',
    validator: v => allowedDensities$1.includes(v)
  },
  extended: {
    type: Boolean,
    default: null
  },
  extensionHeight: {
    type: [Number, String],
    default: 48
  },
  flat: Boolean,
  floating: Boolean,
  height: {
    type: [Number, String],
    default: 64
  },
  image: String,
  title: String,
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeElevationProps(),
  ...makeLocationProps(),
  ...makeRoundedProps(),
  ...makeTagProps({
    tag: 'header'
  }),
  ...makeThemeProps()
}, 'VToolbar');
const VToolbar = genericComponent()({
  name: 'VToolbar',
  props: makeVToolbarProps(),
  setup(props, {
    slots
  }) {
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      borderClasses
    } = useBorder(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      locationStyles
    } = useLocation(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      themeClasses
    } = provideTheme(props);
    const {
      rtlClasses
    } = useRtl();
    const isExtended = shallowRef(props.extended === null ? !!slots.extension?.() : props.extended);
    const contentHeight = computed(() => parseInt(Number(props.height) + (props.density === 'prominent' ? Number(props.height) : 0) - (props.density === 'comfortable' ? 8 : 0) - (props.density === 'compact' ? 16 : 0), 10));
    const extensionHeight = computed(() => isExtended.value ? parseInt(Number(props.extensionHeight) + (props.density === 'prominent' ? Number(props.extensionHeight) : 0) - (props.density === 'comfortable' ? 4 : 0) - (props.density === 'compact' ? 8 : 0), 10) : 0);
    provideDefaults({
      VBtn: {
        variant: 'text'
      }
    });
    useRender(() => {
      const hasTitle = !!(props.title || slots.title);
      const hasImage = !!(slots.image || props.image);
      const extension = slots.extension?.();
      isExtended.value = props.extended === null ? !!extension : props.extended;
      return createVNode(props.tag, {
        "class": normalizeClass(['v-toolbar', `v-toolbar--collapse-${props.collapsePosition}`, {
          'v-toolbar--absolute': props.absolute,
          'v-toolbar--collapse': props.collapse,
          'v-toolbar--flat': props.flat,
          'v-toolbar--floating': props.floating,
          [`v-toolbar--density-${props.density}`]: true
        }, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, themeClasses.value, rtlClasses.value, props.class]),
        "style": normalizeStyle([backgroundColorStyles.value, locationStyles.value, roundedStyles.value, props.style])
      }, {
        default: () => [hasImage && createElementVNode("div", {
          "key": "image",
          "class": "v-toolbar__image"
        }, [!slots.image ? createVNode(VImg, {
          "key": "image-img",
          "cover": true,
          "src": props.image
        }, null) : createVNode(VDefaultsProvider, {
          "key": "image-defaults",
          "disabled": !props.image,
          "defaults": {
            VImg: {
              cover: true,
              src: props.image
            }
          }
        }, slots.image)]), createVNode(VDefaultsProvider, {
          "defaults": {
            VTabs: {
              height: convertToUnit(contentHeight.value)
            }
          }
        }, {
          default: () => [createElementVNode("div", {
            "class": "v-toolbar__content",
            "style": {
              height: convertToUnit(contentHeight.value)
            }
          }, [slots.prepend && createElementVNode("div", {
            "class": "v-toolbar__prepend"
          }, [slots.prepend?.()]), hasTitle && createVNode(VToolbarTitle, {
            "key": "title",
            "text": props.title
          }, {
            text: slots.title
          }), slots.default?.(), slots.append && createElementVNode("div", {
            "class": "v-toolbar__append"
          }, [slots.append?.()])])]
        }), createVNode(VDefaultsProvider, {
          "defaults": {
            VTabs: {
              height: convertToUnit(extensionHeight.value)
            }
          }
        }, {
          default: () => [createVNode(VExpandTransition, null, {
            default: () => [isExtended.value && createElementVNode("div", {
              "class": "v-toolbar__extension",
              "style": {
                height: convertToUnit(extensionHeight.value)
              }
            }, [extension])]
          })]
        })]
      });
    });
    return {
      contentHeight,
      extensionHeight
    };
  }
});

// Utilities

// Types

// Composables
const makeScrollProps = propsFactory({
  scrollTarget: {
    type: String
  },
  scrollThreshold: {
    type: [String, Number],
    default: 300
  }
}, 'scroll');
function useScroll(props, args = {}) {
  const {
    canScroll,
    layoutSize
  } = args;
  let previousScroll = 0;
  let previousScrollHeight = 0;
  const target = ref(null);
  const currentScroll = shallowRef(0);
  const savedScroll = shallowRef(0);
  const currentThreshold = shallowRef(0);
  const isScrollActive = shallowRef(false);
  const isScrollingUp = shallowRef(false);
  const isAtBottom = shallowRef(false);
  const reachedBottomWhileScrollingDown = shallowRef(false);
  const hasEnoughScrollableSpace = shallowRef(true);
  const scrollThreshold = computed(() => {
    return Number(props.scrollThreshold);
  });

  /**
   * 1: at top
   * 0: at threshold
   */
  const scrollRatio = computed(() => {
    return clamp((scrollThreshold.value - currentScroll.value) / scrollThreshold.value || 0);
  });
  function getScrollMetrics(targetEl) {
    const clientHeight = 'window' in targetEl ? window.innerHeight : targetEl.clientHeight;
    const scrollHeight = 'window' in targetEl ? document.documentElement.scrollHeight : targetEl.scrollHeight;
    return {
      clientHeight,
      scrollHeight
    };
  }
  function checkScrollableSpace() {
    const targetEl = target.value;
    if (!targetEl) return;
    const {
      clientHeight,
      scrollHeight
    } = getScrollMetrics(targetEl);
    const maxScrollableDistance = scrollHeight - clientHeight;

    // When the scroll-hide element (like AppBar) hides, it causes the page to grow
    // We need extra scrollable space beyond the threshold to prevent bouncing
    // Add the element's height to the required minimum distance
    const elementHeight = layoutSize?.value || 0;
    const minRequiredDistance = scrollThreshold.value + elementHeight;

    // Only enable scroll-hide if there's enough scrollable space
    hasEnoughScrollableSpace.value = maxScrollableDistance > minRequiredDistance;
  }
  function onResize() {
    checkScrollableSpace();
  }
  function onScroll() {
    const targetEl = target.value;
    if (!targetEl || canScroll && !canScroll.value) return;
    previousScroll = currentScroll.value;
    currentScroll.value = 'window' in targetEl ? targetEl.pageYOffset : targetEl.scrollTop;
    const currentScrollHeight = targetEl instanceof Window ? document.documentElement.scrollHeight : targetEl.scrollHeight;
    if (previousScrollHeight !== currentScrollHeight) {
      // If page is growing (content loading), recalculate scrollable space
      // If page is shrinking (likely due to navbar animation), don't recalculate
      if (currentScrollHeight > previousScrollHeight) {
        checkScrollableSpace();
      }
      previousScrollHeight = currentScrollHeight;
    }
    isScrollingUp.value = currentScroll.value < previousScroll;
    currentThreshold.value = Math.abs(currentScroll.value - scrollThreshold.value);

    // Detect if at bottom of page
    const {
      clientHeight,
      scrollHeight
    } = getScrollMetrics(targetEl);
    const atBottom = currentScroll.value + clientHeight >= scrollHeight - 5;

    // Track when bottom is reached during downward scroll
    // Only set flag if ALL conditions are met:
    // 1. Scrolled past threshold (navbar is hiding)
    // 2. Page has enough scrollable space for scroll-hide
    // This prevents activation on short pages or edge cases
    if (!isScrollingUp.value && atBottom && currentScroll.value >= scrollThreshold.value && hasEnoughScrollableSpace.value) {
      reachedBottomWhileScrollingDown.value = true;
    }

    // Reset the flag when:
    // 1. Scrolling up away from bottom (with small tolerance for touchpad/momentum scrolling)
    // 2. Scroll position jumped significantly (e.g., navigation, scroll restoration)
    // 3. Scroll is at the very top (page navigation resets to top)
    const scrollJumped = Math.abs(currentScroll.value - previousScroll) > 100;
    const atTop = currentScroll.value <= 5;
    const scrolledUpSignificantly = isScrollingUp.value && previousScroll - currentScroll.value > 1;
    if (scrolledUpSignificantly && !atBottom || scrollJumped && currentScroll.value < scrollThreshold.value || atTop) {
      reachedBottomWhileScrollingDown.value = false;
    }

    // Update state
    isAtBottom.value = atBottom;
  }
  watch(isScrollingUp, () => {
    savedScroll.value = savedScroll.value || currentScroll.value;
  });
  watch(isScrollActive, () => {
    savedScroll.value = 0;
  });
  onMounted(() => {
    watch(() => props.scrollTarget, scrollTarget => {
      const newTarget = scrollTarget ? document.querySelector(scrollTarget) : window;
      if (!newTarget) {
        consoleWarn(`Unable to locate element with identifier ${scrollTarget}`);
        return;
      }
      if (newTarget === target.value) return;
      target.value?.removeEventListener('scroll', onScroll);
      target.value = newTarget;
      target.value.addEventListener('scroll', onScroll, {
        passive: true
      });

      // Check scrollable space when target is set
      Promise.resolve().then(() => {
        checkScrollableSpace();
      });
    }, {
      immediate: true
    });

    // Listen to window resize to recalculate scrollable space
    window.addEventListener('resize', onResize, {
      passive: true
    });
  });
  onBeforeUnmount(() => {
    target.value?.removeEventListener('scroll', onScroll);
    window.removeEventListener('resize', onResize);
  });

  // Do we need this? If yes - seems that
  // there's no need to expose onScroll
  canScroll && watch(canScroll, onScroll, {
    immediate: true
  });
  return {
    scrollThreshold,
    currentScroll,
    currentThreshold,
    isScrollActive,
    scrollRatio,
    // required only for testing
    // probably can be removed
    // later (2 chars chlng)
    isScrollingUp,
    savedScroll,
    isAtBottom,
    reachedBottomWhileScrollingDown,
    hasEnoughScrollableSpace
  };
}

// Utilities

// Composables
function useSsrBoot() {
  const isBooted = shallowRef(false);
  onMounted(() => {
    window.requestAnimationFrame(() => {
      isBooted.value = true;
    });
  });
  const ssrBootStyles = toRef(() => !isBooted.value ? {
    transition: 'none !important'
  } : undefined);
  return {
    ssrBootStyles,
    isBooted: readonly(isBooted)
  };
}

// Types

const makeVAppBarProps = propsFactory({
  scrollBehavior: String,
  modelValue: {
    type: Boolean,
    default: true
  },
  location: {
    type: String,
    default: 'top',
    validator: value => ['top', 'bottom'].includes(value)
  },
  ...omit(makeVToolbarProps(), ['location']),
  ...makeLayoutItemProps(),
  ...makeScrollProps(),
  height: {
    type: [Number, String],
    default: 64
  }
}, 'VAppBar');
const VAppBar = genericComponent()({
  name: 'VAppBar',
  props: makeVAppBarProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const vToolbarRef = ref();
    const isActive = useProxiedModel(props, 'modelValue');
    const scrollBehavior = computed(() => {
      const behavior = new Set(props.scrollBehavior?.split(' ') ?? []);
      return {
        hide: behavior.has('hide'),
        fullyHide: behavior.has('fully-hide'),
        inverted: behavior.has('inverted'),
        collapse: behavior.has('collapse'),
        elevate: behavior.has('elevate'),
        fadeImage: behavior.has('fade-image')
        // shrink: behavior.has('shrink'),
      };
    });
    const canScroll = computed(() => {
      const behavior = scrollBehavior.value;
      return behavior.hide || behavior.fullyHide || behavior.inverted || behavior.collapse || behavior.elevate || behavior.fadeImage ||
      // behavior.shrink ||
      !isActive.value;
    });
    const appBarHeight = computed(() => {
      const height = vToolbarRef.value?.contentHeight ?? 0;
      const extensionHeight = vToolbarRef.value?.extensionHeight ?? 0;
      return height + extensionHeight;
    });
    const {
      currentScroll,
      scrollThreshold,
      isScrollingUp,
      scrollRatio,
      isAtBottom,
      reachedBottomWhileScrollingDown,
      hasEnoughScrollableSpace
    } = useScroll(props, {
      canScroll,
      layoutSize: appBarHeight
    });
    const canHide = toRef(() => scrollBehavior.value.hide || scrollBehavior.value.fullyHide);
    const isCollapsed = computed(() => props.collapse || scrollBehavior.value.collapse && (scrollBehavior.value.inverted ? scrollRatio.value > 0 : scrollRatio.value === 0));
    const isFlat = computed(() => props.flat || scrollBehavior.value.fullyHide && !isActive.value || scrollBehavior.value.elevate && (scrollBehavior.value.inverted ? currentScroll.value > 0 : currentScroll.value === 0));
    const opacity = computed(() => scrollBehavior.value.fadeImage ? scrollBehavior.value.inverted ? 1 - scrollRatio.value : scrollRatio.value : undefined);
    const height = computed(() => {
      if (scrollBehavior.value.hide && scrollBehavior.value.inverted) return 0;
      const height = vToolbarRef.value?.contentHeight ?? 0;
      const extensionHeight = vToolbarRef.value?.extensionHeight ?? 0;
      if (!canHide.value) return height + extensionHeight;
      return currentScroll.value < scrollThreshold.value || scrollBehavior.value.fullyHide ? height + extensionHeight : height;
    });
    useToggleScope(() => !!props.scrollBehavior, () => {
      watchEffect(() => {
        if (!canHide.value) {
          isActive.value = true;
          return;
        }
        if (scrollBehavior.value.inverted) {
          isActive.value = currentScroll.value > scrollThreshold.value;
          return;
        }

        // If there's not enough scrollable space, don't apply scroll-hide behavior at all
        // This prevents flickering/bouncing animations on short pages
        if (!hasEnoughScrollableSpace.value) {
          isActive.value = true;
          return;
        }

        // Prevent navbar from showing when we reached bottom while scrolling down
        // This handles the case where scroll momentum causes to hit bottom during hide transition
        if (reachedBottomWhileScrollingDown.value) {
          isActive.value = false;
          return;
        }

        // Normal behavior: show when scrolling up (and not at bottom) or above threshold
        isActive.value = isScrollingUp.value && !isAtBottom.value || currentScroll.value < scrollThreshold.value;
      });
    });
    const {
      ssrBootStyles
    } = useSsrBoot();
    const {
      layoutItemStyles
    } = useLayoutItem({
      id: props.name,
      order: computed(() => parseInt(props.order, 10)),
      position: toRef(() => props.location),
      layoutSize: height,
      elementSize: shallowRef(undefined),
      active: isActive,
      absolute: toRef(() => props.absolute)
    });
    useRender(() => {
      const toolbarProps = omit(VToolbar.filterProps(props), ['location']);
      return createVNode(VToolbar, mergeProps({
        "ref": vToolbarRef,
        "class": ['v-app-bar', {
          'v-app-bar--bottom': props.location === 'bottom'
        }, props.class],
        "style": [{
          ...layoutItemStyles.value,
          '--v-toolbar-image-opacity': opacity.value,
          height: undefined,
          ...ssrBootStyles.value
        }, props.style]
      }, toolbarProps, {
        "collapse": isCollapsed.value,
        "flat": isFlat.value
      }), slots);
    });
    return {};
  }
});

// Utilities

// Types

const allowedDensities = [null, 'default', 'comfortable', 'compact'];

// typeof allowedDensities[number] evaluates to any
// when generating api types for whatever reason.

// Composables
const makeDensityProps = propsFactory({
  density: {
    type: String,
    default: 'default',
    validator: v => allowedDensities.includes(v)
  }
}, 'density');
function useDensity(props, name = getCurrentInstanceName()) {
  const densityClasses = toRef(() => {
    return `${name}--density-${props.density}`;
  });
  return {
    densityClasses
  };
}

// Types

const allowedVariants$5 = ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain'];
function genOverlays(isClickable, name) {
  return createElementVNode(Fragment, null, [isClickable && createElementVNode("span", {
    "key": "overlay",
    "class": normalizeClass(`${name}__overlay`)
  }, null), createElementVNode("span", {
    "key": "underlay",
    "class": normalizeClass(`${name}__underlay`)
  }, null)]);
}
const makeVariantProps = propsFactory({
  color: String,
  variant: {
    type: String,
    default: 'elevated',
    validator: v => allowedVariants$5.includes(v)
  }
}, 'variant');
function useVariant(props, name = getCurrentInstanceName()) {
  const variantClasses = toRef(() => {
    const {
      variant
    } = toValue(props);
    return `${name}--variant-${variant}`;
  });
  const {
    colorClasses,
    colorStyles
  } = useColor(() => {
    const {
      variant,
      color
    } = toValue(props);
    return {
      [['elevated', 'flat'].includes(variant) ? 'background' : 'text']: color
    };
  });
  return {
    colorClasses,
    colorStyles,
    variantClasses
  };
}

// Types

const makeVBtnGroupProps = propsFactory({
  baseColor: String,
  divided: Boolean,
  direction: {
    type: String,
    default: 'horizontal'
  },
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeElevationProps(),
  ...makeRoundedProps(),
  ...makeTagProps(),
  ...makeThemeProps(),
  ...makeVariantProps()
}, 'VBtnGroup');
const VBtnGroup = genericComponent()({
  name: 'VBtnGroup',
  props: makeVBtnGroupProps(),
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      densityClasses
    } = useDensity(props);
    const {
      borderClasses
    } = useBorder(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    provideDefaults({
      VBtn: {
        height: toRef(() => props.direction === 'horizontal' ? 'auto' : null),
        baseColor: toRef(() => props.baseColor),
        color: toRef(() => props.color),
        density: toRef(() => props.density),
        flat: true,
        variant: toRef(() => props.variant)
      }
    });
    useRender(() => {
      return createVNode(props.tag, {
        "class": normalizeClass(['v-btn-group', `v-btn-group--${props.direction}`, {
          'v-btn-group--divided': props.divided
        }, themeClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class]),
        "style": normalizeStyle([roundedStyles.value, props.style])
      }, slots);
    });
  }
});

// Composables

// Types

const makeGroupProps = propsFactory({
  modelValue: {
    type: null,
    default: undefined
  },
  multiple: Boolean,
  mandatory: [Boolean, String],
  max: Number,
  selectedClass: String,
  disabled: Boolean
}, 'group');
const makeGroupItemProps = propsFactory({
  value: null,
  disabled: Boolean,
  selectedClass: String
}, 'group-item');

// Composables

function useGroupItem(props, injectKey, required = true) {
  const vm = getCurrentInstance('useGroupItem');
  if (!vm) {
    throw new Error('[Vuetify] useGroupItem composable must be used inside a component setup function');
  }
  const id = useId();
  provide(Symbol.for(`${injectKey.description}:id`), id);
  const group = inject$1(injectKey, null);
  if (!group) {
    if (!required) return group;
    throw new Error(`[Vuetify] Could not find useGroup injection with symbol ${injectKey.description}`);
  }
  const value = toRef(() => props.value);
  const disabled = computed(() => !!(group.disabled.value || props.disabled));
  function register() {
    group?.register({
      id,
      value,
      disabled
    }, vm);
  }
  function unregister() {
    group?.unregister(id);
  }
  register();
  onBeforeUnmount(() => unregister());
  const isSelected = computed(() => {
    return group.isSelected(id);
  });
  const isFirst = computed(() => {
    return group.items.value[0].id === id;
  });
  const isLast = computed(() => {
    return group.items.value[group.items.value.length - 1].id === id;
  });
  const selectedClass = computed(() => isSelected.value && [group.selectedClass.value, props.selectedClass]);
  watch(isSelected, value => {
    vm.emit('group:selected', {
      value
    });
  }, {
    flush: 'sync'
  });
  return {
    id,
    isSelected,
    isFirst,
    isLast,
    toggle: () => group.select(id, !isSelected.value),
    select: value => group.select(id, value),
    selectedClass,
    value,
    disabled,
    group,
    register,
    unregister
  };
}
function useGroup(props, injectKey) {
  let isUnmounted = false;
  const items = reactive([]);
  const selected = useProxiedModel(props, 'modelValue', [], v => {
    if (v === undefined) return [];
    return getIds(items, v === null ? [null] : wrapInArray(v));
  }, v => {
    const arr = getValues(items, v);
    return props.multiple ? arr : arr[0];
  });
  const groupVm = getCurrentInstance('useGroup');
  function register(item, vm) {
    // Is there a better way to fix this typing?
    const unwrapped = item;
    const key = Symbol.for(`${injectKey.description}:id`);
    const children = findChildrenWithProvide(key, groupVm?.vnode);
    const index = children.indexOf(vm);
    if (unref(unwrapped.value) === undefined) {
      unwrapped.value = index;
      unwrapped.useIndexAsValue = true;
    }
    if (index > -1) {
      items.splice(index, 0, unwrapped);
    } else {
      items.push(unwrapped);
    }
  }
  function unregister(id) {
    if (isUnmounted) return;

    // TODO: re-evaluate this line's importance in the future
    // should we only modify the model if mandatory is set.
    // selected.value = selected.value.filter(v => v !== id)

    forceMandatoryValue();
    const index = items.findIndex(item => item.id === id);
    items.splice(index, 1);
  }

  // If mandatory and nothing is selected, then select first non-disabled item
  function forceMandatoryValue() {
    const item = items.find(item => !item.disabled);
    if (item && props.mandatory === 'force' && !selected.value.length) {
      selected.value = [item.id];
    }
  }
  onMounted(() => {
    forceMandatoryValue();
  });
  onBeforeUnmount(() => {
    isUnmounted = true;
  });
  onUpdated(() => {
    // #19655 update the items that use the index as the value.
    for (let i = 0; i < items.length; i++) {
      if (items[i].useIndexAsValue) {
        items[i].value = i;
      }
    }
  });
  function select(id, value) {
    const item = items.find(item => item.id === id);
    if (value && item?.disabled) return;
    if (props.multiple) {
      const internalValue = selected.value.slice();
      const index = internalValue.findIndex(v => v === id);
      const isSelected = ~index;
      value = value ?? !isSelected;

      // We can't remove value if group is
      // mandatory, value already exists,
      // and it is the only value
      if (isSelected && props.mandatory && internalValue.length <= 1) return;

      // We can't add value if it would
      // cause max limit to be exceeded
      if (!isSelected && props.max != null && internalValue.length + 1 > props.max) return;
      if (index < 0 && value) internalValue.push(id);else if (index >= 0 && !value) internalValue.splice(index, 1);
      selected.value = internalValue;
    } else {
      const isSelected = selected.value.includes(id);
      if (props.mandatory && isSelected) return;
      if (!isSelected && !value) return;
      selected.value = value ?? !isSelected ? [id] : [];
    }
  }
  function step(offset) {
    // getting an offset from selected value obviously won't work with multiple values
    if (props.multiple) consoleWarn('This method is not supported when using "multiple" prop');
    if (!selected.value.length) {
      const item = items.find(item => !item.disabled);
      item && (selected.value = [item.id]);
    } else {
      const currentId = selected.value[0];
      const currentIndex = items.findIndex(i => i.id === currentId);
      let newIndex = (currentIndex + offset) % items.length;
      let newItem = items[newIndex];
      while (newItem.disabled && newIndex !== currentIndex) {
        newIndex = (newIndex + offset) % items.length;
        newItem = items[newIndex];
      }
      if (newItem.disabled) return;
      selected.value = [items[newIndex].id];
    }
  }
  const state = {
    register,
    unregister,
    selected,
    select,
    disabled: toRef(() => props.disabled),
    prev: () => step(items.length - 1),
    next: () => step(1),
    isSelected: id => selected.value.includes(id),
    selectedClass: toRef(() => props.selectedClass),
    items: toRef(() => items),
    getItemIndex: value => getItemIndex(items, value)
  };
  provide(injectKey, state);
  return state;
}
function getItemIndex(items, value) {
  const ids = getIds(items, [value]);
  if (!ids.length) return -1;
  return items.findIndex(item => item.id === ids[0]);
}
function getIds(items, modelValue) {
  const ids = [];
  modelValue.forEach(value => {
    const item = items.find(item => deepEqual(value, item.value));
    const itemByIndex = items[value];
    if (item?.value !== undefined) {
      ids.push(item.id);
    } else if (itemByIndex?.useIndexAsValue) {
      ids.push(itemByIndex.id);
    }
  });
  return ids;
}
function getValues(items, ids) {
  const values = [];
  ids.forEach(id => {
    const itemIndex = items.findIndex(item => item.id === id);
    if (~itemIndex) {
      const item = items[itemIndex];
      values.push(item.value !== undefined ? item.value : itemIndex);
    }
  });
  return values;
}

// Types

const VBtnToggleSymbol = Symbol.for('vuetify:v-btn-toggle');
const makeVBtnToggleProps = propsFactory({
  ...makeVBtnGroupProps(),
  ...makeGroupProps()
}, 'VBtnToggle');
const VBtnToggle = genericComponent()({
  name: 'VBtnToggle',
  props: makeVBtnToggleProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const {
      isSelected,
      next,
      prev,
      select,
      selected
    } = useGroup(props, VBtnToggleSymbol);
    useRender(() => {
      const btnGroupProps = VBtnGroup.filterProps(props);
      return createVNode(VBtnGroup, mergeProps({
        "class": ['v-btn-toggle', {
          'v-btn-toggle--has-color': !!props.color
        }, props.class]
      }, btnGroupProps, {
        "style": props.style
      }), {
        default: () => [slots.default?.({
          isSelected,
          next,
          prev,
          select,
          selected
        })]
      });
    });
    return {
      next,
      prev,
      select
    };
  }
});

// Utilities

// Types

const IconValue = [String, Function, Object, Array];
const IconSymbol = Symbol.for('vuetify:icons');
const makeIconProps = propsFactory({
  icon: {
    type: IconValue
  },
  // Could not remove this and use makeTagProps, types complained because it is not required
  tag: {
    type: [String, Object, Function],
    required: true
  }
}, 'icon');
const VComponentIcon = genericComponent()({
  name: 'VComponentIcon',
  props: makeIconProps(),
  setup(props, {
    slots
  }) {
    return () => {
      const Icon = props.icon;
      return createVNode(props.tag, null, {
        default: () => [props.icon ? createVNode(Icon, null, null) : slots.default?.()]
      });
    };
  }
});
const VSvgIcon = defineComponent({
  name: 'VSvgIcon',
  inheritAttrs: false,
  props: makeIconProps(),
  setup(props, {
    attrs
  }) {
    return () => {
      return createVNode(props.tag, mergeProps(attrs, {
        "style": null
      }), {
        default: () => [createElementVNode("svg", {
          "class": "v-icon__svg",
          "xmlns": "http://www.w3.org/2000/svg",
          "viewBox": "0 0 24 24",
          "role": "img",
          "aria-hidden": "true"
        }, [Array.isArray(props.icon) ? props.icon.map(path => Array.isArray(path) ? createElementVNode("path", {
          "d": path[0],
          "fill-opacity": path[1]
        }, null) : createElementVNode("path", {
          "d": path
        }, null)) : createElementVNode("path", {
          "d": props.icon
        }, null)])]
      });
    };
  }
});
const VLigatureIcon = defineComponent({
  name: 'VLigatureIcon',
  props: makeIconProps(),
  setup(props) {
    return () => {
      return createVNode(props.tag, null, {
        default: () => [props.icon]
      });
    };
  }
});
const VClassIcon = defineComponent({
  name: 'VClassIcon',
  props: makeIconProps(),
  setup(props) {
    return () => {
      return createVNode(props.tag, {
        "class": normalizeClass(props.icon)
      }, null);
    };
  }
});
const useIcon = props => {
  const icons = inject$1(IconSymbol);
  if (!icons) throw new Error('Missing Vuetify Icons provide!');
  const iconData = computed(() => {
    const iconAlias = toValue(props);
    if (!iconAlias) return {
      component: VComponentIcon
    };
    let icon = iconAlias;
    if (typeof icon === 'string') {
      icon = icon.trim();
      if (icon.startsWith('$')) {
        icon = icons.aliases?.[icon.slice(1)];
      }
    }
    if (!icon) consoleWarn(`Could not find aliased icon "${iconAlias}"`);
    if (Array.isArray(icon)) {
      return {
        component: VSvgIcon,
        icon
      };
    } else if (typeof icon !== 'string') {
      return {
        component: VComponentIcon,
        icon
      };
    }
    const iconSetName = Object.keys(icons.sets).find(setName => typeof icon === 'string' && icon.startsWith(`${setName}:`));
    const iconName = iconSetName ? icon.slice(iconSetName.length + 1) : icon;
    const iconSet = icons.sets[iconSetName ?? icons.defaultSet];
    return {
      component: iconSet.component,
      icon: iconName
    };
  });
  return {
    iconData
  };
};

// Utilities

// Types
const predefinedSizes$1 = ['x-small', 'small', 'default', 'large', 'x-large'];
// Composables
const makeSizeProps = propsFactory({
  size: {
    type: [String, Number],
    default: 'default'
  }
}, 'size');
function useSize(props, name = getCurrentInstanceName()) {
  return destructComputed(() => {
    const size = props.size;
    let sizeClasses;
    let sizeStyles;
    if (includes(predefinedSizes$1, size)) {
      sizeClasses = `${name}--size-${size}`;
    } else if (size) {
      sizeStyles = {
        width: convertToUnit(size),
        height: convertToUnit(size)
      };
    }
    return {
      sizeClasses,
      sizeStyles
    };
  });
}

const makeVIconProps = propsFactory({
  color: String,
  disabled: Boolean,
  start: Boolean,
  end: Boolean,
  icon: IconValue,
  opacity: [String, Number],
  ...makeComponentProps(),
  ...makeSizeProps(),
  ...makeTagProps({
    tag: 'i'
  }),
  ...makeThemeProps()
}, 'VIcon');
const VIcon = genericComponent()({
  name: 'VIcon',
  props: makeVIconProps(),
  setup(props, {
    attrs,
    slots
  }) {
    const slotIcon = shallowRef();
    const {
      themeClasses
    } = useTheme();
    const {
      iconData
    } = useIcon(() => slotIcon.value || props.icon);
    const {
      sizeClasses
    } = useSize(props);
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.color);
    useRender(() => {
      const slotValue = slots.default?.();
      if (slotValue) {
        slotIcon.value = flattenFragments(slotValue).filter(node => node.type === Text && node.children && typeof node.children === 'string')[0]?.children;
      }
      const hasClick = !!(attrs.onClick || attrs.onClickOnce);
      return createVNode(iconData.value.component, {
        "tag": props.tag,
        "icon": iconData.value.icon,
        "class": normalizeClass(['v-icon', 'notranslate', themeClasses.value, sizeClasses.value, textColorClasses.value, {
          'v-icon--clickable': hasClick,
          'v-icon--disabled': props.disabled,
          'v-icon--start': props.start,
          'v-icon--end': props.end
        }, props.class]),
        "style": normalizeStyle([{
          '--v-icon-opacity': props.opacity
        }, !sizeClasses.value ? {
          fontSize: convertToUnit(props.size),
          height: convertToUnit(props.size),
          width: convertToUnit(props.size)
        } : undefined, textColorStyles.value, props.style]),
        "role": hasClick ? 'button' : undefined,
        "aria-hidden": !hasClick,
        "tabindex": hasClick ? props.disabled ? -1 : 0 : undefined
      }, {
        default: () => [slotValue]
      });
    });
    return {};
  }
});

// Utilities
function useIntersectionObserver(callback, options) {
  const intersectionRef = ref();
  const isIntersecting = shallowRef(false);
  if (SUPPORTS_INTERSECTION) {
    const observer = new IntersectionObserver(entries => {
      isIntersecting.value = !!entries.find(entry => entry.isIntersecting);
    }, options);
    onScopeDispose(() => {
      observer.disconnect();
    });
    watch(intersectionRef, (newValue, oldValue) => {
      if (oldValue) {
        observer.unobserve(oldValue);
        isIntersecting.value = false;
      }
      if (newValue) observer.observe(newValue);
    }, {
      flush: 'post'
    });
  }
  return {
    intersectionRef,
    isIntersecting
  };
}

// Utilities

// Types

// Types

// Composables
const makeRevealProps = propsFactory({
  reveal: {
    type: [Boolean, Object],
    default: false
  }
}, 'reveal');
function useReveal(props) {
  const defaultDuration = 900;
  const duration = toRef(() => typeof props.reveal === 'object' ? Math.max(0, Number(props.reveal.duration ?? defaultDuration)) : defaultDuration);
  const state = shallowRef(props.reveal ? 'initial' : 'disabled');
  onMounted(async () => {
    if (props.reveal) {
      state.value = 'initial';
      await new Promise(resolve => requestAnimationFrame(resolve));
      state.value = 'pending';
      await new Promise(resolve => setTimeout(resolve, duration.value));
      state.value = 'done';
    }
  });
  return {
    duration,
    state
  };
}

// Types

const makeVProgressCircularProps = propsFactory({
  bgColor: String,
  color: String,
  indeterminate: [Boolean, String],
  rounded: Boolean,
  modelValue: {
    type: [Number, String],
    default: 0
  },
  rotate: {
    type: [Number, String],
    default: 0
  },
  width: {
    type: [Number, String],
    default: 4
  },
  ...makeComponentProps(),
  ...makeRevealProps(),
  ...makeSizeProps(),
  ...makeTagProps({
    tag: 'div'
  }),
  ...makeThemeProps()
}, 'VProgressCircular');
const VProgressCircular = genericComponent()({
  name: 'VProgressCircular',
  props: makeVProgressCircularProps(),
  setup(props, {
    slots
  }) {
    const MAGIC_RADIUS_CONSTANT = 20;
    const CIRCUMFERENCE = 2 * Math.PI * MAGIC_RADIUS_CONSTANT;
    const root = ref();
    const {
      themeClasses
    } = provideTheme(props);
    const {
      sizeClasses,
      sizeStyles
    } = useSize(props);
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.color);
    const {
      textColorClasses: underlayColorClasses,
      textColorStyles: underlayColorStyles
    } = useTextColor(() => props.bgColor);
    const {
      intersectionRef,
      isIntersecting
    } = useIntersectionObserver();
    const {
      resizeRef,
      contentRect
    } = useResizeObserver();
    const {
      state: revealState,
      duration: revealDuration
    } = useReveal(props);
    const normalizedValue = toRef(() => revealState.value === 'initial' ? 0 : clamp(parseFloat(props.modelValue), 0, 100));
    const width = toRef(() => Number(props.width));
    const size = toRef(() => {
      // Get size from element if size prop value is small, large etc
      return sizeStyles.value ? Number(props.size) : contentRect.value ? contentRect.value.width : Math.max(width.value, 32);
    });
    const diameter = toRef(() => MAGIC_RADIUS_CONSTANT / (1 - width.value / size.value) * 2);
    const strokeWidth = toRef(() => width.value / size.value * diameter.value);
    const strokeDashOffset = toRef(() => {
      const baseLength = (100 - normalizedValue.value) / 100 * CIRCUMFERENCE;
      return props.rounded && normalizedValue.value > 0 && normalizedValue.value < 100 ? convertToUnit(Math.min(CIRCUMFERENCE - 0.01, baseLength + strokeWidth.value)) : convertToUnit(baseLength);
    });
    const startAngle = computed(() => {
      const baseAngle = Number(props.rotate);
      return props.rounded ? baseAngle + strokeWidth.value / 2 / CIRCUMFERENCE * 360 : baseAngle;
    });
    watchEffect(() => {
      intersectionRef.value = root.value;
      resizeRef.value = root.value;
    });
    useRender(() => createVNode(props.tag, {
      "ref": root,
      "class": normalizeClass(['v-progress-circular', {
        'v-progress-circular--indeterminate': !!props.indeterminate,
        'v-progress-circular--visible': isIntersecting.value,
        'v-progress-circular--disable-shrink': props.indeterminate && (props.indeterminate === 'disable-shrink' || PREFERS_REDUCED_MOTION()),
        'v-progress-circular--revealing': ['initial', 'pending'].includes(revealState.value)
      }, themeClasses.value, sizeClasses.value, textColorClasses.value, props.class]),
      "style": normalizeStyle([sizeStyles.value, textColorStyles.value, {
        '--progress-reveal-duration': `${revealDuration.value}ms`
      }, props.style]),
      "role": "progressbar",
      "aria-valuemin": "0",
      "aria-valuemax": "100",
      "aria-valuenow": props.indeterminate ? undefined : normalizedValue.value
    }, {
      default: () => [createElementVNode("svg", {
        "style": {
          transform: `rotate(calc(-90deg + ${startAngle.value}deg))`
        },
        "xmlns": "http://www.w3.org/2000/svg",
        "viewBox": `0 0 ${diameter.value} ${diameter.value}`
      }, [createElementVNode("circle", {
        "class": normalizeClass(['v-progress-circular__underlay', underlayColorClasses.value]),
        "style": normalizeStyle(underlayColorStyles.value),
        "fill": "transparent",
        "cx": "50%",
        "cy": "50%",
        "r": MAGIC_RADIUS_CONSTANT,
        "stroke-width": strokeWidth.value,
        "stroke-dasharray": CIRCUMFERENCE,
        "stroke-dashoffset": 0
      }, null), createElementVNode("circle", {
        "class": "v-progress-circular__overlay",
        "fill": "transparent",
        "cx": "50%",
        "cy": "50%",
        "r": MAGIC_RADIUS_CONSTANT,
        "stroke-width": strokeWidth.value,
        "stroke-dasharray": CIRCUMFERENCE,
        "stroke-dashoffset": strokeDashOffset.value,
        "stroke-linecap": props.rounded ? 'round' : undefined
      }, null)]), slots.default && createElementVNode("div", {
        "class": "v-progress-circular__content"
      }, [slots.default({
        value: normalizedValue.value
      })])]
    }));
    return {};
  }
});

// Utilities

// Types

// Composables
const makeChunksProps = propsFactory({
  chunkCount: {
    type: [Number, String],
    default: null
  },
  chunkWidth: {
    type: [Number, String],
    default: null
  },
  chunkGap: {
    type: [Number, String],
    default: 4
  },
  variant: {
    type: String,
    default: undefined,
    validator: v => ['split'].includes(v)
  }
}, 'chunks');
function useChunks(props, containerWidth, value, bufferValue, reversed) {
  const isSplit = toRef(() => props.variant === 'split');
  const chunkCount = toRef(() => isSplit.value ? 2 : Number(props.chunkCount) || 0);
  const hasChunks = toRef(() => !isSplit.value && (!!chunkCount.value || !!props.chunkWidth));
  const chunkWidth = computed(() => {
    const containerSize = toValue(containerWidth);
    if (!containerSize) return 0;
    if (chunkCount.value) {
      const availableWidth = containerSize - Number(props.chunkGap) * (chunkCount.value - 1);
      return availableWidth / chunkCount.value;
    }
    return Number(props.chunkWidth);
  });
  const chunkGap = toRef(() => Number(props.chunkGap));
  const chunksMaskStyles = computed(() => {
    if (!hasChunks.value) return {};
    const chunkGapPx = convertToUnit(chunkGap.value);
    const chunkWidthPx = convertToUnit(chunkWidth.value);
    return {
      maskRepeat: 'repeat-x',
      maskImage: `linear-gradient(90deg, #000, #000 ${chunkWidthPx}, transparent ${chunkWidthPx}, transparent)`,
      maskSize: `calc(${chunkWidthPx} + ${chunkGapPx}) 100%`
    };
  });
  const splitStyles = computed(() => {
    if (!isSplit.value) return undefined;
    const halfGap = convertToUnit(chunkGap.value / 2);
    const position = toValue(reversed) ? 'right' : 'left';
    const val = toValue(value);
    if (val <= 0 || val >= 100) return undefined;
    const buffer = toValue(bufferValue);
    const split = convertToUnit(val, '%');
    const hasBuffer = buffer > val && buffer < 100;
    const bufferSplit = convertToUnit(buffer, '%');
    return {
      bar: {
        width: `calc(${split} - ${halfGap})`
      },
      buffer: hasBuffer ? {
        [position]: `calc(${split} + ${halfGap})`,
        width: `calc(${bufferSplit} - ${split} - ${convertToUnit(chunkGap.value)})`
      } : undefined,
      background: {
        [position]: `calc(${hasBuffer ? bufferSplit : split} + ${halfGap})`,
        width: `calc(100% - ${hasBuffer ? bufferSplit : split} - ${halfGap})`
      }
    };
  });
  function snapValueToChunk(val) {
    if (isSplit.value) return val;
    const containerSize = toValue(containerWidth);
    if (!containerSize) return val;
    const gapRelativeSize = 100 * chunkGap.value / containerSize;
    const chunkRelativeSize = 100 * (chunkWidth.value + chunkGap.value) / containerSize;

    // low-effort workaround to floating-point rounding in the division
    const filledChunks = Math.floor((val + gapRelativeSize) / chunkRelativeSize + 1e-9);
    return clamp(filledChunks * chunkRelativeSize - gapRelativeSize / 2, 0, 100);
  }
  return {
    hasChunks: toRef(() => hasChunks.value || isSplit.value),
    isSplit,
    chunkCount,
    chunksMaskStyles,
    splitStyles,
    snapValueToChunk
  };
}

const makeVProgressLinearProps = propsFactory({
  absolute: Boolean,
  active: {
    type: Boolean,
    default: true
  },
  bgColor: String,
  bgOpacity: [Number, String],
  bufferValue: {
    type: [Number, String],
    default: 0
  },
  bufferColor: String,
  bufferOpacity: [Number, String],
  clickable: Boolean,
  color: String,
  height: {
    type: [Number, String],
    default: 4
  },
  indeterminate: Boolean,
  max: {
    type: [Number, String],
    default: 100
  },
  modelValue: {
    type: [Number, String],
    default: 0
  },
  opacity: [Number, String],
  reverse: Boolean,
  stream: Boolean,
  striped: Boolean,
  roundedBar: Boolean,
  ...makeChunksProps(),
  ...makeComponentProps(),
  ...makeLocationProps({
    location: 'top'
  }),
  ...makeRoundedProps(),
  ...makeTagProps(),
  ...makeThemeProps()
}, 'VProgressLinear');
const VProgressLinear = genericComponent()({
  name: 'VProgressLinear',
  props: makeVProgressLinearProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const root = ref();
    const progress = useProxiedModel(props, 'modelValue');
    const {
      isRtl,
      rtlClasses
    } = useRtl();
    const {
      themeClasses
    } = provideTheme(props);
    const {
      locationStyles
    } = useLocation(props);
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.color);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.bgColor || props.color);
    const {
      backgroundColorClasses: bufferColorClasses,
      backgroundColorStyles: bufferColorStyles
    } = useBackgroundColor(() => props.bufferColor || props.bgColor || props.color);
    const {
      backgroundColorClasses: barColorClasses,
      backgroundColorStyles: barColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      intersectionRef,
      isIntersecting
    } = useIntersectionObserver();
    const max = computed(() => parseFloat(props.max));
    const height = computed(() => parseFloat(props.height));
    const normalizedBuffer = computed(() => clamp(parseFloat(props.bufferValue) / max.value * 100, 0, 100));
    const normalizedValue = computed(() => clamp(parseFloat(progress.value) / max.value * 100, 0, 100));
    const isReversed = computed(() => isRtl.value !== props.reverse);
    const transition = computed(() => props.indeterminate ? 'fade-transition' : 'slide-x-transition');
    const containerWidth = shallowRef(0);
    const {
      hasChunks,
      splitStyles,
      chunksMaskStyles,
      snapValueToChunk
    } = useChunks(props, containerWidth, normalizedValue, normalizedBuffer, isReversed);
    useToggleScope(hasChunks, () => {
      const {
        resizeRef
      } = useResizeObserver(entries => containerWidth.value = entries[0].contentRect.width);
      watchEffect(() => resizeRef.value = root.value);
    });
    const bufferWidth = computed(() => {
      return hasChunks.value ? snapValueToChunk(normalizedBuffer.value) : normalizedBuffer.value;
    });
    const barWidth = computed(() => {
      return hasChunks.value ? snapValueToChunk(normalizedValue.value) : normalizedValue.value;
    });
    function handleClick(e) {
      if (!intersectionRef.value) return;
      const {
        left,
        right,
        width
      } = intersectionRef.value.getBoundingClientRect();
      const value = isReversed.value ? width - e.clientX + (right - width) : e.clientX - left;
      progress.value = Math.round(value / width * max.value);
    }
    watchEffect(() => {
      intersectionRef.value = root.value;
    });
    function renderBackgroundBar() {
      return createElementVNode("div", {
        "class": normalizeClass(['v-progress-linear__background', backgroundColorClasses.value]),
        "style": normalizeStyle([backgroundColorStyles.value, {
          opacity: props.bgOpacity != null ? parseFloat(props.bgOpacity) : undefined,
          width: props.stream ? 0 : undefined
        }, props.indeterminate ? {} : splitStyles.value?.background])
      }, null);
    }
    useRender(() => createVNode(props.tag, {
      "ref": root,
      "class": normalizeClass(['v-progress-linear', {
        'v-progress-linear--absolute': props.absolute,
        'v-progress-linear--active': props.active && isIntersecting.value,
        'v-progress-linear--reverse': isReversed.value,
        'v-progress-linear--rounded': props.rounded,
        'v-progress-linear--rounded-bar': props.roundedBar,
        'v-progress-linear--striped': props.striped,
        'v-progress-linear--clickable': props.clickable,
        'v-progress-linear--variant-split': props.variant === 'split'
      }, roundedClasses.value, themeClasses.value, rtlClasses.value, props.class]),
      "style": normalizeStyle([{
        bottom: props.location === 'bottom' ? 0 : undefined,
        top: props.location === 'top' ? 0 : undefined,
        height: props.active ? convertToUnit(height.value) : 0,
        '--v-progress-linear-height': convertToUnit(height.value),
        '--v-progress-chunk-gap': convertToUnit(props.chunkGap),
        ...(props.absolute ? locationStyles.value : {})
      }, chunksMaskStyles.value, roundedStyles.value, props.style]),
      "role": "progressbar",
      "aria-hidden": props.active ? 'false' : 'true',
      "aria-valuemin": "0",
      "aria-valuemax": props.max,
      "aria-valuenow": props.indeterminate ? undefined : Math.min(parseFloat(progress.value), max.value),
      "onClick": props.clickable && handleClick
    }, {
      default: () => [props.stream && createElementVNode("div", {
        "key": "stream",
        "class": normalizeClass(['v-progress-linear__stream', textColorClasses.value]),
        "style": {
          ...textColorStyles.value,
          [isReversed.value ? 'left' : 'right']: convertToUnit(-height.value),
          borderTop: `${convertToUnit(height.value / 2)} dotted`,
          opacity: props.bufferOpacity != null ? parseFloat(props.bufferOpacity) : undefined,
          top: `calc(50% - ${convertToUnit(height.value / 4)})`,
          width: convertToUnit(100 - normalizedBuffer.value, '%'),
          '--v-progress-linear-stream-to': convertToUnit(height.value * (isReversed.value ? 1 : -1))
        }
      }, null), (props.variant !== 'split' || !props.indeterminate) && renderBackgroundBar(), createElementVNode("div", {
        "class": normalizeClass(['v-progress-linear__buffer', bufferColorClasses.value]),
        "style": normalizeStyle([bufferColorStyles.value, {
          opacity: props.bufferOpacity != null ? parseFloat(props.bufferOpacity) : undefined,
          width: convertToUnit(bufferWidth.value, '%')
        }, splitStyles.value?.buffer])
      }, null), createVNode(Transition, {
        "name": transition.value
      }, {
        default: () => [!props.indeterminate ? createElementVNode("div", {
          "class": normalizeClass(['v-progress-linear__determinate', barColorClasses.value]),
          "style": normalizeStyle([barColorStyles.value, {
            width: convertToUnit(barWidth.value, '%')
          }, splitStyles.value?.bar])
        }, null) : createElementVNode("div", {
          "class": "v-progress-linear__indeterminate"
        }, [props.variant === 'split' && createElementVNode(Fragment, null, [renderBackgroundBar(), renderBackgroundBar(), renderBackgroundBar()]), ['long', 'short'].map(bar => createElementVNode("div", {
          "key": bar,
          "class": normalizeClass(['v-progress-linear__indeterminate', bar, barColorClasses.value]),
          "style": normalizeStyle(barColorStyles.value)
        }, null))])]
      }), slots.default && createElementVNode("div", {
        "class": "v-progress-linear__content"
      }, [slots.default({
        value: normalizedValue.value,
        buffer: normalizedBuffer.value
      })])]
    }));
    return {};
  }
});

// Types

// Composables
const makeLoaderProps = propsFactory({
  loading: [Boolean, String]
}, 'loader');
function useLoader(props, name = getCurrentInstanceName()) {
  const loaderClasses = toRef(() => ({
    [`${name}--loading`]: props.loading
  }));
  return {
    loaderClasses
  };
}
function LoaderSlot(props, {
  slots
}) {
  return createElementVNode("div", {
    "class": normalizeClass(`${props.name}__loader`)
  }, [slots.default?.({
    color: props.color,
    isActive: props.active
  }) || createVNode(VProgressLinear, {
    "absolute": props.absolute,
    "active": props.active,
    "color": props.color,
    "height": "2",
    "indeterminate": true
  }, null)]);
}

// Utilities

// Types

const positionValues = ['static', 'relative', 'fixed', 'absolute', 'sticky'];
// Composables
const makePositionProps = propsFactory({
  position: {
    type: String,
    validator: /* istanbul ignore next */v => positionValues.includes(v)
  }
}, 'position');
function usePosition(props, name = getCurrentInstanceName()) {
  const positionClasses = toRef(() => {
    return props.position ? `${name}--${props.position}` : undefined;
  });
  return {
    positionClasses
  };
}

// Utilities

// Types

function useRoute() {
  const vm = getCurrentInstance('useRoute');
  return computed(() => vm?.proxy?.$route);
}
function useRouter() {
  return getCurrentInstance('useRouter')?.proxy?.$router;
}
function useLink(props, attrs) {
  const RouterLink = resolveDynamicComponent('RouterLink');
  const isLink = toRef(() => !!(props.href || props.to));
  const isClickable = computed(() => {
    return isLink?.value || hasEvent(attrs, 'click') || hasEvent(props, 'click');
  });
  if (typeof RouterLink === 'string' || !('useLink' in RouterLink)) {
    const href = toRef(() => props.href);
    return {
      isLink,
      isRouterLink: toRef(() => false),
      isClickable,
      href,
      linkProps: reactive({
        href
      }),
      route: toRef(() => undefined),
      navigate: toRef(() => undefined)
    };
  }

  // vue-router useLink `to` prop needs to be reactive and useLink will crash if undefined
  const routerLink = RouterLink.useLink({
    to: toRef(() => props.to || ''),
    replace: toRef(() => props.replace)
  });
  // Actual link needs to be undefined when to prop is not used
  const link = computed(() => props.to ? routerLink : undefined);
  const route = useRoute();
  const isActive = computed(() => {
    if (!link.value) return false;
    // router still resolving initial navigation, according to posva:
    // - START_LOCATION has an empty matched array and its name is undefined (unlike 404 Not Page Found)
    // - if the router is still resolving the initial boot, we bypass the active check and returns
    //   isExactActive ?? false to prevent the flashing overlay on page refresh
    if (route.value && route.value.matched.length === 0 && route.value.name == null) {
      return link.value.isExactActive?.value ?? false;
    }
    if (!props.exact) return link.value.isActive?.value ?? false;
    if (!route.value) return link.value.isExactActive?.value ?? false;
    return link.value.isExactActive?.value && deepEqual(link.value.route.value.query, route.value.query);
  });
  const href = computed(() => props.to ? link.value?.route.value.href : props.href);
  const isRouterLink = toRef(() => !!props.to);
  return {
    isLink,
    isRouterLink,
    isClickable,
    isActive,
    route: toRef(() => link.value?.route.value),
    navigate: toRef(() => link.value?.navigate),
    href,
    linkProps: reactive({
      href,
      'aria-current': toRef(() => isActive.value ? 'page' : undefined),
      'aria-disabled': toRef(() => props.disabled && isLink.value ? 'true' : undefined),
      tabindex: toRef(() => props.disabled && isLink.value ? '-1' : undefined)
    })
  };
}
const makeRouterProps = propsFactory({
  href: String,
  replace: Boolean,
  to: [String, Object],
  exact: Boolean
}, 'router');
let inTransition = false;
function useBackButton(router, cb) {
  let popped = false;
  let removeBefore;
  let removeAfter;
  if (IN_BROWSER && router?.beforeEach) {
    nextTick(() => {
      window.addEventListener('popstate', onPopstate);
      removeBefore = router.beforeEach(() => {
        if (!inTransition) {
          inTransition = true;
          return new Promise(resolve => {
            setTimeout(() => resolve(popped ? cb() : undefined));
          });
        }
        return popped ? cb() : undefined;
      });
      removeAfter = router?.afterEach(() => {
        inTransition = false;
      });
    });
    onScopeDispose(() => {
      window.removeEventListener('popstate', onPopstate);
      removeBefore?.();
      removeAfter?.();
    });
  }
  function onPopstate(e) {
    if (e.state?.replaced) return;
    popped = true;
    setTimeout(() => popped = false);
  }
}

// Utilities

// Types

function useSelectLink(link, select) {
  watch(() => link.isActive?.value, isActive => {
    if (link.isLink.value && isActive != null && select) {
      nextTick(() => {
        select(isActive);
      });
    }
  }, {
    immediate: true
  });
}

// Styles

// Types

const stopSymbol = Symbol('rippleStop');
const DELAY_RIPPLE = 80;
function transform(el, value) {
  el.style.transform = value;
  el.style.webkitTransform = value;
}
function isTouchEvent(e) {
  return e.constructor.name === 'TouchEvent';
}
function isKeyboardEvent(e) {
  return e.constructor.name === 'KeyboardEvent';
}
const calculate = (e, el, value = {}) => {
  let localX = 0;
  let localY = 0;
  if (!isKeyboardEvent(e)) {
    const offset = new Box(el);
    const target = isTouchEvent(e) ? e.touches[e.touches.length - 1] : e;
    const point = getTargetBox([target.clientX, target.clientY]);
    localX = point.x - offset.left;
    localY = point.y - offset.top;
  }
  let radius = 0;
  let scale = 0.3;
  if (el._ripple?.circle) {
    scale = 0.15;
    radius = el.clientWidth / 2;
    radius = value.center ? radius : radius + Math.sqrt((localX - radius) ** 2 + (localY - radius) ** 2) / 4;
  } else {
    radius = Math.sqrt(el.clientWidth ** 2 + el.clientHeight ** 2) / 2;
  }
  const centerX = `${(el.clientWidth - radius * 2) / 2}px`;
  const centerY = `${(el.clientHeight - radius * 2) / 2}px`;
  const x = value.center ? centerX : `${localX - radius}px`;
  const y = value.center ? centerY : `${localY - radius}px`;
  return {
    radius,
    scale,
    x,
    y,
    centerX,
    centerY
  };
};
const ripples = {
  /* eslint-disable max-statements */
  show(e, el, value = {}) {
    if (!el?._ripple?.enabled) {
      return;
    }
    const container = document.createElement('span');
    const animation = document.createElement('span');
    container.appendChild(animation);
    container.className = 'v-ripple__container';
    if (value.class) {
      container.className += ` ${value.class}`;
    }
    const {
      radius,
      scale,
      x,
      y,
      centerX,
      centerY
    } = calculate(e, el, value);
    const size = `${radius * 2}px`;
    animation.className = 'v-ripple__animation';
    animation.style.width = size;
    animation.style.height = size;
    el.appendChild(container);
    const computed = window.getComputedStyle(el);
    if (computed && computed.position === 'static') {
      el.style.position = 'relative';
      el.dataset.previousPosition = 'static';
    }
    animation.classList.add('v-ripple__animation--enter');
    animation.classList.add('v-ripple__animation--visible');
    transform(animation, `translate(${x}, ${y}) scale3d(${scale},${scale},${scale})`);
    animation.dataset.activated = String(performance.now());
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        animation.classList.remove('v-ripple__animation--enter');
        animation.classList.add('v-ripple__animation--in');
        transform(animation, `translate(${centerX}, ${centerY}) scale3d(1,1,1)`);
      });
    });
  },
  hide(el) {
    if (!el?._ripple?.enabled) return;
    const ripples = el.getElementsByClassName('v-ripple__animation');
    if (ripples.length === 0) return;
    const animation = Array.from(ripples).findLast(ripple => !ripple.dataset.isHiding);
    if (!animation) return;else animation.dataset.isHiding = 'true';
    const diff = performance.now() - Number(animation.dataset.activated);
    const delay = Math.max(250 - diff, 0);
    setTimeout(() => {
      animation.classList.remove('v-ripple__animation--in');
      animation.classList.add('v-ripple__animation--out');
      setTimeout(() => {
        const ripples = el.getElementsByClassName('v-ripple__animation');
        if (ripples.length === 1 && el.dataset.previousPosition) {
          el.style.position = el.dataset.previousPosition;
          delete el.dataset.previousPosition;
        }
        if (animation.parentNode?.parentNode === el) el.removeChild(animation.parentNode);
      }, 300);
    }, delay);
  }
};
function isRippleEnabled(value) {
  return typeof value === 'undefined' || !!value;
}
function rippleShow(e) {
  const value = {};
  const element = e.currentTarget;
  if (!element?._ripple || element._ripple.touched || e[stopSymbol]) return;

  // Don't allow the event to trigger ripples on any other elements
  e[stopSymbol] = true;
  if (isTouchEvent(e)) {
    element._ripple.touched = true;
    element._ripple.isTouch = true;
  } else {
    // It's possible for touch events to fire
    // as mouse events on Android/iOS, this
    // will skip the event call if it has
    // already been registered as touch
    if (element._ripple.isTouch) return;
  }
  value.center = element._ripple.centered || isKeyboardEvent(e);
  if (element._ripple.class) {
    value.class = element._ripple.class;
  }
  if (isTouchEvent(e)) {
    // already queued that shows or hides the ripple
    if (element._ripple.showTimerCommit) return;
    element._ripple.showTimerCommit = () => {
      ripples.show(e, element, value);
    };
    element._ripple.showTimer = window.setTimeout(() => {
      if (element?._ripple?.showTimerCommit) {
        element._ripple.showTimerCommit();
        element._ripple.showTimerCommit = null;
      }
    }, DELAY_RIPPLE);
  } else {
    ripples.show(e, element, value);
  }
}
function rippleStop(e) {
  e[stopSymbol] = true;
}
function rippleHide(e) {
  const element = e.currentTarget;
  if (!element?._ripple) return;
  window.clearTimeout(element._ripple.showTimer);

  // The touch interaction occurs before the show timer is triggered.
  // We still want to show ripple effect.
  if (e.type === 'touchend' && element._ripple.showTimerCommit) {
    element._ripple.showTimerCommit();
    element._ripple.showTimerCommit = null;

    // re-queue ripple hiding
    element._ripple.showTimer = window.setTimeout(() => {
      rippleHide(e);
    });
    return;
  }
  window.setTimeout(() => {
    if (element._ripple) {
      element._ripple.touched = false;
    }
  });
  ripples.hide(element);
}
function rippleCancelShow(e) {
  const element = e.currentTarget;
  if (!element?._ripple) return;
  if (element._ripple.showTimerCommit) {
    element._ripple.showTimerCommit = null;
  }
  window.clearTimeout(element._ripple.showTimer);
}
let keyboardRipple = false;
function keyboardRippleShow(e, keys) {
  if (!keyboardRipple && keys.includes(e.key)) {
    keyboardRipple = true;
    rippleShow(e);
  }
}
function keyboardRippleHide(e) {
  keyboardRipple = false;
  rippleHide(e);
}
function focusRippleHide(e) {
  if (keyboardRipple) {
    keyboardRipple = false;
    rippleHide(e);
  }
}
function updateRipple(el, binding, wasEnabled) {
  const {
    value,
    modifiers
  } = binding;
  const enabled = isRippleEnabled(value);
  if (!enabled) {
    ripples.hide(el);
  }
  el._ripple = el._ripple ?? {};
  el._ripple.enabled = enabled;
  el._ripple.centered = modifiers.center;
  el._ripple.circle = modifiers.circle;
  const bindingValue = isObject(value) ? value : {};
  if (bindingValue.class) {
    el._ripple.class = bindingValue.class;
  }
  const allowedKeys = bindingValue.keys ?? ['Enter', 'Space'];
  el._ripple.keyDownHandler = e => keyboardRippleShow(e, allowedKeys);
  if (enabled && !wasEnabled) {
    if (modifiers.stop) {
      el.addEventListener('touchstart', rippleStop, {
        passive: true
      });
      el.addEventListener('mousedown', rippleStop);
      return;
    }
    el.addEventListener('touchstart', rippleShow, {
      passive: true
    });
    el.addEventListener('touchend', rippleHide, {
      passive: true
    });
    el.addEventListener('touchmove', rippleCancelShow, {
      passive: true
    });
    el.addEventListener('touchcancel', rippleHide);
    el.addEventListener('mousedown', rippleShow);
    el.addEventListener('mouseup', rippleHide);
    el.addEventListener('mouseleave', rippleHide);
    el.addEventListener('keydown', el._ripple.keyDownHandler);
    el.addEventListener('keyup', keyboardRippleHide);
    el.addEventListener('blur', focusRippleHide);

    // Anchor tags can be dragged, causes other hides to fail - #1537
    el.addEventListener('dragstart', rippleHide, {
      passive: true
    });
  } else if (!enabled && wasEnabled) {
    removeListeners(el);
  }
}
function removeListeners(el) {
  el.removeEventListener('touchstart', rippleStop);
  el.removeEventListener('mousedown', rippleStop);
  el.removeEventListener('touchstart', rippleShow);
  el.removeEventListener('touchend', rippleHide);
  el.removeEventListener('touchmove', rippleCancelShow);
  el.removeEventListener('touchcancel', rippleHide);
  el.removeEventListener('mousedown', rippleShow);
  el.removeEventListener('mouseup', rippleHide);
  el.removeEventListener('mouseleave', rippleHide);
  if (el._ripple?.keyDownHandler) {
    el.removeEventListener('keydown', el._ripple.keyDownHandler);
  }
  el.removeEventListener('keyup', keyboardRippleHide);
  el.removeEventListener('blur', focusRippleHide);
  el.removeEventListener('dragstart', rippleHide);
}
function mounted$4(el, binding) {
  updateRipple(el, binding, false);
}
function unmounted$4(el) {
  removeListeners(el);
  delete el._ripple;
}
function updated$1(el, binding) {
  if (binding.value === binding.oldValue) {
    return;
  }
  const wasEnabled = isRippleEnabled(binding.oldValue);
  updateRipple(el, binding, wasEnabled);
}
const Ripple = {
  mounted: mounted$4,
  unmounted: unmounted$4,
  updated: updated$1
};

// Types

const makeVBtnProps = propsFactory({
  active: {
    type: Boolean,
    default: undefined
  },
  activeColor: String,
  baseColor: String,
  symbol: {
    type: null,
    default: VBtnToggleSymbol
  },
  flat: Boolean,
  icon: [Boolean, String, Function, Object],
  prependIcon: IconValue,
  appendIcon: IconValue,
  block: Boolean,
  readonly: Boolean,
  slim: Boolean,
  stacked: Boolean,
  spaced: String,
  ripple: {
    type: [Boolean, Object],
    default: true
  },
  text: {
    type: [String, Number, Boolean],
    default: undefined
  },
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeDimensionProps(),
  ...makeElevationProps(),
  ...makeGroupItemProps(),
  ...makeLoaderProps(),
  ...makeLocationProps(),
  ...makePositionProps(),
  ...makeRoundedProps(),
  ...makeRouterProps(),
  ...makeSizeProps(),
  ...makeTagProps({
    tag: 'button'
  }),
  ...makeThemeProps(),
  ...makeVariantProps({
    variant: 'elevated'
  })
}, 'VBtn');
const VBtn = genericComponent()({
  name: 'VBtn',
  props: makeVBtnProps(),
  emits: {
    'group:selected': val => true
  },
  setup(props, {
    attrs,
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      borderClasses
    } = useBorder(props);
    const {
      densityClasses
    } = useDensity(props);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      loaderClasses
    } = useLoader(props);
    const {
      locationStyles
    } = useLocation(props);
    const {
      positionClasses
    } = usePosition(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      sizeClasses,
      sizeStyles
    } = useSize(props);
    const group = useGroupItem(props, props.symbol, false);
    const link = useLink(props, attrs);
    const isActive = computed(() => {
      if (props.active !== undefined) {
        return props.active;
      }
      if (link.isRouterLink.value) {
        return link.isActive?.value;
      }
      return group?.isSelected.value;
    });
    const color = toRef(() => isActive.value ? props.activeColor ?? props.color : props.color);
    const variantProps = computed(() => {
      const showColor = group?.isSelected.value && (!link.isLink.value || link.isActive?.value) || !group || link.isActive?.value;
      return {
        color: showColor ? color.value ?? props.baseColor : props.baseColor,
        variant: props.variant
      };
    });
    const {
      colorClasses,
      colorStyles,
      variantClasses
    } = useVariant(variantProps);
    const isDisabled = computed(() => group?.disabled.value || props.disabled);
    const isElevated = toRef(() => {
      return props.variant === 'elevated' && !(props.disabled || props.flat || props.border);
    });
    const valueAttr = computed(() => {
      if (props.value === undefined || typeof props.value === 'symbol') return undefined;
      return Object(props.value) === props.value ? JSON.stringify(props.value, null, 0) : props.value;
    });
    function onClick(e) {
      if (isDisabled.value || link.isLink.value && (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0 || attrs.target === '_blank')) return;
      if (link.isRouterLink.value) {
        link.navigate.value?.(e);
      } else {
        // Group active state for links is handled by useSelectLink
        group?.toggle();
      }
    }
    useSelectLink(link, group?.select);
    useRender(() => {
      const Tag = link.isLink.value ? 'a' : props.tag;
      const hasPrepend = !!(props.prependIcon || slots.prepend);
      const hasAppend = !!(props.appendIcon || slots.append);
      const hasIcon = !!(props.icon && props.icon !== true);
      return withDirectives(createVNode(Tag, mergeProps(link.linkProps, {
        "type": Tag === 'a' ? undefined : 'button',
        "class": ['v-btn', group?.selectedClass.value, {
          'v-btn--active': isActive.value,
          'v-btn--block': props.block,
          'v-btn--disabled': isDisabled.value,
          'v-btn--elevated': isElevated.value,
          'v-btn--flat': props.flat,
          'v-btn--icon': !!props.icon,
          'v-btn--loading': props.loading,
          'v-btn--readonly': props.readonly,
          'v-btn--slim': props.slim,
          'v-btn--stacked': props.stacked
        }, props.spaced ? ['v-btn--spaced', `v-btn--spaced-${props.spaced}`] : [], themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, loaderClasses.value, positionClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, props.class],
        "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, sizeStyles.value, roundedStyles.value, props.style],
        "aria-busy": props.loading ? true : undefined,
        "disabled": isDisabled.value && Tag !== 'a' || undefined,
        "tabindex": props.loading || props.readonly ? -1 : undefined,
        "onClick": onClick,
        "value": Tag !== 'a' ? valueAttr.value : undefined
      }), {
        default: () => [genOverlays(true, 'v-btn'), !props.icon && hasPrepend && createElementVNode("span", {
          "key": "prepend",
          "class": "v-btn__prepend"
        }, [!slots.prepend ? createVNode(VIcon, {
          "key": "prepend-icon",
          "icon": props.prependIcon
        }, null) : createVNode(VDefaultsProvider, {
          "key": "prepend-defaults",
          "disabled": !props.prependIcon,
          "defaults": {
            VIcon: {
              icon: props.prependIcon
            }
          }
        }, slots.prepend)]), createElementVNode("span", {
          "class": "v-btn__content",
          "data-no-activator": ""
        }, [!slots.default && hasIcon ? createVNode(VIcon, {
          "key": "content-icon",
          "icon": props.icon
        }, null) : createVNode(VDefaultsProvider, {
          "key": "content-defaults",
          "disabled": !hasIcon,
          "defaults": {
            VIcon: {
              icon: props.icon
            }
          }
        }, {
          default: () => [slots.default?.() ?? toDisplayString(props.text)]
        })]), !props.icon && hasAppend && createElementVNode("span", {
          "key": "append",
          "class": "v-btn__append"
        }, [!slots.append ? createVNode(VIcon, {
          "key": "append-icon",
          "icon": props.appendIcon
        }, null) : createVNode(VDefaultsProvider, {
          "key": "append-defaults",
          "disabled": !props.appendIcon,
          "defaults": {
            VIcon: {
              icon: props.appendIcon
            }
          }
        }, slots.append)]), !!props.loading && createElementVNode("span", {
          "key": "loader",
          "class": "v-btn__loader"
        }, [slots.loader?.() ?? createVNode(VProgressCircular, {
          "color": typeof props.loading === 'boolean' ? undefined : props.loading,
          "indeterminate": true,
          "width": "2"
        }, null)])]
      }), [[Ripple, !isDisabled.value && props.ripple, '', {
        center: !!props.icon
      }]]);
    });
    return {
      group
    };
  }
});

// Types

const makeVAppBarNavIconProps = propsFactory({
  ...omit(makeVBtnProps({
    icon: '$menu',
    variant: 'text'
  }), ['spaced'])
}, 'VAppBarNavIcon');
const VAppBarNavIcon = genericComponent()({
  name: 'VAppBarNavIcon',
  props: makeVAppBarNavIconProps(),
  setup(props, {
    slots
  }) {
    useRender(() => createVNode(VBtn, mergeProps(props, {
      "class": ['v-app-bar-nav-icon']
    }), slots));
    return {};
  }
});

// Types

const VAppBarTitle = genericComponent()({
  name: 'VAppBarTitle',
  props: makeVToolbarTitleProps(),
  setup(props, {
    slots
  }) {
    useRender(() => createVNode(VToolbarTitle, mergeProps(props, {
      "class": "v-app-bar-title"
    }), slots));
    return {};
  }
});

// Utilities
const VAlertTitle = createSimpleFunctional('v-alert-title');

// Utilities

// Types

// Types

// Composables
const makeIconSizeProps = propsFactory({
  iconSize: [Number, String],
  iconSizes: {
    type: Array,
    default: () => [['x-small', 10], ['small', 16], ['default', 24], ['large', 28], ['x-large', 32]]
  }
}, 'iconSize');
function useIconSizes(props, fallback) {
  const iconSize = computed(() => {
    const iconSizeMap = new Map(props.iconSizes);
    const _iconSize = props.iconSize ?? fallback() ?? 'default';
    return iconSizeMap.has(_iconSize) ? iconSizeMap.get(_iconSize) : _iconSize;
  });
  return {
    iconSize
  };
}

// Types

const allowedTypes = ['success', 'info', 'warning', 'error'];
const makeVAlertProps = propsFactory({
  border: {
    type: [Boolean, String],
    validator: val => {
      return typeof val === 'boolean' || ['top', 'end', 'bottom', 'start'].includes(val);
    }
  },
  borderColor: String,
  closable: Boolean,
  closeIcon: {
    type: IconValue,
    default: '$close'
  },
  closeLabel: {
    type: String,
    default: '$vuetify.close'
  },
  icon: {
    type: [Boolean, String, Function, Object],
    default: null
  },
  modelValue: {
    type: Boolean,
    default: true
  },
  prominent: Boolean,
  title: String,
  text: String,
  type: {
    type: String,
    validator: val => allowedTypes.includes(val)
  },
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeDimensionProps(),
  ...makeElevationProps(),
  ...makeIconSizeProps(),
  ...makeLocationProps(),
  ...makePositionProps(),
  ...makeRoundedProps(),
  ...makeTagProps(),
  ...makeThemeProps(),
  ...makeVariantProps({
    variant: 'flat'
  })
}, 'VAlert');
const VAlert = genericComponent()({
  name: 'VAlert',
  props: makeVAlertProps(),
  emits: {
    'click:close': e => true,
    'update:modelValue': value => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const isActive = useProxiedModel(props, 'modelValue');
    const icon = toRef(() => {
      if (props.icon === false) return undefined;
      if (!props.type) return props.icon;
      return props.icon ?? `$${props.type}`;
    });
    const {
      iconSize
    } = useIconSizes(props, () => props.prominent ? 44 : undefined);
    const {
      themeClasses
    } = provideTheme(props);
    const {
      colorClasses,
      colorStyles,
      variantClasses
    } = useVariant(() => ({
      color: props.color ?? props.type,
      variant: props.variant
    }));
    const {
      densityClasses
    } = useDensity(props);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      locationStyles
    } = useLocation(props);
    const {
      positionClasses
    } = usePosition(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.borderColor);
    const {
      t
    } = useLocale();
    const closeProps = toRef(() => ({
      'aria-label': t(props.closeLabel),
      onClick(e) {
        isActive.value = false;
        emit('click:close', e);
      }
    }));
    return () => {
      const hasPrepend = !!(slots.prepend || icon.value);
      const hasTitle = !!(slots.title || props.title);
      const hasClose = !!(slots.close || props.closable);
      const iconProps = {
        density: props.density,
        icon: icon.value,
        size: props.iconSize || props.prominent ? iconSize.value : undefined
      };
      return isActive.value && createVNode(props.tag, {
        "class": normalizeClass(['v-alert', props.border && {
          'v-alert--border': !!props.border,
          [`v-alert--border-${props.border === true ? 'start' : props.border}`]: true
        }, {
          'v-alert--prominent': props.prominent
        }, themeClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, variantClasses.value, props.class]),
        "style": normalizeStyle([colorStyles.value, dimensionStyles.value, locationStyles.value, roundedStyles.value, props.style]),
        "role": "alert"
      }, {
        default: () => [genOverlays(false, 'v-alert'), props.border && createElementVNode("div", {
          "key": "border",
          "class": normalizeClass(['v-alert__border', textColorClasses.value]),
          "style": normalizeStyle(textColorStyles.value)
        }, null), hasPrepend && createElementVNode("div", {
          "key": "prepend",
          "class": "v-alert__prepend"
        }, [!slots.prepend ? createVNode(VIcon, mergeProps({
          "key": "prepend-icon"
        }, iconProps), null) : createVNode(VDefaultsProvider, {
          "key": "prepend-defaults",
          "disabled": !icon.value,
          "defaults": {
            VIcon: {
              ...iconProps
            }
          }
        }, slots.prepend)]), createElementVNode("div", {
          "class": "v-alert__content"
        }, [hasTitle && createVNode(VAlertTitle, {
          "key": "title"
        }, {
          default: () => [slots.title?.() ?? props.title]
        }), slots.text?.() ?? props.text, slots.default?.()]), slots.append && createElementVNode("div", {
          "key": "append",
          "class": "v-alert__append"
        }, [slots.append()]), hasClose && createElementVNode("div", {
          "key": "close",
          "class": "v-alert__close"
        }, [!slots.close ? createVNode(VBtn, mergeProps({
          "key": "close-btn",
          "icon": props.closeIcon,
          "size": "x-small",
          "variant": "text"
        }, closeProps.value), null) : createVNode(VDefaultsProvider, {
          "key": "close-defaults",
          "defaults": {
            VBtn: {
              icon: props.closeIcon,
              size: 'x-small',
              variant: 'text'
            }
          }
        }, {
          default: () => [slots.close?.({
            props: closeProps.value
          })]
        })])]
      });
    };
  }
});

const makeVBadgeProps = propsFactory({
  bordered: Boolean,
  color: String,
  content: [Number, String],
  dot: Boolean,
  dotSize: [Number, String],
  floating: Boolean,
  icon: IconValue,
  inline: Boolean,
  label: {
    type: String,
    default: '$vuetify.badge'
  },
  max: [Number, String],
  modelValue: {
    type: Boolean,
    default: true
  },
  offsetX: [Number, String],
  offsetY: [Number, String],
  textColor: String,
  ...makeComponentProps(),
  ...makeLocationProps({
    location: 'top end'
  }),
  ...makeRoundedProps(),
  ...makeTagProps(),
  ...makeThemeProps(),
  ...makeTransitionProps({
    transition: 'scale-rotate-transition'
  }),
  ...makeDimensionProps()
}, 'VBadge');
const VBadge = genericComponent()({
  name: 'VBadge',
  inheritAttrs: false,
  props: makeVBadgeProps(),
  setup(props, ctx) {
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      t
    } = useLocale();
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.textColor);
    const {
      themeClasses
    } = useTheme();
    const {
      locationStyles
    } = useLocation(props, true, side => {
      const base = props.floating ? props.dot ? 2 : 4 : props.dot ? Number(props.dotSize ?? 8) : 12;
      return base + (['top', 'bottom'].includes(side) ? Number(props.offsetY ?? 0) : ['left', 'right'].includes(side) ? Number(props.offsetX ?? 0) : 0);
    });
    const {
      dimensionStyles
    } = useDimension(props);
    useRender(() => {
      const value = Number(props.content);
      const content = !props.max || isNaN(value) ? props.content : value <= Number(props.max) ? value : `${props.max}+`;
      const [badgeAttrs, attrs] = pickWithRest(ctx.attrs, ['aria-atomic', 'aria-label', 'aria-live', 'role', 'title']);
      return createVNode(props.tag, mergeProps({
        "class": ['v-badge', {
          'v-badge--bordered': props.bordered,
          'v-badge--dot': props.dot,
          'v-badge--floating': props.floating,
          'v-badge--inline': props.inline
        }, props.class]
      }, attrs, {
        "style": props.style
      }), {
        default: () => [createElementVNode("div", {
          "class": "v-badge__wrapper"
        }, [ctx.slots.default?.(), createVNode(MaybeTransition, {
          "transition": props.transition
        }, {
          default: () => [withDirectives(createElementVNode("span", mergeProps({
            "class": ['v-badge__badge', themeClasses.value, backgroundColorClasses.value, roundedClasses.value, textColorClasses.value],
            "style": [backgroundColorStyles.value, textColorStyles.value, dimensionStyles.value, props.inline ? {} : locationStyles.value, props.dot && props.dotSize ? {
              width: convertToUnit(props.dotSize),
              height: convertToUnit(props.dotSize)
            } : {}, roundedStyles.value],
            "aria-atomic": "true",
            "aria-label": t(props.label, value),
            "aria-live": "polite",
            "role": "status"
          }, badgeAttrs), [props.dot ? undefined : ctx.slots.badge ? ctx.slots.badge?.() : props.icon ? createVNode(VIcon, {
            "icon": props.icon
          }, null) : content]), [[vShow, props.modelValue]])]
        })])]
      });
    });
    return {};
  }
});

// Types

const makeVAvatarProps = propsFactory({
  badge: {
    type: [Boolean, Object],
    default: false
  },
  start: Boolean,
  end: Boolean,
  icon: IconValue,
  image: String,
  text: String,
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeRoundedProps(),
  ...makeSizeProps(),
  ...makeTagProps(),
  ...makeThemeProps(),
  ...makeVariantProps({
    variant: 'flat'
  })
}, 'VAvatar');
const VAvatar = genericComponent()({
  name: 'VAvatar',
  props: makeVAvatarProps(),
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      borderClasses
    } = useBorder(props);
    const {
      colorClasses,
      colorStyles,
      variantClasses
    } = useVariant(props);
    const {
      densityClasses
    } = useDensity(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      sizeClasses,
      sizeStyles
    } = useSize(props);
    const badgeDotSize = computed(() => {
      switch (props.size) {
        case 'x-small':
          return 8;
        case 'small':
          return 10;
        case 'large':
          return 14;
        case 'x-large':
          return 16;
        default:
          return 12;
      }
    });
    const badgeOffset = computed(() => {
      const {
        floating
      } = isObject(props.badge) ? props.badge : {};
      return (floating ? badgeDotSize.value / 2 : 0) - 1.5;
    });
    const badgeProps = computed(() => {
      return {
        bordered: true,
        dot: !slots.badge,
        dotSize: badgeDotSize.value,
        offsetX: badgeOffset.value,
        offsetY: badgeOffset.value,
        color: typeof props.badge === 'string' ? props.badge : 'primary',
        ...(isObject(props.badge) ? props.badge : {})
      };
    });
    useRender(() => {
      const avatar = createVNode(props.tag, {
        "class": normalizeClass(['v-avatar', {
          'v-avatar--start': props.start,
          'v-avatar--end': props.end
        }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, roundedClasses.value, sizeClasses.value, variantClasses.value, props.class]),
        "style": normalizeStyle([colorStyles.value, sizeStyles.value, roundedStyles.value, props.style])
      }, {
        default: () => [!slots.default ? props.image ? createVNode(VImg, {
          "key": "image",
          "src": props.image,
          "alt": "",
          "cover": true
        }, null) : props.icon ? createVNode(VIcon, {
          "key": "icon",
          "icon": props.icon
        }, null) : props.text : createVNode(VDefaultsProvider, {
          "key": "content-defaults",
          "defaults": {
            VImg: {
              cover: true,
              src: props.image
            },
            VIcon: {
              icon: props.icon
            }
          }
        }, {
          default: () => [slots.default()]
        }), genOverlays(false, 'v-avatar')]
      });
      return props.badge ? createVNode(VBadge, badgeProps.value, {
        default: () => avatar,
        badge: slots.badge
      }) : avatar;
    });
    return {};
  }
});

const makeVLabelProps = propsFactory({
  text: String,
  onClick: EventProp(),
  ...makeComponentProps(),
  ...makeThemeProps()
}, 'VLabel');
const VLabel = genericComponent()({
  name: 'VLabel',
  props: makeVLabelProps(),
  setup(props, {
    slots
  }) {
    useRender(() => createElementVNode("label", {
      "class": normalizeClass(['v-label', {
        'v-label--clickable': !!props.onClick
      }, props.class]),
      "style": normalizeStyle(props.style),
      "onClick": props.onClick
    }, [props.text, slots.default?.()]));
    return {};
  }
});

// Types

const VSelectionControlGroupSymbol = Symbol.for('vuetify:selection-control-group');
const makeSelectionControlGroupProps = propsFactory({
  color: String,
  disabled: {
    type: Boolean,
    default: null
  },
  defaultsTarget: String,
  error: Boolean,
  id: String,
  inline: Boolean,
  falseIcon: IconValue,
  trueIcon: IconValue,
  indeterminateIcon: IconValue,
  ripple: {
    type: [Boolean, Object],
    default: true
  },
  multiple: {
    type: Boolean,
    default: null
  },
  name: String,
  readonly: {
    type: Boolean,
    default: null
  },
  modelValue: null,
  type: String,
  valueComparator: {
    type: Function,
    default: deepEqual
  },
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeThemeProps()
}, 'SelectionControlGroup');
const makeVSelectionControlGroupProps = propsFactory({
  ...makeSelectionControlGroupProps({
    defaultsTarget: 'VSelectionControl'
  })
}, 'VSelectionControlGroup');
const VSelectionControlGroup = genericComponent()({
  name: 'VSelectionControlGroup',
  props: makeVSelectionControlGroupProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const modelValue = useProxiedModel(props, 'modelValue');
    const uid = useId();
    const id = toRef(() => props.id || `v-selection-control-group-${uid}`);
    const name = toRef(() => props.name || id.value);
    const updateHandlers = new Set();
    provide(VSelectionControlGroupSymbol, {
      modelValue,
      forceUpdate: () => {
        updateHandlers.forEach(fn => fn());
      },
      onForceUpdate: cb => {
        updateHandlers.add(cb);
        onScopeDispose(() => {
          updateHandlers.delete(cb);
        });
      }
    });
    provideDefaults({
      [props.defaultsTarget]: {
        color: toRef(() => props.color),
        disabled: toRef(() => props.disabled),
        density: toRef(() => props.density),
        error: toRef(() => props.error),
        inline: toRef(() => props.inline),
        modelValue,
        multiple: toRef(() => !!props.multiple || props.multiple == null && Array.isArray(modelValue.value)),
        name,
        falseIcon: toRef(() => props.falseIcon),
        trueIcon: toRef(() => props.trueIcon),
        readonly: toRef(() => props.readonly),
        ripple: toRef(() => props.ripple),
        type: toRef(() => props.type),
        valueComparator: toRef(() => props.valueComparator)
      }
    });
    useRender(() => createElementVNode("div", {
      "class": normalizeClass(['v-selection-control-group', {
        'v-selection-control-group--inline': props.inline
      }, props.class]),
      "style": normalizeStyle(props.style),
      "role": props.type === 'radio' ? 'radiogroup' : undefined
    }, [slots.default?.()]));
    return {};
  }
});

// Types

const makeVSelectionControlProps = propsFactory({
  indeterminate: Boolean,
  label: String,
  baseColor: String,
  trueValue: null,
  falseValue: null,
  value: null,
  ...makeComponentProps(),
  ...makeSelectionControlGroupProps()
}, 'VSelectionControl');
function useSelectionControl(props) {
  const group = inject$1(VSelectionControlGroupSymbol, undefined);
  const {
    densityClasses
  } = useDensity(props);
  const modelValue = useProxiedModel(props, 'modelValue');
  const trueValue = computed(() => props.trueValue !== undefined ? props.trueValue : props.value !== undefined ? props.value : true);
  const falseValue = computed(() => props.falseValue !== undefined ? props.falseValue : false);
  const isMultiple = computed(() => !!props.multiple || props.multiple == null && Array.isArray(modelValue.value));
  const model = computed({
    get() {
      const val = group ? group.modelValue.value : modelValue.value;
      return isMultiple.value ? wrapInArray(val).some(v => props.valueComparator(v, trueValue.value)) : props.valueComparator(val, trueValue.value);
    },
    set(val) {
      if (props.readonly) return;
      const currentValue = val ? trueValue.value : falseValue.value;
      let newVal = currentValue;
      if (isMultiple.value) {
        newVal = val ? [...wrapInArray(modelValue.value), currentValue] : wrapInArray(modelValue.value).filter(item => !props.valueComparator(item, trueValue.value));
      }
      if (group) {
        group.modelValue.value = newVal;
      } else {
        modelValue.value = newVal;
      }
    }
  });
  const isActive = computed(() => model.value || props.indeterminate);
  const {
    textColorClasses,
    textColorStyles
  } = useTextColor(() => {
    if (props.error || props.disabled) return undefined;
    return isActive.value ? props.color : props.baseColor;
  });
  const {
    backgroundColorClasses,
    backgroundColorStyles
  } = useBackgroundColor(() => {
    return isActive.value && !props.error && !props.disabled ? props.color : props.baseColor;
  });
  const icon = computed(() => props.indeterminate ? props.indeterminateIcon : model.value ? props.trueIcon : props.falseIcon);
  return {
    group,
    densityClasses,
    trueValue,
    falseValue,
    model,
    textColorClasses,
    textColorStyles,
    backgroundColorClasses,
    backgroundColorStyles,
    icon
  };
}
const VSelectionControl = genericComponent()({
  name: 'VSelectionControl',
  directives: {
    vRipple: Ripple
  },
  inheritAttrs: false,
  props: makeVSelectionControlProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    attrs,
    slots
  }) {
    const {
      group,
      densityClasses,
      icon,
      model,
      textColorClasses,
      textColorStyles,
      backgroundColorClasses,
      backgroundColorStyles,
      trueValue
    } = useSelectionControl(props);
    const uid = useId();
    const isFocused = shallowRef(false);
    const isFocusVisible = shallowRef(false);
    const input = ref();
    const id = toRef(() => props.id || `input-${uid}`);
    const isInteractive = toRef(() => !props.disabled && !props.readonly);
    group?.onForceUpdate(() => {
      if (input.value) {
        input.value.checked = model.value;
      }
    });
    function onFocus(e) {
      if (props.disabled) return;
      isFocused.value = true;
      if (matchesSelector(e.target, ':focus-visible') !== false) {
        isFocusVisible.value = true;
      }
    }
    function onBlur() {
      isFocused.value = false;
      isFocusVisible.value = false;
    }
    function onClickLabel(e) {
      e.stopPropagation();
    }
    function onInput(e) {
      if (!isInteractive.value) {
        if (input.value) {
          // model value is not updated when input is not interactive
          // but the internal checked state of the input is still updated,
          // so here its value is restored
          input.value.checked = model.value;
        }
        return;
      }
      if (props.readonly && group) {
        nextTick(() => group.forceUpdate());
      }
      model.value = e.target.checked;
    }
    useRender(() => {
      const label = slots.label ? slots.label({
        label: props.label,
        props: {
          for: id.value
        }
      }) : props.label;
      const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
      const inputNode = createElementVNode("input", mergeProps({
        "ref": input,
        "checked": model.value,
        "disabled": !!props.disabled,
        "id": id.value,
        "onBlur": onBlur,
        "onFocus": onFocus,
        "onInput": onInput,
        "aria-disabled": !!props.disabled,
        "aria-label": props.label,
        "type": props.type,
        "value": trueValue.value,
        "name": props.name,
        "aria-checked": props.type === 'checkbox' ? model.value : undefined
      }, inputAttrs), null);
      return createElementVNode("div", mergeProps({
        "class": ['v-selection-control', {
          'v-selection-control--dirty': model.value,
          'v-selection-control--indeterminate': props.indeterminate,
          'v-selection-control--disabled': props.disabled,
          'v-selection-control--error': props.error,
          'v-selection-control--focused': isFocused.value,
          'v-selection-control--focus-visible': isFocusVisible.value,
          'v-selection-control--inline': props.inline
        }, densityClasses.value, props.class]
      }, rootAttrs, {
        "style": props.style
      }), [createElementVNode("div", {
        "class": normalizeClass(['v-selection-control__wrapper', textColorClasses.value]),
        "style": normalizeStyle(textColorStyles.value)
      }, [slots.default?.({
        backgroundColorClasses,
        backgroundColorStyles
      }), withDirectives(createElementVNode("div", {
        "class": normalizeClass(['v-selection-control__input'])
      }, [slots.input?.({
        model,
        textColorClasses,
        textColorStyles,
        backgroundColorClasses,
        backgroundColorStyles,
        inputNode,
        icon: icon.value,
        props: {
          onFocus,
          onBlur,
          id: id.value
        }
      }) ?? createElementVNode(Fragment, null, [icon.value && createVNode(VIcon, {
        "key": "icon",
        "icon": icon.value
      }, null), inputNode])]), [[Ripple, !props.disabled && !props.readonly && props.ripple, null, {
        center: true,
        circle: true
      }]])]), label && createVNode(VLabel, {
        "for": id.value,
        "onClick": onClickLabel
      }, {
        default: () => [label]
      })]);
    });
    return {
      isFocused,
      input
    };
  }
});

// Types

const makeVCheckboxBtnProps = propsFactory({
  ...makeVSelectionControlProps({
    falseIcon: '$checkboxOff',
    trueIcon: '$checkboxOn',
    indeterminateIcon: '$checkboxIndeterminate'
  })
}, 'VCheckboxBtn');
const 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;
      }
    }
    useRender(() => {
      const controlProps = omit(VSelectionControl.filterProps(props), ['modelValue']);
      return createVNode(VSelectionControl, mergeProps(controlProps, {
        "modelValue": model.value,
        "onUpdate:modelValue": [$event => model.value = $event, onChange],
        "class": ['v-checkbox-btn', props.class],
        "style": props.style,
        "type": "checkbox",
        "aria-checked": indeterminate.value ? 'mixed' : undefined
      }), slots);
    });
    return {};
  }
});

// Types

function useInputIcon(props) {
  const {
    t
  } = useLocale();
  function InputIcon({
    name,
    color,
    ...attrs
  }) {
    const localeKey = {
      prepend: 'prependAction',
      prependInner: 'prependAction',
      append: 'appendAction',
      appendInner: 'appendAction',
      clear: 'clear'
    }[name];
    const listener = props[`onClick:${name}`];
    function onKeydown(e) {
      if (e.key !== 'Enter' && e.key !== ' ') return;
      e.preventDefault();
      e.stopPropagation();
      callEvent(listener, new PointerEvent('click', e));
    }
    const label = listener && localeKey ? t(`$vuetify.input.${localeKey}`, props.label ?? '') : undefined;
    return createVNode(VIcon, mergeProps({
      "icon": props[`${name}Icon`],
      "aria-label": label,
      "onClick": listener,
      "onKeydown": onKeydown,
      "color": color
    }, attrs), null);
  }
  return {
    InputIcon
  };
}

// Types

const makeVMessagesProps = propsFactory({
  active: Boolean,
  color: String,
  messages: {
    type: [Array, String],
    default: () => []
  },
  ...makeComponentProps(),
  ...makeTransitionProps({
    transition: {
      component: VSlideYTransition,
      leaveAbsolute: true,
      group: true
    }
  })
}, 'VMessages');
const VMessages = genericComponent()({
  name: 'VMessages',
  props: makeVMessagesProps(),
  setup(props, {
    slots
  }) {
    const messages = computed(() => wrapInArray(props.messages));
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.color);
    useRender(() => createVNode(MaybeTransition, {
      "transition": props.transition,
      "tag": "div",
      "class": normalizeClass(['v-messages', textColorClasses.value, props.class]),
      "style": normalizeStyle([textColorStyles.value, props.style])
    }, {
      default: () => [props.active && messages.value.map((message, i) => createElementVNode("div", {
        "class": "v-messages__message",
        "key": `${i}-${messages.value}`
      }, [slots.message ? slots.message({
        message
      }) : message]))]
    }));
    return {};
  }
});

// Composables

// Types

// Composables
const makeFocusProps = propsFactory({
  focused: Boolean,
  'onUpdate:focused': EventProp()
}, 'focus');
function useFocus(props, name = getCurrentInstanceName()) {
  const isFocused = useProxiedModel(props, 'focused');
  const focusClasses = toRef(() => {
    return {
      [`${name}--focused`]: isFocused.value
    };
  });
  function focus() {
    isFocused.value = true;
  }
  function blur() {
    isFocused.value = false;
  }
  return {
    focusClasses,
    isFocused,
    focus,
    blur
  };
}

// Composables

// Types

const FormKey = Symbol.for('vuetify:form');
const makeFormProps = propsFactory({
  disabled: Boolean,
  fastFail: Boolean,
  readonly: Boolean,
  modelValue: {
    type: Boolean,
    default: null
  },
  validateOn: {
    type: String,
    default: 'input'
  }
}, 'form');
function createForm(props) {
  const model = useProxiedModel(props, 'modelValue');
  const isDisabled = toRef(() => props.disabled);
  const isReadonly = toRef(() => props.readonly);
  const isValidating = shallowRef(false);
  const items = ref([]);
  const errors = ref([]);
  async function validate() {
    const results = [];
    let valid = true;
    errors.value = [];
    isValidating.value = true;
    for (const item of items.value) {
      const itemErrorMessages = await item.validate();
      if (itemErrorMessages.length > 0) {
        valid = false;
        results.push({
          id: item.id,
          errorMessages: itemErrorMessages
        });
      }
      if (!valid && props.fastFail) break;
    }
    errors.value = results;
    isValidating.value = false;
    return {
      valid,
      errors: errors.value
    };
  }
  function reset() {
    items.value.forEach(item => item.reset());
  }
  function resetValidation() {
    items.value.forEach(item => item.resetValidation());
  }
  watch(items, () => {
    let valid = 0;
    let invalid = 0;
    const results = [];
    for (const item of items.value) {
      if (item.isValid === false) {
        invalid++;
        results.push({
          id: item.id,
          errorMessages: item.errorMessages
        });
      } else if (item.isValid === true) valid++;
    }
    errors.value = results;
    model.value = invalid > 0 ? false : valid === items.value.length ? true : null;
  }, {
    deep: true,
    flush: 'post'
  });
  provide(FormKey, {
    register: ({
      id,
      vm,
      validate,
      reset,
      resetValidation
    }) => {
      if (items.value.some(item => item.id === id)) {
        consoleWarn(`Duplicate input name "${id}"`);
      }
      items.value.push({
        id,
        validate,
        reset,
        resetValidation,
        vm: markRaw(vm),
        isValid: null,
        errorMessages: []
      });
    },
    unregister: id => {
      items.value = items.value.filter(item => {
        return item.id !== id;
      });
    },
    update: (id, isValid, errorMessages) => {
      const found = items.value.find(item => item.id === id);
      if (!found) return;
      found.isValid = isValid;
      found.errorMessages = errorMessages;
    },
    isDisabled,
    isReadonly,
    isValidating,
    isValid: model,
    items,
    validateOn: toRef(() => props.validateOn)
  });
  return {
    errors,
    isDisabled,
    isReadonly,
    isValidating,
    isValid: model,
    items,
    validate,
    reset,
    resetValidation
  };
}
function useForm(props) {
  const form = inject$1(FormKey, null);
  return {
    ...form,
    isReadonly: computed(() => !!(props?.readonly ?? form?.isReadonly.value)),
    isDisabled: computed(() => !!(props?.disabled ?? form?.isDisabled.value))
  };
}

// Utilities
const RulesSymbol = Symbol.for('vuetify:rules');
function useRules(fn) {
  const rules = inject$1(RulesSymbol, null);
  if (!fn) {
    if (!rules) {
      throw new Error('Could not find Vuetify rules injection');
    }
    return rules.aliases;
  }
  return rules?.resolve(fn) ?? toRef(fn);
}

// Composables

// Types

const makeValidationProps = propsFactory({
  disabled: {
    type: Boolean,
    default: null
  },
  error: Boolean,
  errorMessages: {
    type: [Array, String],
    default: () => []
  },
  maxErrors: {
    type: [Number, String],
    default: 1
  },
  name: String,
  label: String,
  readonly: {
    type: Boolean,
    default: null
  },
  rules: {
    type: Array,
    default: () => []
  },
  modelValue: null,
  validateOn: String,
  validationValue: null,
  ...makeFocusProps()
}, 'validation');
function useValidation(props, name = getCurrentInstanceName(), id = useId()) {
  const model = useProxiedModel(props, 'modelValue');
  const validationModel = computed(() => props.validationValue === undefined ? model.value : props.validationValue);
  const form = useForm(props);
  const rules = useRules(() => props.rules);
  const internalErrorMessages = ref([]);
  const isPristine = shallowRef(true);
  const isDirty = computed(() => !!(wrapInArray(model.value === '' ? null : model.value).length || wrapInArray(validationModel.value === '' ? null : validationModel.value).length));
  const errorMessages = computed(() => {
    return props.errorMessages?.length ? wrapInArray(props.errorMessages).concat(internalErrorMessages.value).slice(0, Math.max(0, Number(props.maxErrors))) : internalErrorMessages.value;
  });
  const validateOn = computed(() => {
    let value = (props.validateOn ?? form.validateOn?.value) || 'input';
    if (value === 'lazy') value = 'input lazy';
    if (value === 'eager') value = 'input eager';
    const set = new Set(value?.split(' ') ?? []);
    return {
      input: set.has('input'),
      blur: set.has('blur') || set.has('input') || set.has('invalid-input'),
      invalidInput: set.has('invalid-input'),
      lazy: set.has('lazy'),
      eager: set.has('eager')
    };
  });
  const isValid = computed(() => {
    if (props.error || props.errorMessages?.length) return false;
    if (!props.rules.length) return true;
    if (isPristine.value) {
      return internalErrorMessages.value.length || validateOn.value.lazy ? null : true;
    } else {
      return !internalErrorMessages.value.length;
    }
  });
  const isValidating = shallowRef(false);
  let isResetting = false;
  const validationClasses = computed(() => {
    return {
      [`${name}--error`]: isValid.value === false,
      [`${name}--dirty`]: isDirty.value,
      [`${name}--disabled`]: form.isDisabled.value,
      [`${name}--readonly`]: form.isReadonly.value
    };
  });
  const vm = getCurrentInstance('validation');
  const uid = computed(() => props.name ?? unref(id));
  onBeforeMount(() => {
    form.register?.({
      id: uid.value,
      vm,
      validate,
      reset,
      resetValidation
    });
  });
  onBeforeUnmount(() => {
    form.unregister?.(uid.value);
  });
  onMounted(async () => {
    if (!validateOn.value.lazy) {
      await validate(!validateOn.value.eager);
    }
    form.update?.(uid.value, isValid.value, errorMessages.value);
  });
  useToggleScope(() => validateOn.value.input || validateOn.value.invalidInput && isValid.value === false, () => {
    watch(validationModel, () => {
      if (!isResetting) validate();
    });
  });
  useToggleScope(() => validateOn.value.blur, () => {
    watch(() => props.focused, val => {
      if (!val) validate();
    });
  });
  watch([isValid, errorMessages], () => {
    form.update?.(uid.value, isValid.value, errorMessages.value);
  });
  async function reset() {
    isResetting = true;
    model.value = null;
    await nextTick();
    isResetting = false;
    await resetValidation();
  }
  async function resetValidation() {
    isPristine.value = true;
    if (!validateOn.value.lazy) {
      await validate(!validateOn.value.eager);
    } else {
      internalErrorMessages.value = [];
    }
  }
  async function validate(silent = false) {
    const results = [];
    isValidating.value = true;
    for (const rule of rules.value) {
      if (results.length >= Number(props.maxErrors ?? 1)) {
        break;
      }
      const handler = typeof rule === 'function' ? rule : () => rule;
      const result = await handler(validationModel.value);
      if (result === true) continue;
      if (result !== false && typeof result !== 'string') {
        // eslint-disable-next-line no-console
        console.warn(`${result} is not a valid value. Rule functions must return boolean true or a string.`);
        continue;
      }
      results.push(result || '');
    }
    internalErrorMessages.value = results;
    isValidating.value = false;
    isPristine.value = silent;
    return internalErrorMessages.value;
  }
  return {
    errorMessages,
    isDirty,
    isDisabled: form.isDisabled,
    isReadonly: form.isReadonly,
    isPristine,
    isValid,
    isValidating,
    reset,
    resetValidation,
    validate,
    validationClasses
  };
}

// Types

const makeVInputProps = propsFactory({
  id: String,
  appendIcon: IconValue,
  baseColor: String,
  centerAffix: {
    type: Boolean,
    default: true
  },
  color: String,
  glow: Boolean,
  iconColor: [Boolean, String],
  prependIcon: IconValue,
  hideDetails: [Boolean, String],
  hideSpinButtons: Boolean,
  hint: String,
  indentDetails: {
    type: Boolean,
    default: null
  },
  persistentHint: Boolean,
  messages: {
    type: [Array, String],
    default: () => []
  },
  direction: {
    type: String,
    default: 'horizontal',
    validator: v => ['horizontal', 'vertical'].includes(v)
  },
  'onClick:prepend': EventProp(),
  'onClick:append': EventProp(),
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...pick(makeDimensionProps(), ['maxWidth', 'minWidth', 'width']),
  ...makeThemeProps(),
  ...makeValidationProps()
}, 'VInput');
const VInput = genericComponent()({
  name: 'VInput',
  props: {
    ...makeVInputProps()
  },
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    attrs,
    slots,
    emit
  }) {
    const {
      densityClasses
    } = useDensity(props);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      themeClasses
    } = provideTheme(props);
    const {
      rtlClasses
    } = useRtl();
    const {
      InputIcon
    } = useInputIcon(props);
    const uid = useId();
    const id = computed(() => props.id || `input-${uid}`);
    const {
      errorMessages,
      isDirty,
      isDisabled,
      isReadonly,
      isPristine,
      isValid,
      isValidating,
      reset,
      resetValidation,
      validate,
      validationClasses
    } = useValidation(props, 'v-input', id);
    const messages = computed(() => {
      if (props.errorMessages?.length || !isPristine.value && errorMessages.value.length) {
        return errorMessages.value;
      } else if (props.hint && (props.persistentHint || props.focused)) {
        return props.hint;
      } else {
        return props.messages;
      }
    });
    const hasMessages = toRef(() => messages.value.length > 0);
    const hasDetails = toRef(() => !props.hideDetails || props.hideDetails === 'auto' && (hasMessages.value || !!slots.details));
    const messagesId = computed(() => hasDetails.value ? `${id.value}-messages` : undefined);
    const slotProps = computed(() => ({
      id,
      messagesId,
      isDirty,
      isDisabled,
      isReadonly,
      isPristine,
      isValid,
      isValidating,
      hasDetails,
      reset,
      resetValidation,
      validate
    }));
    const color = toRef(() => {
      return props.error || props.disabled ? undefined : props.focused ? props.color : props.baseColor;
    });
    const iconColor = toRef(() => {
      if (!props.iconColor) return undefined;
      return props.iconColor === true ? color.value : props.iconColor;
    });
    useRender(() => {
      const hasPrepend = !!(slots.prepend || props.prependIcon);
      const hasAppend = !!(slots.append || props.appendIcon);
      return createElementVNode("div", {
        "class": normalizeClass(['v-input', `v-input--${props.direction}`, {
          'v-input--center-affix': props.centerAffix,
          'v-input--focused': props.focused,
          'v-input--glow': props.glow,
          'v-input--hide-spin-buttons': props.hideSpinButtons,
          'v-input--indent-details': props.indentDetails
        }, densityClasses.value, themeClasses.value, rtlClasses.value, validationClasses.value, props.class]),
        "style": normalizeStyle([dimensionStyles.value, props.style])
      }, [hasPrepend && createElementVNode("div", {
        "key": "prepend",
        "class": "v-input__prepend"
      }, [slots.prepend ? slots.prepend(slotProps.value) : props.prependIcon && createVNode(InputIcon, {
        "key": "prepend-icon",
        "name": "prepend",
        "color": iconColor.value
      }, null)]), slots.default && createElementVNode("div", {
        "class": "v-input__control"
      }, [slots.default?.(slotProps.value)]), hasAppend && createElementVNode("div", {
        "key": "append",
        "class": "v-input__append"
      }, [slots.append ? slots.append(slotProps.value) : props.appendIcon && createVNode(InputIcon, {
        "key": "append-icon",
        "name": "append",
        "color": iconColor.value
      }, null)]), hasDetails.value && createElementVNode("div", {
        "id": messagesId.value,
        "class": "v-input__details",
        "role": "alert",
        "aria-live": "polite"
      }, [createVNode(VMessages, {
        "active": hasMessages.value,
        "messages": messages.value
      }, {
        message: slots.message
      }), slots.details?.(slotProps.value)])]);
    });
    return {
      reset,
      resetValidation,
      validate,
      isValid,
      errorMessages
    };
  }
});

// Types

const Refs = Symbol('Forwarded refs');

/** Omit properties starting with P */

/** Omit keyof $props from T */

function getDescriptor(obj, key) {
  let currentObj = obj;
  while (currentObj) {
    const descriptor = Reflect.getOwnPropertyDescriptor(currentObj, key);
    if (descriptor) return descriptor;
    currentObj = Object.getPrototypeOf(currentObj);
  }
  return undefined;
}
function forwardRefs(target, ...refs) {
  target[Refs] = refs;
  return new Proxy(target, {
    get(target, key) {
      if (Reflect.has(target, key)) {
        return Reflect.get(target, key);
      }

      // Skip internal properties
      if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return;
      for (const ref of refs) {
        if (ref.value && Reflect.has(ref.value, key)) {
          const val = Reflect.get(ref.value, key);
          return typeof val === 'function' ? val.bind(ref.value) : val;
        }
      }
    },
    has(target, key) {
      if (Reflect.has(target, key)) {
        return true;
      }

      // Skip internal properties
      if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return false;
      for (const ref of refs) {
        if (ref.value && Reflect.has(ref.value, key)) {
          return true;
        }
      }
      return false;
    },
    set(target, key, value) {
      if (Reflect.has(target, key)) {
        return Reflect.set(target, key, value);
      }

      // Skip internal properties
      if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return false;
      for (const ref of refs) {
        if (ref.value && Reflect.has(ref.value, key)) {
          return Reflect.set(ref.value, key, value);
        }
      }
      return false;
    },
    getOwnPropertyDescriptor(target, key) {
      const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
      if (descriptor) return descriptor;

      // Skip internal properties
      if (typeof key === 'symbol' || key.startsWith('$') || key.startsWith('__')) return;

      // Check each ref's own properties
      for (const ref of refs) {
        if (!ref.value) continue;
        const descriptor = getDescriptor(ref.value, key) ?? ('_' in ref.value ? getDescriptor(ref.value._?.setupState, key) : undefined);
        if (descriptor) return descriptor;
      }

      // Recursive search up each ref's prototype
      for (const ref of refs) {
        const childRefs = ref.value && ref.value[Refs];
        if (!childRefs) continue;
        const queue = childRefs.slice();
        while (queue.length) {
          const ref = queue.shift();
          const descriptor = getDescriptor(ref.value, key);
          if (descriptor) return descriptor;
          const childRefs = ref.value && ref.value[Refs];
          if (childRefs) queue.push(...childRefs);
        }
      }
      return undefined;
    }
  });
}

// Types

const makeVCheckboxProps = propsFactory({
  ...omit(makeVInputProps(), ['direction', 'glow']),
  ...omit(makeVCheckboxBtnProps(), ['inline'])
}, 'VCheckbox');
const VCheckbox = genericComponent()({
  name: 'VCheckbox',
  inheritAttrs: false,
  props: makeVCheckboxProps(),
  emits: {
    'update:modelValue': value => true,
    'update:focused': focused => true
  },
  setup(props, {
    attrs,
    slots
  }) {
    const model = useProxiedModel(props, 'modelValue');
    const {
      isFocused,
      focus,
      blur
    } = useFocus(props);
    const inputRef = ref();
    const uid = useId();
    useRender(() => {
      const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
      const inputProps = VInput.filterProps(props);
      const checkboxProps = VCheckboxBtn.filterProps(props);
      return createVNode(VInput, mergeProps({
        "ref": inputRef,
        "class": ['v-checkbox', props.class]
      }, rootAttrs, inputProps, {
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "id": props.id || `checkbox-${uid}`,
        "focused": isFocused.value,
        "style": props.style
      }), {
        ...slots,
        default: ({
          id,
          messagesId,
          isDisabled,
          isReadonly,
          isValid
        }) => createVNode(VCheckboxBtn, mergeProps(checkboxProps, {
          "id": id.value,
          "aria-describedby": messagesId.value,
          "disabled": isDisabled.value,
          "readonly": isReadonly.value
        }, controlAttrs, {
          "error": isValid.value === false,
          "modelValue": model.value,
          "onUpdate:modelValue": $event => model.value = $event,
          "onFocus": focus,
          "onBlur": blur
        }), slots)
      });
    });
    return forwardRefs({}, inputRef);
  }
});

// Utilities

// Types

const breakpoints = ['sm', 'md', 'lg', 'xl', 'xxl']; // no xs

const DisplaySymbol = Symbol.for('vuetify:display');
const defaultDisplayOptions = {
  mobileBreakpoint: 'lg',
  thresholds: {
    xs: 0,
    sm: 600,
    md: 840,
    lg: 1145,
    xl: 1545,
    xxl: 2138
  }
};
const parseDisplayOptions = (options = defaultDisplayOptions) => {
  return mergeDeep(defaultDisplayOptions, options);
};
function getClientWidth(ssr) {
  return IN_BROWSER && !ssr ? window.innerWidth : typeof ssr === 'object' && ssr.clientWidth || 0;
}
function getClientHeight(ssr) {
  return IN_BROWSER && !ssr ? window.innerHeight : typeof ssr === 'object' && ssr.clientHeight || 0;
}
function getPlatform(ssr) {
  const userAgent = IN_BROWSER && !ssr ? window.navigator.userAgent : 'ssr';
  function match(regexp) {
    return Boolean(userAgent.match(regexp));
  }
  const android = match(/android/i);
  const ios = match(/iphone|ipad|ipod/i);
  const cordova = match(/cordova/i);
  const electron = match(/electron/i);
  const chrome = match(/chrome/i);
  const edge = match(/edge/i);
  const firefox = match(/firefox/i);
  const opera = match(/opera/i);
  const win = match(/win/i);
  const mac = match(/mac/i);
  const linux = match(/linux/i);
  return {
    android,
    ios,
    cordova,
    electron,
    chrome,
    edge,
    firefox,
    opera,
    win,
    mac,
    linux,
    touch: SUPPORTS_TOUCH,
    ssr: userAgent === 'ssr'
  };
}
function createDisplay(options, ssr) {
  const {
    thresholds,
    mobileBreakpoint
  } = parseDisplayOptions(options);
  const height = shallowRef(getClientHeight(ssr));
  const platform = shallowRef(getPlatform(ssr));
  const state = reactive({});
  const width = shallowRef(getClientWidth(ssr));
  function updateSize() {
    height.value = getClientHeight();
    width.value = getClientWidth();
  }
  function update() {
    updateSize();
    platform.value = getPlatform();
  }

  // eslint-disable-next-line max-statements
  watchEffect(() => {
    const xs = width.value < thresholds.sm;
    const sm = width.value < thresholds.md && !xs;
    const md = width.value < thresholds.lg && !(sm || xs);
    const lg = width.value < thresholds.xl && !(md || sm || xs);
    const xl = width.value < thresholds.xxl && !(lg || md || sm || xs);
    const xxl = width.value >= thresholds.xxl;
    const name = xs ? 'xs' : sm ? 'sm' : md ? 'md' : lg ? 'lg' : xl ? 'xl' : 'xxl';
    const breakpointValue = typeof mobileBreakpoint === 'number' ? mobileBreakpoint : thresholds[mobileBreakpoint];
    const mobile = width.value < breakpointValue;
    state.xs = xs;
    state.sm = sm;
    state.md = md;
    state.lg = lg;
    state.xl = xl;
    state.xxl = xxl;
    state.smAndUp = !xs;
    state.mdAndUp = !(xs || sm);
    state.lgAndUp = !(xs || sm || md);
    state.xlAndUp = !(xs || sm || md || lg);
    state.smAndDown = !(md || lg || xl || xxl);
    state.mdAndDown = !(lg || xl || xxl);
    state.lgAndDown = !(xl || xxl);
    state.xlAndDown = !xxl;
    state.name = name;
    state.height = height.value;
    state.width = width.value;
    state.mobile = mobile;
    state.mobileBreakpoint = mobileBreakpoint;
    state.platform = platform.value;
    state.thresholds = thresholds;
  });
  if (IN_BROWSER) {
    window.addEventListener('resize', updateSize, {
      passive: true
    });
    onScopeDispose(() => {
      window.removeEventListener('resize', updateSize);
    }, true);
  }
  return {
    ...toRefs(state),
    update,
    ssr: !!ssr
  };
}
const makeDisplayProps = propsFactory({
  mobile: {
    type: Boolean,
    default: false
  },
  mobileBreakpoint: [Number, String]
}, 'display');
function useDisplay(props = {
  mobile: null
}, name = getCurrentInstanceName()) {
  const display = inject$1(DisplaySymbol);
  if (!display) throw new Error('Could not find Vuetify display injection');
  const mobile = computed(() => {
    if (props.mobile) {
      return true;
    } else if (typeof props.mobileBreakpoint === 'number') {
      return display.width.value < props.mobileBreakpoint;
    } else if (props.mobileBreakpoint) {
      return display.width.value < display.thresholds.value[props.mobileBreakpoint];
    } else if (props.mobile === null) {
      return display.mobile.value;
    } else {
      return false;
    }
  });
  const displayClasses = toRef(() => {
    if (!name) return {};
    return {
      [`${name}--mobile`]: mobile.value
    };
  });
  return {
    ...display,
    displayClasses,
    mobile
  };
}

// Utilities

// Types

const GoToSymbol = Symbol.for('vuetify:goto');
function genDefaults$1() {
  return {
    container: undefined,
    duration: 300,
    layout: false,
    offset: 0,
    easing: 'easeInOutCubic',
    patterns: easingPatterns
  };
}
function getContainer(el) {
  return getTarget$1(el) ?? (document.scrollingElement || document.body);
}
function getTarget$1(el) {
  return typeof el === 'string' ? document.querySelector(el) : refElement(el);
}
function getOffset$2(target, horizontal, rtl) {
  if (typeof target === 'number') return horizontal && rtl ? -target : target;
  let el = getTarget$1(target);
  let totalOffset = 0;
  while (el) {
    totalOffset += horizontal ? el.offsetLeft : el.offsetTop;
    el = el.offsetParent;
  }
  return totalOffset;
}
function createGoTo(options, locale) {
  return {
    rtl: locale.isRtl,
    options: mergeDeep(genDefaults$1(), options)
  };
}
async function scrollTo(_target, _options, horizontal, goTo) {
  const property = horizontal ? 'scrollLeft' : 'scrollTop';
  const options = mergeDeep(goTo?.options ?? genDefaults$1(), _options);
  const rtl = goTo?.rtl.value;
  const target = (typeof _target === 'number' ? _target : getTarget$1(_target)) ?? 0;
  const container = options.container === 'parent' && target instanceof HTMLElement ? target.parentElement : getContainer(options.container);
  const ease = PREFERS_REDUCED_MOTION() ? options.patterns.instant : typeof options.easing === 'function' ? options.easing : options.patterns[options.easing];
  if (!ease) throw new TypeError(`Easing function "${options.easing}" not found.`);
  let targetLocation;
  if (typeof target === 'number') {
    targetLocation = getOffset$2(target, horizontal, rtl);
  } else {
    targetLocation = getOffset$2(target, horizontal, rtl) - getOffset$2(container, horizontal, rtl);
    if (options.layout) {
      const styles = window.getComputedStyle(target);
      const layoutOffset = styles.getPropertyValue('--v-layout-top');
      if (layoutOffset) targetLocation -= parseInt(layoutOffset, 10);
    }
  }
  targetLocation += options.offset;
  targetLocation = clampTarget(container, targetLocation, !!rtl, !!horizontal);
  const startLocation = container[property] ?? 0;
  if (targetLocation === startLocation) return Promise.resolve(targetLocation);
  const startTime = performance.now();
  return new Promise(resolve => requestAnimationFrame(function step(currentTime) {
    const timeElapsed = currentTime - startTime;
    const progress = timeElapsed / options.duration;
    const location = Math.floor(startLocation + (targetLocation - startLocation) * ease(clamp(progress, 0, 1)));
    container[property] = location;

    // Allow for some jitter if target time has elapsed
    if (progress >= 1 && Math.abs(location - container[property]) < 10) {
      return resolve(targetLocation);
    } else if (progress > 2) {
      // The target might not be reachable
      consoleWarn('Scroll target is not reachable');
      return resolve(container[property]);
    }
    requestAnimationFrame(step);
  }));
}
function useGoTo(_options = {}) {
  const goToInstance = inject$1(GoToSymbol);
  const {
    isRtl
  } = useRtl();
  if (!goToInstance) throw new Error('[Vuetify] Could not find injected goto instance');
  const goTo = {
    ...goToInstance,
    // can be set via VLocaleProvider
    rtl: toRef(() => goToInstance.rtl.value || isRtl.value)
  };
  async function go(target, options) {
    return scrollTo(target, mergeDeep(_options, options), false, goTo);
  }
  go.horizontal = async (target, options) => {
    return scrollTo(target, mergeDeep(_options, options), true, goTo);
  };
  return go;
}

/**
 * Clamp target value to achieve a smooth scroll animation
 * when the value goes outside the scroll container size
 */
function clampTarget(container, value, rtl, horizontal) {
  const {
    scrollWidth,
    scrollHeight
  } = container;
  const [containerWidth, containerHeight] = container === document.scrollingElement ? [window.innerWidth, window.innerHeight] : [container.offsetWidth, container.offsetHeight];
  let min;
  let max;
  if (horizontal) {
    if (rtl) {
      min = -(scrollWidth - containerWidth);
      max = 0;
    } else {
      min = 0;
      max = scrollWidth - containerWidth;
    }
  } else {
    min = 0;
    max = scrollHeight + -containerHeight;
  }
  return clamp(value, min, max);
}

function calculateUpdatedTarget({
  selectedElement,
  containerElement,
  isRtl,
  isHorizontal
}) {
  const containerSize = getOffsetSize(isHorizontal, containerElement);
  const scrollPosition = getScrollPosition(isHorizontal, isRtl, containerElement);
  const childrenSize = getOffsetSize(isHorizontal, selectedElement);
  const childrenStartPosition = getOffsetPosition(isHorizontal, selectedElement);
  const additionalOffset = childrenSize * 0.4;
  if (scrollPosition > childrenStartPosition) {
    return childrenStartPosition - additionalOffset;
  } else if (scrollPosition + containerSize < childrenStartPosition + childrenSize) {
    return childrenStartPosition - containerSize + childrenSize + additionalOffset;
  }
  return scrollPosition;
}
function calculateCenteredTarget({
  selectedElement,
  containerElement,
  isHorizontal
}) {
  const containerOffsetSize = getOffsetSize(isHorizontal, containerElement);
  const childrenOffsetPosition = getOffsetPosition(isHorizontal, selectedElement);
  const childrenOffsetSize = getOffsetSize(isHorizontal, selectedElement);
  return childrenOffsetPosition - containerOffsetSize / 2 + childrenOffsetSize / 2;
}
function getScrollSize(isHorizontal, element) {
  const key = isHorizontal ? 'scrollWidth' : 'scrollHeight';
  return element?.[key] || 0;
}
function getScrollPosition(isHorizontal, rtl, element) {
  if (!element) {
    return 0;
  }
  const {
    scrollLeft,
    offsetWidth,
    scrollWidth
  } = element;
  if (isHorizontal) {
    return rtl ? scrollWidth - offsetWidth + scrollLeft : scrollLeft;
  }
  return element.scrollTop;
}
function getOffsetSize(isHorizontal, element) {
  const key = isHorizontal ? 'offsetWidth' : 'offsetHeight';
  return element?.[key] || 0;
}
function getOffsetPosition(isHorizontal, element) {
  const key = isHorizontal ? 'offsetLeft' : 'offsetTop';
  return element?.[key] || 0;
}

// Types

const VSlideGroupSymbol = Symbol.for('vuetify:v-slide-group');
const makeVSlideGroupProps = propsFactory({
  centerActive: Boolean,
  scrollToActive: {
    type: Boolean,
    default: true
  },
  contentClass: null,
  direction: {
    type: String,
    default: 'horizontal'
  },
  symbol: {
    type: null,
    default: VSlideGroupSymbol
  },
  nextIcon: {
    type: IconValue,
    default: '$next'
  },
  prevIcon: {
    type: IconValue,
    default: '$prev'
  },
  showArrows: {
    type: [Boolean, String],
    validator: v => typeof v === 'boolean' || ['always', 'desktop', 'mobile', 'never'].includes(v)
  },
  ...makeComponentProps(),
  ...makeDisplayProps({
    mobile: null
  }),
  ...makeTagProps(),
  ...makeGroupProps({
    selectedClass: 'v-slide-group-item--active'
  })
}, 'VSlideGroup');
const VSlideGroup = genericComponent()({
  name: 'VSlideGroup',
  props: makeVSlideGroupProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const {
      isRtl
    } = useRtl();
    const {
      displayClasses,
      mobile
    } = useDisplay(props);
    const group = useGroup(props, props.symbol);
    const isOverflowing = shallowRef(false);
    const scrollOffset = shallowRef(0);
    const containerSize = shallowRef(0);
    const contentSize = shallowRef(0);
    const isHorizontal = computed(() => props.direction === 'horizontal');
    const {
      resizeRef: containerRef,
      contentRect: containerRect
    } = useResizeObserver();
    const {
      resizeRef: contentRef,
      contentRect
    } = useResizeObserver();
    const goTo = useGoTo();
    const goToOptions = computed(() => {
      return {
        container: containerRef.el,
        duration: 200,
        easing: 'easeOutQuart'
      };
    });
    const firstSelectedIndex = computed(() => {
      if (!group.selected.value.length) return -1;
      return group.items.value.findIndex(item => item.id === group.selected.value[0]);
    });
    const lastSelectedIndex = computed(() => {
      if (!group.selected.value.length) return -1;
      return group.items.value.findIndex(item => item.id === group.selected.value[group.selected.value.length - 1]);
    });
    if (IN_BROWSER) {
      let frame = -1;
      watch(() => [group.selected.value, containerRect.value, contentRect.value, isHorizontal.value], () => {
        cancelAnimationFrame(frame);
        frame = requestAnimationFrame(() => {
          if (containerRect.value && contentRect.value) {
            const sizeProperty = isHorizontal.value ? 'width' : 'height';
            containerSize.value = containerRect.value[sizeProperty];
            contentSize.value = contentRect.value[sizeProperty];
            isOverflowing.value = containerSize.value + 1 < contentSize.value;
          }
          if (props.scrollToActive && firstSelectedIndex.value >= 0 && contentRef.el) {
            // TODO: Is this too naive? Should we store element references in group composable?
            const selectedElement = contentRef.el.children[lastSelectedIndex.value];
            scrollToChildren(selectedElement, props.centerActive);
          }
        });
      });
    }
    const isFocused = shallowRef(false);
    function scrollToChildren(children, center) {
      let target = 0;
      if (center) {
        target = calculateCenteredTarget({
          containerElement: containerRef.el,
          isHorizontal: isHorizontal.value,
          selectedElement: children
        });
      } else {
        target = calculateUpdatedTarget({
          containerElement: containerRef.el,
          isHorizontal: isHorizontal.value,
          isRtl: isRtl.value,
          selectedElement: children
        });
      }
      scrollToPosition(target);
    }
    function scrollToPosition(newPosition) {
      if (!IN_BROWSER || !containerRef.el) return;
      const offsetSize = getOffsetSize(isHorizontal.value, containerRef.el);
      const scrollPosition = getScrollPosition(isHorizontal.value, isRtl.value, containerRef.el);
      const scrollSize = getScrollSize(isHorizontal.value, containerRef.el);
      if (scrollSize <= offsetSize ||
      // Prevent scrolling by only a couple of pixels, which doesn't look smooth
      Math.abs(newPosition - scrollPosition) < 16) return;
      if (isHorizontal.value && isRtl.value && containerRef.el) {
        const {
          scrollWidth,
          offsetWidth: containerWidth
        } = containerRef.el;
        newPosition = scrollWidth - containerWidth - newPosition;
      }
      if (isHorizontal.value) {
        goTo.horizontal(newPosition, goToOptions.value);
      } else {
        goTo(newPosition, goToOptions.value);
      }
    }
    function onScroll(e) {
      const {
        scrollTop,
        scrollLeft
      } = e.target;
      scrollOffset.value = isHorizontal.value ? scrollLeft : scrollTop;
    }
    function onFocusin(e) {
      isFocused.value = true;
      if (!isOverflowing.value || !contentRef.el) return;

      // Focused element is likely to be the root of an item, so a
      // breadth-first search will probably find it in the first iteration
      for (const el of e.composedPath()) {
        for (const item of contentRef.el.children) {
          if (item === el) {
            scrollToChildren(item);
            return;
          }
        }
      }
    }
    function onFocusout(e) {
      isFocused.value = false;
    }

    // Affix clicks produce onFocus that we have to ignore to avoid extra scrollToChildren
    let ignoreFocusEvent = false;
    function onFocus(e) {
      if (!ignoreFocusEvent && !isFocused.value && !(e.relatedTarget && contentRef.el?.contains(e.relatedTarget))) focus();
      ignoreFocusEvent = false;
    }
    function onFocusAffixes() {
      ignoreFocusEvent = true;
    }
    function onKeydown(e) {
      if (!contentRef.el) return;
      function toFocus(location) {
        e.preventDefault();
        focus(location);
      }
      if (isHorizontal.value) {
        if (e.key === 'ArrowRight') {
          toFocus(isRtl.value ? 'prev' : 'next');
        } else if (e.key === 'ArrowLeft') {
          toFocus(isRtl.value ? 'next' : 'prev');
        }
      } else {
        if (e.key === 'ArrowDown') {
          toFocus('next');
        } else if (e.key === 'ArrowUp') {
          toFocus('prev');
        }
      }
      if (e.key === 'Home') {
        toFocus('first');
      } else if (e.key === 'End') {
        toFocus('last');
      }
    }
    function getSiblingElement(el, location) {
      if (!el) return undefined;
      let sibling = el;
      do {
        sibling = sibling?.[location === 'next' ? 'nextElementSibling' : 'previousElementSibling'];
      } while (sibling?.hasAttribute('disabled'));
      return sibling;
    }
    function focus(location) {
      if (!contentRef.el) return;
      let el;
      if (!location) {
        const focusable = focusableChildren(contentRef.el);
        el = focusable[0];
      } else if (location === 'next') {
        el = getSiblingElement(contentRef.el.querySelector(':focus'), location);
        if (!el) return focus('first');
      } else if (location === 'prev') {
        el = getSiblingElement(contentRef.el.querySelector(':focus'), location);
        if (!el) return focus('last');
      } else if (location === 'first') {
        el = contentRef.el.firstElementChild;
        if (el?.hasAttribute('disabled')) el = getSiblingElement(el, 'next');
      } else if (location === 'last') {
        el = contentRef.el.lastElementChild;
        if (el?.hasAttribute('disabled')) el = getSiblingElement(el, 'prev');
      }
      if (el) {
        el.focus({
          preventScroll: true
        });
      }
    }
    function scrollTo(location) {
      const direction = isHorizontal.value && isRtl.value ? -1 : 1;
      const offsetStep = (location === 'prev' ? -direction : direction) * containerSize.value;
      let newPosition = scrollOffset.value + offsetStep;

      // TODO: improve it
      if (isHorizontal.value && isRtl.value && containerRef.el) {
        const {
          scrollWidth,
          offsetWidth: containerWidth
        } = containerRef.el;
        newPosition += scrollWidth - containerWidth;
      }
      scrollToPosition(newPosition);
    }
    const slotProps = computed(() => ({
      next: group.next,
      prev: group.prev,
      select: group.select,
      isSelected: group.isSelected
    }));
    const hasOverflowOrScroll = computed(() => isOverflowing.value || Math.abs(scrollOffset.value) > 0);
    const hasAffixes = computed(() => {
      switch (props.showArrows) {
        case 'never':
          return false;

        // Always show arrows on desktop & mobile
        case 'always':
          return true;

        // Always show arrows on desktop
        case 'desktop':
          return !mobile.value;

        // Show arrows on mobile when overflowing.
        // This matches the default 2.2 behavior
        case true:
          return hasOverflowOrScroll.value;

        // Always show on mobile
        case 'mobile':
          return mobile.value || hasOverflowOrScroll.value;

        // https://material.io/components/tabs#scrollable-tabs
        // Always show arrows when
        // overflowed on desktop
        default:
          return !mobile.value && hasOverflowOrScroll.value;
      }
    });
    const hasPrev = computed(() => {
      // 1 pixel in reserve, may be lost after rounding
      return Math.abs(scrollOffset.value) > 1;
    });
    const hasNext = computed(() => {
      if (!hasOverflowOrScroll.value) return false;
      const scrollSizeMax = contentSize.value - containerSize.value;

      // 1 pixel in reserve, may be lost after rounding
      return scrollSizeMax - Math.abs(scrollOffset.value) > 1;
    });
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-slide-group', {
        'v-slide-group--vertical': !isHorizontal.value,
        'v-slide-group--has-affixes': hasAffixes.value,
        'v-slide-group--is-overflowing': isOverflowing.value
      }, displayClasses.value, props.class]),
      "style": normalizeStyle(props.style),
      "tabindex": isFocused.value || group.selected.value.length ? -1 : 0,
      "onFocus": onFocus
    }, {
      default: () => [hasAffixes.value && createElementVNode("div", {
        "key": "prev",
        "class": normalizeClass(['v-slide-group__prev', {
          'v-slide-group__prev--disabled': !hasPrev.value
        }]),
        "onMousedown": onFocusAffixes,
        "onClick": () => hasPrev.value && scrollTo('prev')
      }, [slots.prev?.(slotProps.value) ?? createVNode(VFadeTransition, null, {
        default: () => [createVNode(VIcon, {
          "icon": isRtl.value ? props.nextIcon : props.prevIcon
        }, null)]
      })]), createElementVNode("div", {
        "key": "container",
        "ref": containerRef,
        "class": normalizeClass(['v-slide-group__container', props.contentClass]),
        "onScroll": onScroll
      }, [createElementVNode("div", {
        "ref": contentRef,
        "class": "v-slide-group__content",
        "onFocusin": onFocusin,
        "onFocusout": onFocusout,
        "onKeydown": onKeydown
      }, [slots.default?.(slotProps.value)])]), hasAffixes.value && createElementVNode("div", {
        "key": "next",
        "class": normalizeClass(['v-slide-group__next', {
          'v-slide-group__next--disabled': !hasNext.value
        }]),
        "onMousedown": onFocusAffixes,
        "onClick": () => hasNext.value && scrollTo('next')
      }, [slots.next?.(slotProps.value) ?? createVNode(VFadeTransition, null, {
        default: () => [createVNode(VIcon, {
          "icon": isRtl.value ? props.prevIcon : props.nextIcon
        }, null)]
      })])]
    }));
    return {
      selected: group.selected,
      scrollTo,
      scrollOffset,
      focus,
      hasPrev,
      hasNext
    };
  }
});

// Types

const VChipGroupSymbol = Symbol.for('vuetify:v-chip-group');
const 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');
const 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(() => {
      const slideGroupProps = VSlideGroup.filterProps(props);
      return createVNode(VSlideGroup, mergeProps(slideGroupProps, {
        "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 {};
  }
});

// Types

const 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: undefined
  },
  pill: Boolean,
  prependAvatar: String,
  prependIcon: IconValue,
  ripple: {
    type: [Boolean, Object],
    default: true
  },
  text: {
    type: [String, Number, Boolean],
    default: undefined
  },
  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');
const 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,
      roundedStyles
    } = 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(() => {
      const showColor = !group || group.isSelected.value;
      return {
        color: showColor ? 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, roundedStyles.value, props.style],
        "disabled": props.disabled || undefined,
        "draggable": props.draggable,
        "tabindex": isClickable.value ? 0 : undefined,
        "onClick": (isClickable.value || props.onClick || props.onClickOnce) && onClick,
        "onKeydown": isClickable.value && !isLink.value && onKeyDown
      }), {
        default: () => [genOverlays(isClickable.value, 'v-chip'), hasFilter && createVNode(VExpandXTransition, {
          "key": "filter"
        }, {
          default: () => [withDirectives(createElementVNode("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 && createElementVNode("div", {
          "key": "prepend",
          "class": "v-chip__prepend"
        }, [!slots.prepend ? createElementVNode(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)]), createElementVNode("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 && createElementVNode("div", {
          "key": "append",
          "class": "v-chip__append"
        }, [!slots.append ? createElementVNode(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 && createElementVNode("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]]);
    };
  }
});

// Types

const allowedVariants$4 = ['dotted', 'dashed', 'solid', 'double'];
const makeVDividerProps = propsFactory({
  color: String,
  contentOffset: [Number, String, Array],
  gradient: Boolean,
  inset: Boolean,
  length: [Number, String],
  opacity: [Number, String],
  thickness: [Number, String],
  vertical: Boolean,
  variant: {
    type: String,
    default: 'solid',
    validator: v => allowedVariants$4.includes(v)
  },
  ...makeComponentProps(),
  ...makeThemeProps()
}, 'VDivider');
const VDivider = genericComponent()({
  name: 'VDivider',
  props: makeVDividerProps(),
  setup(props, {
    attrs,
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.color);
    const dividerStyles = computed(() => {
      const styles = {};
      if (props.length) {
        styles[props.vertical ? 'height' : 'width'] = convertToUnit(props.length);
      }
      if (props.thickness) {
        styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
      }
      return styles;
    });
    const contentStyles = toRef(() => {
      const margin = Array.isArray(props.contentOffset) ? props.contentOffset[0] : props.contentOffset;
      const shift = Array.isArray(props.contentOffset) ? props.contentOffset[1] : 0;
      return {
        marginBlock: props.vertical && margin ? convertToUnit(margin) : undefined,
        marginInline: !props.vertical && margin ? convertToUnit(margin) : undefined,
        transform: shift ? `translate${props.vertical ? 'X' : 'Y'}(${convertToUnit(shift)})` : undefined
      };
    });
    useRender(() => {
      const role = attrs.role;
      const hasSlot = !!slots.default;
      const divider = createElementVNode("hr", {
        "class": normalizeClass([{
          'v-divider': true,
          'v-divider--gradient': props.gradient && !slots.default,
          'v-divider--inset': props.inset,
          'v-divider--vertical': props.vertical
        }, themeClasses.value, textColorClasses.value, props.class]),
        "style": normalizeStyle([dividerStyles.value, textColorStyles.value, {
          '--v-border-opacity': props.opacity
        }, {
          'border-style': props.variant
        }, props.style]),
        "aria-orientation": !hasSlot && !role ? props.vertical ? 'vertical' : 'horizontal' : undefined,
        "role": !hasSlot ? role : undefined
      }, null);
      if (!hasSlot) return divider;
      return createElementVNode("div", {
        "class": normalizeClass(['v-divider__wrapper', {
          'v-divider__wrapper--gradient': props.gradient,
          'v-divider__wrapper--inset': props.inset,
          'v-divider__wrapper--vertical': props.vertical
        }])
      }, [divider, createElementVNode("div", {
        "class": "v-divider__content",
        "style": normalizeStyle(contentStyles.value)
      }, [slots.default()]), divider]);
    });
    return {};
  }
});

// Utilities

// List
const ListKey = Symbol.for('vuetify:list');
function createList(options = {
  filterable: false
}) {
  const parent = inject$1(ListKey, {
    filterable: false,
    hasPrepend: shallowRef(false),
    updateHasPrepend: () => null,
    trackingIndex: shallowRef(-1),
    navigationStrategy: shallowRef('focus'),
    uid: ''
  });
  const {
    filterable,
    trackingIndex = parent.trackingIndex,
    navigationStrategy = parent.navigationStrategy,
    uid = parent.uid || useId()
  } = options;
  const data = {
    filterable: parent.filterable || filterable,
    hasPrepend: shallowRef(false),
    updateHasPrepend: value => {
      if (value) data.hasPrepend.value = value;
    },
    trackingIndex,
    navigationStrategy,
    uid
  };
  provide(ListKey, data);
  return parent;
}
function useList() {
  return inject$1(ListKey, null);
}

/* eslint-disable sonarjs/no-identical-functions */
// Utilities
const independentActiveStrategy = mandatory => {
  const strategy = {
    activate: ({
      id,
      value,
      activated
    }) => {
      id = toRaw(id);

      // When mandatory and we're trying to deselect when id
      // is the only currently selected item then do nothing
      if (mandatory && !value && activated.size === 1 && activated.has(id)) return activated;
      if (value) {
        activated.add(id);
      } else {
        activated.delete(id);
      }
      return activated;
    },
    in: (v, children, parents) => {
      let set = new Set();
      if (v != null) {
        for (const id of wrapInArray(v)) {
          set = strategy.activate({
            id,
            value: true,
            activated: new Set(set),
            children,
            parents
          });
        }
      }
      return set;
    },
    out: v => {
      return Array.from(v);
    }
  };
  return strategy;
};
const independentSingleActiveStrategy = mandatory => {
  const parentStrategy = independentActiveStrategy(mandatory);
  const strategy = {
    activate: ({
      activated,
      id,
      ...rest
    }) => {
      id = toRaw(id);
      const singleSelected = activated.has(id) ? new Set([id]) : new Set();
      return parentStrategy.activate({
        ...rest,
        id,
        activated: singleSelected
      });
    },
    in: (v, children, parents) => {
      let set = new Set();
      if (v != null) {
        const arr = wrapInArray(v);
        if (arr.length) {
          set = parentStrategy.in(arr.slice(0, 1), children, parents);
        }
      }
      return set;
    },
    out: (v, children, parents) => {
      return parentStrategy.out(v, children, parents);
    }
  };
  return strategy;
};
const leafActiveStrategy = mandatory => {
  const parentStrategy = independentActiveStrategy(mandatory);
  const strategy = {
    activate: ({
      id,
      activated,
      children,
      ...rest
    }) => {
      id = toRaw(id);
      if (children.has(id)) return activated;
      return parentStrategy.activate({
        id,
        activated,
        children,
        ...rest
      });
    },
    in: parentStrategy.in,
    out: parentStrategy.out
  };
  return strategy;
};
const leafSingleActiveStrategy = mandatory => {
  const parentStrategy = independentSingleActiveStrategy(mandatory);
  const strategy = {
    activate: ({
      id,
      activated,
      children,
      ...rest
    }) => {
      id = toRaw(id);
      if (children.has(id)) return activated;
      return parentStrategy.activate({
        id,
        activated,
        children,
        ...rest
      });
    },
    in: parentStrategy.in,
    out: parentStrategy.out
  };
  return strategy;
};

const singleOpenStrategy = {
  open: ({
    id,
    value,
    opened,
    parents
  }) => {
    if (value) {
      const newOpened = new Set();
      newOpened.add(id);
      let parent = parents.get(id);
      while (parent != null) {
        newOpened.add(parent);
        parent = parents.get(parent);
      }
      return newOpened;
    } else {
      opened.delete(id);
      return opened;
    }
  },
  select: () => null
};
const multipleOpenStrategy = {
  open: ({
    id,
    value,
    opened,
    parents
  }) => {
    if (value) {
      let parent = parents.get(id);
      opened.add(id);
      while (parent != null && parent !== id) {
        opened.add(parent);
        parent = parents.get(parent);
      }
      return opened;
    } else {
      opened.delete(id);
    }
    return opened;
  },
  select: () => null
};
const listOpenStrategy = {
  open: multipleOpenStrategy.open,
  select: ({
    id,
    value,
    opened,
    parents
  }) => {
    if (!value) return opened;
    const path = [];
    let parent = parents.get(id);
    while (parent != null) {
      path.push(parent);
      parent = parents.get(parent);
    }
    return new Set(path);
  }
};

/* eslint-disable sonarjs/no-identical-functions */
// Utilities
const independentSelectStrategy = mandatory => {
  const strategy = {
    select: ({
      id,
      value,
      selected
    }) => {
      id = toRaw(id);

      // When mandatory and we're trying to deselect when id
      // is the only currently selected item then do nothing
      if (mandatory && !value) {
        const on = Array.from(selected.entries()).reduce((arr, [key, value]) => {
          if (value === 'on') arr.push(key);
          return arr;
        }, []);
        if (on.length === 1 && on[0] === id) return selected;
      }
      selected.set(id, value ? 'on' : 'off');
      return selected;
    },
    in: (v, children, parents, disabled) => {
      const map = new Map();
      for (const id of v || []) {
        strategy.select({
          id,
          value: true,
          selected: map,
          children,
          parents,
          disabled
        });
      }
      return map;
    },
    out: v => {
      const arr = [];
      for (const [key, value] of v.entries()) {
        if (value === 'on') arr.push(key);
      }
      return arr;
    }
  };
  return strategy;
};
const independentSingleSelectStrategy = mandatory => {
  const parentStrategy = independentSelectStrategy(mandatory);
  const strategy = {
    select: ({
      selected,
      id,
      ...rest
    }) => {
      id = toRaw(id);
      const singleSelected = selected.has(id) ? new Map([[id, selected.get(id)]]) : new Map();
      return parentStrategy.select({
        ...rest,
        id,
        selected: singleSelected
      });
    },
    in: (v, children, parents, disabled) => {
      if (v?.length) {
        return parentStrategy.in(v.slice(0, 1), children, parents, disabled);
      }
      return new Map();
    },
    out: (v, children, parents) => {
      return parentStrategy.out(v, children, parents);
    }
  };
  return strategy;
};
const leafSelectStrategy = mandatory => {
  const parentStrategy = independentSelectStrategy(mandatory);
  const strategy = {
    select: ({
      id,
      selected,
      children,
      ...rest
    }) => {
      id = toRaw(id);
      if (children.has(id)) return selected;
      return parentStrategy.select({
        id,
        selected,
        children,
        ...rest
      });
    },
    in: parentStrategy.in,
    out: parentStrategy.out
  };
  return strategy;
};
const leafSingleSelectStrategy = mandatory => {
  const parentStrategy = independentSingleSelectStrategy(mandatory);
  const strategy = {
    select: ({
      id,
      selected,
      children,
      ...rest
    }) => {
      id = toRaw(id);
      if (children.has(id)) return selected;
      return parentStrategy.select({
        id,
        selected,
        children,
        ...rest
      });
    },
    in: parentStrategy.in,
    out: parentStrategy.out
  };
  return strategy;
};
const classicSelectStrategy = mandatory => {
  const strategy = {
    select: ({
      id,
      value,
      selected,
      children,
      parents,
      disabled
    }) => {
      id = toRaw(id);
      const original = new Map(selected);
      const items = [id];
      while (items.length) {
        const item = items.shift();
        if (!disabled.has(item)) {
          selected.set(toRaw(item), value ? 'on' : 'off');
        }
        if (children.has(item)) {
          items.push(...children.get(item));
        }
      }
      let parent = toRaw(parents.get(id));
      while (parent) {
        let everySelected = true;
        let noneSelected = true;
        for (const child of children.get(parent)) {
          const cid = toRaw(child);
          if (disabled.has(cid)) continue;
          if (selected.get(cid) !== 'on') everySelected = false;
          if (selected.has(cid) && selected.get(cid) !== 'off') noneSelected = false;
          if (!everySelected && !noneSelected) break;
        }
        selected.set(parent, everySelected ? 'on' : noneSelected ? 'off' : 'indeterminate');
        parent = toRaw(parents.get(parent));
      }

      // If mandatory and planned deselect results in no selected
      // items then we can't do it, so return original state
      if (mandatory && !value) {
        const on = Array.from(selected.entries()).reduce((arr, [key, value]) => {
          if (value === 'on') arr.push(key);
          return arr;
        }, []);
        if (on.length === 0) return original;
      }
      return selected;
    },
    in: (v, children, parents) => {
      let map = new Map();
      for (const id of v || []) {
        map = strategy.select({
          id,
          value: true,
          selected: map,
          children,
          parents,
          disabled: new Set()
        });
      }
      return map;
    },
    out: (v, children) => {
      const arr = [];
      for (const [key, value] of v.entries()) {
        if (value === 'on' && !children.has(key)) arr.push(key);
      }
      return arr;
    }
  };
  return strategy;
};
const trunkSelectStrategy = mandatory => {
  const parentStrategy = classicSelectStrategy(mandatory);
  const strategy = {
    select: parentStrategy.select,
    in: parentStrategy.in,
    out: (v, children, parents) => {
      const arr = [];
      for (const [key, value] of v.entries()) {
        if (value === 'on') {
          if (parents.has(key)) {
            const parent = parents.get(key);
            if (v.get(parent) === 'on') continue;
          }
          arr.push(key);
        }
      }
      return arr;
    }
  };
  return strategy;
};
const branchSelectStrategy = mandatory => {
  const parentStrategy = classicSelectStrategy(mandatory);
  const strategy = {
    select: parentStrategy.select,
    in: (v, children, parents, disabled) => {
      let map = new Map();
      for (const id of v || []) {
        if (children.has(id)) continue;
        map = strategy.select({
          id,
          value: true,
          selected: map,
          children,
          parents,
          disabled
        });
      }
      return map;
    },
    out: v => {
      const arr = [];
      for (const [key, value] of v.entries()) {
        if (value === 'on' || value === 'indeterminate') {
          arr.push(key);
        }
      }
      return arr;
    }
  };
  return strategy;
};

// Composables

// Types

const VNestedSymbol = Symbol.for('vuetify:nested');
const emptyNested = {
  id: shallowRef(),
  root: {
    itemsRegistration: ref('render'),
    register: () => null,
    unregister: () => null,
    updateDisabled: () => null,
    children: ref(new Map()),
    parents: ref(new Map()),
    disabled: ref(new Set()),
    open: () => null,
    openOnSelect: () => null,
    activate: () => null,
    select: () => null,
    activatable: ref(false),
    scrollToActive: ref(false),
    selectable: ref(false),
    opened: ref(new Set()),
    activated: ref(new Set()),
    selected: ref(new Map()),
    selectedValues: ref([]),
    getPath: () => []
  }
};
const makeNestedProps = propsFactory({
  activatable: Boolean,
  selectable: Boolean,
  activeStrategy: [String, Function, Object],
  selectStrategy: [String, Function, Object],
  openStrategy: [String, Object],
  opened: null,
  activated: null,
  selected: null,
  mandatory: Boolean,
  itemsRegistration: {
    type: String,
    default: 'render'
  }
}, 'nested');
const useNested = (props, {
  items,
  returnObject,
  scrollToActive,
  valueComparator
}) => {
  let isUnmounted = false;
  const children = shallowRef(new Map());
  const parents = shallowRef(new Map());
  const disabled = shallowRef(new Set());
  const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(Array.isArray(v) ? v.map(i => toRaw(i)) : v), v => [...v.values()]);
  const activeStrategy = computed(() => {
    if (typeof props.activeStrategy === 'object') return props.activeStrategy;
    if (typeof props.activeStrategy === 'function') return props.activeStrategy(props.mandatory);
    switch (props.activeStrategy) {
      case 'leaf':
        return leafActiveStrategy(props.mandatory);
      case 'single-leaf':
        return leafSingleActiveStrategy(props.mandatory);
      case 'independent':
        return independentActiveStrategy(props.mandatory);
      case 'single-independent':
      default:
        return independentSingleActiveStrategy(props.mandatory);
    }
  });
  const selectStrategy = computed(() => {
    if (typeof props.selectStrategy === 'object') return props.selectStrategy;
    if (typeof props.selectStrategy === 'function') return props.selectStrategy(props.mandatory);
    switch (props.selectStrategy) {
      case 'single-leaf':
        return leafSingleSelectStrategy(props.mandatory);
      case 'leaf':
        return leafSelectStrategy(props.mandatory);
      case 'independent':
        return independentSelectStrategy(props.mandatory);
      case 'single-independent':
        return independentSingleSelectStrategy(props.mandatory);
      case 'trunk':
        return trunkSelectStrategy(props.mandatory);
      case 'branch':
        return branchSelectStrategy(props.mandatory);
      case 'classic':
      default:
        return classicSelectStrategy(props.mandatory);
    }
  });
  const openStrategy = computed(() => {
    if (typeof props.openStrategy === 'object') return props.openStrategy;
    switch (props.openStrategy) {
      case 'list':
        return listOpenStrategy;
      case 'single':
        return singleOpenStrategy;
      case 'multiple':
      default:
        return multipleOpenStrategy;
    }
  });
  const flatItems = computed(() => {
    const flat = [];
    const stack = [...items.value];
    while (stack.length) {
      const item = stack.pop();
      flat.push(item);
      if (item.children) stack.push(...item.children);
    }
    return flat;
  });
  function resolveValue(value) {
    const comparator = toValue(valueComparator);
    if (!comparator) return value;
    const _returnObject = toValue(returnObject);
    for (const item of flatItems.value) {
      const itemVal = _returnObject ? toRaw(item.raw) : item.value;
      if (comparator(value, itemVal)) return itemVal;
    }
    return value;
  }
  const activated = useProxiedModel(props, 'activated', props.activated, v => activeStrategy.value.in(Array.isArray(v) ? v.map(resolveValue) : v, children.value, parents.value), v => activeStrategy.value.out(v, children.value, parents.value));
  const selected = useProxiedModel(props, 'selected', props.selected, v => selectStrategy.value.in(Array.isArray(v) ? v.map(resolveValue) : v, children.value, parents.value, disabled.value), v => selectStrategy.value.out(v, children.value, parents.value));
  onBeforeUnmount(() => {
    isUnmounted = true;
  });
  function getPath(id) {
    const path = [];
    let parent = toRaw(id);
    while (parent !== undefined) {
      path.unshift(parent);
      parent = parents.value.get(parent);
    }
    return path;
  }
  const vm = getCurrentInstance('nested');
  const nodeIds = new Set();
  const itemsUpdatePropagation = throttle(() => {
    nextTick(() => {
      children.value = new Map(children.value);
      parents.value = new Map(parents.value);
    });
  }, 100);
  watch(() => [items.value, toValue(returnObject)], () => {
    if (props.itemsRegistration === 'props') {
      updateInternalMaps();
    }
  }, {
    immediate: true
  });
  function updateInternalMaps() {
    const _parents = new Map();
    const _children = new Map();
    const _disabled = new Set();
    const getValue = toValue(returnObject) ? item => toRaw(item.raw) : item => item.value;
    const stack = [...items.value];
    let i = 0;
    while (i < stack.length) {
      const item = stack[i++];
      const itemValue = getValue(item);
      if (item.children) {
        const childValues = [];
        for (const child of item.children) {
          const childValue = getValue(child);
          _parents.set(childValue, itemValue);
          childValues.push(childValue);
          stack.push(child);
        }
        _children.set(itemValue, childValues);
      }
      if (item.props.disabled) {
        _disabled.add(itemValue);
      }
    }
    children.value = _children;
    parents.value = _parents;
    disabled.value = _disabled;
  }
  const nested = {
    id: shallowRef(),
    root: {
      opened,
      activatable: toRef(() => props.activatable),
      scrollToActive: toRef(() => toValue(scrollToActive)),
      selectable: toRef(() => props.selectable),
      activated,
      selected,
      selectedValues: computed(() => {
        const arr = [];
        for (const [key, value] of selected.value.entries()) {
          if (value === 'on') arr.push(key);
        }
        return arr;
      }),
      itemsRegistration: toRef(() => props.itemsRegistration),
      register: (id, parentId, isDisabled, isGroup) => {
        if (nodeIds.has(id)) {
          const path = getPath(id).map(String).join(' -> ');
          const newPath = getPath(parentId).concat(id).map(String).join(' -> ');
          consoleError(`Multiple nodes with the same ID\n\t${path}\n\t${newPath}`);
          return;
        } else {
          nodeIds.add(id);
        }
        parentId && id !== parentId && parents.value.set(id, parentId);
        isDisabled && disabled.value.add(id);
        isGroup && children.value.set(id, []);
        if (parentId != null) {
          children.value.set(parentId, [...(children.value.get(parentId) || []), id]);
        }
        itemsUpdatePropagation();
      },
      unregister: id => {
        if (isUnmounted) return;
        nodeIds.delete(id);
        children.value.delete(id);
        disabled.value.delete(id);
        const parent = parents.value.get(id);
        if (parent) {
          const list = children.value.get(parent) ?? [];
          children.value.set(parent, list.filter(child => child !== id));
        }
        parents.value.delete(id);
        itemsUpdatePropagation();
      },
      updateDisabled: (id, isDisabled) => {
        if (isDisabled) {
          disabled.value.add(id);
        } else {
          disabled.value.delete(id);
        }
        // classic selection requires refresh to re-evaluate on/off/indeterminate but
        // currently it is only run for selection interactions, so it will set new disabled
        // to "off" and the visual state becomes out of sync
        // -- selected.value = new Map(selected.value)
        // it is not clear if the framework should un-select when disabled changed to true
        // more discussion is needed
      },
      open: (id, value, event) => {
        vm.emit('click:open', {
          id,
          value,
          path: getPath(id),
          event
        });
        const newOpened = openStrategy.value.open({
          id,
          value,
          opened: new Set(opened.value),
          children: children.value,
          parents: parents.value,
          event
        });
        newOpened && (opened.value = newOpened);
      },
      openOnSelect: (id, value, event) => {
        const newOpened = openStrategy.value.select({
          id,
          value,
          selected: new Map(selected.value),
          opened: new Set(opened.value),
          children: children.value,
          parents: parents.value,
          event
        });
        newOpened && (opened.value = newOpened);
      },
      select: (id, value, event) => {
        vm.emit('click:select', {
          id,
          value,
          path: getPath(id),
          event
        });
        const newSelected = selectStrategy.value.select({
          id,
          value,
          selected: new Map(selected.value),
          children: children.value,
          parents: parents.value,
          disabled: disabled.value,
          event
        });
        newSelected && (selected.value = newSelected);
        nested.root.openOnSelect(id, value, event);
      },
      activate: (id, value, event) => {
        if (!props.activatable) {
          return nested.root.select(id, true, event);
        }
        vm.emit('click:activate', {
          id,
          value,
          path: getPath(id),
          event
        });
        const newActivated = activeStrategy.value.activate({
          id,
          value,
          activated: new Set(activated.value),
          children: children.value,
          parents: parents.value,
          event
        });
        if (newActivated.size !== activated.value.size) {
          activated.value = newActivated;
        } else {
          for (const value of newActivated) {
            if (!activated.value.has(value)) {
              activated.value = newActivated;
              return;
            }
          }
          for (const value of activated.value) {
            if (!newActivated.has(value)) {
              activated.value = newActivated;
              return;
            }
          }
        }
      },
      children,
      parents,
      disabled,
      getPath
    }
  };
  provide(VNestedSymbol, nested);
  return nested.root;
};
const useNestedItem = (id, isDisabled, isGroup) => {
  const parent = inject$1(VNestedSymbol, emptyNested);
  const uidSymbol = Symbol('nested item');
  const computedId = computed(() => {
    const idValue = toRaw(toValue(id));
    return idValue !== undefined ? idValue : uidSymbol;
  });
  const item = {
    ...parent,
    id: computedId,
    open: (open, e) => parent.root.open(computedId.value, open, e),
    openOnSelect: (open, e) => parent.root.openOnSelect(computedId.value, open, e),
    isOpen: computed(() => parent.root.opened.value.has(computedId.value)),
    parent: computed(() => parent.root.parents.value.get(computedId.value)),
    activate: (activated, e) => parent.root.activate(computedId.value, activated, e),
    isActivated: computed(() => parent.root.activated.value.has(computedId.value)),
    scrollToActive: parent.root.scrollToActive,
    select: (selected, e) => parent.root.select(computedId.value, selected, e),
    isSelected: computed(() => parent.root.selected.value.get(computedId.value) === 'on'),
    isIndeterminate: computed(() => parent.root.selected.value.get(computedId.value) === 'indeterminate'),
    isLeaf: computed(() => !parent.root.children.value.get(computedId.value)),
    isGroupActivator: parent.isGroupActivator
  };
  onBeforeMount(() => {
    if (parent.isGroupActivator || parent.root.itemsRegistration.value === 'props') return;
    nextTick(() => {
      parent.root.register(computedId.value, parent.id.value, toValue(isDisabled), isGroup);
    });
  });
  onBeforeUnmount(() => {
    if (parent.isGroupActivator || parent.root.itemsRegistration.value === 'props') return;
    parent.root.unregister(computedId.value);
  });
  watch(computedId, (val, oldVal) => {
    if (parent.isGroupActivator || parent.root.itemsRegistration.value === 'props') return;
    parent.root.unregister(oldVal);
    nextTick(() => {
      parent.root.register(val, parent.id.value, toValue(isDisabled), isGroup);
    });
  });
  watch(() => toValue(isDisabled), val => {
    parent.root.updateDisabled(computedId.value, val);
  });
  isGroup && provide(VNestedSymbol, item);
  return item;
};
const useNestedGroupActivator = () => {
  const parent = inject$1(VNestedSymbol, emptyNested);
  provide(VNestedSymbol, {
    ...parent,
    isGroupActivator: true
  });
};

const VListGroupActivator = defineComponent({
  name: 'VListGroupActivator',
  setup(_, {
    slots
  }) {
    useNestedGroupActivator();
    return () => slots.default?.();
  }
});
const makeVListGroupProps = propsFactory({
  /* @deprecated */
  activeColor: String,
  baseColor: String,
  color: String,
  collapseIcon: {
    type: IconValue,
    default: '$collapse'
  },
  disabled: Boolean,
  expandIcon: {
    type: IconValue,
    default: '$expand'
  },
  rawId: [String, Number],
  prependIcon: IconValue,
  appendIcon: IconValue,
  fluid: Boolean,
  subgroup: Boolean,
  title: String,
  value: null,
  ...makeComponentProps(),
  ...makeTagProps()
}, 'VListGroup');
const VListGroup = genericComponent()({
  name: 'VListGroup',
  props: makeVListGroupProps(),
  setup(props, {
    slots
  }) {
    const {
      isOpen,
      open,
      id: _id
    } = useNestedItem(() => props.value, () => props.disabled, true);
    const id = computed(() => `v-list-group--id-${String(props.rawId ?? _id.value)}`);
    const list = useList();
    const {
      isBooted
    } = useSsrBoot();
    const parent = inject$1(VNestedSymbol);
    const renderWhenClosed = toRef(() => parent?.root?.itemsRegistration.value === 'render');
    function onClick(e) {
      if (['INPUT', 'TEXTAREA'].includes(e.target?.tagName)) return;
      open(!isOpen.value, e);
    }
    const activatorProps = computed(() => ({
      onClick,
      class: 'v-list-group__header',
      id: id.value
    }));
    const toggleIcon = computed(() => isOpen.value ? props.collapseIcon : props.expandIcon);
    const activatorDefaults = computed(() => ({
      VListItem: {
        activeColor: props.activeColor,
        baseColor: props.baseColor,
        color: props.color,
        prependIcon: props.prependIcon || props.subgroup && toggleIcon.value,
        appendIcon: props.appendIcon || !props.subgroup && toggleIcon.value,
        title: props.title,
        value: props.value
      }
    }));
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-list-group', {
        'v-list-group--prepend': list?.hasPrepend.value,
        'v-list-group--fluid': props.fluid,
        'v-list-group--subgroup': props.subgroup,
        'v-list-group--open': isOpen.value
      }, props.class]),
      "style": normalizeStyle(props.style)
    }, {
      default: () => [slots.activator && createVNode(VDefaultsProvider, {
        "defaults": activatorDefaults.value
      }, {
        default: () => [createVNode(VListGroupActivator, null, {
          default: () => [slots.activator({
            props: activatorProps.value,
            isOpen: isOpen.value
          })]
        })]
      }), createVNode(MaybeTransition, {
        "transition": {
          component: VExpandTransition
        },
        "disabled": !isBooted.value
      }, {
        default: () => [renderWhenClosed.value ? withDirectives(createElementVNode("div", {
          "class": "v-list-group__items",
          "role": "group",
          "aria-labelledby": id.value
        }, [slots.default?.()]), [[vShow, isOpen.value]]) : isOpen.value && createElementVNode("div", {
          "class": "v-list-group__items",
          "role": "group",
          "aria-labelledby": id.value
        }, [slots.default?.()])]
      })]
    }));
    return {
      isOpen
    };
  }
});

const makeVListItemSubtitleProps = propsFactory({
  opacity: [Number, String],
  ...makeComponentProps(),
  ...makeTagProps()
}, 'VListItemSubtitle');
const VListItemSubtitle = genericComponent()({
  name: 'VListItemSubtitle',
  props: makeVListItemSubtitleProps(),
  setup(props, {
    slots
  }) {
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-list-item-subtitle', props.class]),
      "style": normalizeStyle([{
        '--v-list-item-subtitle-opacity': props.opacity
      }, props.style])
    }, slots));
    return {};
  }
});

// Utilities
const VListItemTitle = createSimpleFunctional('v-list-item-title');

// Types

const makeVListItemProps = propsFactory({
  active: {
    type: Boolean,
    default: undefined
  },
  activeClass: String,
  /* @deprecated */
  activeColor: String,
  appendAvatar: String,
  appendIcon: IconValue,
  baseColor: String,
  disabled: Boolean,
  lines: [Boolean, String],
  link: {
    type: Boolean,
    default: undefined
  },
  nav: Boolean,
  prependAvatar: String,
  prependIcon: IconValue,
  ripple: {
    type: [Boolean, Object],
    default: true
  },
  slim: Boolean,
  prependGap: [Number, String],
  subtitle: {
    type: [String, Number, Boolean],
    default: undefined
  },
  title: {
    type: [String, Number, Boolean],
    default: undefined
  },
  value: null,
  index: Number,
  tabindex: [Number, String],
  onClick: EventProp(),
  onClickOnce: EventProp(),
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeDimensionProps(),
  ...makeElevationProps(),
  ...makeRoundedProps(),
  ...makeRouterProps(),
  ...makeTagProps(),
  ...makeThemeProps(),
  ...makeVariantProps({
    variant: 'text'
  })
}, 'VListItem');
const VListItem = genericComponent()({
  name: 'VListItem',
  directives: {
    vRipple: Ripple
  },
  props: makeVListItemProps(),
  emits: {
    click: e => true
  },
  setup(props, {
    attrs,
    slots,
    emit
  }) {
    const link = useLink(props, attrs);
    const rootEl = ref();
    const id = computed(() => props.value === undefined ? link.href.value : props.value);
    const {
      activate,
      isActivated,
      select,
      isOpen,
      isSelected,
      isIndeterminate,
      isGroupActivator,
      root,
      parent,
      openOnSelect,
      scrollToActive,
      id: uid
    } = useNestedItem(id, () => props.disabled, false);
    const list = useList();
    const isActive = computed(() => props.active !== false && (props.active || link.isActive?.value || (root.activatable.value ? isActivated.value : isSelected.value)));
    const isLink = toRef(() => props.link !== false && link.isLink.value);
    const isSelectable = computed(() => !!list && (root.selectable.value || root.activatable.value || props.value != null));
    const isClickable = computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value || isSelectable.value));
    const isTracked = computed(() => list && list.navigationStrategy.value === 'track' && props.index !== undefined && list.trackingIndex.value === props.index);
    const role = computed(() => list ? isLink.value ? 'link' : isSelectable.value ? 'option' : 'listitem' : undefined);
    const ariaSelected = computed(() => {
      if (!isSelectable.value) return undefined;
      return root.activatable.value ? isActivated.value : root.selectable.value ? isSelected.value : isActive.value;
    });
    const roundedProps = toRef(() => props.rounded || props.nav);
    const color = toRef(() => props.color ?? props.activeColor);
    const variantProps = toRef(() => ({
      color: isActive.value ? color.value ?? props.baseColor : props.baseColor,
      variant: props.variant
    }));

    // useNestedItem doesn't call register until beforeMount,
    // so this can't be an immediate watcher as we don't know parent yet
    watch(() => link.isActive?.value, val => {
      if (!val) return;
      handleActiveLink();
    });
    watch(isActivated, val => {
      if (!val || !scrollToActive) return;
      rootEl.value?.scrollIntoView({
        block: 'nearest',
        behavior: 'instant'
      });
    });
    watch(isTracked, val => {
      if (!val) return;
      rootEl.value?.scrollIntoView({
        block: 'nearest',
        behavior: 'instant'
      });
    });
    onBeforeMount(() => {
      if (link.isActive?.value) {
        nextTick(() => handleActiveLink());
      }
    });
    function handleActiveLink() {
      if (parent.value != null) {
        root.open(parent.value, true);
      }
      openOnSelect(true);
    }
    const {
      themeClasses
    } = provideTheme(props);
    const {
      borderClasses
    } = useBorder(props);
    const {
      colorClasses,
      colorStyles,
      variantClasses
    } = useVariant(variantProps);
    const {
      densityClasses
    } = useDensity(props);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(roundedProps);
    const lineClasses = toRef(() => props.lines ? `v-list-item--${props.lines}-line` : undefined);
    const rippleOptions = toRef(() => props.ripple !== undefined && !!props.ripple && list?.filterable ? {
      keys: ['Enter']
    } : props.ripple);
    const slotProps = computed(() => ({
      isActive: isActive.value,
      select,
      isOpen: isOpen.value,
      isSelected: isSelected.value,
      isIndeterminate: isIndeterminate.value,
      isDisabled: props.disabled
    }));
    function onClick(e) {
      emit('click', e);
      if (['INPUT', 'TEXTAREA'].includes(e.target?.tagName)) return;
      if (!isClickable.value) return;
      link.navigate.value?.(e);
      if (isGroupActivator) return;
      if (root.activatable.value) {
        activate(!isActivated.value, e);
      } else if (root.selectable.value) {
        select(!isSelected.value, e);
      } else if (props.value != null && !isLink.value) {
        select(!isSelected.value, e);
      }
    }
    function onKeyDown(e) {
      const target = e.target;
      if (['INPUT', 'TEXTAREA'].includes(target.tagName)) return;
      if (e.key === 'Enter' || e.key === ' ' && !list?.filterable) {
        e.preventDefault();
        e.stopPropagation();
        e.target.dispatchEvent(new MouseEvent('click', e));
      }
    }
    useRender(() => {
      const Tag = isLink.value ? 'a' : props.tag;
      const hasTitle = slots.title || props.title != null;
      const hasSubtitle = slots.subtitle || props.subtitle != null;
      const hasAppendMedia = !!(props.appendAvatar || props.appendIcon);
      const hasAppend = !!(hasAppendMedia || slots.append);
      const hasPrependMedia = !!(props.prependAvatar || props.prependIcon);
      const hasPrepend = !!(hasPrependMedia || slots.prepend);
      list?.updateHasPrepend(hasPrepend);
      if (props.activeColor) {
        deprecate('active-color', ['color', 'base-color']);
      }
      return withDirectives(createVNode(Tag, mergeProps(link.linkProps, {
        "ref": rootEl,
        "id": props.index !== undefined && list ? `v-list-item-${list.uid}-${props.index}` : undefined,
        "class": ['v-list-item', {
          'v-list-item--active': isActive.value,
          'v-list-item--disabled': props.disabled,
          'v-list-item--link': isClickable.value,
          'v-list-item--nav': props.nav,
          'v-list-item--prepend': !hasPrepend && list?.hasPrepend.value,
          'v-list-item--slim': props.slim,
          'v-list-item--focus-visible': isTracked.value,
          [`${props.activeClass}`]: props.activeClass && isActive.value
        }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, variantClasses.value, props.class],
        "style": [{
          '--v-list-prepend-gap': convertToUnit(props.prependGap)
        }, colorStyles.value, dimensionStyles.value, roundedStyles.value, props.style],
        "tabindex": props.tabindex ?? (isClickable.value ? list ? -2 : 0 : undefined),
        "aria-selected": ariaSelected.value,
        "role": role.value,
        "onClick": (isClickable.value || props.onClick || props.onClickOnce) && onClick,
        "onKeydown": isClickable.value && !isLink.value && onKeyDown
      }), {
        default: () => [genOverlays(isClickable.value || isActive.value, 'v-list-item'), hasPrepend && createElementVNode("div", {
          "key": "prepend",
          "class": "v-list-item__prepend"
        }, [!slots.prepend ? createElementVNode(Fragment, null, [props.prependAvatar && createVNode(VAvatar, {
          "key": "prepend-avatar",
          "density": props.density,
          "image": props.prependAvatar
        }, null), props.prependIcon && createVNode(VIcon, {
          "key": "prepend-icon",
          "density": props.density,
          "icon": props.prependIcon
        }, null)]) : createVNode(VDefaultsProvider, {
          "key": "prepend-defaults",
          "defaults": {
            VAvatar: {
              density: props.density,
              image: props.prependAvatar
            },
            VIcon: {
              density: props.density,
              icon: props.prependIcon
            },
            VListItemAction: {
              start: true
            },
            VCheckboxBtn: {
              density: props.density
            }
          }
        }, {
          default: () => [slots.prepend?.(slotProps.value)]
        }), createElementVNode("div", {
          "class": "v-list-item__spacer"
        }, null)]), createElementVNode("div", {
          "class": "v-list-item__content",
          "data-no-activator": ""
        }, [hasTitle && createVNode(VListItemTitle, {
          "key": "title"
        }, {
          default: () => [slots.title?.({
            title: props.title
          }) ?? toDisplayString(props.title)]
        }), hasSubtitle && createVNode(VListItemSubtitle, {
          "key": "subtitle"
        }, {
          default: () => [slots.subtitle?.({
            subtitle: props.subtitle
          }) ?? toDisplayString(props.subtitle)]
        }), slots.default?.(slotProps.value)]), hasAppend && createElementVNode("div", {
          "key": "append",
          "class": "v-list-item__append"
        }, [!slots.append ? createElementVNode(Fragment, null, [props.appendIcon && createVNode(VIcon, {
          "key": "append-icon",
          "density": props.density,
          "icon": props.appendIcon
        }, null), props.appendAvatar && createVNode(VAvatar, {
          "key": "append-avatar",
          "density": props.density,
          "image": props.appendAvatar
        }, null)]) : createVNode(VDefaultsProvider, {
          "key": "append-defaults",
          "defaults": {
            VAvatar: {
              density: props.density,
              image: props.appendAvatar
            },
            VIcon: {
              density: props.density,
              icon: props.appendIcon
            },
            VListItemAction: {
              end: true
            },
            VCheckboxBtn: {
              density: props.density
            }
          }
        }, {
          default: () => [slots.append?.(slotProps.value)]
        }), createElementVNode("div", {
          "class": "v-list-item__spacer"
        }, null)])]
      }), [[Ripple, isClickable.value && rippleOptions.value]]);
    });
    return {
      activate,
      isActivated,
      isGroupActivator,
      isSelected,
      list,
      select,
      root,
      id: uid,
      link
    };
  }
});

const makeVListSubheaderProps = propsFactory({
  color: String,
  inset: Boolean,
  sticky: Boolean,
  title: String,
  ...makeComponentProps(),
  ...makeTagProps()
}, 'VListSubheader');
const VListSubheader = genericComponent()({
  name: 'VListSubheader',
  props: makeVListSubheaderProps(),
  setup(props, {
    slots
  }) {
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.color);
    useRender(() => {
      const hasText = !!(slots.default || props.title);
      return createVNode(props.tag, {
        "class": normalizeClass(['v-list-subheader', {
          'v-list-subheader--inset': props.inset,
          'v-list-subheader--sticky': props.sticky
        }, textColorClasses.value, props.class]),
        "style": normalizeStyle([{
          textColorStyles
        }, props.style])
      }, {
        default: () => [hasText && createElementVNode("div", {
          "class": "v-list-subheader__text"
        }, [slots.default?.() ?? props.title])]
      });
    });
    return {};
  }
});

// Types

const makeVListChildrenProps = propsFactory({
  items: Array,
  returnObject: Boolean
}, 'VListChildren');
const VListChildren = genericComponent()({
  name: 'VListChildren',
  props: makeVListChildrenProps(),
  setup(props, {
    slots
  }) {
    createList();
    return () => slots.default?.() ?? props.items?.map(({
      children,
      props: itemProps,
      type,
      raw: item
    }, index) => {
      if (type === 'divider') {
        return slots.divider?.({
          props: itemProps
        }) ?? createVNode(VDivider, itemProps, null);
      }
      if (type === 'subheader') {
        return slots.subheader?.({
          props: itemProps
        }) ?? createVNode(VListSubheader, itemProps, null);
      }
      const slotsWithItem = {
        subtitle: slots.subtitle ? slotProps => slots.subtitle?.({
          ...slotProps,
          item
        }) : undefined,
        prepend: slots.prepend ? slotProps => slots.prepend?.({
          ...slotProps,
          item
        }) : undefined,
        append: slots.append ? slotProps => slots.append?.({
          ...slotProps,
          item
        }) : undefined,
        title: slots.title ? slotProps => slots.title?.({
          ...slotProps,
          item
        }) : undefined
      };
      const listGroupProps = VListGroup.filterProps(itemProps);
      return children ? createVNode(VListGroup, mergeProps(listGroupProps, {
        "value": props.returnObject ? item : itemProps?.value,
        "rawId": itemProps?.value
      }), {
        activator: ({
          props: activatorProps
        }) => {
          const listItemProps = mergeProps(itemProps, activatorProps, {
            value: props.returnObject ? item : itemProps.value
          });
          return slots.header ? slots.header({
            props: listItemProps
          }) : createVNode(VListItem, mergeProps(listItemProps, {
            "index": index
          }), slotsWithItem);
        },
        default: () => createVNode(VListChildren, {
          "items": children,
          "returnObject": props.returnObject
        }, slots)
      }) : slots.item ? slots.item({
        props: {
          ...itemProps,
          index
        }
      }) : createVNode(VListItem, mergeProps(itemProps, {
        "index": index,
        "value": props.returnObject ? item : itemProps.value
      }), slotsWithItem);
    });
  }
});

// Utilities

// Types

// Composables
const makeItemsProps = propsFactory({
  items: {
    type: Array,
    default: () => []
  },
  itemTitle: {
    type: [String, Array, Function],
    default: 'title'
  },
  itemValue: {
    type: [String, Array, Function],
    default: 'value'
  },
  itemChildren: {
    type: [Boolean, String, Array, Function],
    default: 'children'
  },
  itemProps: {
    type: [Boolean, String, Array, Function],
    default: 'props'
  },
  itemType: {
    type: [Boolean, String, Array, Function],
    default: 'type'
  },
  returnObject: Boolean,
  valueComparator: Function
}, 'list-items');
const itemTypes$1 = new Set(['item', 'divider', 'subheader']);
function transformItem$3(props, item) {
  const title = getPropertyFromItem(item, props.itemTitle, item);
  const value = getPropertyFromItem(item, props.itemValue, title);
  const children = getPropertyFromItem(item, props.itemChildren);
  const itemProps = props.itemProps === true ? typeof item === 'object' && item != null && !Array.isArray(item) ? 'children' in item ? omit(item, ['children']) : item : undefined : getPropertyFromItem(item, props.itemProps);
  let type = getPropertyFromItem(item, props.itemType, 'item');
  if (!itemTypes$1.has(type)) {
    type = 'item';
  }
  const _props = {
    title,
    value,
    ...itemProps
  };
  return {
    type,
    title: String(_props.title ?? ''),
    value: _props.value,
    props: _props,
    children: type === 'item' && Array.isArray(children) ? transformItems$3(props, children) : undefined,
    raw: item
  };
}
transformItem$3.neededProps = ['itemTitle', 'itemValue', 'itemChildren', 'itemProps', 'itemType'];
function transformItems$3(props, items) {
  // avoid reactive access in the loop
  const _props = pick(props, transformItem$3.neededProps);
  const array = [];
  for (const item of items) {
    array.push(transformItem$3(_props, item));
  }
  return array;
}
function useItems(props) {
  const items = computed(() => transformItems$3(props, props.items));
  const hasNullItem = computed(() => items.value.some(item => item.value === null));
  const itemsMap = shallowRef(new Map());
  const keylessItems = shallowRef([]);
  watchEffect(() => {
    const _items = items.value;
    const map = new Map();
    const keyless = [];
    for (let i = 0; i < _items.length; i++) {
      const item = _items[i];
      if (isPrimitive(item.value) || item.value === null) {
        let values = map.get(item.value);
        if (!values) {
          values = [];
          map.set(item.value, values);
        }
        values.push(item);
      } else {
        keyless.push(item);
      }
    }
    itemsMap.value = map;
    keylessItems.value = keyless;
  });
  function transformIn(value) {
    // Cache unrefed values outside the loop,
    // proxy getters can be slow when you call them a billion times
    const _items = itemsMap.value;
    const _allItems = items.value;
    const _keylessItems = keylessItems.value;
    const _hasNullItem = hasNullItem.value;
    const _returnObject = props.returnObject;
    const hasValueComparator = !!props.valueComparator;
    const valueComparator = props.valueComparator || deepEqual;
    const _props = pick(props, transformItem$3.neededProps);
    const returnValue = [];
    main: for (const v of value) {
      // When the model value is null, return an InternalItem
      // based on null only if null is one of the items
      if (!_hasNullItem && v === null) continue;

      // String model value means value is a custom input value from combobox
      // Don't look up existing items if the model value is a string
      if (_returnObject && typeof v === 'string') {
        returnValue.push(transformItem$3(_props, v));
        continue;
      }

      // Fast path, items with primitive values and no
      // custom valueComparator can use a constant-time
      // map lookup instead of searching the items array
      const fastItems = _items.get(v);

      // Slow path, always use valueComparator.
      // This is O(n^2) so we really don't want to
      // do it for more than a couple hundred items.
      if (hasValueComparator || !fastItems) {
        for (const item of hasValueComparator ? _allItems : _keylessItems) {
          if (valueComparator(v, item.value)) {
            returnValue.push(item);
            continue main;
          }
        }
        // Not an existing item, construct it from the model (#4000)
        returnValue.push(transformItem$3(_props, v));
        continue;
      }
      returnValue.push(...fastItems);
    }
    return returnValue;
  }
  function transformOut(value) {
    return props.returnObject ? value.map(({
      raw
    }) => raw) : value.map(({
      value
    }) => value);
  }
  return {
    items,
    transformIn,
    transformOut
  };
}

// Types

const itemTypes = new Set(['item', 'divider', 'subheader']);
function transformItem$2(props, item) {
  const title = isPrimitive(item) ? item : getPropertyFromItem(item, props.itemTitle);
  const value = isPrimitive(item) ? item : getPropertyFromItem(item, props.itemValue, undefined);
  const children = getPropertyFromItem(item, props.itemChildren);
  const itemProps = props.itemProps === true ? omit(item, ['children']) : getPropertyFromItem(item, props.itemProps);
  let type = getPropertyFromItem(item, props.itemType, 'item');
  if (!itemTypes.has(type)) {
    type = 'item';
  }
  const _props = {
    title,
    value,
    ...itemProps
  };
  return {
    type,
    title: _props.title,
    value: _props.value,
    props: _props,
    children: type === 'item' && children ? transformItems$2(props, children) : undefined,
    raw: item
  };
}
function transformItems$2(props, items) {
  const array = [];
  for (const item of items) {
    array.push(transformItem$2(props, item));
  }
  return array;
}
function useListItems(props) {
  const items = computed(() => transformItems$2(props, props.items));
  return {
    items
  };
}
const makeVListProps = propsFactory({
  baseColor: String,
  /* @deprecated */
  activeColor: String,
  activeClass: String,
  bgColor: String,
  disabled: Boolean,
  filterable: Boolean,
  expandIcon: IconValue,
  collapseIcon: IconValue,
  lines: {
    type: [Boolean, String],
    default: 'one'
  },
  slim: Boolean,
  prependGap: [Number, String],
  indent: [Number, String],
  nav: Boolean,
  navigationStrategy: {
    type: String,
    default: 'focus'
  },
  navigationIndex: Number,
  'onClick:open': EventProp(),
  'onClick:select': EventProp(),
  'onUpdate:opened': EventProp(),
  ...makeNestedProps({
    selectStrategy: 'single-leaf',
    openStrategy: 'list'
  }),
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeDimensionProps(),
  ...makeElevationProps(),
  ...makeItemsProps(),
  ...makeRoundedProps(),
  ...makeTagProps(),
  ...makeThemeProps(),
  ...makeVariantProps({
    variant: 'text'
  })
}, 'VList');
const VList = genericComponent()({
  name: 'VList',
  props: makeVListProps(),
  emits: {
    'update:selected': value => true,
    'update:activated': value => true,
    'update:opened': value => true,
    'update:navigationIndex': value => true,
    'click:open': value => true,
    'click:activate': value => true,
    'click:select': value => true
  },
  setup(props, {
    attrs,
    slots,
    emit
  }) {
    const {
      items
    } = useListItems(props);
    const {
      themeClasses
    } = provideTheme(props);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.bgColor);
    const {
      borderClasses
    } = useBorder(props);
    const {
      densityClasses
    } = useDensity(props);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      children,
      open,
      parents,
      select,
      getPath
    } = useNested(props, {
      items,
      returnObject: toRef(() => props.returnObject),
      scrollToActive: toRef(() => props.navigationStrategy === 'track'),
      valueComparator: toRef(() => props.valueComparator)
    });
    const lineClasses = toRef(() => props.lines ? `v-list--${props.lines}-line` : undefined);
    const activeColor = toRef(() => props.activeColor);
    const baseColor = toRef(() => props.baseColor);
    const color = toRef(() => props.color);
    const isSelectable = toRef(() => props.selectable || props.activatable);
    const navigationIndex = useProxiedModel(props, 'navigationIndex', -1, v => v ?? -1);
    const uid = useId();
    createList({
      filterable: props.filterable,
      trackingIndex: navigationIndex,
      navigationStrategy: toRef(() => props.navigationStrategy),
      uid
    });
    watch(items, () => {
      if (props.navigationStrategy === 'track') {
        navigationIndex.value = -1;
      }
    });
    provideDefaults({
      VListGroup: {
        activeColor,
        baseColor,
        color,
        expandIcon: toRef(() => props.expandIcon),
        collapseIcon: toRef(() => props.collapseIcon)
      },
      VListItem: {
        activeClass: toRef(() => props.activeClass),
        activeColor,
        baseColor,
        color,
        density: toRef(() => props.density),
        disabled: toRef(() => props.disabled),
        lines: toRef(() => props.lines),
        nav: toRef(() => props.nav),
        slim: toRef(() => props.slim),
        variant: toRef(() => props.variant),
        tabindex: toRef(() => props.navigationStrategy === 'track' ? -1 : undefined)
      }
    });
    const isFocused = shallowRef(false);
    const contentRef = ref();
    function onFocusin(e) {
      isFocused.value = true;
    }
    function onFocusout(e) {
      isFocused.value = false;
    }
    function onFocus(e) {
      if (props.navigationStrategy === 'track') {
        if (!~navigationIndex.value) {
          navigationIndex.value = getNextIndex('first');
        }
      } else if (!isFocused.value && !(e.relatedTarget && contentRef.value?.contains(e.relatedTarget))) focus();
    }
    function onBlur() {
      if (props.navigationStrategy === 'track') {
        navigationIndex.value = -1;
      }
    }
    function getNavigationDirection(key) {
      switch (key) {
        case 'ArrowDown':
          return 'next';
        case 'ArrowUp':
          return 'prev';
        case 'Home':
          return 'first';
        case 'End':
          return 'last';
        default:
          return null;
      }
    }
    function getNextIndex(direction) {
      const itemCount = items.value.length;
      if (itemCount === 0) return -1;
      let nextIndex;
      if (direction === 'first') {
        nextIndex = 0;
      } else if (direction === 'last') {
        nextIndex = itemCount - 1;
      } else {
        nextIndex = navigationIndex.value + (direction === 'next' ? 1 : -1);
        if (nextIndex < 0) nextIndex = itemCount - 1;
        if (nextIndex >= itemCount) nextIndex = 0;
      }
      const startIndex = nextIndex;
      let attempts = 0;
      while (attempts < itemCount) {
        const item = items.value[nextIndex];
        if (item && item.type !== 'divider' && item.type !== 'subheader') {
          return nextIndex;
        }
        nextIndex += direction === 'next' || direction === 'first' ? 1 : -1;
        if (nextIndex < 0) nextIndex = itemCount - 1;
        if (nextIndex >= itemCount) nextIndex = 0;
        if (nextIndex === startIndex) return -1;
        attempts++;
      }
      return -1;
    }
    function onKeydown(e) {
      const target = e.target;
      if (!contentRef.value || target.tagName === 'INPUT' && ['Home', 'End'].includes(e.key) || target.tagName === 'TEXTAREA') {
        return;
      }
      const direction = getNavigationDirection(e.key);
      if (direction !== null) {
        e.preventDefault();
        if (props.navigationStrategy === 'track') {
          const nextIndex = getNextIndex(direction);
          if (nextIndex !== -1) {
            navigationIndex.value = nextIndex;
          }
        } else {
          focus(direction);
        }
      }
    }
    function onMousedown(e) {
      isFocused.value = true;
    }
    function focus(location, options) {
      if (contentRef.value) {
        return focusChild(contentRef.value, location, options);
      }
    }
    useRender(() => {
      const indent = props.indent ?? (props.prependGap ? Number(props.prependGap) + 24 : undefined);
      const ariaMultiselectable = isSelectable.value ? attrs.ariaMultiselectable ?? !String(props.selectStrategy).startsWith('single-') : undefined;
      return createVNode(props.tag, {
        "ref": contentRef,
        "class": normalizeClass(['v-list', {
          'v-list--disabled': props.disabled,
          'v-list--nav': props.nav,
          'v-list--slim': props.slim
        }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, props.class]),
        "style": normalizeStyle([{
          '--v-list-indent': convertToUnit(indent),
          '--v-list-group-prepend': indent ? '0px' : undefined,
          '--v-list-prepend-gap': convertToUnit(props.prependGap)
        }, backgroundColorStyles.value, dimensionStyles.value, roundedStyles.value, props.style]),
        "tabindex": props.disabled ? -1 : 0,
        "role": isSelectable.value ? 'listbox' : 'list',
        "aria-activedescendant": props.navigationStrategy === 'track' && navigationIndex.value >= 0 ? `v-list-item-${uid}-${navigationIndex.value}` : undefined,
        "aria-multiselectable": ariaMultiselectable,
        "onFocusin": onFocusin,
        "onFocusout": onFocusout,
        "onFocus": onFocus,
        "onBlur": onBlur,
        "onKeydown": onKeydown,
        "onMousedown": onMousedown
      }, {
        default: () => [createVNode(VListChildren, {
          "items": items.value,
          "returnObject": props.returnObject
        }, slots)]
      });
    });
    return {
      open,
      select,
      focus,
      children,
      parents,
      getPath,
      navigationIndex
    };
  }
});

// Utilities
const VListImg = createSimpleFunctional('v-list-img');

const makeVListItemActionProps = propsFactory({
  start: Boolean,
  end: Boolean,
  ...makeComponentProps(),
  ...makeTagProps()
}, 'VListItemAction');
const VListItemAction = genericComponent()({
  name: 'VListItemAction',
  props: makeVListItemActionProps(),
  setup(props, {
    slots
  }) {
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-list-item-action', {
        'v-list-item-action--start': props.start,
        'v-list-item-action--end': props.end
      }, props.class]),
      "style": normalizeStyle(props.style)
    }, slots));
    return {};
  }
});

const makeVListItemMediaProps = propsFactory({
  start: Boolean,
  end: Boolean,
  ...makeComponentProps(),
  ...makeTagProps()
}, 'VListItemMedia');
const VListItemMedia = genericComponent()({
  name: 'VListItemMedia',
  props: makeVListItemMediaProps(),
  setup(props, {
    slots
  }) {
    useRender(() => {
      return createVNode(props.tag, {
        "class": normalizeClass(['v-list-item-media', {
          'v-list-item-media--start': props.start,
          'v-list-item-media--end': props.end
        }, props.class]),
        "style": normalizeStyle(props.style)
      }, slots);
    });
    return {};
  }
});

// Types

/** Convert a point in local space to viewport space */
function elementToViewport(point, offset) {
  return {
    x: point.x + offset.x,
    y: point.y + offset.y
  };
}

/** Get the difference between two points */
function getOffset$1(a, b) {
  return {
    x: a.x - b.x,
    y: a.y - b.y
  };
}

/** Convert an anchor object to a point in local space */
function anchorToPoint(anchor, box) {
  if (anchor.side === 'top' || anchor.side === 'bottom') {
    const {
      side,
      align
    } = anchor;
    const x = align === 'left' ? 0 : align === 'center' ? box.width / 2 : align === 'right' ? box.width : align;
    const y = side === 'top' ? 0 : side === 'bottom' ? box.height : side;
    return elementToViewport({
      x,
      y
    }, box);
  } else if (anchor.side === 'left' || anchor.side === 'right') {
    const {
      side,
      align
    } = anchor;
    const x = side === 'left' ? 0 : side === 'right' ? box.width : side;
    const y = align === 'top' ? 0 : align === 'center' ? box.height / 2 : align === 'bottom' ? box.height : align;
    return elementToViewport({
      x,
      y
    }, box);
  }
  return elementToViewport({
    x: box.width / 2,
    y: box.height / 2
  }, box);
}

// Composables

// Types

const locationStrategies = {
  static: staticLocationStrategy,
  // specific viewport position, usually centered
  connected: connectedLocationStrategy // connected to a certain element
};
const makeLocationStrategyProps = propsFactory({
  locationStrategy: {
    type: [String, Function],
    default: 'static',
    validator: val => typeof val === 'function' || val in locationStrategies
  },
  location: String,
  origin: {
    type: String,
    default: 'auto'
  },
  offset: [Number, String, Array],
  stickToTarget: Boolean,
  viewportMargin: {
    type: [Number, String],
    default: 12
  }
}, 'VOverlay-location-strategies');
function useLocationStrategies(props, data) {
  const contentStyles = ref({});
  const updateLocation = ref();
  if (IN_BROWSER) {
    useToggleScope(() => !!(data.isActive.value && props.locationStrategy), reset => {
      watch(() => props.locationStrategy, reset);
      onScopeDispose(() => {
        window.removeEventListener('resize', onResize);
        visualViewport?.removeEventListener('resize', onVisualResize);
        visualViewport?.removeEventListener('scroll', onVisualScroll);
        updateLocation.value = undefined;
        if (data.isActive.value) {
          contentStyles.value = {};
        }
      });
      window.addEventListener('resize', onResize, {
        passive: true
      });
      visualViewport?.addEventListener('resize', onVisualResize, {
        passive: true
      });
      visualViewport?.addEventListener('scroll', onVisualScroll, {
        passive: true
      });
      if (typeof props.locationStrategy === 'function') {
        updateLocation.value = props.locationStrategy(data, props, contentStyles)?.updateLocation;
      } else {
        updateLocation.value = locationStrategies[props.locationStrategy](data, props, contentStyles)?.updateLocation;
      }
    });
  }
  function onResize(e) {
    updateLocation.value?.(e);
  }
  function onVisualResize(e) {
    updateLocation.value?.(e);
  }
  function onVisualScroll(e) {
    updateLocation.value?.(e);
  }
  return {
    contentStyles,
    updateLocation
  };
}
function getStaticLocationClasses(location) {
  if (!location) return undefined;
  const normalized = location.includes(' ') ? location : `${location} center`;
  let justify = 'center';
  let align = 'center';
  const inline = {
    left: 'start',
    start: 'start',
    right: 'end',
    end: 'end'
  };
  const block = {
    top: 'start',
    bottom: 'end'
  };
  for (const token of normalized.split(' ')) {
    if (token in inline) justify = inline[token];else if (token in block) align = block[token];
  }
  return {
    [`v-overlay--justify-${justify}`]: true,
    [`v-overlay--align-${align}`]: true
  };
}
function staticLocationStrategy(data, props, contentStyles) {
  // Positioning is handled by CSS flexbox alignment on the overlay root, keeping
  // the content's insets `auto` so user utility classes (justify-*, align-*) compose.
  // Here we only forward an explicit `origin` to `transform-origin` for the transition.
  function updateStyles() {
    if (props.origin !== 'auto' && props.origin !== 'overlap') {
      const {
        side,
        align
      } = parseAnchor(props.origin, data.isRtl.value);
      contentStyles.value = {
        transformOrigin: `${side} ${align}`
      };
    } else {
      contentStyles.value = {};
    }
  }
  watch([() => props.origin, data.isRtl], updateStyles, {
    immediate: true
  });
  return {
    updateLocation: () => {}
  };
}

/** Resolve a CSS length the browser understands (calc(), min(), vw, …) to pixels */
function resolveCssLength(value, container, isWidth) {
  const probe = document.createElement('div');
  probe.style.position = 'absolute';
  probe.style.visibility = 'hidden';
  probe.style[isWidth ? 'width' : 'height'] = value;
  container.appendChild(probe);
  const size = isWidth ? probe.offsetWidth : probe.offsetHeight;
  container.removeChild(probe);
  return size > 0 ? size : Infinity;
}

/** Get size of element ignoring max-width/max-height */
function getIntrinsicSize(el, isRtl) {
  // const scrollables = new Map<Element, [number, number]>()
  // el.querySelectorAll('*').forEach(el => {
  //   const x = el.scrollLeft
  //   const y = el.scrollTop
  //   if (x || y) {
  //     scrollables.set(el, [x, y])
  //   }
  // })

  // const initialMaxWidth = el.style.maxWidth
  // const initialMaxHeight = el.style.maxHeight
  // el.style.removeProperty('max-width')
  // el.style.removeProperty('max-height')

  /* eslint-disable-next-line sonarjs/prefer-immediate-return */
  const contentBox = nullifyTransforms(el);
  if (isRtl) {
    contentBox.x += parseFloat(el.style.right || 0);
  } else {
    contentBox.x -= parseFloat(el.style.left || 0);
  }
  contentBox.y -= parseFloat(el.style.top || 0);

  // el.style.maxWidth = initialMaxWidth
  // el.style.maxHeight = initialMaxHeight
  // scrollables.forEach((position, el) => {
  //   el.scrollTo(...position)
  // })

  return contentBox;
}
function connectedLocationStrategy(data, props, contentStyles) {
  const activatorFixed = Array.isArray(data.target.value) || isFixedPosition(data.target.value);
  if (activatorFixed) {
    Object.assign(contentStyles.value, {
      position: 'fixed',
      top: 0,
      [data.isRtl.value ? 'right' : 'left']: 0
    });
  }
  const {
    preferredAnchor,
    preferredOrigin
  } = destructComputed(() => {
    const parsedAnchor = parseAnchor(props.location ?? 'bottom', data.isRtl.value);
    const parsedOrigin = props.origin === 'overlap' ? parsedAnchor : props.origin === 'auto' ? flipSide(parsedAnchor) : parseAnchor(props.origin, data.isRtl.value);

    // Some combinations of props may produce an invalid origin
    if (parsedAnchor.side === parsedOrigin.side && parsedAnchor.align === flipAlign(parsedOrigin).align) {
      return {
        preferredAnchor: flipCorner(parsedAnchor),
        preferredOrigin: flipCorner(parsedOrigin)
      };
    } else {
      return {
        preferredAnchor: parsedAnchor,
        preferredOrigin: parsedOrigin
      };
    }
  });
  const [getMinWidth, getMinHeight, getMaxWidth, getMaxHeight] = ['minWidth', 'minHeight', 'maxWidth', 'maxHeight'].map(key => {
    const isWidth = key.endsWith('Width');
    return () => {
      const raw = props[key];
      if (raw == null) return Infinity;
      const container = data.contentEl.value?.parentElement ?? document.documentElement;
      if (typeof raw === 'number' || /^-?[\d.]+(?:px)?$/.test(raw.trim())) {
        return parseFloat(raw);
      }
      if (raw.endsWith('%')) {
        // resolve against the overlay container, like CSS would
        const box = getElementBox(container);
        return parseFloat(raw) * (isWidth ? box.width : box.height) / 100;
      }
      // let the browser resolve viewport units, calc(), min(), max(), clamp(), etc.
      return resolveCssLength(raw, container, isWidth);
    };
  });
  const offset = computed(() => {
    if (Array.isArray(props.offset)) {
      return props.offset;
    }
    if (typeof props.offset === 'string') {
      const offset = props.offset.split(' ').map(parseFloat);
      if (offset.length < 2) offset.push(0);
      return offset;
    }
    return typeof props.offset === 'number' ? [props.offset, 0] : [0, 0];
  });
  let observe = false;
  let lastFrame = -1;
  const flipped = new CircularBuffer(4);
  const observer = new ResizeObserver(() => {
    if (!observe) return;

    // Detect consecutive frames
    requestAnimationFrame(newTime => {
      if (newTime !== lastFrame) flipped.clear();
      requestAnimationFrame(newNewTime => {
        lastFrame = newNewTime;
      });
    });
    if (flipped.isFull) {
      const values = flipped.values();
      if (deepEqual(values.at(-1), values.at(-3)) && !deepEqual(values.at(-1), values.at(-2))) {
        // Flipping is causing a container resize loop
        return;
      }
    }
    const result = updateLocation();
    if (result) flipped.push(result.flipped);
  });
  let targetBox = new Box({
    x: 0,
    y: 0,
    width: 0,
    height: 0
  });
  watch(data.target, (newTarget, oldTarget) => {
    if (oldTarget && !Array.isArray(oldTarget)) observer.unobserve(oldTarget);
    if (!Array.isArray(newTarget)) {
      if (newTarget) observer.observe(newTarget);
    } else if (!deepEqual(newTarget, oldTarget)) {
      updateLocation();
    }
  }, {
    immediate: true
  });
  watch(data.contentEl, (newContentEl, oldContentEl) => {
    if (oldContentEl) observer.unobserve(oldContentEl);
    if (newContentEl) observer.observe(newContentEl);
  }, {
    immediate: true
  });
  onScopeDispose(() => {
    observer.disconnect();
  });

  // eslint-disable-next-line max-statements
  function updateLocation() {
    observe = false;
    requestAnimationFrame(() => observe = true);
    if (!data.target.value || !data.contentEl.value) return;
    if (Array.isArray(data.target.value) || data.target.value.offsetParent || data.target.value.getClientRects().length) {
      targetBox = getTargetBox(data.target.value);
    } // Otherwise target element is hidden, use last known value

    const contentBox = getIntrinsicSize(data.contentEl.value, data.isRtl.value);
    const scrollParents = getScrollParents(data.contentEl.value);
    const viewportMargin = Number(props.viewportMargin);
    const minWidth = getMinWidth();
    const minHeight = getMinHeight();
    const maxWidth = getMaxWidth();
    const maxHeight = getMaxHeight();
    if (!scrollParents.length) {
      scrollParents.push(document.documentElement);
      if (!(data.contentEl.value.style.top && data.contentEl.value.style.left)) {
        contentBox.x -= parseFloat(document.documentElement.style.getPropertyValue('--v-body-scroll-x') || 0);
        contentBox.y -= parseFloat(document.documentElement.style.getPropertyValue('--v-body-scroll-y') || 0);
      }
    }
    const viewport = scrollParents.reduce((box, el) => {
      const scrollBox = getElementBox(el);
      if (box) {
        return new Box({
          x: Math.max(box.left, scrollBox.left),
          y: Math.max(box.top, scrollBox.top),
          width: Math.min(box.right, scrollBox.right) - Math.max(box.left, scrollBox.left),
          height: Math.min(box.bottom, scrollBox.bottom) - Math.max(box.top, scrollBox.top)
        });
      }
      return scrollBox;
    }, undefined);
    if (props.stickToTarget) {
      viewport.x += Math.min(viewportMargin, targetBox.x);
      viewport.y += Math.min(viewportMargin, targetBox.y);
      viewport.width = Math.max(viewport.width - viewportMargin * 2, targetBox.x + targetBox.width - viewportMargin);
      viewport.height = Math.max(viewport.height - viewportMargin * 2, targetBox.y + targetBox.height - viewportMargin);
    } else {
      viewport.x += viewportMargin;
      viewport.y += viewportMargin;
      viewport.width -= viewportMargin * 2;
      viewport.height -= viewportMargin * 2;
    }
    let placement = {
      anchor: preferredAnchor.value,
      origin: preferredOrigin.value
    };
    function checkOverflow(_placement) {
      const box = new Box(contentBox);
      const targetPoint = anchorToPoint(_placement.anchor, targetBox);
      const contentPoint = anchorToPoint(_placement.origin, box);
      let {
        x,
        y
      } = getOffset$1(targetPoint, contentPoint);
      switch (_placement.anchor.side) {
        case 'top':
          y -= offset.value[0];
          break;
        case 'bottom':
          y += offset.value[0];
          break;
        case 'left':
          x -= offset.value[0];
          break;
        case 'right':
          x += offset.value[0];
          break;
      }
      switch (_placement.anchor.align) {
        case 'top':
          y -= offset.value[1];
          break;
        case 'bottom':
          y += offset.value[1];
          break;
        case 'left':
          x -= offset.value[1];
          break;
        case 'right':
          x += offset.value[1];
          break;
      }
      box.x += x;
      box.y += y;
      box.width = Math.min(box.width, maxWidth);
      box.height = Math.min(box.height, maxHeight);
      const overflows = getOverflow(box, viewport);
      return {
        overflows,
        x,
        y
      };
    }
    let x = 0;
    let y = 0;
    const available = {
      x: 0,
      y: 0
    };
    const flipped = {
      x: false,
      y: false
    };
    let resets = -1;
    while (true) {
      if (resets++ > 10) {
        consoleError('Infinite loop detected in connectedLocationStrategy');
        break;
      }
      const {
        x: _x,
        y: _y,
        overflows
      } = checkOverflow(placement);
      x += _x;
      y += _y;
      contentBox.x += _x;
      contentBox.y += _y;

      // flip
      {
        const axis = getAxis(placement.anchor);
        const hasOverflowX = overflows.x.before || overflows.x.after;
        const hasOverflowY = overflows.y.before || overflows.y.after;
        let reset = false;
        ['x', 'y'].forEach(key => {
          if (key === 'x' && hasOverflowX && !flipped.x || key === 'y' && hasOverflowY && !flipped.y) {
            const newPlacement = {
              anchor: {
                ...placement.anchor
              },
              origin: {
                ...placement.origin
              }
            };
            const flip = key === 'x' ? axis === 'y' ? flipAlign : flipSide : axis === 'y' ? flipSide : flipAlign;
            newPlacement.anchor = flip(newPlacement.anchor);
            newPlacement.origin = flip(newPlacement.origin);
            const {
              overflows: newOverflows
            } = checkOverflow(newPlacement);
            if (newOverflows[key].before <= overflows[key].before && newOverflows[key].after <= overflows[key].after || newOverflows[key].before + newOverflows[key].after < (overflows[key].before + overflows[key].after) / 2) {
              placement = newPlacement;
              reset = flipped[key] = true;
            }
          }
        });
        if (reset) continue;
      }

      // shift
      if (overflows.x.before) {
        x += overflows.x.before;
        contentBox.x += overflows.x.before;
      }
      if (overflows.x.after) {
        x -= overflows.x.after;
        contentBox.x -= overflows.x.after;
      }
      if (overflows.y.before) {
        y += overflows.y.before;
        contentBox.y += overflows.y.before;
      }
      if (overflows.y.after) {
        y -= overflows.y.after;
        contentBox.y -= overflows.y.after;
      }

      // size
      {
        const overflows = getOverflow(contentBox, viewport);
        available.x = viewport.width - overflows.x.before - overflows.x.after;
        available.y = viewport.height - overflows.y.before - overflows.y.after;
        x += overflows.x.before;
        contentBox.x += overflows.x.before;
        y += overflows.y.before;
        contentBox.y += overflows.y.before;
      }
      break;
    }
    const axis = getAxis(placement.anchor);
    const transformOrigin = props.origin !== 'auto' && props.origin !== 'overlap' ? parseAnchor(props.origin, data.isRtl.value) : placement.origin;
    Object.assign(contentStyles.value, {
      '--v-overlay-anchor-origin': `${placement.anchor.side} ${placement.anchor.align}`,
      transformOrigin: `${transformOrigin.side} ${transformOrigin.align}`,
      // transform: `translate(${pixelRound(x)}px, ${pixelRound(y)}px)`,
      top: convertToUnit(pixelRound(y)),
      left: data.isRtl.value ? undefined : convertToUnit(pixelRound(x)),
      right: data.isRtl.value ? convertToUnit(pixelRound(-x)) : undefined,
      minWidth: convertToUnit(axis === 'y' ? Math.min(minWidth, targetBox.width) : minWidth),
      maxWidth: convertToUnit(pixelCeil(clamp(available.x, minWidth === Infinity ? 0 : minWidth, maxWidth))),
      maxHeight: convertToUnit(pixelCeil(clamp(available.y, minHeight === Infinity ? 0 : minHeight, maxHeight)))
    });
    return {
      available,
      contentBox,
      flipped
    };
  }
  watch(() => [preferredAnchor.value, preferredOrigin.value, props.origin, props.offset, props.minWidth, props.minHeight, props.maxWidth, props.maxHeight], () => updateLocation());
  nextTick(() => {
    const result = updateLocation();

    // TODO: overflowing content should only require a single updateLocation call
    // Icky hack to make sure the content is positioned consistently
    if (!result) return;
    const {
      available,
      contentBox
    } = result;
    if (contentBox.height > available.y) {
      requestAnimationFrame(() => {
        updateLocation();
        requestAnimationFrame(() => {
          updateLocation();
        });
      });
    }
  });
  return {
    updateLocation
  };
}
function pixelRound(val) {
  return Math.round(val * devicePixelRatio) / devicePixelRatio;
}
function pixelCeil(val) {
  return Math.ceil(val * devicePixelRatio) / devicePixelRatio;
}

let clean = true;
const frames = [];

/**
 * Schedule a task to run in an animation frame on its own
 * This is useful for heavy tasks that may cause jank if all ran together
 */
function requestNewFrame(cb) {
  if (!clean || frames.length) {
    frames.push(cb);
    run();
  } else {
    clean = false;
    cb();
    run();
  }
}
let raf = -1;
function run() {
  cancelAnimationFrame(raf);
  raf = requestAnimationFrame(() => {
    const frame = frames.shift();
    if (frame) frame();
    if (frames.length) run();else clean = true;
  });
}

// Utilities

// Types

const scrollStrategies = {
  none: null,
  close: closeScrollStrategy,
  block: blockScrollStrategy,
  reposition: repositionScrollStrategy
};
const makeScrollStrategyProps = propsFactory({
  scrollStrategy: {
    type: [String, Function],
    default: 'block',
    validator: val => typeof val === 'function' || val in scrollStrategies
  }
}, 'VOverlay-scroll-strategies');
function useScrollStrategies(props, data) {
  if (!IN_BROWSER) return;
  let scope;
  watchEffect(async () => {
    scope?.stop();
    if (!(data.isActive.value && props.scrollStrategy)) return;
    scope = effectScope();
    await new Promise(resolve => setTimeout(resolve));
    scope.active && scope.run(() => {
      if (typeof props.scrollStrategy === 'function') {
        props.scrollStrategy(data, props, scope);
      } else {
        scrollStrategies[props.scrollStrategy]?.(data, props, scope);
      }
    });
  });
  onScopeDispose(() => {
    scope?.stop();
  });
}
function closeScrollStrategy(data) {
  function onScroll(e) {
    data.isActive.value = false;
  }
  bindScroll(getTargetEl(data.target.value, data.contentEl.value), onScroll);
}
function blockScrollStrategy(data, props) {
  const offsetParent = data.root.value?.offsetParent;
  const target = getTargetEl(data.target.value, data.contentEl.value);
  const scrollElements = [...new Set([...getScrollParents(target, props.contained ? offsetParent : undefined), ...getScrollParents(data.contentEl.value, props.contained ? offsetParent : undefined)])].filter(el => !el.classList.contains('v-overlay-scroll-blocked'));
  const scrollbarWidth = window.innerWidth - document.documentElement.offsetWidth;
  const scrollableParent = (el => hasScrollbar(el) && el)(offsetParent || document.documentElement);
  if (scrollableParent) {
    data.root.value.classList.add('v-overlay--scroll-blocked');
  }
  scrollElements.forEach((el, i) => {
    el.style.setProperty('--v-body-scroll-x', convertToUnit(-el.scrollLeft));
    el.style.setProperty('--v-body-scroll-y', convertToUnit(-el.scrollTop));
    if (el !== document.documentElement || getComputedStyle(el).overflowY !== 'scroll') {
      el.style.setProperty('--v-scrollbar-offset', convertToUnit(scrollbarWidth));
    }
    el.classList.add('v-overlay-scroll-blocked');
  });
  onScopeDispose(() => {
    scrollElements.forEach((el, i) => {
      const x = parseFloat(el.style.getPropertyValue('--v-body-scroll-x'));
      const y = parseFloat(el.style.getPropertyValue('--v-body-scroll-y'));
      const scrollBehavior = el.style.scrollBehavior;
      el.style.scrollBehavior = 'auto';
      el.style.removeProperty('--v-body-scroll-x');
      el.style.removeProperty('--v-body-scroll-y');
      el.style.removeProperty('--v-scrollbar-offset');
      el.classList.remove('v-overlay-scroll-blocked');
      el.scrollLeft = -x;
      el.scrollTop = -y;
      el.style.scrollBehavior = scrollBehavior;
    });
    if (scrollableParent) {
      data.root.value.classList.remove('v-overlay--scroll-blocked');
    }
  });
}
function repositionScrollStrategy(data, props, scope) {
  let slow = false;
  let raf = -1;
  let ric = -1;
  function update(e) {
    requestNewFrame(() => {
      const start = performance.now();
      data.updateLocation.value?.(e);
      const time = performance.now() - start;
      slow = time / (1000 / 60) > 2;
    });
  }
  ric = (typeof requestIdleCallback === 'undefined' ? cb => cb() : requestIdleCallback)(() => {
    scope.run(() => {
      bindScroll(getTargetEl(data.target.value, data.contentEl.value), e => {
        if (slow) {
          // If the position calculation is slow,
          // defer updates until scrolling is finished.
          // Browsers usually fire one scroll event per frame so
          // we just wait until we've got two frames without an event
          cancelAnimationFrame(raf);
          raf = requestAnimationFrame(() => {
            raf = requestAnimationFrame(() => {
              update(e);
            });
          });
        } else {
          update(e);
        }
      });
    });
  });
  onScopeDispose(() => {
    typeof cancelIdleCallback !== 'undefined' && cancelIdleCallback(ric);
    cancelAnimationFrame(raf);
  });
}
function getTargetEl(target, contentEl) {
  return Array.isArray(target) ? document.elementsFromPoint(...target).find(el => !contentEl?.contains(el)) : target ?? contentEl;
}
function bindScroll(el, onScroll) {
  const scrollElements = [document, ...getScrollParents(el)];
  scrollElements.forEach(el => {
    el.addEventListener('scroll', onScroll, {
      passive: true
    });
  });
  onScopeDispose(() => {
    scrollElements.forEach(el => {
      el.removeEventListener('scroll', onScroll);
    });
  });
}

// Types

const VMenuSymbol = Symbol.for('vuetify:v-menu');

// Utilities

// Types

// Composables
const makeDelayProps = propsFactory({
  closeDelay: [Number, String],
  openDelay: [Number, String]
}, 'delay');
function useDelay(props, cb) {
  let clearDelay = () => {};
  function runDelay(isOpening, options) {
    clearDelay?.();
    const delay = isOpening ? props.openDelay : props.closeDelay;
    const normalizedDelay = Math.max(options?.minDelay ?? 0, Number(delay ?? 0));
    return new Promise(resolve => {
      clearDelay = defer(normalizedDelay, () => {
        cb?.(isOpening);
        resolve(isOpening);
      });
    });
  }
  function runOpenDelay() {
    return runDelay(true);
  }
  function runCloseDelay(options) {
    return runDelay(false, options);
  }
  return {
    clearDelay,
    runOpenDelay,
    runCloseDelay
  };
}

// Components

// Types

const makeActivatorProps = propsFactory({
  target: [String, Object],
  activator: [String, Object],
  activatorProps: {
    type: Object,
    default: () => ({})
  },
  openOnClick: {
    type: Boolean,
    default: undefined
  },
  openOnHover: Boolean,
  openOnFocus: {
    type: Boolean,
    default: undefined
  },
  closeOnContentClick: Boolean,
  ...makeDelayProps()
}, 'VOverlay-activator');
function useActivator(props, {
  isActive,
  isTop,
  contentEl
}) {
  const vm = getCurrentInstance('useActivator');
  const activatorEl = ref();
  let isHovered = false;
  let isFocused = false;
  let firstEnter = true;
  const openOnFocus = computed(() => props.openOnFocus || props.openOnFocus == null && props.openOnHover);
  const openOnClick = computed(() => props.openOnClick || props.openOnClick == null && !props.openOnHover && !openOnFocus.value);
  const {
    runOpenDelay,
    runCloseDelay
  } = useDelay(props, value => {
    if (value === (props.openOnHover && isHovered || openOnFocus.value && isFocused) && !(props.openOnHover && isActive.value && !isTop.value)) {
      if (isActive.value !== value) {
        firstEnter = true;
      }
      isActive.value = value;
    }
  });
  let reopenLock = false;
  watch(isActive, v => {
    if (v) return;
    reopenLock = true;
    setTimeout(() => reopenLock = false, 50);
  });
  const cursorTarget = ref();
  const availableEvents = {
    onClick: e => {
      if (reopenLock && !isActive.value) return;
      e.stopPropagation();
      activatorEl.value = e.currentTarget || e.target;
      if (!isActive.value) {
        cursorTarget.value = [e.clientX, e.clientY];
      }
      isActive.value = !isActive.value;
    },
    onMouseenter: e => {
      isHovered = true;
      activatorEl.value = e.currentTarget || e.target;
      if (props.target === 'cursor') {
        cursorTarget.value = [e.clientX, e.clientY];
      }
      runOpenDelay();
    },
    onMousemove: e => {
      cursorTarget.value = [e.clientX, e.clientY];
    },
    onMouseleave: e => {
      isHovered = false;
      if (props.target === 'cursor') isFocused = false;
      runCloseDelay();
    },
    onFocus: e => {
      if (reopenLock) return;
      if (matchesSelector(e.target, ':focus-visible') === false) return;
      isFocused = true;
      e.stopPropagation();
      activatorEl.value = e.currentTarget || e.target;
      runOpenDelay();
    },
    onBlur: e => {
      // Body parks from clicks on empty areas inside content also count as "still focused".
      const next = e.relatedTarget;
      if (!next || contentEl.value?.contains(next)) return;
      isFocused = false;
      e.stopPropagation();
      runCloseDelay({
        minDelay: 1
      });
    }
  };
  const activatorEvents = computed(() => {
    const events = {};
    if (openOnClick.value) {
      events.onClick = availableEvents.onClick;
    }
    if (props.openOnHover) {
      events.onMouseenter = availableEvents.onMouseenter;
      events.onMouseleave = availableEvents.onMouseleave;
      if (props.target === 'cursor' && !openOnClick.value) {
        events.onMousemove = availableEvents.onMousemove;
      }
    }
    if (openOnFocus.value) {
      events.onFocus = availableEvents.onFocus;
      events.onBlur = availableEvents.onBlur;
    }
    return events;
  });
  const contentEvents = computed(() => {
    const events = {};
    if (props.openOnHover) {
      events.onMouseenter = () => {
        isHovered = true;
        runOpenDelay();
      };
      events.onMouseleave = () => {
        isHovered = false;
        runCloseDelay();
      };
    }
    if (openOnFocus.value) {
      events.onFocusin = e => {
        if (!e.target.matches(':focus-visible')) return;
        isFocused = true;
        runOpenDelay();
      };
      events.onFocusout = e => {
        const next = e.relatedTarget;
        if (!next || contentEl.value?.contains(next)) return;
        isFocused = false;
        runCloseDelay({
          minDelay: 1
        });
      };
    }
    if (props.closeOnContentClick) {
      const menu = inject$1(VMenuSymbol, null);
      events.onClick = () => {
        isActive.value = false;
        menu?.closeParents();
      };
    }
    return events;
  });
  const scrimEvents = computed(() => {
    const events = {};
    if (props.openOnHover) {
      events.onMouseenter = () => {
        if (firstEnter) {
          isHovered = true;
          firstEnter = false;
          runOpenDelay();
        }
      };
      events.onMouseleave = () => {
        isHovered = false;
        runCloseDelay();
      };
    }
    return events;
  });
  watch(isTop, val => {
    if (val && (props.openOnHover && !isHovered && (!openOnFocus.value || !isFocused) || openOnFocus.value && !isFocused && (!props.openOnHover || !isHovered)) && !contentEl.value?.contains(getActiveElement())) {
      runCloseDelay();
    }
  });
  watch(isActive, val => {
    if (!val) {
      setTimeout(() => {
        cursorTarget.value = undefined;
      });
    }
  }, {
    flush: 'post'
  });
  const activatorRef = templateRef();
  watchEffect(() => {
    if (!activatorRef.value) return;
    nextTick(() => {
      activatorEl.value = activatorRef.el;
    });
  });
  const targetRef = templateRef();
  const target = computed(() => {
    if (props.target === 'cursor' && cursorTarget.value) return cursorTarget.value;
    if (targetRef.value) return targetRef.el;
    return getTarget(props.target, vm) || activatorEl.value;
  });
  const targetEl = computed(() => {
    return Array.isArray(target.value) ? undefined : target.value;
  });
  let scope;
  watch(() => !!props.activator, val => {
    if (val && IN_BROWSER) {
      scope = effectScope();
      scope.run(() => {
        _useActivator(props, vm, {
          activatorEl,
          activatorEvents
        });
      });
    } else if (scope) {
      scope.stop();
    }
  }, {
    flush: 'post',
    immediate: true
  });
  onScopeDispose(() => {
    scope?.stop();
  });
  return {
    activatorEl,
    activatorRef,
    target,
    targetEl,
    targetRef,
    activatorEvents,
    contentEvents,
    scrimEvents
  };
}
function _useActivator(props, vm, {
  activatorEl,
  activatorEvents
}) {
  watch(() => props.activator, (val, oldVal) => {
    if (oldVal && val !== oldVal) {
      const activator = getActivator(oldVal);
      activator && unbindActivatorProps(activator);
    }
    if (val) {
      nextTick(() => bindActivatorProps());
    }
  }, {
    immediate: true
  });
  watch(() => props.activatorProps, () => {
    bindActivatorProps();
  });
  onScopeDispose(() => {
    unbindActivatorProps();
  });
  function bindActivatorProps(el = getActivator(), _props = props.activatorProps) {
    if (!el) return;
    bindProps(el, mergeProps(activatorEvents.value, _props));
  }
  function unbindActivatorProps(el = getActivator(), _props = props.activatorProps) {
    if (!el) return;
    unbindProps(el, mergeProps(activatorEvents.value, _props));
  }
  function getActivator(selector = props.activator) {
    const activator = getTarget(selector, vm);

    // The activator should only be a valid element (Ignore comments and text nodes)
    activatorEl.value = activator?.nodeType === Node.ELEMENT_NODE ? activator : undefined;
    return activatorEl.value;
  }
}
function getTarget(selector, vm) {
  if (!selector) return;
  let target;
  if (selector === 'parent') {
    let el = vm?.proxy?.$el?.parentNode;
    while (el?.hasAttribute('data-no-activator')) {
      el = el.parentNode;
    }
    target = el;
  } else if (typeof selector === 'string') {
    // Selector
    target = document.querySelector(selector);
  } else if ('$el' in selector) {
    // Component (ref)
    target = selector.$el;
  } else {
    // HTMLElement | Element | [x, y]
    target = selector;
  }
  return target;
}

// Utilities

// Types

// Types

// Composables
const makeFocusTrapProps = propsFactory({
  retainFocus: Boolean,
  captureFocus: Boolean,
  /** @deprecated */
  disableInitialFocus: Boolean
}, 'focusTrap');
const registry = new Map();
let subscribers = 0;
function lastActiveTrap() {
  let el;
  for (const {
    isActive,
    contentEl
  } of registry.values()) {
    if (isActive.value && contentEl.value) el = contentEl.value;
  }
  return el;
}
function onKeydown(e) {
  const activeElement = getActiveElement();
  if (e.key !== 'Tab' || !activeElement) return;
  const parentTraps = Array.from(registry.values()).filter(({
    isActive,
    contentEl
  }) => isActive.value && contentEl.value?.contains(activeElement)).map(x => x.contentEl.value);
  let closestTrap;
  let currentNode = activeElement;
  while (currentNode) {
    if (parentTraps.includes(currentNode)) {
      closestTrap = currentNode;
      break;
    }
    currentNode = currentNode.parentElement;
  }
  if (!closestTrap) {
    const trapEl = lastActiveTrap(); // assuming last registered == topmost panel
    if (!trapEl) return;
    const focusable = focusableChildren(trapEl).filter(x => x.tabIndex >= 0);
    e.preventDefault();
    if (!focusable.length) {
      trapEl.focus({
        preventScroll: true
      });
    } else if (e.shiftKey) {
      focusable[focusable.length - 1].focus();
    } else {
      focusable[0].focus();
    }
    return;
  }
  const focusable = focusableChildren(closestTrap)
  // excluding VListItems with tabindex="-2"
  .filter(x => x.tabIndex >= 0);
  if (!focusable.length) return;
  if (focusable.length === 1 && focusable[0].classList.contains('v-list') && focusable[0].contains(activeElement)) {
    e.preventDefault();
    return;
  }
  const firstElement = focusable[0];
  const lastElement = focusable[focusable.length - 1];

  // contentEl wrapper (tabindex=-1) counts as "before first"
  const atFirst = activeElement === firstElement || activeElement === closestTrap || firstElement.classList.contains('v-list') && firstElement.contains(activeElement);
  const atLast = activeElement === lastElement || lastElement.classList.contains('v-list') && lastElement.contains(activeElement);
  if (e.shiftKey && atFirst) {
    e.preventDefault();
    lastElement.focus();
  }
  if (!e.shiftKey && atLast) {
    e.preventDefault();
    firstElement.focus();
  }
}
function useFocusTrap(props, {
  isActive,
  localTop,
  contentEl
}) {
  const trapId = Symbol('trap');
  let focusTrapSuppressed = false;
  let focusTrapSuppressionTimeout = -1;
  async function onPointerdown() {
    focusTrapSuppressed = true;
    focusTrapSuppressionTimeout = window.setTimeout(() => {
      focusTrapSuppressed = false;
    }, 100);
  }
  async function captureOnFocus(e) {
    const before = e.relatedTarget;
    const after = e.target;
    document.removeEventListener('pointerdown', onPointerdown);
    document.removeEventListener('keydown', captureOnKeydown);
    await new Promise(resolve => requestAnimationFrame(resolve));
    if (isActive.value && !focusTrapSuppressed && before !== after && contentEl.value &&
    // We're the menu without open submenus or overlays
    toValue(localTop) &&
    // It isn't the document or the container body
    ![document, contentEl.value].includes(after) &&
    // It isn't inside the container body
    !contentEl.value.contains(after)) {
      const focusable = focusableChildren(contentEl.value);
      focusable[0]?.focus();
    }
  }
  function captureOnKeydown(e) {
    if (e.key !== 'Tab') return;
    document.removeEventListener('keydown', captureOnKeydown);
    if (isActive.value && contentEl.value && e.target && !contentEl.value.contains(e.target)) {
      const allFocusableElements = focusableChildren(document.documentElement);
      if (e.shiftKey && e.target === allFocusableElements.at(0) || !e.shiftKey && e.target === allFocusableElements.at(-1)) {
        const focusable = focusableChildren(contentEl.value);
        if (focusable.length > 0) {
          e.preventDefault();
          focusable[0].focus();
        }
      }
    }
  }
  const shouldCapture = toRef(() => isActive.value && props.captureFocus && !props.disableInitialFocus);
  if (IN_BROWSER) {
    watch(() => props.retainFocus, val => {
      if (val) {
        registry.set(trapId, {
          isActive,
          contentEl
        });
      } else {
        registry.delete(trapId);
      }
    }, {
      immediate: true
    });
    watch(shouldCapture, val => {
      if (val) {
        document.addEventListener('pointerdown', onPointerdown);
        document.addEventListener('focusin', captureOnFocus, {
          once: true
        });
        document.addEventListener('keydown', captureOnKeydown);
      } else {
        document.removeEventListener('pointerdown', onPointerdown);
        document.removeEventListener('focusin', captureOnFocus);
        document.removeEventListener('keydown', captureOnKeydown);
      }
    }, {
      immediate: true
    });
    if (subscribers++ < 1) {
      document.addEventListener('keydown', onKeydown);
    }
  }
  onScopeDispose(() => {
    registry.delete(trapId);
    if (!IN_BROWSER) return;
    clearTimeout(focusTrapSuppressionTimeout);
    document.removeEventListener('pointerdown', onPointerdown);
    document.removeEventListener('focusin', captureOnFocus);
    document.removeEventListener('keydown', captureOnKeydown);
    if (--subscribers < 1) {
      document.removeEventListener('keydown', onKeydown);
    }
  });
}

// Composables
function useHydration() {
  if (!IN_BROWSER) return shallowRef(false);
  const {
    ssr
  } = useDisplay();
  if (ssr) {
    const isMounted = shallowRef(false);
    onMounted(() => {
      isMounted.value = true;
    });
    return isMounted;
  } else {
    return shallowRef(true);
  }
}

// Utilities

// Types

const makeLazyProps = propsFactory({
  eager: Boolean
}, 'lazy');
function useLazy(props, active) {
  const isBooted = shallowRef(false);
  const hasContent = toRef(() => isBooted.value || props.eager || active.value);
  watch(active, () => isBooted.value = true);
  function onAfterLeave() {
    if (!props.eager) isBooted.value = false;
  }
  return {
    isBooted,
    hasContent,
    onAfterLeave
  };
}

// Utilities
function useScopeId() {
  const vm = getCurrentInstance('useScopeId');
  const scopeId = vm.vnode.scopeId;
  return {
    scopeId: scopeId ? {
      [scopeId]: ''
    } : undefined
  };
}

// Composables

// Types

const StackSymbol = Symbol.for('vuetify:stack');
const globalStack = reactive([]);
function useStack(isActive, zIndex, disableGlobalStack) {
  const vm = getCurrentInstance('useStack');
  const createStackEntry = !disableGlobalStack;
  const parent = inject$1(StackSymbol, undefined);
  const stack = reactive({
    activeChildren: new Set()
  });
  provide(StackSymbol, stack);
  const _zIndex = shallowRef(Number(toValue(zIndex)));
  useToggleScope(isActive, () => {
    const lastZIndex = globalStack.at(-1)?.[1];
    _zIndex.value = lastZIndex ? lastZIndex + 10 : Number(toValue(zIndex));
    if (createStackEntry) {
      globalStack.push([vm.uid, _zIndex.value]);
    }
    parent?.activeChildren.add(vm.uid);
    onScopeDispose(() => {
      if (createStackEntry) {
        const idx = toRaw(globalStack).findIndex(v => v[0] === vm.uid);
        globalStack.splice(idx, 1);
      }
      parent?.activeChildren.delete(vm.uid);
    });
  });
  const globalTop = shallowRef(true);
  if (createStackEntry) {
    watchEffect(() => {
      const _isTop = globalStack.at(-1)?.[0] === vm.uid;
      setTimeout(() => globalTop.value = _isTop);
    });
  }
  const localTop = toRef(() => !stack.activeChildren.size);
  return {
    globalTop: readonly(globalTop),
    localTop,
    stackStyles: toRef(() => ({
      zIndex: _zIndex.value
    }))
  };
}

// Utilities
function useTeleport(target) {
  const teleportTarget = computed(() => {
    const _target = target();
    if (_target === true || !IN_BROWSER) return undefined;
    const targetElement = _target === false ? document.body : typeof _target === 'string' ? document.querySelector(_target) : _target;
    if (targetElement == null) {
      warn(`Unable to locate target ${_target}`);
      return undefined;
    }
    let container = [...targetElement.children].find(el => el.matches('.v-overlay-container'));
    if (!container) {
      container = document.createElement('div');
      container.className = 'v-overlay-container';
      targetElement.appendChild(container);
    }
    return container;
  });
  return {
    teleportTarget
  };
}

// Utilities

// Types

function defaultConditional() {
  return true;
}
function checkEvent(e, el, binding, ignoreActive = false) {
  // The include element callbacks below can be expensive
  // so we should avoid calling them when we're not active.
  // Explicitly check for false to allow fallback compatibility
  // with non-toggleable components
  if (!e || !ignoreActive && checkIsActive(e, binding) === false) return false;

  // If we're clicking inside the shadowroot, then the app root doesn't get the same
  // level of introspection as to _what_ we're clicking. We want to check to see if
  // our target is the shadowroot parent container, and if it is, ignore.
  const root = attachedRoot(el);
  if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot && root.host === e.target) return false;

  // Check if additional elements were passed to be included in check
  // (click must be outside all included elements, if any)
  const elements = (typeof binding.value === 'object' && binding.value.include || (() => []))();
  // Add the root element for the component this directive was defined on
  elements.push(el);

  // Check if it's a click outside our elements, and then if our callback returns true.
  // Non-toggleable components should take action in their callback and return falsy.
  // Toggleable can return true if it wants to deactivate.
  // Note that, because we're in the capture phase, this callback will occur before
  // the bubbling click event on any outside elements.
  return !elements.some(el => el?.contains(e.target));
}
function checkIsActive(e, binding) {
  const isActive = typeof binding.value === 'object' && binding.value.closeConditional || defaultConditional;
  return isActive(e);
}
function directive(e, el, binding) {
  const handler = typeof binding.value === 'function' ? binding.value : binding.value.handler;

  // Clicks in the Shadow DOM change their target while using setTimeout, so the original target is saved here
  e.shadowTarget = e.target;
  el._clickOutside.lastMousedownWasOutside && checkEvent(e, el, binding) && setTimeout(() => {
    checkIsActive(e, binding) && handler && handler(e);
  }, 0);
}
function handleShadow(el, callback) {
  const root = attachedRoot(el);
  callback(document);
  if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot) {
    callback(root);
  }
}
const ClickOutside = {
  // [data-app] may not be found
  // if using bind, inserted makes
  // sure that the root element is
  // available, iOS does not support
  // clicks on body
  mounted(el, binding) {
    const onClick = e => directive(e, el, binding);
    const onMousedown = e => {
      // Ignore the active check here so ancestors of the top overlay (e.g. a menu
      // with an open submenu, which isn't localTop) still record that the click
      // landed outside, letting the close cascade propagate. #20003
      el._clickOutside.lastMousedownWasOutside = checkEvent(e, el, binding, true);
    };
    handleShadow(el, app => {
      app.addEventListener('click', onClick, true);
      app.addEventListener('mousedown', onMousedown, true);
    });
    if (!el._clickOutside) {
      el._clickOutside = {
        lastMousedownWasOutside: false
      };
    }
    el._clickOutside[binding.instance.$.uid] = {
      onClick,
      onMousedown
    };
  },
  beforeUnmount(el, binding) {
    if (!el._clickOutside) return;
    handleShadow(el, app => {
      if (!app || !el._clickOutside?.[binding.instance.$.uid]) return;
      const {
        onClick,
        onMousedown
      } = el._clickOutside[binding.instance.$.uid];
      app.removeEventListener('click', onClick, true);
      app.removeEventListener('mousedown', onMousedown, true);
    });
    delete el._clickOutside[binding.instance.$.uid];
  }
};

// Types

const overlayActivators = new WeakMap();
function Scrim(props) {
  const {
    modelValue,
    color,
    ...rest
  } = props;
  return createVNode(Transition, {
    "name": "fade-transition",
    "appear": true
  }, {
    default: () => [props.modelValue && createElementVNode("div", mergeProps({
      "class": ['v-overlay__scrim', props.color.backgroundColorClasses.value],
      "style": props.color.backgroundColorStyles.value
    }, rest), null)]
  });
}
const makeVOverlayProps = propsFactory({
  absolute: Boolean,
  attach: [Boolean, String, Object],
  closeOnBack: {
    type: Boolean,
    default: true
  },
  contained: Boolean,
  contentClass: null,
  contentProps: null,
  disabled: Boolean,
  opacity: [Number, String],
  noClickAnimation: Boolean,
  modelValue: Boolean,
  persistent: Boolean,
  scrim: {
    type: [Boolean, String],
    default: true
  },
  zIndex: {
    type: [Number, String],
    default: 2000
  },
  ...makeActivatorProps(),
  ...makeComponentProps(),
  ...makeDimensionProps(),
  ...makeLazyProps(),
  ...makeLocationStrategyProps(),
  ...makeScrollStrategyProps(),
  ...makeFocusTrapProps(),
  ...makeThemeProps(),
  ...makeTransitionProps()
}, 'VOverlay');
const VOverlay = genericComponent()({
  name: 'VOverlay',
  directives: {
    vClickOutside: ClickOutside
  },
  inheritAttrs: false,
  props: {
    _disableGlobalStack: Boolean,
    ...omit(makeVOverlayProps(), ['disableInitialFocus'])
  },
  emits: {
    'click:outside': e => true,
    'update:modelValue': value => true,
    keydown: e => true,
    afterEnter: () => true,
    afterLeave: () => true
  },
  setup(props, {
    slots,
    attrs,
    emit
  }) {
    const vm = getCurrentInstance('VOverlay');
    const root = ref();
    const scrimEl = ref();
    const contentEl = ref();
    const model = useProxiedModel(props, 'modelValue');
    const isActive = computed({
      get: () => model.value,
      set: v => {
        if (!(v && props.disabled)) model.value = v;
      }
    });
    const {
      themeClasses
    } = provideTheme(props);
    const {
      rtlClasses,
      isRtl
    } = useRtl();
    const {
      hasContent,
      onAfterLeave: _onAfterLeave
    } = useLazy(props, isActive);
    const scrimColor = useBackgroundColor(() => {
      return typeof props.scrim === 'string' ? props.scrim : null;
    });
    const {
      globalTop,
      localTop,
      stackStyles
    } = useStack(isActive, () => props.zIndex, props._disableGlobalStack);
    const {
      activatorEl,
      activatorRef,
      target,
      targetEl,
      targetRef,
      activatorEvents,
      contentEvents,
      scrimEvents
    } = useActivator(props, {
      isActive,
      isTop: localTop,
      contentEl
    });
    const {
      teleportTarget
    } = useTeleport(() => {
      const target = props.attach || props.contained;
      if (target) return target;
      const rootNode = activatorEl?.value?.getRootNode() || vm.proxy?.$el?.getRootNode();
      if (rootNode instanceof ShadowRoot) return rootNode;
      return false;
    });
    const {
      dimensionStyles
    } = useDimension(props);
    const isMounted = useHydration();
    const staticLocationClasses = computed(() => {
      return props.locationStrategy === 'static' ? getStaticLocationClasses(props.location) : undefined;
    });
    const {
      scopeId
    } = useScopeId();
    watch(() => props.disabled, v => {
      if (v) isActive.value = false;
    });
    const {
      contentStyles,
      updateLocation
    } = useLocationStrategies(props, {
      isRtl,
      contentEl,
      target,
      isActive
    });
    useScrollStrategies(props, {
      root,
      contentEl,
      targetEl,
      target,
      isActive,
      updateLocation
    });
    function onClickOutside(e) {
      emit('click:outside', e);
      if (!props.persistent) isActive.value = false;else animateClick();
    }
    function closeConditional(e) {
      return isActive.value && localTop.value && (
      // If using scrim, only close if clicking on it rather than anything opened on top
      !props.scrim || e.target === scrimEl.value || e instanceof MouseEvent && e.shadowTarget === scrimEl.value);
    }
    useFocusTrap(props, {
      isActive,
      localTop,
      contentEl
    });
    let openedWithActivatorFocus = false;
    watchEffect(() => {
      if (!contentEl.value) return;
      if (activatorEl.value) overlayActivators.set(contentEl.value, activatorEl.value);else overlayActivators.delete(contentEl.value);
    });
    function ownsFocus(activeElement) {
      let current = activeElement;
      const visited = new Set();
      while (current) {
        const el = current.closest('.v-overlay__content');
        if (!el || visited.has(el)) return false;
        if (el === contentEl.value) return true;
        visited.add(el);
        current = overlayActivators.get(el) ?? null;
      }
      return false;
    }
    function returnFocusToActivator() {
      const el = activatorEl.value;
      if (!el || !el.isConnected) return;
      // Skip submenus; the outermost close in the cascade will restore focus.
      if (el.closest('.v-overlay__content')) return;
      if (contentEl.value?._clickOutside?.lastMousedownWasOutside) return;
      const activeEl = getActiveElement();
      const focusWasInOverlay = (!activeEl || activeEl === document.body) && openedWithActivatorFocus || activeEl === el || el.contains(activeEl) || ownsFocus(activeEl);
      if (!focusWasInOverlay) return;
      const parent = el.parentElement;
      const focusableInParent = parent ? focusableChildren(parent) : [];
      let target;
      if (focusableInParent.includes(el)) {
        target = el;
      } else {
        const focusableWithin = focusableChildren(el);
        target = focusableWithin.find(x => x.tagName === 'INPUT' || x.tagName === 'TEXTAREA') ?? focusableWithin[0];
      }
      target?.focus({
        preventScroll: true
      });
    }
    watch(isActive, val => {
      if (val) {
        const activeEl = getActiveElement();
        const el = activatorEl.value;
        openedWithActivatorFocus = !!el && (activeEl === el || el.contains(activeEl));
        // eager reuses contentEl, so the mousedown that opened us would linger until the next one
        if (contentEl.value?._clickOutside) {
          contentEl.value._clickOutside.lastMousedownWasOutside = false;
        }
      } else {
        returnFocusToActivator();
      }
    }, {
      flush: 'post'
    });
    IN_BROWSER && watch(isActive, val => {
      if (val) {
        window.addEventListener('keydown', onKeydown);
      } else {
        window.removeEventListener('keydown', onKeydown);
      }
    }, {
      immediate: true
    });
    onBeforeUnmount(() => {
      if (!IN_BROWSER) return;
      window.removeEventListener('keydown', onKeydown);
    });
    function onKeydown(e) {
      if (e.key === 'Escape' && globalTop.value) {
        if (!contentEl.value?.contains(getActiveElement())) {
          emit('keydown', e);
        }
        if (!props.persistent) {
          isActive.value = false;
          if (contentEl.value?.contains(getActiveElement())) {
            activatorEl.value?.focus();
          }
        } else animateClick();
      }
    }
    function onKeydownSelf(e) {
      if (e.key === 'Escape' && !globalTop.value) return;
      emit('keydown', e);
    }
    const router = useRouter();
    useToggleScope(() => props.closeOnBack, () => {
      useBackButton(router, () => {
        if (globalTop.value && isActive.value) {
          if (!props.persistent) isActive.value = false;else animateClick();
          return false;
        }
        return undefined;
      });
    });
    const top = ref();
    watch(() => isActive.value && (props.absolute || props.contained) && teleportTarget.value == null, val => {
      if (val) {
        const scrollParent = getScrollParent(root.value);
        if (scrollParent && scrollParent !== document.scrollingElement) {
          top.value = scrollParent.scrollTop;
        }
      }
    });

    // Add a quick "bounce" animation to the content
    function animateClick() {
      if (props.noClickAnimation) return;
      contentEl.value && animate(contentEl.value, [{
        transformOrigin: 'center'
      }, {
        transform: 'scale(1.03)'
      }, {
        transformOrigin: 'center'
      }], {
        duration: 150,
        easing: standardEasing
      });
    }
    function onAfterEnter() {
      emit('afterEnter');
    }
    function onAfterLeave() {
      _onAfterLeave();
      emit('afterLeave');
    }
    useRender(() => createElementVNode(Fragment, null, [slots.activator?.({
      isActive: isActive.value,
      targetRef,
      props: mergeProps({
        ref: activatorRef
      }, activatorEvents.value, props.activatorProps)
    }), isMounted.value && hasContent.value && createVNode(Teleport, {
      "disabled": !teleportTarget.value,
      "to": teleportTarget.value
    }, {
      default: () => [createElementVNode("div", mergeProps({
        "class": ['v-overlay', {
          'v-overlay--absolute': props.absolute || props.contained,
          'v-overlay--active': isActive.value,
          'v-overlay--contained': props.contained
        }, staticLocationClasses.value, themeClasses.value, rtlClasses.value, props.class],
        "style": [stackStyles.value, {
          '--v-overlay-opacity': props.opacity,
          top: convertToUnit(top.value)
        }, props.style],
        "ref": root,
        "onKeydown": onKeydownSelf
      }, scopeId, attrs), [createVNode(Scrim, mergeProps({
        "color": scrimColor,
        "modelValue": isActive.value && !!props.scrim,
        "ref": scrimEl
      }, scrimEvents.value), null), createVNode(MaybeTransition, {
        "appear": true,
        "persisted": true,
        "transition": props.transition,
        "target": target.value,
        "onAfterEnter": onAfterEnter,
        "onAfterLeave": onAfterLeave
      }, {
        default: () => [withDirectives(createElementVNode("div", mergeProps({
          "ref": contentEl,
          "class": ['v-overlay__content', props.contentClass],
          "style": [dimensionStyles.value, contentStyles.value]
        }, contentEvents.value, props.contentProps), [slots.default?.({
          isActive
        })]), [[vShow, isActive.value], [ClickOutside, {
          handler: onClickOutside,
          closeConditional,
          include: () => {
            if (!isActive.value) return [];
            return [activatorEl.value,
            // Submenu clicks count as "inside"; clicks in ancestor overlays (e.g. a host dialog) don't.
            ...Array.from(document.querySelectorAll('.v-overlay__content')).filter(ownsFocus)];
          }
        }]])]
      })])]
    })]));
    return {
      activatorEl,
      scrimEl,
      target,
      animateClick,
      contentEl,
      rootEl: root,
      globalTop,
      localTop,
      updateLocation
    };
  }
});

// Types

const makeVMenuProps = propsFactory({
  // TODO
  // disableKeys: Boolean,
  id: String,
  submenu: Boolean,
  ...omit(makeVOverlayProps({
    captureFocus: true,
    closeDelay: 250,
    closeOnContentClick: true,
    locationStrategy: 'connected',
    location: undefined,
    openDelay: 300,
    scrim: false,
    scrollStrategy: 'reposition',
    transition: {
      component: VDialogTransition
    }
  }), ['absolute'])
}, 'VMenu');
const VMenu = genericComponent()({
  name: 'VMenu',
  props: makeVMenuProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const isActive = useProxiedModel(props, 'modelValue');
    const {
      scopeId
    } = useScopeId();
    const {
      isRtl
    } = useRtl();
    const uid = useId();
    const id = toRef(() => props.id || `v-menu-${uid}`);
    const overlay = ref();
    const parent = inject$1(VMenuSymbol, null);
    const openChildren = shallowRef(new Set());
    provide(VMenuSymbol, {
      register() {
        openChildren.value.add(uid);
      },
      unregister() {
        openChildren.value.delete(uid);
      },
      closeParents(e) {
        const clickedOutside = !e || overlay.value?.contentEl?._clickOutside?.lastMousedownWasOutside;
        setTimeout(() => {
          if (!openChildren.value.size && !props.persistent && clickedOutside) {
            isActive.value = false;
            parent?.closeParents(e);
          }
        }, 40);
      }
    });
    onBeforeUnmount(() => parent?.unregister());
    onDeactivated(() => isActive.value = false);
    watch(isActive, val => {
      val ? parent?.register() : parent?.unregister();
    }, {
      immediate: true
    });
    function onClickOutside(e) {
      parent?.closeParents(e);
    }
    function onKeydown(e) {
      if (props.disabled) return;
      if (e.key === 'Tab') {
        const nextElement = getNextElement(focusableChildren(overlay.value?.contentEl, false), e.shiftKey ? 'prev' : 'next', el => el.tabIndex >= 0);
        if (!nextElement && !props.retainFocus) {
          isActive.value = false;
        }
      } else if (props.submenu && e.key === (isRtl.value ? 'ArrowRight' : 'ArrowLeft')) {
        isActive.value = false;
      }
    }
    function onActivatorKeydown(e) {
      if (props.disabled || e.isComposing) return;
      const el = overlay.value?.contentEl;
      if (el && isActive.value) {
        if (e.key === 'ArrowDown') {
          e.preventDefault();
          e.stopImmediatePropagation();
          focusChild(el, 'next');
        } else if (e.key === 'ArrowUp') {
          e.preventDefault();
          e.stopImmediatePropagation();
          focusChild(el, 'prev');
        } else if (props.submenu) {
          if (e.key === (isRtl.value ? 'ArrowRight' : 'ArrowLeft')) {
            isActive.value = false;
          } else if (e.key === (isRtl.value ? 'ArrowLeft' : 'ArrowRight')) {
            e.preventDefault();
            focusChild(el, 'first');
          }
        }
      } else if (props.submenu ? e.key === (isRtl.value ? 'ArrowLeft' : 'ArrowRight') : ['ArrowDown', 'ArrowUp'].includes(e.key)) {
        isActive.value = true;
        e.preventDefault();
        setTimeout(() => setTimeout(() => onActivatorKeydown(e)));
      }
    }
    const activatorProps = computed(() => mergeProps({
      'aria-haspopup': 'menu',
      'aria-expanded': String(isActive.value),
      'aria-controls': id.value,
      'aria-owns': id.value,
      onKeydown: onActivatorKeydown
    }, props.activatorProps));
    useRender(() => {
      const overlayProps = VOverlay.filterProps(props);
      return createVNode(VOverlay, mergeProps({
        "ref": overlay,
        "id": id.value,
        "class": ['v-menu', props.class],
        "style": props.style
      }, overlayProps, {
        "modelValue": isActive.value,
        "onUpdate:modelValue": $event => isActive.value = $event,
        "absolute": true,
        "activatorProps": activatorProps.value,
        "location": props.location ?? (props.submenu ? 'end' : 'bottom'),
        "onClick:outside": onClickOutside,
        "onKeydown": onKeydown
      }, scopeId), {
        activator: slots.activator,
        default: (...args) => createVNode(VDefaultsProvider, {
          "root": "VMenu"
        }, {
          default: () => [slots.default?.(...args)]
        })
      });
    });
    return forwardRefs({
      id,
      ΨopenChildren: openChildren
    }, overlay);
  }
});

const makeVSheetProps = propsFactory({
  color: String,
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeDimensionProps(),
  ...makeElevationProps(),
  ...makeLocationProps(),
  ...makePositionProps(),
  ...makeRoundedProps(),
  ...makeTagProps(),
  ...makeThemeProps()
}, 'VSheet');
const VSheet = genericComponent()({
  name: 'VSheet',
  props: makeVSheetProps(),
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      borderClasses
    } = useBorder(props);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      locationStyles
    } = useLocation(props);
    const {
      positionClasses
    } = usePosition(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-sheet', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, props.class]),
      "style": normalizeStyle([backgroundColorStyles.value, dimensionStyles.value, locationStyles.value, roundedStyles.value, props.style])
    }, slots));
    return {};
  }
});

// Types

const makeVCounterProps = propsFactory({
  active: Boolean,
  disabled: Boolean,
  max: [Number, String],
  value: {
    type: [Number, String],
    default: 0
  },
  ...makeComponentProps(),
  ...makeTransitionProps({
    transition: {
      component: VSlideYTransition
    }
  })
}, 'VCounter');
const 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(createElementVNode("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 {};
  }
});

const makeVFieldLabelProps = propsFactory({
  floating: Boolean,
  ...makeComponentProps()
}, 'VFieldLabel');
const 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 {};
  }
});

// Types

const allowedVariants$3 = ['underlined', 'outlined', 'filled', 'solo', 'solo-inverted', 'solo-filled', 'plain'];
const makeVFieldProps = propsFactory({
  appendInnerIcon: IconValue,
  bgColor: String,
  clearable: Boolean,
  clearIcon: {
    type: IconValue,
    default: '$clear'
  },
  active: Boolean,
  centerAffix: {
    type: Boolean,
    default: undefined
  },
  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$3.includes(v)
  },
  'onClick:clear': EventProp(),
  'onClick:appendInner': EventProp(),
  'onClick:prependInner': EventProp(),
  ...makeComponentProps(),
  ...makeLoaderProps(),
  ...makeRoundedProps(),
  ...makeThemeProps()
}, 'VField');
const 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,
      roundedStyles
    } = 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 ? undefined : `${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 ? undefined : 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 undefined;
      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 / 0.75;
          const width = Math.abs(targetWidth - rect.width) > 1 ? {
            maxWidth: convertToUnit(targetWidth)
          } : undefined;
          const style = getComputedStyle(el);
          const targetStyle = getComputedStyle(targetEl);
          const duration = parseFloat(style.transitionDuration) * 1000 || 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 ? undefined : id.value
      };
    });
    const mainLabelProps = toRef(() => {
      const ariaHidden = hasFloatingLabel.value && isActive.value;
      return {
        'aria-hidden': ariaHidden,
        for: ariaHidden ? undefined : id.value
      };
    });
    function onClick(e) {
      if (e.target !== getActiveElement()) {
        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 createElementVNode("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, roundedStyles.value, props.style],
        "onClick": onClick
      }, attrs), [createElementVNode("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 && createElementVNode("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)]), createElementVNode("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
      }) ?? createElementVNode("div", {
        "id": id.value,
        "class": "v-field__input",
        "aria-describedby": messagesId.value
      }, null)]), hasClear && createVNode(VExpandXTransition, {
        "key": "clear"
      }, {
        default: () => [withDirectives(createElementVNode("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 && createElementVNode("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)]), createElementVNode("div", {
        "class": normalizeClass(['v-field__outline', textColorClasses.value]),
        "style": normalizeStyle(textColorStyles.value)
      }, [isOutlined && createElementVNode(Fragment, null, [createElementVNode("div", {
        "class": "v-field__outline__start"
      }, null), hasFloatingLabel.value && createElementVNode("div", {
        "class": "v-field__outline__notch"
      }, [createVNode(VFieldLabel, mergeProps({
        "ref": floatingLabelRef,
        "floating": true
      }, floatingLabelProps.value), {
        default: () => [label()]
      })]), createElementVNode("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
    };
  }
});

// Utilities

// Types

// Types

// Composables
const 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 undefined;
    return isSuppressing.value ? `${props.name}-${uniqueId}-${reloadTrigger.value}` : props.name;
  });
  const fieldAutocomplete = toRef(() => {
    return isSuppressing.value ? 'off' : props.autocomplete;
  });
  return {
    isSuppressing,
    fieldAutocomplete,
    fieldName,
    update: () => reloadTrigger.value = new Date().getTime()
  };
}

function useAutofocus(props) {
  function onIntersect(isIntersecting, entries) {
    if (!props.autofocus || !isIntersecting) return;
    const el = entries[0].target;
    const target = el.matches('input,textarea') ? el : el.querySelector('input,textarea');

    // Defer past overlay enter setup (e.g. VDialogTransition visibility:hidden)
    setTimeout(() => target?.focus(), 50);
  }
  return {
    onIntersect
  };
}

// Types

const activeTypes = ['color', 'file', 'time', 'date', 'datetime-local', 'week', 'month'];
const 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');
const 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', undefined, 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 undefined;
      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 !== getActiveElement()) {
          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) {
          // #22307 - Whitespace has been removed from the
          // start, offset the caret position to compensate
          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 = props.hideDetails !== true && !!(slots.details || hasCounter && (props.persistentCounter || props.hideDetails === false || isFocused.value));
      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 = createElementVNode("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 createElementVNode(Fragment, null, [props.prefix && createElementVNode("span", {
              "class": "v-text-field__prefix"
            }, [createElementVNode("span", {
              "class": "v-text-field__prefix__text"
            }, [props.prefix])]), withDirectives(slots.default ? createElementVNode("div", {
              "class": normalizeClass(fieldClass),
              "data-no-activator": ""
            }, [slots.default({
              id
            }), inputNode]) : cloneVNode(inputNode, {
              class: fieldClass
            }), [[Intersect, onIntersect, null, {
              once: true
            }]]), props.suffix && createElementVNode("span", {
              "class": "v-text-field__suffix"
            }, [createElementVNode("span", {
              "class": "v-text-field__suffix__text"
            }, [props.suffix])])]);
          }
        }),
        details: hasDetails ? slotProps => createElementVNode(Fragment, null, [slots.details?.(slotProps), hasCounter && createElementVNode(Fragment, null, [createElementVNode("span", null, null), createVNode(VCounter, {
          "active": props.persistentCounter || isFocused.value,
          "value": counterValue.value,
          "max": max.value,
          "disabled": props.disabled
        }, slots.counter)])]) : undefined
      });
    });
    return forwardRefs({}, vInputRef, vFieldRef, inputRef);
  }
});

// Types

const makeVVirtualScrollItemProps = propsFactory({
  renderless: Boolean,
  ...makeComponentProps()
}, 'VVirtualScrollItem');
const VVirtualScrollItem = genericComponent()({
  name: 'VVirtualScrollItem',
  inheritAttrs: false,
  props: makeVVirtualScrollItemProps(),
  emits: {
    'update:height': height => true
  },
  setup(props, {
    attrs,
    emit,
    slots
  }) {
    const {
      resizeRef,
      contentRect
    } = useResizeObserver(undefined, 'border');
    watch(() => contentRect.value?.height, height => {
      if (height != null) emit('update:height', height);
    });
    useRender(() => props.renderless ? createElementVNode(Fragment, null, [slots.default?.({
      itemRef: resizeRef
    })]) : createElementVNode("div", mergeProps({
      "ref": resizeRef,
      "class": ['v-virtual-scroll__item', props.class],
      "style": props.style
    }, attrs), [slots.default?.()]));
  }
});

// Composables

// Types

const UP = -1;
const DOWN = 1;

/** Determines how large each batch of items should be */
const BUFFER_PX = 100;
const 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(
  // Assume 16px items filling the entire screen height if
  // not provided. This is probably incorrect but it minimises
  // the chance of ending up with empty space at the bottom.
  // The default value is set here to avoid poisoning getSize()
  (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
  });
  let heights = new Map();
  const updateTime = shallowRef(0);
  let targetScrollIndex = -1;
  let targetScrollHeight = 0;
  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);
    calculateVisibleItems();
  }, updateTime);
  const unwatch = watch(hasInitialRender, v => {
    if (!v) return;
    // First render is complete, update offsets and visible
    // items in case our assumed item height was incorrect

    unwatch();
    markerOffset = markerRef.value.offsetTop;
    updateOffsets.immediate();
    calculateVisibleItems();
    if (!~targetScrollIndex) return;
    nextTick(() => {
      IN_BROWSER && window.requestAnimationFrame(() => {
        if (~targetScrollIndex) scrollToIndex(targetScrollIndex);
      });
    });
  });
  onScopeDispose(() => {
    updateOffsets.clear();
  });
  function estimateItemHeight() {
    let total = 0;
    for (const count of heights.values()) total += count;
    let seen = 0;
    for (const height of [...heights.keys()].sort((a, b) => a - b)) {
      seen += heights.get(height);
      if (seen * 2 >= total) return height;
    }
    return itemHeight.value;
  }
  function handleItemResize(index, height) {
    const prevHeight = sizes[index];
    const prevItemHeight = itemHeight.value;
    if (height > 0) {
      if (prevHeight) {
        const count = heights.get(prevHeight) - 1;
        count ? heights.set(prevHeight, count) : heights.delete(prevHeight);
      }
      heights.set(height, (heights.get(height) ?? 0) + 1);
      itemHeight.value = estimateItemHeight();
    }
    if (prevHeight !== height || prevItemHeight !== 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;
    const nextOffset = offsets[next] || wholeOffset;
    return wholeOffset + (nextOffset - 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();
    const scrollDeltaT = scrollTime - lastScrollTime;
    if (scrollDeltaT > 500) {
      scrollVelocity = Math.sign(scrollTop - lastScrollTop);

      // Not super important, only update at the
      // start of a scroll sequence to avoid reflows
      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 startPx = Math.max(0, scrollTop - BUFFER_PX);
    const start = clamp(calculateIndex(startPx), 0, items.value.length);
    const endPx = scrollTop + viewportHeight.value + BUFFER_PX;
    const end = clamp(calculateIndex(endPx) + 1, start + 1, items.value.length);
    if (
    // Only update the side we're scrolling towards,
    // the other side will be updated incidentally
    (direction !== UP || start < first.value) && (direction !== DOWN || end > last.value)) {
      const topOverflow = calculateOffset(first.value) - calculateOffset(start);
      const bottomOverflow = calculateOffset(end) - calculateOffset(last.value);
      const bufferOverflow = Math.max(topOverflow, bottomOverflow);
      if (bufferOverflow > BUFFER_PX) {
        first.value = start;
        last.value = end;
      } else {
        // Only update the side that's reached its limit if there's still buffer left
        if (start <= 0) first.value = start;
        if (end >= items.value.length) {
          last.value = end;
          first.value = start;
        }
      }
    }
    paddingTop.value = calculateOffset(first.value);
    paddingBottom.value = calculateOffset(items.value.length) - calculateOffset(last.value);
  }
  function scrollToIndex(index) {
    if (targetScrollIndex !== index) targetScrollHeight = 0;
    const offset = calculateOffset(index);
    if (!containerRef.value || index && !offset) {
      targetScrollIndex = index;
      return;
    }

    // Move the window first so paddingTop/Bottom make scrollHeight large enough
    // before we assign scrollTop (otherwise the browser clamps the scroll).
    const itemSize = itemHeight.value || 16;
    const buffer = Math.ceil(BUFFER_PX / itemSize);
    const viewport = Math.max(1, Math.ceil((viewportHeight.value || 0) / itemSize));
    first.value = clamp(index - buffer, 0, Math.max(0, items.value.length - 1));
    last.value = clamp(index + viewport + buffer, first.value + 1, items.value.length);
    paddingTop.value = calculateOffset(first.value);
    paddingBottom.value = calculateOffset(items.value.length) - calculateOffset(last.value);
    scrollVelocity = 0;
    lastScrollTime = 0;
    targetScrollIndex = index;
    nextTick(() => {
      const el = containerRef.value;
      // Superseded by a later scrollToIndex
      if (!el || !~targetScrollIndex || targetScrollIndex !== index) return;
      const top = calculateOffset(index);
      el.scrollTop = top;
      // Resize-driven calculateVisibleItems reads lastScrollTop, not the DOM
      lastScrollTop = el.scrollTop;
      if (index && el.scrollTop < top - 1 && el.scrollHeight > targetScrollHeight) {
        targetScrollHeight = el.scrollHeight;
        IN_BROWSER && requestAnimationFrame(() => {
          if (targetScrollIndex === index) scrollToIndex(index);
        });
      } else {
        targetScrollIndex = -1;
        calculateVisibleItems();
      }
    });
  }
  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
    });
    heights = new Map();
    updateOffsets.immediate();
    calculateVisibleItems();
  }, {
    deep: 1
  });
  return {
    calculateVisibleItems,
    containerRef,
    markerRef,
    computedItems,
    paddingTop,
    paddingBottom,
    scrollToIndex,
    handleScroll,
    handleScrollend,
    handleItemResize
  };
}

// https://gist.github.com/robertleeplummerjr/1cc657191d34ecd0a324
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;
}

// Types

const makeVVirtualScrollProps = propsFactory({
  items: {
    type: Array,
    default: () => []
  },
  renderless: Boolean,
  ...makeVirtualProps(),
  ...makeComponentProps(),
  ...makeDimensionProps()
}, 'VVirtualScroll');
const 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 ? createElementVNode(Fragment, null, [createElementVNode("div", {
        "ref": markerRef,
        "class": "v-virtual-scroll__spacer",
        "style": {
          paddingTop: convertToUnit(paddingTop.value)
        }
      }, null), children, createElementVNode("div", {
        "class": "v-virtual-scroll__spacer",
        "style": {
          paddingBottom: convertToUnit(paddingBottom.value)
        }
      }, null)]) : createElementVNode("div", {
        "ref": containerRef,
        "class": normalizeClass(['v-virtual-scroll', props.class]),
        "onScrollPassive": handleScroll,
        "onScrollend": handleScrollend,
        "style": normalizeStyle([dimensionStyles.value, props.style])
      }, [createElementVNode("div", {
        "ref": markerRef,
        "class": "v-virtual-scroll__container",
        "style": {
          paddingTop: convertToUnit(paddingTop.value),
          paddingBottom: convertToUnit(paddingBottom.value)
        }
      }, [children])]);
    });
    return {
      calculateVisibleItems,
      scrollToIndex
    };
  }
});

// Utilities

// Types

function mergeRanges(ranges) {
  const sorted = ranges.filter(span => span[0] < span[1]).toSorted((a, b) => a[0] - b[0]);
  const merged = [];
  for (const span of sorted) {
    const last = merged.at(-1);
    if (last && span[0] <= last[1]) last[1] = Math.max(last[1], span[1]);else merged.push([span[0], span[1]]);
  }
  return merged;
}
function chunkText(text, ranges) {
  const chunks = [];
  let cursor = 0;
  for (const [start, end] of ranges) {
    if (cursor < start) chunks.push({
      text: text.slice(cursor, start),
      match: false
    });
    chunks.push({
      text: text.slice(start, end),
      match: true
    });
    cursor = end;
  }
  if (cursor < text.length) chunks.push({
    text: text.slice(cursor),
    match: false
  });
  return chunks;
}
function findRanges(text, query, matchAll, ignoreCase) {
  const terms = wrapInArray(query).filter(Boolean);
  const haystack = ignoreCase ? text.toLocaleLowerCase() : text;
  const spans = [];
  for (const term of terms) {
    const needle = ignoreCase ? term.toLocaleLowerCase() : term;
    let index = haystack.indexOf(needle);
    if (index !== -1) {
      spans.push([index, index + term.length]);
      if (matchAll) {
        index = haystack.indexOf(needle, index + term.length);
        while (index !== -1) {
          spans.push([index, index + term.length]);
          index = haystack.indexOf(needle, index + term.length);
        }
      }
    }
  }
  return mergeRanges(spans);
}

// mirror of `toHighlight` from `@vuetify/v0`
// temporary shim, to be replaced in v5.0
function toHighlight(text, query, options = {}) {
  const _text = toValue(text);
  const _query = toValue(query);
  const _matches = toValue(options.matches);
  const matchAll = toValue(options.matchAll) ?? false;
  const ignoreCase = toValue(options.ignoreCase) ?? false;
  if (_matches?.length) return chunkText(_text, mergeRanges(_matches));
  if (_query) {
    const ranges = findRanges(_text, _query, matchAll, ignoreCase);
    return ranges.length > 0 ? chunkText(_text, ranges) : [{
      text: _text,
      match: false
    }];
  }
  return [{
    text: _text,
    match: false
  }];
}

// Types

const makeVHighlightProps = propsFactory({
  text: {
    type: String,
    default: ''
  },
  query: [String, Array],
  matches: Array,
  matchAll: Boolean,
  ignoreCase: Boolean,
  color: String,
  opacity: [String, Number],
  markClass: String,
  ...makeTagProps({
    tag: 'span'
  })
}, 'VHighlight');
const VHighlight = defineComponent({
  name: 'VHighlight',
  props: makeVHighlightProps(),
  setup(props) {
    const chunks = computed(() => toHighlight(() => props.text, () => props.query, {
      matches: () => props.matches,
      matchAll: () => props.matchAll,
      ignoreCase: () => props.ignoreCase
    }));
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.color);
    return () => createVNode(props.tag, {
      "class": "v-highlight"
    }, {
      default: () => [chunks.value.map((chunk, i) => chunk.match ? createElementVNode("mark", {
        "key": i,
        "class": normalizeClass(['v-highlight__mark', textColorClasses.value, props.markClass]),
        "style": normalizeStyle([textColorStyles.value, {
          '--v-highlight-opacity': props.opacity
        }])
      }, [chunk.text]) : createElementVNode("span", {
        "key": i
      }, [chunk.text]))]
    });
  }
});

// Utilities

// Types

function useFocusRepair(active, content, fallback) {
  return function repairOrphanedFocus(e) {
    if (!e.relatedTarget && document.activeElement === document.body && active.value) {
      requestAnimationFrame(() => {
        if (!active.value) return;
        const el = content();
        const target = (el && focusableChildren(el)[0]) ?? fallback();
        target?.focus({
          preventScroll: true
        });
      });
      return true;
    }
    return false;
  };
}

// Utilities

// Types

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
  }; // typescript doesn't know about vue's event merging
}

// Utilities

// Types

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];
      const isListGroup = originGroup.type === 'list';
      const atEdge = isListGroup || (direction === 'forward' ? origin.at(-1) === e.target : origin.at(0) === e.target);
      if (atEdge) {
        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];

    // List groups always allow leaving (VList manages internal focus)
    // Element groups require being at the edge focusable child
    if (originGroup.type !== 'list') {
      const isAtEdge = direction === 'forward' ? origin.at(-1) === target : origin.at(0) === target;
      if (!isAtEdge) 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
  };
}

/* eslint-disable max-statements */
/* eslint-disable no-labels */


// Types

/**
 * - boolean: match without highlight
 * - number: single match (index), length already known
 * - []: single match (start, end)
 * - [][]: multiple matches (start, end), shouldn't overlap
 */

// Composables
const 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];
}
const makeFilterProps = propsFactory({
  customFilter: Function,
  customKeyFilter: Object,
  filterKeys: [Array, String],
  filterMode: {
    type: String,
    default: 'intersection'
  },
  noFilter: Boolean
}, 'filter');

// eslint-disable-next-line complexity
function filterItems(items, query, options) {
  const array = [];
  // always ensure we fall back to a functioning filter
  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') {
            // clear unless, divider appears before 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(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 = new Map();
    results.forEach(({
      index,
      matches
    }) => {
      const item = originalItems[index];
      _filteredItems.push(item);
      if (item.value !== undefined) {
        _filteredMatches.set(item.value, matches);
      }
    });
    filteredItems.value = _filteredItems;
    filteredMatches.value = _filteredMatches;
  });
  function getMatches(item) {
    return filteredMatches.value.get(item.value);
  }
  return {
    filteredItems,
    filteredMatches,
    getMatches
  };
}

// Utilities

// Types

// Types

// Composables
const 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}`);
  const ariaExpanded = toRef(() => toValue(isOpen));
  const ariaControls = toRef(() => menuId.value);
  return {
    menuId,
    ariaExpanded,
    ariaControls
  };
}

// Types

const 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');
const makeVSelectProps = propsFactory({
  search: String,
  ...makeFilterProps({
    filterKeys: ['title']
  }),
  ...makeSelectProps(),
  ...omit(makeVTextFieldProps({
    modelValue: null,
    role: 'combobox'
  }), ['validationValue', 'dirty']),
  ...makeTransitionProps({
    transition: {
      component: VDialogTransition
    }
  })
}, 'VSelect');
const 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;
    let openedByKeyboard = false;
    let openedByArrow = null;
    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' // Set aria-haspopup to 'listbox'
        }
      };
    });
    const listRef = ref();
    const listEvents = useScrolling(listRef, vTextFieldRef);
    const repairOrphanedFocus = useFocusRepair(menu, () => vMenuRef.value?.contentEl, () => vTextFieldRef.value?.controlRef);
    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;
      openedByKeyboard = false;
      openedByArrow = null;
      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 (['ArrowDown', 'ArrowUp'].includes(e.key)) {
        openedByArrow = e.key === 'ArrowDown' ? 'next' : 'prev';
      } else if (['Enter', ' '].includes(e.key)) {
        openedByArrow = null;
      }
      if (['Enter', 'ArrowDown', ' '].includes(e.key)) {
        openedByKeyboard = true;
        menu.value = true;
      }
      if (['Escape', 'Tab'].includes(e.key)) {
        menu.value = false;
      }
      if (props.clearable && e.key === 'Backspace') {
        e.preventDefault();
        model.value = [];
        onClear();
        return;
      }
      if (e.key === 'Home') {
        listRef.value?.focus('first');
      } else if (e.key === 'End') {
        listRef.value?.focus('last');
      }

      // html select hotkeys
      const KEYBOARD_LOOKUP_THRESHOLD = 1000; // milliseconds

      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)) {
          // No matches but we have a repeated letter, try the next item with that prefix
          keyboardLookupPrefix = keyboardLookupPrefix.slice(0, -1);
          keyboardLookupIndex++;
          result = findItemBase();
          if (result) return result;
        }

        // Still nothing, wrap around to the top
        keyboardLookupIndex = 0;
        result = findItemBase();
        if (result) return result;

        // Still nothing, try just the new letter
        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];
          }
        }
        return undefined;
      }
      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 {
        const add = set !== false;
        model.value = add ? [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 focusSelectedItem(options) {
      // Virtual list only mounts a window — numeric index into DOM children is wrong
      const selected = listRef.value?.$el?.querySelector?.('[aria-selected="true"]');
      if (!selected) return false;
      selected.focus(options);
      return true;
    }
    function onAfterEnter() {
      if (props.eager) {
        vVirtualScrollRef.value?.calculateVisibleItems();
      }
      if (!listRef.value || !isFocused.value) return;

      // VMenu re-dispatches ArrowUp/Down after open and already moved focus to next/prev
      if (listRef.value.$el?.contains(getActiveElement())) return;
      const opts = {
        focusVisible: false,
        preventScroll: props.noAutoScroll
      };

      // fallback for VMenu's re-dispatch; fires before the virtual list has scrolled
      if (openedByArrow) {
        listRef.value.focus(openedByArrow, opts);
        return;
      }
      if (focusSelectedItem(opts)) return;
      if (openedByKeyboard) {
        listRef.value.focus('first', opts);
      }
    }
    function onAfterLeave() {
      search.value = '';
      if (isFocused.value) {
        if (vMenuRef.value?.contentEl?._clickOutside?.lastMousedownWasOutside) {
          isFocused.value = false;
        } else {
          vTextFieldRef.value?.focus();
        }
      }
    }
    function onFocusin(e) {
      isFocused.value = true;
    }
    function onFocusout(e) {
      if (!vTextFieldRef.value?.$el.contains(e.relatedTarget) && !e.currentTarget.contains(e.relatedTarget)) {
        if (repairOrphanedFocus(e)) return;
        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, val => {
      if (!val) {
        openedByKeyboard = false;
        openedByArrow = null;
      }
      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 ? undefined : 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": undefined,
        "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
        }) => createElementVNode(Fragment, null, [createElementVNode("select", {
          "hidden": true,
          "multiple": props.multiple,
          "name": autocomplete.fieldName.value
        }, [items.value.map(item => createElementVNode("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",
          "captureFocus": false,
          "disabled": menuDisabled.value,
          "eager": props.eager,
          "maxHeight": 310,
          "openOnClick": false,
          "closeOnContentClick": false,
          "transition": props.transition,
          "onAfterEnter": onAfterEnter,
          "onAfterLeave": onAfterLeave
        }, computedMenuProps.value, {
          "contentClass": ['v-select__content', computedMenuProps.value.contentClass]
        }), {
          default: () => [createVNode(VSheet, {
            "elevation": props.menuElevation,
            "onFocusin": onFocusin,
            "onFocusout": onFocusout,
            "onKeydown": onMenuKeydown
          }, {
            default: () => [slots['menu-header'] && createElementVNode("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, {
                      "ref": itemRef,
                      "key": `divider-${index}`
                    }), null);
                  }
                  if (item.type === 'subheader') {
                    return slots.subheader?.({
                      props: item.raw,
                      index
                    }) ?? createVNode(VListSubheader, mergeProps(item.props, {
                      "ref": itemRef,
                      "key": `subheader-${index}`
                    }), null);
                  }
                  return slots.item?.({
                    item: item.raw,
                    internalItem: item,
                    index,
                    props: itemProps
                  }) ?? createVNode(VListItem, mergeProps(itemProps, {
                    "role": "option"
                  }), {
                    prepend: ({
                      isSelected
                    }) => createElementVNode(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) : undefined, camelizedProps.prependAvatar && createVNode(VAvatar, {
                      "image": camelizedProps.prependAvatar
                    }, null), camelizedProps.prependIcon && createVNode(VIcon, {
                      "icon": camelizedProps.prependIcon
                    }, null)]),
                    title: () => {
                      return search.value ? createVNode(VHighlight, {
                        "text": item.title,
                        "matches": getMatches(item)?.title,
                        "markClass": "v-select__mask",
                        "matchAll": true,
                        "ignoreCase": true
                      }, null) : item.title;
                    }
                  });
                }
              }), slots['append-item']?.()]
            }), slots['menu-footer'] && createElementVNode("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': undefined
          });
          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
          })) : undefined;
          if (hasSlot && !slotContent) return undefined;
          return createElementVNode("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 ?? createElementVNode("span", {
            "class": "v-select__selection-text"
          }, [item.title, props.multiple && index < model.value.length - 1 && createElementVNode("span", {
            "class": "v-select__selection-comma"
          }, [createTextVNode(",")])])]);
        })]),
        'append-inner': (...args) => createElementVNode(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) : undefined, props.appendInnerIcon && createVNode(InputIcon, {
          "key": "append-icon",
          "name": "appendInner",
          "color": args[0].iconColor.value
        }, null)])
      });
    });
    return forwardRefs({
      isFocused,
      menu,
      search,
      filteredItems,
      select
    }, vTextFieldRef);
  }
});

// Types

const makeVAutocompleteProps = propsFactory({
  autoSelectFirst: {
    type: [Boolean, String]
  },
  clearOnSelect: Boolean,
  search: String,
  ...makeFilterProps({
    filterKeys: ['title']
  }),
  ...makeSelectProps(),
  ...omit(makeVTextFieldProps({
    modelValue: null,
    role: 'combobox'
  }), ['validationValue', 'dirty'])
}, 'VAutocomplete');
const VAutocomplete = genericComponent()({
  name: 'VAutocomplete',
  props: makeVAutocompleteProps(),
  emits: {
    'update:focused': focused => true,
    'update:search': value => true,
    'update:modelValue': value => true,
    'update:menu': value => true
  },
  setup(props, {
    slots
  }) {
    const {
      t
    } = useLocale();
    const vTextFieldRef = ref();
    const isFocused = shallowRef(false);
    const isPristine = shallowRef(true);
    const listHasFocus = shallowRef(false);
    const vMenuRef = ref();
    const vVirtualScrollRef = ref();
    const selectionIndex = shallowRef(-1);
    const _searchLock = shallowRef(null);
    const {
      items,
      transformIn,
      transformOut
    } = useItems(props);
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => vTextFieldRef.value?.color);
    const {
      InputIcon
    } = useInputIcon(props);
    const search = useProxiedModel(props, 'search', '');
    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 {
      filteredItems,
      getMatches
    } = useFilter(props, items, () => _searchLock.value ?? (isPristine.value ? '' : search.value));
    const displayItems = computed(() => {
      if (props.hideSelected && _searchLock.value === null) {
        return filteredItems.value.filter(filteredItem => !model.value.some(s => s.value === filteredItem.value));
      }
      return filteredItems.value;
    });
    const closableChips = toRef(() => props.closableChips && !form.isReadonly.value && !form.isDisabled.value);
    const hasChips = computed(() => !!(props.chips || slots.chip));
    const hasSelectionSlot = computed(() => hasChips.value || !!slots.selection);
    const selectedValues = computed(() => model.value.map(selection => selection.props.value));
    const firstSelectableItem = computed(() => displayItems.value.find(x => x.type === 'item' && !x.props.disabled));
    const highlightFirst = computed(() => {
      const selectFirst = props.autoSelectFirst === true || props.autoSelectFirst === 'exact' && search.value === firstSelectableItem.value?.title;
      return selectFirst && displayItems.value.length > 0 && !isPristine.value && !listHasFocus.value;
    });
    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 listRef = ref();
    const headerRef = ref();
    const footerRef = ref();
    const listEvents = useScrolling(listRef, vTextFieldRef);
    const repairOrphanedFocus = useFocusRepair(menu, () => vMenuRef.value?.contentEl, () => vTextFieldRef.value?.controlRef);
    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;
      }
      search.value = '';
    }
    function onMousedownControl() {
      if (menuDisabled.value) return;
      menu.value = true;
    }
    function onMousedownMenuIcon(e) {
      if (menuDisabled.value) return;
      if (isFocused.value) {
        e.preventDefault();
        e.stopPropagation();
      }
      menu.value = !menu.value;
    }
    function onMenuKeydown(e) {
      if (e.key === 'Tab') {
        onTabKeydown(e);
      }
      if (listRef.value?.$el.contains(e.target) && (checkPrintable(e) || e.key === 'Backspace')) {
        vTextFieldRef.value?.focus();
      }
    }

    // eslint-disable-next-line complexity
    function onKeydown(e) {
      if (isComposingIgnoreKey(e) || form.isReadonly.value) return;
      const selectionStart = vTextFieldRef.value?.selectionStart;
      const length = model.value.length;
      if (['Enter', 'ArrowDown', 'ArrowUp'].includes(e.key)) {
        e.preventDefault();
      }
      if (['Enter', 'ArrowDown'].includes(e.key)) {
        menu.value = true;
      }
      if (['Escape'].includes(e.key)) {
        menu.value = false;
      }
      if (highlightFirst.value && ['Enter', 'Tab'].includes(e.key) && firstSelectableItem.value && !model.value.some(({
        value
      }) => value === firstSelectableItem.value.value)) {
        select(firstSelectableItem.value);
      }
      if (e.key === 'ArrowDown' && highlightFirst.value) {
        listRef.value?.focus('next');
      }
      if (['Backspace', 'Delete'].includes(e.key)) {
        if (!props.multiple && hasSelectionSlot.value && model.value.length > 0 && !search.value) return select(model.value[0], false);
        if (~selectionIndex.value) {
          e.preventDefault();
          const originalSelectionIndex = selectionIndex.value;
          select(model.value[selectionIndex.value], false);
          selectionIndex.value = originalSelectionIndex >= length - 1 ? length - 2 : originalSelectionIndex;
        } else if (e.key === 'Backspace' && !search.value) {
          selectionIndex.value = length - 1;
        }
        return;
      }
      if (!props.multiple) return;
      if (e.key === 'ArrowLeft') {
        if (selectionIndex.value < 0 && selectionStart && selectionStart > 0) return;
        const prev = selectionIndex.value > -1 ? selectionIndex.value - 1 : length - 1;
        if (model.value[prev]) {
          selectionIndex.value = prev;
        } else {
          const searchLength = search.value?.length ?? null;
          selectionIndex.value = -1;
          vTextFieldRef.value?.setSelectionRange(searchLength, searchLength);
        }
      } else if (e.key === 'ArrowRight') {
        if (selectionIndex.value < 0) return;
        const next = selectionIndex.value + 1;
        if (model.value[next]) {
          selectionIndex.value = next;
        } else {
          selectionIndex.value = -1;
          vTextFieldRef.value?.setSelectionRange(0, 0);
        }
      } else if (~selectionIndex.value && checkPrintable(e)) {
        selectionIndex.value = -1;
      }
    }
    function onChange(e) {
      if (matchesSelector(vTextFieldRef.value, ':autofill') || matchesSelector(vTextFieldRef.value, ':-webkit-autofill')) {
        const item = items.value.find(item => item.title === e.target.value);
        if (item) {
          select(item);
        }
      }
    }
    function onAfterEnter() {
      if (props.eager) {
        vVirtualScrollRef.value?.calculateVisibleItems();
      }
    }
    function onAfterLeave() {
      if (isFocused.value) {
        if (vMenuRef.value?.contentEl?._clickOutside?.lastMousedownWasOutside) {
          isFocused.value = false;
        } else {
          isPristine.value = true;
          vTextFieldRef.value?.focus();
        }
      }
      _searchLock.value = null;
    }
    function onFocusin(e) {
      isFocused.value = true;
      setTimeout(() => {
        listHasFocus.value = true;
      });
    }
    function onFocusout(e) {
      listHasFocus.value = false;
      if (!vTextFieldRef.value?.$el.contains(e.relatedTarget)) {
        if (repairOrphanedFocus(e)) return;
        isFocused.value = false;
      }
    }
    function onUpdateModelValue(v) {
      if (v == null || v === '' && !props.multiple && !hasSelectionSlot.value) model.value = [];
    }
    let mousedownInsideContentAt = 0;
    function onMousedownContent() {
      mousedownInsideContentAt = performance.now();
    }
    function onBlur(e) {
      const next = e.relatedTarget;
      const menuContent = vMenuRef.value?.contentEl;
      if (menuContent?.contains(next) || !next && performance.now() - mousedownInsideContentAt < 10) {
        isFocused.value = true;
      }
    }
    const isSelecting = shallowRef(false);

    /** @param set - null means toggle */
    function select(item, set = true) {
      if (!item || 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];
        }
        if (props.clearOnSelect) {
          search.value = '';
        }
      } else {
        const add = set !== false;
        model.value = add ? [item] : [];
        _searchLock.value = isPristine.value ? '' : search.value ?? '';
        search.value = add && !hasSelectionSlot.value ? item.title : '';

        // watch for search watcher to trigger
        nextTick(() => {
          menu.value = false;
          isPristine.value = true;
        });
      }
    }
    watch(isFocused, (val, oldVal) => {
      if (val === oldVal) return;
      if (val) {
        isSelecting.value = true;
        search.value = props.multiple || hasSelectionSlot.value ? '' : String(model.value.at(-1)?.props.title ?? '');
        isPristine.value = true;
        nextTick(() => isSelecting.value = false);
      } else {
        if (!props.multiple && search.value == null) model.value = [];
        menu.value = false;
        if (!isPristine.value && search.value) {
          _searchLock.value = search.value;
        }
        search.value = '';
        selectionIndex.value = -1;
      }
    });
    watch(search, val => {
      if (!isFocused.value || isSelecting.value) return;
      if (val) menu.value = true;
      isPristine.value = !val;
    });
    watch(menu, val => {
      if (!props.hideSelected && val && model.value.length && isPristine.value) {
        const index = displayItems.value.findIndex(item => model.value.some(s => item.value === s.value));
        IN_BROWSER && !props.noAutoScroll && window.requestAnimationFrame(() => {
          index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
        });
      }
      if (val) _searchLock.value = null;
    });
    watch(items, (newVal, oldVal) => {
      if (menu.value) return;
      if (isFocused.value && !oldVal.length && newVal.length) {
        menu.value = true;
      }
    });
    useRender(() => {
      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 menuSlotProps = {
        search,
        filteredItems: filteredItems.value
      };
      return createVNode(VTextField, mergeProps({
        "ref": vTextFieldRef
      }, textFieldProps, {
        "modelValue": search.value,
        "onUpdate:modelValue": [$event => search.value = $event, onUpdateModelValue],
        "focused": isFocused.value,
        "onUpdate:focused": $event => isFocused.value = $event,
        "validationValue": model.externalValue,
        "counterValue": counterValue.value,
        "dirty": isDirty,
        "onChange": onChange,
        "class": ['v-autocomplete', `v-autocomplete--${props.multiple ? 'multiple' : 'single'}`, {
          'v-autocomplete--active-menu': menu.value,
          'v-autocomplete--chips': !!props.chips,
          'v-autocomplete--selection-slot': !!hasSelectionSlot.value,
          'v-autocomplete--selecting-index': selectionIndex.value > -1
        }, props.class],
        "style": props.style,
        "readonly": form.isReadonly.value,
        "placeholder": isDirty ? undefined : props.placeholder,
        "onClick:clear": onClear,
        "onMousedown:control": onMousedownControl,
        "onKeydown": onKeydown,
        "onBlur": onBlur,
        "aria-expanded": ariaExpanded.value,
        "aria-controls": ariaControls.value
      }), {
        ...slots,
        default: ({
          id
        }) => createElementVNode(Fragment, null, [createVNode(VMenu, mergeProps({
          "id": menuId.value,
          "ref": vMenuRef,
          "modelValue": menu.value,
          "onUpdate:modelValue": $event => menu.value = $event,
          "activator": "parent",
          "disabled": menuDisabled.value,
          "eager": props.eager,
          "maxHeight": 310,
          "openOnClick": false,
          "closeOnContentClick": false,
          "onAfterEnter": onAfterEnter,
          "onAfterLeave": onAfterLeave
        }, props.menuProps, {
          "contentClass": ['v-autocomplete__content', props.menuProps?.contentClass]
        }), {
          default: () => [createVNode(VSheet, {
            "elevation": props.menuElevation,
            "onFocusin": onFocusin,
            "onKeydown": onMenuKeydown,
            "onMousedown": onMousedownContent
          }, {
            default: () => [slots['menu-header'] && createElementVNode("header", {
              "ref": headerRef
            }, [slots['menu-header'](menuSlotProps)]), hasList && createVNode(VList, mergeProps({
              "key": "autocomplete-list",
              "ref": listRef,
              "filterable": true,
              "selected": selectedValues.value,
              "selectStrategy": props.multiple ? 'independent' : 'single-independent',
              "onMousedown": e => e.preventDefault(),
              "onFocusout": onFocusout,
              "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,
                    active: highlightFirst.value && item === firstSelectableItem.value ? true : undefined,
                    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, {
                      "ref": itemRef,
                      "key": `divider-${index}`
                    }), null);
                  }
                  if (item.type === 'subheader') {
                    return slots.subheader?.({
                      props: item.raw,
                      index
                    }) ?? createVNode(VListSubheader, mergeProps(item.props, {
                      "ref": itemRef,
                      "key": `subheader-${index}`
                    }), null);
                  }
                  return slots.item?.({
                    item: item.raw,
                    internalItem: item,
                    index,
                    props: itemProps
                  }) ?? createVNode(VListItem, mergeProps(itemProps, {
                    "role": "option"
                  }), {
                    prepend: ({
                      isSelected
                    }) => createElementVNode(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) : undefined, camelizedProps.prependAvatar && createVNode(VAvatar, {
                      "image": camelizedProps.prependAvatar
                    }, null), camelizedProps.prependIcon && createVNode(VIcon, {
                      "icon": camelizedProps.prependIcon
                    }, null)]),
                    title: () => {
                      return isPristine.value ? item.title : createVNode(VHighlight, {
                        "text": item.title,
                        "matches": getMatches(item)?.title,
                        "markClass": "v-autocomplete__mask",
                        "matchAll": true,
                        "ignoreCase": true
                      }, null);
                    }
                  });
                }
              }), slots['append-item']?.()]
            }), slots['menu-footer'] && createElementVNode("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': undefined
          });
          const hasSlot = hasChips.value ? !!slots.chip : !!slots.selection;
          const slotContent = hasSlot ? ensureValidVNode(hasChips.value ? slots.chip({
            item: item.raw,
            internalItem: item,
            index,
            props: slotProps
          }) : slots.selection({
            item: item.raw,
            internalItem: item,
            index
          })) : undefined;
          if (hasSlot && !slotContent) return undefined;
          return createElementVNode("div", {
            "key": item.value,
            "class": normalizeClass(['v-autocomplete__selection', index === selectionIndex.value && ['v-autocomplete__selection--selected', textColorClasses.value]]),
            "style": normalizeStyle(index === selectionIndex.value ? textColorStyles.value : {})
          }, [hasChips.value ? !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 ?? createElementVNode("span", {
            "class": "v-autocomplete__selection-text"
          }, [item.title, props.multiple && index < model.value.length - 1 && createElementVNode("span", {
            "class": "v-autocomplete__selection-comma"
          }, [createTextVNode(",")])])]);
        })]),
        'append-inner': (...args) => createElementVNode(Fragment, null, [slots['append-inner']?.(...args), props.menuIcon ? createVNode(VIcon, {
          "class": "v-autocomplete__menu-icon",
          "color": vTextFieldRef.value?.fieldIconColor,
          "icon": props.menuIcon,
          "onMousedown": onMousedownMenuIcon,
          "onClick": noop,
          "aria-hidden": true,
          "tabindex": "-1"
        }, null) : undefined, props.appendInnerIcon && createVNode(InputIcon, {
          "key": "append-icon",
          "name": "appendInner",
          "color": args[0].iconColor.value
        }, null)])
      });
    });
    return forwardRefs({
      isFocused,
      isPristine,
      menu,
      search,
      filteredItems,
      select
    }, vTextFieldRef);
  }
});

const makeVBannerActionsProps = propsFactory({
  color: String,
  density: String,
  ...makeComponentProps()
}, 'VBannerActions');
const VBannerActions = genericComponent()({
  name: 'VBannerActions',
  props: makeVBannerActionsProps(),
  setup(props, {
    slots
  }) {
    provideDefaults({
      VBtn: {
        color: props.color,
        density: props.density,
        slim: true,
        variant: 'text'
      }
    });
    useRender(() => createElementVNode("div", {
      "class": normalizeClass(['v-banner-actions', props.class]),
      "style": normalizeStyle(props.style)
    }, [slots.default?.()]));
    return {};
  }
});

// Utilities
const VBannerText = createSimpleFunctional('v-banner-text');

// Types

const makeVBannerProps = propsFactory({
  avatar: String,
  bgColor: String,
  color: String,
  icon: IconValue,
  lines: String,
  stacked: Boolean,
  sticky: Boolean,
  text: String,
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeDimensionProps(),
  ...makeDisplayProps({
    mobile: null
  }),
  ...makeElevationProps(),
  ...makeLocationProps(),
  ...makePositionProps(),
  ...makeRoundedProps(),
  ...makeTagProps(),
  ...makeThemeProps()
}, 'VBanner');
const VBanner = genericComponent()({
  name: 'VBanner',
  props: makeVBannerProps(),
  setup(props, {
    slots
  }) {
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.bgColor);
    const {
      borderClasses
    } = useBorder(props);
    const {
      densityClasses
    } = useDensity(props);
    const {
      displayClasses,
      mobile
    } = useDisplay(props);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      locationStyles
    } = useLocation(props);
    const {
      positionClasses
    } = usePosition(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      themeClasses
    } = provideTheme(props);
    const color = toRef(() => props.color);
    const density = toRef(() => props.density);
    provideDefaults({
      VBannerActions: {
        color,
        density
      }
    });
    useRender(() => {
      const hasText = !!(props.text || slots.text);
      const hasPrependMedia = !!(props.avatar || props.icon);
      const hasPrepend = !!(hasPrependMedia || slots.prepend);
      return createVNode(props.tag, {
        "class": normalizeClass(['v-banner', {
          'v-banner--stacked': props.stacked || mobile.value,
          'v-banner--sticky': props.sticky,
          [`v-banner--${props.lines}-line`]: !!props.lines
        }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, displayClasses.value, elevationClasses.value, positionClasses.value, roundedClasses.value, props.class]),
        "style": normalizeStyle([backgroundColorStyles.value, dimensionStyles.value, locationStyles.value, roundedStyles.value, props.style]),
        "role": "banner"
      }, {
        default: () => [hasPrepend && createElementVNode("div", {
          "key": "prepend",
          "class": "v-banner__prepend"
        }, [!slots.prepend ? createVNode(VAvatar, {
          "key": "prepend-avatar",
          "color": color.value,
          "density": density.value,
          "icon": props.icon,
          "image": props.avatar
        }, null) : createVNode(VDefaultsProvider, {
          "key": "prepend-defaults",
          "disabled": !hasPrependMedia,
          "defaults": {
            VAvatar: {
              color: color.value,
              density: density.value,
              icon: props.icon,
              image: props.avatar
            }
          }
        }, slots.prepend)]), createElementVNode("div", {
          "class": "v-banner__content"
        }, [hasText && createVNode(VBannerText, {
          "key": "text"
        }, {
          default: () => [slots.text?.() ?? props.text]
        }), slots.default?.()]), slots.actions && createVNode(VBannerActions, {
          "key": "actions"
        }, slots.actions)]
      });
    });
  }
});

// Types

const makeVBottomNavigationProps = propsFactory({
  baseColor: String,
  bgColor: String,
  color: String,
  grow: Boolean,
  mode: {
    type: String,
    validator: v => !v || ['horizontal', 'shift'].includes(v)
  },
  height: {
    type: [Number, String],
    default: 56
  },
  active: {
    type: Boolean,
    default: true
  },
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeElevationProps(),
  ...makeRoundedProps(),
  ...makeLayoutItemProps({
    name: 'bottom-navigation'
  }),
  ...makeTagProps({
    tag: 'header'
  }),
  ...makeGroupProps({
    selectedClass: 'v-btn--selected'
  }),
  ...makeThemeProps()
}, 'VBottomNavigation');
const VBottomNavigation = genericComponent()({
  name: 'VBottomNavigation',
  props: makeVBottomNavigationProps(),
  emits: {
    'update:active': value => true,
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = useTheme();
    const {
      borderClasses
    } = useBorder(props);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.bgColor);
    const {
      densityClasses
    } = useDensity(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      ssrBootStyles
    } = useSsrBoot();
    const height = computed(() => Number(props.height) - (props.density === 'comfortable' ? 8 : 0) - (props.density === 'compact' ? 16 : 0));
    const isActive = useProxiedModel(props, 'active', props.active);
    const {
      layoutItemStyles
    } = useLayoutItem({
      id: props.name,
      order: computed(() => parseInt(props.order, 10)),
      position: toRef(() => 'bottom'),
      layoutSize: toRef(() => isActive.value ? height.value : 0),
      elementSize: height,
      active: isActive,
      absolute: toRef(() => props.absolute)
    });
    useGroup(props, VBtnToggleSymbol);
    provideDefaults({
      VBtn: {
        baseColor: toRef(() => props.baseColor),
        color: toRef(() => props.color),
        density: toRef(() => props.density),
        stacked: toRef(() => props.mode !== 'horizontal'),
        variant: 'text'
      }
    }, {
      scoped: true
    });
    useRender(() => {
      return createVNode(props.tag, {
        "class": normalizeClass(['v-bottom-navigation', {
          'v-bottom-navigation--active': isActive.value,
          'v-bottom-navigation--grow': props.grow,
          'v-bottom-navigation--shift': props.mode === 'shift'
        }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class]),
        "style": normalizeStyle([backgroundColorStyles.value, layoutItemStyles.value, {
          height: convertToUnit(height.value)
        }, ssrBootStyles.value, roundedStyles.value, props.style])
      }, {
        default: () => [slots.default && createElementVNode("div", {
          "class": "v-bottom-navigation__content"
        }, [slots.default()])]
      });
    });
    return {};
  }
});

// Types

const makeVDialogProps = propsFactory({
  fullscreen: Boolean,
  scrollable: Boolean,
  ...omit(makeVOverlayProps({
    captureFocus: true,
    location: 'center center',
    origin: 'center center',
    scrollStrategy: 'block',
    transition: {
      component: VDialogTransition
    },
    zIndex: 2400,
    retainFocus: true
  }), ['disableInitialFocus'])
}, 'VDialog');
const VDialog = genericComponent()({
  name: 'VDialog',
  props: makeVDialogProps(),
  emits: {
    'update:modelValue': value => true,
    afterEnter: () => true,
    afterLeave: () => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const isActive = useProxiedModel(props, 'modelValue');
    const {
      scopeId
    } = useScopeId();
    const overlay = ref();
    function onAfterEnter() {
      emit('afterEnter');
      if ((props.scrim || props.retainFocus) && overlay.value?.contentEl && !overlay.value.contentEl.contains(getActiveElement())) {
        overlay.value.contentEl.focus({
          preventScroll: true
        });
      }
    }
    function onAfterLeave() {
      emit('afterLeave');
    }
    watch(isActive, async val => {
      if (!val) {
        await nextTick();
        overlay.value?.activatorEl?.focus({
          preventScroll: true
        });
      }
    });
    useRender(() => {
      const overlayProps = VOverlay.filterProps(props);
      const activatorProps = mergeProps({
        'aria-haspopup': 'dialog'
      }, props.activatorProps);
      const contentProps = mergeProps({
        tabindex: -1
      }, props.contentProps);
      const locationStrategy = props.fullscreen ? noop : props.locationStrategy;
      return createVNode(VOverlay, mergeProps({
        "ref": overlay,
        "class": ['v-dialog', {
          'v-dialog--fullscreen': props.fullscreen,
          'v-dialog--scrollable': props.scrollable
        }, props.class],
        "style": props.style
      }, overlayProps, {
        "modelValue": isActive.value,
        "onUpdate:modelValue": $event => isActive.value = $event,
        "aria-modal": "true",
        "activatorProps": activatorProps,
        "contentProps": contentProps,
        "height": !props.fullscreen ? props.height : undefined,
        "width": !props.fullscreen ? props.width : undefined,
        "maxHeight": !props.fullscreen ? props.maxHeight : undefined,
        "maxWidth": !props.fullscreen ? props.maxWidth : undefined,
        "locationStrategy": locationStrategy,
        "role": "dialog",
        "onAfterEnter": onAfterEnter,
        "onAfterLeave": onAfterLeave
      }, scopeId), {
        activator: slots.activator,
        default: (...args) => createVNode(VDefaultsProvider, {
          "root": "VDialog"
        }, {
          default: () => [slots.default?.(...args)]
        })
      });
    });
    return forwardRefs({}, overlay);
  }
});

// Types

const makeVBottomSheetProps = propsFactory({
  inset: Boolean,
  ...makeVDialogProps({
    transition: 'bottom-sheet-transition',
    location: 'bottom center',
    origin: 'bottom center',
    viewportMargin: 0
  })
}, 'VBottomSheet');
const VBottomSheet = genericComponent()({
  name: 'VBottomSheet',
  props: makeVBottomSheetProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const isActive = useProxiedModel(props, 'modelValue');
    useRender(() => {
      const dialogProps = VDialog.filterProps(props);
      return createVNode(VDialog, mergeProps(dialogProps, {
        "contentClass": ['v-bottom-sheet__content', props.contentClass],
        "modelValue": isActive.value,
        "onUpdate:modelValue": $event => isActive.value = $event,
        "class": ['v-bottom-sheet', {
          'v-bottom-sheet--inset': props.inset
        }, props.class],
        "style": props.style
      }), slots);
    });
    return {};
  }
});

const makeVBreadcrumbsDividerProps = propsFactory({
  divider: [Number, String],
  ...makeComponentProps()
}, 'VBreadcrumbsDivider');
const VBreadcrumbsDivider = genericComponent()({
  name: 'VBreadcrumbsDivider',
  props: makeVBreadcrumbsDividerProps(),
  setup(props, {
    slots
  }) {
    useRender(() => createElementVNode("li", {
      "aria-hidden": "true",
      "class": normalizeClass(['v-breadcrumbs-divider', props.class]),
      "style": normalizeStyle(props.style)
    }, [slots?.default?.() ?? props.divider]));
    return {};
  }
});

const makeVBreadcrumbsItemProps = propsFactory({
  active: Boolean,
  activeClass: String,
  activeColor: String,
  color: String,
  disabled: Boolean,
  title: String,
  ...makeComponentProps(),
  ...pick(makeDimensionProps(), ['width', 'maxWidth']),
  ...makeRouterProps(),
  ...makeTagProps({
    tag: 'li'
  })
}, 'VBreadcrumbsItem');
const VBreadcrumbsItem = genericComponent()({
  name: 'VBreadcrumbsItem',
  props: makeVBreadcrumbsItemProps(),
  setup(props, {
    slots,
    attrs
  }) {
    const link = useLink(props, attrs);
    const isActive = computed(() => props.active || link.isActive?.value);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => isActive.value ? props.activeColor : props.color);
    useRender(() => {
      return createVNode(props.tag, {
        "class": normalizeClass(['v-breadcrumbs-item', {
          'v-breadcrumbs-item--active': isActive.value,
          'v-breadcrumbs-item--disabled': props.disabled,
          [`${props.activeClass}`]: isActive.value && props.activeClass
        }, textColorClasses.value, props.class]),
        "style": normalizeStyle([textColorStyles.value, dimensionStyles.value, props.style]),
        "aria-current": isActive.value ? 'page' : undefined
      }, {
        default: () => [!link.isLink.value ? slots.default?.() ?? props.title : createElementVNode("a", mergeProps({
          "class": "v-breadcrumbs-item--link",
          "onClick": link.navigate.value
        }, link.linkProps), [slots.default?.() ?? props.title])]
      });
    });
    return {};
  }
});

// Types

const makeVBreadcrumbsProps = propsFactory({
  activeClass: String,
  activeColor: String,
  bgColor: String,
  color: String,
  disabled: Boolean,
  divider: {
    type: String,
    default: '/'
  },
  icon: IconValue,
  items: {
    type: Array,
    default: () => []
  },
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeRoundedProps(),
  ...makeTagProps({
    tag: 'ul'
  })
}, 'VBreadcrumbs');
const VBreadcrumbs = genericComponent()({
  name: 'VBreadcrumbs',
  props: makeVBreadcrumbsProps(),
  setup(props, {
    slots
  }) {
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.bgColor);
    const {
      densityClasses
    } = useDensity(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    provideDefaults({
      VBreadcrumbsDivider: {
        divider: toRef(() => props.divider)
      },
      VBreadcrumbsItem: {
        activeClass: toRef(() => props.activeClass),
        activeColor: toRef(() => props.activeColor),
        color: toRef(() => props.color),
        disabled: toRef(() => props.disabled)
      }
    });
    const items = computed(() => props.items.map(item => {
      return typeof item === 'string' ? {
        item: {
          title: item
        },
        raw: item
      } : {
        item,
        raw: item
      };
    }));
    useRender(() => {
      const hasPrepend = !!(slots.prepend || props.icon);
      return createVNode(props.tag, {
        "class": normalizeClass(['v-breadcrumbs', backgroundColorClasses.value, densityClasses.value, roundedClasses.value, props.class]),
        "style": normalizeStyle([backgroundColorStyles.value, roundedStyles.value, props.style])
      }, {
        default: () => [hasPrepend && createElementVNode("li", {
          "key": "prepend",
          "class": "v-breadcrumbs__prepend"
        }, [!slots.prepend ? createVNode(VIcon, {
          "key": "prepend-icon",
          "start": true,
          "icon": props.icon
        }, null) : createVNode(VDefaultsProvider, {
          "key": "prepend-defaults",
          "disabled": !props.icon,
          "defaults": {
            VIcon: {
              icon: props.icon,
              start: true
            }
          }
        }, slots.prepend)]), items.value.map(({
          item,
          raw
        }, index, array) => createElementVNode(Fragment, null, [slots.item?.({
          item,
          index
        }) ?? createVNode(VBreadcrumbsItem, mergeProps({
          "key": index,
          "disabled": index >= array.length - 1
        }, typeof item === 'string' ? {
          title: item
        } : item), {
          default: slots.title ? () => slots.title?.({
            item,
            index
          }) : undefined
        }), index < array.length - 1 && createVNode(VBreadcrumbsDivider, null, {
          default: slots.divider ? () => slots.divider?.({
            item: raw,
            index
          }) : undefined
        })])), slots.default?.()]
      });
    });
    return {};
  }
});

// Types

const makeVIconBtnProps = propsFactory({
  active: {
    type: Boolean,
    default: undefined
  },
  activeColor: String,
  activeIcon: [String, Function, Object],
  activeVariant: String,
  baseVariant: {
    type: String,
    default: 'tonal'
  },
  disabled: Boolean,
  height: [Number, String],
  width: [Number, String],
  hideOverlay: Boolean,
  icon: [String, Function, Object],
  iconColor: String,
  loading: Boolean,
  opacity: [Number, String],
  readonly: Boolean,
  rotate: [Number, String],
  size: {
    type: [Number, String],
    default: 'default'
  },
  sizes: {
    type: Array,
    default: () => [['x-small', 16], ['small', 24], ['default', 40], ['large', 48], ['x-large', 56]]
  },
  text: {
    type: [String, Number, Boolean],
    default: undefined
  },
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeElevationProps(),
  ...makeIconSizeProps(),
  ...makeRoundedProps(),
  ...makeTagProps({
    tag: 'button'
  }),
  ...makeThemeProps(),
  ...makeVariantProps({
    variant: 'flat'
  })
}, 'VIconBtn');
const VIconBtn = genericComponent()({
  name: 'VIconBtn',
  props: makeVIconBtnProps(),
  emits: {
    'update:active': value => true
  },
  setup(props, {
    attrs,
    slots
  }) {
    const isActive = useProxiedModel(props, 'active');
    const {
      themeClasses
    } = provideTheme(props);
    const {
      borderClasses
    } = useBorder(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      colorClasses,
      colorStyles,
      variantClasses
    } = useVariant(() => ({
      color: (() => {
        if (props.disabled) return undefined;
        if (!isActive.value) return props.color;
        // Use an inline fallback as opposed to setting a default color
        // because non-toggle buttons are default flat whereas toggle
        // buttons are default tonal and active flat. The exact use
        // case for this is a toggle button with no active color.
        return props.activeColor ?? props.color ?? 'surface-variant';
      })(),
      variant: (() => {
        if (isActive.value === undefined) return props.variant;
        if (isActive.value) return props.activeVariant ?? props.variant;
        return props.baseVariant ?? props.variant;
      })()
    }));
    const btnSizeMap = new Map(props.sizes);
    function onClick() {
      if (props.disabled || props.readonly || isActive.value === undefined || props.tag === 'a' && attrs.href) return;
      isActive.value = !isActive.value;
    }
    useRender(() => {
      const icon = isActive.value ? props.activeIcon ?? props.icon : props.icon;
      const _btnSize = props.size;
      const hasNamedSize = btnSizeMap.has(_btnSize);
      const btnSize = hasNamedSize ? btnSizeMap.get(_btnSize) : _btnSize;
      const btnHeight = props.height ?? btnSize;
      const btnWidth = props.width ?? btnSize;
      const {
        iconSize
      } = useIconSizes(props, () => new Map(props.iconSizes).get(_btnSize));
      const iconProps = {
        icon,
        size: iconSize.value,
        color: props.iconColor,
        opacity: props.opacity
      };
      return createVNode(props.tag, {
        "type": props.tag === 'button' ? 'button' : undefined,
        "class": normalizeClass([{
          'v-icon-btn': true,
          'v-icon-btn--active': isActive.value,
          'v-icon-btn--disabled': props.disabled,
          'v-icon-btn--loading': props.loading,
          'v-icon-btn--readonly': props.readonly,
          [`v-icon-btn--${props.size}`]: true
        }, themeClasses.value, colorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, variantClasses.value, props.class]),
        "style": normalizeStyle([{
          '--v-icon-btn-rotate': convertToUnit(props.rotate, 'deg'),
          '--v-icon-btn-height': convertToUnit(btnHeight),
          '--v-icon-btn-width': convertToUnit(btnWidth)
        }, colorStyles.value, roundedStyles.value, props.style]),
        "tabindex": props.disabled || props.readonly ? -1 : 0,
        "onClick": onClick
      }, {
        default: () => [genOverlays(!props.hideOverlay, 'v-icon-btn'), createElementVNode("div", {
          "class": "v-icon-btn__content",
          "data-no-activator": ""
        }, [!slots.default && icon ? createVNode(VIcon, mergeProps({
          "key": "content-icon"
        }, iconProps), null) : createVNode(VDefaultsProvider, {
          "key": "content-defaults",
          "disabled": !icon,
          "defaults": {
            VIcon: {
              ...iconProps
            }
          }
        }, {
          default: () => slots.default?.() ?? toDisplayString(props.text)
        })]), !!props.loading && createElementVNode("span", {
          "key": "loader",
          "class": "v-icon-btn__loader"
        }, [slots.loader?.() ?? createVNode(VProgressCircular, {
          "color": typeof props.loading === 'boolean' ? undefined : props.loading,
          "indeterminate": "disable-shrink",
          "width": "2",
          "size": iconSize.value
        }, null)])]
      });
    });
    return {};
  }
});

function isLeapYear(year) {
  return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
}

// Types

const PARSE_REGEX = /^(\d{4})-(\d{1,2})(-(\d{1,2}))?([^\d]+(\d{1,2}))?(:(\d{1,2}))?(:(\d{1,2}))?$/;
const PARSE_TIME = /(\d\d?)(:(\d\d?)|)(:(\d\d?)|)/;
const DAYS_IN_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const DAYS_IN_MONTH_LEAP = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const DAYS_IN_MONTH_MIN = 28;
const DAYS_IN_MONTH_MAX = 31;
const MONTH_MAX = 12;
const MONTH_MIN = 1;
const DAY_MIN = 1;
const DAYS_IN_WEEK = 7;
const MINUTES_IN_HOUR = 60;
const MINUTE_MAX = 59;
const MINUTES_IN_DAY = 24 * 60;
const HOURS_IN_DAY = 24;
const HOUR_MAX = 23;
const FIRST_HOUR = 0;
const OFFSET_YEAR = 10000;
const OFFSET_MONTH = 100;
const OFFSET_HOUR = 100;
const OFFSET_TIME = 10000;
function getStartOfWeek(timestamp, weekdays, today) {
  const start = copyTimestamp(timestamp);
  findWeekday(start, weekdays[0], prevDay);
  updateFormatted(start);
  if (today) {
    updateRelative(start, today, start.hasTime);
  }
  return start;
}
function getEndOfWeek(timestamp, weekdays, today) {
  const end = copyTimestamp(timestamp);
  findWeekday(end, weekdays[weekdays.length - 1]);
  updateFormatted(end);
  if (today) {
    updateRelative(end, today, end.hasTime);
  }
  return end;
}
function getStartOfMonth(timestamp) {
  const start = copyTimestamp(timestamp);
  start.day = DAY_MIN;
  updateWeekday(start);
  updateFormatted(start);
  return start;
}
function getEndOfMonth(timestamp) {
  const end = copyTimestamp(timestamp);
  end.day = daysInMonth(end.year, end.month);
  updateWeekday(end);
  updateFormatted(end);
  return end;
}
function validateNumber(input) {
  return isFinite(parseInt(input));
}
function validateTime(input) {
  return typeof input === 'number' && isFinite(input) || !!PARSE_TIME.exec(input) || typeof input === 'object' && isFinite(input.hour) && isFinite(input.minute);
}
function parseTime(input) {
  if (typeof input === 'number') {
    // when a number is given, it's minutes since 12:00am
    return input;
  } else if (typeof input === 'string') {
    // when a string is given, it's a hh:mm:ss format where seconds are optional
    const parts = PARSE_TIME.exec(input);
    if (!parts) {
      return false;
    }
    return parseInt(parts[1]) * 60 + parseInt(parts[3] || 0);
  } else if (typeof input === 'object') {
    // when an object is given, it must have hour and minute
    if (typeof input.hour !== 'number' || typeof input.minute !== 'number') {
      return false;
    }
    return input.hour * 60 + input.minute;
  } else {
    // unsupported type
    return false;
  }
}
function validateTimestamp(input) {
  return typeof input === 'number' && isFinite(input) || typeof input === 'string' && !!PARSE_REGEX.exec(input) || input instanceof Date;
}
function parseTimestamp(input, required = false, now) {
  if (typeof input === 'number' && isFinite(input)) {
    input = new Date(input);
  }
  if (input instanceof Date) {
    const date = parseDate(input);
    return date;
  }
  if (typeof input !== 'string') {
    if (required) {
      throw new Error(`${input} is not a valid timestamp. It must be a Date, number of milliseconds since Epoch, or a string in the format of YYYY-MM-DD or YYYY-MM-DD hh:mm. Zero-padding is optional and seconds are ignored.`);
    }
    return null;
  }

  // YYYY-MM-DD hh:mm:ss
  const parts = PARSE_REGEX.exec(input);
  if (!parts) {
    if (required) {
      throw new Error(`${input} is not a valid timestamp. It must be a Date, number of milliseconds since Epoch, or a string in the format of YYYY-MM-DD or YYYY-MM-DD hh:mm. Zero-padding is optional and seconds are ignored.`);
    }
    return null;
  }
  const timestamp = {
    date: input,
    time: '',
    year: parseInt(parts[1]),
    month: parseInt(parts[2]),
    day: parseInt(parts[4]) || 1,
    hour: parseInt(parts[6]) || 0,
    minute: parseInt(parts[8]) || 0,
    weekday: 0,
    hasDay: !!parts[4],
    hasTime: !!(parts[6] && parts[8]),
    past: false,
    present: false,
    future: false
  };
  updateWeekday(timestamp);
  updateFormatted(timestamp);
  return timestamp;
}
function parseDate(date) {
  return updateFormatted({
    date: '',
    time: '',
    year: date.getFullYear(),
    month: date.getMonth() + 1,
    day: date.getDate(),
    weekday: date.getDay(),
    hour: date.getHours(),
    minute: date.getMinutes(),
    hasDay: true,
    hasTime: true,
    past: false,
    present: true,
    future: false
  });
}
function getDayIdentifier(timestamp) {
  return timestamp.year * OFFSET_YEAR + timestamp.month * OFFSET_MONTH + timestamp.day;
}
function getTimeIdentifier(timestamp) {
  return timestamp.hour * OFFSET_HOUR + timestamp.minute;
}
function getTimestampIdentifier(timestamp) {
  return getDayIdentifier(timestamp) * OFFSET_TIME + getTimeIdentifier(timestamp);
}
function updateRelative(timestamp, now, time = false) {
  let a = getDayIdentifier(now);
  let b = getDayIdentifier(timestamp);
  let present = a === b;
  if (timestamp.hasTime && time && present) {
    a = getTimeIdentifier(now);
    b = getTimeIdentifier(timestamp);
    present = a === b;
  }
  timestamp.past = b < a;
  timestamp.present = present;
  timestamp.future = b > a;
  return timestamp;
}
function isTimedless(input) {
  return input instanceof Date || typeof input === 'number' && isFinite(input);
}
function updateHasTime(timestamp, hasTime, now) {
  if (timestamp.hasTime !== hasTime) {
    timestamp.hasTime = hasTime;
    if (!hasTime) {
      timestamp.hour = HOUR_MAX;
      timestamp.minute = MINUTE_MAX;
      timestamp.time = getTime(timestamp);
    }
  }
  return timestamp;
}
function updateMinutes(timestamp, minutes, now) {
  timestamp.hasTime = true;
  timestamp.hour = 0;
  timestamp.minute = 0;
  nextMinutes(timestamp, minutes);
  updateFormatted(timestamp);
  if (now) {
    updateRelative(timestamp, now, true);
  }
  return timestamp;
}
function updateWeekday(timestamp) {
  timestamp.weekday = getWeekday(timestamp);
  return timestamp;
}
function updateFormatted(timestamp) {
  timestamp.time = getTime(timestamp);
  timestamp.date = getDate$1(timestamp);
  return timestamp;
}
function getWeekday(timestamp) {
  if (timestamp.hasDay) {
    const _ = Math.floor;
    const k = timestamp.day;
    const m = (timestamp.month + 9) % MONTH_MAX + 1;
    const C = _(timestamp.year / 100);
    const Y = timestamp.year % 100 - (timestamp.month <= 2 ? 1 : 0);
    return ((k + _(2.6 * m - 0.2) - 2 * C + Y + _(Y / 4) + _(C / 4)) % 7 + 7) % 7;
  }
  return timestamp.weekday;
}
function daysInMonth(year, month) {
  return isLeapYear(year) ? DAYS_IN_MONTH_LEAP[month] : DAYS_IN_MONTH[month];
}
function copyTimestamp(timestamp) {
  if (timestamp == null) return null;
  const {
    date,
    time,
    year,
    month,
    day,
    weekday,
    hour,
    minute,
    hasDay,
    hasTime,
    past,
    present,
    future
  } = timestamp;
  return {
    date,
    time,
    year,
    month,
    day,
    weekday,
    hour,
    minute,
    hasDay,
    hasTime,
    past,
    present,
    future
  };
}
function padNumber(x, length) {
  let padded = String(x);
  while (padded.length < length) {
    padded = '0' + padded;
  }
  return padded;
}
function getDate$1(timestamp) {
  let str = `${padNumber(timestamp.year, 4)}-${padNumber(timestamp.month, 2)}`;
  if (timestamp.hasDay) str += `-${padNumber(timestamp.day, 2)}`;
  return str;
}
function getTime(timestamp) {
  if (!timestamp.hasTime) {
    return '';
  }
  return `${padNumber(timestamp.hour, 2)}:${padNumber(timestamp.minute, 2)}`;
}
function nextMinutes(timestamp, minutes) {
  timestamp.minute += minutes;
  while (timestamp.minute >= MINUTES_IN_HOUR) {
    timestamp.minute -= MINUTES_IN_HOUR;
    timestamp.hour++;
    if (timestamp.hour >= HOURS_IN_DAY) {
      nextDay(timestamp);
      timestamp.hour = FIRST_HOUR;
    }
  }
  return timestamp;
}
function nextDay(timestamp) {
  timestamp.day++;
  timestamp.weekday = (timestamp.weekday + 1) % DAYS_IN_WEEK;
  if (timestamp.day > DAYS_IN_MONTH_MIN && timestamp.day > daysInMonth(timestamp.year, timestamp.month)) {
    timestamp.day = DAY_MIN;
    timestamp.month++;
    if (timestamp.month > MONTH_MAX) {
      timestamp.month = MONTH_MIN;
      timestamp.year++;
    }
  }
  return timestamp;
}
function prevDay(timestamp) {
  timestamp.day--;
  timestamp.weekday = (timestamp.weekday + 6) % DAYS_IN_WEEK;
  if (timestamp.day < DAY_MIN) {
    timestamp.month--;
    if (timestamp.month < MONTH_MIN) {
      timestamp.year--;
      timestamp.month = MONTH_MAX;
    }
    timestamp.day = daysInMonth(timestamp.year, timestamp.month);
  }
  return timestamp;
}
function relativeDays(timestamp, mover = nextDay, days = 1) {
  while (--days >= 0) mover(timestamp);
  return timestamp;
}
function diffMinutes(min, max) {
  const Y = (max.year - min.year) * 525600;
  const M = (max.month - min.month) * 43800;
  const D = (max.day - min.day) * 1440;
  const h = (max.hour - min.hour) * 60;
  const m = max.minute - min.minute;
  return Y + M + D + h + m;
}
function findWeekday(timestamp, weekday, mover = nextDay, maxDays = 6) {
  while (timestamp.weekday !== weekday && --maxDays >= 0) mover(timestamp);
  return timestamp;
}
function getWeekdaySkips(weekdays) {
  const skips = [1, 1, 1, 1, 1, 1, 1];
  const filled = [0, 0, 0, 0, 0, 0, 0];
  for (let i = 0; i < weekdays.length; i++) {
    filled[weekdays[i]] = 1;
  }
  for (let k = 0; k < DAYS_IN_WEEK; k++) {
    let skip = 1;
    for (let j = 1; j < DAYS_IN_WEEK; j++) {
      const next = (k + j) % DAYS_IN_WEEK;
      if (filled[next]) {
        break;
      }
      skip++;
    }
    skips[k] = filled[k] * skip;
  }
  return skips;
}
function timestampToDate(timestamp) {
  const time = `${padNumber(timestamp.hour, 2)}:${padNumber(timestamp.minute, 2)}`;
  const date = timestamp.date;
  return new Date(`${date}T${time}:00+00:00`);
}
function createDayList(start, end, now, weekdaySkips, max = 42, min = 0) {
  const stop = getDayIdentifier(end);
  const days = [];
  let current = copyTimestamp(start);
  let currentIdentifier = 0;
  let stopped = currentIdentifier === stop;
  if (stop < getDayIdentifier(start)) {
    throw new Error('End date is earlier than start date.');
  }
  while ((!stopped || days.length < min) && days.length < max) {
    currentIdentifier = getDayIdentifier(current);
    stopped = stopped || currentIdentifier === stop;
    if (weekdaySkips[current.weekday] === 0) {
      current = nextDay(current);
      continue;
    }
    const day = copyTimestamp(current);
    updateFormatted(day);
    updateRelative(day, now);
    days.push(day);
    current = relativeDays(current, nextDay, weekdaySkips[current.weekday]);
  }
  if (!days.length) throw new Error('No dates found using specified start date, end date, and weekdays.');
  return days;
}
function createIntervalList(timestamp, first, minutes, count, now) {
  const intervals = [];
  for (let i = 0; i < count; i++) {
    const mins = first + i * minutes;
    const int = copyTimestamp(timestamp);
    intervals.push(updateMinutes(int, mins, now));
  }
  return intervals;
}
function createNativeLocaleFormatter(locale, getOptions) {
  const emptyFormatter = (_t, _s) => '';
  if (typeof Intl === 'undefined' || typeof Intl.DateTimeFormat === 'undefined') {
    return emptyFormatter;
  }
  return (timestamp, short) => {
    try {
      const intlFormatter = new Intl.DateTimeFormat(locale || undefined, getOptions(timestamp, short));
      return intlFormatter.format(timestampToDate(timestamp));
    } catch (e) {
      return '';
    }
  };
}
function validateWeekdays(input) {
  if (typeof input === 'string') {
    input = input.split(',');
  }
  if (Array.isArray(input)) {
    const ints = input.map(x => parseInt(x));
    if (ints.length > DAYS_IN_WEEK || ints.length === 0) {
      return false;
    }
    const visited = {};
    let wrapped = false;
    for (let i = 0; i < ints.length; i++) {
      const x = ints[i];
      if (!isFinite(x) || x < 0 || x >= DAYS_IN_WEEK) {
        return false;
      }
      if (i > 0) {
        const d = x - ints[i - 1];
        if (d < 0) {
          if (wrapped) {
            return false;
          }
          wrapped = true;
        } else if (d === 0) {
          return false;
        }
      }
      if (visited[x]) {
        return false;
      }
      visited[x] = true;
    }
    return true;
  }
  return false;
}

// Utilities

// Types

function useTimes(props) {
  const times = reactive({
    now: parseTimestamp('0000-00-00 00:00', true),
    today: parseTimestamp('0000-00-00', true)
  });
  const parsedNow = computed(() => {
    return props.now && validateTimestamp(props.now) ? parseTimestamp(props.now, true) : null;
  });
  function setPresent() {
    times.now.present = times.today.present = true;
    times.now.past = times.today.past = false;
    times.now.future = times.today.future = false;
  }
  function getNow() {
    return parseDate(new Date());
  }
  function updateDay(now, target) {
    if (now.date !== target.date) {
      target.year = now.year;
      target.month = now.month;
      target.day = now.day;
      target.weekday = now.weekday;
      target.date = now.date;
    }
  }
  function updateTime(now, target) {
    if (now.time !== target.time) {
      target.hour = now.hour;
      target.minute = now.minute;
      target.time = now.time;
    }
  }
  function updateTimes() {
    const now = parsedNow.value || getNow();
    updateDay(now, times.now);
    updateTime(now, times.now);
    updateDay(now, times.today);
  }
  watch(parsedNow, updateTimes);
  updateTimes();
  setPresent();
  return {
    times,
    parsedNow,
    updateTimes,
    setPresent,
    getNow,
    updateDay,
    updateTime
  };
}

// Utilities

// Types

function weekInfo(locale) {
  // https://simplelocalize.io/data/locales/
  // then `new Intl.Locale(...).getWeekInfo()`
  const code = locale.slice(-2).toUpperCase();
  switch (true) {
    case locale === 'GB-alt-variant':
      {
        return {
          firstDay: 0,
          firstWeekSize: 4
        };
      }
    case locale === '001':
      {
        return {
          firstDay: 1,
          firstWeekSize: 1
        };
      }
    case `AG AS BD BR BS BT BW BZ CA CO DM DO ET GT GU HK HN ID IL IN JM JP KE
    KH KR LA MH MM MO MT MX MZ NI NP PA PE PH PK PR PY SA SG SV TH TT TW UM US
    VE VI WS YE ZA ZW`.includes(code):
      {
        return {
          firstDay: 0,
          firstWeekSize: 1
        };
      }
    case `AI AL AM AR AU AZ BA BM BN BY CL CM CN CR CY EC GE HR KG KZ LB LK LV
    MD ME MK MN MY NZ RO RS SI TJ TM TR UA UY UZ VN XK`.includes(code):
      {
        return {
          firstDay: 1,
          firstWeekSize: 1
        };
      }
    case `AD AN AT AX BE BG CH CZ DE DK EE ES FI FJ FO FR GB GF GP GR HU IE IS
    IT LI LT LU MC MQ NL NO PL RE RU SE SK SM VA`.includes(code):
      {
        return {
          firstDay: 1,
          firstWeekSize: 4
        };
      }
    case `AE AF BH DJ DZ EG IQ IR JO KW LY OM QA SD SY`.includes(code):
      {
        return {
          firstDay: 6,
          firstWeekSize: 1
        };
      }
    case code === 'MV':
      {
        return {
          firstDay: 5,
          firstWeekSize: 1
        };
      }
    case code === 'PT':
      {
        return {
          firstDay: 0,
          firstWeekSize: 4
        };
      }
    default:
      return null;
  }
}
function getWeekArray(date, locale, firstDayOfWeek) {
  const weeks = [];
  let currentWeek = [];
  const firstDayOfMonth = startOfMonth(date);
  const lastDayOfMonth = endOfMonth(date);
  const first = firstDayOfWeek ?? weekInfo(locale)?.firstDay ?? 0;
  const firstDayWeekIndex = (firstDayOfMonth.getDay() - first + 7) % 7;
  const lastDayWeekIndex = (lastDayOfMonth.getDay() - first + 7) % 7;
  for (let i = 0; i < firstDayWeekIndex; i++) {
    const adjacentDay = new Date(firstDayOfMonth);
    adjacentDay.setDate(adjacentDay.getDate() - (firstDayWeekIndex - i));
    currentWeek.push(adjacentDay);
  }
  for (let i = 1; i <= lastDayOfMonth.getDate(); i++) {
    const day = new Date(date.getFullYear(), date.getMonth(), i);

    // Add the day to the current week
    currentWeek.push(day);

    // If the current week has 7 days, add it to the weeks array and start a new week
    if (currentWeek.length === 7) {
      weeks.push(currentWeek);
      currentWeek = [];
    }
  }
  for (let i = 1; i < 7 - lastDayWeekIndex; i++) {
    const adjacentDay = new Date(lastDayOfMonth);
    adjacentDay.setDate(adjacentDay.getDate() + i);
    currentWeek.push(adjacentDay);
  }
  if (currentWeek.length > 0) {
    weeks.push(currentWeek);
  }
  return weeks;
}
function startOfWeek(date, locale, firstDayOfWeek) {
  let day = (firstDayOfWeek ?? weekInfo(locale)?.firstDay ?? 0) % 7;

  // prevent infinite loop
  if (![0, 1, 2, 3, 4, 5, 6].includes(day)) {
    consoleWarn('Invalid firstDayOfWeek, expected discrete number in range [0-6]');
    day = 0;
  }
  const d = new Date(date);
  while (d.getDay() !== day) {
    d.setDate(d.getDate() - 1);
  }
  return d;
}
function endOfWeek(date, locale) {
  const d = new Date(date);
  const lastDay = ((weekInfo(locale)?.firstDay ?? 0) + 6) % 7;
  while (d.getDay() !== lastDay) {
    d.setDate(d.getDate() + 1);
  }
  return d;
}
function startOfMonth(date) {
  return new Date(date.getFullYear(), date.getMonth(), 1);
}
function endOfMonth(date) {
  return new Date(date.getFullYear(), date.getMonth() + 1, 0);
}
function parseLocalDate(value) {
  const parts = value.split('-').map(Number);

  // new Date() uses local time zone when passing individual date component values
  return new Date(parts[0], parts[1] - 1, parts[2]);
}
const _YYYMMDD = /^([12]\d{3}-([1-9]|0[1-9]|1[0-2])-([1-9]|0[1-9]|[12]\d|3[01]))$/;
function date(value) {
  if (value == null) return new Date();
  if (value instanceof Date) return value;
  if (typeof value === 'string') {
    let parsed;
    if (_YYYMMDD.test(value)) {
      return parseLocalDate(value);
    } else {
      parsed = Date.parse(value);
    }
    if (!isNaN(parsed)) return new Date(parsed);
  }
  return null;
}
const sundayJanuarySecond2000 = new Date(2000, 0, 2);
function getWeekdays(locale, firstDayOfWeek, weekdayFormat) {
  const daysFromSunday = firstDayOfWeek ?? weekInfo(locale)?.firstDay ?? 0;
  return createRange(7).map(i => {
    const weekday = new Date(sundayJanuarySecond2000);
    weekday.setDate(sundayJanuarySecond2000.getDate() + daysFromSunday + i);
    return new Intl.DateTimeFormat(locale, {
      weekday: weekdayFormat ?? 'narrow'
    }).format(weekday);
  });
}
function format(value, formatString, locale, formats) {
  const newDate = date(value) ?? new Date();
  const customFormat = formats?.[formatString];
  if (typeof customFormat === 'function') {
    return customFormat(newDate, formatString, locale);
  }
  let options = {};
  switch (formatString) {
    case 'fullDate':
      options = {
        year: 'numeric',
        month: 'short',
        day: 'numeric'
      };
      break;
    case 'fullDateWithWeekday':
      options = {
        weekday: 'long',
        year: 'numeric',
        month: 'long',
        day: 'numeric'
      };
      break;
    case 'normalDate':
      const day = newDate.getDate();
      const month = new Intl.DateTimeFormat(locale, {
        month: 'long'
      }).format(newDate);
      return `${day} ${month}`;
    case 'normalDateWithWeekday':
      options = {
        weekday: 'short',
        day: 'numeric',
        month: 'short'
      };
      break;
    case 'shortDate':
      options = {
        month: 'short',
        day: 'numeric'
      };
      break;
    case 'year':
      options = {
        year: 'numeric'
      };
      break;
    case 'month':
      options = {
        month: 'long'
      };
      break;
    case 'monthShort':
      options = {
        month: 'short'
      };
      break;
    case 'monthAndYear':
      options = {
        month: 'long',
        year: 'numeric'
      };
      break;
    case 'monthAndDate':
      options = {
        month: 'long',
        day: 'numeric'
      };
      break;
    case 'weekday':
      options = {
        weekday: 'long'
      };
      break;
    case 'weekdayShort':
      options = {
        weekday: 'short'
      };
      break;
    case 'dayOfMonth':
      return new Intl.NumberFormat(locale).format(newDate.getDate());
    case 'hours12h':
      options = {
        hour: 'numeric',
        hour12: true
      };
      break;
    case 'hours24h':
      options = {
        hour: 'numeric',
        hour12: false
      };
      break;
    case 'minutes':
      options = {
        minute: 'numeric'
      };
      break;
    case 'seconds':
      options = {
        second: 'numeric'
      };
      break;
    case 'fullTime':
      options = {
        hour: 'numeric',
        minute: 'numeric'
      };
      break;
    case 'fullTime12h':
      options = {
        hour: 'numeric',
        minute: 'numeric',
        hour12: true
      };
      break;
    case 'fullTime24h':
      options = {
        hour: 'numeric',
        minute: 'numeric',
        hour12: false
      };
      break;
    case 'fullDateTime':
      options = {
        year: 'numeric',
        month: 'short',
        day: 'numeric',
        hour: 'numeric',
        minute: 'numeric'
      };
      break;
    case 'fullDateTime12h':
      options = {
        year: 'numeric',
        month: 'short',
        day: 'numeric',
        hour: 'numeric',
        minute: 'numeric',
        hour12: true
      };
      break;
    case 'fullDateTime24h':
      options = {
        year: 'numeric',
        month: 'short',
        day: 'numeric',
        hour: 'numeric',
        minute: 'numeric',
        hour12: false
      };
      break;
    case 'keyboardDate':
      options = {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit'
      };
      break;
    case 'keyboardDateTime':
      options = {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: 'numeric',
        minute: 'numeric'
      };
      return new Intl.DateTimeFormat(locale, options).format(newDate).replace(/, /g, ' ');
    case 'keyboardDateTime12h':
      options = {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: 'numeric',
        minute: 'numeric',
        hour12: true
      };
      return new Intl.DateTimeFormat(locale, options).format(newDate).replace(/, /g, ' ');
    case 'keyboardDateTime24h':
      options = {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: 'numeric',
        minute: 'numeric',
        hour12: false
      };
      return new Intl.DateTimeFormat(locale, options).format(newDate).replace(/, /g, ' ');
    default:
      options = customFormat ?? {
        timeZone: 'UTC',
        timeZoneName: 'short'
      };
  }
  return new Intl.DateTimeFormat(locale, options).format(newDate);
}
function toISO$1(adapter, value) {
  const date = adapter.toJsDate(value);
  const year = date.getFullYear();
  const month = padStart(String(date.getMonth() + 1), 2, '0');
  const day = padStart(String(date.getDate()), 2, '0');
  return `${year}-${month}-${day}`;
}
function parseISO(value) {
  const [year, month, day] = value.split('-').map(Number);
  return new Date(year, month - 1, day);
}
function addMinutes(date, amount) {
  const d = new Date(date);
  d.setMinutes(d.getMinutes() + amount);
  return d;
}
function addHours(date, amount) {
  const d = new Date(date);
  d.setHours(d.getHours() + amount);
  return d;
}
function addDays(date, amount) {
  const d = new Date(date);
  d.setDate(d.getDate() + amount);
  return d;
}
function addWeeks(date, amount) {
  const d = new Date(date);
  d.setDate(d.getDate() + amount * 7);
  return d;
}
function addMonths(date, amount) {
  const d = new Date(date);
  d.setDate(1);
  d.setMonth(d.getMonth() + amount);
  return d;
}
function getYear(date) {
  return date.getFullYear();
}
function getMonth(date) {
  return date.getMonth();
}
function getWeek(date, locale, firstDayOfWeek, firstDayOfYear) {
  const weekInfoFromLocale = weekInfo(locale);
  const weekStart = firstDayOfWeek ?? weekInfoFromLocale?.firstDay ?? 0;
  const minWeekSize = weekInfoFromLocale?.firstWeekSize ?? 1;
  return firstDayOfYear !== undefined ? calculateWeekWithFirstDayOfYear(date, locale, weekStart, firstDayOfYear) : calculateWeekWithMinWeekSize(date, locale, weekStart, minWeekSize);
}
function calculateWeekWithFirstDayOfYear(date, locale, weekStart, firstDayOfYear) {
  const firstDayOfYearOffset = (7 + firstDayOfYear - weekStart) % 7;
  const currentWeekStart = startOfWeek(date, locale, weekStart);
  const currentWeekEnd = addDays(currentWeekStart, 6);
  function yearStartWeekdayOffset(year) {
    return (7 + new Date(year, 0, 1).getDay() - weekStart) % 7;
  }
  let year = getYear(currentWeekStart);
  if (year < getYear(currentWeekEnd) && yearStartWeekdayOffset(year + 1) <= firstDayOfYearOffset) {
    year++;
  }
  const yearStart = new Date(year, 0, 1);
  const offset = yearStartWeekdayOffset(year);
  const d1w1 = offset <= firstDayOfYearOffset ? addDays(yearStart, -offset) : addDays(yearStart, 7 - offset);
  return 1 + getDiff(endOfDay(currentWeekStart), startOfDay(d1w1), 'weeks');
}
function calculateWeekWithMinWeekSize(date, locale, weekStart, minWeekSize) {
  const currentWeekStart = startOfWeek(date, locale, weekStart);
  const currentWeekEnd = addDays(startOfWeek(date, locale, weekStart), 6);
  function firstWeekSize(year) {
    const yearStart = new Date(year, 0, 1);
    return 7 - getDiff(yearStart, startOfWeek(yearStart, locale, weekStart), 'days');
  }
  let year = getYear(currentWeekStart);
  if (year < getYear(currentWeekEnd) && firstWeekSize(year + 1) >= minWeekSize) {
    year++;
  }
  const yearStart = new Date(year, 0, 1);
  const size = firstWeekSize(year);
  const d1w1 = size >= minWeekSize ? addDays(yearStart, size - 7) : addDays(yearStart, size);
  return 1 + getDiff(endOfDay(currentWeekStart), startOfDay(d1w1), 'weeks');
}
function getDate(date) {
  return date.getDate();
}
function getNextMonth(date) {
  return new Date(date.getFullYear(), date.getMonth() + 1, 1);
}
function getPreviousMonth(date) {
  return new Date(date.getFullYear(), date.getMonth() - 1, 1);
}
function getHours(date) {
  return date.getHours();
}
function getMinutes(date) {
  return date.getMinutes();
}
function startOfYear(date) {
  return new Date(date.getFullYear(), 0, 1);
}
function endOfYear(date) {
  return new Date(date.getFullYear(), 11, 31);
}
function isWithinRange(date, range) {
  return isEqual(date, range[0]) || isEqual(date, range[1]) || isAfter(date, range[0]) && isBefore(date, range[1]);
}
function isValid(date) {
  const d = new Date(date);
  return d instanceof Date && !isNaN(d.getTime());
}
function isAfter(date, comparing) {
  return date.getTime() > comparing.getTime();
}
function isAfterDay(date, comparing) {
  return isAfter(startOfDay(date), startOfDay(comparing));
}
function isBefore(date, comparing) {
  return date.getTime() < comparing.getTime();
}
function isEqual(date, comparing) {
  return date.getTime() === comparing.getTime();
}
function isSameDay(date, comparing) {
  return date.getDate() === comparing.getDate() && date.getMonth() === comparing.getMonth() && date.getFullYear() === comparing.getFullYear();
}
function isSameMonth(date, comparing) {
  return date.getMonth() === comparing.getMonth() && date.getFullYear() === comparing.getFullYear();
}
function isSameYear(date, comparing) {
  return date.getFullYear() === comparing.getFullYear();
}
function getDiff(date, comparing, unit) {
  const d = new Date(date);
  const c = new Date(comparing);
  switch (unit) {
    case 'years':
      return d.getFullYear() - c.getFullYear();
    case 'quarters':
      return Math.floor((d.getMonth() - c.getMonth() + (d.getFullYear() - c.getFullYear()) * 12) / 4);
    case 'months':
      return d.getMonth() - c.getMonth() + (d.getFullYear() - c.getFullYear()) * 12;
    case 'weeks':
      return Math.floor((d.getTime() - c.getTime()) / (1000 * 60 * 60 * 24 * 7));
    case 'days':
      return Math.floor((d.getTime() - c.getTime()) / (1000 * 60 * 60 * 24));
    case 'hours':
      return Math.floor((d.getTime() - c.getTime()) / (1000 * 60 * 60));
    case 'minutes':
      return Math.floor((d.getTime() - c.getTime()) / (1000 * 60));
    case 'seconds':
      return Math.floor((d.getTime() - c.getTime()) / 1000);
    default:
      {
        return d.getTime() - c.getTime();
      }
  }
}
function setHours(date, count) {
  const d = new Date(date);
  d.setHours(count);
  return d;
}
function setMinutes(date, count) {
  const d = new Date(date);
  d.setMinutes(count);
  return d;
}
function setMonth(date, count) {
  const d = new Date(date);
  d.setMonth(count);
  return d;
}
function setDate(date, day) {
  const d = new Date(date);
  d.setDate(day);
  return d;
}
function setYear(date, year) {
  const d = new Date(date);
  d.setFullYear(year);
  return d;
}
function startOfDay(date) {
  return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
}
function endOfDay(date) {
  return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);
}
class VuetifyDateAdapter {
  constructor(options) {
    this.locale = options.locale;
    this.formats = options.formats;
  }
  date(value) {
    return date(value);
  }
  toJsDate(date) {
    return date;
  }
  toISO(date) {
    return toISO$1(this, date);
  }
  parseISO(date) {
    return parseISO(date);
  }
  addMinutes(date, amount) {
    return addMinutes(date, amount);
  }
  addHours(date, amount) {
    return addHours(date, amount);
  }
  addDays(date, amount) {
    return addDays(date, amount);
  }
  addWeeks(date, amount) {
    return addWeeks(date, amount);
  }
  addMonths(date, amount) {
    return addMonths(date, amount);
  }
  getWeekArray(date, firstDayOfWeek) {
    const firstDay = firstDayOfWeek !== undefined ? Number(firstDayOfWeek) : undefined;
    return getWeekArray(date, this.locale, firstDay);
  }
  startOfWeek(date, firstDayOfWeek) {
    const firstDay = firstDayOfWeek !== undefined ? Number(firstDayOfWeek) : undefined;
    return startOfWeek(date, this.locale, firstDay);
  }
  endOfWeek(date) {
    return endOfWeek(date, this.locale);
  }
  startOfMonth(date) {
    return startOfMonth(date);
  }
  endOfMonth(date) {
    return endOfMonth(date);
  }
  format(date, formatString) {
    return format(date, formatString, this.locale, this.formats);
  }
  isEqual(date, comparing) {
    return isEqual(date, comparing);
  }
  isValid(date) {
    return isValid(date);
  }
  isWithinRange(date, range) {
    return isWithinRange(date, range);
  }
  isAfter(date, comparing) {
    return isAfter(date, comparing);
  }
  isAfterDay(date, comparing) {
    return isAfterDay(date, comparing);
  }
  isBefore(date, comparing) {
    return !isAfter(date, comparing) && !isEqual(date, comparing);
  }
  isSameDay(date, comparing) {
    return isSameDay(date, comparing);
  }
  isSameMonth(date, comparing) {
    return isSameMonth(date, comparing);
  }
  isSameYear(date, comparing) {
    return isSameYear(date, comparing);
  }
  setMinutes(date, count) {
    return setMinutes(date, count);
  }
  setHours(date, count) {
    return setHours(date, count);
  }
  setMonth(date, count) {
    return setMonth(date, count);
  }
  setDate(date, day) {
    return setDate(date, day);
  }
  setYear(date, year) {
    return setYear(date, year);
  }
  getDiff(date, comparing, unit) {
    return getDiff(date, comparing, unit);
  }
  getWeekdays(firstDayOfWeek, weekdayFormat) {
    const firstDay = firstDayOfWeek !== undefined ? Number(firstDayOfWeek) : undefined;
    return getWeekdays(this.locale, firstDay, weekdayFormat);
  }
  getYear(date) {
    return getYear(date);
  }
  getMonth(date) {
    return getMonth(date);
  }
  getWeek(date, firstDayOfWeek, firstDayOfYear) {
    const firstDay = firstDayOfWeek !== undefined ? Number(firstDayOfWeek) : undefined;
    const firstWeekStart = firstDayOfYear !== undefined ? Number(firstDayOfYear) : undefined;
    return getWeek(date, this.locale, firstDay, firstWeekStart);
  }
  getDate(date) {
    return getDate(date);
  }
  getNextMonth(date) {
    return getNextMonth(date);
  }
  getPreviousMonth(date) {
    return getPreviousMonth(date);
  }
  getHours(date) {
    return getHours(date);
  }
  getMinutes(date) {
    return getMinutes(date);
  }
  startOfDay(date) {
    return startOfDay(date);
  }
  endOfDay(date) {
    return endOfDay(date);
  }
  startOfYear(date) {
    return startOfYear(date);
  }
  endOfYear(date) {
    return endOfYear(date);
  }
}

// Composables
const DateOptionsSymbol = Symbol.for('vuetify:date-options');
const DateAdapterSymbol = Symbol.for('vuetify:date-adapter');
function createDate(options, locale) {
  const _options = mergeDeep({
    adapter: VuetifyDateAdapter,
    locale: {
      af: 'af-ZA',
      // ar: '', # not the same value for all variants
      bg: 'bg-BG',
      ca: 'ca-ES',
      ckb: '',
      cs: 'cs-CZ',
      de: 'de-DE',
      el: 'el-GR',
      en: 'en-US',
      // es: '', # not the same value for all variants
      et: 'et-EE',
      fa: 'fa-IR',
      fi: 'fi-FI',
      // fr: '', #not the same value for all variants
      hr: 'hr-HR',
      hu: 'hu-HU',
      he: 'he-IL',
      id: 'id-ID',
      it: 'it-IT',
      ja: 'ja-JP',
      ko: 'ko-KR',
      lv: 'lv-LV',
      lt: 'lt-LT',
      nl: 'nl-NL',
      no: 'no-NO',
      pl: 'pl-PL',
      pt: 'pt-PT',
      ro: 'ro-RO',
      ru: 'ru-RU',
      sk: 'sk-SK',
      sl: 'sl-SI',
      srCyrl: 'sr-SP',
      srLatn: 'sr-SP',
      sv: 'sv-SE',
      th: 'th-TH',
      tr: 'tr-TR',
      az: 'az-AZ',
      uk: 'uk-UA',
      vi: 'vi-VN',
      zhHans: 'zh-CN',
      zhHant: 'zh-TW'
    }
  }, options);
  return {
    options: _options,
    instance: createInstance(_options, locale)
  };
}
function daysDiff(adapter, start, stop) {
  const iso = [`${adapter.toISO(stop ?? start).split('T')[0]}T00:00:00Z`, `${adapter.toISO(start).split('T')[0]}T00:00:00Z`];
  return typeof adapter.date() === 'string' ? adapter.getDiff(iso[0], iso[1], 'days') // for StringDateAdapter
  : adapter.getDiff(adapter.date(iso[0]), adapter.date(iso[1]), 'days');
}
function createInstance(options, locale) {
  const instance = reactive(typeof options.adapter === 'function'
  // eslint-disable-next-line new-cap
  ? new options.adapter({
    locale: options.locale[locale.current.value] ?? locale.current.value,
    formats: options.formats
  }) : options.adapter);
  watch(locale.current, value => {
    instance.locale = options.locale[value] ?? value ?? instance.locale;
  });
  return instance;
}
function useDate() {
  const options = inject$1(DateOptionsSymbol);
  if (!options) throw new Error('[Vuetify] Could not find injected date options');
  const locale = useLocale();
  return createInstance(options, locale);
}

// Composables

// Types

const makeCalendarBaseProps = propsFactory({
  start: {
    type: [String, Number, Date],
    validate: validateTimestamp,
    default: () => parseDate(new Date()).date
  },
  end: {
    type: [String, Number, Date],
    validate: validateTimestamp
  },
  weekdays: {
    type: [Array, String],
    default: () => [0, 1, 2, 3, 4, 5, 6],
    validate: validateWeekdays
  },
  firstDayOfWeek: [Number, String],
  firstDayOfYear: [Number, String],
  weekdayFormat: {
    type: Function,
    default: null
  },
  dayFormat: {
    type: Function,
    default: null
  },
  format: String,
  locale: String,
  now: {
    type: String,
    validator: validateTimestamp
  },
  type: {
    type: String,
    default: 'month'
  }
}, 'VCalendar-base');
function useCalendarBase(props) {
  const {
    times,
    updateTimes
  } = useTimes({
    now: props.now
  });
  const locale = provideLocale(props);
  const adapter = useDate();
  const parsedStart = computed(() => {
    if (props.type === 'month') {
      return getStartOfMonth(parseTimestamp(props.start, true));
    }
    return parseTimestamp(props.start, true);
  });
  const parsedEnd = computed(() => {
    const start = parsedStart.value;
    const end = props.end ? parseTimestamp(props.end) || start : start;
    const value = getTimestampIdentifier(end) < getTimestampIdentifier(start) ? start : end;
    if (props.type === 'month') {
      return getEndOfMonth(value);
    }
    return value;
  });
  const parsedValue = computed(() => {
    return validateTimestamp(props.modelValue) ? parseTimestamp(props.modelValue, true) : parsedStart.value || times.today;
  });
  const parsedWeekdays = computed(() => {
    const weekdays = Array.isArray(props.weekdays) ? props.weekdays : (props.weekdays || '').split(',').map(x => parseInt(x, 10));
    const first = adapter.toJsDate(adapter.startOfWeek(adapter.date(), props.firstDayOfWeek)).getDay();
    return [...weekdays.toSorted().filter(v => v >= first), ...weekdays.toSorted().filter(v => v < first)];
  });
  const effectiveWeekdays = computed(() => {
    const start = parsedValue.value;
    const days = parseInt(String(props.categoryDays)) || 1;
    switch (props.type) {
      case 'day':
        return [start.weekday];
      case '4day':
        return [start.weekday, (start.weekday + 1) % 7, (start.weekday + 2) % 7, (start.weekday + 3) % 7];
      case 'category':
        return Array.from({
          length: days
        }, (_, i) => (start.weekday + i) % 7);
      default:
        return parsedWeekdays.value;
    }
  });
  const weekdaySkips = computed(() => {
    return getWeekdaySkips(parsedWeekdays.value);
  });
  const days = computed(() => {
    return createDayList(parsedStart.value, parsedEnd.value, times.today, weekdaySkips.value);
  });
  const dayFormatter = computed(() => {
    if (props.dayFormat) {
      return props.dayFormat;
    }
    return createNativeLocaleFormatter(locale.current.value, () => ({
      timeZone: 'UTC',
      day: 'numeric'
    }));
  });
  const weekdayFormatter = computed(() => {
    if (props.weekdayFormat) {
      return props.weekdayFormat;
    }
    return createNativeLocaleFormatter(locale.current.value, (_tms, short) => ({
      timeZone: 'UTC',
      weekday: short ? 'short' : 'long'
    }));
  });
  function getColorProps(colors) {
    return computeColor(colors);
  }
  function getRelativeClasses(timestamp, outside = false) {
    return {
      'v-present': timestamp.present,
      'v-past': timestamp.past,
      'v-future': timestamp.future,
      'v-outside': outside
    };
  }
  function getWeekNumber(timestamp) {
    return adapter.getWeek(adapter.date(timestamp.date), props.firstDayOfWeek, props.firstDayOfYear);
  }
  function _getStartOfWeek(timestamp) {
    return getStartOfWeek(timestamp, parsedWeekdays.value, times.today);
  }
  function _getEndOfWeek(timestamp) {
    return getEndOfWeek(timestamp, parsedWeekdays.value, times.today);
  }
  function getFormatter(options) {
    return createNativeLocaleFormatter(locale.current.value, () => options);
  }
  return {
    times,
    locale,
    parsedValue,
    parsedWeekdays,
    effectiveWeekdays,
    weekdaySkips,
    parsedStart,
    parsedEnd,
    days,
    dayFormatter,
    weekdayFormatter,
    getColorProps,
    getRelativeClasses,
    getWeekNumber,
    getStartOfWeek: _getStartOfWeek,
    getEndOfWeek: _getEndOfWeek,
    getFormatter,
    updateTimes
  };
}

// Composables

// Types

const makeCalendarWithIntervalsProps = propsFactory({
  maxDays: {
    type: Number,
    default: 7
  },
  intervalHeight: {
    type: [Number, String],
    default: 48,
    validate: validateNumber
  },
  intervalWidth: {
    type: [Number, String],
    default: 60,
    validate: validateNumber
  },
  intervalMinutes: {
    type: [Number, String],
    default: 60,
    validate: validateNumber
  },
  firstInterval: {
    type: [Number, String],
    default: 0,
    validate: validateNumber
  },
  firstTime: {
    type: [Number, String, Object],
    validate: validateTime
  },
  intervalCount: {
    type: [Number, String],
    default: 24,
    validate: validateNumber
  },
  intervalFormat: {
    type: Function,
    default: null
  },
  intervalStyle: {
    type: Function,
    default: null
  },
  showIntervalLabel: {
    type: Function,
    default: null
  }
}, 'VCalendar-intervals');
function useCalendarWithIntervals(props) {
  const base = useCalendarBase(props);
  const scrollAreaRef = shallowRef();
  const parsedFirstInterval = computed(() => {
    return parseInt(String(props.firstInterval || 0));
  });
  const parsedIntervalMinutes = computed(() => {
    return parseInt(String(props.intervalMinutes || 60));
  });
  const parsedIntervalCount = computed(() => {
    return parseInt(String(props.intervalCount || 24));
  });
  const parsedIntervalHeight = computed(() => {
    return parseFloat(String(props.intervalHeight || 48));
  });
  const parsedFirstTime = computed(() => {
    return parseTime(props.firstTime);
  });
  const firstMinute = computed(() => {
    const time = parsedFirstTime.value;
    return time !== false && time >= 0 && time <= MINUTES_IN_DAY ? time : parsedFirstInterval.value * parsedIntervalMinutes.value;
  });
  const effectiveIntervalCount = computed(() => {
    const dayLimit = Math.ceil((MINUTES_IN_DAY - firstMinute.value) / parsedIntervalMinutes.value);
    return clamp(parsedIntervalCount.value, 0, dayLimit);
  });
  const bodyHeight = computed(() => {
    return effectiveIntervalCount.value * parsedIntervalHeight.value;
  });
  const days = computed(() => {
    return createDayList(base.parsedStart.value, base.parsedEnd.value, base.times.today, base.weekdaySkips.value, props.maxDays);
  });
  const intervals = computed(() => {
    const daysValue = days.value;
    const first = firstMinute.value;
    const minutes = parsedIntervalMinutes.value;
    const count = effectiveIntervalCount.value;
    const now = base.times.now;
    return daysValue.map(d => createIntervalList(d, first, minutes, count, now));
  });
  const intervalFormatter = computed(() => {
    if (props.intervalFormat) {
      return props.intervalFormat;
    }
    const hour12 = props.format === 'ampm' ? true : props.format === '24hr' ? false : undefined;
    const hourStyle = props.format === '24hr' ? '2-digit' : 'numeric';
    return createNativeLocaleFormatter(base.locale.current.value, (tms, short) => !short ? {
      timeZone: 'UTC',
      hour: '2-digit',
      minute: '2-digit',
      hour12
    } : tms.minute === 0 ? {
      timeZone: 'UTC',
      hour: hourStyle,
      hour12
    } : {
      timeZone: 'UTC',
      hour: hourStyle,
      minute: '2-digit',
      hour12
    });
  });
  function showIntervalLabelDefault(interval) {
    const first = intervals.value[0][0];
    const isFirst = first.hour === interval.hour && first.minute === interval.minute;
    return !isFirst;
  }
  function intervalStyleDefault(_interval) {
    return undefined;
  }
  function getIntervalAtEvent(e) {
    const bounds = new Box(e.currentTarget);
    const touchEvent = e;
    const mouseEvent = e;
    const touches = touchEvent.changedTouches || touchEvent.touches;
    const target = touches && touches[0] ? touches[0] : mouseEvent;
    const point = getTargetBox([target.clientX, target.clientY]);
    return (point.y - bounds.top) / parsedIntervalHeight.value;
  }
  function getTimestampAtEvent(e, day) {
    const timestamp = copyTimestamp(day);
    const addMinutes = Math.floor(getIntervalAtEvent(e) * parsedIntervalMinutes.value);
    const minutes = firstMinute.value + addMinutes;
    return updateMinutes(timestamp, minutes, base.times.now);
  }
  function getSlotScope(timestamp) {
    const scope = copyTimestamp(timestamp);
    scope.timeToY = timeToY;
    scope.timeDelta = timeDelta;
    scope.minutesToPixels = minutesToPixels;
    scope.week = days.value;
    scope.intervalRange = [firstMinute.value, firstMinute.value + effectiveIntervalCount.value * parsedIntervalMinutes.value];
    return scope;
  }
  function scrollToTime(time) {
    const y = timeToY(time);
    const pane = scrollAreaRef.value;
    if (y === false || !pane) {
      return false;
    }
    pane.scrollTop = y;
    return true;
  }
  function minutesToPixels(minutes) {
    return minutes / parsedIntervalMinutes.value * parsedIntervalHeight.value;
  }
  function timeToY(time, targetDateOrClamp = false) {
    const clamp = targetDateOrClamp !== false;
    const targetDate = typeof targetDateOrClamp !== 'boolean' ? targetDateOrClamp : undefined;
    let y = timeDelta(time, targetDate);
    if (y === false) return y;
    y *= bodyHeight.value;
    if (clamp) {
      if (y < 0) {
        y = 0;
      } else if (y > bodyHeight.value) {
        y = bodyHeight.value;
      }
    } else {
      if (y < 0) {
        y = y + bodyHeight.value;
      } else if (y > bodyHeight.value) {
        y = y - bodyHeight.value;
      }
    }
    return y;
  }
  function timeDelta(time, targetDate) {
    let minutes = parseTime(time);
    if (minutes === false) {
      return false;
    }
    const gap = effectiveIntervalCount.value * parsedIntervalMinutes.value;
    if (targetDate && typeof time === 'object' && 'day' in time) {
      const a = getDayIdentifier(time);
      const b = getDayIdentifier(targetDate);
      minutes += (a - b) * gap;
    }
    const min = firstMinute.value;
    return (minutes - min) / gap;
  }
  return {
    ...base,
    scrollAreaRef,
    parsedFirstInterval,
    parsedIntervalMinutes,
    parsedIntervalCount,
    parsedIntervalHeight,
    parsedFirstTime,
    firstMinute,
    bodyHeight,
    days,
    intervals,
    intervalFormatter,
    showIntervalLabelDefault,
    intervalStyleDefault,
    getIntervalAtEvent,
    getTimestampAtEvent,
    getSlotScope,
    scrollToTime,
    minutesToPixels,
    timeToY,
    timeDelta
  };
}

// Types

const makeIntervalHighlightProps = propsFactory({
  intervalHighlight: {
    type: [Boolean, String],
    default: false
  }
}, 'interval-highlight');
function useIntervalHighlight(props, base) {
  const hoveredTime = shallowRef(null);

  // The underlay paints `background: currentColor`, so we only need a text color.
  const {
    textColorClasses,
    textColorStyles
  } = useTextColor(() => typeof props.intervalHighlight === 'string' && props.intervalHighlight ? props.intervalHighlight : 'surface-variant');

  // Day columns can overlay the intervals, so snap the cursor to an interval row.
  function getHoveredTimeFromEvent(e) {
    const index = Math.floor(base.getIntervalAtEvent(e));
    const intervals = base.intervals.value[0];
    if (!intervals || index < 0 || index >= intervals.length) return null;
    return intervals[index].time;
  }
  function onMousemove(e) {
    if (!props.intervalHighlight) return;
    hoveredTime.value = getHoveredTimeFromEvent(e);
  }
  function onMouseleave() {
    if (!props.intervalHighlight) return;
    hoveredTime.value = null;
  }
  function isHighlighted(interval) {
    return !!props.intervalHighlight && hoveredTime.value === interval.time;
  }
  function genUnderlay() {
    if (!props.intervalHighlight) return undefined;
    return createElementVNode("div", {
      "class": normalizeClass(['v-calendar-daily__day-interval__underlay', textColorClasses.value]),
      "style": normalizeStyle(textColorStyles.value)
    }, null);
  }
  return {
    hoveredTime,
    onMousemove,
    onMouseleave,
    isHighlighted,
    genUnderlay
  };
}

// Types

function mounted$3(el, binding) {
  const handler = binding.value;
  const options = {
    passive: !binding.modifiers?.active
  };
  window.addEventListener('resize', handler, options);
  el._onResize = Object(el._onResize);
  el._onResize[binding.instance.$.uid] = {
    handler,
    options
  };
  if (!binding.modifiers?.quiet) {
    handler();
  }
}
function unmounted$3(el, binding) {
  if (!el._onResize?.[binding.instance.$.uid]) return;
  const {
    handler,
    options
  } = el._onResize[binding.instance.$.uid];
  window.removeEventListener('resize', handler, options);
  delete el._onResize[binding.instance.$.uid];
}
const Resize = {
  mounted: mounted$3,
  unmounted: unmounted$3
};

// Types

const VCalendarDaily = defineComponent({
  name: 'VCalendarDaily',
  directives: {
    vResize: Resize
  },
  props: {
    color: String,
    shortWeekdays: {
      type: Boolean,
      default: true
    },
    shortIntervals: {
      type: Boolean,
      default: true
    },
    hideHeader: Boolean,
    ...makeIntervalHighlightProps(),
    ...makeCalendarBaseProps(),
    ...makeCalendarWithIntervalsProps()
  },
  setup(props, {
    slots,
    attrs
  }) {
    const scrollPush = ref(0);
    const pane = ref();
    const base = useCalendarWithIntervals(props);
    const highlight = useIntervalHighlight(props, base);
    function init() {
      nextTick(onResize);
    }
    function onResize() {
      scrollPush.value = getScrollPush();
    }
    function getScrollPush() {
      return base.scrollAreaRef.value && pane.value ? base.scrollAreaRef.value.offsetWidth - pane.value.offsetWidth : 0;
    }
    function genHead() {
      return createElementVNode("div", {
        "class": "v-calendar-daily__head",
        "style": {
          marginRight: scrollPush.value + 'px'
        }
      }, [genHeadIntervals(), genHeadDays()]);
    }
    function genHeadIntervals() {
      const width = convertToUnit(props.intervalWidth);
      return createElementVNode("div", {
        "class": "v-calendar-daily__intervals-head",
        "style": {
          width
        }
      }, [slots['interval-header']?.()]);
    }
    function genHeadDays() {
      return base.days.value.map(genHeadDay);
    }
    function genHeadDay(day, index) {
      const events = getPrefixedEventHandlers(attrs, ':day', nativeEvent => ({
        nativeEvent,
        ...base.getSlotScope(day)
      }));
      return createElementVNode("div", mergeProps({
        "key": day.date,
        "class": ['v-calendar-daily_head-day', base.getRelativeClasses(day)]
      }, events), [genHeadWeekday(day), genHeadDayLabel(day), genDayHeader(day, index)]);
    }
    function genDayHeader(day, index) {
      return slots['day-header']?.({
        week: base.days.value,
        ...day,
        index
      }) ?? [];
    }
    function genHeadWeekday(day) {
      const color = day.present ? props.color : undefined;
      return createElementVNode("div", mergeProps(base.getColorProps({
        text: color
      }), {
        "class": "v-calendar-daily_head-weekday"
      }), [base.weekdayFormatter.value(day, props.shortWeekdays)]);
    }
    function genHeadDayLabel(day) {
      return createElementVNode("div", {
        "class": "v-calendar-daily_head-day-label"
      }, [slots['day-label-header']?.(day) ?? genHeadDayButton(day)]);
    }
    function genHeadDayButton(day) {
      const events = getPrefixedEventHandlers(attrs, ':date', nativeEvent => ({
        nativeEvent,
        ...day
      }));
      return createVNode(VIconBtn, mergeProps({
        "active": day.present,
        "activeColor": props.color,
        "variant": "outlined",
        "baseVariant": "text",
        "onUpdate:active": noop
      }, events), {
        default: () => [base.dayFormatter.value(day, false)]
      });
    }
    function genBody() {
      return createElementVNode("div", {
        "class": "v-calendar-daily__body"
      }, [genScrollArea()]);
    }
    function genScrollArea() {
      return createElementVNode("div", {
        "ref": base.scrollAreaRef,
        "class": "v-calendar-daily__scroll-area"
      }, [genPane()]);
    }
    function genPane() {
      return createElementVNode("div", {
        "ref": pane,
        "class": "v-calendar-daily__pane",
        "style": {
          height: convertToUnit(base.bodyHeight.value)
        }
      }, [genDayContainer()]);
    }
    function genDayContainer() {
      return createElementVNode("div", {
        "class": "v-calendar-daily__day-container"
      }, [genBodyIntervals(), slots.days?.() ?? genDays()]);
    }
    function genDays() {
      return base.days.value.map((day, index) => {
        const events = getPrefixedEventHandlers(attrs, ':time', nativeEvent => ({
          nativeEvent,
          ...base.getSlotScope(base.getTimestampAtEvent(nativeEvent, day))
        }));
        return createElementVNode("div", mergeProps({
          "key": day.date,
          "class": ['v-calendar-daily__day', base.getRelativeClasses(day)]
        }, events, {
          "onMousemove": highlight.onMousemove,
          "onMouseleave": highlight.onMouseleave
        }), [genDayIntervals(index), genDayBody(day)]);
      });
    }
    function genDayBody(day) {
      return slots['day-body']?.(base.getSlotScope(day)) ?? [];
    }
    function genDayIntervals(index) {
      return base.intervals.value[index].map(genDayInterval);
    }
    function genDayInterval(interval) {
      const height = convertToUnit(props.intervalHeight);
      const styler = props.intervalStyle || base.intervalStyleDefault;
      return createElementVNode("div", {
        "class": normalizeClass(['v-calendar-daily__day-interval', {
          'v-calendar-daily__day-interval--hover': highlight.isHighlighted(interval)
        }]),
        "key": interval.time,
        "style": normalizeStyle([{
          height
        }, styler(interval)])
      }, [highlight.genUnderlay(), slots.interval?.(base.getSlotScope(interval))]);
    }
    function genBodyIntervals() {
      const width = convertToUnit(props.intervalWidth);
      const events = getPrefixedEventHandlers(attrs, ':interval', nativeEvent => ({
        nativeEvent,
        ...base.getTimestampAtEvent(nativeEvent, base.parsedStart.value)
      }));
      return createElementVNode("div", mergeProps({
        "class": "v-calendar-daily__intervals-body",
        "style": {
          width
        }
      }, events), [genIntervalLabels()]);
    }
    function genIntervalLabels() {
      if (!base.intervals.value.length) return null;
      return base.intervals.value[0].map(genIntervalLabel);
    }
    function genIntervalLabel(interval) {
      const height = convertToUnit(props.intervalHeight);
      const short = props.shortIntervals;
      const shower = props.showIntervalLabel || base.showIntervalLabelDefault;
      const show = shower(interval);
      const label = show ? base.intervalFormatter.value(interval, short) : undefined;
      return createElementVNode("div", {
        "key": interval.time,
        "class": "v-calendar-daily__interval",
        "style": {
          height
        }
      }, [createElementVNode("div", {
        "class": "v-calendar-daily__interval-text"
      }, [label])]);
    }
    onMounted(init);
    useRender(() => withDirectives(createElementVNode("div", {
      "class": normalizeClass(['v-calendar-daily', attrs.class]),
      "onDragstart": e => e.preventDefault()
    }, [!props.hideHeader ? genHead() : undefined, genBody()]), [[Resize, onResize, void 0, {
      quiet: true
    }]]));
    return {
      ...base,
      scrollPush,
      pane,
      init,
      onResize,
      getScrollPush
    };
  }
});

// Types

function parsedCategoryText(category, categoryText) {
  return typeof categoryText === 'function' ? categoryText(category) : typeof categoryText === 'string' && typeof category === 'object' && category ? category[categoryText] : typeof category === 'string' ? category : '';
}
function getParsedCategories(categories, categoryText) {
  if (typeof categories === 'string') return categories.split(/\s*,\s/);
  if (Array.isArray(categories)) {
    return categories.map(category => {
      if (typeof category === 'string') return category;
      const categoryName = typeof category.categoryName === 'string' ? category.categoryName : parsedCategoryText(category, categoryText);
      return {
        ...category,
        categoryName
      };
    });
  }
  return [];
}

// Types

const VCalendarCategory = defineComponent({
  name: 'VCalendarCategory',
  props: {
    categories: {
      type: [Array, String],
      default: ''
    },
    categoryText: [String, Function],
    categoryForInvalid: {
      type: String,
      default: ''
    },
    ...makeIntervalHighlightProps(),
    ...makeCalendarBaseProps(),
    ...makeCalendarWithIntervalsProps()
  },
  setup(props, {
    slots,
    attrs
  }) {
    const base = useCalendarWithIntervals(props);
    const highlight = useIntervalHighlight(props, base);
    const parsedCategories = computed(() => {
      return getParsedCategories(props.categories, props.categoryText);
    });
    function getCategoryScope(scope, category) {
      const cat = typeof category === 'object' && category && category.categoryName === props.categoryForInvalid ? null : category;
      return {
        ...scope,
        category: cat
      };
    }
    function genDayHeader(scope) {
      return createElementVNode("div", {
        "class": "v-calendar-category__columns"
      }, [parsedCategories.value.map(category => {
        return genDayHeaderCategory(scope, getCategoryScope(scope, category));
      })]);
    }
    function genDayHeaderCategory(day, scope) {
      const headerTitle = typeof scope.category === 'object' ? scope.category.categoryName : scope.category;
      const events = getPrefixedEventHandlers(attrs, ':dayCategory', () => {
        return getCategoryScope(base.getSlotScope(day) || day, scope.category);
      });
      return createElementVNode("div", mergeProps({
        "class": "v-calendar-category__column-header"
      }, events), [slots.category?.(scope) ?? genDayHeaderCategoryTitle(headerTitle), slots['day-header']?.(scope)]);
    }
    function genDayHeaderCategoryTitle(categoryName) {
      return createElementVNode("div", {
        "class": "v-calendar-category__category"
      }, [categoryName === null ? props.categoryForInvalid : categoryName]);
    }
    function genDays() {
      const days = [];
      base.days.value.forEach((d, j) => {
        const day = new Array(parsedCategories.value.length || 1);
        day.fill(d);
        days.push(...day.map((v, i) => genDay(v, j, i)));
      });
      return days;
    }
    function genDay(day, index, categoryIndex) {
      const category = parsedCategories.value[categoryIndex];
      const events = getPrefixedEventHandlers(attrs, ':time', e => {
        return base.getSlotScope(base.getTimestampAtEvent(e, day));
      });
      return createElementVNode("div", mergeProps({
        "key": day.date + '-' + categoryIndex,
        "class": ['v-calendar-daily__day', base.getRelativeClasses(day)]
      }, events, {
        "onMousemove": highlight.onMousemove,
        "onMouseleave": highlight.onMouseleave
      }), [genDayIntervals(index, category), genDayBody(day, category)]);
    }
    function genDayIntervals(index, category) {
      return base.intervals.value[index].map(v => genDayInterval(v, category));
    }
    function genDayInterval(interval, category) {
      const height = convertToUnit(props.intervalHeight);
      const styler = props.intervalStyle || base.intervalStyleDefault;
      return createElementVNode("div", {
        "key": interval.time,
        "class": normalizeClass(['v-calendar-daily__day-interval', {
          'v-calendar-daily__day-interval--hover': highlight.isHighlighted(interval)
        }]),
        "style": normalizeStyle([{
          height
        }, styler({
          ...interval,
          category
        })])
      }, [highlight.genUnderlay(), slots.interval?.(getCategoryScope(base.getSlotScope(interval), category))]);
    }
    function genDayBody(day, category) {
      return createElementVNode("div", {
        "class": "v-calendar-category__columns"
      }, [genDayBodyCategory(day, category)]);
    }
    function genDayBodyCategory(day, category) {
      const events = getPrefixedEventHandlers(attrs, ':timeCategory', e => {
        return getCategoryScope(base.getSlotScope(base.getTimestampAtEvent(e, day)), category);
      });
      return createElementVNode("div", mergeProps({
        "class": "v-calendar-category__column"
      }, events), [slots['day-body']?.(getCategoryScope(base.getSlotScope(day), category))]);
    }
    useRender(() => createVNode(VCalendarDaily, mergeProps({
      "class": ['v-calendar-daily', 'v-calendar-category']
    }, props), {
      ...slots,
      days: genDays,
      'day-header': genDayHeader
    }));
    return {
      ...base,
      parsedCategories
    };
  }
});

/**
 * Centralized key alias mapping for consistent key normalization across the hotkey system.
 *
 * This maps various user-friendly aliases to canonical key names that match
 * KeyboardEvent.key values (in lowercase) where possible.
 */
const keyAliasMap = {
  // Modifier aliases (from vue-use, other libraries, and current implementation)
  control: 'ctrl',
  command: 'cmd',
  option: 'alt',
  // Arrow key aliases (common abbreviations)
  up: 'arrowup',
  down: 'arrowdown',
  left: 'arrowleft',
  right: 'arrowright',
  // Other common key aliases
  esc: 'escape',
  spacebar: ' ',
  space: ' ',
  return: 'enter',
  del: 'delete',
  // Symbol aliases (existing from hotkey-parsing.ts)
  plus: '+',
  slash: '/',
  underscore: '_',
  minus: '-',
  hyphen: '-'
};

/**
 * Normalizes a key string to its canonical form using the alias map.
 *
 * @param key - The key string to normalize
 * @returns The canonical key name in lowercase
 */
function normalizeKey(key) {
  const lowerKey = key.toLowerCase();
  return keyAliasMap[lowerKey] || lowerKey;
}

// Utilities

// Types

class ParseError extends Error {}

/**
 * Splits a single combination string into individual key parts.
 * Grammar:
 *
 * sequence   = alternate *('-' alternate)
 * alternate  = combo *('/' combo)
 * combo      = key *(('+' | '_') key)
 * key        = /./ *(/[^-/+_ ]/)
 *
 */
function parseKeyCombination(input) {
  let pos = 0;
  try {
    const result = parseSequence();
    if (!atEnd()) {
      throw new ParseError(`Unexpected character '${peek()}' at position ${pos}`);
    }
    return result;
  } catch (err) {
    if (err instanceof ParseError) {
      consoleWarn(`Invalid hotkey combination: ${err.message}\n  ${input}\n  ${' '.repeat(pos)}^`);
      return '';
    } else {
      throw err;
    }
  }
  function peek(ahead = 0) {
    return pos + ahead < input.length ? input[pos + ahead] : null;
  }
  function consume() {
    if (pos >= input.length) {
      throw new ParseError('Unexpected end of input');
    }
    return input[pos++];
  }
  function atEnd() {
    return pos >= input.length;
  }

  // sequence = alternate *('-' alternate)
  function parseSequence() {
    const parts = [parseAlternate()];
    while (peek() === '-') {
      consume();
      parts.push(parseAlternate());
    }
    if (parts.length === 1) return parts[0];
    return {
      type: 'sequence',
      parts
    };
  }

  // alternate = combo *('/' combo)
  function parseAlternate() {
    const parts = [parseCombo()];
    while (peek() === '/') {
      consume();
      parts.push(parseCombo());
    }
    if (parts.length === 1) return parts[0];
    return {
      type: 'alternate',
      parts
    };
  }

  // combo = key *(('+' | '_') key)
  function parseCombo() {
    const keys = [parseKey()];
    while (includes(['+', '_'], peek())) {
      consume();
      keys.push(parseKey());
    }
    if (keys.length === 1) return keys[0];
    return {
      type: 'combo',
      parts: keys
    };
  }

  // key = /./ *(/[^-/+_ ]/)
  function parseKey() {
    const ch = peek();
    if (ch == null) {
      throw new ParseError('Unexpected end of input');
    }
    const next = peek(1);
    if (isSep(ch) && next != null && !isSep(next)) {
      throw new ParseError(`Unexpected separator '${ch}' at position ${pos}`);
    }
    const first = consume();
    // separator keys are always a single character
    if (isSep(first)) return first;
    const chars = [first];
    while (!atEnd() && !isSep(peek()) && peek() !== ' ') {
      chars.push(consume());
    }
    return normalizeKey(chars.join(''));
  }
}
function isSep(char) {
  return includes(['-', '/', '+', '_'], char);
}

// Composables

// Types

const MODIFIERS = ['ctrl', 'shift', 'alt', 'meta', 'cmd'];
const modifiersSet = new Set(MODIFIERS);
function isModifier(key) {
  return modifiersSet.has(key);
}
const emptyModifiers = Object.fromEntries(MODIFIERS.map(m => [m, false]));
function useHotkey(keys, callback, options = {}) {
  if (!IN_BROWSER) return function () {};
  const {
    event = 'keydown',
    inputs = false,
    preventDefault = true,
    sequenceTimeout = 1000
  } = options;
  const isMac = navigator?.userAgent?.includes('Macintosh') ?? false;
  let timeout = 0;
  let keyGroups;
  let isSequence = false;
  let groupIndex = 0;
  function isInputFocused() {
    if (toValue(inputs)) return false;
    const activeElement = getActiveElement();
    return activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA' || activeElement.isContentEditable || activeElement.contentEditable === 'true');
  }
  function resetSequence() {
    groupIndex = 0;
    clearTimeout(timeout);
  }
  function handler(e) {
    const group = keyGroups[groupIndex];
    if (!group || isInputFocused()) return;
    if (!matchesKeyGroup(e, group, isMac)) {
      if (isSequence) resetSequence();
      return;
    }
    if (toValue(preventDefault)) e.preventDefault();
    if (!isSequence) {
      callback(e);
      return;
    }
    clearTimeout(timeout);
    groupIndex++;
    if (groupIndex === keyGroups.length) {
      callback(e);
      resetSequence();
      return;
    }
    timeout = window.setTimeout(resetSequence, toValue(sequenceTimeout));
  }
  function cleanup() {
    window.removeEventListener(toValue(event), handler);
    clearTimeout(timeout);
  }
  watch(() => toValue(keys), newKeys => {
    cleanup();
    if (newKeys) {
      const parsed = parseKeyCombination(newKeys.toLowerCase());
      if (parsed) {
        const parts = typeof parsed !== 'string' && parsed.type === 'sequence' ? parsed.parts : [parsed];
        isSequence = parts.length > 1;
        keyGroups = parts;
        resetSequence();
        window.addEventListener(toValue(event), handler);
      }
    }
  }, {
    immediate: true
  });

  // Watch for changes in the event type to re-register the listener
  watch(() => toValue(event), (newEvent, oldEvent) => {
    if (oldEvent && keyGroups && keyGroups.length > 0) {
      window.removeEventListener(oldEvent, handler);
      window.addEventListener(newEvent, handler);
    }
  });
  onScopeDispose(cleanup, true);
  return cleanup;
}
function matchesKeyGroup(e, group, isMac) {
  if (typeof group !== 'string' && group.type === 'alternate') {
    return group.parts.some(part => matchesKeyGroup(e, part, isMac));
  }
  const {
    modifiers,
    actualKey
  } = parseKeyGroup(group);
  const expectCtrl = modifiers.ctrl || !isMac && (modifiers.cmd || modifiers.meta);
  const expectMeta = isMac && (modifiers.cmd || modifiers.meta);
  return e.ctrlKey === expectCtrl && e.metaKey === expectMeta && e.shiftKey === modifiers.shift && e.altKey === modifiers.alt && e.key.toLowerCase() === actualKey?.toLowerCase();
}
function parseKeyGroup(group) {
  const parts = typeof group === 'string' ? [group] : group.parts;
  const modifiers = {
    ...emptyModifiers
  };
  let actualKey;
  for (const part of parts) {
    if (isModifier(part)) {
      modifiers[part] = true;
    } else {
      // TODO: handle multiple keys
      actualKey = part;
    }
  }
  return {
    modifiers,
    actualKey
  };
}

// Utilities

// Types

const makeMaskProps = propsFactory({
  mask: [String, Object]
}, 'mask');
const defaultDelimiters = /[-!$%^&*()_+|~=`{}[\]:";'<>?,./\\ ]/;
const presets = {
  'credit-card': '#### - #### - #### - ####',
  date: '##/##/####',
  'date-time': '##/##/#### ##:##',
  'iso-date': '####-##-##',
  'iso-date-time': '####-##-## ##:##',
  phone: '(###) ### - ####',
  social: '###-##-####',
  time: '##:##',
  'time-with-seconds': '##:##:##'
};
const defaultTokens = {
  '#': {
    pattern: /[0-9]/
  },
  A: {
    pattern: /[A-Z]/i,
    convert: v => v.toUpperCase()
  },
  a: {
    pattern: /[a-z]/i,
    convert: v => v.toLowerCase()
  },
  N: {
    pattern: /[0-9A-Z]/i,
    convert: v => v.toUpperCase()
  },
  n: {
    pattern: /[0-9a-z]/i,
    convert: v => v.toLowerCase()
  },
  X: {
    pattern: defaultDelimiters
  }
};
function useMask(props) {
  const mask = computed(() => {
    if (typeof props.mask === 'string') {
      if (props.mask in presets) return presets[props.mask];
      return props.mask;
    }
    return props.mask?.mask ?? '';
  });
  const tokens = computed(() => {
    return {
      ...defaultTokens,
      ...(isObject(props.mask) ? props.mask.tokens : null)
    };
  });
  function isMask(char) {
    return char in tokens.value;
  }
  function maskValidates(mask, char) {
    if (char == null || !isMask(mask)) return false;
    const item = tokens.value[mask];
    if (item.pattern) return item.pattern.test(char);
    return item.test(char);
  }
  function convert(mask, char) {
    const item = tokens.value[mask];
    return item.convert ? item.convert(char) : char;
  }
  function maskText(text) {
    const trimmedText = text?.trim().replace(/\s+/g, ' ');
    if (trimmedText == null) return '';
    if (!mask.value.length || !trimmedText.length) return trimmedText;
    let textIndex = 0;
    let maskIndex = 0;
    let newText = '';
    while (maskIndex < mask.value.length) {
      const mchar = mask.value[maskIndex];
      const tchar = trimmedText[textIndex];

      // Escaped character in mask, the next mask character is inserted
      if (mchar === '\\') {
        newText += mask.value[maskIndex + 1];
        maskIndex += 2;
        continue;
      }
      if (!isMask(mchar)) {
        newText += mchar;
        if (tchar === mchar) {
          textIndex++;
        }
      } else if (maskValidates(mchar, tchar)) {
        newText += convert(mchar, tchar);
        textIndex++;
      } else if (textIndex < trimmedText.length) {
        // No match, try the next input character
        textIndex++;
        continue;
      } else {
        break;
      }
      maskIndex++;
    }
    return newText;
  }
  function unmaskText(text) {
    if (text == null) return null;
    if (!mask.value.length || !text.length) return text;
    let result = '';
    const unmaskMap = getUnmaskMap(text);
    for (let i = 0; i < text.length; i++) {
      if (!unmaskMap[i]) result += text[i];
    }
    return result;
  }
  function isDelimiter(text, index) {
    if (!mask.value.length || !text.length) return false;
    return !!getUnmaskMap(text)[index];
  }
  function getUnmaskMap(text) {
    if (text == null || !mask.value.length || !text.length) return [];
    let textIndex = 0;
    let maskIndex = 0;
    const result = Array.from({
      length: text.length
    }, () => true);
    while (true) {
      const mchar = mask.value[maskIndex];
      const tchar = text[textIndex];
      if (tchar == null) break;
      if (mchar == null) {
        result[textIndex] = false;
        textIndex++;
        continue;
      }

      // Escaped character in mask, skip the next input character
      if (mchar === '\\') {
        if (tchar === mask.value[maskIndex + 1]) {
          textIndex++;
        }
        maskIndex += 2;
        continue;
      }
      if (maskValidates(mchar, tchar)) {
        // masked char
        result[textIndex] = false;
        textIndex++;
        maskIndex++;
        continue;
      } else if (mchar !== tchar) {
        // input doesn't match mask, skip forward until it does
        while (true) {
          const mchar = mask.value[maskIndex++];
          if (mchar == null || maskValidates(mchar, tchar)) break;
        }
        continue;
      }
      textIndex++;
      maskIndex++;
    }
    return result;
  }
  function isValid(text) {
    if (!text) return false;
    return unmaskText(text) === unmaskText(maskText(text));
  }
  function isComplete(text) {
    if (!text) return false;
    const maskedText = maskText(text);
    return maskedText.length === mask.value.length && isValid(text);
  }
  return {
    isDelimiter,
    isValid,
    isComplete,
    mask: maskText,
    unmask: unmaskText
  };
}

// Types

const VCalendarWeekly = defineComponent({
  name: 'VCalendarWeekly',
  props: {
    minWeeks: {
      validate: validateNumber,
      default: 1
    },
    monthFormat: Function,
    showWeek: Boolean,
    color: String,
    shortWeekdays: {
      type: Boolean,
      default: true
    },
    showMonthOnFirst: {
      type: Boolean,
      default: true
    },
    shortMonths: {
      type: Boolean,
      default: true
    },
    hideHeader: Boolean,
    ...makeCalendarBaseProps()
  },
  setup(props, {
    slots,
    attrs
  }) {
    const base = useCalendarBase(props);
    const theme = useTheme();
    const parsedMinWeeks = computed(() => {
      return parseInt(String(props.minWeeks));
    });
    const days = computed(() => {
      const minDays = parsedMinWeeks.value * base.parsedWeekdays.value.length;
      const start = base.getStartOfWeek(base.parsedStart.value);
      const end = base.getEndOfWeek(base.parsedEnd.value);
      return createDayList(start, end, base.times.today, base.weekdaySkips.value, Number.MAX_SAFE_INTEGER, minDays);
    });
    const todayWeek = computed(() => {
      const today = base.times.today;
      const start = base.getStartOfWeek(today);
      const end = base.getEndOfWeek(today);
      return createDayList(start, end, today, base.weekdaySkips.value, base.parsedWeekdays.value.length, base.parsedWeekdays.value.length);
    });
    const monthFormatter = computed(() => {
      if (props.monthFormat) {
        // TODO: what happens when this is a string?
        return props.monthFormat;
      }
      return createNativeLocaleFormatter(base.locale.current.value, (_tms, short) => ({
        timeZone: 'UTC',
        month: short ? 'short' : 'long'
      }));
    });
    function isOutside(day) {
      const dayIdentifier = getDayIdentifier(day);
      return dayIdentifier < getDayIdentifier(base.parsedStart.value) || dayIdentifier > getDayIdentifier(base.parsedEnd.value);
    }
    function genHead() {
      return createElementVNode("div", {
        "class": "v-calendar-weekly__head",
        "role": "row"
      }, [genHeadDays()]);
    }
    function genHeadDays() {
      const header = todayWeek.value.map(genHeadDay);
      if (props.showWeek) {
        header.unshift(createElementVNode("div", {
          "class": "v-calendar-weekly__head-weeknumber"
        }, null));
      }
      return header;
    }
    function genHeadDay(day, index) {
      const outside = isOutside(days.value[index]);
      const color = day.present ? props.color : undefined;
      return createElementVNode("div", mergeProps(base.getColorProps({
        text: color
      }), {
        "key": day.date,
        "class": ['v-calendar-weekly__head-weekday', base.getRelativeClasses(day, outside)],
        "role": "columnheader"
      }), [base.weekdayFormatter.value(day, props.shortWeekdays)]);
    }
    function genWeeks() {
      const daysValue = days.value;
      const weekDays = base.parsedWeekdays.value.length;
      const weeks = [];
      for (let i = 0; i < daysValue.length; i += weekDays) {
        weeks.push(genWeek(daysValue.slice(i, i + weekDays), getWeekNumber(daysValue[i])));
      }
      return weeks;
    }
    function genWeek(week, weekNumber) {
      const weekNodes = week.map((day, index) => genDay(day, index, week));
      if (props.showWeek) {
        weekNodes.unshift(genWeekNumber(weekNumber));
      }
      return createElementVNode("div", {
        "key": week[0].date,
        "class": "v-calendar-weekly__week",
        "role": "row"
      }, [weekNodes]);
    }
    function getWeekNumber(determineDay) {
      return base.getWeekNumber(determineDay);
    }
    function genWeekNumber(weekNumber) {
      return createElementVNode("div", {
        "class": "v-calendar-weekly__weeknumber"
      }, [createElementVNode("small", null, [String(weekNumber)])]);
    }
    function genDay(day, index, week) {
      const outside = isOutside(day);
      const events = getPrefixedEventHandlers(attrs, ':day', nativeEvent => {
        return {
          nativeEvent,
          ...day
        };
      });
      return createElementVNode("div", mergeProps({
        "key": day.date,
        "class": ['v-calendar-weekly__day', base.getRelativeClasses(day, outside)],
        "role": "cell"
      }, events), [genDayLabel(day), slots.day?.({
        outside,
        index,
        week,
        ...day
      })]);
    }
    function genDayLabel(day) {
      return createElementVNode("div", {
        "class": "v-calendar-weekly__day-label"
      }, [slots['day-label']?.(day) ?? genDayLabelButton(day)]);
    }
    function genDayLabelButton(day) {
      const hasMonth = day.day === 1 && props.showMonthOnFirst;
      const events = getPrefixedEventHandlers(attrs, ':date', nativeEvent => ({
        nativeEvent,
        ...day
      }));
      return createVNode(VIconBtn, mergeProps({
        "active": day.present,
        "activeColor": props.color,
        "variant": "outlined",
        "baseVariant": "text",
        "onUpdate:active": noop
      }, events), {
        default: () => [hasMonth ? monthFormatter.value(day, props.shortMonths) + ' ' + base.dayFormatter.value(day, false) : base.dayFormatter.value(day, false)]
      });
    }
    useRender(() => createElementVNode("div", {
      "class": normalizeClass(['v-calendar-weekly', theme.themeClasses.value]),
      "onDragstart": e => e.preventDefault()
    }, [!props.hideHeader ? genHead() : undefined, genWeeks()]));
    return {
      ...base,
      days,
      todayWeek,
      monthFormatter,
      isOutside
    };
  }
});

// Types

const MILLIS_IN_DAY = 86400000;
function getVisuals(events, minStart = 0) {
  const visuals = events.map(event => ({
    event,
    columnCount: 0,
    column: 0,
    left: 0,
    width: 100
  }));
  visuals.sort((a, b) => {
    return Math.max(minStart, a.event.startTimestampIdentifier) - Math.max(minStart, b.event.startTimestampIdentifier) || b.event.endTimestampIdentifier - a.event.endTimestampIdentifier;
  });
  return visuals;
}
function hasOverlap(s0, e0, s1, e1, exclude = true) {
  return exclude ? !(s0 >= e1 || e0 <= s1) : !(s0 > e1 || e0 < s1);
}
function setColumnCount(groups) {
  groups.forEach(group => {
    group.visuals.forEach(groupVisual => {
      groupVisual.columnCount = groups.length;
    });
  });
}
function getRange(event) {
  return [event.startTimestampIdentifier, event.endTimestampIdentifier];
}
function getDayRange(event) {
  return [event.startIdentifier, event.endIdentifier];
}
function getNormalizedRange(event, dayStart) {
  return [Math.max(dayStart, event.startTimestampIdentifier), Math.min(dayStart + MILLIS_IN_DAY, event.endTimestampIdentifier)];
}
function getOpenGroup(groups, start, end, timed) {
  for (let i = 0; i < groups.length; i++) {
    const group = groups[i];
    let intersected = false;
    if (hasOverlap(start, end, group.start, group.end, timed)) {
      for (let k = 0; k < group.visuals.length; k++) {
        const groupVisual = group.visuals[k];
        const [groupStart, groupEnd] = timed ? getRange(groupVisual.event) : getDayRange(groupVisual.event);
        if (hasOverlap(start, end, groupStart, groupEnd, timed)) {
          intersected = true;
          break;
        }
      }
    }
    if (!intersected) {
      return i;
    }
  }
  return -1;
}
function getOverlapGroupHandler(firstWeekday) {
  const handler = {
    groups: [],
    min: -1,
    max: -1,
    reset: () => {
      handler.groups = [];
      handler.min = handler.max = -1;
    },
    getVisuals: (day, dayEvents, timed, reset = false) => {
      if (day.weekday === firstWeekday || reset) {
        handler.reset();
      }
      const dayStart = getTimestampIdentifier(day);
      const visuals = getVisuals(dayEvents, dayStart);
      visuals.forEach(visual => {
        const [start, end] = timed ? getRange(visual.event) : getDayRange(visual.event);
        if (handler.groups.length > 0 && !hasOverlap(start, end, handler.min, handler.max, timed)) {
          setColumnCount(handler.groups);
          handler.reset();
        }
        let targetGroup = getOpenGroup(handler.groups, start, end, timed);
        if (targetGroup === -1) {
          targetGroup = handler.groups.length;
          handler.groups.push({
            start,
            end,
            visuals: []
          });
        }
        const target = handler.groups[targetGroup];
        target.visuals.push(visual);
        target.start = Math.min(target.start, start);
        target.end = Math.max(target.end, end);
        visual.column = targetGroup;
        if (handler.min === -1) {
          handler.min = start;
          handler.max = end;
        } else {
          handler.min = Math.min(handler.min, start);
          handler.max = Math.max(handler.max, end);
        }
      });
      setColumnCount(handler.groups);
      if (timed) {
        handler.reset();
      }
      return visuals;
    }
  };
  return handler;
}

// Types
const FULL_WIDTH$1 = 100;
const column = (events, firstWeekday, overlapThreshold) => {
  const handler = getOverlapGroupHandler(firstWeekday);
  return (day, dayEvents, timed, reset) => {
    const visuals = handler.getVisuals(day, dayEvents, timed, reset);
    if (timed) {
      visuals.forEach(visual => {
        visual.left = visual.column * FULL_WIDTH$1 / visual.columnCount;
        visual.width = FULL_WIDTH$1 / visual.columnCount;
      });
    }
    return visuals;
  };
};

// Types
const FULL_WIDTH = 100;
const DEFAULT_OFFSET = 5;
const WIDTH_MULTIPLIER = 1.7;

/**
 * Variation of column mode where events can be stacked. The priority of this
 * mode is to stack events together taking up the least amount of space while
 * trying to ensure the content of the event is always visible as well as its
 * start and end. A sibling column has intersecting event content and must be
 * placed beside each other. Non-sibling columns are offset by 5% from the
 * previous column. The width is scaled by 1.7 so the events overlap and
 * whitespace is reduced. If there is a hole in columns the event width is
 * scaled up so it intersects with the next column. The columns have equal
 * width in the space they are given. If the event doesn't have any to the
 * right of it that intersect with its content, its right side is extended
 * to the right side.
 */

const stack = (events, firstWeekday, overlapThreshold) => {
  const handler = getOverlapGroupHandler(firstWeekday);

  // eslint-disable-next-line max-statements
  return (day, dayEvents, timed, reset) => {
    if (!timed) {
      return handler.getVisuals(day, dayEvents, timed, reset);
    }
    const dayStart = getTimestampIdentifier(day);
    const visuals = getVisuals(dayEvents, dayStart);
    const groups = getGroups(visuals, dayStart);
    for (const group of groups) {
      const nodes = [];
      for (const visual of group.visuals) {
        const child = getNode(visual, dayStart);
        const index = getNextIndex(child, nodes);
        if (index === false) {
          const parent = getParent(child, nodes);
          if (parent) {
            child.parent = parent;
            child.sibling = hasOverlap(child.start, child.end, parent.start, addTime(parent.start, overlapThreshold));
            child.index = parent.index + 1;
            parent.children.push(child);
          }
        } else {
          const [parent] = getOverlappingRange(child, nodes, index - 1, index - 1);
          const children = getOverlappingRange(child, nodes, index + 1, index + nodes.length, true);
          child.children = children;
          child.index = index;
          if (parent) {
            child.parent = parent;
            child.sibling = hasOverlap(child.start, child.end, parent.start, addTime(parent.start, overlapThreshold));
            parent.children.push(child);
          }
          for (const grand of children) {
            if (grand.parent === parent) {
              grand.parent = child;
            }
            const grandNext = grand.index - child.index <= 1;
            if (grandNext && child.sibling && hasOverlap(child.start, addTime(child.start, overlapThreshold), grand.start, grand.end)) {
              grand.sibling = true;
            }
          }
        }
        nodes.push(child);
      }
      calculateBounds(nodes, overlapThreshold);
    }
    visuals.sort((a, b) => a.left - b.left || a.event.startTimestampIdentifier - b.event.startTimestampIdentifier);
    return visuals;
  };
};
function calculateBounds(nodes, overlapThreshold) {
  for (const node of nodes) {
    const {
      visual,
      parent
    } = node;
    const columns = getMaxChildIndex(node) + 1;
    const spaceLeft = parent ? parent.visual.left : 0;
    const spaceWidth = FULL_WIDTH - spaceLeft;
    const offset = Math.min(DEFAULT_OFFSET, FULL_WIDTH / columns);
    const columnWidthMultiplier = getColumnWidthMultiplier(node, nodes);
    const columnOffset = spaceWidth / (columns - node.index + 1);
    const columnWidth = spaceWidth / (columns - node.index + (node.sibling ? 1 : 0)) * columnWidthMultiplier;
    if (parent) {
      visual.left = node.sibling ? spaceLeft + columnOffset : spaceLeft + offset;
    }
    visual.width = hasFullWidth(node, nodes, overlapThreshold) ? FULL_WIDTH - visual.left : Math.min(FULL_WIDTH - visual.left, columnWidth * WIDTH_MULTIPLIER);
  }
}
function getColumnWidthMultiplier(node, nodes) {
  if (!node.children.length) {
    return 1;
  }
  const maxColumn = node.index + nodes.length;
  const minColumn = node.children.reduce((min, c) => Math.min(min, c.index), maxColumn);
  return minColumn - node.index;
}
function getOverlappingIndices(node, nodes) {
  const indices = [];
  for (const other of nodes) {
    if (hasOverlap(node.start, node.end, other.start, other.end)) {
      indices.push(other.index);
    }
  }
  return indices;
}
function getNextIndex(node, nodes) {
  const indices = getOverlappingIndices(node, nodes);
  indices.sort();
  for (let i = 0; i < indices.length; i++) {
    if (i < indices[i]) {
      return i;
    }
  }
  return false;
}
function getOverlappingRange(node, nodes, indexMin, indexMax, returnFirstColumn = false) {
  const overlapping = [];
  for (const other of nodes) {
    if (other.index >= indexMin && other.index <= indexMax && hasOverlap(node.start, node.end, other.start, other.end)) {
      overlapping.push(other);
    }
  }
  if (returnFirstColumn && overlapping.length > 0) {
    const first = overlapping.reduce((min, n) => Math.min(min, n.index), overlapping[0].index);
    return overlapping.filter(n => n.index === first);
  }
  return overlapping;
}
function getParent(node, nodes) {
  let parent = null;
  for (const other of nodes) {
    if (hasOverlap(node.start, node.end, other.start, other.end) && (parent === null || other.index > parent.index)) {
      parent = other;
    }
  }
  return parent;
}
function hasFullWidth(node, nodes, overlapThreshold) {
  for (const other of nodes) {
    if (other !== node && other.index > node.index && hasOverlap(node.start, addTime(node.start, overlapThreshold), other.start, other.end)) {
      return false;
    }
  }
  return true;
}
function getGroups(visuals, dayStart) {
  const groups = [];
  for (const visual of visuals) {
    const [start, end] = getNormalizedRange(visual.event, dayStart);
    let added = false;
    for (const group of groups) {
      if (hasOverlap(start, end, group.start, group.end)) {
        group.visuals.push(visual);
        group.end = Math.max(group.end, end);
        added = true;
        break;
      }
    }
    if (!added) {
      groups.push({
        start,
        end,
        visuals: [visual]
      });
    }
  }
  return groups;
}
function getNode(visual, dayStart) {
  const [start, end] = getNormalizedRange(visual.event, dayStart);
  return {
    parent: null,
    sibling: true,
    index: 0,
    visual,
    start,
    end,
    children: []
  };
}
function getMaxChildIndex(node) {
  let max = node.index;
  for (const child of node.children) {
    const childMax = getMaxChildIndex(child);
    if (childMax > max) {
      max = childMax;
    }
  }
  return max;
}
function addTime(identifier, minutes) {
  const removeMinutes = identifier % 100;
  const totalMinutes = removeMinutes + minutes;
  const addHours = Math.floor(totalMinutes / 60);
  const addMinutes = totalMinutes % 60;
  return identifier - removeMinutes + addHours * 100 + addMinutes;
}

// Types
const CalendarEventOverlapModes = {
  stack,
  column
};

// Types

function parseEvent(input, index, startProperty, endProperty, timed = false, category = false) {
  const startInput = input[startProperty];
  const endInput = input[endProperty];
  const startParsed = parseTimestamp(startInput, true);
  const endParsed = endInput ? parseTimestamp(endInput, true) : startParsed;
  const start = isTimedless(startInput) ? updateHasTime(startParsed, timed) : startParsed;
  const end = isTimedless(endInput) ? updateHasTime(endParsed, timed) : endParsed;
  const startIdentifier = getDayIdentifier(start);
  const startTimestampIdentifier = getTimestampIdentifier(start);
  const endIdentifier = getDayIdentifier(end);
  const endOffset = start.hasTime ? 0 : 2359;
  const endTimestampIdentifier = getTimestampIdentifier(end) + endOffset;
  const allDay = !start.hasTime;
  return {
    input,
    start,
    startIdentifier,
    startTimestampIdentifier,
    end,
    endIdentifier,
    endTimestampIdentifier,
    allDay,
    index,
    category
  };
}
function isEventOn(event, dayIdentifier) {
  return dayIdentifier >= event.startIdentifier && dayIdentifier <= event.endIdentifier;
}
function isEventOnDay(event, day, inRange) {
  if (inRange) {
    const dayStart = nextMinutes(copyTimestamp(day), inRange[0]);
    const dayEnd = nextMinutes(copyTimestamp(day), inRange[1]);
    const starts = event.startTimestampIdentifier < getTimestampIdentifier(dayEnd);
    const ends = event.endTimestampIdentifier > getTimestampIdentifier(dayStart);
    return starts && ends;
  }
  return isEventOn(event, getDayIdentifier(day));
}
function isEventHiddenOn(event, day) {
  return event.end.time === '00:00' && event.end.date === day.date && event.start.date !== day.date;
}
function isEventStart(event, day, dayIdentifier, firstWeekday) {
  return dayIdentifier === event.startIdentifier || firstWeekday === day.weekday && isEventOn(event, dayIdentifier);
}
function isEventOverlapping(event, startIdentifier, endIdentifier) {
  return startIdentifier <= event.endIdentifier && endIdentifier >= event.startIdentifier;
}

// Types

// Constants
const WIDTH_FULL = 100;
const WIDTH_START = 95;
const makeCalendarWithEventsProps = propsFactory({
  events: {
    type: Array,
    default: () => []
  },
  eventStart: {
    type: String,
    default: 'start'
  },
  eventEnd: {
    type: String,
    default: 'end'
  },
  eventTimed: {
    type: [String, Function],
    default: 'timed'
  },
  eventCategory: {
    type: [String, Function],
    default: 'category'
  },
  eventHeight: {
    type: Number,
    default: 20
  },
  eventColor: {
    type: [String, Function],
    default: 'primary'
  },
  eventTextColor: {
    type: [String, Function]
  },
  eventName: {
    type: [String, Function],
    default: 'name'
  },
  eventOverlapThreshold: {
    type: [String, Number],
    default: 60
  },
  eventOverlapMode: {
    type: [String, Function],
    default: 'stack',
    validate: mode => mode in CalendarEventOverlapModes || typeof mode === 'function'
  },
  eventMore: {
    type: Boolean,
    default: true
  },
  eventMoreText: {
    type: String,
    default: '$vuetify.calendar.moreEvents'
  },
  eventRipple: {
    type: [Boolean, Object],
    default: null
  },
  eventMarginBottom: {
    type: Number,
    default: 1
  }
}, 'VCalendar-events');
function useCalendarWithEvents(props, slots, attrs) {
  const base = useCalendarBase(props);
  const noEvents = computed(() => {
    return !Array.isArray(props.events) || props.events.length === 0;
  });
  const categoryMode = computed(() => {
    return props.type === 'category';
  });
  const eventTimedFunction = computed(() => {
    return typeof props.eventTimed === 'function' ? props.eventTimed : event => !!event[props.eventTimed];
  });
  const eventCategoryFunction = computed(() => {
    return typeof props.eventCategory === 'function' ? props.eventCategory : event => event[props.eventCategory];
  });
  const parsedEvents = computed(() => {
    if (!props.events) return [];
    return props.events.map((event, index) => parseEvent(event, index, props.eventStart || '', props.eventEnd || '', eventTimedFunction.value(event), categoryMode.value ? eventCategoryFunction.value(event) : false));
  });
  const parsedEventOverlapThreshold = computed(() => {
    return parseInt(String(props.eventOverlapThreshold || 0));
  });
  const eventTextColorFunction = computed(() => {
    return typeof props.eventTextColor === 'function' ? props.eventTextColor : () => props.eventTextColor;
  });
  const eventNameFunction = computed(() => {
    return typeof props.eventName === 'function' ? props.eventName : (event, timedEvent) => event.input[props.eventName] || '';
  });
  const eventModeFunction = computed(() => {
    return typeof props.eventOverlapMode === 'function' ? props.eventOverlapMode : CalendarEventOverlapModes[props.eventOverlapMode];
  });
  const eventWeekdays = computed(() => {
    return base.effectiveWeekdays.value;
  });
  function eventColorFunction(e) {
    return typeof props.eventColor === 'function' ? props.eventColor(e) : e.color || props.eventColor;
  }
  const eventsRef = ref([]);
  function updateEventVisibility() {
    if (noEvents.value || !props.eventMore) {
      return;
    }
    const eventHeight = props.eventHeight || 0;
    const eventsMap = getEventsMap();
    for (const date in eventsMap) {
      const {
        parent,
        events,
        more
      } = eventsMap[date];
      if (!more) {
        break;
      }
      const parentBounds = parent.getBoundingClientRect();
      const last = events.length - 1;
      const eventsSorted = events.map(event => ({
        event,
        bottom: event.getBoundingClientRect().bottom
      })).sort((a, b) => a.bottom - b.bottom);
      let hidden = 0;
      for (let i = 0; i <= last; i++) {
        const bottom = eventsSorted[i].bottom;
        const hide = i === last ? bottom > parentBounds.bottom : bottom + eventHeight > parentBounds.bottom;
        if (hide) {
          eventsSorted[i].event.style.display = 'none';
          hidden++;
        }
      }

      // TODO: avoid direct DOM manipulation
      if (hidden) {
        more.style.display = '';
        more.innerHTML = base.locale.t(props.eventMoreText, hidden);
      } else {
        more.style.display = 'none';
      }
    }
  }
  function getEventsMap() {
    const eventsMap = {};
    const elements = eventsRef.value;
    if (!elements || !elements.length) {
      return eventsMap;
    }
    elements.forEach(el => {
      const date = el.getAttribute('data-date');
      if (el.parentElement && date) {
        if (!(date in eventsMap)) {
          eventsMap[date] = {
            parent: el.parentElement,
            more: null,
            events: []
          };
        }
        if (el.getAttribute('data-more')) {
          eventsMap[date].more = el;
        } else {
          eventsMap[date].events.push(el);
          el.style.display = '';
        }
      }
    });
    return eventsMap;
  }
  function genDayEvent({
    event
  }, day) {
    const eventHeight = props.eventHeight || 0;
    const eventMarginBottom = props.eventMarginBottom || 0;
    const dayIdentifier = getDayIdentifier(day);
    const week = day.week;
    const start = dayIdentifier === event.startIdentifier;
    let end = dayIdentifier === event.endIdentifier;
    let width = WIDTH_START;
    if (!categoryMode.value) {
      for (let i = day.index + 1; i < week.length; i++) {
        const weekdayIdentifier = getDayIdentifier(week[i]);
        if (event.endIdentifier >= weekdayIdentifier) {
          width += WIDTH_FULL;
          end = end || weekdayIdentifier === event.endIdentifier;
        } else {
          end = true;
          break;
        }
      }
    }
    const scope = {
      eventParsed: event,
      day,
      start,
      end,
      timed: false
    };
    return genEvent(event, scope, false, {
      class: ['v-event', {
        'v-event-start': start,
        'v-event-end': end
      }],
      style: {
        height: `${eventHeight}px`,
        width: `${width}%`,
        marginBottom: `${eventMarginBottom}px`
      },
      'data-date': day.date
    });
  }
  function genTimedEvent({
    event,
    left,
    width
  }, day) {
    const startDelta = day.timeDelta(event.start, day);
    const endDelta = day.timeDelta(event.end, day);
    if (endDelta === false || startDelta === false || endDelta < 0 || startDelta >= 1 || isEventHiddenOn(event, day)) {
      return false;
    }
    const dayIdentifier = getDayIdentifier(day);
    const start = event.startIdentifier >= dayIdentifier;
    const end = event.endIdentifier > dayIdentifier;
    const top = day.timeToY(event.start, day);
    const bottom = day.timeToY(event.end, day);
    const height = Math.max(props.eventHeight || 0, bottom - top);
    const scope = {
      eventParsed: event,
      day,
      start,
      end,
      timed: true
    };
    return genEvent(event, scope, true, {
      class: 'v-event-timed',
      style: {
        top: `${top}px`,
        height: `${height}px`,
        left: `${left}%`,
        width: `${width}%`
      }
    });
  }
  function genEvent(event, scopeInput, timedEvent, data) {
    const slot = slots.event;
    const text = eventTextColorFunction.value(event.input);
    const background = eventColorFunction(event.input);
    const overlapsNoon = event.start.hour < 12 && event.end.hour >= 12;
    const singline = diffMinutes(event.start, event.end) <= parsedEventOverlapThreshold.value;
    const formatTime = (withTime, ampm) => {
      const hour12 = props.format === 'ampm' ? true : props.format === '24hr' ? false : undefined;
      const formatter = base.getFormatter({
        timeZone: 'UTC',
        hour: props.format === '24hr' ? '2-digit' : 'numeric',
        minute: withTime.minute > 0 ? 'numeric' : undefined,
        hour12
      });
      return formatter(withTime, true);
    };
    const timeSummary = () => formatTime(event.start) + ' - ' + formatTime(event.end);
    const eventSummary = () => {
      const name = eventNameFunction.value(event, timedEvent);
      if (event.start.hasTime) {
        if (timedEvent) {
          const time = timeSummary();
          const delimiter = singline ? ', ' : createElementVNode("br", null, null);
          return createElementVNode("span", {
            "class": "v-event-summary"
          }, [createElementVNode("strong", null, [name]), delimiter, time]);
        } else {
          const time = formatTime(event.start);
          return createElementVNode("span", {
            "class": "v-event-summary"
          }, [createElementVNode("strong", null, [time]), createTextVNode(" "), name]);
        }
      }
      return createElementVNode("span", {
        "class": "v-event-summary"
      }, [name]);
    };
    const scope = {
      ...scopeInput,
      event: event.input,
      outside: scopeInput.day.outside,
      singline,
      overlapsNoon,
      formatTime,
      timeSummary,
      eventSummary
    };
    const events = getPrefixedEventHandlers(attrs, ':event', nativeEvent => ({
      ...scope,
      nativeEvent
    }));
    return withDirectives(createElementVNode("div", mergeProps(base.getColorProps({
      text,
      background
    }), events, data, {
      "ref_for": true,
      "ref": eventsRef
    }), [slot?.(scope) ?? genName(eventSummary)]), [[Ripple, props.eventRipple ?? true]]);
  }
  function genName(eventSummary) {
    return createElementVNode("div", {
      "class": "pl-1"
    }, [eventSummary()]);
  }
  function genPlaceholder(day) {
    const height = (props.eventHeight || 0) + (props.eventMarginBottom || 0);
    return createElementVNode("div", {
      "style": {
        height: `${height}px`
      },
      "data-date": day.date,
      "ref_for": true,
      "ref": eventsRef
    }, null);
  }
  function genMore(day) {
    const eventHeight = props.eventHeight || 0;
    const eventMarginBottom = props.eventMarginBottom || 0;
    const events = getPrefixedEventHandlers(attrs, ':more', nativeEvent => ({
      nativeEvent,
      ...day
    }));
    return withDirectives(createElementVNode("div", mergeProps({
      "class": ['v-event-more pl-1', {
        'v-outside': day.outside
      }],
      "data-date": day.date,
      "data-more": "1",
      "style": {
        display: 'none',
        height: `${eventHeight}px`,
        marginBottom: `${eventMarginBottom}px`
      },
      "ref_for": true,
      "ref": eventsRef
    }, events), null), [[Ripple, props.eventRipple ?? true]]);
  }
  function getVisibleEvents() {
    const days = base.days.value;
    const start = getDayIdentifier(days[0]);
    const end = getDayIdentifier(days[days.length - 1]);
    return parsedEvents.value.filter(event => isEventOverlapping(event, start, end));
  }
  function isEventForCategory(event, category) {
    return !categoryMode.value || typeof category === 'object' && category.categoryName && category.categoryName === event.category || typeof event.category === 'string' && category === event.category || typeof event.category !== 'string' && category === null;
  }
  function getEventsForDay(day) {
    const identifier = getDayIdentifier(day);
    const firstWeekday = eventWeekdays.value[0];
    return parsedEvents.value.filter(event => isEventStart(event, day, identifier, firstWeekday));
  }
  function getEventsForDayAll(day) {
    const identifier = getDayIdentifier(day);
    const firstWeekday = eventWeekdays.value[0];
    return parsedEvents.value.filter(event => event.allDay && (categoryMode.value ? isEventOn(event, identifier) : isEventStart(event, day, identifier, firstWeekday)) && isEventForCategory(event, day.category));
  }
  function getEventsForDayTimed(day) {
    return parsedEvents.value.filter(event => !event.allDay && isEventOnDay(event, day, day.intervalRange) && isEventForCategory(event, day.category));
  }
  function getScopedSlots() {
    if (noEvents.value) {
      return {
        ...slots
      };
    }
    const mode = eventModeFunction.value(parsedEvents.value, eventWeekdays.value[0], parsedEventOverlapThreshold.value);
    const isNode = input => !!input;
    const getSlotChildren = (day, getter, mapper, timed) => {
      const events = getter(day);
      const visuals = mode(day, events, timed, categoryMode.value);
      if (timed) {
        return visuals.map(visual => mapper(visual, day)).filter(isNode);
      }
      const children = [];
      visuals.forEach((visual, index) => {
        while (children.length < visual.column) {
          children.push(genPlaceholder(day));
        }
        const mapped = mapper(visual, day);
        if (mapped) {
          children.push(mapped);
        }
      });
      return children;
    };
    return {
      ...slots,
      day: day => {
        let children = getSlotChildren(day, getEventsForDay, genDayEvent, false);
        if (children && children.length > 0 && props.eventMore) {
          children.push(genMore(day));
        }
        if (slots.day) {
          const slot = slots.day(day);
          if (slot) {
            children = children ? children.concat(slot) : slot;
          }
        }
        return children;
      },
      'day-header': day => {
        let children = getSlotChildren(day, getEventsForDayAll, genDayEvent, false);
        if (slots['day-header']) {
          const slot = slots['day-header'](day);
          if (slot) {
            children = children ? children.concat(slot) : slot;
          }
        }
        return children;
      },
      'day-body': day => {
        const events = getSlotChildren(day, getEventsForDayTimed, genTimedEvent, true);
        let children = [createElementVNode("div", {
          "class": "v-event-timed-container"
        }, [events])];
        if (slots['day-body']) {
          const slot = slots['day-body'](day);
          if (slot) {
            children = children.concat(slot);
          }
        }
        return children;
      }
    };
  }
  return {
    ...base,
    noEvents,
    parsedEvents,
    parsedEventOverlapThreshold,
    eventTimedFunction,
    eventCategoryFunction,
    eventTextColorFunction,
    eventNameFunction,
    eventModeFunction,
    eventWeekdays,
    categoryMode,
    eventColorFunction,
    eventsRef,
    updateEventVisibility,
    getEventsMap,
    genDayEvent,
    genTimedEvent,
    genEvent,
    genName,
    genPlaceholder,
    genMore,
    getVisibleEvents,
    isEventForCategory,
    getEventsForDay,
    getEventsForDayAll,
    getEventsForDayTimed,
    getScopedSlots
  };
}

// Types

// Types

const VCalendar = genericComponent()({
  name: 'VCalendar',
  directives: {
    vResize: Resize
  },
  props: {
    modelValue: {
      type: [String, Number, Date],
      validate: validateTimestamp
    },
    categoryDays: {
      type: [Number, String],
      default: 1,
      validate: x => isFinite(parseInt(x)) && parseInt(x) > 0
    },
    categories: {
      type: [Array, String],
      default: ''
    },
    categoryText: {
      type: [String, Function]
    },
    categoryHideDynamic: {
      type: Boolean
    },
    categoryShowAll: {
      type: Boolean
    },
    categoryForInvalid: {
      type: String,
      default: ''
    },
    ...makeIntervalHighlightProps(),
    ...makeCalendarBaseProps(),
    ...makeCalendarWithEventsProps(),
    ...makeCalendarWithIntervalsProps()
  },
  setup(props, {
    slots,
    attrs,
    emit
  }) {
    const root = ref();
    const base = useCalendarWithEvents(props, slots, attrs);
    const lastStart = ref(null);
    const lastEnd = ref(null);
    const parsedCategoryDays = computed(() => {
      return parseInt(String(props.categoryDays)) || 1;
    });
    const parsedCategories = computed(() => {
      return getParsedCategories(props.categories, props.categoryText);
    });
    const renderProps = computed(() => {
      const around = base.parsedValue.value;
      let component = null;
      let maxDays = props.maxDays;
      let categories = parsedCategories.value;
      let start = around;
      let end = around;
      switch (props.type) {
        case 'month':
          component = VCalendarWeekly;
          start = getStartOfMonth(around);
          end = getEndOfMonth(around);
          break;
        case 'week':
          component = VCalendarDaily;
          start = base.getStartOfWeek(around);
          end = base.getEndOfWeek(around);
          maxDays = 7;
          break;
        case 'day':
          component = VCalendarDaily;
          maxDays = 1;
          break;
        case '4day':
          component = VCalendarDaily;
          end = relativeDays(copyTimestamp(end), nextDay, 3);
          updateFormatted(end);
          maxDays = 4;
          break;
        case 'custom-weekly':
          component = VCalendarWeekly;
          start = base.parsedStart.value || around;
          end = base.parsedEnd.value;
          break;
        case 'custom-daily':
          component = VCalendarDaily;
          start = base.parsedStart.value || around;
          end = base.parsedEnd.value;
          break;
        case 'category':
          const days = parsedCategoryDays.value;
          component = VCalendarCategory;
          end = relativeDays(copyTimestamp(end), nextDay, days);
          updateFormatted(end);
          maxDays = days;
          categories = getCategoryList(categories);
          break;
        default:
          const type = props.type;
          throw new Error(`${type} is not a valid Calendar type`);
      }
      return {
        component,
        start,
        end,
        maxDays,
        categories
      };
    });
    const eventWeekdays = computed(() => {
      return base.effectiveWeekdays.value;
    });
    const categoryMode = computed(() => {
      return props.type === 'category';
    });
    const monthLongFormatter = computed(() => {
      return base.getFormatter({
        timeZone: 'UTC',
        month: 'long'
      });
    });
    const monthShortFormatter = computed(() => {
      return base.getFormatter({
        timeZone: 'UTC',
        month: 'short'
      });
    });
    const title = computed(() => {
      const {
        start,
        end
      } = renderProps.value;
      const spanYears = start.year !== end.year;
      const spanMonths = spanYears || start.month !== end.month;
      if (spanYears) {
        return monthShortFormatter.value(start, true) + ' ' + start.year + ' - ' + monthShortFormatter.value(end, true) + ' ' + end.year;
      }
      if (spanMonths) {
        return monthShortFormatter.value(start, true) + ' - ' + monthShortFormatter.value(end, true) + ' ' + end.year;
      } else {
        return monthLongFormatter.value(start, false) + ' ' + start.year;
      }
    });
    function checkChange() {
      const {
        start,
        end
      } = renderProps.value;
      if (!lastStart.value || !lastEnd.value || start.date !== lastStart.value.date || end.date !== lastEnd.value.date) {
        lastStart.value = start;
        lastEnd.value = end;
        emit('change', {
          start,
          end
        });
      }
    }
    function move(amount = 1) {
      const moved = copyTimestamp(base.parsedValue.value);
      const forward = amount > 0;
      const mover = forward ? nextDay : prevDay;
      const limit = forward ? DAYS_IN_MONTH_MAX : DAY_MIN;
      let times = forward ? amount : -amount;
      while (--times >= 0) {
        switch (props.type) {
          case 'month':
            moved.day = limit;
            mover(moved);
            break;
          case 'week':
            relativeDays(moved, mover, DAYS_IN_WEEK);
            break;
          case 'day':
            relativeDays(moved, mover, 1);
            break;
          case '4day':
            relativeDays(moved, mover, 4);
            break;
          case 'category':
            relativeDays(moved, mover, parsedCategoryDays.value);
            break;
        }
      }
      updateWeekday(moved);
      updateFormatted(moved);
      updateRelative(moved, base.times.now);
      if (props.modelValue instanceof Date) {
        emit('update:modelValue', timestampToDate(moved));
      } else if (typeof props.modelValue === 'number') {
        emit('update:modelValue', timestampToDate(moved).getTime());
      } else {
        emit('update:modelValue', moved.date);
      }
      emit('moved', moved);
    }
    function next(amount = 1) {
      move(amount);
    }
    function prev(amount = 1) {
      move(-amount);
    }
    function getCategoryList(categories) {
      if (!base.noEvents.value) {
        const categoryMap = categories.reduce((map, category, index) => {
          if (typeof category === 'object' && category.categoryName) map[category.categoryName] = {
            index,
            count: 0
          };else if (typeof category === 'string') map[category] = {
            index,
            count: 0
          };
          return map;
        }, {});
        if (!props.categoryHideDynamic || !props.categoryShowAll) {
          let categoryLength = categories.length;
          base.parsedEvents.value.forEach(ev => {
            let category = ev.category;
            if (typeof category !== 'string') {
              category = props.categoryForInvalid;
            }
            if (!category) {
              return;
            }
            if (category in categoryMap) {
              categoryMap[category].count++;
            } else if (!props.categoryHideDynamic) {
              categoryMap[category] = {
                index: categoryLength++,
                count: 1
              };
            }
          });
        }
        if (!props.categoryShowAll) {
          for (const category in categoryMap) {
            if (categoryMap[category].count === 0) {
              delete categoryMap[category];
            }
          }
        }
        categories = categories.filter(category => {
          if (typeof category === 'object' && category.categoryName) {
            return categoryMap.hasOwnProperty(category.categoryName);
          } else if (typeof category === 'string') {
            return categoryMap.hasOwnProperty(category);
          }
          return false;
        });
      }
      return categories;
    }
    watch(renderProps, checkChange);
    onMounted(() => {
      base.updateEventVisibility();
      checkChange();
    });
    onUpdated(() => {
      window.requestAnimationFrame(base.updateEventVisibility);
    });
    useRender(() => {
      const {
        start,
        end,
        maxDays,
        component: Component,
        categories
      } = renderProps.value;
      return withDirectives(createVNode(Component, mergeProps({
        "ref": root,
        "class": ['v-calendar', {
          'v-calendar-events': !base.noEvents.value
        }],
        "role": "grid"
      }, Component.filterProps(props), {
        "start": start.date,
        "end": end.date,
        "maxDays": maxDays,
        "weekdays": base.effectiveWeekdays.value,
        "categories": categories,
        "onClick:date": (e, day) => {
          if (attrs['onUpdate:modelValue']) emit('update:modelValue', day.date);
        }
      }), base.getScopedSlots()), [[Resize, base.updateEventVisibility, void 0, {
        quiet: true
      }]]);
    });
    return forwardRefs({
      ...base,
      lastStart,
      lastEnd,
      parsedCategoryDays,
      renderProps,
      eventWeekdays,
      categoryMode,
      title,
      monthLongFormatter,
      monthShortFormatter,
      parsedCategories,
      checkChange,
      move,
      next,
      prev,
      getCategoryList
    }, root);
  }
});

const makeVCardActionsProps = propsFactory({
  ...makeComponentProps(),
  ...makeTagProps()
}, 'VCardActions');
const VCardActions = genericComponent()({
  name: 'VCardActions',
  props: makeVCardActionsProps(),
  setup(props, {
    slots
  }) {
    provideDefaults({
      VBtn: {
        slim: true,
        variant: 'text'
      }
    });
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-card-actions', props.class]),
      "style": normalizeStyle(props.style)
    }, slots));
    return {};
  }
});

const makeVCardSubtitleProps = propsFactory({
  opacity: [Number, String],
  ...makeComponentProps(),
  ...makeTagProps()
}, 'VCardSubtitle');
const VCardSubtitle = genericComponent()({
  name: 'VCardSubtitle',
  props: makeVCardSubtitleProps(),
  setup(props, {
    slots
  }) {
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-card-subtitle', props.class]),
      "style": normalizeStyle([{
        '--v-card-subtitle-opacity': props.opacity
      }, props.style])
    }, slots));
    return {};
  }
});

// Utilities
const VCardTitle = createSimpleFunctional('v-card-title');

const makeCardItemProps = propsFactory({
  appendAvatar: String,
  appendIcon: IconValue,
  prependAvatar: String,
  prependIcon: IconValue,
  subtitle: {
    type: [String, Number, Boolean],
    default: undefined
  },
  title: {
    type: [String, Number, Boolean],
    default: undefined
  },
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeTagProps()
}, 'VCardItem');
const VCardItem = genericComponent()({
  name: 'VCardItem',
  props: makeCardItemProps(),
  setup(props, {
    slots
  }) {
    useRender(() => {
      const hasPrependMedia = !!(props.prependAvatar || props.prependIcon);
      const hasPrepend = !!(hasPrependMedia || slots.prepend);
      const hasAppendMedia = !!(props.appendAvatar || props.appendIcon);
      const hasAppend = !!(hasAppendMedia || slots.append);
      const hasTitle = !!(props.title != null || slots.title);
      const hasSubtitle = !!(props.subtitle != null || slots.subtitle);
      return createVNode(props.tag, {
        "class": normalizeClass(['v-card-item', props.class]),
        "style": normalizeStyle(props.style)
      }, {
        default: () => [hasPrepend && createElementVNode("div", {
          "key": "prepend",
          "class": "v-card-item__prepend"
        }, [!slots.prepend ? createElementVNode(Fragment, null, [props.prependAvatar && createVNode(VAvatar, {
          "key": "prepend-avatar",
          "density": props.density,
          "image": props.prependAvatar
        }, null), props.prependIcon && createVNode(VIcon, {
          "key": "prepend-icon",
          "density": props.density,
          "icon": props.prependIcon
        }, null)]) : createVNode(VDefaultsProvider, {
          "key": "prepend-defaults",
          "disabled": !hasPrependMedia,
          "defaults": {
            VAvatar: {
              density: props.density,
              image: props.prependAvatar
            },
            VIcon: {
              density: props.density,
              icon: props.prependIcon
            }
          }
        }, slots.prepend)]), createElementVNode("div", {
          "class": "v-card-item__content"
        }, [hasTitle && createVNode(VCardTitle, {
          "key": "title"
        }, {
          default: () => [slots.title?.() ?? toDisplayString(props.title)]
        }), hasSubtitle && createVNode(VCardSubtitle, {
          "key": "subtitle"
        }, {
          default: () => [slots.subtitle?.() ?? toDisplayString(props.subtitle)]
        }), slots.default?.()]), hasAppend && createElementVNode("div", {
          "key": "append",
          "class": "v-card-item__append"
        }, [!slots.append ? createElementVNode(Fragment, null, [props.appendIcon && createVNode(VIcon, {
          "key": "append-icon",
          "density": props.density,
          "icon": props.appendIcon
        }, null), props.appendAvatar && createVNode(VAvatar, {
          "key": "append-avatar",
          "density": props.density,
          "image": props.appendAvatar
        }, null)]) : createVNode(VDefaultsProvider, {
          "key": "append-defaults",
          "disabled": !hasAppendMedia,
          "defaults": {
            VAvatar: {
              density: props.density,
              image: props.appendAvatar
            },
            VIcon: {
              density: props.density,
              icon: props.appendIcon
            }
          }
        }, slots.append)])]
      });
    });
    return {};
  }
});

const makeVCardTextProps = propsFactory({
  opacity: [Number, String],
  ...makeComponentProps(),
  ...makeTagProps()
}, 'VCardText');
const VCardText = genericComponent()({
  name: 'VCardText',
  props: makeVCardTextProps(),
  setup(props, {
    slots
  }) {
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-card-text', props.class]),
      "style": normalizeStyle([{
        '--v-card-text-opacity': props.opacity
      }, props.style])
    }, slots));
    return {};
  }
});

// Types

const makeVCardProps = propsFactory({
  appendAvatar: String,
  appendIcon: IconValue,
  disabled: Boolean,
  flat: Boolean,
  hover: Boolean,
  image: String,
  link: {
    type: Boolean,
    default: undefined
  },
  prependAvatar: String,
  prependIcon: IconValue,
  ripple: {
    type: [Boolean, Object],
    default: true
  },
  subtitle: {
    type: [String, Number, Boolean],
    default: undefined
  },
  text: {
    type: [String, Number, Boolean],
    default: undefined
  },
  title: {
    type: [String, Number, Boolean],
    default: undefined
  },
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeDimensionProps(),
  ...makeElevationProps(),
  ...makeLoaderProps(),
  ...makeLocationProps(),
  ...makePositionProps(),
  ...makeRoundedProps(),
  ...makeRouterProps(),
  ...makeTagProps(),
  ...makeThemeProps(),
  ...makeVariantProps({
    variant: 'elevated'
  })
}, 'VCard');
const VCard = genericComponent()({
  name: 'VCard',
  directives: {
    vRipple: Ripple
  },
  props: makeVCardProps(),
  setup(props, {
    attrs,
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      borderClasses
    } = useBorder(props);
    const {
      colorClasses,
      colorStyles,
      variantClasses
    } = useVariant(props);
    const {
      densityClasses
    } = useDensity(props);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      loaderClasses
    } = useLoader(props);
    const {
      locationStyles
    } = useLocation(props);
    const {
      positionClasses
    } = usePosition(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const link = useLink(props, attrs);
    const loadingColor = shallowRef(undefined);
    watch(() => props.loading, (val, old) => {
      loadingColor.value = !val && typeof old === 'string' ? old : typeof val === 'boolean' ? undefined : val;
    }, {
      immediate: true
    });
    useRender(() => {
      const isLink = props.link !== false && link.isLink.value;
      const isClickable = !props.disabled && props.link !== false && (props.link || link.isClickable.value);
      const Tag = isLink ? 'a' : props.tag;
      const hasTitle = !!(slots.title || props.title != null);
      const hasSubtitle = !!(slots.subtitle || props.subtitle != null);
      const hasHeader = hasTitle || hasSubtitle;
      const hasAppend = !!(slots.append || props.appendAvatar || props.appendIcon);
      const hasPrepend = !!(slots.prepend || props.prependAvatar || props.prependIcon);
      const hasImage = !!(slots.image || props.image);
      const hasCardItem = hasHeader || hasPrepend || hasAppend;
      const hasText = !!(slots.text || props.text != null);
      return withDirectives(createVNode(Tag, mergeProps(link.linkProps, {
        "class": ['v-card', {
          'v-card--disabled': props.disabled,
          'v-card--flat': props.flat,
          'v-card--hover': props.hover && !(props.disabled || props.flat),
          'v-card--link': isClickable
        }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, loaderClasses.value, positionClasses.value, roundedClasses.value, variantClasses.value, props.class],
        "style": [colorStyles.value, dimensionStyles.value, locationStyles.value, {
          '--v-card-height': convertToUnit(props.height)
        }, roundedStyles.value, props.style],
        "onClick": isClickable && link.navigate.value,
        "tabindex": props.disabled ? -1 : undefined
      }), {
        default: () => [hasImage && createElementVNode("div", {
          "key": "image",
          "class": "v-card__image"
        }, [!slots.image ? createVNode(VImg, {
          "key": "image-img",
          "cover": true,
          "src": props.image
        }, null) : createVNode(VDefaultsProvider, {
          "key": "image-defaults",
          "disabled": !props.image,
          "defaults": {
            VImg: {
              cover: true,
              src: props.image
            }
          }
        }, slots.image)]), createVNode(LoaderSlot, {
          "name": "v-card",
          "active": !!props.loading,
          "color": loadingColor.value
        }, {
          default: slots.loader
        }), hasCardItem && createVNode(VCardItem, {
          "key": "item",
          "prependAvatar": props.prependAvatar,
          "prependIcon": props.prependIcon,
          "title": props.title,
          "subtitle": props.subtitle,
          "appendAvatar": props.appendAvatar,
          "appendIcon": props.appendIcon
        }, {
          default: slots.item,
          prepend: slots.prepend,
          title: slots.title,
          subtitle: slots.subtitle,
          append: slots.append
        }), hasText && createVNode(VCardText, {
          "key": "text"
        }, {
          default: () => [slots.text?.() ?? props.text]
        }), slots.default?.(), slots.actions && createVNode(VCardActions, null, {
          default: slots.actions
        }), genOverlays(isClickable, 'v-card')]
      }), [[Ripple, isClickable && props.ripple]]);
    });
    return {};
  }
});

// Utilities

// Types

const handleGesture = wrapper => {
  const {
    touchstartX,
    touchendX,
    touchstartY,
    touchendY
  } = wrapper;
  const dirRatio = 0.5;
  const minDistance = 16;
  wrapper.offsetX = touchendX - touchstartX;
  wrapper.offsetY = touchendY - touchstartY;
  if (Math.abs(wrapper.offsetY) < dirRatio * Math.abs(wrapper.offsetX)) {
    wrapper.left && touchendX < touchstartX - minDistance && wrapper.left(wrapper);
    wrapper.right && touchendX > touchstartX + minDistance && wrapper.right(wrapper);
  }
  if (Math.abs(wrapper.offsetX) < dirRatio * Math.abs(wrapper.offsetY)) {
    wrapper.up && touchendY < touchstartY - minDistance && wrapper.up(wrapper);
    wrapper.down && touchendY > touchstartY + minDistance && wrapper.down(wrapper);
  }
};
function touchstart(event, wrapper) {
  const touch = event.changedTouches[0];
  wrapper.touchstartX = touch.clientX;
  wrapper.touchstartY = touch.clientY;
  wrapper.start?.({
    originalEvent: event,
    ...wrapper
  });
}
function touchend(event, wrapper) {
  const touch = event.changedTouches[0];
  wrapper.touchendX = touch.clientX;
  wrapper.touchendY = touch.clientY;
  wrapper.end?.({
    originalEvent: event,
    ...wrapper
  });
  handleGesture(wrapper);
}
function touchmove(event, wrapper) {
  const touch = event.changedTouches[0];
  wrapper.touchmoveX = touch.clientX;
  wrapper.touchmoveY = touch.clientY;
  wrapper.move?.({
    originalEvent: event,
    ...wrapper
  });
}
function createHandlers(value = {}) {
  const wrapper = {
    touchstartX: 0,
    touchstartY: 0,
    touchendX: 0,
    touchendY: 0,
    touchmoveX: 0,
    touchmoveY: 0,
    offsetX: 0,
    offsetY: 0,
    left: value.left,
    right: value.right,
    up: value.up,
    down: value.down,
    start: value.start,
    move: value.move,
    end: value.end
  };
  return {
    touchstart: e => touchstart(e, wrapper),
    touchend: e => touchend(e, wrapper),
    touchmove: e => touchmove(e, wrapper)
  };
}
function mounted$2(el, binding) {
  const value = binding.value;
  const target = value?.parent ? el.parentElement : el;
  const options = value?.options ?? {
    passive: true
  };
  const uid = binding.instance?.$.uid; // TODO: use custom uid generator

  if (!target || uid === undefined) return;
  const handlers = createHandlers(binding.value);
  target._touchHandlers = target._touchHandlers ?? Object.create(null);
  target._touchHandlers[uid] = handlers;
  keys(handlers).forEach(eventName => {
    target.addEventListener(eventName, handlers[eventName], options);
  });
}
function unmounted$2(el, binding) {
  const target = binding.value?.parent ? el.parentElement : el;
  const uid = binding.instance?.$.uid;
  if (!target?._touchHandlers || uid === undefined) return;
  const handlers = target._touchHandlers[uid];

  // guard against double teardown: e.g. router & suspence racing
  if (!handlers) return;
  keys(handlers).forEach(eventName => {
    target.removeEventListener(eventName, handlers[eventName]);
  });
  delete target._touchHandlers[uid];
  if (!keys(target._touchHandlers).length) {
    // only relevant if we keep `parent: boolean`
    delete target._touchHandlers;
  }
}
const Touch = {
  mounted: mounted$2,
  unmounted: unmounted$2
};

// Types

const VWindowSymbol = Symbol.for('vuetify:v-window');
const VWindowGroupSymbol = Symbol.for('vuetify:v-window-group');
const makeVWindowProps = propsFactory({
  continuous: Boolean,
  nextIcon: {
    type: [Boolean, String, Function, Object],
    default: '$next'
  },
  prevIcon: {
    type: [Boolean, String, Function, Object],
    default: '$prev'
  },
  reverse: Boolean,
  showArrows: {
    type: [Boolean, String],
    validator: v => typeof v === 'boolean' || v === 'hover'
  },
  verticalArrows: [Boolean, String],
  touch: {
    type: [Object, Boolean],
    default: undefined
  },
  direction: {
    type: String,
    default: 'horizontal'
  },
  modelValue: null,
  disabled: Boolean,
  selectedClass: {
    type: String,
    default: 'v-window-item--active'
  },
  // TODO: mandatory should probably not be exposed but do this for now
  mandatory: {
    type: [Boolean, String],
    default: 'force'
  },
  crossfade: Boolean,
  transitionDuration: Number,
  ...makeComponentProps(),
  ...makeTagProps(),
  ...makeThemeProps()
}, 'VWindow');
const VWindow = genericComponent()({
  name: 'VWindow',
  directives: {
    vTouch: Touch
  },
  props: makeVWindowProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      isRtl
    } = useRtl();
    const {
      t
    } = useLocale();
    const group = useGroup(props, VWindowGroupSymbol);
    const rootRef = ref();
    const isRtlReverse = computed(() => isRtl.value ? !props.reverse : props.reverse);
    const isReversed = shallowRef(false);
    const transition = computed(() => {
      if (props.crossfade) {
        return 'v-window-crossfade-transition';
      }
      const axis = props.direction === 'vertical' ? 'y' : 'x';
      const reverse = isRtlReverse.value ? !isReversed.value : isReversed.value;
      const direction = reverse ? '-reverse' : '';
      return `v-window-${axis}${direction}-transition`;
    });
    const transitionCount = shallowRef(0);
    const transitionHeight = ref(undefined);
    const activeIndex = computed(() => {
      return group.items.value.findIndex(item => group.selected.value.includes(item.id));
    });

    // Fix for https://github.com/vuetifyjs/vuetify/issues/18447
    watch(activeIndex, (newVal, oldVal) => {
      let scrollableParent;
      const savedScrollPosition = {
        left: 0,
        top: 0
      };
      if (IN_BROWSER && oldVal >= 0) {
        scrollableParent = getScrollParent(rootRef.value);
        savedScrollPosition.left = scrollableParent?.scrollLeft;
        savedScrollPosition.top = scrollableParent?.scrollTop;
      }
      const itemsLength = group.items.value.length;
      const lastIndex = itemsLength - 1;
      if (itemsLength <= 2) {
        isReversed.value = newVal < oldVal;
      } else if (newVal === lastIndex && oldVal === 0) {
        isReversed.value = false;
      } else if (newVal === 0 && oldVal === lastIndex) {
        isReversed.value = true;
      } else {
        isReversed.value = newVal < oldVal;
      }
      nextTick(() => {
        if (!IN_BROWSER || !scrollableParent) return;
        const currentScrollY = scrollableParent.scrollTop;
        if (currentScrollY !== savedScrollPosition.top) {
          scrollableParent.scrollTo({
            ...savedScrollPosition,
            behavior: 'instant'
          });
        }
        requestAnimationFrame(() => {
          if (!scrollableParent) return;
          const rafScrollY = scrollableParent.scrollTop;
          if (rafScrollY !== savedScrollPosition.top) {
            scrollableParent.scrollTo({
              ...savedScrollPosition,
              behavior: 'instant'
            });
          }
        });
      });
    }, {
      flush: 'sync'
    }); // Run synchronously before DOM updates

    provide(VWindowSymbol, {
      transition,
      isReversed,
      transitionCount,
      transitionHeight,
      rootRef
    });
    const canMoveBack = toRef(() => props.continuous || activeIndex.value !== 0);
    const canMoveForward = toRef(() => props.continuous || activeIndex.value !== group.items.value.length - 1);
    function prev() {
      canMoveBack.value && group.prev();
    }
    function next() {
      canMoveForward.value && group.next();
    }
    const arrows = computed(() => {
      const arrows = [];
      const prevProps = {
        icon: isRtl.value ? props.nextIcon : props.prevIcon,
        class: `v-window__${isRtlReverse.value ? 'right' : 'left'}`,
        onClick: group.prev,
        'aria-label': t('$vuetify.carousel.prev')
      };
      arrows.push(canMoveBack.value ? slots.prev ? slots.prev({
        props: prevProps
      }) : createVNode(VBtn, prevProps, null) : createElementVNode("div", null, null));
      const nextProps = {
        icon: isRtl.value ? props.prevIcon : props.nextIcon,
        class: `v-window__${isRtlReverse.value ? 'left' : 'right'}`,
        onClick: group.next,
        'aria-label': t('$vuetify.carousel.next')
      };
      arrows.push(canMoveForward.value ? slots.next ? slots.next({
        props: nextProps
      }) : createVNode(VBtn, nextProps, null) : createElementVNode("div", null, null));
      return arrows;
    });
    const touchOptions = computed(() => {
      if (props.touch === false) return props.touch;
      const options = {
        left: () => {
          isRtlReverse.value ? prev() : next();
        },
        right: () => {
          isRtlReverse.value ? next() : prev();
        },
        start: ({
          originalEvent
        }) => {
          originalEvent.stopPropagation();
        }
      };
      return {
        ...options,
        ...(props.touch === true ? {} : props.touch)
      };
    });
    function onKeyDown(e) {
      if (props.direction === 'horizontal' && e.key === 'ArrowLeft' || props.direction === 'vertical' && e.key === 'ArrowUp') {
        e.preventDefault();
        prev();
        nextTick(() => {
          canMoveBack.value ? focusArrow(0) : focusArrow(1);
        });
      }
      if (props.direction === 'horizontal' && e.key === 'ArrowRight' || props.direction === 'vertical' && e.key === 'ArrowDown') {
        e.preventDefault();
        next();
        nextTick(() => {
          canMoveForward.value ? focusArrow(1) : focusArrow(0);
        });
      }
    }
    function focusArrow(index) {
      const arrow = arrows.value[index];
      if (!arrow) return;
      const arrowEl = Array.isArray(arrow) ? arrow[0] : arrow;
      arrowEl.el?.focus();
    }
    useRender(() => withDirectives(createVNode(props.tag, {
      "ref": rootRef,
      "class": normalizeClass(['v-window', {
        'v-window--show-arrows-on-hover': props.showArrows === 'hover',
        'v-window--vertical-arrows': !!props.verticalArrows,
        'v-window--crossfade': !!props.crossfade
      }, themeClasses.value, props.class]),
      "style": normalizeStyle([props.style, {
        '--v-window-transition-duration': !PREFERS_REDUCED_MOTION() ? convertToUnit(props.transitionDuration, 'ms') : null
      }])
    }, {
      default: () => [createElementVNode("div", {
        "class": "v-window__container",
        "style": {
          height: transitionHeight.value
        }
      }, [slots.default?.({
        group
      }), props.showArrows !== false && createElementVNode("div", {
        "class": normalizeClass(['v-window__controls', {
          'v-window__controls--left': props.verticalArrows === 'left' || props.verticalArrows === true
        }, {
          'v-window__controls--right': props.verticalArrows === 'right'
        }]),
        "onKeydown": onKeyDown
      }, [arrows.value])]), slots.additional?.({
        group
      })]
    }), [[Touch, touchOptions.value]]));
    return {
      group
    };
  }
});

// Types

const makeVCarouselProps = propsFactory({
  color: String,
  cycle: Boolean,
  delimiterIcon: {
    type: IconValue,
    default: '$delimiter'
  },
  height: {
    type: [Number, String],
    default: 500
  },
  hideDelimiters: Boolean,
  hideDelimiterBackground: Boolean,
  interval: {
    type: [Number, String],
    default: 6000,
    validator: value => Number(value) > 0
  },
  progress: [Boolean, String],
  verticalDelimiters: [Boolean, String],
  ...makeVWindowProps({
    continuous: true,
    mandatory: 'force',
    showArrows: true
  })
}, 'VCarousel');
const VCarousel = genericComponent()({
  name: 'VCarousel',
  props: makeVCarouselProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const model = useProxiedModel(props, 'modelValue');
    const {
      t
    } = useLocale();
    const windowRef = ref();
    let slideTimeout = -1;
    watch(model, restartTimeout);
    watch(() => props.interval, restartTimeout);
    watch(() => props.cycle, val => {
      if (val) restartTimeout();else window.clearTimeout(slideTimeout);
    });
    onMounted(startTimeout);
    function startTimeout() {
      if (!props.cycle || !windowRef.value) return;
      slideTimeout = window.setTimeout(windowRef.value.group.next, Number(props.interval) > 0 ? Number(props.interval) : 6000);
    }
    function restartTimeout() {
      window.clearTimeout(slideTimeout);
      window.requestAnimationFrame(startTimeout);
    }
    function onDelimiterKeyDown(e, group) {
      if (props.direction === 'horizontal' && e.key === 'ArrowLeft' || props.direction === 'vertical' && e.key === 'ArrowUp') {
        e.preventDefault();
        group.prev();
        nextTick(() => windowRef.value?.$el.querySelector('.v-btn--active')?.focus());
      }
      if (props.direction === 'horizontal' && e.key === 'ArrowRight' || props.direction === 'vertical' && e.key === 'ArrowDown') {
        e.preventDefault();
        group.next();
        nextTick(() => windowRef.value?.$el.querySelector('.v-btn--active')?.focus());
      }
    }
    useRender(() => {
      const windowProps = VWindow.filterProps(props);
      return createVNode(VWindow, mergeProps({
        "ref": windowRef
      }, windowProps, {
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "class": ['v-carousel', {
          'v-carousel--hide-delimiter-background': props.hideDelimiterBackground,
          'v-carousel--vertical-delimiters': props.verticalDelimiters
        }, props.class],
        "style": [{
          height: convertToUnit(props.height)
        }, props.style]
      }), {
        default: slots.default,
        additional: ({
          group
        }) => createElementVNode(Fragment, null, [!props.hideDelimiters && createElementVNode("div", {
          "class": "v-carousel__controls",
          "style": {
            left: props.verticalDelimiters === 'left' && props.verticalDelimiters ? 0 : 'auto',
            right: props.verticalDelimiters === 'right' ? 0 : 'auto'
          }
        }, [group.items.value.length > 0 && createVNode(VDefaultsProvider, {
          "defaults": {
            VBtn: {
              color: props.color,
              icon: props.delimiterIcon,
              size: 'x-small',
              variant: 'text'
            }
          },
          "scoped": true
        }, {
          default: () => [group.items.value.map((item, index) => {
            const props = {
              id: `carousel-item-${item.id}`,
              'aria-label': t('$vuetify.carousel.ariaLabel.delimiter', index + 1, group.items.value.length),
              class: ['v-carousel__controls__item', group.isSelected(item.id) && 'v-btn--active'],
              onClick: () => group.select(item.id, true),
              onKeydown: e => onDelimiterKeyDown(e, group)
            };
            return slots.item ? slots.item({
              props,
              item
            }) : createVNode(VBtn, mergeProps(item, props), null);
          })]
        })]), props.progress && createVNode(VProgressLinear, {
          "absolute": true,
          "class": "v-carousel__progress",
          "color": typeof props.progress === 'string' ? props.progress : undefined,
          "modelValue": (group.getItemIndex(model.value) + 1) / group.items.value.length * 100
        }, null)]),
        prev: slots.prev,
        next: slots.next
      });
    });
    return {};
  }
});

const makeVWindowItemProps = propsFactory({
  reverseTransition: {
    type: [Boolean, String],
    default: undefined
  },
  transition: {
    type: [Boolean, String],
    default: undefined
  },
  ...makeComponentProps(),
  ...makeGroupItemProps(),
  ...makeLazyProps()
}, 'VWindowItem');
const VWindowItem = genericComponent()({
  name: 'VWindowItem',
  directives: {
    vTouch: Touch
  },
  props: makeVWindowItemProps(),
  emits: {
    'group:selected': val => true
  },
  setup(props, {
    slots
  }) {
    const window = inject$1(VWindowSymbol);
    const groupItem = useGroupItem(props, VWindowGroupSymbol);
    const {
      isBooted
    } = useSsrBoot();
    if (!window || !groupItem) throw new Error('[Vuetify] VWindowItem must be used inside VWindow');
    const isTransitioning = shallowRef(false);
    const hasTransition = computed(() => isBooted.value && (window.isReversed.value ? props.reverseTransition !== false : props.transition !== false));
    function onAfterTransition() {
      if (!isTransitioning.value || !window) {
        return;
      }

      // Finalize transition state.
      isTransitioning.value = false;
      if (window.transitionCount.value > 0) {
        window.transitionCount.value -= 1;

        // Remove container height if we are out of transition.
        if (window.transitionCount.value === 0) {
          window.transitionHeight.value = undefined;
        }
      }
    }
    function onBeforeTransition() {
      if (isTransitioning.value || !window) {
        return;
      }

      // Initialize transition state here.
      isTransitioning.value = true;
      if (window.transitionCount.value === 0) {
        // Set initial height for height transition.
        window.transitionHeight.value = convertToUnit(window.rootRef.value?.clientHeight);
      }
      window.transitionCount.value += 1;
    }
    function onTransitionCancelled() {
      onAfterTransition(); // This should have the same path as normal transition end.
    }
    function onEnterTransition(el) {
      if (!isTransitioning.value) {
        return;
      }
      nextTick(() => {
        // Do not set height if no transition or cancelled.
        if (!hasTransition.value || !isTransitioning.value || !window) {
          return;
        }

        // Set transition target height.
        window.transitionHeight.value = convertToUnit(el.clientHeight);
      });
    }
    const transition = computed(() => {
      const name = window.isReversed.value ? props.reverseTransition : props.transition;
      return !hasTransition.value ? false : {
        name: typeof name !== 'string' ? window.transition.value : name,
        onBeforeEnter: onBeforeTransition,
        onAfterEnter: onAfterTransition,
        onEnterCancelled: onTransitionCancelled,
        onBeforeLeave: onBeforeTransition,
        onAfterLeave: onAfterTransition,
        onLeaveCancelled: onTransitionCancelled,
        onEnter: onEnterTransition
      };
    });
    const {
      hasContent
    } = useLazy(props, groupItem.isSelected);
    useRender(() => createVNode(MaybeTransition, {
      "transition": transition.value,
      "disabled": !isBooted.value
    }, {
      default: () => [withDirectives(createElementVNode("div", {
        "class": normalizeClass(['v-window-item', groupItem.selectedClass.value, props.class]),
        "style": normalizeStyle(props.style)
      }, [hasContent.value && slots.default?.()]), [[vShow, groupItem.isSelected.value]])]
    }));
    return {
      groupItem
    };
  }
});

// Types

const makeVCarouselItemProps = propsFactory({
  ...makeVImgProps(),
  ...makeVWindowItemProps()
}, 'VCarouselItem');
const VCarouselItem = genericComponent()({
  name: 'VCarouselItem',
  inheritAttrs: false,
  props: makeVCarouselItemProps(),
  setup(props, {
    slots,
    attrs
  }) {
    useRender(() => {
      const imgProps = VImg.filterProps(props);
      const windowItemProps = VWindowItem.filterProps(props);
      return createVNode(VWindowItem, mergeProps({
        "class": ['v-carousel-item', props.class]
      }, windowItemProps), {
        default: () => [createVNode(VImg, mergeProps(attrs, imgProps), slots)]
      });
    });
  }
});

// Styles
const VCode = createSimpleFunctional('v-code', 'code');

// Types

const makeVColorPickerCanvasProps = propsFactory({
  color: {
    type: Object
  },
  disabled: Boolean,
  readonly: Boolean,
  dotSize: {
    type: [Number, String],
    default: 10
  },
  height: {
    type: [Number, String],
    default: 150
  },
  width: {
    type: [Number, String],
    default: 300
  },
  ...makeComponentProps()
}, 'VColorPickerCanvas');
const VColorPickerCanvas = defineComponent({
  name: 'VColorPickerCanvas',
  props: makeVColorPickerCanvasProps(),
  emits: {
    'update:color': color => true,
    'update:position': hue => true
  },
  setup(props, {
    emit
  }) {
    const isInteracting = shallowRef(false);
    const canvasRef = ref();
    const canvasWidth = shallowRef(parseFloat(props.width));
    const canvasHeight = shallowRef(parseFloat(props.height));
    const _dotPosition = ref({
      x: 0,
      y: 0
    });
    const isInteractive = toRef(() => !props.disabled && !props.readonly);
    const dotPosition = computed({
      get: () => _dotPosition.value,
      set(val) {
        if (!canvasRef.value) return;
        const {
          x,
          y
        } = val;
        _dotPosition.value = val;
        emit('update:color', {
          h: props.color?.h ?? 0,
          s: clamp(x, 0, canvasWidth.value) / canvasWidth.value,
          v: 1 - clamp(y, 0, canvasHeight.value) / canvasHeight.value,
          a: props.color?.a ?? 1
        });
      }
    });
    const dotStyles = computed(() => {
      const {
        x,
        y
      } = dotPosition.value;
      const radius = parseInt(props.dotSize, 10) / 2;
      return {
        width: convertToUnit(props.dotSize),
        height: convertToUnit(props.dotSize),
        transform: `translate(${convertToUnit(x - radius)}, ${convertToUnit(y - radius)})`
      };
    });
    const {
      resizeRef
    } = useResizeObserver(entries => {
      if (!resizeRef.el?.offsetParent) return;
      const {
        width,
        height
      } = entries[0].contentRect;
      canvasWidth.value = Math.round(width);
      canvasHeight.value = Math.round(height);
    });
    function updateDotPosition(x, y, rect) {
      const {
        left,
        top,
        width,
        height
      } = rect;
      dotPosition.value = {
        x: clamp(x - left, 0, width),
        y: clamp(y - top, 0, height)
      };
    }
    function handleMouseDown(e) {
      if (e.type === 'mousedown') {
        // Prevent text selection while dragging
        e.preventDefault();
      }
      if (!isInteractive.value) return;
      handleMouseMove(e);
      window.addEventListener('mousemove', handleMouseMove);
      window.addEventListener('mouseup', handleMouseUp);
      window.addEventListener('touchmove', handleMouseMove);
      window.addEventListener('touchend', handleMouseUp);
    }
    function handleMouseMove(e) {
      if (!isInteractive.value || !canvasRef.value) return;
      isInteracting.value = true;
      const coords = getEventCoordinates(e);
      const point = getTargetBox([coords.clientX, coords.clientY]);
      updateDotPosition(point.x, point.y, getTargetBox(canvasRef.value));
    }
    function handleMouseUp() {
      window.removeEventListener('mousemove', handleMouseMove);
      window.removeEventListener('mouseup', handleMouseUp);
      window.removeEventListener('touchmove', handleMouseMove);
      window.removeEventListener('touchend', handleMouseUp);
    }
    function updateCanvas() {
      if (!canvasRef.value) return;
      const canvas = canvasRef.value;
      const ctx = canvas.getContext('2d');
      if (!ctx) return;
      const saturationGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
      saturationGradient.addColorStop(0, 'hsla(0, 0%, 100%, 1)'); // white
      saturationGradient.addColorStop(1, `hsla(${props.color?.h ?? 0}, 100%, 50%, 1)`);
      ctx.fillStyle = saturationGradient;
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      const valueGradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
      valueGradient.addColorStop(0, 'hsla(0, 0%, 0%, 0)'); // transparent
      valueGradient.addColorStop(1, 'hsla(0, 0%, 0%, 1)'); // black
      ctx.fillStyle = valueGradient;
      ctx.fillRect(0, 0, canvas.width, canvas.height);
    }
    watch(() => props.color?.h, updateCanvas, {
      immediate: true
    });
    watch(() => [canvasWidth.value, canvasHeight.value], (newVal, oldVal) => {
      updateCanvas();
      _dotPosition.value = {
        x: dotPosition.value.x * newVal[0] / oldVal[0],
        y: dotPosition.value.y * newVal[1] / oldVal[1]
      };
    }, {
      flush: 'post'
    });
    watch(() => props.color, () => {
      if (isInteracting.value) {
        isInteracting.value = false;
        return;
      }
      _dotPosition.value = props.color ? {
        x: props.color.s * canvasWidth.value,
        y: (1 - props.color.v) * canvasHeight.value
      } : {
        x: 0,
        y: 0
      };
    }, {
      deep: true,
      immediate: true
    });
    onMounted(() => updateCanvas());
    useRender(() => createElementVNode("div", {
      "ref": resizeRef,
      "class": normalizeClass(['v-color-picker-canvas', props.class]),
      "style": normalizeStyle(props.style),
      "onMousedown": handleMouseDown,
      "onTouchstartPassive": handleMouseDown
    }, [createElementVNode("canvas", {
      "ref": canvasRef,
      "width": canvasWidth.value,
      "height": canvasHeight.value
    }, null), props.color && createElementVNode("div", {
      "class": normalizeClass(['v-color-picker-canvas__dot', {
        'v-color-picker-canvas__dot--disabled': props.disabled
      }]),
      "style": normalizeStyle(dotStyles.value)
    }, null)]));
    return {};
  }
});

// Utilities

// Types

function stripAlpha(color, stripAlpha) {
  if (stripAlpha) {
    const {
      a,
      ...rest
    } = color;
    return rest;
  }
  return color;
}
function extractColor(color, input) {
  if (input == null || typeof input === 'string') {
    const hasA = typeof color.a === 'number' && color.a < 1;
    if (input?.startsWith('rgb(')) {
      const {
        r,
        g,
        b,
        a
      } = HSVtoRGB(color);
      return `rgb(${r} ${g} ${b}` + (hasA ? ` / ${a})` : ')');
    } else if (input?.startsWith('hsl(')) {
      const {
        h,
        s,
        l,
        a
      } = HSVtoHSL(color);
      return `hsl(${h} ${Math.round(s * 100)} ${Math.round(l * 100)}` + (hasA ? ` / ${a})` : ')');
    }
    const hex = HSVtoHex(color);
    if (color.a === 1) return hex.slice(0, 7);else return hex;
  }
  if (typeof input === 'object') {
    let converted;
    if (has(input, ['r', 'g', 'b'])) converted = HSVtoRGB(color);else if (has(input, ['h', 's', 'l'])) converted = HSVtoHSL(color);else if (has(input, ['h', 's', 'v'])) converted = color;
    return stripAlpha(converted, !has(input, ['a']) && color.a === 1);
  }
  return color;
}
const nullColor = {
  h: 0,
  s: 0,
  v: 0,
  a: 1
};
const rgba = {
  inputProps: {
    type: 'number',
    min: 0
  },
  inputs: [{
    label: 'R',
    max: 255,
    step: 1,
    getValue: c => Math.round(c.r),
    getColor: (c, v) => ({
      ...c,
      r: Number(v)
    }),
    localeKey: 'redInput'
  }, {
    label: 'G',
    max: 255,
    step: 1,
    getValue: c => Math.round(c.g),
    getColor: (c, v) => ({
      ...c,
      g: Number(v)
    }),
    localeKey: 'greenInput'
  }, {
    label: 'B',
    max: 255,
    step: 1,
    getValue: c => Math.round(c.b),
    getColor: (c, v) => ({
      ...c,
      b: Number(v)
    }),
    localeKey: 'blueInput'
  }, {
    label: 'A',
    max: 1,
    step: 0.01,
    getValue: ({
      a
    }) => a != null ? Math.round(a * 100) / 100 : 1,
    getColor: (c, v) => ({
      ...c,
      a: Number(v)
    }),
    localeKey: 'alphaInput'
  }],
  to: HSVtoRGB,
  from: RGBtoHSV
};
const rgb = {
  ...rgba,
  inputs: rgba.inputs?.slice(0, 3)
};
const hsla = {
  inputProps: {
    type: 'number',
    min: 0
  },
  inputs: [{
    label: 'H',
    max: 360,
    step: 1,
    getValue: c => Math.round(c.h),
    getColor: (c, v) => ({
      ...c,
      h: Number(v)
    }),
    localeKey: 'hueInput'
  }, {
    label: 'S',
    max: 1,
    step: 0.01,
    getValue: c => Math.round(c.s * 100) / 100,
    getColor: (c, v) => ({
      ...c,
      s: Number(v)
    }),
    localeKey: 'saturationInput'
  }, {
    label: 'L',
    max: 1,
    step: 0.01,
    getValue: c => Math.round(c.l * 100) / 100,
    getColor: (c, v) => ({
      ...c,
      l: Number(v)
    }),
    localeKey: 'lightnessInput'
  }, {
    label: 'A',
    max: 1,
    step: 0.01,
    getValue: ({
      a
    }) => a != null ? Math.round(a * 100) / 100 : 1,
    getColor: (c, v) => ({
      ...c,
      a: Number(v)
    }),
    localeKey: 'alphaInput'
  }],
  to: HSVtoHSL,
  from: HSLtoHSV
};
const hsl = {
  ...hsla,
  inputs: hsla.inputs.slice(0, 3)
};
const hexa = {
  inputProps: {
    type: 'text'
  },
  inputs: [{
    label: 'HEXA',
    getValue: c => c,
    getColor: (c, v) => v,
    localeKey: 'hexaInput'
  }],
  to: HSVtoHex,
  from: HexToHSV
};
const hex = {
  ...hexa,
  inputs: [{
    label: 'HEX',
    getValue: c => c.slice(0, 7),
    getColor: (c, v) => v,
    localeKey: 'hexInput'
  }]
};
const modes = {
  rgb,
  rgba,
  hsl,
  hsla,
  hex,
  hexa
};

// Types

const VColorPickerInput = ({
  label,
  ...rest
}) => {
  return createElementVNode("div", {
    "class": "v-color-picker-edit__input"
  }, [createElementVNode("input", normalizeProps(guardReactiveProps(rest)), null), createElementVNode("span", null, [label])]);
};
const makeVColorPickerEditProps = propsFactory({
  color: Object,
  disabled: Boolean,
  hideInputLabels: Boolean,
  readonly: Boolean,
  mode: {
    type: String,
    default: 'rgba',
    validator: v => Object.keys(modes).includes(v)
  },
  modes: {
    type: Array,
    default: () => Object.keys(modes),
    validator: v => Array.isArray(v) && v.every(m => Object.keys(modes).includes(m))
  },
  ...makeComponentProps()
}, 'VColorPickerEdit');
const VColorPickerEdit = defineComponent({
  name: 'VColorPickerEdit',
  props: makeVColorPickerEditProps(),
  emits: {
    'update:color': color => true,
    'update:mode': mode => true
  },
  setup(props, {
    emit
  }) {
    const {
      t
    } = useLocale();
    const enabledModes = computed(() => {
      return props.modes.map(key => ({
        ...modes[key],
        name: key
      }));
    });
    const inputs = computed(() => {
      const mode = enabledModes.value.find(m => m.name === props.mode);
      if (!mode) return [];
      const color = props.color ? mode.to(props.color) : null;
      return mode.inputs?.map(({
        getValue,
        getColor,
        localeKey,
        ...inputProps
      }) => {
        return {
          ...mode.inputProps,
          ...inputProps,
          ariaLabel: t(`$vuetify.colorPicker.ariaLabel.${localeKey}`),
          disabled: props.disabled,
          readonly: props.readonly,
          value: color && getValue(color),
          onChange: e => {
            const target = e.target;
            if (!target) return;
            emit('update:color', mode.from(getColor(color ?? mode.to(nullColor), target.value)));
          }
        };
      });
    });
    useRender(() => createElementVNode("div", {
      "class": normalizeClass(['v-color-picker-edit', props.class]),
      "style": normalizeStyle(props.style)
    }, [inputs.value?.map(inputProps => createVNode(VColorPickerInput, mergeProps(inputProps, {
      "label": props.hideInputLabels ? undefined : inputProps.label
    }), null)), enabledModes.value.length > 1 && createVNode(VBtn, {
      "icon": "$unfold",
      "size": "x-small",
      "variant": "plain",
      "aria-label": t('$vuetify.colorPicker.ariaLabel.changeFormat'),
      "onClick": () => {
        const mi = enabledModes.value.findIndex(m => m.name === props.mode);
        emit('update:mode', enabledModes.value[(mi + 1) % enabledModes.value.length].name);
      }
    }, null)]));
    return {};
  }
});

/* eslint-disable max-statements */
// Composables

// Types

const VSliderSymbol = Symbol.for('vuetify:v-slider');
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];
}
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');
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
  };
};
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;
};

// Types

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');
const VSliderThumb = genericComponent()({
  name: 'VSliderThumb',
  directives: {
    vRipple: Ripple
  },
  props: makeVSliderThumbProps(),
  emits: {
    'update:modelValue': v => true
  },
  setup(props, {
    slots,
    emit
  }) {
    const slider = inject$1(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), [[Ripple, 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 {};
  }
});

// Types

const makeVSliderTrackProps = propsFactory({
  start: {
    type: Number,
    required: true
  },
  stop: {
    type: Number,
    required: true
  },
  ...makeComponentProps()
}, 'VSliderTrack');
const VSliderTrack = genericComponent()({
  name: 'VSliderTrack',
  props: makeVSliderTrackProps(),
  emits: {},
  setup(props, {
    slots
  }) {
    const slider = inject$1(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,
      roundedStyles
    } = 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)
        }, roundedStyles.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 {};
  }
});

// Types

const makeVSliderProps = propsFactory({
  ...makeFocusProps(),
  ...makeSliderProps(),
  ...makeVInputProps(),
  modelValue: {
    type: [Number, String],
    default: 0
  }
}, 'VSlider');
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);
  }
});

// Types

const makeVColorPickerPreviewProps = propsFactory({
  color: {
    type: Object
  },
  disabled: Boolean,
  readonly: Boolean,
  hideAlpha: Boolean,
  hideEyeDropper: Boolean,
  eyeDropperIcon: {
    type: IconValue,
    default: '$eyeDropper'
  },
  ...makeComponentProps()
}, 'VColorPickerPreview');
const VColorPickerPreview = defineComponent({
  name: 'VColorPickerPreview',
  props: makeVColorPickerPreviewProps(),
  emits: {
    'update:color': color => true
  },
  setup(props, {
    emit
  }) {
    const {
      t
    } = useLocale();
    const abortController = new AbortController();
    const isInteractive = toRef(() => !props.disabled && !props.readonly);
    onUnmounted(() => abortController.abort());
    async function openEyeDropper() {
      if (!SUPPORTS_EYE_DROPPER || !isInteractive.value) return;
      const eyeDropper = new window.EyeDropper();
      try {
        const result = await eyeDropper.open({
          signal: abortController.signal
        });
        const colorHexValue = RGBtoHSV(parseColor(result.sRGBHex));
        emit('update:color', {
          ...(props.color ?? nullColor),
          ...colorHexValue
        });
      } catch (e) {}
    }
    useRender(() => createElementVNode("div", {
      "class": normalizeClass(['v-color-picker-preview', {
        'v-color-picker-preview--hide-alpha': props.hideAlpha
      }, props.class]),
      "style": normalizeStyle(props.style)
    }, [SUPPORTS_EYE_DROPPER && !props.hideEyeDropper && createElementVNode("div", {
      "class": "v-color-picker-preview__eye-dropper",
      "key": "eyeDropper"
    }, [createVNode(VBtn, {
      "aria-label": t('$vuetify.colorPicker.ariaLabel.eyedropper'),
      "density": "comfortable",
      "disabled": props.disabled,
      "readonly": props.readonly,
      "icon": props.eyeDropperIcon,
      "variant": "plain",
      "onClick": openEyeDropper
    }, null)]), createElementVNode("div", {
      "class": "v-color-picker-preview__dot"
    }, [createElementVNode("div", {
      "style": {
        background: HSVtoCSS(props.color ?? nullColor)
      }
    }, null)]), createElementVNode("div", {
      "class": "v-color-picker-preview__sliders"
    }, [createVNode(VSlider, {
      "class": "v-color-picker-preview__track v-color-picker-preview__hue",
      "aria-label": t('$vuetify.colorPicker.ariaLabel.hueSlider'),
      "modelValue": props.color?.h,
      "onUpdate:modelValue": h => emit('update:color', {
        ...(props.color ?? nullColor),
        h
      }),
      "step": 1,
      "min": 0,
      "max": 360,
      "disabled": props.disabled,
      "readonly": props.readonly,
      "thumbSize": 14,
      "trackSize": 8,
      "trackFillColor": "white",
      "hideDetails": true
    }, null), !props.hideAlpha && createVNode(VSlider, {
      "class": "v-color-picker-preview__track v-color-picker-preview__alpha",
      "aria-label": t('$vuetify.colorPicker.ariaLabel.alphaSlider'),
      "modelValue": props.color?.a ?? 1,
      "onUpdate:modelValue": a => emit('update:color', {
        ...(props.color ?? nullColor),
        a
      }),
      "step": 0.01,
      "min": 0,
      "max": 1,
      "disabled": props.disabled,
      "readonly": props.readonly,
      "thumbSize": 14,
      "trackSize": 8,
      "trackFillColor": "white",
      "hideDetails": true
    }, null)])]));
    return {};
  }
});

const red = {
  base: '#f44336',
  lighten5: '#ffebee',
  lighten4: '#ffcdd2',
  lighten3: '#ef9a9a',
  lighten2: '#e57373',
  lighten1: '#ef5350',
  darken1: '#e53935',
  darken2: '#d32f2f',
  darken3: '#c62828',
  darken4: '#b71c1c',
  accent1: '#ff8a80',
  accent2: '#ff5252',
  accent3: '#ff1744',
  accent4: '#d50000'
};
const pink = {
  base: '#e91e63',
  lighten5: '#fce4ec',
  lighten4: '#f8bbd0',
  lighten3: '#f48fb1',
  lighten2: '#f06292',
  lighten1: '#ec407a',
  darken1: '#d81b60',
  darken2: '#c2185b',
  darken3: '#ad1457',
  darken4: '#880e4f',
  accent1: '#ff80ab',
  accent2: '#ff4081',
  accent3: '#f50057',
  accent4: '#c51162'
};
const purple = {
  base: '#9c27b0',
  lighten5: '#f3e5f5',
  lighten4: '#e1bee7',
  lighten3: '#ce93d8',
  lighten2: '#ba68c8',
  lighten1: '#ab47bc',
  darken1: '#8e24aa',
  darken2: '#7b1fa2',
  darken3: '#6a1b9a',
  darken4: '#4a148c',
  accent1: '#ea80fc',
  accent2: '#e040fb',
  accent3: '#d500f9',
  accent4: '#aa00ff'
};
const deepPurple = {
  base: '#673ab7',
  lighten5: '#ede7f6',
  lighten4: '#d1c4e9',
  lighten3: '#b39ddb',
  lighten2: '#9575cd',
  lighten1: '#7e57c2',
  darken1: '#5e35b1',
  darken2: '#512da8',
  darken3: '#4527a0',
  darken4: '#311b92',
  accent1: '#b388ff',
  accent2: '#7c4dff',
  accent3: '#651fff',
  accent4: '#6200ea'
};
const indigo = {
  base: '#3f51b5',
  lighten5: '#e8eaf6',
  lighten4: '#c5cae9',
  lighten3: '#9fa8da',
  lighten2: '#7986cb',
  lighten1: '#5c6bc0',
  darken1: '#3949ab',
  darken2: '#303f9f',
  darken3: '#283593',
  darken4: '#1a237e',
  accent1: '#8c9eff',
  accent2: '#536dfe',
  accent3: '#3d5afe',
  accent4: '#304ffe'
};
const blue = {
  base: '#2196f3',
  lighten5: '#e3f2fd',
  lighten4: '#bbdefb',
  lighten3: '#90caf9',
  lighten2: '#64b5f6',
  lighten1: '#42a5f5',
  darken1: '#1e88e5',
  darken2: '#1976d2',
  darken3: '#1565c0',
  darken4: '#0d47a1',
  accent1: '#82b1ff',
  accent2: '#448aff',
  accent3: '#2979ff',
  accent4: '#2962ff'
};
const lightBlue = {
  base: '#03a9f4',
  lighten5: '#e1f5fe',
  lighten4: '#b3e5fc',
  lighten3: '#81d4fa',
  lighten2: '#4fc3f7',
  lighten1: '#29b6f6',
  darken1: '#039be5',
  darken2: '#0288d1',
  darken3: '#0277bd',
  darken4: '#01579b',
  accent1: '#80d8ff',
  accent2: '#40c4ff',
  accent3: '#00b0ff',
  accent4: '#0091ea'
};
const cyan = {
  base: '#00bcd4',
  lighten5: '#e0f7fa',
  lighten4: '#b2ebf2',
  lighten3: '#80deea',
  lighten2: '#4dd0e1',
  lighten1: '#26c6da',
  darken1: '#00acc1',
  darken2: '#0097a7',
  darken3: '#00838f',
  darken4: '#006064',
  accent1: '#84ffff',
  accent2: '#18ffff',
  accent3: '#00e5ff',
  accent4: '#00b8d4'
};
const teal = {
  base: '#009688',
  lighten5: '#e0f2f1',
  lighten4: '#b2dfdb',
  lighten3: '#80cbc4',
  lighten2: '#4db6ac',
  lighten1: '#26a69a',
  darken1: '#00897b',
  darken2: '#00796b',
  darken3: '#00695c',
  darken4: '#004d40',
  accent1: '#a7ffeb',
  accent2: '#64ffda',
  accent3: '#1de9b6',
  accent4: '#00bfa5'
};
const green = {
  base: '#4caf50',
  lighten5: '#e8f5e9',
  lighten4: '#c8e6c9',
  lighten3: '#a5d6a7',
  lighten2: '#81c784',
  lighten1: '#66bb6a',
  darken1: '#43a047',
  darken2: '#388e3c',
  darken3: '#2e7d32',
  darken4: '#1b5e20',
  accent1: '#b9f6ca',
  accent2: '#69f0ae',
  accent3: '#00e676',
  accent4: '#00c853'
};
const lightGreen = {
  base: '#8bc34a',
  lighten5: '#f1f8e9',
  lighten4: '#dcedc8',
  lighten3: '#c5e1a5',
  lighten2: '#aed581',
  lighten1: '#9ccc65',
  darken1: '#7cb342',
  darken2: '#689f38',
  darken3: '#558b2f',
  darken4: '#33691e',
  accent1: '#ccff90',
  accent2: '#b2ff59',
  accent3: '#76ff03',
  accent4: '#64dd17'
};
const lime = {
  base: '#cddc39',
  lighten5: '#f9fbe7',
  lighten4: '#f0f4c3',
  lighten3: '#e6ee9c',
  lighten2: '#dce775',
  lighten1: '#d4e157',
  darken1: '#c0ca33',
  darken2: '#afb42b',
  darken3: '#9e9d24',
  darken4: '#827717',
  accent1: '#f4ff81',
  accent2: '#eeff41',
  accent3: '#c6ff00',
  accent4: '#aeea00'
};
const yellow = {
  base: '#ffeb3b',
  lighten5: '#fffde7',
  lighten4: '#fff9c4',
  lighten3: '#fff59d',
  lighten2: '#fff176',
  lighten1: '#ffee58',
  darken1: '#fdd835',
  darken2: '#fbc02d',
  darken3: '#f9a825',
  darken4: '#f57f17',
  accent1: '#ffff8d',
  accent2: '#ffff00',
  accent3: '#ffea00',
  accent4: '#ffd600'
};
const amber = {
  base: '#ffc107',
  lighten5: '#fff8e1',
  lighten4: '#ffecb3',
  lighten3: '#ffe082',
  lighten2: '#ffd54f',
  lighten1: '#ffca28',
  darken1: '#ffb300',
  darken2: '#ffa000',
  darken3: '#ff8f00',
  darken4: '#ff6f00',
  accent1: '#ffe57f',
  accent2: '#ffd740',
  accent3: '#ffc400',
  accent4: '#ffab00'
};
const orange = {
  base: '#ff9800',
  lighten5: '#fff3e0',
  lighten4: '#ffe0b2',
  lighten3: '#ffcc80',
  lighten2: '#ffb74d',
  lighten1: '#ffa726',
  darken1: '#fb8c00',
  darken2: '#f57c00',
  darken3: '#ef6c00',
  darken4: '#e65100',
  accent1: '#ffd180',
  accent2: '#ffab40',
  accent3: '#ff9100',
  accent4: '#ff6d00'
};
const deepOrange = {
  base: '#ff5722',
  lighten5: '#fbe9e7',
  lighten4: '#ffccbc',
  lighten3: '#ffab91',
  lighten2: '#ff8a65',
  lighten1: '#ff7043',
  darken1: '#f4511e',
  darken2: '#e64a19',
  darken3: '#d84315',
  darken4: '#bf360c',
  accent1: '#ff9e80',
  accent2: '#ff6e40',
  accent3: '#ff3d00',
  accent4: '#dd2c00'
};
const brown = {
  base: '#795548',
  lighten5: '#efebe9',
  lighten4: '#d7ccc8',
  lighten3: '#bcaaa4',
  lighten2: '#a1887f',
  lighten1: '#8d6e63',
  darken1: '#6d4c41',
  darken2: '#5d4037',
  darken3: '#4e342e',
  darken4: '#3e2723'
};
const blueGrey = {
  base: '#607d8b',
  lighten5: '#eceff1',
  lighten4: '#cfd8dc',
  lighten3: '#b0bec5',
  lighten2: '#90a4ae',
  lighten1: '#78909c',
  darken1: '#546e7a',
  darken2: '#455a64',
  darken3: '#37474f',
  darken4: '#263238'
};
const grey = {
  base: '#9e9e9e',
  lighten5: '#fafafa',
  lighten4: '#f5f5f5',
  lighten3: '#eeeeee',
  lighten2: '#e0e0e0',
  lighten1: '#bdbdbd',
  darken1: '#757575',
  darken2: '#616161',
  darken3: '#424242',
  darken4: '#212121'
};
const shades = {
  black: '#000000',
  white: '#ffffff',
  transparent: '#ffffff00'
};
var colors = {
  red,
  pink,
  purple,
  deepPurple,
  indigo,
  blue,
  lightBlue,
  cyan,
  teal,
  green,
  lightGreen,
  lime,
  yellow,
  amber,
  orange,
  deepOrange,
  brown,
  blueGrey,
  grey,
  shades
};

// Types

const makeVColorPickerSwatchesProps = propsFactory({
  swatches: {
    type: Array,
    default: () => parseDefaultColors(colors)
  },
  disabled: Boolean,
  readonly: Boolean,
  color: Object,
  maxHeight: [Number, String],
  ...makeComponentProps()
}, 'VColorPickerSwatches');
function parseDefaultColors(colors) {
  return Object.keys(colors).map(key => {
    const color = colors[key];
    return color.base ? [color.base, color.darken4, color.darken3, color.darken2, color.darken1, color.lighten1, color.lighten2, color.lighten3, color.lighten4, color.lighten5] : [color.black, color.white, color.transparent];
  });
}
const VColorPickerSwatches = defineComponent({
  name: 'VColorPickerSwatches',
  props: makeVColorPickerSwatchesProps(),
  emits: {
    'update:color': color => true
  },
  setup(props, {
    emit
  }) {
    const isInteractive = toRef(() => !props.disabled && !props.readonly);
    function onSwatchClick(hsva) {
      if (!isInteractive.value || !hsva) {
        return;
      }
      emit('update:color', hsva);
    }
    useRender(() => createElementVNode("div", {
      "class": normalizeClass(['v-color-picker-swatches', props.class]),
      "style": normalizeStyle([{
        maxHeight: convertToUnit(props.maxHeight)
      }, props.style])
    }, [createElementVNode("div", null, [props.swatches.map(swatch => createElementVNode("div", {
      "class": "v-color-picker-swatches__swatch"
    }, [swatch.map(color => {
      const rgba = parseColor(color);
      const hsva = RGBtoHSV(rgba);
      const background = RGBtoCSS(rgba);
      return createElementVNode("div", {
        "class": normalizeClass(['v-color-picker-swatches__color', {
          'v-color-picker-swatches__color--disabled': props.disabled
        }]),
        "onClick": () => onSwatchClick(hsva)
      }, [createElementVNode("div", {
        "style": {
          background
        }
      }, [props.color && deepEqual(props.color, hsva) ? createVNode(VIcon, {
        "size": "x-small",
        "icon": "$success",
        "color": getContrast(color, '#FFFFFF') > 2 ? 'white' : 'black'
      }, null) : undefined])]);
    })]))])]));
    return {};
  }
});

// Utilities
const VPickerTitle = createSimpleFunctional('v-picker-title');

// Types

const makeVPickerProps = propsFactory({
  bgColor: String,
  divided: Boolean,
  landscape: Boolean,
  title: String,
  hideHeader: Boolean,
  hideTitle: Boolean,
  ...makeVSheetProps()
}, 'VPicker');
const VPicker = genericComponent()({
  name: 'VPicker',
  props: makeVPickerProps(),
  setup(props, {
    slots
  }) {
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    useRender(() => {
      const sheetProps = VSheet.filterProps(props);
      const hasTitle = !props.hideTitle && !!(props.title || slots.title);
      return createVNode(VSheet, mergeProps(sheetProps, {
        "color": props.bgColor,
        "class": ['v-picker', {
          'v-picker--divided': props.divided,
          'v-picker--landscape': props.landscape,
          'v-picker--with-actions': !!slots.actions
        }, props.class],
        "style": props.style
      }), {
        default: () => [!props.hideHeader && createElementVNode("div", {
          "key": "header",
          "class": normalizeClass(['v-picker__header-wrapper', backgroundColorClasses.value]),
          "style": normalizeStyle([backgroundColorStyles.value])
        }, [hasTitle && createVNode(VPickerTitle, {
          "key": "picker-title"
        }, {
          default: () => [slots.title?.() ?? props.title]
        }), slots.header && createElementVNode("div", {
          "class": "v-picker__header"
        }, [slots.header()])]), createElementVNode("div", {
          "class": "v-picker__body"
        }, [slots.default?.()]), slots.actions && createVNode(VDefaultsProvider, {
          "defaults": {
            VBtn: {
              slim: true,
              variant: 'text'
            }
          }
        }, {
          default: () => [createElementVNode("div", {
            "class": "v-picker__actions"
          }, [slots.actions()])]
        })]
      });
    });
    return {};
  }
});

// Types

const makeVColorPickerProps = propsFactory({
  canvasHeight: {
    type: [String, Number],
    default: 150
  },
  disabled: Boolean,
  dotSize: {
    type: [Number, String],
    default: 10
  },
  hideCanvas: Boolean,
  hideSliders: Boolean,
  hideInputs: Boolean,
  hideInputLabels: Boolean,
  mode: {
    type: String,
    default: 'rgba',
    validator: v => Object.keys(modes).includes(v)
  },
  modes: {
    type: Array,
    default: () => Object.keys(modes),
    validator: v => Array.isArray(v) && v.every(m => Object.keys(modes).includes(m))
  },
  showSwatches: Boolean,
  readonly: Boolean,
  swatches: Array,
  swatchesMaxHeight: {
    type: [Number, String],
    default: 150
  },
  modelValue: {
    type: [Object, String]
  },
  ...makeVPickerProps({
    hideHeader: true
  }),
  ...pick(makeVColorPickerPreviewProps(), ['hideEyeDropper', 'eyeDropperIcon'])
}, 'VColorPicker');
const VColorPicker = defineComponent({
  name: 'VColorPicker',
  props: makeVColorPickerProps(),
  emits: {
    'update:modelValue': color => true,
    'update:mode': mode => true
  },
  setup(props, {
    slots
  }) {
    const mode = useProxiedModel(props, 'mode');
    const hue = ref(null);
    const model = useProxiedModel(props, 'modelValue', undefined, v => {
      if (v == null || v === '') return null;
      let c;
      try {
        c = RGBtoHSV(parseColor(v));
      } catch (err) {
        consoleWarn(err);
        return null;
      }
      return c;
    }, v => {
      if (!v) return null;
      return extractColor(v, props.modelValue);
    });
    const currentColor = computed(() => {
      return model.value ? {
        ...model.value,
        h: hue.value ?? model.value.h
      } : null;
    });
    const {
      rtlClasses
    } = useRtl();
    let externalChange = true;
    watch(model, v => {
      if (!externalChange) {
        // prevent hue shift from rgb conversion inaccuracy
        externalChange = true;
        return;
      }
      if (!v) return;
      hue.value = v.h;
    }, {
      immediate: true
    });
    const updateColor = hsva => {
      externalChange = false;
      hue.value = hsva.h;
      model.value = hsva;
    };
    onBeforeMount(() => {
      if (!props.modes.includes(mode.value)) mode.value = props.modes[0];
    });
    provideDefaults({
      VSlider: {
        color: null,
        trackColor: null,
        trackFillColor: null
      }
    });
    useRender(() => {
      const pickerProps = VPicker.filterProps(props);
      return createVNode(VPicker, mergeProps(pickerProps, {
        "class": ['v-color-picker', rtlClasses.value, props.class],
        "style": [{
          '--v-color-picker-color-hsv': HSVtoCSS({
            ...(currentColor.value ?? nullColor),
            a: 1
          })
        }, props.style]
      }), {
        ...slots,
        default: () => createElementVNode(Fragment, null, [!props.hideCanvas && createVNode(VColorPickerCanvas, {
          "key": "canvas",
          "color": currentColor.value,
          "onUpdate:color": updateColor,
          "disabled": props.disabled,
          "readonly": props.readonly,
          "dotSize": props.dotSize,
          "width": props.width,
          "height": props.canvasHeight
        }, null), (!props.hideSliders || !props.hideInputs) && createElementVNode("div", {
          "key": "controls",
          "class": "v-color-picker__controls"
        }, [!props.hideSliders && createVNode(VColorPickerPreview, {
          "key": "preview",
          "color": currentColor.value,
          "onUpdate:color": updateColor,
          "hideAlpha": !mode.value.endsWith('a'),
          "disabled": props.disabled,
          "readonly": props.readonly,
          "hideEyeDropper": props.hideEyeDropper,
          "eyeDropperIcon": props.eyeDropperIcon
        }, null), !props.hideInputs && createVNode(VColorPickerEdit, {
          "key": "edit",
          "modes": props.modes,
          "mode": mode.value,
          "onUpdate:mode": m => mode.value = m,
          "color": currentColor.value,
          "onUpdate:color": updateColor,
          "disabled": props.disabled,
          "readonly": props.readonly,
          "hideInputLabels": props.hideInputLabels
        }, null)]), props.showSwatches && createVNode(VColorPickerSwatches, {
          "key": "swatches",
          "color": currentColor.value,
          "onUpdate:color": updateColor,
          "maxHeight": props.swatchesMaxHeight,
          "swatches": props.swatches,
          "disabled": props.disabled,
          "readonly": props.readonly
        }, null)])
      });
    });
    return {};
  }
});

// Types

const makeVConfirmEditProps = propsFactory({
  modelValue: null,
  color: String,
  cancelText: {
    type: String,
    default: '$vuetify.confirmEdit.cancel'
  },
  okText: {
    type: String,
    default: '$vuetify.confirmEdit.ok'
  },
  disabled: {
    type: [Boolean, Array],
    default: undefined
  },
  hideActions: Boolean
}, 'VConfirmEdit');
const VConfirmEdit = genericComponent()({
  name: 'VConfirmEdit',
  props: makeVConfirmEditProps(),
  emits: {
    cancel: () => true,
    save: value => true,
    'update:modelValue': value => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const model = useProxiedModel(props, 'modelValue');
    const internalModel = ref();
    watchEffect(() => {
      internalModel.value = structuredClone(deepToRaw(model.value));
    });
    const {
      t
    } = useLocale();
    const isPristine = computed(() => {
      return deepEqual(model.value, internalModel.value);
    });
    function isActionDisabled(action) {
      if (typeof props.disabled === 'boolean') {
        return props.disabled;
      }
      if (Array.isArray(props.disabled)) {
        return props.disabled.includes(action);
      }
      return isPristine.value;
    }
    const isSaveDisabled = computed(() => isActionDisabled('save'));
    const isCancelDisabled = computed(() => isActionDisabled('cancel'));
    function save() {
      model.value = internalModel.value;
      emit('save', internalModel.value);
    }
    function cancel() {
      internalModel.value = structuredClone(deepToRaw(model.value));
      emit('cancel');
    }
    function actions(actionsProps) {
      return createElementVNode(Fragment, null, [createVNode(VBtn, mergeProps({
        "disabled": isCancelDisabled.value,
        "variant": "text",
        "color": props.color,
        "onClick": cancel,
        "text": t(props.cancelText)
      }, actionsProps), null), createVNode(VBtn, mergeProps({
        "disabled": isSaveDisabled.value,
        "variant": "text",
        "color": props.color,
        "onClick": save,
        "text": t(props.okText)
      }, actionsProps), null)]);
    }
    let actionsUsed = false;
    useRender(() => {
      return createElementVNode(Fragment, null, [slots.default?.({
        model: internalModel,
        save,
        cancel,
        isPristine: isPristine.value,
        get actions() {
          actionsUsed = true;
          return actions;
        }
      }), !props.hideActions && !actionsUsed && actions()]);
    });
    return {
      save,
      cancel,
      isPristine
    };
  }
});

// Types

const availablePipLocations = ['prepend', 'prepend-inner', 'append', 'append-inner'];
const makeVColorInputProps = propsFactory({
  hidePip: Boolean,
  colorPip: Boolean,
  menuProps: Object,
  pipIcon: {
    type: String,
    default: '$color'
  },
  pipLocation: {
    type: String,
    default: 'prepend',
    validator: v => availablePipLocations.includes(v)
  },
  pipVariant: {
    type: String,
    default: 'text'
  },
  pickerProps: Object,
  ...makeFocusProps(),
  ...makeVConfirmEditProps(),
  ...makeVTextFieldProps(),
  ...omit(makeVColorPickerProps(), ['location', 'height', 'minHeight', 'maxHeight'])
}, 'VColorInput');
const VColorInput = genericComponent()({
  name: 'VColorInput',
  props: makeVColorInputProps(),
  emits: {
    'update:modelValue': val => true
  },
  setup(props, {
    slots
  }) {
    const model = useProxiedModel(props, 'modelValue');
    const menu = shallowRef(false);
    const isFocused = shallowRef(props.focused);
    const isInteractive = computed(() => !props.disabled && !props.readonly);
    const display = computed(() => model.value || null);
    function onKeydown(e) {
      if (e.key !== 'Enter') return;
      if (!menu.value || !isFocused.value) {
        menu.value = true;
        return;
      }
      const target = e.target;
      model.value = target.value;
    }
    function onClick(e) {
      e.preventDefault();
      e.stopPropagation();
      menu.value = true;
    }
    function onSave() {
      menu.value = false;
    }
    function onCancel() {
      menu.value = false;
    }
    useRender(() => {
      const confirmEditProps = VConfirmEdit.filterProps(props);
      const colorPickerProps = {
        ...VColorPicker.filterProps(omit(props, ['active', 'bgColor', 'color', 'rounded', 'maxWidth', 'minWidth', 'width'])),
        ...props.pickerProps
      };
      const textFieldProps = VTextField.filterProps(props);
      const slotWithPip = props.hidePip ? undefined : {
        [props.pipLocation]: arg => createElementVNode(Fragment, null, [createVNode(VAvatar, {
          "class": "v-color-input__pip",
          "color": props.colorPip ? model.value : undefined,
          "variant": props.pipVariant,
          "icon": props.pipIcon
        }, null), slots[props.pipLocation]?.(arg)])
      };
      return createVNode(VTextField, mergeProps(textFieldProps, {
        "class": ['v-color-input', props.class],
        "style": props.style,
        "modelValue": display.value,
        "onKeydown": isInteractive.value ? onKeydown : undefined,
        "focused": menu.value || isFocused.value,
        "onClick:control": !props.disabled ? onClick : undefined,
        "onClick:prependInner": !props.disabled ? onClick : undefined,
        "onUpdate:focused": event => isFocused.value = event,
        "onClick:appendInner": !props.disabled ? onClick : undefined,
        "onUpdate:modelValue": val => {
          model.value = val;
        }
      }), {
        ...slots,
        ...slotWithPip,
        default: () => createElementVNode(Fragment, null, [createVNode(VMenu, mergeProps({
          "modelValue": menu.value,
          "onUpdate:modelValue": $event => menu.value = $event,
          "activator": "parent",
          "minWidth": "0",
          "closeOnContentClick": false,
          "openOnClick": false
        }, props.menuProps), {
          default: () => [createVNode(VConfirmEdit, mergeProps(confirmEditProps, {
            "modelValue": model.value,
            "onUpdate:modelValue": $event => model.value = $event,
            "onSave": onSave,
            "onCancel": onCancel
          }), {
            default: ({
              actions,
              model: proxyModel,
              save,
              cancel,
              isPristine
            }) => {
              function onUpdateModel(value) {
                if (!props.hideActions) {
                  proxyModel.value = value;
                } else {
                  model.value = value;
                }
              }
              return createVNode(VColorPicker, mergeProps(colorPickerProps, {
                "modelValue": props.hideActions ? model.value : proxyModel.value,
                "onUpdate:modelValue": value => onUpdateModel(value)
              }), {
                actions: !props.hideActions ? () => slots.actions?.({
                  save,
                  cancel,
                  isPristine
                }) ?? actions() : undefined
              });
            }
          })]
        }), slots.default?.()])
      });
    });
  }
});

// Types

const makeVComboboxProps = propsFactory({
  alwaysFilter: Boolean,
  autoSelectFirst: {
    type: [Boolean, String]
  },
  clearOnSelect: {
    type: Boolean,
    default: true
  },
  delimiters: Array,
  ...makeFilterProps({
    filterKeys: ['title']
  }),
  ...makeSelectProps({
    hideNoData: true,
    returnObject: true
  }),
  ...omit(makeVTextFieldProps({
    modelValue: null,
    role: 'combobox'
  }), ['validationValue', 'dirty'])
}, 'VCombobox');
const VCombobox = genericComponent()({
  name: 'VCombobox',
  props: makeVComboboxProps(),
  emits: {
    'update:focused': focused => true,
    'update:modelValue': value => true,
    'update:search': value => true,
    'update:menu': value => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    const vTextFieldRef = ref();
    const isFocused = shallowRef(false);
    const isPristine = shallowRef(true);
    const listHasFocus = shallowRef(false);
    const vMenuRef = ref();
    const vVirtualScrollRef = ref();
    const selectionIndex = shallowRef(-1);
    let cleared = false;
    const {
      items,
      transformIn,
      transformOut
    } = useItems(props);
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => vTextFieldRef.value?.color);
    const {
      InputIcon
    } = useInputIcon(props);
    const model = useProxiedModel(props, 'modelValue', [], v => transformIn(wrapInArray(v)), v => {
      const transformed = transformOut(v);
      return props.multiple ? transformed : transformed[0] ?? null;
    });
    const form = useForm(props);
    const closableChips = toRef(() => props.closableChips && !form.isReadonly.value && !form.isDisabled.value);
    const hasChips = computed(() => !!(props.chips || slots.chip));
    const hasSelectionSlot = computed(() => hasChips.value || !!slots.selection);
    const _search = shallowRef(!props.multiple && !hasSelectionSlot.value ? model.value[0]?.title ?? '' : '');
    const _searchLock = shallowRef(null);
    const search = computed({
      get: () => {
        return _search.value;
      },
      set: async val => {
        _search.value = val ?? '';
        if (val === null || val === '' && !props.multiple && !hasSelectionSlot.value) {
          model.value = [];
        } else if (!props.multiple && !hasSelectionSlot.value) {
          model.value = [transformItem$3(props, val)];
          nextTick(() => vVirtualScrollRef.value?.scrollToIndex(0));
        }
        if (val && props.multiple && props.delimiters?.length) {
          const values = splitByDelimiters(val);
          if (values.length > 1) {
            selectMultiple(values);
            _search.value = '';
          }
        }
        if (!val) selectionIndex.value = -1;
        isPristine.value = !val;
      }
    });
    const counterValue = computed(() => {
      return typeof props.counterValue === 'function' ? props.counterValue(model.value) : typeof props.counterValue === 'number' ? props.counterValue : props.multiple ? model.value.length : search.value.length;
    });
    const {
      filteredItems,
      getMatches
    } = useFilter(props, items, () => _searchLock.value ?? (props.alwaysFilter || !isPristine.value ? search.value : ''));
    const displayItems = computed(() => {
      if (props.hideSelected && _searchLock.value === null) {
        return filteredItems.value.filter(filteredItem => !model.value.some(s => s.value === filteredItem.value));
      }
      return filteredItems.value;
    });
    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);
    watch(_search, value => {
      if (cleared) {
        // wait for clear to finish, VTextField sets _search to null
        // then search computed triggers and updates _search to ''
        nextTick(() => cleared = false);
      } else if (isFocused.value && !menu.value) {
        menu.value = true;
      }
      emit('update:search', value);
    });
    watch(model, value => {
      if (!props.multiple && !hasSelectionSlot.value) {
        _search.value = value[0]?.title ?? '';
      }
    });
    const selectedValues = computed(() => model.value.map(selection => selection.value));
    const firstSelectableItem = computed(() => displayItems.value.find(x => x.type === 'item' && !x.props.disabled));
    const highlightFirst = computed(() => {
      const selectFirst = props.autoSelectFirst === true || props.autoSelectFirst === 'exact' && search.value === firstSelectableItem.value?.title;
      return selectFirst && displayItems.value.length > 0 && !isPristine.value && !listHasFocus.value;
    });
    const listRef = ref();
    const headerRef = ref();
    const footerRef = ref();
    const listEvents = useScrolling(listRef, vTextFieldRef);
    const repairOrphanedFocus = useFocusRepair(menu, () => vMenuRef.value?.contentEl, () => vTextFieldRef.value?.controlRef);
    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) {
      cleared = true;
      nextTick(() => cleared = false);
      if (props.openOnClear) {
        menu.value = true;
      }
    }
    function onMousedownControl() {
      if (menuDisabled.value) return;
      menu.value = true;
    }
    function onMousedownMenuIcon(e) {
      if (menuDisabled.value) return;
      if (isFocused.value) {
        e.preventDefault();
        e.stopPropagation();
      }
      menu.value = !menu.value;
    }
    function onMenuKeydown(e) {
      if (e.key === 'Tab') {
        onTabKeydown(e);
      }
      if (listRef.value?.$el.contains(e.target) && (checkPrintable(e) || e.key === 'Backspace')) {
        vTextFieldRef.value?.focus();
      }
    }

    // eslint-disable-next-line complexity
    function onKeydown(e) {
      if (isComposingIgnoreKey(e) || form.isReadonly.value) return;
      const selectionStart = vTextFieldRef.value?.selectionStart;
      const length = model.value.length;
      if (['Enter', 'ArrowDown', 'ArrowUp'].includes(e.key)) {
        e.preventDefault();
      }
      if (['Enter', 'ArrowDown'].includes(e.key)) {
        menu.value = true;
      }
      if (['Escape'].includes(e.key)) {
        menu.value = false;
      }
      if (highlightFirst.value && ['Enter', 'Tab'].includes(e.key) && firstSelectableItem.value && !model.value.some(({
        value
      }) => value === firstSelectableItem.value.value)) {
        select(firstSelectableItem.value);
      }
      if (e.key === 'ArrowDown' && highlightFirst.value) {
        listRef.value?.focus('next');
      }
      if (e.key === 'Enter' && search.value) {
        select(transformItem$3(props, search.value), true, true);
        if (hasSelectionSlot.value) _search.value = '';
      }
      if (['Backspace', 'Delete'].includes(e.key)) {
        if (!props.multiple && hasSelectionSlot.value && model.value.length > 0 && !search.value) return select(model.value[0], false);
        if (~selectionIndex.value) {
          e.preventDefault();
          const originalSelectionIndex = selectionIndex.value;
          select(model.value[selectionIndex.value], false);
          selectionIndex.value = originalSelectionIndex >= length - 1 ? length - 2 : originalSelectionIndex;
        } else if (e.key === 'Backspace' && !search.value) {
          selectionIndex.value = length - 1;
        }
        return;
      }
      if (!props.multiple) return;
      if (e.key === 'ArrowLeft') {
        if (selectionIndex.value < 0 && selectionStart && selectionStart > 0) return;
        const prev = selectionIndex.value > -1 ? selectionIndex.value - 1 : length - 1;
        if (model.value[prev]) {
          selectionIndex.value = prev;
        } else {
          selectionIndex.value = -1;
          vTextFieldRef.value?.setSelectionRange(search.value.length, search.value.length);
        }
      } else if (e.key === 'ArrowRight') {
        if (selectionIndex.value < 0) return;
        const next = selectionIndex.value + 1;
        if (model.value[next]) {
          selectionIndex.value = next;
        } else {
          selectionIndex.value = -1;
          vTextFieldRef.value?.setSelectionRange(0, 0);
        }
      } else if (~selectionIndex.value && checkPrintable(e)) {
        selectionIndex.value = -1;
      }
    }
    function onPaste(e) {
      const clipboardText = e?.clipboardData?.getData('Text') ?? '';
      const values = splitByDelimiters(clipboardText);
      if (values.length > 1 && props.multiple) {
        e.preventDefault();
        selectMultiple(values);
      }
    }
    function onAfterEnter() {
      if (props.eager) {
        vVirtualScrollRef.value?.calculateVisibleItems();
      }
    }
    function onAfterLeave() {
      if (isFocused.value) {
        if (vMenuRef.value?.contentEl?._clickOutside?.lastMousedownWasOutside) {
          isFocused.value = false;
        } else {
          vTextFieldRef.value?.focus();
        }
      }
      isPristine.value = true;
      _searchLock.value = null;
    }
    /** @param set - null means toggle */
    function select(item, set = true, keepMenu = false) {
      if (!item || 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];
        }
        if (props.clearOnSelect) {
          search.value = '';
        }
      } else {
        const add = set !== false;
        model.value = add ? [item] : [];
        if ((!isPristine.value || props.alwaysFilter) && _search.value) {
          _searchLock.value = _search.value;
        }
        _search.value = add && !hasSelectionSlot.value ? item.title : '';

        // watch for search watcher to trigger
        nextTick(() => {
          menu.value = keepMenu;
          isPristine.value = true;
        });
      }
    }
    function splitByDelimiters(val) {
      const effectiveDelimiters = ['\n', ...(props.delimiters ?? [])];
      const signsToMatch = effectiveDelimiters.map(escapeForRegex).join('|');
      return val.split(new RegExp(`(?:${signsToMatch})+`));
    }
    async function selectMultiple(values) {
      for (let value of values) {
        value = value.trim();
        if (value) {
          select(transformItem$3(props, value));
          await nextTick();
        }
      }
    }
    function onFocusin(e) {
      isFocused.value = true;
      setTimeout(() => {
        listHasFocus.value = true;
      });
    }
    function onFocusout(e) {
      listHasFocus.value = false;
      if (!vTextFieldRef.value?.$el.contains(e.relatedTarget)) {
        if (repairOrphanedFocus(e)) return;
        isFocused.value = false;
      }
    }
    let mousedownInsideContentAt = 0;
    function onMousedownContent() {
      mousedownInsideContentAt = performance.now();
    }
    function onBlur(e) {
      const next = e.relatedTarget;
      const menuContent = vMenuRef.value?.contentEl;
      if (menuContent?.contains(next) || !next && performance.now() - mousedownInsideContentAt < 10) {
        isFocused.value = true;
      }
    }
    watch(isFocused, (val, oldVal) => {
      if (val || val === oldVal) return;
      selectionIndex.value = -1;
      menu.value = false;
      if (search.value) {
        if (props.multiple) {
          select(transformItem$3(props, search.value));
          return;
        }
        if (!hasSelectionSlot.value) return;
        if (model.value.some(({
          title
        }) => title === search.value)) {
          _search.value = '';
        } else {
          select(transformItem$3(props, search.value));
        }
      }
    });
    watch(menu, val => {
      if (!props.hideSelected && val && model.value.length && isPristine.value) {
        const index = displayItems.value.findIndex(item => model.value.some(s => (props.valueComparator || deepEqual)(s.value, item.value)));
        IN_BROWSER && !props.noAutoScroll && window.requestAnimationFrame(() => {
          index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
        });
      }
      if (val) _searchLock.value = null;
    });
    watch(items, (newVal, oldVal) => {
      if (menu.value) return;
      if (isFocused.value && !oldVal.length && newVal.length) {
        menu.value = true;
      }
    });
    useRender(() => {
      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 menuSlotProps = {
        search,
        filteredItems: filteredItems.value
      };
      return createVNode(VTextField, mergeProps({
        "ref": vTextFieldRef
      }, textFieldProps, {
        "modelValue": search.value,
        "onUpdate:modelValue": $event => search.value = $event,
        "focused": isFocused.value,
        "onUpdate:focused": $event => isFocused.value = $event,
        "validationValue": model.externalValue,
        "counterValue": counterValue.value,
        "dirty": isDirty,
        "class": ['v-combobox', {
          'v-combobox--active-menu': menu.value,
          'v-combobox--chips': !!props.chips,
          'v-combobox--selection-slot': !!hasSelectionSlot.value,
          'v-combobox--selecting-index': selectionIndex.value > -1,
          [`v-combobox--${props.multiple ? 'multiple' : 'single'}`]: true
        }, props.class],
        "style": props.style,
        "readonly": form.isReadonly.value,
        "placeholder": isDirty ? undefined : props.placeholder,
        "onClick:clear": onClear,
        "onMousedown:control": onMousedownControl,
        "onKeydown": onKeydown,
        "onPaste": onPaste,
        "onBlur": onBlur,
        "aria-expanded": ariaExpanded.value,
        "aria-controls": ariaControls.value
      }), {
        ...slots,
        default: ({
          id
        }) => createElementVNode(Fragment, null, [createVNode(VMenu, mergeProps({
          "id": menuId.value,
          "ref": vMenuRef,
          "modelValue": menu.value,
          "onUpdate:modelValue": $event => menu.value = $event,
          "activator": "parent",
          "disabled": menuDisabled.value,
          "eager": props.eager,
          "maxHeight": 310,
          "openOnClick": false,
          "closeOnContentClick": false,
          "onAfterEnter": onAfterEnter,
          "onAfterLeave": onAfterLeave
        }, props.menuProps, {
          "contentClass": ['v-combobox__content', props.menuProps?.contentClass]
        }), {
          default: () => [createVNode(VSheet, {
            "elevation": props.menuElevation,
            "onFocusin": onFocusin,
            "onKeydown": onMenuKeydown,
            "onMousedown": onMousedownContent
          }, {
            default: () => [slots['menu-header'] && createElementVNode("header", {
              "ref": headerRef
            }, [slots['menu-header'](menuSlotProps)]), hasList && createVNode(VList, mergeProps({
              "key": "combobox-list",
              "ref": listRef,
              "filterable": true,
              "selected": selectedValues.value,
              "selectStrategy": props.multiple ? 'independent' : 'single-independent',
              "onMousedown": e => e.preventDefault(),
              "selectable": !!displayItems.value.length,
              "onFocusout": onFocusout,
              "tabindex": "-1",
              "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,
                    active: highlightFirst.value && item === firstSelectableItem.value ? true : undefined,
                    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, {
                      "ref": itemRef,
                      "key": `divider-${index}`
                    }), null);
                  }
                  if (item.type === 'subheader') {
                    return slots.subheader?.({
                      props: item.raw,
                      index
                    }) ?? createVNode(VListSubheader, mergeProps(item.props, {
                      "ref": itemRef,
                      "key": `subheader-${index}`
                    }), null);
                  }
                  return slots.item?.({
                    item: item.raw,
                    internalItem: item,
                    index,
                    props: itemProps
                  }) ?? createVNode(VListItem, mergeProps(itemProps, {
                    "role": "option"
                  }), {
                    prepend: ({
                      isSelected
                    }) => createElementVNode(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) : undefined, camelizedProps.prependAvatar && createVNode(VAvatar, {
                      "image": camelizedProps.prependAvatar
                    }, null), camelizedProps.prependIcon && createVNode(VIcon, {
                      "icon": camelizedProps.prependIcon
                    }, null)]),
                    title: () => {
                      return isPristine.value ? item.title : createVNode(VHighlight, {
                        "text": item.title,
                        "matches": getMatches(item)?.title,
                        "markClass": "v-combobox__mask",
                        "matchAll": true,
                        "ignoreCase": true
                      }, null);
                    }
                  });
                }
              }), slots['append-item']?.()]
            }), slots['menu-footer'] && createElementVNode("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': undefined
          });
          const hasSlot = hasChips.value ? !!slots.chip : !!slots.selection;
          const slotContent = hasSlot ? ensureValidVNode(hasChips.value ? slots.chip({
            item: item.raw,
            internalItem: item,
            index,
            props: slotProps
          }) : slots.selection({
            item: item.raw,
            internalItem: item,
            index
          })) : undefined;
          if (hasSlot && !slotContent) return undefined;
          return createElementVNode("div", {
            "key": item.value,
            "class": normalizeClass(['v-combobox__selection', index === selectionIndex.value && ['v-combobox__selection--selected', textColorClasses.value]]),
            "style": normalizeStyle(index === selectionIndex.value ? textColorStyles.value : {})
          }, [hasChips.value ? !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 ?? createElementVNode("span", {
            "class": "v-combobox__selection-text"
          }, [item.title, props.multiple && index < model.value.length - 1 && createElementVNode("span", {
            "class": "v-combobox__selection-comma"
          }, [createTextVNode(",")])])]);
        })]),
        'append-inner': (...args) => createElementVNode(Fragment, null, [slots['append-inner']?.(...args), (!props.hideNoData || props.items.length) && props.menuIcon ? createVNode(VIcon, {
          "class": "v-combobox__menu-icon",
          "color": vTextFieldRef.value?.fieldIconColor,
          "icon": props.menuIcon,
          "onMousedown": onMousedownMenuIcon,
          "onClick": noop,
          "aria-hidden": true,
          "tabindex": "-1"
        }, null) : undefined, props.appendInnerIcon && createVNode(InputIcon, {
          "key": "append-icon",
          "name": "appendInner",
          "color": args[0].iconColor.value
        }, null)])
      });
    });
    return forwardRefs({
      isFocused,
      isPristine,
      menu,
      search,
      selectionIndex,
      filteredItems,
      select
    }, vTextFieldRef);
  }
});

// Composables

// Types

const makeDataTableExpandProps = propsFactory({
  expandOnClick: Boolean,
  showExpand: Boolean,
  expanded: {
    type: Array,
    default: () => []
  },
  expandStrategy: {
    type: String,
    default: 'multiple'
  }
}, 'DataTable-expand');
const VDataTableExpandedKey = Symbol.for('vuetify:datatable:expanded');
function provideExpanded(props) {
  const expandOnClick = toRef(() => props.expandOnClick);
  const expanded = useProxiedModel(props, 'expanded', props.expanded, v => {
    return new Set(v);
  }, v => {
    return [...v.values()];
  });
  function expand(item, value) {
    const rawValue = toRaw(item.value);
    const newExpanded = value && props.expandStrategy === 'single' ? new Set() : new Set(expanded.value);
    if (!value) {
      const existing = [...expanded.value].find(x => toRaw(x) === rawValue);
      newExpanded.delete(existing);
    } else {
      newExpanded.add(item.value);
    }
    expanded.value = newExpanded;
  }
  function isExpanded(item) {
    const rawValue = toRaw(item.value);
    return [...expanded.value].some(x => toRaw(x) === rawValue);
  }
  function toggleExpand(item) {
    expand(item, !isExpanded(item));
  }
  const data = {
    expand,
    expanded,
    expandOnClick,
    isExpanded,
    toggleExpand
  };
  provide(VDataTableExpandedKey, data);
  return data;
}
function useExpanded() {
  const data = inject$1(VDataTableExpandedKey);
  if (!data) throw new Error('foo');
  return data;
}

// Composables

// Types

const makeDataTableGroupProps = propsFactory({
  groupBy: {
    type: Array,
    default: () => []
  },
  opened: {
    type: Array,
    default: () => []
  },
  openAll: Boolean,
  groupKey: Function
}, 'DataTable-group');
const VDataTableGroupSymbol = Symbol.for('vuetify:data-table-group');
function createGroupBy(props) {
  const groupBy = useProxiedModel(props, 'groupBy');
  const opened = useProxiedModel(props, 'opened');
  const openAll = toRef(() => props.openAll);
  const groupKey = toRef(() => props.groupKey);
  return {
    groupBy,
    opened,
    openAll,
    groupKey
  };
}
function provideGroupBy(options) {
  const {
    disableSort,
    groupBy,
    sortBy
  } = options;
  const openedModel = options.opened ?? ref([]);

  // Keep a Set mirror for O(1) lookups; the v-model carries the string[] form.
  const localOpened = shallowRef(new Set(openedModel.value));
  watch(openedModel, val => {
    localOpened.value = new Set(val);
  });
  const opened = computed({
    get: () => localOpened.value,
    set: v => {
      localOpened.value = v;
      openedModel.value = [...v.values()];
    }
  });
  const sortByWithGroups = computed(() => {
    return groupBy.value.map(val => ({
      ...val,
      order: val.order ?? false
    })).concat(disableSort?.value ? [] : sortBy.value);
  });
  function isGroupOpen(group) {
    return opened.value.has(group.id);
  }
  function toggleGroup(group) {
    const newOpened = new Set(opened.value);
    if (isGroupOpen(group)) newOpened.delete(group.id);else newOpened.add(group.id);
    opened.value = newOpened;
  }
  function extractRows(items) {
    function dive(group) {
      const arr = [];
      for (const item of group.items) {
        if ('type' in item && item.type === 'group') {
          arr.push(...dive(item));
        } else {
          arr.push(item);
        }
      }
      return [...new Set(arr)];
    }
    return dive({
      items});
  }
  const data = {
    sortByWithGroups,
    toggleGroup,
    opened,
    groupBy,
    extractRows,
    isGroupOpen
  };
  provide(VDataTableGroupSymbol, data);
  return data;
}
function useGroupBy() {
  const data = inject$1(VDataTableGroupSymbol);
  if (!data) throw new Error('Missing group!');
  return data;
}
function groupItemsByProperty(items, groupBy) {
  if (!items.length) return [];
  const groups = new Map();
  for (const item of items) {
    const value = getObjectValueByPath(item.raw, groupBy);
    if (!groups.has(value)) {
      groups.set(value, []);
    }
    groups.get(value).push(item);
  }
  return groups;
}
const defaultGroupId = (key, value, parentKey) => `${parentKey}_${key}_${value}`;
function groupItems(items, groupBy, groupKey, depth = 0, parentKey = 'root') {
  if (!groupBy.length) return [];
  const groupedItems = groupItemsByProperty(items, groupBy[0]);
  const groups = [];
  const rest = groupBy.slice(1);
  groupedItems.forEach((items, value) => {
    const key = groupBy[0];
    const id = groupKey ? groupKey({
      key,
      value,
      parentKey: depth === 0 ? null : parentKey
    }) : defaultGroupId(key, value, parentKey);
    groups.push({
      depth,
      id,
      key,
      value,
      items: rest.length ? groupItems(items, rest, groupKey, depth + 1, id) : items,
      type: 'group'
    });
  });
  return groups;
}
function collectGroupIds(groups) {
  return groups.flatMap(group => [group.id, ...collectGroupIds(group.items.filter(item => 'type' in item && item.type === 'group'))]);
}
function useOpenAllGroups(opened, openAll, items, groupBy, groupKey) {
  const allIds = computed(() => {
    if (!toValue(openAll) || !groupBy.value.length) return new Set();
    return new Set(collectGroupIds(groupItems(toValue(items), groupBy.value.map(group => group.key), toValue(groupKey))));
  });
  watch(allIds, (newIds, oldIds) => {
    if (!toValue(openAll)) return;
    const current = new Set(opened.value);
    let changed = false;
    for (const id of newIds) {
      if (!oldIds?.has(id) && !current.has(id)) {
        current.add(id);
        changed = true;
      }
    }
    for (const id of oldIds ?? []) {
      if (!newIds.has(id) && current.has(id)) {
        current.delete(id);
        changed = true;
      }
    }
    if (changed) opened.value = current;
  }, {
    immediate: true
  });
}
function flattenItems(items, isOpen, hasSummary) {
  const flatItems = [];
  for (const item of items) {
    // TODO: make this better
    if ('type' in item && item.type === 'group') {
      if (item.value != null) {
        flatItems.push(item);
      }
      if (isOpen(item) || item.value == null) {
        flatItems.push(...flattenItems(item.items, isOpen, hasSummary));
        if (hasSummary) {
          flatItems.push({
            ...item,
            type: 'group-summary'
          });
        }
      }
    } else {
      flatItems.push(item);
    }
  }
  return flatItems;
}
function useGroupedItems(items, groupBy, opened, hasSummary, isGroupOpen, groupKey) {
  const groups = computed(() => {
    if (!groupBy.value.length) return [];
    return groupItems(toValue(items), groupBy.value.map(item => item.key), toValue(groupKey));
  });
  const isOpen = isGroupOpen ?? (group => opened.value.has(group.id));
  const flatItems = computed(() => {
    if (!groupBy.value.length) return toValue(items);
    return flattenItems(groups.value, isOpen, toValue(hasSummary));
  });
  return {
    groups,
    flatItems
  };
}

// Utilities

// Types

function useOptions({
  page,
  itemsPerPage,
  sortBy,
  groupBy,
  search
}) {
  const vm = getCurrentInstance('VDataTable');
  const options = () => ({
    page: page.value,
    itemsPerPage: itemsPerPage.value,
    sortBy: sortBy.value,
    groupBy: groupBy.value,
    search: search.value
  });
  let oldOptions = null;
  watch(options, value => {
    if (deepEqual(oldOptions, value)) return;

    // Reset page when searching
    if (oldOptions && oldOptions.search !== value.search) {
      page.value = 1;
    }
    vm.emit('update:options', value);
    oldOptions = value;
  }, {
    deep: true,
    immediate: true
  });
}

// Composables

// Types

const makeDataTablePaginateProps = propsFactory({
  page: {
    type: [Number, String],
    default: 1
  },
  itemsPerPage: {
    type: [Number, String],
    default: 10
  },
  pageBy: {
    type: String,
    default: 'any'
  }
}, 'DataTable-paginate');
const VDataTablePaginationSymbol = Symbol.for('vuetify:data-table-pagination');
function createPagination(props) {
  const page = useProxiedModel(props, 'page', undefined, value => Number(value ?? 1));
  const itemsPerPage = useProxiedModel(props, 'itemsPerPage', undefined, value => Number(value ?? 10));
  return {
    page,
    itemsPerPage
  };
}
function providePagination(options) {
  const {
    page,
    itemsPerPage,
    itemsLength
  } = options;
  const startIndex = computed(() => {
    if (itemsPerPage.value === -1) return 0;
    return itemsPerPage.value * (page.value - 1);
  });
  const stopIndex = computed(() => {
    if (itemsPerPage.value === -1) return itemsLength.value;
    return Math.min(itemsLength.value, startIndex.value + itemsPerPage.value);
  });
  const pageCount = computed(() => {
    if (itemsPerPage.value === -1 || itemsLength.value === 0) return 1;
    return Math.ceil(itemsLength.value / itemsPerPage.value);
  });

  // Don't run immediately, items may not have been loaded yet: #17966
  watch([page, pageCount], () => {
    if (page.value > pageCount.value) {
      page.value = pageCount.value;
    }
  });
  function setItemsPerPage(value) {
    itemsPerPage.value = value;
    page.value = 1;
  }
  function nextPage() {
    page.value = clamp(page.value + 1, 1, pageCount.value);
  }
  function prevPage() {
    page.value = clamp(page.value - 1, 1, pageCount.value);
  }
  function setPage(value) {
    page.value = clamp(value, 1, pageCount.value);
  }
  const data = {
    page,
    itemsPerPage,
    startIndex,
    stopIndex,
    pageCount,
    itemsLength,
    nextPage,
    prevPage,
    setPage,
    setItemsPerPage
  };
  provide(VDataTablePaginationSymbol, data);
  return data;
}
function usePagination() {
  const data = inject$1(VDataTablePaginationSymbol);
  if (!data) throw new Error('Missing pagination!');
  return data;
}
function usePaginatedItems(options) {
  const vm = getCurrentInstance('usePaginatedItems');
  const {
    items,
    startIndex,
    stopIndex,
    itemsPerPage
  } = options;
  const paginatedItems = computed(() => {
    if (itemsPerPage.value <= 0) return toValue(items);
    return toValue(items).slice(startIndex.value, stopIndex.value);
  });
  watch(paginatedItems, val => {
    vm.emit('update:currentItems', val);
  }, {
    immediate: true
  });
  return {
    paginatedItems
  };
}
function usePaginatedGroups(options) {
  const {
    sortedItems,
    paginate,
    group
  } = options;
  const pageBy = toValue(options.pageBy); // TODO: make reactive

  if (pageBy === 'item') {
    const {
      paginatedItems,
      pageCount,
      setItemsPerPage,
      prevPage,
      nextPage,
      setPage
    } = paginate(sortedItems);
    const {
      flatItems: paginatedItemsWithGroups
    } = group(paginatedItems);
    return {
      pageCount,
      setItemsPerPage,
      prevPage,
      nextPage,
      setPage,
      paginatedItems: paginatedItemsWithGroups
    };
  }
  if (pageBy === 'group') {
    const {
      flatItems,
      groups
    } = group(sortedItems);
    const {
      paginatedItems: paginatedGroups,
      pageCount,
      setItemsPerPage,
      prevPage,
      nextPage,
      setPage
    } = paginate(groups);
    const paginatedItemsWithGroups = computed(() => {
      if (!paginatedGroups.value.length) return [];
      const firstGroupId = paginatedGroups.value.at(0).id;
      const lastGroupId = paginatedGroups.value.at(-1).id;
      const start = flatItems.value.findIndex(item => item.type === 'group' && item.id === firstGroupId);
      const lastGroupIndex = flatItems.value.findIndex(item => item.type === 'group' && item.id === lastGroupId);
      const stop = flatItems.value.findIndex((item, i) => i > lastGroupIndex && item.type === 'group' && item.depth === 0);
      return flatItems.value.slice(start, stop === -1 ? undefined : stop);
    });
    return {
      pageCount,
      setItemsPerPage,
      prevPage,
      nextPage,
      setPage,
      paginatedItems: paginatedItemsWithGroups
    };
  }
  if (pageBy === 'any') {
    const {
      flatItems
    } = group(sortedItems);
    const {
      paginatedItems: paginatedItemsWithGroups,
      pageCount,
      setItemsPerPage,
      prevPage,
      nextPage,
      setPage
    } = paginate(flatItems);
    return {
      pageCount,
      setItemsPerPage,
      prevPage,
      nextPage,
      setPage,
      paginatedItems: paginatedItemsWithGroups
    };
  }
  throw new Error(`Unrecognized pagination target ${pageBy}`);
}

// Composables

// Types

const singleSelectStrategy = {
  showSelectAll: false,
  allSelected: () => [],
  select: ({
    items,
    value
  }) => {
    return new Set(value ? [items[0]?.value] : []);
  },
  selectAll: ({
    selected
  }) => selected
};
const pageSelectStrategy = {
  showSelectAll: true,
  allSelected: ({
    currentPage
  }) => currentPage,
  select: ({
    items,
    value,
    selected
  }) => {
    for (const item of items) {
      if (value) selected.add(item.value);else selected.delete(item.value);
    }
    return selected;
  },
  selectAll: ({
    value,
    currentPage,
    selected
  }) => pageSelectStrategy.select({
    items: currentPage,
    value,
    selected
  })
};
const allSelectStrategy = {
  showSelectAll: true,
  allSelected: ({
    allItems
  }) => allItems,
  select: ({
    items,
    value,
    selected
  }) => {
    for (const item of items) {
      if (value) selected.add(item.value);else selected.delete(item.value);
    }
    return selected;
  },
  selectAll: ({
    value,
    allItems
  }) => {
    return new Set(value ? allItems.map(item => item.value) : []);
  }
};
const makeDataTableSelectProps = propsFactory({
  showSelect: Boolean,
  selectStrategy: {
    type: [String, Object],
    default: 'page'
  },
  modelValue: {
    type: Array,
    default: () => []
  },
  valueComparator: Function
}, 'DataTable-select');
const VDataTableSelectionSymbol = Symbol.for('vuetify:data-table-selection');
function provideSelection(props, {
  allItems,
  currentPage
}) {
  const selected = useProxiedModel(props, 'modelValue', props.modelValue, v => {
    const customComparator = props.valueComparator;
    if (customComparator) {
      return new Set(wrapInArray(v).map(v => {
        return allItems.value.find(item => customComparator(v, item.value))?.value ?? v;
      }));
    }
    return new Set(wrapInArray(v).map(v => {
      return isPrimitive(v) ? allItems.value.find(item => v === item.value)?.value ?? v : allItems.value.find(item => deepEqual(v, item.value))?.value ?? v;
    }));
  }, v => {
    return [...v.values()];
  });
  const allSelectable = computed(() => allItems.value.filter(item => item.selectable));
  const currentPageSelectable = computed(() => toValue(currentPage).filter(item => item.selectable));
  const selectStrategy = computed(() => {
    if (typeof props.selectStrategy === 'object') return props.selectStrategy;
    switch (props.selectStrategy) {
      case 'single':
        return singleSelectStrategy;
      case 'all':
        return allSelectStrategy;
      case 'page':
      default:
        return pageSelectStrategy;
    }
  });
  const lastSelectedIndex = shallowRef(null);
  function isSelected(items) {
    return wrapInArray(items).every(item => selected.value.has(item.value));
  }
  function isSomeSelected(items) {
    return wrapInArray(items).some(item => selected.value.has(item.value));
  }
  function select(items, value) {
    const newSelected = selectStrategy.value.select({
      items,
      value,
      selected: new Set(selected.value)
    });
    selected.value = newSelected;
  }
  function toggleSelect(item, index, event) {
    const items = [];
    const pageItems = toValue(currentPage);
    index = index ?? pageItems.findIndex(i => i.value === item.value);
    if (props.selectStrategy !== 'single' && event?.shiftKey && lastSelectedIndex.value !== null) {
      const [start, end] = [lastSelectedIndex.value, index].sort((a, b) => a - b);
      items.push(...pageItems.slice(start, end + 1).filter(item => item.selectable));
    } else {
      items.push(item);
      lastSelectedIndex.value = index;
    }
    select(items, !isSelected([item]));
  }
  function selectAll(value) {
    const newSelected = selectStrategy.value.selectAll({
      value,
      allItems: allSelectable.value,
      currentPage: currentPageSelectable.value,
      selected: new Set(selected.value)
    });
    selected.value = newSelected;
  }
  const someSelected = computed(() => selected.value.size > 0);
  const allSelected = computed(() => {
    const items = selectStrategy.value.allSelected({
      allItems: allSelectable.value,
      currentPage: currentPageSelectable.value
    });
    return !!items.length && isSelected(items);
  });
  const showSelectAll = toRef(() => selectStrategy.value.showSelectAll);
  const data = {
    toggleSelect,
    select,
    selectAll,
    isSelected,
    isSomeSelected,
    someSelected,
    allSelected,
    showSelectAll,
    lastSelectedIndex,
    selectStrategy
  };
  provide(VDataTableSelectionSymbol, data);
  return data;
}
function useSelection() {
  const data = inject$1(VDataTableSelectionSymbol);
  if (!data) throw new Error('Missing selection!');
  return data;
}

// Composables

// Types

const makeDataTableSortProps = propsFactory({
  initialSortOrder: {
    type: String,
    default: 'asc',
    validator: v => !v || ['asc', 'desc'].includes(v)
  },
  sortBy: {
    type: Array,
    default: () => []
  },
  customKeySort: Object,
  multiSort: {
    type: [Boolean, Object],
    default: false
  },
  mustSort: Boolean
}, 'DataTable-sort');
const VDataTableSortSymbol = Symbol.for('vuetify:data-table-sort');
function createSort(props) {
  const initialSortOrder = toRef(() => props.initialSortOrder);
  const sortBy = useProxiedModel(props, 'sortBy');
  const mustSort = toRef(() => props.mustSort);
  const multiSort = toRef(() => props.multiSort);
  return {
    initialSortOrder,
    sortBy,
    multiSort,
    mustSort
  };
}
function resolveMultiSort(multiSort, event) {
  if (!isObject(multiSort)) {
    return {
      active: !!multiSort
    };
  }
  const {
    key,
    mode,
    modifier
  } = multiSort;
  const reverseMode = modifier === 'alt' && event?.altKey || modifier === 'shift' && event?.shiftKey;
  return {
    active: !key || event?.ctrlKey || event?.metaKey || false,
    mode: reverseMode ? mode === 'append' ? 'prepend' : 'append' : mode
  };
}
function provideSort(options) {
  const {
    initialSortOrder,
    sortBy,
    mustSort,
    multiSort,
    page
  } = options;
  const toggleSort = (column, event, mandatory = false) => {
    if (column.key == null) return;
    let newSortBy = sortBy.value.map(x => ({
      ...x
    })) ?? [];
    const item = newSortBy.find(x => x.key === column.key);
    const initialOrder = initialSortOrder.value;
    const secondaryOrder = initialSortOrder.value === 'desc' ? 'asc' : 'desc';
    if (!item) {
      const {
        active,
        mode
      } = resolveMultiSort(multiSort.value, event);
      if (active) {
        if (mode === 'prepend') {
          newSortBy.unshift({
            key: column.key,
            order: initialOrder
          });
        } else {
          newSortBy.push({
            key: column.key,
            order: initialOrder
          });
        }
      } else {
        newSortBy = [{
          key: column.key,
          order: initialOrder
        }];
      }
    } else if (item.order === secondaryOrder) {
      if (mandatory || mustSort.value && newSortBy.length === 1) {
        item.order = initialSortOrder.value;
      } else {
        newSortBy = newSortBy.filter(x => x.key !== column.key);
      }
    } else {
      item.order = secondaryOrder;
    }
    sortBy.value = newSortBy;
    if (page) page.value = 1;
  };
  function isSorted(column) {
    return !!sortBy.value.find(item => item.key === column.key);
  }
  const data = {
    sortBy,
    toggleSort,
    isSorted
  };
  provide(VDataTableSortSymbol, data);
  return data;
}
function useSort() {
  const data = inject$1(VDataTableSortSymbol);
  if (!data) throw new Error('Missing sort!');
  return data;
}

// TODO: abstract into project composable
function useSortedItems(props, items, sortBy, options) {
  const locale = useLocale();
  const sortedItems = computed(() => {
    if (!sortBy.value.length) return items.value;
    return sortItems(items.value, sortBy.value, locale.current.value, {
      transform: options?.transform,
      sortFunctions: {
        ...props.customKeySort,
        ...options?.sortFunctions?.value
      },
      sortRawFunctions: options?.sortRawFunctions?.value
    });
  });
  return {
    sortedItems
  };
}
function sortItems(items, sortByItems, locale, options) {
  const stringCollator = new Intl.Collator(locale, {
    sensitivity: 'accent',
    usage: 'sort'
  });
  const transformedItems = items.map(item => [item, options?.transform ? options.transform(item) : item]);
  return transformedItems.sort((a, b) => {
    for (let i = 0; i < sortByItems.length; i++) {
      let hasCustomResult = false;
      const sortKey = sortByItems[i].key;
      const sortOrder = sortByItems[i].order ?? 'asc';
      if (sortOrder === false) continue;
      let sortA = getObjectValueByPath(a[1], sortKey);
      let sortB = getObjectValueByPath(b[1], sortKey);
      let sortARaw = a[0].raw;
      let sortBRaw = b[0].raw;
      if (sortOrder === 'desc') {
        [sortA, sortB] = [sortB, sortA];
        [sortARaw, sortBRaw] = [sortBRaw, sortARaw];
      }
      if (options?.sortRawFunctions?.[sortKey]) {
        const customResult = options.sortRawFunctions[sortKey](sortARaw, sortBRaw);
        if (customResult == null) continue;
        hasCustomResult = true;
        if (customResult) return customResult;
      }
      if (options?.sortFunctions?.[sortKey]) {
        const customResult = options.sortFunctions[sortKey](sortA, sortB);
        if (customResult == null) continue;
        hasCustomResult = true;
        if (customResult) return customResult;
      }
      if (hasCustomResult) continue;

      // Dates should be compared numerically
      if (sortA instanceof Date && sortB instanceof Date) {
        sortA = sortA.getTime();
        sortB = sortB.getTime();
      }
      [sortA, sortB] = [sortA, sortB].map(s => s != null ? s.toString().toLocaleLowerCase() : s);
      if (sortA !== sortB) {
        if (isEmpty(sortA) && isEmpty(sortB)) return 0;
        if (isEmpty(sortA)) return -1;
        if (isEmpty(sortB)) return 1;
        if (!isNaN(sortA) && !isNaN(sortB)) return Number(sortA) - Number(sortB);
        return stringCollator.compare(sortA, sortB);
      }
    }
    return 0;
  }).map(([item]) => item);
}

// Utilities

// Types

// Composables
const makeDataIteratorItemsProps = propsFactory({
  items: {
    type: Array,
    default: () => []
  },
  itemValue: {
    type: [String, Array, Function],
    default: 'id'
  },
  itemSelectable: {
    type: [String, Array, Function],
    default: null
  },
  returnObject: Boolean
}, 'DataIterator-items');
function transformItem$1(props, item) {
  const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue);
  const selectable = getPropertyFromItem(item, props.itemSelectable, true);
  return {
    type: 'item',
    value,
    selectable,
    raw: item
  };
}
function transformItems$1(props, items) {
  const array = [];
  for (const item of items) {
    array.push(transformItem$1(props, item));
  }
  return array;
}
function useDataIteratorItems(props) {
  const items = computed(() => transformItems$1(props, props.items));
  return {
    items
  };
}

// Types

const makeVDataIteratorProps = propsFactory({
  search: String,
  loading: Boolean,
  itemsLength: [Number, String],
  ...makeComponentProps(),
  ...makeDataIteratorItemsProps(),
  ...makeDataTableSelectProps(),
  ...makeDataTableSortProps(),
  ...makeDataTablePaginateProps({
    itemsPerPage: 5
  }),
  ...makeDataTableExpandProps(),
  ...makeDataTableGroupProps(),
  ...makeFilterProps(),
  ...makeTagProps(),
  ...makeTransitionProps({
    transition: {
      component: VFadeTransition,
      hideOnLeave: true
    }
  })
}, 'VDataIterator');
const VDataIterator = genericComponent()({
  name: 'VDataIterator',
  props: makeVDataIteratorProps(),
  emits: {
    'update:modelValue': value => true,
    'update:groupBy': value => true,
    'update:page': value => true,
    'update:itemsPerPage': value => true,
    'update:sortBy': value => true,
    'update:options': value => true,
    'update:expanded': value => true,
    'update:opened': value => true,
    'update:currentItems': value => true
  },
  setup(props, {
    slots
  }) {
    const {
      groupBy,
      opened,
      openAll,
      groupKey
    } = createGroupBy(props);
    const search = toRef(() => props.search);
    const {
      items
    } = useDataIteratorItems(props);
    const {
      filteredItems
    } = useFilter(props, items, search, {
      transform: item => item.raw
    });
    const {
      initialSortOrder,
      sortBy,
      multiSort,
      mustSort
    } = createSort(props);
    const {
      page,
      itemsPerPage
    } = createPagination(props);
    const {
      toggleSort
    } = provideSort({
      initialSortOrder,
      sortBy,
      multiSort,
      mustSort,
      page
    });
    const {
      sortByWithGroups,
      opened: openedGroups,
      extractRows,
      isGroupOpen,
      toggleGroup
    } = provideGroupBy({
      groupBy,
      sortBy,
      opened
    });
    const {
      sortedItems
    } = useSortedItems(props, filteredItems, sortByWithGroups, {
      transform: item => item.raw
    });
    useOpenAllGroups(openedGroups, openAll, sortedItems, groupBy, groupKey);
    const {
      flatItems
    } = useGroupedItems(sortedItems, groupBy, openedGroups, false, isGroupOpen, groupKey);
    const manualPagination = toRef(() => !isEmpty(props.itemsLength));
    const itemsLength = toRef(() => manualPagination.value ? Number(props.itemsLength) : flatItems.value.length);
    const {
      startIndex,
      stopIndex,
      pageCount,
      prevPage,
      nextPage,
      setItemsPerPage,
      setPage
    } = providePagination({
      page,
      itemsPerPage,
      itemsLength
    });
    const paginatedItems = shallowRef([]);
    const currentItems = computed(() => manualPagination.value ? flatItems.value : paginatedItems.value);
    useToggleScope(() => !manualPagination.value, () => {
      const {
        paginatedItems: items
      } = usePaginatedItems({
        items: flatItems,
        startIndex,
        stopIndex,
        itemsPerPage
      });
      watchEffect(() => {
        paginatedItems.value = items.value;
      });
    });
    const currentItemsWithoutGroups = computed(() => extractRows(currentItems.value));
    const {
      isSelected,
      select,
      selectAll,
      toggleSelect
    } = provideSelection(props, {
      allItems: items,
      currentPage: currentItemsWithoutGroups
    });
    const {
      isExpanded,
      toggleExpand
    } = provideExpanded(props);
    useOptions({
      page,
      itemsPerPage,
      sortBy,
      groupBy,
      search
    });
    const slotProps = computed(() => ({
      page: page.value,
      itemsPerPage: itemsPerPage.value,
      sortBy: sortBy.value,
      pageCount: pageCount.value,
      toggleSort,
      prevPage,
      nextPage,
      setPage,
      setItemsPerPage,
      isSelected,
      select,
      selectAll,
      toggleSelect,
      isExpanded,
      toggleExpand,
      isGroupOpen,
      toggleGroup,
      items: currentItemsWithoutGroups.value,
      itemsCount: filteredItems.value.length,
      groupedItems: currentItems.value
    }));
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-data-iterator', {
        'v-data-iterator--loading': props.loading
      }, props.class]),
      "style": normalizeStyle(props.style)
    }, {
      default: () => [slots.header?.(slotProps.value), createVNode(MaybeTransition, {
        "transition": props.transition
      }, {
        default: () => [props.loading ? createVNode(LoaderSlot, {
          "key": "loader",
          "name": "v-data-iterator",
          "active": true
        }, {
          default: slotProps => slots.loader?.(slotProps)
        }) : createElementVNode("div", {
          "key": "items"
        }, [!currentItems.value.length ? slots['no-data']?.() : slots.default?.(slotProps.value)])]
      }), slots.footer?.(slotProps.value)]
    }));
    return {};
  }
});

// Utilities

// Types

function useRefs() {
  const refs = ref([]);
  onBeforeUpdate(() => refs.value = []);
  function updateRef(e, i) {
    refs.value[i] = e;
  }
  return {
    refs,
    updateRef
  };
}

// Types

const makeVPaginationProps = propsFactory({
  activeColor: String,
  start: {
    type: [Number, String],
    default: 1
  },
  modelValue: {
    type: Number,
    default: props => props.start
  },
  disabled: Boolean,
  length: {
    type: [Number, String],
    default: 1,
    validator: val => val % 1 === 0
  },
  totalVisible: [Number, String],
  firstIcon: {
    type: IconValue,
    default: '$first'
  },
  prevIcon: {
    type: IconValue,
    default: '$prev'
  },
  nextIcon: {
    type: IconValue,
    default: '$next'
  },
  lastIcon: {
    type: IconValue,
    default: '$last'
  },
  ariaLabel: {
    type: String,
    default: '$vuetify.pagination.ariaLabel.root'
  },
  pageAriaLabel: {
    type: String,
    default: '$vuetify.pagination.ariaLabel.page'
  },
  currentPageAriaLabel: {
    type: String,
    default: '$vuetify.pagination.ariaLabel.currentPage'
  },
  firstAriaLabel: {
    type: String,
    default: '$vuetify.pagination.ariaLabel.first'
  },
  previousAriaLabel: {
    type: String,
    default: '$vuetify.pagination.ariaLabel.previous'
  },
  nextAriaLabel: {
    type: String,
    default: '$vuetify.pagination.ariaLabel.next'
  },
  lastAriaLabel: {
    type: String,
    default: '$vuetify.pagination.ariaLabel.last'
  },
  ellipsis: {
    type: String,
    default: '...'
  },
  showFirstLastPage: {
    type: [Boolean, String],
    default: false
  },
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeElevationProps(),
  ...makeRoundedProps(),
  ...makeSizeProps(),
  ...makeTagProps({
    tag: 'nav'
  }),
  ...makeThemeProps(),
  ...makeVariantProps({
    variant: 'text'
  })
}, 'VPagination');
const VPagination = genericComponent()({
  name: 'VPagination',
  props: makeVPaginationProps(),
  emits: {
    'update:modelValue': value => true,
    first: value => true,
    prev: value => true,
    next: value => true,
    last: value => true
  },
  setup(props, {
    slots,
    emit
  }) {
    const page = useProxiedModel(props, 'modelValue');
    const {
      t,
      n
    } = useLocale();
    const {
      isRtl
    } = useRtl();
    const {
      themeClasses
    } = provideTheme(props);
    const {
      width
    } = useDisplay();
    const maxButtons = shallowRef(-1);
    provideDefaults(undefined, {
      scoped: true
    });
    const {
      resizeRef
    } = useResizeObserver(entries => {
      if (!entries.length) return;
      const {
        target,
        contentRect
      } = entries[0];
      const firstItem = target.querySelector('.v-pagination__list > *');
      if (!firstItem) return;
      const totalWidth = contentRect.width;
      const itemWidth = firstItem.offsetWidth + parseFloat(getComputedStyle(firstItem).marginRight) * 2;
      maxButtons.value = getMax(totalWidth, itemWidth);
    });
    const length = computed(() => parseInt(props.length, 10));
    const start = computed(() => parseInt(props.start, 10));
    const totalVisible = computed(() => {
      if (props.totalVisible != null) return parseInt(props.totalVisible, 10);else if (maxButtons.value >= 0) return maxButtons.value;
      return getMax(width.value, 58);
    });
    function getMax(totalWidth, itemWidth) {
      const minButtons = props.showFirstLastPage ? 5 : 3;
      return Math.max(0, Math.floor(
      // Round to two decimal places to avoid floating point errors
      Number(((totalWidth - itemWidth * minButtons) / itemWidth).toFixed(2))));
    }
    const range = computed(() => {
      if (length.value <= 0 || isNaN(length.value) || length.value > Number.MAX_SAFE_INTEGER) return [];
      if (props.totalVisible == null && length.value < 3) {
        return createRange(length.value, start.value);
      }
      if (totalVisible.value <= 0) return [];else if (totalVisible.value === 1) return [page.value];
      if (length.value <= totalVisible.value) {
        return createRange(length.value, start.value);
      }
      const even = totalVisible.value % 2 === 0;
      const middle = even ? totalVisible.value / 2 : Math.floor(totalVisible.value / 2);
      const left = even ? middle : middle + 1;
      const right = length.value - middle;
      if (left - page.value >= 0) {
        return [...createRange(Math.max(1, totalVisible.value - 1), start.value), props.ellipsis, length.value];
      } else if (page.value - right >= (even ? 1 : 0)) {
        const rangeLength = totalVisible.value - 1;
        const rangeStart = length.value - rangeLength + start.value;
        return [start.value, props.ellipsis, ...createRange(rangeLength, rangeStart)];
      } else {
        const rangeLength = Math.max(1, totalVisible.value - 2);
        const rangeStart = rangeLength === 1 ? page.value : page.value - Math.ceil(rangeLength / 2) + start.value;
        return [start.value, props.ellipsis, ...createRange(rangeLength, rangeStart), props.ellipsis, length.value];
      }
    });

    // TODO: 'first' | 'prev' | 'next' | 'last' does not work here?
    function setValue(e, value, event) {
      e.preventDefault();
      page.value = value;
      event && emit(event, value);
    }
    const {
      refs,
      updateRef
    } = useRefs();
    provideDefaults({
      VPaginationBtn: {
        color: toRef(() => props.color),
        border: toRef(() => props.border),
        density: toRef(() => props.density),
        size: toRef(() => props.size),
        variant: toRef(() => props.variant),
        rounded: toRef(() => props.rounded),
        elevation: toRef(() => props.elevation)
      }
    });
    const items = computed(() => {
      return range.value.map((item, index) => {
        const ref = e => updateRef(e, index);
        if (typeof item === 'string') {
          return {
            isActive: false,
            key: `ellipsis-${index}`,
            page: item,
            props: {
              ref,
              ellipsis: true,
              icon: true,
              disabled: true
            }
          };
        } else {
          const isActive = item === page.value;
          return {
            isActive,
            key: item,
            page: n(item),
            props: {
              ref,
              ellipsis: false,
              icon: true,
              disabled: !!props.disabled || Number(props.length) < 2,
              color: isActive ? props.activeColor : props.color,
              'aria-current': isActive,
              'aria-label': t(isActive ? props.currentPageAriaLabel : props.pageAriaLabel, item),
              onClick: e => setValue(e, item)
            }
          };
        }
      });
    });
    const controls = computed(() => {
      const prevDisabled = !!props.disabled || page.value <= start.value;
      const nextDisabled = !!props.disabled || page.value >= start.value + length.value - 1;
      return {
        first: [true, 'only-first'].includes(props.showFirstLastPage) ? {
          icon: isRtl.value ? props.lastIcon : props.firstIcon,
          onClick: e => setValue(e, start.value, 'first'),
          disabled: prevDisabled,
          'aria-label': t(props.firstAriaLabel),
          'aria-disabled': prevDisabled
        } : undefined,
        prev: {
          icon: isRtl.value ? props.nextIcon : props.prevIcon,
          onClick: e => setValue(e, page.value - 1, 'prev'),
          disabled: prevDisabled,
          'aria-label': t(props.previousAriaLabel),
          'aria-disabled': prevDisabled
        },
        next: {
          icon: isRtl.value ? props.prevIcon : props.nextIcon,
          onClick: e => setValue(e, page.value + 1, 'next'),
          disabled: nextDisabled,
          'aria-label': t(props.nextAriaLabel),
          'aria-disabled': nextDisabled
        },
        last: props.showFirstLastPage === true ? {
          icon: isRtl.value ? props.firstIcon : props.lastIcon,
          onClick: e => setValue(e, start.value + length.value - 1, 'last'),
          disabled: nextDisabled,
          'aria-label': t(props.lastAriaLabel),
          'aria-disabled': nextDisabled
        } : undefined
      };
    });
    function updateFocus() {
      const currentIndex = page.value - start.value;
      refs.value[currentIndex]?.$el.focus();
    }
    function onKeydown(e) {
      if (e.key === keyValues.left && !props.disabled && page.value > Number(props.start)) {
        page.value = page.value - 1;
        nextTick(updateFocus);
      } else if (e.key === keyValues.right && !props.disabled && page.value < start.value + length.value - 1) {
        page.value = page.value + 1;
        nextTick(updateFocus);
      }
    }
    useRender(() => createVNode(props.tag, {
      "ref": resizeRef,
      "class": normalizeClass(['v-pagination', themeClasses.value, props.class]),
      "style": normalizeStyle(props.style),
      "role": "navigation",
      "aria-label": t(props.ariaLabel),
      "onKeydown": onKeydown,
      "data-testid": "v-pagination-root"
    }, {
      default: () => [createElementVNode("ul", {
        "class": "v-pagination__list"
      }, [[true, 'only-first'].includes(props.showFirstLastPage) && createElementVNode("li", {
        "key": "first",
        "class": "v-pagination__first",
        "data-testid": "v-pagination-first"
      }, [slots.first ? slots.first(controls.value.first) : createVNode(VBtn, mergeProps({
        "_as": "VPaginationBtn"
      }, controls.value.first), null)]), createElementVNode("li", {
        "key": "prev",
        "class": "v-pagination__prev",
        "data-testid": "v-pagination-prev"
      }, [slots.prev ? slots.prev(controls.value.prev) : createVNode(VBtn, mergeProps({
        "_as": "VPaginationBtn"
      }, controls.value.prev), null)]), items.value.map((item, index) => createElementVNode("li", {
        "key": item.key,
        "class": normalizeClass(['v-pagination__item', {
          'v-pagination__item--is-active': item.isActive
        }]),
        "data-testid": "v-pagination-item"
      }, [slots.item ? slots.item(item) : createVNode(VBtn, mergeProps({
        "_as": "VPaginationBtn"
      }, item.props), {
        default: () => [item.page]
      })])), createElementVNode("li", {
        "key": "next",
        "class": "v-pagination__next",
        "data-testid": "v-pagination-next"
      }, [slots.next ? slots.next(controls.value.next) : createVNode(VBtn, mergeProps({
        "_as": "VPaginationBtn"
      }, controls.value.next), null)]), props.showFirstLastPage === true && createElementVNode("li", {
        "key": "last",
        "class": "v-pagination__last",
        "data-testid": "v-pagination-last"
      }, [slots.last ? slots.last(controls.value.last) : createVNode(VBtn, mergeProps({
        "_as": "VPaginationBtn"
      }, controls.value.last), null)])])]
    }));
    return {};
  }
});

const makeVDataTableFooterProps = propsFactory({
  color: String,
  prevIcon: {
    type: IconValue,
    default: '$prev'
  },
  nextIcon: {
    type: IconValue,
    default: '$next'
  },
  firstIcon: {
    type: IconValue,
    default: '$first'
  },
  lastIcon: {
    type: IconValue,
    default: '$last'
  },
  itemsPerPageText: {
    type: String,
    default: '$vuetify.dataFooter.itemsPerPageText'
  },
  pageText: {
    type: String,
    default: '$vuetify.dataFooter.pageText'
  },
  firstPageLabel: {
    type: String,
    default: '$vuetify.dataFooter.firstPage'
  },
  prevPageLabel: {
    type: String,
    default: '$vuetify.dataFooter.prevPage'
  },
  nextPageLabel: {
    type: String,
    default: '$vuetify.dataFooter.nextPage'
  },
  lastPageLabel: {
    type: String,
    default: '$vuetify.dataFooter.lastPage'
  },
  itemsPerPageOptions: {
    type: Array,
    default: () => [{
      value: 10,
      title: '10'
    }, {
      value: 25,
      title: '25'
    }, {
      value: 50,
      title: '50'
    }, {
      value: 100,
      title: '100'
    }, {
      value: -1,
      title: '$vuetify.dataFooter.itemsPerPageAll'
    }]
  },
  showCurrentPage: Boolean,
  ...pick(makeVPaginationProps({
    showFirstLastPage: true
  }), ['showFirstLastPage'])
}, 'VDataTableFooter');
const VDataTableFooter = genericComponent()({
  name: 'VDataTableFooter',
  props: makeVDataTableFooterProps(),
  setup(props, {
    slots
  }) {
    const {
      t
    } = useLocale();
    const {
      page,
      pageCount,
      startIndex,
      stopIndex,
      itemsLength,
      itemsPerPage,
      setItemsPerPage
    } = usePagination();
    const itemsPerPageOptions = computed(() => props.itemsPerPageOptions.map(option => {
      if (typeof option === 'number') {
        return {
          value: option,
          title: option === -1 ? t('$vuetify.dataFooter.itemsPerPageAll') : String(option)
        };
      }
      return {
        ...option,
        title: !isNaN(Number(option.title)) ? option.title : t(option.title)
      };
    }));
    useRender(() => {
      const paginationProps = VPagination.filterProps(props);
      return createElementVNode("div", {
        "class": "v-data-table-footer"
      }, [slots.prepend?.(), createElementVNode("div", {
        "class": "v-data-table-footer__items-per-page"
      }, [createElementVNode("span", null, [t(props.itemsPerPageText)]), createVNode(VSelect, {
        "items": itemsPerPageOptions.value,
        "itemColor": props.color,
        "modelValue": itemsPerPage.value,
        "onUpdate:modelValue": v => setItemsPerPage(Number(v)),
        "density": "compact",
        "variant": "outlined",
        "aria-label": t(props.itemsPerPageText),
        "hideDetails": true
      }, null)]), createElementVNode("div", {
        "class": "v-data-table-footer__info"
      }, [createElementVNode("div", null, [t(props.pageText, !itemsLength.value ? 0 : startIndex.value + 1, stopIndex.value, itemsLength.value)])]), createElementVNode("div", {
        "class": "v-data-table-footer__pagination"
      }, [createVNode(VPagination, mergeProps({
        "modelValue": page.value,
        "onUpdate:modelValue": $event => page.value = $event,
        "density": "comfortable",
        "firstAriaLabel": props.firstPageLabel,
        "lastAriaLabel": props.lastPageLabel,
        "length": pageCount.value,
        "nextAriaLabel": props.nextPageLabel,
        "previousAriaLabel": props.prevPageLabel,
        "rounded": true,
        "showFirstLastPage": true,
        "totalVisible": props.showCurrentPage ? 1 : 0,
        "variant": "plain"
      }, omit(paginationProps, ['color'])), null)])]);
    });
    return {};
  }
});

// Types

const VDataTableColumn = defineFunctionalComponent({
  align: {
    type: String,
    default: 'start'
  },
  fixed: {
    type: [Boolean, String],
    default: false
  },
  fixedOffset: [Number, String],
  fixedEndOffset: [Number, String],
  height: [Number, String],
  lastFixed: Boolean,
  firstFixedEnd: Boolean,
  noPadding: Boolean,
  indent: [Number, String],
  empty: Boolean,
  tag: String,
  width: [Number, String],
  maxWidth: [Number, String],
  nowrap: Boolean
}, (props, {
  slots
}) => {
  const Tag = props.tag ?? 'td';
  const fixedSide = typeof props.fixed === 'string' ? props.fixed : props.fixed ? 'start' : 'none';
  return createVNode(Tag, {
    "class": normalizeClass(['v-data-table__td', {
      'v-data-table-column--fixed': fixedSide === 'start',
      'v-data-table-column--fixed-end': fixedSide === 'end',
      'v-data-table-column--last-fixed': props.lastFixed,
      'v-data-table-column--first-fixed-end': props.firstFixedEnd,
      'v-data-table-column--no-padding': props.noPadding,
      'v-data-table-column--nowrap': props.nowrap,
      'v-data-table-column--empty': props.empty
    }, `v-data-table-column--align-${props.align}`]),
    "style": {
      height: convertToUnit(props.height),
      width: convertToUnit(props.width),
      maxWidth: convertToUnit(props.maxWidth),
      left: fixedSide === 'start' ? convertToUnit(props.fixedOffset || null) : undefined,
      right: fixedSide === 'end' ? convertToUnit(props.fixedEndOffset || null) : undefined,
      paddingInlineStart: props.indent ? convertToUnit(props.indent) : undefined
    }
  }, {
    default: () => [slots.default?.()]
  });
});

// Utilities

// Types

const makeDataTableHeaderProps = propsFactory({
  headers: Array
}, 'DataTable-header');
const VDataTableHeadersSymbol = Symbol.for('vuetify:data-table-headers');
const defaultHeader = {
  title: '',
  sortable: false
};
const defaultActionHeader = {
  ...defaultHeader,
  width: 48
};
function priorityQueue(arr = []) {
  const queue = arr.map(element => ({
    element,
    priority: 0
  }));
  return {
    enqueue: (element, priority) => {
      let added = false;
      for (let i = 0; i < queue.length; i++) {
        const item = queue[i];
        if (item.priority > priority) {
          queue.splice(i, 0, {
            element,
            priority
          });
          added = true;
          break;
        }
      }
      if (!added) queue.push({
        element,
        priority
      });
    },
    size: () => queue.length,
    count: () => {
      let count = 0;
      if (!queue.length) return 0;
      const whole = Math.floor(queue[0].priority);
      for (let i = 0; i < queue.length; i++) {
        if (Math.floor(queue[i].priority) === whole) count += 1;
      }
      return count;
    },
    dequeue: () => {
      return queue.shift();
    }
  };
}
function extractLeaves(item, columns = []) {
  if (!item.children) {
    columns.push(item);
  } else {
    for (const child of item.children) {
      extractLeaves(child, columns);
    }
  }
  return columns;
}
function extractKeys(headers, keys = new Set()) {
  for (const item of headers) {
    if (item.key) keys.add(item.key);
    if (item.children) {
      extractKeys(item.children, keys);
    }
  }
  return keys;
}
function getDefaultItem(item) {
  if (!item.key) return undefined;
  if (item.key === 'data-table-group') return defaultHeader;
  if (['data-table-expand', 'data-table-select'].includes(item.key)) return defaultActionHeader;
  return undefined;
}
function getDepth(item, depth = 0) {
  if (!item.children) return depth;
  return Math.max(depth, ...item.children.map(child => getDepth(child, depth + 1)));
}
function parseFixedColumns(items) {
  let seenFixed = false;
  function setFixed(item, side, parentFixedSide = 'none') {
    if (!item) return;
    if (parentFixedSide !== 'none') {
      item.fixed = parentFixedSide;
    }

    // normalize to simplify logic below
    if (item.fixed === true) {
      item.fixed = 'start';
    }
    if (item.fixed === side) {
      if (item.children) {
        if (side === 'start') {
          for (let i = item.children.length - 1; i >= 0; i--) {
            setFixed(item.children[i], side, side);
          }
        } else {
          for (let i = 0; i < item.children.length; i++) {
            setFixed(item.children[i], side, side);
          }
        }
      } else {
        if (!seenFixed && side === 'start') {
          item.lastFixed = true;
        } else if (!seenFixed && side === 'end') {
          item.firstFixedEnd = true;
        } else if (isNaN(Number(item.width))) {
          consoleError(`Multiple fixed columns should have a static width (key: ${item.key})`);
        } else {
          item.minWidth = Math.max(Number(item.width) || 0, Number(item.minWidth) || 0);
        }
        seenFixed = true;
      }
    } else {
      if (item.children) {
        if (side === 'start') {
          for (let i = item.children.length - 1; i >= 0; i--) {
            setFixed(item.children[i], side);
          }
        } else {
          for (let i = 0; i < item.children.length; i++) {
            setFixed(item.children[i], side);
          }
        }
      } else {
        seenFixed = false;
      }
    }
  }
  for (let i = items.length - 1; i >= 0; i--) {
    setFixed(items[i], 'start');
  }
  for (let i = 0; i < items.length; i++) {
    setFixed(items[i], 'end');
  }
  let fixedOffset = 0;
  for (let i = 0; i < items.length; i++) {
    fixedOffset = setFixedOffset(items[i], fixedOffset);
  }
  let fixedEndOffset = 0;
  for (let i = items.length - 1; i >= 0; i--) {
    fixedEndOffset = setFixedEndOffset(items[i], fixedEndOffset);
  }
}
function setFixedOffset(item, offset = 0) {
  if (!item) return offset;
  if (item.children) {
    item.fixedOffset = offset;
    for (const child of item.children) {
      offset = setFixedOffset(child, offset);
    }
  } else if (item.fixed && item.fixed !== 'end') {
    item.fixedOffset = offset;
    offset += parseFloat(item.width || '0') || 0;
  }
  return offset;
}
function setFixedEndOffset(item, offset = 0) {
  if (!item) return offset;
  if (item.children) {
    item.fixedEndOffset = offset;
    for (const child of item.children) {
      offset = setFixedEndOffset(child, offset);
    }
  } else if (item.fixed === 'end') {
    item.fixedEndOffset = offset;
    offset += parseFloat(item.width || '0') || 0;
  }
  return offset;
}
function parse(items, maxDepth) {
  const headers = [];
  let currentDepth = 0;
  const queue = priorityQueue(items);
  while (queue.size() > 0) {
    let rowSize = queue.count();
    const row = [];
    let fraction = 1;
    while (rowSize > 0) {
      const {
        element: item,
        priority
      } = queue.dequeue();
      const diff = maxDepth - currentDepth - getDepth(item);
      row.push({
        ...item,
        rowspan: diff ?? 1,
        colspan: item.children ? extractLeaves(item).length : 1
      });
      if (item.children) {
        for (const child of item.children) {
          // This internally sorts items that are on the same priority "row"
          const sort = priority % 1 + fraction / Math.pow(10, currentDepth + 2);
          queue.enqueue(child, currentDepth + diff + sort);
        }
      }
      fraction += 1;
      rowSize -= 1;
    }
    currentDepth += 1;
    headers.push(row);
  }
  const columns = items.map(item => extractLeaves(item)).flat();
  return {
    columns,
    headers
  };
}
function convertToInternalHeaders(items) {
  const internalHeaders = [];
  for (const item of items) {
    const defaultItem = {
      ...getDefaultItem(item),
      ...item
    };
    const key = defaultItem.key ?? (typeof defaultItem.value === 'string' ? defaultItem.value : null);
    const value = defaultItem.value ?? key ?? null;
    const internalItem = {
      ...defaultItem,
      key,
      value,
      sortable: defaultItem.sortable ?? (defaultItem.key != null || !!defaultItem.sort),
      children: defaultItem.children ? convertToInternalHeaders(defaultItem.children) : undefined
    };
    internalHeaders.push(internalItem);
  }
  return internalHeaders;
}
function createHeaders(props, options) {
  const headers = ref([]);
  const columns = ref([]);
  const sortFunctions = ref({});
  const sortRawFunctions = ref({});
  const filterFunctions = ref({});
  watchEffect(() => {
    const _headers = props.headers || Object.keys(props.items[0] ?? {}).map(key => ({
      key,
      title: capitalize(key)
    }));
    const items = _headers.slice();
    const keys = extractKeys(items);
    if (options?.groupBy?.value.length && !keys.has('data-table-group')) {
      items.unshift({
        key: 'data-table-group',
        title: 'Group'
      });
    }
    if (options?.showSelect?.value && !keys.has('data-table-select')) {
      items.unshift({
        key: 'data-table-select'
      });
    }
    if (options?.showExpand?.value && !keys.has('data-table-expand')) {
      items.push({
        key: 'data-table-expand'
      });
    }
    const internalHeaders = convertToInternalHeaders(items);
    parseFixedColumns(internalHeaders);
    const maxDepth = Math.max(...internalHeaders.map(item => getDepth(item))) + 1;
    const parsed = parse(internalHeaders, maxDepth);
    headers.value = parsed.headers;
    columns.value = parsed.columns;
    const flatHeaders = parsed.headers.flat(1);
    sortFunctions.value = {};
    sortRawFunctions.value = {};
    filterFunctions.value = {};
    for (const header of flatHeaders) {
      if (!header.key) continue;
      if (header.sortable) {
        if (header.sort) {
          sortFunctions.value[header.key] = header.sort;
        }
        if (header.sortRaw) {
          sortRawFunctions.value[header.key] = header.sortRaw;
        }
      }
      if (header.filter) {
        filterFunctions.value[header.key] = header.filter;
      }
    }
  });
  const data = {
    headers,
    columns,
    sortFunctions,
    sortRawFunctions,
    filterFunctions
  };
  provide(VDataTableHeadersSymbol, data);
  return data;
}
function useHeaders() {
  const data = inject$1(VDataTableHeadersSymbol);
  if (!data) throw new Error('Missing headers!');
  return data;
}

// Utilities

// Types

function useLoadingConfig(loading, fallbackColor) {
  const active = computed(() => {
    const v = loading();
    return v != null && v !== false && v !== 'false';
  });
  const side = computed(() => {
    const v = loading();
    if (typeof v === 'object' && v !== null && v.side) return v.side;
    return 'start';
  });
  const color = computed(() => {
    const v = loading();
    if (typeof v === 'object' && v !== null && v.color) return v.color;
    if (typeof v === 'string' && v !== 'true') return v;
    return fallbackColor();
  });
  return {
    active,
    side,
    color
  };
}

// Types

const makeVDataTableHeadersProps = propsFactory({
  color: String,
  disableSort: Boolean,
  fixedHeader: Boolean,
  multiSort: Boolean,
  initialSortOrder: String,
  sortIcon: {
    type: IconValue
    // default: '$sort', // maybe in v4
  },
  sortAscIcon: {
    type: IconValue,
    default: '$sortAsc'
  },
  sortDescIcon: {
    type: IconValue,
    default: '$sortDesc'
  },
  headerProps: {
    type: Object
  },
  selectAllLabel: {
    type: String,
    default: '$vuetify.dataTable.ariaLabel.selectAll'
  },
  /** @deprecated */
  sticky: Boolean,
  ...makeDensityProps(),
  ...makeDisplayProps(),
  ...makeLoaderProps()
}, 'VDataTableHeaders');
const VDataTableHeaders = genericComponent()({
  name: 'VDataTableHeaders',
  props: makeVDataTableHeadersProps(),
  setup(props, {
    slots
  }) {
    const {
      t
    } = useLocale();
    const {
      toggleSort,
      sortBy,
      isSorted
    } = useSort();
    const {
      someSelected,
      allSelected,
      selectAll,
      showSelectAll
    } = useSelection();
    const {
      columns,
      headers
    } = useHeaders();
    const {
      loaderClasses
    } = useLoader(props);
    function getFixedStyles(column, y) {
      if (!(props.sticky || props.fixedHeader) && !column.fixed) return undefined;
      const fixedSide = typeof column.fixed === 'string' ? column.fixed : column.fixed ? 'start' : 'none';
      return {
        position: 'sticky',
        left: fixedSide === 'start' ? convertToUnit(column.fixedOffset) : undefined,
        right: fixedSide === 'end' ? convertToUnit(column.fixedEndOffset) : undefined,
        top: props.sticky || props.fixedHeader ? `calc(var(--v-table-header-height) * ${y})` : undefined
      };
    }
    function handleEnterKeyPress(event, column) {
      if (event.key === 'Enter' && !props.disableSort) {
        toggleSort(column, event);
      }
    }
    function getSortIcon(column) {
      const item = sortBy.value.find(item => item.key === column.key);
      switch (item?.order) {
        case 'asc':
          return props.sortAscIcon;
        case 'desc':
          return props.sortDescIcon;
        default:
          return props.sortIcon || (props.initialSortOrder === 'asc' ? props.sortAscIcon : props.sortDescIcon);
      }
    }
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      displayClasses,
      mobile
    } = useDisplay(props);
    const loadingConfig = useLoadingConfig(() => props.loading, () => props.color);
    const slotProps = computed(() => ({
      headers: headers.value,
      columns: columns.value,
      toggleSort,
      isSorted,
      sortBy: sortBy.value,
      someSelected: someSelected.value,
      allSelected: allSelected.value,
      selectAll,
      getSortIcon
    }));
    const headerCellClasses = computed(() => ['v-data-table__th', {
      'v-data-table__th--sticky': props.sticky || props.fixedHeader
    }, displayClasses.value, loaderClasses.value]);
    const VDataTableHeaderCell = ({
      column,
      x,
      y
    }) => {
      const noPadding = column.key === 'data-table-select' || column.key === 'data-table-expand';
      const isEmpty = column.key === 'data-table-group' && column.width === 0 && !column.title;
      const headerProps = mergeProps(props.headerProps ?? {}, column.headerProps ?? {});
      const isSortable = column.sortable && !props.disableSort;
      const sortItem = isSortable ? sortBy.value.find(item => item.key === column.key) : undefined;
      const ariaSort = sortItem?.order === 'asc' ? 'ascending' : sortItem?.order === 'desc' ? 'descending' : undefined;
      return createVNode(VDataTableColumn, mergeProps({
        "tag": "th",
        "aria-sort": ariaSort,
        "align": column.align,
        "class": [{
          'v-data-table__th--sortable': isSortable,
          'v-data-table__th--sorted': isSorted(column),
          'v-data-table__th--fixed': column.fixed
        }, ...headerCellClasses.value],
        "style": {
          width: convertToUnit(column.width),
          minWidth: convertToUnit(column.minWidth),
          maxWidth: convertToUnit(column.maxWidth),
          ...getFixedStyles(column, y)
        },
        "colspan": column.colspan,
        "rowspan": column.rowspan,
        "fixed": column.fixed,
        "nowrap": column.nowrap,
        "lastFixed": column.lastFixed,
        "firstFixedEnd": column.firstFixedEnd,
        "noPadding": noPadding,
        "empty": isEmpty,
        "tabindex": isSortable ? 0 : undefined,
        "onClick": isSortable ? event => toggleSort(column, event) : undefined,
        "onKeydown": isSortable ? event => handleEnterKeyPress(event, column) : undefined
      }, headerProps), {
        default: () => {
          const columnSlotName = `header.${column.key}`;
          const columnSlotProps = {
            column,
            selectAll,
            isSorted,
            toggleSort,
            sortBy: sortBy.value,
            someSelected: someSelected.value,
            allSelected: allSelected.value,
            getSortIcon
          };
          if (slots[columnSlotName]) return slots[columnSlotName](columnSlotProps);
          if (isEmpty) return '';
          if (column.key === 'data-table-select') {
            return slots['header.data-table-select']?.(columnSlotProps) ?? (showSelectAll.value && createVNode(VCheckboxBtn, {
              "aria-label": t(props.selectAllLabel),
              "color": props.color,
              "density": props.density,
              "modelValue": allSelected.value,
              "indeterminate": someSelected.value && !allSelected.value,
              "onUpdate:modelValue": selectAll
            }, null));
          }
          return createElementVNode("div", {
            "class": "v-data-table-header__content"
          }, [createElementVNode("span", null, [column.title]), column.sortable && !props.disableSort && createVNode(VIcon, {
            "key": "icon",
            "class": "v-data-table-header__sort-icon",
            "icon": getSortIcon(column)
          }, null), props.multiSort && isSorted(column) && createElementVNode("div", {
            "key": "badge",
            "class": normalizeClass(['v-data-table-header__sort-badge', ...backgroundColorClasses.value]),
            "style": normalizeStyle(backgroundColorStyles.value)
          }, [sortBy.value.findIndex(x => x.key === column.key) + 1])]);
        }
      });
    };
    const VDataTableMobileHeaderCell = () => {
      const sortableColumns = computed(() => {
        return columns.value.filter(column => column?.sortable && !props.disableSort);
      });
      const showSelectColumn = columns.value.find(column => column.key === 'data-table-select');
      const sortingChips = computed({
        get: () => sortableColumns.value.filter(({
          key
        }) => sortBy.value.some(v => v.key === key)),
        set: val => {
          const sortedColumns = wrapInArray(val);
          const activeSortKeys = sortBy.value.map(v => v.key);
          const newColumnsToSort = sortedColumns.filter(({
            key
          }) => !activeSortKeys.includes(key));
          newColumnsToSort.forEach(column => toggleSort(column));
          // sortBy is proxied model, needs nextTick after toggleSort
          nextTick(() => sortBy.value = sortBy.value.filter(({
            key
          }) => sortedColumns.some(c => c.key === key)));
        }
      });
      function renderSortSelect() {
        return createVNode(VSelect, {
          "modelValue": sortingChips.value,
          "onUpdate:modelValue": $event => sortingChips.value = $event,
          "chips": true,
          "color": props.color,
          "class": "v-data-table__td-sort-select",
          "clearable": true,
          "density": "default",
          "items": sortableColumns.value,
          "label": t('$vuetify.dataTable.sortBy'),
          "multiple": props.multiSort,
          "variant": "underlined",
          "returnObject": true,
          "onClick:clear": () => sortBy.value = []
        }, {
          chip: ({
            internalItem
          }) => createVNode(VChip, {
            "onClick": internalItem.raw.sortable ? () => toggleSort(internalItem.raw, undefined, true) : undefined,
            "onMousedown": e => {
              e.preventDefault();
              e.stopPropagation();
            }
          }, {
            default: () => [internalItem.title, createVNode(VIcon, {
              "class": normalizeClass(['v-data-table__td-sort-icon', isSorted(internalItem.raw) && 'v-data-table__td-sort-icon-active']),
              "icon": getSortIcon(internalItem.raw),
              "size": "small"
            }, null)]
          })
        });
      }
      function renderSelectAll() {
        return createVNode(VCheckboxBtn, {
          "aria-label": t(props.selectAllLabel),
          "class": "v-data-table-header__select-all",
          "color": props.color,
          "density": "compact",
          "modelValue": allSelected.value,
          "indeterminate": someSelected.value && !allSelected.value,
          "onUpdate:modelValue": () => selectAll(!allSelected.value)
        }, null);
      }
      return createVNode(VDataTableColumn, mergeProps({
        "tag": "th",
        "class": [...headerCellClasses.value],
        "colspan": headers.value.length + 1
      }, props.headerProps), {
        default: () => [createElementVNode("div", {
          "class": "v-data-table-header__content"
        }, [slots['mobile.header']?.(slotProps.value) ?? createElementVNode(Fragment, null, [sortableColumns.value.length > 0 && renderSortSelect(), showSelectColumn && renderSelectAll()])])]
      });
    };
    const showMobileHeader = computed(() => {
      if (slots['mobile.header']) return true;
      const hasSortableColumns = columns.value.some(column => column?.sortable && !props.disableSort);
      const hasSelectionControl = columns.value.some(column => column.key === 'data-table-select');
      return hasSortableColumns || hasSelectionControl;
    });
    useRender(() => {
      return mobile.value ? createElementVNode(Fragment, null, [showMobileHeader.value && createElementVNode("tr", null, [createVNode(VDataTableMobileHeaderCell, null, null)])]) : createElementVNode(Fragment, null, [slots.headers ? slots.headers(slotProps.value) : headers.value.map((row, y) => createElementVNode("tr", null, [row.map((column, x) => createVNode(VDataTableHeaderCell, {
        "key": column.key ?? x,
        "column": column,
        "x": x,
        "y": y
      }, null))])), loadingConfig.active.value && ['start', 'both'].includes(loadingConfig.side.value) && createElementVNode("tr", {
        "class": "v-data-table-progress"
      }, [createElementVNode("th", {
        "colspan": columns.value.length
      }, [createVNode(LoaderSlot, {
        "name": "v-data-table-progress",
        "absolute": true,
        "active": true,
        "color": loadingConfig.color.value,
        "indeterminate": true
      }, {
        default: slots.loader
      })])])]);
    });
  }
});

// Types

const makeVDataTableGroupHeaderRowProps = propsFactory({
  item: {
    type: Object,
    required: true
  },
  groupCollapseIcon: {
    type: IconValue,
    default: '$tableGroupCollapse'
  },
  groupExpandIcon: {
    type: IconValue,
    default: '$tableGroupExpand'
  },
  selectGroupLabel: {
    type: String,
    default: '$vuetify.dataTable.ariaLabel.selectGroup'
  },
  ...makeDensityProps()
}, 'VDataTableGroupHeaderRow');
const VDataTableGroupHeaderRow = genericComponent()({
  name: 'VDataTableGroupHeaderRow',
  props: makeVDataTableGroupHeaderRowProps(),
  setup(props, {
    slots
  }) {
    const {
      t
    } = useLocale();
    const {
      isGroupOpen,
      toggleGroup,
      extractRows
    } = useGroupBy();
    const {
      isSelected,
      isSomeSelected,
      select
    } = useSelection();
    const {
      columns
    } = useHeaders();
    const rows = computed(() => {
      return extractRows([props.item]);
    });
    const colspan = toRef(() => columns.value.length - (columns.value.some(c => c.key === 'data-table-select') ? 1 : 0));
    return () => createElementVNode("tr", {
      "class": "v-data-table-group-header-row",
      "style": {
        '--v-data-table-group-header-row-depth': props.item.depth
      }
    }, [columns.value.map(column => {
      if (column.key === 'data-table-group') {
        const icon = isGroupOpen(props.item) ? props.groupCollapseIcon : props.groupExpandIcon;
        const onClick = () => toggleGroup(props.item);
        return slots['data-table-group']?.({
          item: props.item,
          count: rows.value.length,
          props: {
            icon,
            onClick
          }
        }) ?? createVNode(VDataTableColumn, {
          "class": "v-data-table-group-header-row__column",
          "colspan": colspan.value
        }, {
          default: () => [createVNode(VBtn, {
            "size": "small",
            "variant": "text",
            "icon": icon,
            "onClick": onClick
          }, null), createElementVNode("span", null, [props.item.value]), createElementVNode("span", null, [createTextVNode("("), rows.value.length, createTextVNode(")")])]
        });
      } else if (column.key === 'data-table-select') {
        const selectableRows = rows.value.filter(x => x.selectable);
        const modelValue = selectableRows.length > 0 && isSelected(selectableRows);
        const indeterminate = isSomeSelected(selectableRows) && !modelValue;
        const selectGroup = v => select(selectableRows, v);
        return slots['data-table-select']?.({
          props: {
            modelValue,
            indeterminate,
            'onUpdate:modelValue': selectGroup
          }
        }) ?? createVNode(VDataTableColumn, {
          "class": "v-data-table__td--select-row",
          "noPadding": true
        }, {
          default: () => [createVNode(VCheckboxBtn, {
            "aria-label": t(props.selectGroupLabel),
            "density": props.density,
            "disabled": selectableRows.length === 0,
            "modelValue": modelValue,
            "indeterminate": indeterminate,
            "onUpdate:modelValue": selectGroup
          }, null)]
        });
      }
      return '';
    })]);
  }
});

// Types

const makeVDataTableRowProps = propsFactory({
  color: String,
  index: Number,
  item: Object,
  cellProps: [Object, Function],
  collapseIcon: {
    type: IconValue,
    default: '$collapse'
  },
  expandIcon: {
    type: IconValue,
    default: '$expand'
  },
  selectRowLabel: {
    type: String,
    default: '$vuetify.dataTable.ariaLabel.selectRow'
  },
  getMatches: Function,
  onClick: EventProp(),
  onContextmenu: EventProp(),
  onDblclick: EventProp(),
  ...makeDensityProps(),
  ...makeDisplayProps()
}, 'VDataTableRow');
const VDataTableRow = genericComponent()({
  name: 'VDataTableRow',
  props: makeVDataTableRowProps(),
  setup(props, {
    slots
  }) {
    const {
      t
    } = useLocale();
    const {
      displayClasses,
      mobile
    } = useDisplay(props, 'v-data-table__tr');
    const {
      isSelected,
      toggleSelect,
      someSelected,
      allSelected,
      selectAll
    } = useSelection();
    const {
      isExpanded,
      toggleExpand
    } = useExpanded();
    const {
      toggleSort,
      sortBy,
      isSorted
    } = useSort();
    const {
      columns
    } = useHeaders();
    useRender(() => createElementVNode("tr", {
      "class": normalizeClass(['v-data-table__tr', {
        'v-data-table__tr--clickable': !!(props.onClick || props.onContextmenu || props.onDblclick)
      }, displayClasses.value]),
      "onClick": props.onClick,
      "onContextmenu": props.onContextmenu,
      "onDblclick": props.onDblclick
    }, [props.item && columns.value.map((column, i) => {
      const item = props.item;
      const slotName = `item.${column.key}`;
      const headerSlotName = `header.${column.key}`;
      const slotProps = {
        index: props.index,
        item: item.raw,
        internalItem: item,
        value: getObjectValueByPath(item.columns, column.key),
        column,
        isSelected,
        toggleSelect,
        isExpanded,
        toggleExpand
      };
      const columnSlotProps = {
        column,
        selectAll,
        isSorted,
        toggleSort,
        sortBy: sortBy.value,
        someSelected: someSelected.value,
        allSelected: allSelected.value,
        getSortIcon: () => ''
      };
      const cellProps = typeof props.cellProps === 'function' ? props.cellProps({
        index: slotProps.index,
        item: slotProps.item,
        internalItem: slotProps.internalItem,
        value: slotProps.value,
        column
      }) : props.cellProps;
      const columnCellProps = typeof column.cellProps === 'function' ? column.cellProps({
        index: slotProps.index,
        item: slotProps.item,
        internalItem: slotProps.internalItem,
        value: slotProps.value
      }) : column.cellProps;
      const noPadding = column.key === 'data-table-select' || column.key === 'data-table-expand';
      const isEmpty = column.key === 'data-table-group' && column.width === 0 && !column.title;
      return createVNode(VDataTableColumn, mergeProps({
        "key": column.key ?? i,
        "align": column.align,
        "indent": column.indent,
        "class": {
          'v-data-table__td--expanded-row': column.key === 'data-table-expand',
          'v-data-table__td--select-row': column.key === 'data-table-select'
        },
        "fixed": column.fixed,
        "fixedOffset": column.fixedOffset,
        "fixedEndOffset": column.fixedEndOffset,
        "lastFixed": column.lastFixed,
        "firstFixedEnd": column.firstFixedEnd,
        "maxWidth": !mobile.value ? column.maxWidth : undefined,
        "noPadding": noPadding,
        "empty": isEmpty,
        "nowrap": column.nowrap,
        "width": !mobile.value ? column.width : undefined
      }, cellProps, columnCellProps), {
        default: () => {
          if (column.key === 'data-table-select') {
            return slots['item.data-table-select']?.({
              ...slotProps,
              props: {
                color: props.color,
                disabled: !item.selectable,
                modelValue: isSelected([item]),
                onClick: withModifiers(() => toggleSelect(item), ['stop'])
              }
            }) ?? createVNode(VCheckboxBtn, {
              "aria-label": t(props.selectRowLabel),
              "color": props.color,
              "disabled": !item.selectable,
              "density": props.density,
              "modelValue": isSelected([item]),
              "onClick": withModifiers(event => toggleSelect(item, props.index, event), ['stop'])
            }, null);
          }
          if (column.key === 'data-table-expand') {
            return slots['item.data-table-expand']?.({
              ...slotProps,
              props: {
                icon: isExpanded(item) ? props.collapseIcon : props.expandIcon,
                size: 'small',
                variant: 'text',
                onClick: withModifiers(() => toggleExpand(item), ['stop'])
              }
            }) ?? createVNode(VBtn, {
              "icon": isExpanded(item) ? props.collapseIcon : props.expandIcon,
              "size": "small",
              "variant": "text",
              "onClick": withModifiers(() => toggleExpand(item), ['stop'])
            }, null);
          }
          if (slots[slotName] && !mobile.value) return slots[slotName](slotProps);
          const text = toDisplayString(slotProps.value);
          const matches = props.getMatches?.(item)?.[column.key];
          const displayValue = matches?.length ? createVNode(VHighlight, {
            "text": text,
            "matches": matches
          }, null) : text;
          return !mobile.value ? displayValue : createElementVNode(Fragment, null, [createElementVNode("div", {
            "class": "v-data-table__td-title"
          }, [slots[headerSlotName]?.(columnSlotProps) ?? column.title]), createElementVNode("div", {
            "class": "v-data-table__td-value"
          }, [slots[slotName]?.(slotProps) ?? displayValue])]);
        }
      });
    })]));
  }
});

// Types

const makeVDataTableRowsProps = propsFactory({
  color: String,
  loading: [Boolean, String, Object],
  loadingText: {
    type: String,
    default: '$vuetify.dataIterator.loadingText'
  },
  hideNoData: Boolean,
  items: {
    type: Array,
    default: () => []
  },
  noDataText: {
    type: String,
    default: '$vuetify.noDataText'
  },
  rowProps: [Object, Function],
  cellProps: [Object, Function],
  expandTransition: {
    type: null,
    default: () => ({
      component: VExpandTransition
    }),
    validator: val => val !== true
  },
  ...pick(makeVDataTableRowProps(), ['collapseIcon', 'expandIcon', 'density', 'getMatches']),
  ...pick(makeVDataTableGroupHeaderRowProps(), ['groupCollapseIcon', 'groupExpandIcon', 'density']),
  ...makeDisplayProps()
}, 'VDataTableRows');
const VDataTableRows = genericComponent()({
  name: 'VDataTableRows',
  inheritAttrs: false,
  props: makeVDataTableRowsProps(),
  setup(props, {
    attrs,
    slots
  }) {
    const {
      columns
    } = useHeaders();
    const {
      expandOnClick,
      toggleExpand,
      isExpanded
    } = useExpanded();
    const {
      isSelected,
      toggleSelect
    } = useSelection();
    const {
      toggleGroup,
      isGroupOpen
    } = useGroupBy();
    const {
      t
    } = useLocale();
    const {
      mobile
    } = useDisplay(props);
    useRender(() => {
      const groupHeaderRowProps = pick(props, ['groupCollapseIcon', 'groupExpandIcon', 'density']);
      if (props.loading && (!props.items.length || slots.loading)) {
        return createElementVNode("tr", {
          "class": "v-data-table-rows-loading",
          "key": "loading"
        }, [createElementVNode("td", {
          "colspan": columns.value.length
        }, [slots.loading?.() ?? t(props.loadingText)])]);
      }
      if (!props.loading && !props.items.length && !props.hideNoData) {
        return createElementVNode("tr", {
          "class": "v-data-table-rows-no-data",
          "key": "no-data"
        }, [createElementVNode("td", {
          "colspan": columns.value.length
        }, [slots['no-data']?.() ?? t(props.noDataText)])]);
      }
      return createElementVNode(Fragment, null, [props.items.map((item, index) => {
        if (item.type === 'group') {
          const slotProps = {
            index,
            item,
            columns: columns.value,
            isExpanded,
            toggleExpand,
            isSelected,
            toggleSelect,
            toggleGroup,
            isGroupOpen
          };
          return slots['group-header'] ? slots['group-header'](slotProps) : createVNode(VDataTableGroupHeaderRow, mergeProps({
            "key": `group-header_${item.id}`,
            "item": item
          }, getPrefixedEventHandlers(attrs, ':groupHeader', () => slotProps), groupHeaderRowProps), slots);
        }
        if (item.type === 'group-summary') {
          const slotProps = {
            index,
            item,
            columns: columns.value,
            toggleGroup
          };
          return slots['group-summary']?.(slotProps) ?? '';
        }
        const slotProps = {
          index: item.virtualIndex ?? index,
          item: item.raw,
          internalItem: item,
          columns: columns.value,
          isExpanded,
          toggleExpand,
          isSelected,
          toggleSelect
        };
        const itemSlotProps = {
          ...slotProps,
          props: mergeProps({
            key: `item_${item.key ?? item.index}`,
            onClick: expandOnClick.value ? () => {
              toggleExpand(item);
            } : undefined,
            index,
            item,
            color: props.color,
            cellProps: props.cellProps,
            collapseIcon: props.collapseIcon,
            expandIcon: props.expandIcon,
            density: props.density,
            mobile: mobile.value,
            getMatches: props.getMatches
          }, getPrefixedEventHandlers(attrs, ':row', () => slotProps), typeof props.rowProps === 'function' ? props.rowProps({
            item: slotProps.item,
            index: slotProps.index,
            internalItem: slotProps.internalItem
          }) : props.rowProps)
        };
        return createElementVNode(Fragment, {
          "key": itemSlotProps.props.key
        }, [slots.item ? slots.item(itemSlotProps) : createVNode(VDataTableRow, itemSlotProps.props, slots), slots['expanded-row'] ? isExpanded(item) && slots['expanded-row'](slotProps) : slots.expanded && createElementVNode("tr", {
          "class": "v-data-table__tr--expanded"
        }, [createElementVNode("td", {
          "colspan": columns.value.length
        }, [props.expandTransition ? createVNode(MaybeTransition, {
          "transition": props.expandTransition
        }, {
          default: () => [isExpanded(item) ? createElementVNode("div", null, [slots.expanded(slotProps)]) : null]
        }) // bypass <Transition> to avoid flash when expand-strategy=single
        : isExpanded(item) && createElementVNode("div", null, [slots.expanded(slotProps)])])])]);
      })]);
    });
    return {};
  }
});

// Types

const makeVTableProps = propsFactory({
  gridlines: {
    type: [Boolean, String],
    default: 'horizontal',
    validator: v => typeof v === 'boolean' || ['horizontal', 'vertical', 'all'].includes(v)
  },
  fixedHeader: Boolean,
  fixedFooter: Boolean,
  height: [Number, String],
  hover: Boolean,
  striped: {
    type: String,
    default: null,
    validator: v => ['even', 'odd'].includes(v)
  },
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeTagProps(),
  ...makeThemeProps()
}, 'VTable');
const VTable = genericComponent()({
  name: 'VTable',
  inheritAttrs: false,
  props: makeVTableProps(),
  setup(props, {
    attrs,
    slots,
    emit
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      densityClasses
    } = useDensity(props);
    const gridlinesVariant = computed(() => {
      if (props.gridlines === false) return 'none';
      if (props.gridlines === true) return 'all';
      return props.gridlines;
    });
    useRender(() => {
      const [tableAttrs, rootAttrs] = pickWithRest(attrs, [/^aria-label/]);
      return createVNode(props.tag, mergeProps(rootAttrs, {
        "class": ['v-table', `v-table--gridlines-${gridlinesVariant.value}`, {
          'v-table--fixed-height': !!props.height,
          'v-table--fixed-header': props.fixedHeader,
          'v-table--fixed-footer': props.fixedFooter,
          'v-table--has-top': !!slots.top,
          'v-table--has-bottom': !!slots.bottom,
          'v-table--hover': props.hover,
          'v-table--striped-even': props.striped === 'even',
          'v-table--striped-odd': props.striped === 'odd'
        }, themeClasses.value, densityClasses.value, props.class],
        "style": props.style
      }), {
        default: () => [slots.top?.(), slots.default ? createElementVNode("div", {
          "class": "v-table__wrapper",
          "style": {
            height: convertToUnit(props.height)
          }
        }, [createElementVNode("table", normalizeProps(guardReactiveProps(tableAttrs)), [slots.caption?.(), slots.default()])]) : slots.wrapper?.(), slots.bottom?.()]
      });
    });
    return {};
  }
});

// Utilities

// Types

// Composables
const makeDataTableItemsProps = propsFactory({
  items: {
    type: Array,
    default: () => []
  },
  itemValue: {
    type: [String, Array, Function],
    default: 'id'
  },
  itemSelectable: {
    type: [String, Array, Function],
    default: null
  },
  rowProps: [Object, Function],
  cellProps: [Object, Function],
  returnObject: Boolean
}, 'DataTable-items');
function transformItem(props, item, index, columns) {
  const value = props.returnObject ? item : getPropertyFromItem(item, props.itemValue);
  const selectable = getPropertyFromItem(item, props.itemSelectable, true);
  const itemColumns = columns.reduce((obj, column) => {
    if (column.key != null) obj[column.key] = getPropertyFromItem(item, column.value);
    return obj;
  }, {});
  return {
    type: 'item',
    key: props.returnObject ? getPropertyFromItem(item, props.itemValue) : value,
    index,
    value,
    selectable,
    columns: itemColumns,
    raw: item
  };
}
function transformItems(props, items, columns) {
  return items.map((item, index) => transformItem(props, item, index, columns));
}
function useDataTableItems(props, columns) {
  const items = computed(() => transformItems(props, props.items, columns.value));
  return {
    items
  };
}

// Types

const makeDataTableProps = propsFactory({
  ...makeVDataTableRowsProps(),
  hideDefaultBody: Boolean,
  hideDefaultFooter: Boolean,
  hideDefaultHeader: Boolean,
  width: [String, Number],
  search: String,
  ...makeDataTableExpandProps(),
  ...makeDataTableGroupProps(),
  ...makeDataTableHeaderProps(),
  ...makeDataTableItemsProps(),
  ...makeDataTableSelectProps(),
  ...makeDataTableSortProps(),
  ...omit(makeVDataTableHeadersProps(), ['multiSort', 'initialSortOrder']),
  ...makeVTableProps()
}, 'DataTable');
const makeVDataTableProps = propsFactory({
  ...makeDataTablePaginateProps(),
  ...makeDataTableProps(),
  ...makeFilterProps(),
  ...makeVDataTableFooterProps()
}, 'VDataTable');
const VDataTable = genericComponent()({
  name: 'VDataTable',
  props: makeVDataTableProps(),
  emits: {
    'update:modelValue': value => true,
    'update:page': value => true,
    'update:itemsPerPage': value => true,
    'update:sortBy': value => true,
    'update:options': value => true,
    'update:groupBy': value => true,
    'update:expanded': value => true,
    'update:opened': value => true,
    'update:currentItems': value => true
  },
  setup(props, {
    attrs,
    slots
  }) {
    const {
      groupBy,
      opened,
      openAll,
      groupKey
    } = createGroupBy(props);
    const {
      initialSortOrder,
      sortBy,
      multiSort,
      mustSort
    } = createSort(props);
    const {
      page,
      itemsPerPage
    } = createPagination(props);
    const {
      disableSort
    } = toRefs(props);
    const {
      columns,
      headers,
      sortFunctions,
      sortRawFunctions,
      filterFunctions
    } = createHeaders(props, {
      groupBy,
      showSelect: toRef(() => props.showSelect),
      showExpand: toRef(() => props.showExpand)
    });
    const {
      items
    } = useDataTableItems(props, columns);
    const search = toRef(() => props.search);
    const {
      filteredItems,
      getMatches
    } = useFilter(props, items, search, {
      transform: item => item.columns,
      customKeyFilter: filterFunctions
    });
    const {
      toggleSort
    } = provideSort({
      initialSortOrder,
      sortBy,
      multiSort,
      mustSort,
      page
    });
    const {
      sortByWithGroups,
      opened: openedGroups,
      extractRows,
      isGroupOpen,
      toggleGroup
    } = provideGroupBy({
      groupBy,
      sortBy,
      disableSort,
      opened
    });
    const {
      sortedItems
    } = useSortedItems(props, filteredItems, sortByWithGroups, {
      transform: item => ({
        ...item.raw,
        ...item.columns
      }),
      sortFunctions,
      sortRawFunctions
    });
    useOpenAllGroups(openedGroups, openAll, sortedItems, groupBy, groupKey);
    const pageBy = computed(() => {
      if (props.pageBy === 'auto') {
        return props.groupBy.length ? 'group' : 'item';
      }
      return props.pageBy;
    });
    const {
      pageCount,
      setItemsPerPage,
      prevPage,
      nextPage,
      setPage,
      paginatedItems
    } = usePaginatedGroups({
      pageBy,
      sortedItems,
      paginate: items => {
        const itemsLength = computed(() => toValue(items).length);
        const {
          startIndex,
          stopIndex,
          pageCount,
          setItemsPerPage,
          prevPage,
          nextPage,
          setPage
        } = providePagination({
          page,
          itemsPerPage,
          itemsLength
        });
        const {
          paginatedItems
        } = usePaginatedItems({
          items,
          startIndex,
          stopIndex,
          itemsPerPage
        });
        return {
          paginatedItems,
          pageCount,
          setItemsPerPage,
          prevPage,
          nextPage,
          setPage
        };
      },
      group: items => useGroupedItems(items, groupBy, openedGroups, () => !!slots['group-summary'], isGroupOpen, groupKey)
    });
    const paginatedItemsWithoutGroups = computed(() => extractRows(paginatedItems.value));
    const {
      isSelected,
      select,
      selectAll,
      toggleSelect,
      someSelected,
      allSelected
    } = provideSelection(props, {
      allItems: items,
      currentPage: paginatedItemsWithoutGroups
    });
    const {
      isExpanded,
      toggleExpand
    } = provideExpanded(props);
    const loadingConfig = useLoadingConfig(() => props.loading, () => props.color);
    useOptions({
      page,
      itemsPerPage,
      sortBy,
      groupBy,
      search
    });
    provideDefaults({
      VDataTableRows: {
        hideNoData: toRef(() => props.hideNoData),
        noDataText: toRef(() => props.noDataText),
        loading: toRef(() => props.loading),
        loadingText: toRef(() => props.loadingText)
      }
    });
    const slotProps = computed(() => ({
      page: page.value,
      itemsPerPage: itemsPerPage.value,
      itemsLength: filteredItems.value.length,
      sortBy: sortBy.value,
      pageCount: pageCount.value,
      toggleSort,
      setItemsPerPage,
      prevPage,
      nextPage,
      setPage,
      someSelected: someSelected.value,
      allSelected: allSelected.value,
      isSelected,
      select,
      selectAll,
      toggleSelect,
      isExpanded,
      toggleExpand,
      isGroupOpen,
      toggleGroup,
      items: paginatedItemsWithoutGroups.value.map(item => item.raw),
      internalItems: paginatedItemsWithoutGroups.value,
      groupedItems: paginatedItems.value,
      columns: columns.value,
      headers: headers.value
    }));
    useRender(() => {
      const dataTableFooterProps = VDataTableFooter.filterProps(props);
      const dataTableHeadersProps = VDataTableHeaders.filterProps(omit(props, ['multiSort']));
      const dataTableRowsProps = VDataTableRows.filterProps(props);
      const tableProps = VTable.filterProps(props);
      return createVNode(VTable, mergeProps({
        "class": ['v-data-table', {
          'v-data-table--show-select': props.showSelect,
          'v-data-table--loading': props.loading
        }, props.class],
        "style": props.style
      }, tableProps, {
        "fixedHeader": props.fixedHeader || props.sticky
      }), {
        top: () => slots.top?.(slotProps.value),
        caption: slots.caption,
        default: () => slots.default ? slots.default(slotProps.value) : createElementVNode(Fragment, null, [slots.colgroup?.(slotProps.value), !props.hideDefaultHeader && createElementVNode("thead", {
          "key": "thead"
        }, [createVNode(VDataTableHeaders, mergeProps(dataTableHeadersProps, {
          "multiSort": !!props.multiSort
        }), slots)]), slots.thead?.(slotProps.value), !props.hideDefaultBody && createElementVNode("tbody", null, [slots['body.prepend']?.(slotProps.value), slots.body ? slots.body(slotProps.value) : createVNode(VDataTableRows, mergeProps(attrs, dataTableRowsProps, {
          "items": paginatedItems.value,
          "getMatches": getMatches
        }), slots), slots['body.append']?.(slotProps.value), loadingConfig.active.value && ['end', 'both'].includes(loadingConfig.side.value) && createElementVNode("tr", {
          "class": "v-data-table-progress v-data-table-progress--bottom"
        }, [createElementVNode("th", {
          "colspan": columns.value.length
        }, [createVNode(LoaderSlot, {
          "name": "v-data-table-progress",
          "absolute": true,
          "active": true,
          "color": loadingConfig.color.value,
          "indeterminate": true
        }, {
          default: slots.loader
        })])])]), slots.tbody?.(slotProps.value), slots.tfoot?.(slotProps.value)]),
        bottom: () => slots.bottom ? slots.bottom(slotProps.value) : !props.hideDefaultFooter && createElementVNode(Fragment, null, [createVNode(VDivider, null, null), createVNode(VDataTableFooter, dataTableFooterProps, {
          prepend: slots['footer.prepend']
        })])
      });
    });
    return {};
  }
});

// Types

const makeVDataTableVirtualProps = propsFactory({
  ...omit(makeDataTableProps(), ['hideDefaultFooter']),
  ...makeDataTableGroupProps(),
  ...makeVirtualProps(),
  ...makeFilterProps()
}, 'VDataTableVirtual');
function elementNodes(nodes) {
  return (nodes ?? []).flatMap(node => Array.isArray(node) ? elementNodes(node) : !isVNode(node) ? [] : node.type === Fragment ? elementNodes(node.children) : typeof node.type === 'symbol' ? [] : [node]);
}
const VDataTableVirtual = genericComponent()({
  name: 'VDataTableVirtual',
  props: makeVDataTableVirtualProps(),
  emits: {
    'update:modelValue': value => true,
    'update:sortBy': value => true,
    'update:options': value => true,
    'update:groupBy': value => true,
    'update:expanded': value => true,
    'update:opened': value => true
  },
  setup(props, {
    attrs,
    slots
  }) {
    const {
      groupBy,
      opened,
      openAll,
      groupKey
    } = createGroupBy(props);
    const {
      initialSortOrder,
      sortBy,
      multiSort,
      mustSort
    } = createSort(props);
    const {
      disableSort
    } = toRefs(props);
    const {
      columns,
      headers,
      filterFunctions,
      sortFunctions,
      sortRawFunctions
    } = createHeaders(props, {
      groupBy,
      showSelect: toRef(() => props.showSelect),
      showExpand: toRef(() => props.showExpand)
    });
    const {
      items
    } = useDataTableItems(props, columns);
    const search = toRef(() => props.search);
    const {
      filteredItems,
      getMatches
    } = useFilter(props, items, search, {
      transform: item => item.columns,
      customKeyFilter: filterFunctions
    });
    const {
      toggleSort
    } = provideSort({
      initialSortOrder,
      sortBy,
      multiSort,
      mustSort
    });
    const {
      sortByWithGroups,
      opened: openedGroups,
      extractRows,
      isGroupOpen,
      toggleGroup
    } = provideGroupBy({
      groupBy,
      sortBy,
      disableSort,
      opened
    });
    const {
      sortedItems
    } = useSortedItems(props, filteredItems, sortByWithGroups, {
      transform: item => ({
        ...item.raw,
        ...item.columns
      }),
      sortFunctions,
      sortRawFunctions
    });
    useOpenAllGroups(openedGroups, openAll, sortedItems, groupBy, groupKey);
    const {
      flatItems
    } = useGroupedItems(sortedItems, groupBy, openedGroups, () => !!slots['group-summary'], isGroupOpen, groupKey);
    const allItems = computed(() => extractRows(flatItems.value));
    const {
      isSelected,
      select,
      selectAll,
      toggleSelect,
      someSelected,
      allSelected
    } = provideSelection(props, {
      allItems,
      currentPage: allItems
    });
    const {
      expanded,
      isExpanded,
      toggleExpand
    } = provideExpanded(props);
    const {
      containerRef,
      markerRef,
      paddingTop,
      paddingBottom,
      computedItems,
      handleItemResize,
      handleScroll,
      handleScrollend,
      calculateVisibleItems,
      scrollToIndex
    } = useVirtual(props, flatItems);
    const displayItems = computed(() => computedItems.value.map(item => ({
      ...item.raw,
      virtualIndex: item.index
    })));

    // one virtual size per index = item row + optional expanded rows
    const rowHeights = new Map();
    const expandedHeights = new Map();
    function updateSize(index) {
      const expanded = expandedHeights.get(index)?.reduce((sum, height) => sum + (height || 0), 0) ?? 0;
      handleItemResize(index, (rowHeights.get(index) ?? 0) + expanded);
    }
    function setRowHeight(index, height) {
      rowHeights.set(index, height);
      updateSize(index);
    }
    function setExpandedHeight(index, row, height) {
      const heights = expandedHeights.get(index) ?? [];
      heights[row] = height;
      expandedHeights.set(index, heights);
      updateSize(index);
    }
    function trimExpandedHeights(index, count) {
      const heights = expandedHeights.get(index);
      if (!heights || heights.length <= count) return;
      heights.length = count;
      updateSize(index);
    }
    watch(expanded, () => {
      if (!slots['expanded-row']) return;
      for (const index of [...expandedHeights.keys()]) {
        const item = flatItems.value[index];
        if (item?.type === 'item' && isExpanded(item)) continue;
        expandedHeights.delete(index);
        updateSize(index);
      }
    });
    watch(flatItems, () => {
      rowHeights.clear();
      expandedHeights.clear();
    });
    useOptions({
      sortBy,
      page: shallowRef(1),
      itemsPerPage: shallowRef(-1),
      groupBy,
      search
    });
    provideDefaults({
      VDataTableRows: {
        hideNoData: toRef(() => props.hideNoData),
        noDataText: toRef(() => props.noDataText),
        loading: toRef(() => props.loading),
        loadingText: toRef(() => props.loadingText)
      }
    });
    const slotProps = computed(() => ({
      itemsLength: allItems.value.length,
      sortBy: sortBy.value,
      toggleSort,
      someSelected: someSelected.value,
      allSelected: allSelected.value,
      isSelected,
      select,
      selectAll,
      toggleSelect,
      isExpanded,
      toggleExpand,
      isGroupOpen,
      toggleGroup,
      items: allItems.value.map(item => item.raw),
      internalItems: allItems.value,
      groupedItems: flatItems.value,
      columns: columns.value,
      headers: headers.value
    }));
    useRender(() => {
      const dataTableHeadersProps = VDataTableHeaders.filterProps(omit(props, ['multiSort']));
      const dataTableRowsProps = VDataTableRows.filterProps(props);
      const tableProps = VTable.filterProps(props);
      const [tableAttrs] = pickWithRest(attrs, [/^aria-label/]);
      return createVNode(VTable, mergeProps({
        "class": ['v-data-table', {
          'v-data-table--loading': props.loading
        }, props.class],
        "style": props.style
      }, tableProps, {
        "fixedHeader": props.fixedHeader || props.sticky
      }), {
        top: () => slots.top?.(slotProps.value),
        wrapper: () => createElementVNode("div", {
          "ref": containerRef,
          "onScrollPassive": handleScroll,
          "onScrollend": handleScrollend,
          "class": "v-table__wrapper",
          "style": {
            height: convertToUnit(props.height)
          }
        }, [createElementVNode("table", normalizeProps(guardReactiveProps(tableAttrs)), [slots.caption?.(), slots.colgroup?.(slotProps.value), !props.hideDefaultHeader && createElementVNode("thead", {
          "key": "thead"
        }, [createVNode(VDataTableHeaders, mergeProps(dataTableHeadersProps, {
          "multiSort": !!props.multiSort
        }), slots)]), slots.thead?.(slotProps.value), !props.hideDefaultBody && createElementVNode("tbody", {
          "key": "tbody"
        }, [createElementVNode("tr", {
          "ref": markerRef,
          "style": {
            height: convertToUnit(paddingTop.value),
            border: 0
          }
        }, [createElementVNode("td", {
          "colspan": columns.value.length,
          "style": {
            height: 0,
            border: 0
          }
        }, null)]), slots['body.prepend']?.(slotProps.value), createVNode(VDataTableRows, mergeProps(attrs, dataTableRowsProps, {
          "items": displayItems.value,
          "getMatches": getMatches
        }), {
          ...omit(slots, ['expanded', 'expanded-row']),
          item: itemSlotProps => {
            const {
              props: rowProps,
              ...itemSlot
            } = itemSlotProps;
            const index = itemSlotProps.internalItem.virtualIndex ?? itemSlotProps.internalItem.index;
            const itemExpanded = isExpanded(itemSlotProps.internalItem);
            const expandedRows = props.showExpand && itemExpanded && slots['expanded-row'] ? elementNodes(slots['expanded-row'](itemSlot)) : [];

            // rows that stay never resize, so a shrunk slot reports nothing
            if (slots['expanded-row'] && (expandedHeights.get(index)?.length ?? 0) > expandedRows.length) {
              nextTick(() => trimExpandedHeights(index, expandedRows.length));
            }
            return createElementVNode(Fragment, null, [createVNode(VVirtualScrollItem, {
              "key": index,
              "renderless": true,
              "onUpdate:height": height => setRowHeight(index, height)
            }, {
              default: ({
                itemRef
              }) => slots.item?.({
                ...itemSlotProps,
                itemRef
              }) ?? createVNode(VDataTableRow, mergeProps(rowProps, {
                "ref": itemRef,
                "index": itemSlotProps.index,
                "getMatches": getMatches
              }), slots)
            }), props.showExpand && (slots['expanded-row'] ? expandedRows.map((node, row) => createVNode(VVirtualScrollItem, {
              "key": `${index}-expanded-${row}`,
              "renderless": true,
              "onUpdate:height": height => setExpandedHeight(index, row, height)
            }, {
              default: ({
                itemRef
              }) => cloneVNode(node, {
                ref: itemRef
              }, true)
            })) : slots.expanded && createVNode(VVirtualScrollItem, {
              "key": `${index}-expanded`,
              "renderless": true,
              "onUpdate:height": height => setExpandedHeight(index, 0, height)
            }, {
              default: ({
                itemRef
              }) => createElementVNode("tr", {
                "class": "v-data-table__tr--expanded",
                "ref": itemRef
              }, [createElementVNode("td", {
                "colspan": columns.value.length
              }, [props.expandTransition ? createVNode(MaybeTransition, {
                "transition": props.expandTransition
              }, {
                default: () => [itemExpanded ? createElementVNode("div", null, [slots.expanded(itemSlot)]) : null]
              }) // bypass <Transition> to avoid flash when expand-strategy=single
              : itemExpanded && createElementVNode("div", null, [slots.expanded(itemSlot)])])])
            }))]);
          }
        }), slots['body.append']?.(slotProps.value), createElementVNode("tr", {
          "style": {
            height: convertToUnit(paddingBottom.value),
            border: 0
          }
        }, [createElementVNode("td", {
          "colspan": columns.value.length,
          "style": {
            height: 0,
            border: 0
          }
        }, null)])]), slots.tbody?.(slotProps.value), slots.tfoot?.(slotProps.value)])]),
        bottom: () => slots.bottom?.(slotProps.value)
      });
    });
    return {
      calculateVisibleItems,
      scrollToIndex
    };
  }
});

// Types

const makeVDataTableServerProps = propsFactory({
  itemsLength: {
    type: [Number, String],
    required: true
  },
  ...makeDataTablePaginateProps(),
  ...makeDataTableProps(),
  ...makeVDataTableFooterProps()
}, 'VDataTableServer');
const VDataTableServer = genericComponent()({
  name: 'VDataTableServer',
  props: makeVDataTableServerProps(),
  emits: {
    'update:modelValue': value => true,
    'update:page': page => true,
    'update:itemsPerPage': page => true,
    'update:sortBy': sortBy => true,
    'update:options': options => true,
    'update:expanded': options => true,
    'update:groupBy': value => true,
    'update:opened': value => true
  },
  setup(props, {
    attrs,
    slots
  }) {
    const {
      groupBy,
      opened,
      openAll,
      groupKey
    } = createGroupBy(props);
    const {
      initialSortOrder,
      sortBy,
      multiSort,
      mustSort
    } = createSort(props);
    const {
      page,
      itemsPerPage
    } = createPagination(props);
    const {
      disableSort
    } = toRefs(props);
    const itemsLength = computed(() => parseInt(props.itemsLength, 10));
    const {
      columns,
      headers
    } = createHeaders(props, {
      groupBy,
      showSelect: toRef(() => props.showSelect),
      showExpand: toRef(() => props.showExpand)
    });
    const {
      items
    } = useDataTableItems(props, columns);
    const {
      toggleSort
    } = provideSort({
      initialSortOrder,
      sortBy,
      multiSort,
      mustSort,
      page
    });
    const {
      opened: openedGroups,
      isGroupOpen,
      toggleGroup,
      extractRows
    } = provideGroupBy({
      groupBy,
      sortBy,
      disableSort,
      opened
    });
    useOpenAllGroups(openedGroups, openAll, items, groupBy, groupKey);
    const {
      pageCount,
      setItemsPerPage,
      prevPage,
      nextPage,
      setPage
    } = providePagination({
      page,
      itemsPerPage,
      itemsLength
    });
    const {
      flatItems
    } = useGroupedItems(items, groupBy, openedGroups, () => !!slots['group-summary'], isGroupOpen, groupKey);
    const {
      isSelected,
      select,
      selectAll,
      toggleSelect,
      someSelected,
      allSelected
    } = provideSelection(props, {
      allItems: items,
      currentPage: items
    });
    const {
      isExpanded,
      toggleExpand
    } = provideExpanded(props);
    const itemsWithoutGroups = computed(() => extractRows(items.value));
    useOptions({
      page,
      itemsPerPage,
      sortBy,
      groupBy,
      search: toRef(() => props.search)
    });
    provide('v-data-table', {
      toggleSort,
      sortBy
    });
    provideDefaults({
      VDataTableRows: {
        hideNoData: toRef(() => props.hideNoData),
        noDataText: toRef(() => props.noDataText),
        loading: toRef(() => props.loading),
        loadingText: toRef(() => props.loadingText)
      }
    });
    const slotProps = computed(() => ({
      page: page.value,
      itemsPerPage: itemsPerPage.value,
      itemsLength: itemsLength.value,
      sortBy: sortBy.value,
      pageCount: pageCount.value,
      toggleSort,
      setItemsPerPage,
      prevPage,
      nextPage,
      setPage,
      someSelected: someSelected.value,
      allSelected: allSelected.value,
      isSelected,
      select,
      selectAll,
      toggleSelect,
      isExpanded,
      toggleExpand,
      isGroupOpen,
      toggleGroup,
      items: itemsWithoutGroups.value.map(item => item.raw),
      internalItems: itemsWithoutGroups.value,
      groupedItems: flatItems.value,
      columns: columns.value,
      headers: headers.value
    }));
    useRender(() => {
      const dataTableFooterProps = VDataTableFooter.filterProps(props);
      const dataTableHeadersProps = VDataTableHeaders.filterProps(omit(props, ['multiSort']));
      const dataTableRowsProps = VDataTableRows.filterProps(props);
      const tableProps = VTable.filterProps(props);
      return createVNode(VTable, mergeProps({
        "class": ['v-data-table', {
          'v-data-table--loading': props.loading
        }, props.class],
        "style": props.style
      }, tableProps, {
        "fixedHeader": props.fixedHeader || props.sticky
      }), {
        top: () => slots.top?.(slotProps.value),
        caption: slots.caption,
        default: () => slots.default ? slots.default(slotProps.value) : createElementVNode(Fragment, null, [slots.colgroup?.(slotProps.value), !props.hideDefaultHeader && createElementVNode("thead", {
          "key": "thead",
          "class": "v-data-table__thead",
          "role": "rowgroup"
        }, [createVNode(VDataTableHeaders, mergeProps(dataTableHeadersProps, {
          "multiSort": !!props.multiSort
        }), slots)]), slots.thead?.(slotProps.value), !props.hideDefaultBody && createElementVNode("tbody", {
          "class": "v-data-table__tbody",
          "role": "rowgroup"
        }, [slots['body.prepend']?.(slotProps.value), slots.body ? slots.body(slotProps.value) : createVNode(VDataTableRows, mergeProps(attrs, dataTableRowsProps, {
          "items": flatItems.value
        }), slots), slots['body.append']?.(slotProps.value)]), slots.tbody?.(slotProps.value), slots.tfoot?.(slotProps.value)]),
        bottom: () => slots.bottom ? slots.bottom(slotProps.value) : !props.hideDefaultFooter && createElementVNode(Fragment, null, [createVNode(VDivider, null, null), createVNode(VDataTableFooter, dataTableFooterProps, {
          prepend: slots['footer.prepend']
        })])
      });
    });
  }
});

const makeVContainerProps = propsFactory({
  fluid: {
    type: Boolean,
    default: false
  },
  ...makeComponentProps(),
  ...makeDimensionProps(),
  ...makeTagProps()
}, 'VContainer');
const VContainer = genericComponent()({
  name: 'VContainer',
  props: makeVContainerProps(),
  setup(props, {
    slots
  }) {
    const {
      rtlClasses
    } = useRtl();
    const {
      dimensionStyles
    } = useDimension(props);
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-container', {
        'v-container--fluid': props.fluid
      }, rtlClasses.value, props.class]),
      "style": normalizeStyle([dimensionStyles.value, props.style])
    }, slots));
    return {};
  }
});

// Styles

// Types

const breakpointProps = (() => {
  return breakpoints.reduce((props, val) => {
    props[val] = {
      type: [Boolean, String, Number],
      default: false
    };
    return props;
  }, {});
})();
const offsetProps = (() => {
  return breakpoints.reduce((props, val) => {
    const offsetKey = 'offset' + capitalize(val);
    props[offsetKey] = {
      type: [String, Number],
      default: null
    };
    return props;
  }, {});
})();
const propMap$1 = {
  col: keys(breakpointProps),
  offset: keys(offsetProps),
  order: ['order', 'orderSm', 'orderMd', 'orderLg', 'orderXl', 'orderXxl']
};
function parseCols(val) {
  if (typeof val === 'string' && val.includes('/')) {
    const [cols, size] = val.split('/');
    return {
      cols: Number(cols),
      size: Number(size)
    };
  }
  return {
    cols: val
  };
}
function parseBreakpoint(type, prop, val) {
  if (val == null || val === false) {
    return {};
  }
  const {
    cols,
    size
  } = parseCols(val);
  const breakpoint = prop.replace(type, '').toLowerCase();
  if (type === 'offset') {
    return {
      className: `v-col--offset-${breakpoint}-${cols}`,
      variables: [{
        [`--v-col-offset-base-${breakpoint}`]: size
      }]
    };
  } else if (type === 'order') {
    return {
      className: `order-${breakpoint}-${cols}`
    };
  }

  // Handling the boolean style prop when accepting [Boolean, String, Number]
  // means Vue will not convert <v-col sm></v-col> to sm: true for us.
  // Since the default is false, an empty string indicates the prop's presence.
  return {
    className: cols === '' || cols === true ? `v-col--${breakpoint}` : `v-col--cols-${breakpoint}-${cols}`,
    variables: [{
      [`--v-col-size-base-${breakpoint}`]: size
    }]
  };
}
const ALIGN_SELF_VALUES = ['auto', 'start', 'end', 'center', 'baseline', 'stretch'];
const alignSelfValidator = str => ALIGN_SELF_VALUES.includes(str);
const makeVColProps = propsFactory({
  cols: {
    type: [Boolean, String, Number],
    default: false
  },
  ...breakpointProps,
  offset: {
    type: [String, Number],
    default: null
  },
  ...offsetProps,
  /** @deprecated use order-* class instead */
  order: {
    type: [String, Number],
    default: null
  },
  /** @deprecated use order-sm-* class instead */
  orderSm: {
    type: [String, Number],
    default: null
  },
  /** @deprecated use order-md-* class instead */
  orderMd: {
    type: [String, Number],
    default: null
  },
  /** @deprecated use order-lg-* class instead */
  orderLg: {
    type: [String, Number],
    default: null
  },
  /** @deprecated use order-xl-* class instead */
  orderXl: {
    type: [String, Number],
    default: null
  },
  /** @deprecated use order-xxl-* class instead */
  orderXxl: {
    type: [String, Number],
    default: null
  },
  /** @deprecated use align-self-* class instead */
  alignSelf: {
    type: String,
    default: null,
    validator: alignSelfValidator
  },
  ...makeComponentProps(),
  ...makeTagProps()
}, 'VCol');
const VCol = genericComponent()({
  name: 'VCol',
  props: makeVColProps(),
  setup(props, {
    slots
  }) {
    const sizeBaseOverride = computed(() => parseCols(props.cols).size);
    const offsetBaseOverride = computed(() => parseCols(props.offset).size);
    const responsive = computed(() => {
      const classList = ['v-col'];
      const variablesList = [];

      // Loop through `col`, `offset`, `order` breakpoint props
      let type;
      for (type in propMap$1) {
        propMap$1[type].forEach(prop => {
          const value = props[prop];
          const {
            className,
            variables
          } = parseBreakpoint(type, prop, value);
          if (className) classList.push(className);
          if (variables) variablesList.push(...variables);
        });
      }
      const {
        cols
      } = parseCols(props.cols);
      const {
        cols: offset
      } = parseCols(props.offset);
      classList.push({
        [`v-col--cols-${cols}`]: cols,
        [`v-col--offset-${offset}`]: offset,
        [`order-${props.order}`]: props.order,
        [`align-self-${props.alignSelf}`]: props.alignSelf
      });
      return {
        classes: classList,
        variables: variablesList
      };
    });
    return () => h(props.tag, {
      class: [responsive.value.classes, props.class],
      style: [{
        '--v-col-size-base': sizeBaseOverride.value
      }, {
        '--v-col-offset-base': offsetBaseOverride.value
      }, responsive.value.variables, props.style]
    }, slots.default?.());
  }
});

// Styles

// Types

const ALIGNMENT = ['start', 'end', 'center'];
const SPACE = ['space-between', 'space-around', 'space-evenly'];
const ALIGN_VALUES = [...ALIGNMENT, 'baseline', 'stretch'];
const alignValidator = str => ALIGN_VALUES.includes(str);
const JUSTIFY_VALUES = [...ALIGNMENT, ...SPACE];
const justifyValidator = str => JUSTIFY_VALUES.includes(str);
const ALIGN_CONTENT_VALUES = [...ALIGNMENT, ...SPACE, 'stretch'];
const alignContentValidator = str => ALIGN_CONTENT_VALUES.includes(str);
const propMap = {
  align: ['align', 'alignSm', 'alignMd', 'alignLg', 'alignXl', 'alignXxl'],
  justify: ['justify', 'justifySm', 'justifyMd', 'justifyLg', 'justifyXl', 'justifyXxl'],
  alignContent: ['alignContent', 'alignContentSm', 'alignContentMd', 'alignContentLg', 'alignContentXl', 'alignContentXxl']
};
const classMap = {
  align: 'align',
  justify: 'justify',
  alignContent: 'align-content'
};
function breakpointClass(type, prop, val) {
  let className = classMap[type];
  if (val == null) {
    return undefined;
  }
  if (prop) {
    // alignSm -> Sm
    const breakpoint = prop.replace(type, '');
    className += `-${breakpoint}`;
  }
  // .align-items-sm-center
  className += `-${val}`;
  return className.toLowerCase();
}
const makeVRowProps = propsFactory({
  /** @deprecated use density="compact" instead */
  dense: Boolean,
  /** @deprecated use align-* class instead */
  align: {
    type: String,
    default: null,
    validator: alignValidator
  },
  /** @deprecated use align-sm-* class instead */
  alignSm: {
    type: String,
    default: null,
    validator: alignValidator
  },
  /** @deprecated use align-md-* class instead */
  alignMd: {
    type: String,
    default: null,
    validator: alignValidator
  },
  /** @deprecated use align-lg-* class instead */
  alignLg: {
    type: String,
    default: null,
    validator: alignValidator
  },
  /** @deprecated use align-xl-* class instead */
  alignXl: {
    type: String,
    default: null,
    validator: alignValidator
  },
  /** @deprecated use align-xxl-* class instead */
  alignXxl: {
    type: String,
    default: null,
    validator: alignValidator
  },
  /** @deprecated use justify-* class instead */
  justify: {
    type: String,
    default: null,
    validator: justifyValidator
  },
  /** @deprecated use justify-sm-* class instead */
  justifySm: {
    type: String,
    default: null,
    validator: justifyValidator
  },
  /** @deprecated use justify-md-* class instead */
  justifyMd: {
    type: String,
    default: null,
    validator: justifyValidator
  },
  /** @deprecated use justify-lg-* class instead */
  justifyLg: {
    type: String,
    default: null,
    validator: justifyValidator
  },
  /** @deprecated use justify-xl-* class instead */
  justifyXl: {
    type: String,
    default: null,
    validator: justifyValidator
  },
  /** @deprecated use justify-xxl-* class instead */
  justifyXxl: {
    type: String,
    default: null,
    validator: justifyValidator
  },
  /** @deprecated use align-content-* class instead */
  alignContent: {
    type: String,
    default: null,
    validator: alignContentValidator
  },
  /** @deprecated use align-content-sm-* class instead */
  alignContentSm: {
    type: String,
    default: null,
    validator: alignContentValidator
  },
  /** @deprecated use align-content-md-* class instead */
  alignContentMd: {
    type: String,
    default: null,
    validator: alignContentValidator
  },
  /** @deprecated use align-content-lg-* class instead */
  alignContentLg: {
    type: String,
    default: null,
    validator: alignContentValidator
  },
  /** @deprecated use align-content-xl-* class instead */
  alignContentXl: {
    type: String,
    default: null,
    validator: alignContentValidator
  },
  /** @deprecated use align-content-xxl-* class instead */
  alignContentXxl: {
    type: String,
    default: null,
    validator: alignContentValidator
  },
  noGutters: Boolean,
  gap: [Number, String, Array],
  size: [Number, String],
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeTagProps()
}, 'VRow');
const VRow = genericComponent()({
  name: 'VRow',
  props: makeVRowProps(),
  setup(props, {
    slots
  }) {
    if (props.dense) {
      deprecate('dense', 'density="compact"');
    }
    const classes = computed(() => {
      const classList = [];

      // Loop through `align`, `justify`, `alignContent` breakpoint props
      let type;
      for (type in propMap) {
        propMap[type].forEach(prop => {
          const value = props[prop];
          const className = breakpointClass(type, prop, value);
          if (className) classList.push(className);
        });
      }
      classList.push({
        'v-row--no-gutters': props.noGutters,
        'v-row--density-default': props.density === 'default' && !props.noGutters && !props.dense,
        'v-row--density-compact': props.density === 'compact' || props.dense,
        'v-row--density-comfortable': props.density === 'comfortable',
        [`align-${props.align}`]: props.align,
        [`justify-${props.justify}`]: props.justify,
        [`align-content-${props.alignContent}`]: props.alignContent
      });
      return classList;
    });
    const horizontalGap = computed(() => {
      return Array.isArray(props.gap) ? convertToUnit(props.gap[0] || 0) : convertToUnit(props.gap);
    });
    const verticalGap = computed(() => {
      return Array.isArray(props.gap) ? convertToUnit(props.gap[1] || 0) : horizontalGap.value;
    });
    return () => h(props.tag, {
      class: ['v-row', classes.value, props.class],
      style: [{
        '--v-col-gap-x': horizontalGap.value,
        '--v-col-gap-y': verticalGap.value,
        '--v-row-columns': props.size
      }, props.style]
    }, slots.default?.());
  }
});

// Styles
const VSpacer = createSimpleFunctional('v-spacer', 'div', 'VSpacer');

// Types

const makeVDatePickerControlsProps = propsFactory({
  active: {
    type: [String, Array],
    default: undefined
  },
  controlHeight: [Number, String],
  controlVariant: {
    type: String,
    default: 'docked'
  },
  noMonthPicker: Boolean,
  disabled: {
    type: [Boolean, String, Array],
    default: null
  },
  nextIcon: {
    type: IconValue,
    default: '$next'
  },
  prevIcon: {
    type: IconValue,
    default: '$prev'
  },
  modeIcon: {
    type: IconValue,
    default: '$subgroup'
  },
  text: String,
  monthText: String,
  yearText: String,
  viewMode: {
    type: String,
    default: 'month'
  }
}, 'VDatePickerControls');
const VDatePickerControls = genericComponent()({
  name: 'VDatePickerControls',
  props: makeVDatePickerControlsProps(),
  emits: {
    'click:year': () => true,
    'click:month': () => true,
    'click:prev': () => true,
    'click:next': () => true,
    'click:prev-year': () => true,
    'click:next-year': () => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    const disableMonth = computed(() => {
      return Array.isArray(props.disabled) ? props.disabled.includes('text') : !!props.disabled;
    });
    const disableYear = computed(() => {
      return Array.isArray(props.disabled) ? props.disabled.includes('mode') : !!props.disabled;
    });
    const disablePrevMonth = computed(() => {
      return Array.isArray(props.disabled) ? props.disabled.includes('prev-month') : !!props.disabled;
    });
    const disableNextMonth = computed(() => {
      return Array.isArray(props.disabled) ? props.disabled.includes('next-month') : !!props.disabled;
    });
    const disablePrevYear = computed(() => {
      return Array.isArray(props.disabled) ? props.disabled.includes('prev-year') : !!props.disabled;
    });
    const disableNextYear = computed(() => {
      return Array.isArray(props.disabled) ? props.disabled.includes('next-year') : !!props.disabled;
    });
    function onClickPrevMonth() {
      emit('click:prev');
    }
    function onClickNextMonth() {
      emit('click:next');
    }
    function onClickPrevYear() {
      emit('click:prev-year');
    }
    function onClickNextYear() {
      emit('click:next-year');
    }
    function onClickYear() {
      emit('click:year');
    }
    function onClickMonth() {
      emit('click:month');
    }
    useRender(() => {
      const innerDefaults = {
        VBtn: {
          density: 'comfortable',
          variant: 'text'
        }
      };
      const prevMonth = createVNode(VBtn, {
        "data-testid": "prev-month",
        "disabled": disablePrevMonth.value,
        "icon": props.prevIcon,
        "aria-label": t('$vuetify.datePicker.ariaLabel.previousMonth'),
        "onClick": onClickPrevMonth
      }, null);
      const nextMonth = createVNode(VBtn, {
        "data-testid": "next-month",
        "disabled": disableNextMonth.value,
        "icon": props.nextIcon,
        "aria-label": t('$vuetify.datePicker.ariaLabel.nextMonth'),
        "onClick": onClickNextMonth
      }, null);
      const prevYear = createVNode(VBtn, {
        "data-testid": "prev-year",
        "disabled": disablePrevYear.value,
        "icon": props.prevIcon,
        "aria-label": t('$vuetify.datePicker.ariaLabel.previousYear'),
        "onClick": onClickPrevYear
      }, null);
      const nextYear = createVNode(VBtn, {
        "data-testid": "next-year",
        "disabled": disableNextYear.value,
        "icon": props.nextIcon,
        "aria-label": t('$vuetify.datePicker.ariaLabel.nextYear'),
        "onClick": onClickNextYear
      }, null);
      const onlyMonthBtn = createVNode(VBtn, {
        "class": "v-date-picker-controls__only-month-btn",
        "data-testid": "month-btn",
        "density": "default",
        "disabled": disableMonth.value,
        "text": props.monthText,
        "appendIcon": props.modeIcon,
        "rounded": true,
        "aria-label": t('$vuetify.datePicker.ariaLabel.selectMonth'),
        "onClick": onClickMonth
      }, null);
      const onlyYearBtn = createVNode(VBtn, {
        "class": "v-date-picker-controls__only-year-btn",
        "data-testid": "year-btn",
        "density": "default",
        "disabled": disableYear.value,
        "text": props.yearText,
        "appendIcon": props.modeIcon,
        "rounded": true,
        "aria-label": t('$vuetify.datePicker.ariaLabel.selectYear'),
        "onClick": onClickYear
      }, null);
      const monthYearBtn = createVNode(VBtn, {
        "class": "v-date-picker-controls__year-btn",
        "data-testid": "year-btn",
        "density": "default",
        "disabled": disableYear.value,
        "text": props.text,
        "appendIcon": props.modeIcon,
        "rounded": true,
        "aria-label": t('$vuetify.datePicker.ariaLabel.selectYear'),
        "onClick": onClickYear
      }, null);
      const monthYearSplit = createElementVNode(Fragment, null, [createVNode(VBtn, {
        "class": "v-date-picker-controls__month-btn",
        "data-testid": "month-btn",
        "height": "36",
        "disabled": disableMonth.value,
        "text": props.text,
        "rounded": true,
        "aria-label": t('$vuetify.datePicker.ariaLabel.selectMonth'),
        "onClick": onClickMonth
      }, null), createVNode(VBtn, {
        "class": "v-date-picker-controls__mode-btn",
        "data-testid": "year-btn",
        "disabled": disableYear.value,
        "icon": props.modeIcon,
        "aria-label": t('$vuetify.datePicker.ariaLabel.selectYear'),
        "onClick": onClickYear
      }, null)]);
      const slotProps = {
        viewMode: props.viewMode,
        disabled: Array.isArray(props.disabled) ? props.disabled : [],
        monthYearText: props.text ?? '',
        monthText: props.monthText ?? '',
        yearText: props.yearText ?? '',
        openMonths: onClickMonth,
        openYears: onClickYear,
        prevMonth: onClickPrevMonth,
        nextMonth: onClickNextMonth,
        prevYear: onClickPrevYear,
        nextYear: onClickNextYear
      };
      const modalControls = createElementVNode(Fragment, null, [props.noMonthPicker ? monthYearBtn : monthYearSplit, createVNode(VSpacer, null, null), createElementVNode("div", {
        "class": "v-date-picker-controls__month"
      }, [prevMonth, nextMonth])]);
      const dockedControls = createElementVNode(Fragment, null, [createElementVNode("div", {
        "class": "v-date-picker-controls__month"
      }, [prevMonth, onlyMonthBtn, nextMonth]), createVNode(VSpacer, null, null), createElementVNode("div", {
        "class": "v-date-picker-controls__year"
      }, [prevYear, onlyYearBtn, nextYear])]);
      return createVNode(VDefaultsProvider, {
        "defaults": innerDefaults
      }, {
        default: () => [createElementVNode("div", {
          "class": normalizeClass(['v-date-picker-controls', `v-date-picker-controls--variant-${props.controlVariant}`]),
          "style": {
            '--v-date-picker-controls-height': convertToUnit(props.controlHeight)
          }
        }, [slots.default?.(slotProps) ?? createElementVNode(Fragment, null, [props.controlVariant === 'modal' && modalControls, props.controlVariant === 'docked' && dockedControls])])]
      });
    });
    return {};
  }
});

// Types

const makeVDatePickerHeaderProps = propsFactory({
  appendIcon: IconValue,
  color: String,
  header: String,
  transition: String,
  onClick: EventProp(),
  onClickOnce: EventProp()
}, 'VDatePickerHeader');
const VDatePickerHeader = genericComponent()({
  name: 'VDatePickerHeader',
  props: makeVDatePickerHeaderProps(),
  emits: {
    click: () => true,
    'click:append': () => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    function onClick() {
      emit('click');
    }
    function onClickAppend() {
      emit('click:append');
    }
    useRender(() => {
      const hasContent = !!(slots.default || props.header);
      const hasAppend = !!(slots.append || props.appendIcon);
      return createElementVNode("div", {
        "class": normalizeClass(['v-date-picker-header', {
          'v-date-picker-header--clickable': !!(props.onClick || props.onClickOnce)
        }, backgroundColorClasses.value]),
        "style": normalizeStyle(backgroundColorStyles.value),
        "onClick": (props.onClick || props.onClickOnce) && onClick
      }, [slots.prepend && createElementVNode("div", {
        "key": "prepend",
        "class": "v-date-picker-header__prepend"
      }, [slots.prepend()]), hasContent && createVNode(MaybeTransition, {
        "key": "content",
        "name": props.transition
      }, {
        default: () => [createElementVNode("div", {
          "key": props.header,
          "class": "v-date-picker-header__content"
        }, [slots.default?.() ?? props.header])]
      }), hasAppend && createElementVNode("div", {
        "class": "v-date-picker-header__append"
      }, [!slots.append ? createVNode(VBtn, {
        "key": "append-btn",
        "icon": props.appendIcon,
        "variant": "text",
        "onClick": onClickAppend
      }, null) : createVNode(VDefaultsProvider, {
        "key": "append-defaults",
        "disabled": !props.appendIcon,
        "defaults": {
          VBtn: {
            icon: props.appendIcon,
            variant: 'text'
          }
        }
      }, {
        default: () => [slots.append?.()]
      })])]);
    });
    return {};
  }
});

// Composables

// Types

// Types

// Composables
const makeCalendarProps = propsFactory({
  allowedDates: [Array, Function],
  disabled: {
    type: Boolean,
    default: null
  },
  displayValue: null,
  modelValue: Array,
  month: [Number, String],
  max: null,
  min: null,
  showAdjacentMonths: Boolean,
  year: [Number, String],
  weekdays: {
    type: Array,
    default: () => [0, 1, 2, 3, 4, 5, 6]
  },
  weeksInMonth: {
    type: String,
    default: 'dynamic'
  },
  firstDayOfWeek: {
    type: [Number, String],
    default: undefined
  },
  firstDayOfYear: {
    type: [Number, String],
    default: undefined
  },
  weekdayFormat: String
}, 'calendar');
function useCalendar(props) {
  const adapter = useDate();
  const model = useProxiedModel(props, 'modelValue', [], v => wrapInArray(v).map(i => adapter.date(i)));
  const displayValue = computed(() => {
    if (props.displayValue) return adapter.date(props.displayValue);
    if (model.value.length > 0) return adapter.date(model.value[0]);
    if (props.min) return adapter.date(props.min);
    if (Array.isArray(props.allowedDates)) return adapter.date(props.allowedDates[0]);
    return adapter.date();
  });
  const year = useProxiedModel(props, 'year', undefined, v => {
    const value = v != null ? Number(v) : adapter.getYear(displayValue.value);
    return adapter.startOfYear(adapter.setYear(adapter.date(), value));
  }, v => adapter.getYear(v));
  const month = useProxiedModel(props, 'month', undefined, v => {
    const value = v != null ? Number(v) : adapter.getMonth(displayValue.value);
    const date = adapter.setYear(adapter.startOfMonth(adapter.date()), adapter.getYear(year.value));
    return adapter.setMonth(date, value);
  }, v => adapter.getMonth(v));
  const weekdayLabels = computed(() => {
    const firstDayOfWeek = adapter.toJsDate(adapter.startOfWeek(adapter.date(), props.firstDayOfWeek)).getDay();
    return adapter.getWeekdays(props.firstDayOfWeek, props.weekdayFormat).filter((_, i) => props.weekdays.includes((i + firstDayOfWeek) % 7));
  });
  const weeksInMonth = computed(() => {
    const weeks = adapter.getWeekArray(month.value, props.firstDayOfWeek);
    const days = weeks.flat();

    // Make sure there's always 6 weeks in month (6 * 7 days)
    // if weeksInMonth is 'static'
    const daysInMonth = 6 * 7;
    if (props.weeksInMonth === 'static' && days.length < daysInMonth) {
      const lastDay = days[days.length - 1];
      let week = [];
      for (let day = 1; day <= daysInMonth - days.length; day++) {
        week.push(adapter.addDays(lastDay, day));
        if (day % 7 === 0) {
          weeks.push(week);
          week = [];
        }
      }
    }
    return weeks;
  });
  function genDays(days, today) {
    return days.filter(date => {
      return props.weekdays.includes(adapter.toJsDate(date).getDay());
    }).map((date, index) => {
      const isoDate = adapter.toISO(date);
      const isAdjacent = !adapter.isSameMonth(date, month.value);
      const isStart = adapter.isSameDay(date, adapter.startOfMonth(month.value));
      const isEnd = adapter.isSameDay(date, adapter.endOfMonth(month.value));
      const isSame = adapter.isSameDay(date, month.value);
      const weekdaysCount = props.weekdays.length;
      return {
        date,
        formatted: adapter.format(date, 'keyboardDate'),
        isAdjacent,
        isDisabled: isDisabled(date),
        isEnd,
        isHidden: isAdjacent && !props.showAdjacentMonths,
        isSame,
        isSelected: model.value.some(value => adapter.isSameDay(date, value)),
        isStart,
        isToday: adapter.isSameDay(date, today),
        isWeekEnd: index % weekdaysCount === weekdaysCount - 1,
        isWeekStart: index % weekdaysCount === 0,
        isoDate,
        localized: adapter.format(date, 'dayOfMonth'),
        month: adapter.getMonth(date),
        year: adapter.getYear(date)
      };
    });
  }
  const daysInWeek = computed(() => {
    const lastDay = adapter.startOfWeek(displayValue.value, props.firstDayOfWeek);
    const week = [];
    for (let day = 0; day <= 6; day++) {
      week.push(adapter.addDays(lastDay, day));
    }
    const today = adapter.date();
    return genDays(week, today);
  });
  const daysInMonth = computed(() => {
    const days = weeksInMonth.value.flat();
    const today = adapter.date();
    return genDays(days, today);
  });
  const weekNumbers = computed(() => {
    return weeksInMonth.value.map(week => {
      return week.length ? adapter.getWeek(week[0], props.firstDayOfWeek, props.firstDayOfYear) : null;
    });
  });
  const {
    minDate,
    maxDate
  } = useCalendarRange(props);
  function isDisabled(value) {
    if (props.disabled) return true;
    const date = adapter.date(value);
    if (minDate.value && adapter.isBefore(adapter.endOfDay(date), minDate.value)) return true;
    if (maxDate.value && adapter.isAfter(date, maxDate.value)) return true;
    if (Array.isArray(props.allowedDates) && props.allowedDates.length > 0) {
      return !props.allowedDates.some(d => adapter.isSameDay(adapter.date(d), date));
    }
    if (typeof props.allowedDates === 'function') {
      return !props.allowedDates(date);
    }
    return false;
  }
  return {
    displayValue,
    daysInMonth,
    daysInWeek,
    genDays,
    model,
    weeksInMonth,
    weekdayLabels,
    weekNumbers
  };
}
function useCalendarRange(props) {
  const adapter = useDate();
  const minDate = computed(() => {
    if (!props.min) return null;
    const date = adapter.date(props.min);
    return adapter.isValid(date) ? date : null;
  });
  const maxDate = computed(() => {
    if (!props.max) return null;
    const date = adapter.date(props.max);
    return adapter.isValid(date) ? date : null;
  });
  function clampDate(date) {
    if (minDate.value && adapter.isBefore(date, minDate.value)) {
      return minDate.value;
    }
    if (maxDate.value && adapter.isAfter(date, maxDate.value)) {
      return maxDate.value;
    }
    return date;
  }
  function isInAllowedRange(date) {
    return (!minDate.value || adapter.isAfter(date, minDate.value)) && (!maxDate.value || adapter.isBefore(date, maxDate.value));
  }
  return {
    minDate,
    maxDate,
    clampDate,
    isInAllowedRange
  };
}

// Utilities

// Types

// pulled from v0, should be replaced by direct v0 import in v5.0
// the only change was adapting to jsDOM by adding `?` in `el.scrollIntoView?.({ block: 'nearest' })`
function useVirtualFocus(items, options) {
  const {
    control,
    orientation = 'vertical',
    circular = false,
    columns: _columns,
    onHighlight
  } = options;
  const highlightedId = shallowRef();
  let previousEl = null;
  function applyHighlight(id) {
    const item = items().find(i => i.id === id);
    if (!item?.el) return false;
    const el = toValue(item.el);
    if (!el) return false;
    const controlEl = toValue(control);
    if (controlEl) {
      const itemId = el.getAttribute('id');
      if (itemId) controlEl.setAttribute('aria-activedescendant', itemId);
    }
    if (previousEl) delete previousEl.dataset.highlighted;
    el.dataset.highlighted = '';
    previousEl = el;
    el.scrollIntoView?.({
      block: 'nearest'
    });
    onHighlight?.(id);
    return true;
  }
  function mod(n, i) {
    return (i % n + n) % n;
  }
  function indexOf(id) {
    return items().findIndex(item => item.id === id);
  }
  function go(id) {
    highlightedId.value = id;
    applyHighlight(id);
  }
  function step(stride) {
    const all = items();
    if (!all.length) return;
    const current = highlightedId.value == null ? -1 : indexOf(highlightedId.value);
    const dir = stride > 0 ? 1 : -1;
    const abs = Math.abs(stride);
    const maxHops = Math.ceil(all.length / abs);
    let index = current + stride;
    let hops = 0;
    if (circular) {
      index = mod(all.length, index);
    } else if (index < 0 || index >= all.length) {
      return;
    }
    while (hops < maxHops) {
      const item = all[index];
      if (item && !toValue(item.disabled)) {
        go(item.id);
        return;
      }
      hops++;
      index = circular ? mod(all.length, index + stride) : index + dir * abs;
      if (!circular && (index < 0 || index >= all.length)) return;
    }
  }
  function first() {
    const item = items().find(i => !toValue(i.disabled));
    if (item) go(item.id);
  }
  function last() {
    const item = [...items()].reverse().find(i => !toValue(i.disabled));
    if (item) go(item.id);
  }
  function rowFirst() {
    const cols = toValue(_columns) ?? 0;
    if (!cols) return first();
    const all = items();
    const cur = highlightedId.value == null ? 0 : Math.max(0, indexOf(highlightedId.value));
    const start = cur - cur % cols;
    for (let i = start; i < Math.min(start + cols, all.length); i++) {
      if (!toValue(all[i]?.disabled)) {
        go(all[i].id);
        return;
      }
    }
  }
  function rowLast() {
    const cols = toValue(_columns) ?? 0;
    if (!cols) return last();
    const all = items();
    const cur = highlightedId.value == null ? 0 : Math.max(0, indexOf(highlightedId.value));
    const start = cur - cur % cols;
    const end = Math.min(start + cols, all.length);
    for (let i = end - 1; i >= start; i--) {
      if (!toValue(all[i]?.disabled)) {
        go(all[i].id);
        return;
      }
    }
  }
  function highlight(id) {
    const prev = highlightedId.value;
    highlightedId.value = id;
    if (!applyHighlight(id)) highlightedId.value = prev;
  }
  function focusHighlighted() {
    if (highlightedId.value == null) return;
    const item = items().find(i => i.id === highlightedId.value);
    if (!item?.el) return;
    toValue(item.el)?.focus();
  }
  function clear() {
    highlightedId.value = undefined;
    toValue(control)?.removeAttribute('aria-activedescendant');
    if (previousEl) {
      delete previousEl.dataset.highlighted;
      previousEl = null;
    }
  }
  function isRtl(e) {
    const el = e.currentTarget;
    return el ? getComputedStyle(el).direction === 'rtl' : false;
  }
  function onKeydown(e) {
    const cols = toValue(_columns);
    const rtl = isRtl(e);
    if (cols) {
      switch (e.key) {
        case 'ArrowRight':
          e.preventDefault();
          step(rtl ? -1 : 1);
          break;
        case 'ArrowLeft':
          e.preventDefault();
          step(rtl ? 1 : -1);
          break;
        case 'ArrowDown':
          e.preventDefault();
          step(cols);
          break;
        case 'ArrowUp':
          e.preventDefault();
          step(-cols);
          break;
        case 'Home':
          e.preventDefault();
          e.ctrlKey ? first() : rowFirst();
          break;
        case 'End':
          e.preventDefault();
          e.ctrlKey ? last() : rowLast();
          break;
      }
      return;
    }
    const prevKeys = [];
    const nextKeys = [];
    if (orientation === 'vertical' || orientation === 'both') {
      prevKeys.push('ArrowUp');
      nextKeys.push('ArrowDown');
    }
    if (orientation === 'horizontal' || orientation === 'both') {
      prevKeys.push(rtl ? 'ArrowRight' : 'ArrowLeft');
      nextKeys.push(rtl ? 'ArrowLeft' : 'ArrowRight');
    }
    if (prevKeys.includes(e.key)) {
      e.preventDefault();
      step(-1);
    } else if (nextKeys.includes(e.key)) {
      e.preventDefault();
      step(1);
    } else if (e.key === 'Home') {
      e.preventDefault();
      first();
    } else if (e.key === 'End') {
      e.preventDefault();
      last();
    }
  }
  onScopeDispose(clear);
  return {
    highlightedId,
    highlight,
    focusHighlighted,
    clear,
    next: () => step(1),
    prev: () => step(-1),
    first,
    last,
    onKeydown
  };
}

// Composables

// Types

function keyToDirection(key) {
  switch (key) {
    case 'ArrowUp':
      return 'up';
    case 'ArrowDown':
      return 'down';
    case 'ArrowLeft':
      return 'left';
    case 'ArrowRight':
      return 'right';
    default:
      return null;
  }
}
function useGridSelection({
  items,
  columns,
  initialValue,
  itemAttribute,
  onSelect,
  onNavigation,
  onHighlight,
  onEscape
}) {
  const hasFocusIn = shallowRef(false);
  const containerEl = shallowRef();
  const virtualFocus = useVirtualFocus(() => items().map(item => ({
    id: item.value,
    disabled: item.isDisabled,
    el: () => containerEl.value?.querySelector(`[${itemAttribute}="${item.value}"]`)
  })), {
    control: containerEl,
    columns
  });
  if (onHighlight) {
    watch(virtualFocus.highlightedId, id => onHighlight(id));
  }
  function onFocusin(e) {
    const grid = containerEl.value;
    if (!grid || grid.contains(e.relatedTarget)) return;
    hasFocusIn.value = true;
    const targetEl = e.target;
    const targetId = targetEl?.getAttribute?.(itemAttribute);
    if (targetId != null && items().some(item => String(item.value) === targetId)) {
      virtualFocus.highlight(targetId);
      return;
    }
    const initial = initialValue(virtualFocus.highlightedId.value);
    if (initial != null) virtualFocus.highlight(initial);
    virtualFocus.focusHighlighted();
  }
  function onFocusout(e) {
    if (containerEl.value?.contains(e.relatedTarget)) return;
    hasFocusIn.value = false;
    virtualFocus.clear();
  }
  function onActivate() {
    const id = virtualFocus.highlightedId.value;
    if (id == null) return;
    const item = items().find(x => x.value === id);
    if (item && !item.isDisabled) {
      onSelect(id);
    }
  }
  function selectItem(value) {
    virtualFocus.highlight(value);
    virtualFocus.focusHighlighted();
    onSelect(value);
  }
  function focusItem(value) {
    virtualFocus.highlight(value);
    if (virtualFocus.highlightedId.value == null) virtualFocus.first();
    virtualFocus.focusHighlighted();
  }
  function onContainerKeydown(e) {
    if (e.key === 'Escape') {
      e.preventDefault();
      onEscape?.();
      return;
    }
    if ((e.key === 'Enter' || e.key === ' ') && virtualFocus.highlightedId.value != null) {
      e.preventDefault();
      onActivate();
      return;
    }
    const direction = keyToDirection(e.key);
    if (direction && onNavigation?.(direction, e, virtualFocus.highlightedId.value)) return;
    virtualFocus.onKeydown(e);
    virtualFocus.focusHighlighted();
  }
  const containerProps = computed(() => ({
    ref: el => containerEl.value = el ?? undefined,
    tabindex: hasFocusIn.value ? -1 : 0,
    onKeydown: onContainerKeydown,
    onFocusin,
    onFocusout
  }));
  return {
    containerProps,
    containerEl,
    selectItem,
    focusItem,
    clear: virtualFocus.clear
  };
}

// Utilities

// Types

function useRangePicker({
  multiple,
  model,
  compare,
  normalizeEnd = v => v,
  previewValue: externalPreview
}) {
  const rangeStart = computed(() => model.value.length >= 1 ? model.value[0] : undefined);
  const rangeEnd = computed(() => model.value.length >= 2 ? model.value[model.value.length - 1] : undefined);
  const previewValue = externalPreview ?? shallowRef();
  const previewRange = computed(() => {
    if (multiple.value !== 'range') return null;
    if (!rangeStart.value || rangeEnd.value) return null;
    if (!previewValue.value) return null;
    const start = rangeStart.value;
    const preview = previewValue.value;
    if (compare(start, preview) === 0) return null;
    return compare(start, preview) < 0 ? [start, preview] : [preview, start];
  });
  function isSelected(value) {
    if (multiple.value === 'range' && model.value.length === 2) {
      return isWithinRange(value);
    }
    for (const v of model.value) {
      if (compare(v, value) === 0) return true;
    }
    return false;
  }
  function isWithinRange(value) {
    if (multiple.value !== 'range' || model.value.length < 2) return false;
    const [start, end] = [model.value[0], model.value[model.value.length - 1]];
    return compare(value, start) >= 0 && compare(value, end) <= 0;
  }
  function isRangeStart(value) {
    if (multiple.value !== 'range' || model.value.length < 2) return false;
    return compare(value, model.value[0]) === 0;
  }
  function isRangeEnd(value) {
    if (multiple.value !== 'range' || model.value.length < 2) return false;
    return compare(value, model.value[model.value.length - 1]) === 0;
  }
  function isRangeMiddle(value) {
    return isWithinRange(value) && !isRangeStart(value) && !isRangeEnd(value);
  }
  function select(value) {
    if (multiple.value === 'range') {
      onRangeSelect(value);
    } else if (multiple.value) {
      onMultipleSelect(value);
    } else {
      model.value = [value];
    }
  }
  function onRangeSelect(value) {
    if (model.value.length === 0) {
      model.value = [value];
    } else if (model.value.length === 1) {
      const start = model.value[0];
      if (compare(value, start) === 0) {
        model.value = [];
      } else if (compare(value, start) < 0) {
        model.value = [value, normalizeEnd(start)];
      } else {
        model.value = [start, normalizeEnd(value)];
      }
    } else {
      model.value = [value];
    }
  }
  function setPreview(value) {
    previewValue.value = value;
  }
  function clearPreview() {
    previewValue.value = undefined;
  }
  function isPreviewStart(value) {
    const range = previewRange.value;
    if (!range) return false;
    return compare(value, range[0]) === 0;
  }
  function isPreviewEnd(value) {
    const range = previewRange.value;
    if (!range) return false;
    return compare(value, range[1]) === 0;
  }
  function isPreviewMiddle(value) {
    const range = previewRange.value;
    if (!range) return false;
    return compare(value, range[0]) > 0 && compare(value, range[1]) < 0;
  }
  function isInPreviewRange(value) {
    return isPreviewStart(value) || isPreviewEnd(value) || isPreviewMiddle(value);
  }
  function onMultipleSelect(value) {
    const index = model.value.findIndex(v => compare(v, value) === 0);
    if (index === -1) {
      model.value = [...model.value, value];
    } else {
      const copy = [...model.value];
      copy.splice(index, 1);
      model.value = copy;
    }
  }
  return {
    isSelected,
    isRangeStart,
    isRangeEnd,
    isRangeMiddle,
    select,
    setPreview,
    clearPreview,
    isPreviewStart,
    isPreviewEnd,
    isPreviewMiddle,
    isInPreviewRange
  };
}

// Types

const makeVDatePickerMonthProps = propsFactory({
  color: String,
  hideWeekdays: Boolean,
  multiple: [Boolean, Number, String],
  showWeek: Boolean,
  readonly: Boolean,
  transition: {
    type: String,
    default: 'picker-transition'
  },
  reverseTransition: {
    type: String,
    default: 'picker-reverse-transition'
  },
  events: {
    type: [Array, Function, Object],
    default: () => null
  },
  eventColor: {
    type: [Array, Function, Object, String],
    default: () => null
  },
  noAutoNavigation: Boolean,
  previewValue: null,
  ...omit(makeCalendarProps(), ['displayValue'])
}, 'VDatePickerMonth');
const VDatePickerMonth = genericComponent()({
  name: 'VDatePickerMonth',
  props: makeVDatePickerMonthProps(),
  emits: {
    'update:modelValue': date => true,
    'update:month': date => true,
    'update:year': date => true,
    'update:previewValue': _value => true,
    'boundary-navigate': _payload => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const uid = useId();
    const {
      t
    } = useLocale();
    const {
      daysInMonth,
      model,
      weekNumbers,
      weekdayLabels
    } = useCalendar(props);
    const adapter = useDate();
    const isReverse = shallowRef(false);
    const transition = toRef(() => {
      return !isReverse.value ? props.transition : props.reverseTransition;
    });
    function compareDays(a, b) {
      if (adapter.isSameDay(a, b)) return 0;
      return adapter.isBefore(a, b) ? -1 : 1;
    }
    const previewValue = useProxiedModel(props, 'previewValue');
    const range = useRangePicker({
      multiple: computed(() => {
        if (props.multiple === 'range') return 'range';
        return !!props.multiple;
      }),
      model,
      compare: compareDays,
      normalizeEnd: value => adapter.endOfDay(value),
      previewValue
    });
    const selectionColor = toRef(() => props.color || 'surface-variant');
    const {
      backgroundColorClasses: rangeColorClasses,
      backgroundColorStyles: rangeColorStyles
    } = useBackgroundColor(selectionColor);
    const atMax = computed(() => {
      const max = ['number', 'string'].includes(typeof props.multiple) ? Number(props.multiple) : Infinity;
      return model.value.length >= max;
    });
    const dayRows = computed(() => {
      return chunkArray(daysInMonth.value, props.weekdays.length);
    });
    function isSelectedDay(item) {
      return range.isSelected(item.date);
    }
    function isDayDisabled(item) {
      return item.isDisabled || item.isHidden || atMax.value && !isSelectedDay(item);
    }
    function getDateAriaLabel(item) {
      const fullDate = adapter.format(item.date, 'fullDateWithWeekday');
      const localeKey = item.isToday ? 'currentDate' : 'selectDate';
      return t(`$vuetify.datePicker.ariaLabel.${localeKey}`, fullDate);
    }
    function onClick(value) {
      range.select(adapter.startOfDay(value));
    }
    function initialFocusDate(current) {
      const isVisible = d => !d.isAdjacent && !d.isDisabled;

      // Preserve existing highlight if it's still pointing to a visible day in the current grid
      if (current != null) {
        const cur = daysInMonth.value.find(d => d.isoDate === current);
        if (cur && !cur.isAdjacent) return current;
      }
      const selected = daysInMonth.value.find(d => isVisible(d) && model.value.some(m => adapter.isSameDay(m, d.date)));
      return (selected ?? daysInMonth.value.find(isVisible))?.isoDate;
    }
    const {
      containerProps,
      containerEl,
      selectItem,
      focusItem,
      clear
    } = useGridSelection({
      items: () => daysInMonth.value.map(d => ({
        value: d.isoDate,
        isDisabled: isDayDisabled(d)
      })),
      columns: () => props.weekdays.length,
      initialValue: initialFocusDate,
      itemAttribute: 'data-v-date',
      onSelect: onDaySelect,
      onNavigation: onNavigationBoundary,
      onEscape
    });
    function onDaySelect(isoDate) {
      const item = daysInMonth.value.find(d => d.isoDate === isoDate);
      if (!item || isDayDisabled(item)) return;
      onClick(item.date);
      if (item.isAdjacent) {
        emit('update:month', adapter.getMonth(item.date));
        emit('update:year', adapter.getYear(item.date));
        nextTick(() => focusItem(isoDate));
      }
    }
    function onNavigationBoundary(direction, e, curId) {
      if (curId == null) return false;
      const cols = props.weekdays.length;
      const rtl = getComputedStyle(e.currentTarget).direction === 'rtl';

      // stride = array-index delta; calendarDays = actual date offset for boundary crossing
      let stride;
      let calendarDays;
      if (direction === 'left') {
        stride = rtl ? 1 : -1;
        calendarDays = stride;
      } else if (direction === 'right') {
        stride = rtl ? -1 : 1;
        calendarDays = stride;
      } else if (direction === 'up') {
        stride = -cols;
        calendarDays = -7;
      } else {
        stride = cols;
        calendarDays = 7;
      }
      const all = daysInMonth.value;
      const curIndex = all.findIndex(d => d.isoDate === curId);
      if (curIndex < 0) return false;
      const targetItem = all[curIndex + stride];

      // isHidden = isAdjacent && !showAdjacentMonths — no button in DOM for this day
      if (targetItem && !targetItem.isHidden) return false;
      e.preventDefault();
      let targetIsoDate;
      if (targetItem) {
        targetIsoDate = targetItem.isoDate;
      } else {
        const step = calendarDays < 0 ? -1 : 1;
        let candidate = adapter.addDays(adapter.date(curId), calendarDays);
        while (!props.weekdays.includes(adapter.toJsDate(candidate).getDay())) {
          candidate = adapter.addDays(candidate, step);
        }
        targetIsoDate = adapter.toISO(candidate);
      }
      if (props.noAutoNavigation) {
        emit('boundary-navigate', {
          direction,
          targetIsoDate
        });
        return true;
      }
      const targetDate = adapter.date(targetIsoDate);
      emit('update:month', adapter.getMonth(targetDate));
      emit('update:year', adapter.getYear(targetDate));
      nextTick(() => focusItem(targetIsoDate));
      return true;
    }
    function onEscape() {
      const rawTarget = model.value[0] ?? adapter.date();
      const targetIso = adapter.toISO(adapter.date(rawTarget));
      const inCurrentMonth = daysInMonth.value.find(d => d.isoDate === targetIso && !d.isAdjacent);
      if (inCurrentMonth) {
        focusItem(targetIso);
        return;
      }
      const targetDate = adapter.date(rawTarget);
      emit('update:month', adapter.getMonth(targetDate));
      emit('update:year', adapter.getYear(targetDate));
      nextTick(() => focusItem(targetIso));
    }
    function onDayClick(item) {
      if (item.isAdjacent) {
        onDaySelect(item.isoDate);
      } else {
        selectItem(item.isoDate);
      }
    }
    function focusGrid() {
      containerEl.value?.focus();
    }
    watch(daysInMonth, (val, oldVal) => {
      if (!oldVal || val[0].isoDate === oldVal[0].isoDate) return; // only clear when the month actually changes

      isReverse.value = adapter.isBefore(val[0].date, oldVal[0].date);
      clear();
    });
    function getEventColors(date) {
      const {
        events,
        eventColor
      } = props;
      let eventData;
      let eventColors = [];
      if (Array.isArray(events)) {
        eventData = events.includes(date);
      } else if (events instanceof Function) {
        eventData = events(date) || false;
      } else if (events) {
        eventData = events[date] || false;
      } else {
        eventData = false;
      }
      if (!eventData) {
        return [];
      } else if (eventData !== true) {
        eventColors = wrapInArray(eventData);
      } else if (typeof eventColor === 'string') {
        eventColors = [eventColor];
      } else if (typeof eventColor === 'function') {
        eventColors = wrapInArray(eventColor(date));
      } else if (Array.isArray(eventColor)) {
        eventColors = eventColor;
      } else if (typeof eventColor === 'object' && eventColor !== null) {
        eventColors = wrapInArray(eventColor[date]);
      }

      // Fallback to default color if no color is found
      return !eventColors.length ? ['surface-variant'] : eventColors.filter(Boolean).map(color => typeof color === 'string' ? color : 'surface-variant');
    }
    function genEvents(date) {
      const eventColors = getEventColors(date);
      if (!eventColors.length) return null;
      return createElementVNode("div", {
        "class": "v-date-picker-month__events"
      }, [eventColors.map(color => createVNode(VBadge, {
        "dot": true,
        "color": color
      }, null))]);
    }
    useRender(() => createElementVNode("div", {
      "class": "v-date-picker-month",
      "style": {
        '--v-date-picker-days-in-week': props.weekdays.length
      }
    }, [props.showWeek && createElementVNode("div", {
      "key": "weeks",
      "class": "v-date-picker-month__weeks"
    }, [!props.hideWeekdays && createElementVNode("div", {
      "key": "hide-week-days",
      "class": "v-date-picker-month__day"
    }, [createTextVNode("\xA0")]), weekNumbers.value.map(week => createElementVNode("div", {
      "class": normalizeClass(['v-date-picker-month__day', 'v-date-picker-month__day--adjacent'])
    }, [week]))]), createVNode(MaybeTransition, {
      "name": transition.value
    }, {
      default: () => [createElementVNode("div", mergeProps({
        "key": daysInMonth.value[0].date?.toString(),
        "class": "v-date-picker-month__days",
        "role": "grid",
        "onMouseleave": range.clearPreview
      }, containerProps.value), [!props.hideWeekdays && createElementVNode("div", {
        "key": "weekday-labels",
        "class": "v-date-picker-month__days-row"
      }, [weekdayLabels.value.map(weekDay => createElementVNode("div", {
        "class": normalizeClass(['v-date-picker-month__day', 'v-date-picker-month__weekday'])
      }, [weekDay]))]), dayRows.value.map((row, rowIndex) => createElementVNode("div", {
        "class": "v-date-picker-month__days-row",
        "role": "row"
      }, [row.map((item, colIndex) => {
        const i = rowIndex * props.weekdays.length + colIndex;
        const isSelected = isSelectedDay(item);
        const disabled = isDayDisabled(item);
        const rangeStart = range.isRangeStart(item.date);
        const rangeEnd = range.isRangeEnd(item.date);
        const rangeMiddle = range.isRangeMiddle(item.date);
        const previewStart = range.isPreviewStart(item.date);
        const previewEnd = range.isPreviewEnd(item.date);
        const previewMiddle = range.isPreviewMiddle(item.date);
        const slotProps = {
          props: {
            class: 'v-date-picker-month__day-btn',
            color: isSelected && !rangeMiddle || item.isToday ? props.color : undefined,
            disabled,
            readonly: props.readonly,
            icon: true,
            ripple: false,
            tabindex: -1,
            variant: isSelected && !rangeMiddle ? 'flat' : item.isToday ? 'outlined' : 'text',
            'aria-label': getDateAriaLabel(item),
            'aria-current': item.isToday ? 'date' : undefined,
            id: `${uid}-day-${item.isoDate}`,
            'data-v-date': !disabled ? item.isoDate : undefined,
            onMousedown: e => e.preventDefault(),
            // preserve virtual focus
            onClick: () => onDayClick(item),
            onMouseenter: () => range.setPreview(item.date),
            onFocus: () => range.setPreview(item.date),
            onBlur: range.clearPreview
          },
          item,
          i
        };
        const hasRangeBg = rangeStart || rangeEnd || rangeMiddle;
        const hasPreviewBg = previewStart || previewEnd || previewMiddle;
        return createElementVNode("div", {
          "class": normalizeClass(['v-date-picker-month__day', {
            'v-date-picker-month__day--adjacent': item.isAdjacent,
            'v-date-picker-month__day--hide-adjacent': item.isHidden,
            'v-date-picker-month__day--selected': isSelected,
            'v-date-picker-month__day--week-end': item.isWeekEnd,
            'v-date-picker-month__day--week-start': item.isWeekStart,
            'v-date-picker-month__day--range-start': rangeStart,
            'v-date-picker-month__day--range-end': rangeEnd,
            'v-date-picker-month__day--range-middle': rangeMiddle,
            'v-date-picker-month__day--preview-start': previewStart,
            'v-date-picker-month__day--preview-end': previewEnd,
            'v-date-picker-month__day--preview-middle': previewMiddle
          }]),
          "role": "gridcell"
        }, [(hasRangeBg || hasPreviewBg) && createElementVNode("div", {
          "key": "range-bg",
          "class": normalizeClass(['v-date-picker-month__range-bg', hasRangeBg ? 'v-date-picker-month__range-bg--range' : 'v-date-picker-month__range-bg--preview', rangeColorClasses.value]),
          "style": normalizeStyle(rangeColorStyles.value)
        }, null), (props.showAdjacentMonths || !item.isAdjacent) && (slots.day?.(slotProps) ?? createVNode(VBtn, slotProps.props, {
          default: () => [item.localized, genEvents(item.isoDate)]
        }))]);
      })]))])]
    })]));
    return {
      focusGrid,
      focusItem
    };
  }
});

// Types

const makeVDatePickerMonthsProps = propsFactory({
  color: String,
  columns: {
    type: Number,
    default: 2
  },
  height: [String, Number],
  min: null,
  max: null,
  modelValue: Number,
  year: Number,
  allowedMonths: [Array, Function]
}, 'VDatePickerMonths');
const VDatePickerMonths = genericComponent()({
  name: 'VDatePickerMonths',
  props: makeVDatePickerMonthsProps(),
  emits: {
    'update:modelValue': date => true,
    escape: () => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const adapter = useDate();
    const model = useProxiedModel(props, 'modelValue');
    const uid = useId();
    const months = computed(() => {
      let date = adapter.startOfYear(adapter.date());
      if (props.year) {
        date = adapter.setYear(date, props.year);
      }
      return createRange(12).map(i => {
        const text = adapter.format(date, 'monthShort');
        const label = adapter.format(date, 'month');
        const isDisabled = !!(!isMonthAllowed(i) || props.min && adapter.isAfter(adapter.startOfMonth(adapter.date(props.min)), date) || props.max && adapter.isAfter(date, adapter.startOfMonth(adapter.date(props.max))));
        date = adapter.getNextMonth(date);
        return {
          isDisabled,
          text,
          label,
          value: i
        };
      });
    });
    watchEffect(() => {
      model.value = model.value ?? adapter.getMonth(adapter.date());
    });
    function isMonthAllowed(month) {
      if (Array.isArray(props.allowedMonths) && props.allowedMonths.length) {
        return props.allowedMonths.includes(month);
      }
      if (typeof props.allowedMonths === 'function') {
        return props.allowedMonths(month);
      }
      return true;
    }
    function onMonthSelect(value) {
      if (model.value === value) emit('update:modelValue', value);else model.value = value;
    }
    const {
      containerProps,
      selectItem
    } = useGridSelection({
      items: () => months.value,
      columns: () => props.columns,
      initialValue: current => current ?? model.value ?? adapter.getMonth(adapter.date()),
      itemAttribute: 'data-v-month',
      onSelect: onMonthSelect,
      onEscape: () => emit('escape')
    });
    useRender(() => createElementVNode("div", {
      "class": "v-date-picker-months",
      "style": {
        height: convertToUnit(props.height)
      }
    }, [createElementVNode("div", mergeProps({
      "class": "v-date-picker-months__content",
      "style": {
        '--v-date-picker-months-columns': props.columns
      }
    }, containerProps.value), [months.value.map((month, i) => {
      const btnProps = {
        id: `${uid}-month-${i}`,
        active: model.value === i,
        ariaLabel: month.label,
        color: model.value === i ? props.color : undefined,
        disabled: month.isDisabled,
        rounded: true,
        tabindex: -1,
        text: month.text,
        variant: model.value === month.value ? 'flat' : 'text',
        'data-v-month': month.value,
        onMousedown: e => e.preventDefault(),
        // preserve virtual focus
        onClick: () => selectItem(i)
      };
      return slots.month?.({
        month,
        i,
        props: btnProps
      }) ?? createVNode(VBtn, mergeProps({
        "key": "month"
      }, btnProps), null);
    })])]));
    return {};
  }
});

// Types

// Types

const makeVDatePickerYearsProps = propsFactory({
  color: String,
  columns: {
    type: Number,
    default: 3
  },
  height: [String, Number],
  min: null,
  max: null,
  modelValue: Number,
  allowedYears: [Array, Function]
}, 'VDatePickerYears');
const VDatePickerYears = genericComponent()({
  name: 'VDatePickerYears',
  props: makeVDatePickerYearsProps(),
  directives: {
    vIntersect: Intersect
  },
  emits: {
    'update:modelValue': year => true,
    escape: () => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const adapter = useDate();
    const model = useProxiedModel(props, 'modelValue');
    const containerRef = templateRef();
    const uid = useId();
    const years = computed(() => {
      const year = adapter.getYear(adapter.date());
      let min = year - 100;
      let max = year + 52;
      if (props.min) {
        min = adapter.getYear(adapter.date(props.min));
      }
      if (props.max) {
        max = adapter.getYear(adapter.date(props.max));
      }
      let date = adapter.startOfYear(adapter.date());
      date = adapter.setYear(date, min);
      return createRange(max - min + 1, min).map(i => {
        const text = adapter.format(date, 'year');
        date = adapter.setYear(date, adapter.getYear(date) + 1);
        return {
          text,
          value: i,
          isDisabled: !isYearAllowed(i)
        };
      });
    });
    watchEffect(() => {
      model.value = model.value ?? adapter.getYear(adapter.date());
    });
    function isYearAllowed(year) {
      if (Array.isArray(props.allowedYears) && props.allowedYears.length) {
        return props.allowedYears.includes(year);
      }
      if (typeof props.allowedYears === 'function') {
        return props.allowedYears(year);
      }
      return true;
    }
    function onYearSelect(value) {
      if (model.value === value) emit('update:modelValue', value);else model.value = value;
    }
    const {
      containerProps,
      containerEl,
      selectItem
    } = useGridSelection({
      items: () => years.value,
      columns: () => props.columns,
      initialValue: current => current ?? model.value ?? adapter.getYear(adapter.date()),
      itemAttribute: 'data-v-year',
      onSelect: onYearSelect,
      onEscape: () => emit('escape')
    });
    function scrollToSelected() {
      const container = containerRef.el;
      const target = containerEl.value?.querySelector(`[data-v-year="${model.value}"]`);
      if (!container || !target) return;
      const containerRect = container.getBoundingClientRect();
      const targetRect = target.getBoundingClientRect();
      container.scrollTop += targetRect.top - containerRect.top - container.clientHeight / 2 + targetRect.height / 2;
    }
    useRender(() => withDirectives(createElementVNode("div", {
      "class": "v-date-picker-years",
      "ref": containerRef,
      "tabindex": -1,
      "style": {
        height: convertToUnit(props.height)
      }
    }, [createElementVNode("div", mergeProps({
      "class": "v-date-picker-years__content",
      "style": {
        '--v-date-picker-years-columns': props.columns
      }
    }, containerProps.value), [years.value.map((year, i) => {
      const btnProps = {
        id: `${uid}-year-${year.value}`,
        active: model.value === year.value,
        color: model.value === year.value ? props.color : undefined,
        rounded: true,
        tabindex: -1,
        text: year.text,
        disabled: year.isDisabled,
        variant: model.value === year.value ? 'flat' : 'text',
        'data-v-year': year.value,
        onMousedown: e => e.preventDefault(),
        // preserve virtual focus
        onClick: () => selectItem(year.value)
      };
      return slots.year?.({
        year,
        i,
        props: btnProps
      }) ?? createVNode(VBtn, mergeProps({
        "key": "month"
      }, btnProps), null);
    })])]), [[Intersect, {
      handler: scrollToSelected
    }, null, {
      once: true
    }]]));
    return {};
  }
});

// Types

// Types

const makeVDatePickerProps = propsFactory({
  // TODO: implement in v3.5
  // calendarIcon: {
  //   type: String,
  //   default: '$calendar',
  // },
  // keyboardIcon: {
  //   type: String,
  //   default: '$edit',
  // },
  // inputMode: {
  //   type: String as PropType<'calendar' | 'keyboard'>,
  //   default: 'calendar',
  // },
  // inputText: {
  //   type: String,
  //   default: '$vuetify.datePicker.input.placeholder',
  // },
  // inputPlaceholder: {
  //   type: String,
  //   default: 'dd/mm/yyyy',
  // },
  header: {
    type: String,
    default: '$vuetify.datePicker.header'
  },
  headerColor: String,
  headerDateFormat: {
    type: String,
    default: 'normalDateWithWeekday'
  },
  landscapeHeaderWidth: [Number, String],
  ...omit(makeVDatePickerControlsProps(), ['active', 'monthText', 'yearText']),
  ...makeVDatePickerMonthProps({
    weeksInMonth: 'static'
  }),
  ...omit(makeVDatePickerMonthsProps(), ['modelValue', 'columns']),
  ...omit(makeVDatePickerYearsProps(), ['modelValue', 'columns']),
  ...makeVPickerProps({
    title: '$vuetify.datePicker.title'
  }),
  modelValue: null
}, 'VDatePicker');
const VDatePicker = genericComponent()({
  name: 'VDatePicker',
  props: makeVDatePickerProps(),
  emits: {
    'update:modelValue': date => true,
    'update:month': date => true,
    'update:year': date => true,
    'update:previewValue': _value => true,
    // 'update:inputMode': (date: any) => true,
    'update:viewMode': date => true,
    'boundary-navigate': _payload => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const adapter = useDate();
    const {
      t
    } = useLocale();
    const {
      rtlClasses
    } = useRtl();
    const model = useProxiedModel(props, 'modelValue', undefined, v => wrapInArray(v).map(i => adapter.date(i)), v => props.multiple ? v : v[0]);
    const viewMode = useProxiedModel(props, 'viewMode');
    // owns the hover preview so VDatePickerMonth isn't handed a prop nobody writes back
    const previewValue = useProxiedModel(props, 'previewValue');
    // const inputMode = useProxiedModel(props, 'inputMode')

    const {
      minDate,
      maxDate,
      clampDate
    } = useCalendarRange(props);
    const internal = computed(() => {
      const today = adapter.date();
      const value = model.value?.[0] ? adapter.date(model.value[0]) : clampDate(today);
      return value && adapter.isValid(value) ? value : today;
    });
    const headerColor = toRef(() => props.headerColor ?? props.color);
    const _month = useProxiedModel(props, 'month');
    const month = computed({
      get: () => Number(_month.value ?? adapter.getMonth(adapter.startOfMonth(internal.value))),
      set: v => _month.value = v
    });
    const _year = useProxiedModel(props, 'year');
    const year = computed({
      get: () => Number(_year.value ?? adapter.getYear(adapter.startOfYear(adapter.setMonth(internal.value, month.value)))),
      set: v => _year.value = v
    });
    const isReversing = shallowRef(false);
    const header = computed(() => {
      if (props.multiple === 'range' && model.value.length === 2) {
        const [startDate, endDate] = model.value;
        const daysBetween = adapter.getDiff(endDate, startDate, 'days') + 1;
        return t('$vuetify.datePicker.itemsSelected', daysBetween);
      }
      if (props.multiple && model.value.length > 1) {
        return t('$vuetify.datePicker.itemsSelected', model.value.length);
      }
      const formattedDate = model.value[0] && adapter.isValid(model.value[0]) ? adapter.format(adapter.date(model.value[0]), props.headerDateFormat) : t(props.header);
      return props.landscape && formattedDate.split(' ').length === 3 ? formattedDate.replace(' ', '\n') : formattedDate;
    });
    const monthStart = toRef(() => {
      let date = adapter.date();
      date = adapter.setDate(date, 1);
      date = adapter.setMonth(date, month.value);
      date = adapter.setYear(date, year.value); // year is not always ISO
      return date;
    });
    const monthYearText = toRef(() => adapter.format(monthStart.value, 'monthAndYear'));
    const monthText = toRef(() => adapter.format(monthStart.value, 'monthShort'));
    const yearText = toRef(() => adapter.format(monthStart.value, 'year'));

    // const headerIcon = toRef(() => props.inputMode === 'calendar' ? props.keyboardIcon : props.calendarIcon)
    const headerTransition = toRef(() => `date-picker-header${isReversing.value ? '-reverse' : ''}-transition`);
    const disabled = computed(() => {
      if (props.disabled) return true;
      const targets = [];
      if (viewMode.value !== 'month') {
        targets.push(...['prev-month', 'next-month', 'prev-year', 'next-year']);
      } else {
        let _date = adapter.date();
        _date = adapter.startOfMonth(_date);
        _date = adapter.setMonth(_date, month.value);
        _date = adapter.setYear(_date, year.value);
        if (minDate.value) {
          const prevMonthEnd = adapter.addDays(adapter.startOfMonth(_date), -1);
          const prevYearEnd = adapter.addDays(adapter.startOfYear(_date), -1);
          adapter.isAfter(minDate.value, prevMonthEnd) && targets.push('prev-month');
          adapter.isAfter(minDate.value, prevYearEnd) && targets.push('prev-year');
        }
        if (maxDate.value) {
          const nextMonthStart = adapter.addDays(adapter.endOfMonth(_date), 1);
          const nextYearStart = adapter.addDays(adapter.endOfYear(_date), 1);
          adapter.isAfter(nextMonthStart, maxDate.value) && targets.push('next-month');
          adapter.isAfter(nextYearStart, maxDate.value) && targets.push('next-year');
        }
      }
      return targets;
    });
    const allowedYears = computed(() => {
      return props.allowedYears || isYearAllowed;
    });
    const allowedMonths = computed(() => {
      return props.allowedMonths || isMonthAllowed;
    });
    function isAllowedInRange(start, end) {
      const allowedDates = props.allowedDates;
      if (typeof allowedDates !== 'function') return true;
      const days = 1 + daysDiff(adapter, start, end);
      for (let i = 0; i < days; i++) {
        if (allowedDates(adapter.addDays(start, i))) return true;
      }
      return false;
    }
    function isYearAllowed(year) {
      if (typeof props.allowedDates === 'function') {
        const startOfYear = adapter.parseISO(`${year}-01-01`);
        return isAllowedInRange(startOfYear, adapter.endOfYear(startOfYear));
      }
      if (Array.isArray(props.allowedDates) && props.allowedDates.length) {
        for (const date of props.allowedDates) {
          if (adapter.getYear(adapter.date(date)) === year) return true;
        }
        return false;
      }
      return true;
    }
    function isMonthAllowed(month) {
      if (typeof props.allowedDates === 'function') {
        const monthTwoDigits = String(month + 1).padStart(2, '0');
        const startOfMonth = adapter.parseISO(`${year.value}-${monthTwoDigits}-01`);
        return isAllowedInRange(startOfMonth, adapter.endOfMonth(startOfMonth));
      }
      if (Array.isArray(props.allowedDates) && props.allowedDates.length) {
        for (const date of props.allowedDates) {
          if (adapter.getYear(adapter.date(date)) === year.value && adapter.getMonth(adapter.date(date)) === month) return true;
        }
        return false;
      }
      return true;
    }

    // function onClickAppend () {
    //   inputMode.value = inputMode.value === 'calendar' ? 'keyboard' : 'calendar'
    // }

    function onClickNextMonth() {
      if (month.value < 11) {
        month.value++;
      } else {
        year.value++;
        month.value = 0;
        onUpdateYear();
      }
      onUpdateMonth();
    }
    function onClickPrevMonth() {
      if (month.value > 0) {
        month.value--;
      } else {
        year.value--;
        month.value = 11;
        onUpdateYear();
      }
      onUpdateMonth();
    }
    function onClickNextYear() {
      year.value++;
      if (maxDate.value) {
        const monthTwoDigits = String(month.value + 1).padStart(2, '0');
        const monthStart = adapter.parseISO(`${year.value}-${monthTwoDigits}-01`);
        if (adapter.isAfter(monthStart, maxDate.value)) {
          month.value = adapter.getMonth(maxDate.value);
        }
      }
      onUpdateYear();
    }
    function onClickPrevYear() {
      year.value--;
      if (minDate.value) {
        const monthTwoDigits = String(month.value + 1).padStart(2, '0');
        const monthStart = adapter.endOfMonth(adapter.parseISO(`${year.value}-${monthTwoDigits}-01`));
        if (adapter.isAfter(minDate.value, monthStart)) {
          month.value = adapter.getMonth(minDate.value);
        }
      }
      onUpdateYear();
    }
    const monthGridRef = shallowRef();
    function focusDate(isoDate) {
      monthGridRef.value?.focusItem(isoDate);
    }
    function onClickDate() {
      viewMode.value = 'month';
    }
    function onEscape() {
      viewMode.value = 'month';
      nextTick(() => monthGridRef.value?.focusGrid());
    }
    function onClickMonth() {
      viewMode.value = viewMode.value === 'months' ? 'month' : 'months';
    }
    function onClickYear() {
      viewMode.value = viewMode.value === 'year' ? 'month' : 'year';
    }
    function onUpdateMonth() {
      if (viewMode.value === 'months') onClickMonth();
    }
    function onUpdateYear() {
      if (viewMode.value === 'year') onClickYear();
    }
    watch(model, (val, oldVal) => {
      if (props.noAutoNavigation) return;
      const arrBefore = wrapInArray(oldVal);
      const arrAfter = wrapInArray(val);
      if (!arrAfter.length) return;
      const before = adapter.date(arrBefore[arrBefore.length - 1]);
      const after = adapter.date(arrAfter[arrAfter.length - 1]);
      if (adapter.isSameDay(before, after)) return;
      const newMonth = adapter.getMonth(after);
      const newYear = adapter.getYear(after);
      if (newMonth !== month.value) {
        month.value = newMonth;
        onUpdateMonth();
      }
      if (newYear !== year.value) {
        year.value = newYear;
        onUpdateYear();
      }
      isReversing.value = adapter.isBefore(before, after);
    });
    useRender(() => {
      const pickerProps = VPicker.filterProps(props);
      const datePickerControlsProps = omit(VDatePickerControls.filterProps(props), ['viewMode']);
      const datePickerHeaderProps = VDatePickerHeader.filterProps(props);
      const datePickerMonthProps = VDatePickerMonth.filterProps(props);
      const datePickerMonthsProps = omit(VDatePickerMonths.filterProps(props), ['modelValue']);
      const datePickerYearsProps = omit(VDatePickerYears.filterProps(props), ['modelValue']);
      const headerProps = {
        color: headerColor.value,
        header: header.value,
        transition: headerTransition.value
      };
      return createVNode(VPicker, mergeProps(pickerProps, {
        "color": headerColor.value,
        "class": ['v-date-picker', `v-date-picker--${viewMode.value}`, {
          'v-date-picker--show-week': props.showWeek
        }, rtlClasses.value, props.class],
        "style": [{
          '--v-date-picker-landscape-header-width': convertToUnit(props.landscapeHeaderWidth)
        }, props.style]
      }), {
        title: () => slots.title?.() ?? createElementVNode("div", {
          "class": "v-date-picker__title"
        }, [t(props.title)]),
        header: () => slots.header ? createVNode(VDefaultsProvider, {
          "defaults": {
            VDatePickerHeader: {
              ...headerProps
            }
          }
        }, {
          default: () => [slots.header?.(headerProps)]
        }) : createVNode(VDatePickerHeader, mergeProps({
          "key": "header"
        }, datePickerHeaderProps, headerProps, {
          "onClick": viewMode.value !== 'month' ? onClickDate : undefined
        }), {
          prepend: slots.prepend,
          append: slots.append
        }),
        default: () => createElementVNode(Fragment, null, [createVNode(VDatePickerControls, mergeProps(datePickerControlsProps, {
          "disabled": disabled.value,
          "viewMode": viewMode.value,
          "text": monthYearText.value,
          "monthText": monthText.value,
          "yearText": yearText.value,
          "onClick:next": onClickNextMonth,
          "onClick:prev": onClickPrevMonth,
          "onClick:nextYear": onClickNextYear,
          "onClick:prevYear": onClickPrevYear,
          "onClick:month": onClickMonth,
          "onClick:year": onClickYear
        }), {
          default: slots.controls
        }), createVNode(VFadeTransition, {
          "hideOnLeave": true
        }, {
          default: () => [viewMode.value === 'months' ? createVNode(VDatePickerMonths, mergeProps({
            "key": "date-picker-months"
          }, datePickerMonthsProps, {
            "modelValue": month.value,
            "onUpdate:modelValue": [$event => month.value = $event, onUpdateMonth],
            "min": minDate.value,
            "max": maxDate.value,
            "year": year.value,
            "allowedMonths": allowedMonths.value,
            "onEscape": onEscape
          }), {
            month: slots.month
          }) : viewMode.value === 'year' ? createVNode(VDatePickerYears, mergeProps({
            "key": "date-picker-years"
          }, datePickerYearsProps, {
            "modelValue": year.value,
            "onUpdate:modelValue": [$event => year.value = $event, onUpdateYear],
            "min": minDate.value,
            "max": maxDate.value,
            "allowedYears": allowedYears.value,
            "onEscape": onEscape
          }), {
            year: slots.year
          }) : createVNode(VDatePickerMonth, mergeProps({
            "ref": monthGridRef,
            "key": "date-picker-month"
          }, datePickerMonthProps, {
            "modelValue": model.value,
            "onUpdate:modelValue": $event => model.value = $event,
            "month": month.value,
            "onUpdate:month": [$event => month.value = $event, onUpdateMonth],
            "year": year.value,
            "onUpdate:year": [$event => year.value = $event, onUpdateYear],
            "previewValue": previewValue.value,
            "onUpdate:previewValue": $event => previewValue.value = $event,
            "onBoundaryNavigate": payload => emit('boundary-navigate', payload),
            "min": minDate.value,
            "max": maxDate.value
          }), {
            day: slots.day
          })]
        })]),
        actions: slots.actions
      });
    });
    return {
      focusDate
    };
  }
});

// Composables

// Types

// Types

class DateFormatSpec {
  constructor(order,
  // mdy | dmy | ymd
  separator // / | - | .
  ) {
    this.order = order;
    this.separator = separator;
  }
  get format() {
    return this.order.split('').map(sign => `${sign}${sign}`).join(this.separator).replace('yy', 'yyyy');
  }
  static canBeParsed(v) {
    if (typeof v !== 'string') return false;
    const lowercase = v.toLowerCase();
    return ['y', 'm', 'd'].every(sign => lowercase.includes(sign)) && ['/', '-', '.'].some(sign => v.includes(sign));
  }
  static parse(v) {
    if (!DateFormatSpec.canBeParsed(v)) {
      throw new Error(`[${v}] cannot be parsed into date format specification`);
    }
    const order = v.toLowerCase().split('').filter((c, i, all) => 'dmy'.includes(c) && all.indexOf(c) === i).join('');
    const separator = ['/', '-', '.'].find(sign => v.includes(sign));
    return new DateFormatSpec(order, separator);
  }
}
const makeDateFormatProps = propsFactory({
  inputFormat: {
    type: String,
    validator: v => !v || DateFormatSpec.canBeParsed(v)
  }
}, 'date-format');
function useDateFormat(props, locale) {
  const adapter = useDate();
  function inferFromLocale() {
    const localeForDateFormat = locale.value ?? 'en-US';
    const formatFromLocale = Intl.DateTimeFormat(localeForDateFormat, {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit'
    }).format(adapter.toJsDate(adapter.parseISO('1999-12-07'))).replace(/(07)|(٠٧)|(٢٩)|(۱۶)|(০৭)/, 'dd').replace(/(12)|(١٢)|(٠٨)|(۰۹)|(১২)/, 'mm').replace(/(1999)|(2542)|(١٩٩٩)|(١٤٢٠)|(۱۳۷۸)|(১৯৯৯)/, 'yyyy').replace(/[^ymd\-/.]/g, '').replace(/\.$/, '');
    if (!DateFormatSpec.canBeParsed(formatFromLocale)) {
      consoleWarn(`Date format inferred from locale [${localeForDateFormat}] is invalid: [${formatFromLocale}]`);
      return 'mm/dd/yyyy';
    }
    return formatFromLocale;
  }
  const currentFormat = toRef(() => {
    return DateFormatSpec.canBeParsed(props.inputFormat) ? DateFormatSpec.parse(props.inputFormat) : DateFormatSpec.parse(inferFromLocale());
  });
  function parseDate(dateString) {
    function parseDateParts(text) {
      const parts = text.trim().split(currentFormat.value.separator);
      return {
        y: Number(parts[currentFormat.value.order.indexOf('y')]),
        m: Number(parts[currentFormat.value.order.indexOf('m')]),
        d: Number(parts[currentFormat.value.order.indexOf('d')])
      };
    }
    function validateDateParts(dateParts) {
      const {
        y: year,
        m: month,
        d: day
      } = dateParts;
      if (!year || !month || !day) return null;
      if (month < 1 || month > 12) return null;
      if (day < 1 || day > 31) return null;
      return {
        year: autoFixYear(year),
        month,
        day
      };
    }
    function autoFixYear(year) {
      const currentYear = adapter.getYear(adapter.date());
      if (year > 100 || currentYear % 100 >= 50) {
        return year;
      }
      const currentCentury = ~~(currentYear / 100) * 100;
      return year < 50 ? currentCentury + year : currentCentury - 100 + year;
    }
    const dateParts = parseDateParts(dateString);
    const validatedParts = validateDateParts(dateParts);
    if (!validatedParts) return null;
    const {
      year,
      month,
      day
    } = validatedParts;
    const pad = v => String(v).padStart(2, '0');
    return adapter.parseISO(`${year}-${pad(month)}-${pad(day)}`);
  }
  function isValid(text) {
    return !!parseDate(text);
  }
  function formatDate(value) {
    const parts = adapter.toISO(value).split('T')[0].split('-');
    return currentFormat.value.order.split('').map(sign => parts['ymd'.indexOf(sign)]).join(currentFormat.value.separator);
  }
  return {
    isValid,
    parseDate,
    formatDate,
    parserFormat: toRef(() => currentFormat.value.format)
  };
}

// Types

// Types

const makeVDateInputProps = propsFactory({
  displayFormat: {
    type: [Function, String],
    default: undefined
  },
  location: {
    type: String,
    default: 'bottom start'
  },
  menu: Boolean,
  menuProps: Object,
  updateOn: {
    type: Array,
    default: () => ['blur', 'enter']
  },
  pickerProps: Object,
  ...makeDateFormatProps(),
  ...makeDisplayProps({
    mobile: null
  }),
  ...makeFocusProps(),
  ...makeVConfirmEditProps({
    hideActions: true
  }),
  ...makeVTextFieldProps({
    prependIcon: '$calendar'
  }),
  ...omit(makeVDatePickerProps({
    hideHeader: true,
    showAdjacentMonths: true
  }), ['location', 'rounded', 'height', 'minHeight', 'maxHeight'])
}, 'VDateInput');
const VDateInput = genericComponent()({
  name: 'VDateInput',
  props: makeVDateInputProps(),
  emits: {
    save: value => true,
    cancel: () => true,
    'update:focused': val => true,
    'update:modelValue': val => true,
    'update:menu': val => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    const adapter = useDate();
    const adapterLocale = computed(() => adapter.locale);
    const {
      isValid,
      parseDate,
      formatDate,
      parserFormat
    } = useDateFormat(props, adapterLocale);
    const {
      mobile
    } = useDisplay(props);
    const {
      InputIcon
    } = useInputIcon(props);
    const {
      clampDate,
      isInAllowedRange
    } = useCalendarRange(props);
    const emptyModelValue = () => props.multiple ? [] : null;
    const model = useProxiedModel(props, 'modelValue', emptyModelValue(), val => Array.isArray(val) ? val.map(item => adapter.toJsDate(item)) : val ? adapter.toJsDate(val) : val, val => Array.isArray(val) ? val.map(item => adapter.date(item)) : val ? adapter.date(val) : val);
    const menu = useProxiedModel(props, 'menu');
    const isEditingInput = shallowRef(false);
    const isFocused = shallowRef(props.focused);
    const vTextFieldRef = ref();
    const disabledActions = ref(['save']);
    function format(date) {
      if (typeof props.displayFormat === 'function') {
        return props.displayFormat(date);
      }
      if (props.displayFormat) {
        return adapter.format(date, props.displayFormat ?? 'keyboardDate');
      }
      return formatDate(date);
    }
    const display = computed(() => {
      const value = wrapInArray(model.value);
      if (!value.length) return null;
      if (props.multiple === true) {
        return t('$vuetify.datePicker.itemsSelected', value.length);
      }
      if (props.multiple === 'range') {
        const start = value[0];
        const end = value[value.length - 1];
        if (!adapter.isValid(start) || !adapter.isValid(end)) return '';
        return `${format(adapter.date(start))} - ${format(adapter.date(end))}`;
      }
      return adapter.isValid(model.value) ? format(adapter.date(model.value)) : '';
    });
    const inputmode = computed(() => {
      if (!mobile.value) return undefined;
      if (isEditingInput.value) return 'text';
      return 'none';
    });
    const isInteractive = computed(() => !props.disabled && !props.readonly);
    const isReadonly = computed(() => {
      if (!props.updateOn.length) return true;
      return !(mobile.value && isEditingInput.value) && props.readonly;
    });
    watch(menu, val => {
      if (val) return;
      isEditingInput.value = false;
      disabledActions.value = ['save'];
    });
    function onKeydown(e) {
      if (e.key !== 'Enter') return;
      if (!menu.value || !isFocused.value) {
        menu.value = true;
      }
      if (props.updateOn.includes('enter') && !props.readonly) {
        onUserInput(e.target);
      }
    }
    function onClick(e) {
      if (props.disabled) return;
      e.preventDefault();
      e.stopPropagation();
      if (menu.value && mobile.value) {
        isEditingInput.value = !props.readonly;
      } else {
        menu.value = true;
      }
    }
    function onCancel() {
      emit('cancel');
      menu.value = false;
      isEditingInput.value = false;
    }
    function onSave(value) {
      emit('save', value);
      menu.value = false;
    }
    function onUpdateDisplayModel(value) {
      if (value != null) return;
      model.value = emptyModelValue();
    }
    function onBlur(e) {
      if (e.relatedTarget?.closest('[data-v-date]')) {
        return; // first click on a day
      }
      if (props.updateOn.includes('blur') && !props.readonly) {
        onUserInput(e.target);
      }

      // When in mobile mode and editing is done (due to keyboard dismissal), close the menu
      if (mobile.value && isEditingInput.value && !isFocused.value) {
        menu.value = false;
        isEditingInput.value = false;
      }
    }
    function onUserInput({
      value
    }) {
      if (!value.trim()) {
        model.value = emptyModelValue();
      } else if (!props.multiple) {
        if (isValid(value)) {
          model.value = clampDate(parseDate(value));
        }
      } else {
        const parts = value.trim().split(/\D+-\D+|[^\d\-/.]+/);
        if (parts.every(isValid)) {
          if (props.multiple === 'range') {
            const [start, stop] = parts.map(parseDate).map(clampDate).toSorted((a, b) => adapter.isAfter(a, b) ? 1 : -1);
            model.value = stop == null ? [start] : [start, adapter.endOfDay(stop)];
          } else {
            model.value = parts.map(parseDate).filter(isInAllowedRange);
          }
        }
      }
    }
    useRender(() => {
      const hasPrepend = !!(props.prependIcon || slots.prepend);
      const confirmEditProps = VConfirmEdit.filterProps(props);
      const datePickerProps = {
        ...VDatePicker.filterProps(omit(props, ['active', 'bgColor', 'color', 'location', 'rounded', 'maxWidth', 'minWidth', 'width'])),
        ...props.pickerProps
      };
      const datePickerSlots = pick(slots, ['title', 'header', 'day', 'month', 'year']);
      const textFieldProps = VTextField.filterProps(omit(props, ['placeholder']));
      return createVNode(VTextField, mergeProps({
        "ref": vTextFieldRef
      }, textFieldProps, {
        "class": ['v-date-input', props.class],
        "style": props.style,
        "modelValue": display.value,
        "inputmode": inputmode.value,
        "placeholder": props.placeholder ?? parserFormat.value,
        "readonly": isReadonly.value,
        "onKeydown": isInteractive.value ? onKeydown : undefined,
        "focused": menu.value || isFocused.value,
        "onBlur": onBlur,
        "validationValue": model.value,
        "onClick:control": onClick,
        "onUpdate:modelValue": onUpdateDisplayModel,
        "onUpdate:focused": event => isFocused.value = event
      }), {
        ...slots,
        default: () => createElementVNode(Fragment, null, [createVNode(VMenu, mergeProps({
          "modelValue": menu.value,
          "onUpdate:modelValue": $event => menu.value = $event,
          "activator": "parent",
          "minWidth": "0",
          "eager": isFocused.value,
          "location": props.location,
          "closeOnContentClick": false,
          "openOnClick": false
        }, props.menuProps), {
          default: () => [createVNode(VConfirmEdit, mergeProps(confirmEditProps, {
            "modelValue": model.value,
            "onUpdate:modelValue": $event => model.value = $event,
            "disabled": disabledActions.value,
            "onSave": onSave,
            "onCancel": onCancel
          }), {
            default: ({
              actions,
              model: proxyModel,
              save,
              cancel,
              isPristine
            }) => {
              function onUpdateModel(value) {
                if (!props.hideActions) {
                  proxyModel.value = value;
                } else {
                  model.value = value;
                  if (!props.multiple) {
                    menu.value = false;
                  }
                }
                emit('save', value);
                disabledActions.value = [];
              }
              return createVNode(VDatePicker, mergeProps(datePickerProps, {
                "modelValue": props.hideActions ? model.value : proxyModel.value,
                "onUpdate:modelValue": value => onUpdateModel(value),
                "onMousedown": e => e.preventDefault()
              }), {
                ...datePickerSlots,
                actions: !props.hideActions ? () => slots.actions?.({
                  save,
                  cancel,
                  isPristine
                }) ?? actions() : undefined
              });
            }
          })]
        }), slots.default?.()]),
        prepend: hasPrepend ? prependSlotProps => slots.prepend ? slots.prepend(prependSlotProps) : props.prependIcon && createVNode(InputIcon, {
          "key": "prepend-icon",
          "name": "prepend",
          "tabindex": props['onClick:prepend'] ? undefined : -1,
          "onClick": isInteractive.value ? onClick : undefined
        }, null) : undefined
      });
    });
    return forwardRefs({}, vTextFieldRef);
  }
});

// Types

// Types

const makeVEmptyStateProps = propsFactory({
  actionText: String,
  bgColor: String,
  color: String,
  icon: IconValue,
  image: String,
  justify: {
    type: String,
    default: 'center'
  },
  headline: String,
  title: String,
  text: String,
  textWidth: {
    type: [Number, String],
    default: 500
  },
  href: String,
  to: String,
  ...makeComponentProps(),
  ...makeDimensionProps(),
  ...makeSizeProps({
    size: undefined
  }),
  ...makeThemeProps()
}, 'VEmptyState');
const VEmptyState = genericComponent()({
  name: 'VEmptyState',
  props: makeVEmptyStateProps(),
  emits: {
    'click:action': e => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.bgColor);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      displayClasses
    } = useDisplay();
    function onClickAction(e) {
      emit('click:action', e);
    }
    useRender(() => {
      const hasActions = !!(slots.actions || props.actionText);
      const hasHeadline = !!(slots.headline || props.headline);
      const hasTitle = !!(slots.title || props.title);
      const hasText = !!(slots.text || props.text);
      const hasMedia = !!(slots.media || props.image || props.icon);
      const size = props.size || (props.image ? 200 : 96);
      return createElementVNode("div", {
        "class": normalizeClass(['v-empty-state', {
          [`v-empty-state--${props.justify}`]: true
        }, themeClasses.value, backgroundColorClasses.value, displayClasses.value, props.class]),
        "style": normalizeStyle([backgroundColorStyles.value, dimensionStyles.value, props.style])
      }, [hasMedia && createElementVNode("div", {
        "key": "media",
        "class": "v-empty-state__media"
      }, [!slots.media ? createElementVNode(Fragment, null, [props.image ? createVNode(VImg, {
        "key": "image",
        "src": props.image,
        "height": size
      }, null) : props.icon ? createVNode(VIcon, {
        "key": "icon",
        "color": props.color,
        "size": size,
        "icon": props.icon
      }, null) : undefined]) : createVNode(VDefaultsProvider, {
        "key": "media-defaults",
        "defaults": {
          VImg: {
            src: props.image,
            height: size
          },
          VIcon: {
            size,
            icon: props.icon
          }
        }
      }, {
        default: () => [slots.media()]
      })]), hasHeadline && createElementVNode("div", {
        "key": "headline",
        "class": "v-empty-state__headline"
      }, [slots.headline?.() ?? props.headline]), hasTitle && createElementVNode("div", {
        "key": "title",
        "class": "v-empty-state__title"
      }, [slots.title?.() ?? props.title]), hasText && createElementVNode("div", {
        "key": "text",
        "class": "v-empty-state__text",
        "style": {
          maxWidth: convertToUnit(props.textWidth)
        }
      }, [slots.text?.() ?? props.text]), slots.default && createElementVNode("div", {
        "key": "content",
        "class": "v-empty-state__content"
      }, [slots.default()]), hasActions && createElementVNode("div", {
        "key": "actions",
        "class": "v-empty-state__actions"
      }, [createVNode(VDefaultsProvider, {
        "defaults": {
          VBtn: {
            class: 'v-empty-state__action-btn',
            color: props.color ?? 'surface-variant',
            href: props.href,
            text: props.actionText,
            to: props.to
          }
        }
      }, {
        default: () => [slots.actions?.({
          props: {
            onClick: onClickAction
          }
        }) ?? createVNode(VBtn, {
          "onClick": onClickAction
        }, null)]
      })])]);
    });
    return {};
  }
});

// Types

const VExpansionPanelSymbol = Symbol.for('vuetify:v-expansion-panel');

const makeVExpansionPanelTextProps = propsFactory({
  ...makeComponentProps(),
  ...makeLazyProps()
}, 'VExpansionPanelText');
const VExpansionPanelText = genericComponent()({
  name: 'VExpansionPanelText',
  props: makeVExpansionPanelTextProps(),
  setup(props, {
    slots
  }) {
    const expansionPanel = inject$1(VExpansionPanelSymbol);
    if (!expansionPanel) throw new Error('[Vuetify] v-expansion-panel-text needs to be placed inside v-expansion-panel');
    const {
      hasContent,
      onAfterLeave
    } = useLazy(props, expansionPanel.isSelected);
    useRender(() => createVNode(VExpandTransition, {
      "onAfterLeave": onAfterLeave
    }, {
      default: () => [withDirectives(createElementVNode("div", {
        "class": normalizeClass(['v-expansion-panel-text', props.class]),
        "style": normalizeStyle(props.style)
      }, [slots.default && hasContent.value && createElementVNode("div", {
        "class": "v-expansion-panel-text__wrapper"
      }, [slots.default?.()])]), [[vShow, expansionPanel.isSelected.value]])]
    }));
    return {};
  }
});

// Types

const makeVExpansionPanelTitleProps = propsFactory({
  color: String,
  expandIcon: {
    type: IconValue,
    default: '$expand'
  },
  collapseIcon: {
    type: IconValue,
    default: '$collapse'
  },
  hideActions: Boolean,
  focusable: Boolean,
  static: Boolean,
  ripple: {
    type: [Boolean, Object],
    default: false
  },
  readonly: Boolean,
  hover: {
    type: Boolean,
    default: true
  },
  ...makeComponentProps(),
  ...makeDimensionProps()
}, 'VExpansionPanelTitle');
const VExpansionPanelTitle = genericComponent()({
  name: 'VExpansionPanelTitle',
  directives: {
    vRipple: Ripple
  },
  props: makeVExpansionPanelTitleProps(),
  setup(props, {
    slots
  }) {
    const expansionPanel = inject$1(VExpansionPanelSymbol);
    if (!expansionPanel) throw new Error('[Vuetify] v-expansion-panel-title needs to be placed inside v-expansion-panel');
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      dimensionStyles
    } = useDimension(props);
    const slotProps = computed(() => ({
      collapseIcon: props.collapseIcon,
      disabled: expansionPanel.disabled.value,
      expanded: expansionPanel.isSelected.value,
      expandIcon: props.expandIcon,
      readonly: props.readonly
    }));
    const icon = toRef(() => expansionPanel.isSelected.value ? props.collapseIcon : props.expandIcon);
    useRender(() => withDirectives(createElementVNode("button", {
      "class": normalizeClass(['v-expansion-panel-title', {
        'v-expansion-panel-title--active': expansionPanel.isSelected.value,
        'v-expansion-panel-title--focusable': props.focusable,
        'v-expansion-panel-title--static': props.static,
        'v-expansion-panel-title--hover': props.hover
      }, backgroundColorClasses.value, props.class]),
      "style": normalizeStyle([backgroundColorStyles.value, dimensionStyles.value, props.style]),
      "type": "button",
      "tabindex": expansionPanel.disabled.value ? -1 : undefined,
      "disabled": expansionPanel.disabled.value,
      "aria-expanded": expansionPanel.isSelected.value,
      "onClick": !props.readonly ? expansionPanel.toggle : undefined
    }, [createElementVNode("span", {
      "class": "v-expansion-panel-title__overlay"
    }, null), slots.default?.(slotProps.value), !props.hideActions && createVNode(VDefaultsProvider, {
      "defaults": {
        VIcon: {
          icon: icon.value
        }
      }
    }, {
      default: () => [createElementVNode("span", {
        "class": "v-expansion-panel-title__icon"
      }, [slots.actions?.(slotProps.value) ?? createVNode(VIcon, null, null)])]
    })]), [[Ripple, props.ripple]]));
    return {};
  }
});

const makeVExpansionPanelProps = propsFactory({
  title: String,
  text: String,
  bgColor: String,
  ...makeElevationProps(),
  ...makeGroupItemProps(),
  ...makeRoundedProps(),
  ...makeTagProps(),
  ...makeVExpansionPanelTitleProps(),
  ...makeVExpansionPanelTextProps()
}, 'VExpansionPanel');
const VExpansionPanel = genericComponent()({
  name: 'VExpansionPanel',
  props: makeVExpansionPanelProps(),
  emits: {
    'group:selected': val => true
  },
  setup(props, {
    slots
  }) {
    const groupItem = useGroupItem(props, VExpansionPanelSymbol);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.bgColor);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const isDisabled = toRef(() => groupItem?.disabled.value || props.disabled);
    const selectedIndices = computed(() => groupItem.group.items.value.reduce((arr, item, index) => {
      if (groupItem.group.selected.value.includes(item.id)) arr.push(index);
      return arr;
    }, []));
    const isBeforeSelected = computed(() => {
      const index = groupItem.group.items.value.findIndex(item => item.id === groupItem.id);
      return !groupItem.isSelected.value && selectedIndices.value.some(selectedIndex => selectedIndex - index === 1);
    });
    const isAfterSelected = computed(() => {
      const index = groupItem.group.items.value.findIndex(item => item.id === groupItem.id);
      return !groupItem.isSelected.value && selectedIndices.value.some(selectedIndex => selectedIndex - index === -1);
    });
    provide(VExpansionPanelSymbol, groupItem);
    useRender(() => {
      const hasText = !!(slots.text || props.text);
      const hasTitle = !!(slots.title || props.title);
      const expansionPanelTitleProps = VExpansionPanelTitle.filterProps(props);
      const expansionPanelTextProps = VExpansionPanelText.filterProps(props);
      return createVNode(props.tag, {
        "class": normalizeClass(['v-expansion-panel', {
          'v-expansion-panel--active': groupItem.isSelected.value,
          'v-expansion-panel--before-active': isBeforeSelected.value,
          'v-expansion-panel--after-active': isAfterSelected.value,
          'v-expansion-panel--disabled': isDisabled.value
        }, roundedClasses.value, backgroundColorClasses.value, props.class]),
        "style": normalizeStyle([backgroundColorStyles.value, roundedStyles.value, props.style])
      }, {
        default: () => [createElementVNode("div", {
          "class": normalizeClass(['v-expansion-panel__shadow', ...elevationClasses.value])
        }, null), createVNode(VDefaultsProvider, {
          "defaults": {
            VExpansionPanelTitle: {
              ...expansionPanelTitleProps
            },
            VExpansionPanelText: {
              ...expansionPanelTextProps
            }
          }
        }, {
          default: () => [hasTitle && createVNode(VExpansionPanelTitle, {
            "key": "title"
          }, {
            default: () => [slots.title ? slots.title() : props.title]
          }), hasText && createVNode(VExpansionPanelText, {
            "key": "text"
          }, {
            default: () => [slots.text ? slots.text() : props.text]
          }), slots.default?.()]
        })]
      });
    });
    return {
      groupItem
    };
  }
});

// Types

const allowedVariants$2 = ['default', 'accordion', 'inset', 'popout'];
const makeVExpansionPanelsProps = propsFactory({
  flat: Boolean,
  gap: [String, Number],
  noDivider: Boolean,
  rounded: [Boolean, Number, String, Array],
  ...makeGroupProps(),
  ...pick(makeVExpansionPanelProps(), ['bgColor', 'collapseIcon', 'color', 'eager', 'elevation', 'expandIcon', 'focusable', 'hideActions', 'hover', 'readonly', 'ripple', 'static', 'tile']),
  ...makeThemeProps(),
  ...makeComponentProps(),
  ...makeTagProps(),
  variant: {
    type: String,
    default: 'default',
    validator: v => allowedVariants$2.includes(v)
  }
}, 'VExpansionPanels');
const VExpansionPanels = genericComponent()({
  name: 'VExpansionPanels',
  props: makeVExpansionPanelsProps(),
  emits: {
    'update:modelValue': val => true
  },
  setup(props, {
    slots
  }) {
    const {
      next,
      prev
    } = useGroup(props, VExpansionPanelSymbol);
    const {
      themeClasses
    } = provideTheme(props);
    const outerRounded = toRef(() => Array.isArray(props.rounded) ? props.rounded[0] : props.rounded);
    const innerRounded = toRef(() => Array.isArray(props.rounded) ? props.rounded[1] : undefined);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(outerRounded);
    const variantClass = toRef(() => props.variant && `v-expansion-panels--variant-${props.variant}`);
    provideDefaults({
      VExpansionPanel: {
        bgColor: toRef(() => props.bgColor),
        collapseIcon: toRef(() => props.collapseIcon),
        color: toRef(() => props.color),
        eager: toRef(() => props.eager),
        elevation: toRef(() => props.elevation),
        expandIcon: toRef(() => props.expandIcon),
        focusable: toRef(() => props.focusable),
        hideActions: toRef(() => props.hideActions),
        hover: toRef(() => props.hover),
        readonly: toRef(() => props.readonly),
        ripple: toRef(() => props.ripple),
        static: toRef(() => props.static)
      }
    });
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-expansion-panels', {
        'v-expansion-panels--flat': props.flat,
        'v-expansion-panels--tile': props.tile,
        'v-expansion-panels--no-divider': props.noDivider || !!props.gap
      }, themeClasses.value, roundedClasses.value, variantClass.value, props.class]),
      "style": normalizeStyle([roundedStyles.value, {
        '--v-expansion-panels-inner-radius': convertToUnit(innerRounded.value),
        gap: props.gap ? convertToUnit(props.gap) : undefined
      }, props.style])
    }, {
      default: () => [slots.default?.({
        prev,
        next
      })]
    }));
    return {
      next,
      prev
    };
  }
});

// Types

const makeVFabProps = propsFactory({
  app: Boolean,
  appear: Boolean,
  extended: Boolean,
  layout: Boolean,
  offset: Boolean,
  modelValue: {
    type: Boolean,
    default: true
  },
  ...omit(makeVBtnProps({
    active: true
  }), ['location', 'spaced']),
  ...makeLayoutItemProps(),
  ...makeLocationProps(),
  ...makeTransitionProps({
    transition: 'fab-transition'
  })
}, 'VFab');
const VFab = genericComponent()({
  name: 'VFab',
  props: makeVFabProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const model = useProxiedModel(props, 'modelValue');
    const height = shallowRef(56);
    const layoutItemStyles = ref();
    const {
      resizeRef
    } = useResizeObserver(entries => {
      if (!entries.length) return;
      height.value = entries[0].target.clientHeight;
    });
    const hasPosition = toRef(() => props.app || props.absolute);
    const position = computed(() => {
      if (!hasPosition.value) return false;
      return props.location?.split(' ').shift() ?? 'bottom';
    });
    const orientation = computed(() => {
      if (!hasPosition.value) return false;
      return props.location?.split(' ')[1] ?? 'end';
    });
    useToggleScope(() => props.app, () => {
      const layout = useLayoutItem({
        id: props.name,
        order: computed(() => parseInt(props.order, 10)),
        position,
        layoutSize: computed(() => props.layout ? height.value + 24 : 0),
        elementSize: computed(() => height.value + 24),
        active: computed(() => props.app && model.value),
        absolute: toRef(() => props.absolute)
      });
      watchEffect(() => {
        layoutItemStyles.value = layout.layoutItemStyles.value;
      });
    });
    const vFabRef = ref();
    useRender(() => {
      const btnProps = VBtn.filterProps(props);
      return createElementVNode("div", {
        "ref": vFabRef,
        "class": normalizeClass(['v-fab', {
          'v-fab--absolute': props.absolute,
          'v-fab--app': !!props.app,
          'v-fab--extended': props.extended,
          'v-fab--offset': props.offset,
          [`v-fab--${position.value}`]: hasPosition.value,
          [`v-fab--${orientation.value}`]: hasPosition.value
        }, props.class]),
        "style": normalizeStyle([props.app ? {
          ...layoutItemStyles.value
        } : {
          height: props.absolute ? '100%' : 'inherit'
        }, props.style])
      }, [createElementVNode("div", {
        "class": "v-fab__container"
      }, [createVNode(MaybeTransition, {
        "appear": props.appear,
        "transition": props.transition
      }, {
        default: () => [withDirectives(createVNode(VBtn, mergeProps({
          "ref": resizeRef
        }, btnProps, {
          "active": undefined,
          "location": undefined
        }), slots), [[vShow, props.active]])]
      })])]);
    });
    return {};
  }
});

// Types

function useFileDrop() {
  function getTransfer(e) {
    return e.dataTransfer ?? e.clipboardData ?? null;
  }
  function hasFilesOrFolders(e) {
    const transfer = getTransfer(e);
    const entries = [...(transfer?.items ?? [])].filter(x => x.kind === 'file').map(x => x.webkitGetAsEntry()).filter(Boolean);
    return entries.length > 0 || [...(transfer?.files ?? [])].length > 0;
  }
  async function handleDrop(e) {
    const transfer = getTransfer(e);
    const result = [];
    const entries = [...(transfer?.items ?? [])].filter(x => x.kind === 'file').map(x => x.webkitGetAsEntry()).filter(Boolean);
    if (entries.length) {
      for (const entry of entries) {
        const files = await traverseFileTree(entry, appendIfDirectory('.', entry));
        result.push(...files.map(x => x.file));
      }
    } else {
      result.push(...[...(transfer?.files ?? [])]);
    }
    return result;
  }
  return {
    handleDrop,
    hasFilesOrFolders
  };
}
function traverseFileTree(item, path = '') {
  return new Promise((resolve, reject) => {
    if (item.isFile) {
      const fileEntry = item;
      fileEntry.file(file => resolve([{
        file,
        path
      }]), reject);
    } else if (item.isDirectory) {
      const directoryReader = item.createReader();
      directoryReader.readEntries(async entries => {
        const files = [];
        for (const entry of entries) {
          files.push(...(await traverseFileTree(entry, appendIfDirectory(path, entry))));
        }
        resolve(files);
      });
    }
  });
}
function appendIfDirectory(path, item) {
  return item.isDirectory ? `${path}/${item.name}` : path;
}

// Utilities
// Composables
const makeFileFilterProps = propsFactory({
  filterByType: String
}, 'file-accept');
function useFileFilter(props) {
  const fileFilter = computed(() => props.filterByType ? createFilter(props.filterByType) : null);
  function filterAccepted(files) {
    if (fileFilter.value) {
      const accepted = files.filter(fileFilter.value);
      return {
        accepted,
        rejected: files.filter(f => !accepted.includes(f))
      };
    }
    return {
      accepted: files,
      rejected: []
    };
  }
  return {
    filterAccepted
  };
}
function createFilter(v) {
  const types = v.split(',').map(x => x.trim().toLowerCase());
  const extensionsToMatch = types.filter(x => x.startsWith('.'));
  const wildcards = types.filter(x => x.endsWith('/*'));
  const typesToMatch = types.filter(x => !extensionsToMatch.includes(x) && !wildcards.includes(x));
  return file => {
    const extension = file.name.split('.').at(-1)?.toLowerCase() ?? '';
    const typeGroup = file.type.split('/').at(0)?.toLowerCase() ?? '';
    return typesToMatch.includes(file.type) || extensionsToMatch.includes(`.${extension}`) || wildcards.includes(`${typeGroup}/*`);
  };
}

// Types

const makeVFileInputProps = propsFactory({
  chips: Boolean,
  counter: Boolean,
  counterSizeString: {
    type: String,
    default: '$vuetify.fileInput.counterSize'
  },
  counterString: {
    type: String,
    default: '$vuetify.fileInput.counter'
  },
  hideInput: Boolean,
  multiple: Boolean,
  showSize: {
    type: [Boolean, Number, String],
    default: false,
    validator: v => {
      return typeof v === 'boolean' || [1000, 1024].includes(Number(v));
    }
  },
  truncateLength: {
    type: [Number, String],
    default: 22
  },
  ...omit(makeVInputProps({
    prependIcon: '$file'
  }), ['direction']),
  modelValue: {
    type: [Array, Object],
    default: props => props.multiple ? [] : null,
    validator: val => {
      return wrapInArray(val).every(v => v != null && typeof v === 'object');
    }
  },
  ...makeFileFilterProps(),
  ...makeVFieldProps({
    clearable: true
  })
}, 'VFileInput');
const VFileInput = genericComponent()({
  name: 'VFileInput',
  inheritAttrs: false,
  props: makeVFileInputProps(),
  emits: {
    'click:control': e => true,
    'mousedown:control': e => true,
    'update:focused': focused => true,
    'update:modelValue': files => true,
    rejected: files => true
  },
  setup(props, {
    attrs,
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    const {
      filterAccepted
    } = useFileFilter(props);
    const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => !props.multiple && Array.isArray(val) ? val[0] : val);
    const {
      isFocused,
      focus,
      blur
    } = useFocus(props);
    const base = computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined);
    const totalBytes = computed(() => (model.value ?? []).reduce((bytes, {
      size = 0
    }) => bytes + size, 0));
    const totalBytesReadable = computed(() => humanReadableFileSize(totalBytes.value, base.value));
    const fileNames = computed(() => (model.value ?? []).map(file => {
      const {
        name = '',
        size = 0
      } = file;
      const truncatedText = truncateText(name);
      return !props.showSize ? truncatedText : `${truncatedText} (${humanReadableFileSize(size, base.value)})`;
    }));
    const counterValue = computed(() => {
      const fileCount = model.value?.length ?? 0;
      if (props.showSize) return t(props.counterSizeString, fileCount, totalBytesReadable.value);else return t(props.counterString, fileCount);
    });
    const vInputRef = ref();
    const vFieldRef = ref();
    const inputRef = ref();
    const isActive = toRef(() => isFocused.value || props.active);
    const isPlainOrUnderlined = computed(() => ['plain', 'underlined'].includes(props.variant));
    const isDragging = shallowRef(false);
    const {
      handleDrop,
      hasFilesOrFolders
    } = useFileDrop();
    function onFocus() {
      if (inputRef.value !== getActiveElement()) {
        inputRef.value?.focus();
      }
      if (!isFocused.value) focus();
    }
    function onClickPrepend(e) {
      inputRef.value?.click();
    }
    function onControlMousedown(e) {
      emit('mousedown:control', e);
    }
    function onControlClick(e) {
      inputRef.value?.click();
      emit('click:control', e);
    }
    function onClear(e) {
      e.stopPropagation();
      onFocus();
      nextTick(() => {
        model.value = [];
        callEvent(props['onClick:clear'], e);
      });
    }
    function truncateText(str) {
      if (str.length < Number(props.truncateLength)) return str;
      const charsKeepOneSide = Math.floor((Number(props.truncateLength) - 1) / 2);
      return `${str.slice(0, charsKeepOneSide)}…${str.slice(str.length - charsKeepOneSide)}`;
    }
    function onDragover(e) {
      if (props.disabled || props.readonly) return;
      e.preventDefault();
      e.stopImmediatePropagation();
      isDragging.value = true;
    }
    function onDragleave(e) {
      e.preventDefault();
      isDragging.value = false;
    }
    async function onDrop(e) {
      e.preventDefault();
      e.stopImmediatePropagation();
      isDragging.value = false;
      if (!inputRef.value || props.disabled || props.readonly || !hasFilesOrFolders(e)) return;
      const allDroppedFiles = await handleDrop(e);
      selectAccepted(allDroppedFiles);
    }
    async function onPaste(e) {
      if (!inputRef.value || props.disabled || props.readonly || !hasFilesOrFolders(e)) return;
      e.preventDefault();
      const files = await handleDrop(e);
      if (files.length) {
        selectAccepted(files);
      }
    }
    function onFileSelection(e) {
      if (!e.target || e.repack) return; // prevent loop

      if (!props.filterByType) {
        const target = e.target;
        model.value = [...(target.files ?? [])];
      } else {
        selectAccepted([...e.target.files]);
      }
    }
    function selectAccepted(files) {
      const dataTransfer = new DataTransfer();
      const {
        accepted,
        rejected
      } = filterAccepted(files);
      if (rejected.length) {
        emit('rejected', rejected);
      }
      for (const file of accepted) {
        dataTransfer.items.add(file);
      }
      inputRef.value.files = dataTransfer.files;
      model.value = [...dataTransfer.files];
      const event = new Event('change', {
        bubbles: true
      });
      event.repack = true;
      inputRef.value.dispatchEvent(event);
    }
    watch(model, newValue => {
      const hasModelReset = !Array.isArray(newValue) || !newValue.length;
      if (hasModelReset && inputRef.value) {
        inputRef.value.value = '';
      }
    });
    useRender(() => {
      const hasCounter = !!(slots.counter || props.counter);
      const hasDetails = props.hideDetails !== true && !!(slots.details || hasCounter && (props.hideDetails === false || model.value?.length));
      const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
      const {
        modelValue: _,
        ...inputProps
      } = VInput.filterProps(props);
      const fieldProps = {
        ...VField.filterProps(props),
        'onClick:clear': onClear
      };
      const expectsDirectory = attrs.webkitdirectory !== undefined && attrs.webkitdirectory !== false;
      const acceptFallback = attrs.accept ? String(attrs.accept) : undefined;
      const inputAccept = expectsDirectory ? undefined : props.filterByType ?? acceptFallback;
      return createVNode(VInput, mergeProps({
        "ref": vInputRef,
        "modelValue": props.multiple ? model.value : model.value[0],
        "class": ['v-file-input', {
          'v-file-input--chips': !!props.chips,
          'v-file-input--dragging': isDragging.value,
          'v-file-input--hide': props.hideInput,
          'v-input--plain-underlined': isPlainOrUnderlined.value
        }, props.class],
        "style": props.style,
        "onClick:prepend": onClickPrepend
      }, rootAttrs, inputProps, {
        "centerAffix": !isPlainOrUnderlined.value,
        "focused": isFocused.value,
        "indentDetails": props.indentDetails ?? !isPlainOrUnderlined.value
      }), {
        ...slots,
        default: ({
          id,
          isDisabled,
          isDirty,
          isReadonly,
          isValid,
          hasDetails
        }) => createVNode(VField, mergeProps({
          "ref": vFieldRef,
          "prependIcon": props.prependIcon,
          "onMousedown": onControlMousedown,
          "onClick": onControlClick,
          "onClick:prependInner": props['onClick:prependInner'],
          "onClick:appendInner": props['onClick:appendInner']
        }, fieldProps, {
          "id": id.value,
          "active": isActive.value || isDirty.value,
          "dirty": isDirty.value || props.dirty,
          "disabled": isDisabled.value,
          "focused": isFocused.value,
          "details": hasDetails.value,
          "error": isValid.value === false,
          "onDragover": onDragover,
          "onDrop": onDrop
        }), {
          ...slots,
          default: ({
            props: {
              class: fieldClass,
              ...slotProps
            },
            controlRef
          }) => createElementVNode(Fragment, null, [createElementVNode("input", mergeProps({
            "ref": val => inputRef.value = controlRef.value = val,
            "type": "file",
            "accept": inputAccept,
            "readonly": isReadonly.value,
            "disabled": isDisabled.value,
            "multiple": props.multiple,
            "name": props.name,
            "onClick": e => {
              e.stopPropagation();
              if (isReadonly.value) e.preventDefault();
              onFocus();
            },
            "onChange": onFileSelection,
            "onDragleave": onDragleave,
            "onFocus": onFocus,
            "onBlur": blur,
            "onPaste": onPaste
          }, slotProps, inputAttrs), null), createElementVNode("div", {
            "class": normalizeClass(fieldClass)
          }, [!!model.value?.length && !props.hideInput && (slots.selection ? slots.selection({
            fileNames: fileNames.value,
            totalBytes: totalBytes.value,
            totalBytesReadable: totalBytesReadable.value
          }) : props.chips ? fileNames.value.map(text => createVNode(VChip, {
            "key": text,
            "size": "small",
            "text": text
          }, null)) : fileNames.value.join(', '))])])
        }),
        details: hasDetails ? slotProps => createElementVNode(Fragment, null, [slots.details?.(slotProps), hasCounter && createElementVNode(Fragment, null, [createElementVNode("span", null, null), createVNode(VCounter, {
          "active": !!model.value?.length,
          "value": counterValue.value,
          "disabled": props.disabled
        }, slots.counter)])]) : undefined
      });
    });
    return forwardRefs({}, vInputRef, vFieldRef, inputRef);
  }
});

// Types

const makeVFileUploadItemProps = propsFactory({
  clearable: Boolean,
  file: {
    type: Object,
    default: null
  },
  fileIcon: {
    type: String,
    // TODO: setup up a proper aliased icon
    default: 'mdi-file-document'
  },
  showSize: Boolean,
  ...makeVListItemProps({
    border: true,
    rounded: true,
    lines: 'two'
  })
}, 'VFileUploadItem');
const VFileUploadItem = genericComponent()({
  name: 'VFileUploadItem',
  props: makeVFileUploadItemProps(),
  emits: {
    'click:remove': () => true,
    click: e => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const preview = ref();
    const base = computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined);
    function onClickRemove() {
      emit('click:remove');
    }
    watchEffect(() => {
      preview.value = props.file?.type.startsWith('image') ? URL.createObjectURL(props.file) : undefined;
    });
    useRender(() => {
      const listItemProps = VListItem.filterProps(props);
      return createVNode(VListItem, mergeProps(listItemProps, {
        "class": ['v-file-upload-item', props.class],
        "title": props.title ?? props.file?.name,
        "subtitle": props.showSize ? humanReadableFileSize(props.file?.size, base.value) : props.file?.type,
        "style": props.style
      }), {
        ...slots,
        title: slots.title ?? (() => props?.title ?? props.file?.name),
        prepend: slotProps => createElementVNode(Fragment, null, [!slots.prepend ? createVNode(VAvatar, {
          "icon": props.fileIcon,
          "image": preview.value,
          "rounded": true
        }, null) : createVNode(VDefaultsProvider, {
          "defaults": {
            VAvatar: {
              image: preview.value,
              icon: !preview.value ? props.fileIcon : undefined,
              rounded: true
            }
          }
        }, {
          default: () => [slots.prepend?.(slotProps) ?? createVNode(VAvatar, null, null)]
        })]),
        append: slotProps => createElementVNode(Fragment, null, [props.clearable && createElementVNode(Fragment, null, [!slots.clear ? createVNode(VBtn, {
          "icon": "$clear",
          "density": "comfortable",
          "variant": "text",
          "onClick": onClickRemove
        }, null) : createVNode(VDefaultsProvider, {
          "defaults": {
            VBtn: {
              icon: '$clear',
              density: 'comfortable',
              variant: 'text'
            }
          }
        }, {
          default: () => [slots.clear?.({
            ...slotProps,
            props: {
              onClick: onClickRemove
            }
          }) ?? createVNode(VBtn, null, null)]
        })]), slots.append?.(slotProps)])
      });
    });
  }
});

let nextId = 0;
const fileIds = new WeakMap();
function getFileKey(file) {
  let id = fileIds.get(file);
  if (id == null) {
    id = ++nextId;
    fileIds.set(file, id);
  }
  return id;
}

// Types

const VFileUploadKey = Symbol.for('vuetify:file-upload');
const makeVFileUploadDropzoneProps = propsFactory({
  browseText: {
    type: String,
    default: '$vuetify.fileUpload.browse'
  },
  dividerText: {
    type: String,
    default: '$vuetify.fileUpload.divider'
  },
  title: {
    type: String,
    default: '$vuetify.fileUpload.title'
  },
  subtitle: String,
  icon: {
    type: IconValue,
    default: '$upload'
  },
  clearable: Boolean,
  disabled: Boolean,
  readonly: Boolean,
  error: Boolean,
  hideBrowse: Boolean,
  insetFileList: Boolean,
  multiple: Boolean,
  scrim: {
    type: [Boolean, String],
    default: true
  },
  showSize: Boolean,
  ...makeDelayProps(),
  ...makeDensityProps(),
  ...pick(makeVDividerProps({
    length: 150
  }), ['length', 'thickness', 'opacity']),
  ...makeVSheetProps(),
  modelValue: {
    type: Array,
    default: () => []
  }
}, 'VFileUploadDropzone');
const VFileUploadDropzone = genericComponent()({
  name: 'VFileUploadDropzone',
  props: makeVFileUploadDropzoneProps(),
  emits: {
    'click:browse': () => true,
    'click:remove': index => true,
    drop: files => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    const {
      densityClasses
    } = useDensity(props);
    const {
      handleDrop,
      hasFilesOrFolders
    } = useFileDrop();
    const context = inject$1(VFileUploadKey, null);
    const vSheetRef = ref();
    const isDragging = shallowRef(false);
    const isDisabled = toRef(() => context?.disabled.value ?? props.disabled);
    const isReadonly = toRef(() => context?.readonly.value ?? props.readonly);
    const isInteractive = toRef(() => !isDisabled.value && !isReadonly.value);
    function onDragover(e) {
      if (!isInteractive.value) return;
      e.preventDefault();
      e.stopImmediatePropagation();
      isDragging.value = true;
    }
    function onDragleave(e) {
      e.preventDefault();
      const container = e.currentTarget;
      if (!container.contains(e.relatedTarget)) {
        isDragging.value = false;
      }
    }
    async function onDrop(e) {
      e.preventDefault();
      e.stopImmediatePropagation();
      isDragging.value = false;
      if (!isInteractive.value || !hasFilesOrFolders(e)) return;
      const files = await handleDrop(e);
      if (context) {
        context.onDrop(files);
      } else {
        emit('drop', files);
      }
    }
    function onClickBrowse() {
      if (!isInteractive.value) return;
      if (context) {
        context.onClickBrowse();
      } else {
        emit('click:browse');
      }
    }
    function onKeydown(e) {
      if (!isInteractive.value) return;
      if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        onClickBrowse();
      }
    }
    function onClickRemove(index) {
      if (!isInteractive.value) return;
      if (context) {
        context.onClickRemove(index);
      } else {
        emit('click:remove', index);
      }
    }
    async function onPaste(e) {
      if (!isInteractive.value || !hasFilesOrFolders(e)) return;
      e.preventDefault();
      const files = await handleDrop(e);
      if (!files.length) return;
      if (context) {
        context.onDrop(files);
      } else {
        emit('drop', files);
      }
    }
    useRender(() => {
      const modelValue = context?.files.value ?? props.modelValue;
      const disabled = isDisabled.value;
      const readonly = isReadonly.value;
      const interactive = isInteractive.value;
      const error = context?.error.value || props.error;
      const hasTitle = !!(slots.title || props.title);
      const hasIcon = !!(slots.icon || props.icon);
      const hasBrowse = !!(!props.hideBrowse && (slots.browse || props.density === 'default'));
      const hasFiles = modelValue.length > 0;
      const isInset = props.insetFileList && hasFiles;
      const sheetProps = VSheet.filterProps(props);
      const dividerProps = VDivider.filterProps(props);
      return createVNode(VSheet, mergeProps({
        "ref": vSheetRef,
        "tabindex": disabled ? -1 : 0
      }, sheetProps, {
        "class": ['v-file-upload-dropzone', {
          'v-file-upload-dropzone--clickable': !hasBrowse,
          'v-file-upload-dropzone--disabled': disabled,
          'v-file-upload-dropzone--readonly': readonly,
          'v-file-upload-dropzone--dragging': isDragging.value,
          'v-file-upload-dropzone--has-files': hasFiles,
          'v-file-upload-dropzone--inset': isInset,
          'v-file-upload-dropzone--error': error
        }, densityClasses.value, props.class],
        "style": props.style,
        "onDragleave": onDragleave,
        "onDragover": onDragover,
        "onDrop": onDrop,
        "onPaste": onPaste,
        "onClick": !hasBrowse && !(isInset && hasFiles) ? onClickBrowse : undefined,
        "onKeydown": onKeydown
      }), {
        default: () => [slots.default?.({
          isDragging: isDragging.value,
          hasFiles,
          files: modelValue,
          props: {
            onClick: onClickBrowse
          }
        }) ?? (isInset ? createElementVNode("div", {
          "key": "inset",
          "class": "v-file-upload-inset"
        }, [modelValue.length === 1 && !props.multiple ? slots.single?.({
          file: modelValue[0],
          props: {
            'onClick:remove': () => onClickRemove(0)
          }
        }) ?? createVNode(VDefaultsProvider, {
          "defaults": {
            VFileUploadItem: {
              file: modelValue[0],
              clearable: props.clearable && !readonly,
              disabled,
              showSize: props.showSize,
              border: false
            }
          }
        }, {
          default: () => [createVNode(VFileUploadItem, {
            "onClick:remove": () => onClickRemove(0)
          }, null)]
        }) : modelValue.map((file, i) => {
          const key = getFileKey(file);
          const slotProps = {
            file,
            props: {
              'onClick:remove': () => onClickRemove(i)
            }
          };
          return createVNode(VDefaultsProvider, {
            "key": key,
            "defaults": {
              VFileUploadItem: {
                file,
                clearable: props.clearable && !readonly,
                disabled,
                showSize: props.showSize,
                border: false
              }
            }
          }, {
            default: () => [slots.item?.(slotProps) ?? createVNode(VFileUploadItem, {
              "key": key,
              "onClick:remove": () => onClickRemove(i)
            }, null)]
          });
        }), createVNode(VDivider, null, null), createElementVNode("div", {
          "class": "v-file-upload-inset__action"
        }, [!slots.browse ? createVNode(VBtn, {
          "readonly": !interactive,
          "text": t(props.browseText),
          "variant": "text",
          "onClick": onClickBrowse
        }, null) : createVNode(VDefaultsProvider, {
          "defaults": {
            VBtn: {
              readonly: !interactive,
              text: t(props.browseText),
              variant: 'text'
            }
          }
        }, {
          default: () => [slots.browse({
            props: {
              onClick: onClickBrowse
            }
          })]
        })])]) : createElementVNode(Fragment, null, [hasIcon && createElementVNode("div", {
          "key": "icon",
          "class": "v-file-upload-icon"
        }, [!slots.icon ? createVNode(VIcon, {
          "key": "icon-icon",
          "icon": props.icon
        }, null) : createVNode(VDefaultsProvider, {
          "key": "icon-defaults",
          "defaults": {
            VIcon: {
              icon: props.icon
            }
          }
        }, {
          default: () => [slots.icon()]
        })]), hasTitle && createElementVNode("div", {
          "key": "title",
          "class": "v-file-upload-title"
        }, [slots.title?.() ?? t(props.title)]), props.density === 'default' && createElementVNode(Fragment, null, [hasBrowse && createElementVNode(Fragment, null, [createElementVNode("div", {
          "key": "upload-divider",
          "class": "v-file-upload-divider"
        }, [slots.divider?.() ?? createVNode(VDivider, dividerProps, {
          default: () => [t(props.dividerText)]
        })]), !slots.browse ? createVNode(VBtn, {
          "readonly": !interactive,
          "size": "large",
          "text": t(props.browseText),
          "variant": "tonal",
          "onClick": onClickBrowse
        }, null) : createVNode(VDefaultsProvider, {
          "defaults": {
            VBtn: {
              readonly: !interactive,
              size: 'large',
              text: t(props.browseText),
              variant: 'tonal'
            }
          }
        }, {
          default: () => [slots.browse({
            props: {
              onClick: onClickBrowse
            }
          })]
        })]), props.subtitle && createElementVNode("div", {
          "class": "v-file-upload-subtitle"
        }, [props.subtitle])])])), createVNode(VOverlay, {
          "modelValue": isDragging.value,
          "contained": true,
          "scrim": props.scrim
        }, null), slots.input?.(), slots.loader?.()]
      });
    });
    return forwardRefs({}, vSheetRef);
  }
});

// Types

const makeVFileUploadListProps = propsFactory({
  clearable: Boolean,
  showSize: Boolean,
  files: Array,
  ...makeVListProps({
    border: false,
    elevation: 0,
    lines: false
  })
}, 'VFileUploadList');
const VFileUploadList = genericComponent()({
  name: 'VFileUploadList',
  props: makeVFileUploadListProps(),
  setup(props, {
    slots
  }) {
    const context = inject$1(VFileUploadKey, null);
    useRender(() => {
      const files = props.files ?? context?.files.value ?? [];
      const disabled = context?.disabled.value ?? props.disabled;
      const readonly = context?.readonly.value ?? false;
      const listProps = VList.filterProps(props);
      if (!slots.default && !files.length) return createCommentVNode();
      return createVNode(VList, mergeProps(listProps, {
        "disabled": disabled,
        "class": ['v-file-upload-list', props.class],
        "style": props.style,
        "bgColor": "transparent"
      }), {
        default: () => [slots.default?.({
          files,
          onClickRemove: i => context?.onClickRemove(i)
        }) ?? files.map((file, index) => {
          const key = getFileKey(file);
          const slotProps = {
            file,
            props: {
              'onClick:remove': () => context?.onClickRemove(index)
            }
          };
          return createVNode(VDefaultsProvider, {
            "key": key,
            "defaults": {
              VFileUploadItem: {
                file,
                clearable: props.clearable && !readonly,
                disabled,
                showSize: props.showSize,
                variant: 'flat'
              }
            }
          }, {
            default: () => [slots.item?.(slotProps) ?? createVNode(VFileUploadItem, {
              "key": key,
              "onClick:remove": () => context?.onClickRemove(index)
            }, null)]
          });
        })]
      });
    });
  }
});

// Types

const makeVFileUploadProps = propsFactory({
  browseText: {
    type: String,
    default: '$vuetify.fileUpload.browse'
  },
  dividerText: {
    type: String,
    default: '$vuetify.fileUpload.divider'
  },
  title: {
    type: String,
    default: '$vuetify.fileUpload.title'
  },
  subtitle: String,
  icon: {
    type: IconValue,
    default: '$upload'
  },
  clearable: Boolean,
  insetFileList: Boolean,
  hideBrowse: Boolean,
  multiple: Boolean,
  scrim: {
    type: [Boolean, String],
    default: true
  },
  showSize: Boolean,
  ...makeFileFilterProps(),
  ...makeLoaderProps(),
  ...omit(makeVInputProps(), ['direction']),
  modelValue: {
    type: [Array, Object],
    default: null,
    validator: val => {
      return wrapInArray(val).every(v => v != null && typeof v === 'object');
    }
  }
}, 'VFileUpload');
const VFileUpload = genericComponent()({
  name: 'VFileUpload',
  inheritAttrs: false,
  props: makeVFileUploadProps(),
  emits: {
    'update:modelValue': files => true,
    'update:focused': focused => true,
    rejected: files => true
  },
  setup(props, {
    attrs,
    emit,
    slots
  }) {
    const {
      filterAccepted
    } = useFileFilter(props);
    const {
      isFocused
    } = useFocus(props);
    const {
      loaderClasses
    } = useLoader(props);
    const form = useForm(props);
    const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => props.multiple || Array.isArray(props.modelValue) ? val : val[0]);
    const vInputRef = ref();
    const vDropzoneRef = ref();
    const inputRef = ref(null);
    const isError = toRef(() => vInputRef.value?.isValid === false);
    const isInteractive = toRef(() => !form.isDisabled.value && !form.isReadonly.value);
    const loadingColor = shallowRef(undefined);
    watch(() => props.loading, (val, old) => {
      loadingColor.value = !val && typeof old === 'string' ? old : typeof val === 'boolean' ? undefined : val;
    }, {
      immediate: true
    });
    provide(VFileUploadKey, {
      files: model,
      disabled: form.isDisabled,
      readonly: form.isReadonly,
      error: isError,
      onDrop,
      onClickBrowse: onClick,
      onClickRemove
    });
    watch(model, newValue => {
      const hasModelReset = !Array.isArray(newValue) || !newValue.length;
      if (hasModelReset && inputRef.value) {
        inputRef.value.value = '';
      }
    });
    function onDrop(files) {
      if (!isInteractive.value) return;
      selectAccepted(files);
    }
    function onFileSelection(e) {
      if (!e.target || e.repack) return; // prevent loop
      const target = e.target;
      const selectedFiles = [...(target.files ?? [])];
      if (!selectedFiles.length) return;
      if (!props.filterByType) {
        model.value = props.multiple ? [...model.value, ...selectedFiles] : selectedFiles;
      } else {
        selectAccepted(selectedFiles);
      }
    }
    function selectAccepted(files) {
      const dataTransfer = new DataTransfer();
      const {
        accepted,
        rejected
      } = filterAccepted(files);
      if (rejected.length) {
        emit('rejected', rejected);
      }
      for (const file of accepted) {
        dataTransfer.items.add(file);
      }
      inputRef.value.files = dataTransfer.files;
      const newFiles = [...dataTransfer.files];
      model.value = props.multiple ? [...model.value, ...newFiles] : newFiles;
      const event = new Event('change', {
        bubbles: true
      });
      event.repack = true;
      inputRef.value.dispatchEvent(event);
    }
    function onClick() {
      if (!isInteractive.value) return;
      inputRef.value?.click();
    }
    function onClickRemove(index) {
      if (!isInteractive.value) return;
      const newValue = model.value.filter((_, i) => i !== index);
      model.value = newValue;
      if (newValue.length > 0 || !inputRef.value) return;
      inputRef.value.value = '';
    }
    useRender(() => {
      const {
        modelValue: _,
        ...inputProps
      } = VInput.filterProps(props);
      const {
        modelValue: __,
        ...dropzoneProps
      } = VFileUploadDropzone.filterProps(props);
      const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
      const expectsDirectory = attrs.webkitdirectory !== undefined && attrs.webkitdirectory !== false;
      const acceptFallback = attrs.accept ? String(attrs.accept) : undefined;
      const inputAccept = expectsDirectory ? undefined : props.filterByType ?? acceptFallback;
      const inputNode = createElementVNode("input", mergeProps({
        "ref": inputRef,
        "type": "file",
        "accept": inputAccept,
        "disabled": props.disabled ?? undefined,
        "multiple": props.multiple,
        "name": props.name,
        "onChange": onFileSelection
      }, inputAttrs), null);
      return createVNode(VInput, mergeProps({
        "ref": vInputRef,
        "modelValue": props.multiple ? model.value : model.value[0],
        "onUpdate:modelValue": val => {
          if (val == null || Array.isArray(val) && !val.length) {
            model.value = [];
          }
        },
        "class": ['v-file-upload', loaderClasses.value, props.class],
        "style": props.style,
        "focused": isFocused.value
      }, rootAttrs, inputProps), {
        ...slots,
        default: () => {
          return createElementVNode(Fragment, null, [slots.default ? createElementVNode(Fragment, null, [slots.default(), createElementVNode("input", mergeProps({
            "ref": inputRef,
            "type": "file",
            "accept": inputAccept,
            "disabled": props.disabled ?? undefined,
            "multiple": props.multiple,
            "name": props.name,
            "style": "display: none;",
            "onChange": onFileSelection
          }, inputAttrs), null)]) : createVNode(VFileUploadDropzone, mergeProps({
            "ref": vDropzoneRef
          }, dropzoneProps), {
            browse: slots.browse,
            icon: slots.icon,
            title: slots.title,
            divider: slots.divider,
            single: slots.single,
            item: slots.item,
            input: () => slots.input?.({
              inputNode
            }) ?? inputNode,
            loader: () => createVNode(LoaderSlot, {
              "name": "v-file-upload",
              "active": !!props.loading,
              "color": loadingColor.value
            }, {
              default: slots.loader
            })
          }), !slots.default && !props.insetFileList && createVNode(VDefaultsProvider, {
            "defaults": {
              VFileUploadList: {
                clearable: props.clearable,
                showSize: props.showSize
              }
            }
          }, {
            default: () => [createVNode(VFileUploadList, null, {
              item: slots.item
            })]
          })]);
        }
      });
    });
    return forwardRefs({
      controlRef: inputRef
    }, vInputRef, vDropzoneRef);
  }
});

const makeVFooterProps = propsFactory({
  app: Boolean,
  color: String,
  height: {
    type: [Number, String],
    default: 'auto'
  },
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeElevationProps(),
  ...makeLayoutItemProps(),
  ...makeRoundedProps(),
  ...makeTagProps({
    tag: 'footer'
  }),
  ...makeThemeProps()
}, 'VFooter');
const VFooter = genericComponent()({
  name: 'VFooter',
  props: makeVFooterProps(),
  setup(props, {
    slots
  }) {
    const layoutItemStyles = ref();
    const {
      themeClasses
    } = provideTheme(props);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      borderClasses
    } = useBorder(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const autoHeight = shallowRef(32);
    const {
      resizeRef
    } = useResizeObserver(entries => {
      if (!entries.length) return;
      autoHeight.value = entries[0].target.clientHeight;
    });
    const height = computed(() => props.height === 'auto' ? autoHeight.value : parseInt(props.height, 10));
    useToggleScope(() => props.app, () => {
      const layout = useLayoutItem({
        id: props.name,
        order: computed(() => parseInt(props.order, 10)),
        position: toRef(() => 'bottom'),
        layoutSize: height,
        elementSize: computed(() => props.height === 'auto' ? undefined : height.value),
        active: toRef(() => props.app),
        absolute: toRef(() => props.absolute)
      });
      watchEffect(() => {
        layoutItemStyles.value = layout.layoutItemStyles.value;
      });
    });
    useRender(() => createVNode(props.tag, {
      "ref": resizeRef,
      "class": normalizeClass(['v-footer', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, props.class]),
      "style": normalizeStyle([backgroundColorStyles.value, props.app ? layoutItemStyles.value : {
        height: convertToUnit(props.height)
      }, roundedStyles.value, props.style])
    }, slots));
    return {};
  }
});

// Types

const makeVFormProps = propsFactory({
  ...makeComponentProps(),
  ...makeFormProps()
}, 'VForm');
const VForm = genericComponent()({
  name: 'VForm',
  props: makeVFormProps(),
  emits: {
    'update:modelValue': val => true,
    submit: e => true
  },
  setup(props, {
    slots,
    emit
  }) {
    const form = createForm(props);
    const formRef = ref();
    function onReset(e) {
      e.preventDefault();
      form.reset();
    }
    function onSubmit(_e) {
      const e = _e;
      const ready = form.validate();
      e.then = ready.then.bind(ready);
      e.catch = ready.catch.bind(ready);
      e.finally = ready.finally.bind(ready);
      emit('submit', e);
      if (!e.defaultPrevented) {
        ready.then(({
          valid
        }) => {
          if (valid) {
            formRef.value?.submit();
          }
        });
      }
      e.preventDefault();
    }
    useRender(() => createElementVNode("form", {
      "ref": formRef,
      "class": normalizeClass(['v-form', props.class]),
      "style": normalizeStyle(props.style),
      "novalidate": true,
      "onReset": onReset,
      "onSubmit": onSubmit
    }, [slots.default?.({
      get errors() {
        return form.errors.value;
      },
      get isDisabled() {
        return form.isDisabled.value;
      },
      get isReadonly() {
        return form.isReadonly.value;
      },
      get isValidating() {
        return form.isValidating.value;
      },
      get isValid() {
        return form.isValid.value;
      },
      get items() {
        return form.items.value;
      },
      validate: form.validate,
      reset: form.reset,
      resetValidation: form.resetValidation
    })]));
    return forwardRefs(form, formRef);
  }
});

const makeVKbdProps = propsFactory({
  color: String,
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeRoundedProps(),
  ...makeTagProps({
    tag: 'kbd'
  }),
  ...makeThemeProps(),
  ...makeElevationProps()
}, 'VKbd');
const VKbd = genericComponent()({
  name: 'VKbd',
  props: makeVKbdProps(),
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      borderClasses
    } = useBorder(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      elevationClasses
    } = useElevation(props);
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-kbd', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, props.class]),
      "style": normalizeStyle([backgroundColorStyles.value, roundedStyles.value, props.style])
    }, slots));
    return {};
  }
});

// Types

// Display mode types for different visual representations

// Extended variant type that includes our custom 'contained' variant

// Key display tuple: [mode, content] where content is string or IconValue

// Key tuple: [mode, content, keycode] where content is string or IconValue

function processKey(config, requestedMode, isMac) {
  const keyCfg = isMac && config.mac ? config.mac : config.default;

  // 1. Resolve the safest display mode for the current platform
  const mode = (() => {
    // If the requested mode lacks an asset, fall back to text
    if (requestedMode === 'icon' && !keyCfg.icon) return 'text';
    if (requestedMode === 'symbol' && !keyCfg.symbol) return 'text';
    return requestedMode;
  })();

  // 2. Pick value for the chosen mode, defaulting to text representation
  let value = keyCfg[mode] ?? keyCfg.text;

  // 3. Guard against icon tokens leaking into text mode (e.g. "$ctrl")
  if (mode === 'text' && typeof value === 'string' && value.startsWith('$') && !value.startsWith('$vuetify.')) {
    value = value.slice(1).toUpperCase(); // "$ctrl" → "CTRL"
  }
  return mode === 'icon' ? ['icon', value] : [mode, value];
}
const hotkeyMap = {
  ctrl: {
    mac: {
      symbol: '⌃',
      icon: '$ctrl',
      text: '$vuetify.hotkey.ctrl'
    },
    default: {
      text: 'Ctrl'
    }
  },
  meta: {
    mac: {
      symbol: '⌘',
      icon: '$command',
      text: '$vuetify.hotkey.command'
    },
    default: {
      text: 'Ctrl'
    }
  },
  cmd: {
    mac: {
      symbol: '⌘',
      icon: '$command',
      text: '$vuetify.hotkey.command'
    },
    default: {
      text: 'Ctrl'
    }
  },
  shift: {
    mac: {
      symbol: '⇧',
      icon: '$shift',
      text: '$vuetify.hotkey.shift'
    },
    default: {
      text: 'Shift'
    }
  },
  alt: {
    mac: {
      symbol: '⌥',
      icon: '$alt',
      text: '$vuetify.hotkey.option'
    },
    default: {
      text: 'Alt'
    }
  },
  enter: {
    default: {
      symbol: '↵',
      icon: '$enter',
      text: '$vuetify.hotkey.enter'
    }
  },
  arrowup: {
    default: {
      symbol: '↑',
      icon: '$arrowup',
      text: '$vuetify.hotkey.upArrow'
    }
  },
  arrowdown: {
    default: {
      symbol: '↓',
      icon: '$arrowdown',
      text: '$vuetify.hotkey.downArrow'
    }
  },
  arrowleft: {
    default: {
      symbol: '←',
      icon: '$arrowleft',
      text: '$vuetify.hotkey.leftArrow'
    }
  },
  arrowright: {
    default: {
      symbol: '→',
      icon: '$arrowright',
      text: '$vuetify.hotkey.rightArrow'
    }
  },
  backspace: {
    default: {
      symbol: '⌫',
      icon: '$backspace',
      text: '$vuetify.hotkey.backspace'
    }
  },
  escape: {
    default: {
      text: '$vuetify.hotkey.escape'
    }
  },
  ' ': {
    mac: {
      symbol: '␣',
      icon: '$space',
      text: '$vuetify.hotkey.space'
    },
    default: {
      text: '$vuetify.hotkey.space'
    }
  },
  '-': {
    default: {
      text: '-'
    }
  },
  '+': {
    default: {
      text: '+'
    }
  }
};
const makeVHotkeyProps = propsFactory({
  // String representing keyboard shortcuts (e.g., "ctrl+k", "meta+shift+p")
  keys: String,
  // How to display keys: 'symbol' uses special characters (⌘, ⌃), 'icon' uses SVG icons, 'text' uses words
  displayMode: {
    type: String,
    default: 'icon'
  },
  // Custom key mapping configuration. Users can import and modify the exported hotkeyMap as needed
  keyMap: {
    type: Object,
    default: () => hotkeyMap
  },
  platform: {
    type: String,
    default: 'auto'
  },
  inline: Boolean,
  disabled: Boolean,
  prefix: String,
  suffix: String,
  variant: {
    type: String,
    default: 'elevated',
    validator: v => ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain', 'contained'].includes(v)
  },
  ...makeComponentProps(),
  ...makeThemeProps(),
  ...makeBorderProps(),
  ...makeRoundedProps(),
  ...makeElevationProps(),
  color: String
}, 'VHotkey');
const AND_DELINEATOR = Symbol('VHotkey:AND_DELINEATOR'); // For +_ separators
const OR_DELINEATOR = Symbol('VHotkey:OR_DELINEATOR'); // For / separators
const THEN_DELINEATOR = Symbol('VHotkey:THEN_DELINEATOR'); // For - separators

function getKeyText(keyMap, key, isMac) {
  const lowerKey = key.toLowerCase();
  if (lowerKey in keyMap) {
    const result = processKey(keyMap[lowerKey], 'text', isMac);
    return typeof result[1] === 'string' ? result[1] : String(result[1]);
  }
  return key.toUpperCase();
}
function applyDisplayModeToKey(keyMap, mode, key, isMac) {
  const lowerKey = key.toLowerCase();
  if (lowerKey in keyMap) {
    const result = processKey(keyMap[lowerKey], mode, isMac);
    if (result[0] === 'text' && typeof result[1] === 'string' && result[1].startsWith('$') && !result[1].startsWith('$vuetify.')) {
      return ['text', result[1].replace('$', '').toUpperCase(), key];
    }
    return [...result, key];
  }
  return ['text', key.toUpperCase(), key];
}
const VHotkey = genericComponent()({
  name: 'VHotkey',
  props: makeVHotkeyProps(),
  setup(props) {
    const {
      t
    } = useLocale();
    const {
      themeClasses
    } = provideTheme(props);
    const {
      rtlClasses
    } = useRtl();
    const {
      borderClasses
    } = useBorder(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      colorClasses,
      colorStyles,
      variantClasses
    } = useVariant(() => ({
      color: props.color,
      variant: props.variant === 'contained' ? 'elevated' : props.variant
    }));
    const isMac = computed(() => props.platform === 'auto' ? typeof navigator !== 'undefined' && /macintosh/i.test(navigator.userAgent) : props.platform === 'mac');
    const keyCombinations = computed(() => {
      if (!props.keys) return [];

      // Split by spaces to handle multiple key combinations
      // Example: "ctrl+k meta+p" -> ["ctrl+k", "meta+p"]
      return props.keys.split(/\b \b/).map(combination => {
        const result = [];
        function visit(node) {
          if (typeof node === 'string') {
            if (node !== '') {
              result.push(applyDisplayModeToKey(props.keyMap, props.displayMode, node, isMac.value));
            }
          } else {
            for (let i = 0; i < node.parts.length; i++) {
              if (i > 0) {
                if (node.type === 'sequence') {
                  result.push(THEN_DELINEATOR);
                } else if (node.type === 'alternate') {
                  result.push(OR_DELINEATOR);
                } else if (node.type === 'combo') {
                  result.push(AND_DELINEATOR);
                } else ;
              }
              visit(node.parts[i]);
            }
          }
        }
        visit(parseKeyCombination(combination));
        return result;
      });
    });
    const accessibleLabel = computed(() => {
      if (!props.keys) return '';

      // Convert the parsed key combinations into readable text
      const readableShortcuts = keyCombinations.value.map(combination => {
        const readableParts = [];
        for (const key of combination) {
          if (Array.isArray(key)) {
            // Always use text representation for screen readers
            const textKey = key[0] === 'icon' || key[0] === 'symbol' ? applyDisplayModeToKey(mergeDeep(hotkeyMap, props.keyMap), 'text', String(key[1]), isMac.value)[1] : key[1];
            readableParts.push(translateKey(textKey));
          } else {
            if (key === AND_DELINEATOR) {
              readableParts.push(t('$vuetify.hotkey.plus'));
            } else if (key === OR_DELINEATOR) {
              readableParts.push(t('$vuetify.hotkey.or'));
            } else if (key === THEN_DELINEATOR) {
              readableParts.push(t('$vuetify.hotkey.then'));
            }
          }
        }
        return readableParts.join(' ');
      });
      const shortcutText = readableShortcuts.join(', ');
      return t('$vuetify.hotkey.shortcut', shortcutText);
    });
    function translateKey(key) {
      return key.startsWith('$vuetify.') ? t(key) : key;
    }
    function getKeyTooltip(key) {
      if (props.displayMode === 'text') return undefined;
      const textKey = getKeyText(props.keyMap, String(key[2]), isMac.value);
      return translateKey(textKey);
    }
    function renderKey(key, keyIndex) {
      const isContained = props.variant === 'contained';
      const KeyComponent = isContained ? 'kbd' : VKbd;
      const keyClasses = ['v-hotkey__key', `v-hotkey__key-${key[0]}`, ...(isContained ? ['v-hotkey__key--nested'] : [borderClasses.value, roundedClasses.value, elevationClasses.value, colorClasses.value])];
      return createVNode(KeyComponent, {
        "key": keyIndex,
        "class": normalizeClass(keyClasses),
        "style": normalizeStyle(isContained ? undefined : [colorStyles.value, roundedStyles.value]),
        "aria-hidden": "true",
        "title": getKeyTooltip(key)
      }, {
        default: () => [key[0] === 'icon' ? createVNode(VIcon, {
          "icon": key[1],
          "aria-hidden": "true"
        }, null) : translateKey(key[1])]
      });
    }
    function renderDivider(key, keyIndex) {
      return createElementVNode("span", {
        "key": keyIndex,
        "class": "v-hotkey__divider",
        "aria-hidden": "true"
      }, [key === AND_DELINEATOR ? '+' : key === OR_DELINEATOR ? t('$vuetify.hotkey.or') : t('$vuetify.hotkey.then')]);
    }
    useRender(() => {
      const content = createElementVNode(Fragment, null, [props.prefix && createElementVNode("span", {
        "key": "prefix",
        "class": "v-hotkey__prefix"
      }, [props.prefix]), keyCombinations.value.map((combination, comboIndex) => createElementVNode("span", {
        "class": "v-hotkey__combination",
        "key": comboIndex
      }, [combination.map((key, keyIndex) => Array.isArray(key) ? renderKey(key, keyIndex) : renderDivider(key, keyIndex)), comboIndex < keyCombinations.value.length - 1 && createElementVNode("span", {
        "aria-hidden": "true"
      }, [createTextVNode("\xA0")])])), props.suffix && createElementVNode("span", {
        "key": "suffix",
        "class": "v-hotkey__suffix"
      }, [props.suffix])]);
      return createElementVNode("div", {
        "class": normalizeClass(['v-hotkey', {
          'v-hotkey--disabled': props.disabled,
          'v-hotkey--inline': props.inline,
          'v-hotkey--contained': props.variant === 'contained'
        }, themeClasses.value, rtlClasses.value, variantClasses.value, props.class]),
        "style": normalizeStyle(props.style),
        "role": "img",
        "aria-label": accessibleLabel.value
      }, [props.variant !== 'contained' ? content : createVNode(VKbd, {
        "key": "contained",
        "class": normalizeClass(['v-hotkey__contained-wrapper', borderClasses.value, roundedClasses.value, elevationClasses.value, colorClasses.value]),
        "style": normalizeStyle([colorStyles.value, roundedStyles.value]),
        "aria-hidden": "true"
      }, {
        default: () => [content]
      })]);
    });
  }
});

// Composables
const makeVHoverProps = propsFactory({
  disabled: Boolean,
  modelValue: {
    type: Boolean,
    default: null
  },
  ...makeDelayProps()
}, 'VHover');
const VHover = genericComponent()({
  name: 'VHover',
  props: makeVHoverProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const isHovering = useProxiedModel(props, 'modelValue');

    // track hover state regardless of disabled, so we can reconcile
    const internal = shallowRef(false);
    const {
      runOpenDelay,
      runCloseDelay
    } = useDelay(props, value => {
      internal.value = value;
      if (!props.disabled) {
        isHovering.value = value;
      }
    });
    watch(() => props.disabled, (val, old) => {
      if (old && !val) {
        isHovering.value = internal.value;
      }
    });
    return () => slots.default?.({
      isHovering: isHovering.value,
      props: {
        onMouseenter: runOpenDelay,
        onMouseleave: runCloseDelay
      }
    });
  }
});

// Types

const makeVInfiniteScrollProps = propsFactory({
  color: String,
  direction: {
    type: String,
    default: 'vertical',
    validator: v => ['vertical', 'horizontal'].includes(v)
  },
  side: {
    type: String,
    default: 'end',
    validator: v => ['start', 'end', 'both'].includes(v)
  },
  mode: {
    type: String,
    default: 'intersect',
    validator: v => ['intersect', 'manual'].includes(v)
  },
  margin: [Number, String],
  loadMoreText: {
    type: String,
    default: '$vuetify.infiniteScroll.loadMore'
  },
  emptyText: {
    type: String,
    default: '$vuetify.infiniteScroll.empty'
  },
  ...makeDimensionProps(),
  ...makeTagProps()
}, 'VInfiniteScroll');
const VInfiniteScrollIntersect = defineComponent({
  name: 'VInfiniteScrollIntersect',
  props: {
    side: {
      type: String,
      required: true
    },
    rootMargin: String
  },
  emits: {
    intersect: (side, isIntersecting) => true
  },
  setup(props, {
    emit
  }) {
    const {
      intersectionRef,
      isIntersecting
    } = useIntersectionObserver();
    watch(isIntersecting, async val => {
      emit('intersect', props.side, val);
    });
    useRender(() => createElementVNode("div", {
      "class": "v-infinite-scroll-intersect",
      "style": {
        '--v-infinite-margin-size': props.rootMargin
      },
      "ref": intersectionRef
    }, [createTextVNode("\xA0")]));
    return {};
  }
});
const VInfiniteScroll = genericComponent()({
  name: 'VInfiniteScroll',
  props: makeVInfiniteScrollProps(),
  emits: {
    load: options => true
  },
  setup(props, {
    slots,
    emit
  }) {
    const rootEl = ref();
    const startStatus = shallowRef('ok');
    const endStatus = shallowRef('ok');
    const margin = computed(() => convertToUnit(props.margin));
    const isIntersecting = shallowRef(false);
    function setScrollAmount(amount) {
      if (!rootEl.value) return;
      const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
      rootEl.value[property] = amount;
    }
    function getScrollAmount() {
      if (!rootEl.value) return 0;
      const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
      return rootEl.value[property];
    }
    function getScrollSize() {
      if (!rootEl.value) return 0;
      const property = props.direction === 'vertical' ? 'scrollHeight' : 'scrollWidth';
      return rootEl.value[property];
    }
    function getContainerSize() {
      if (!rootEl.value) return 0;
      const property = props.direction === 'vertical' ? 'clientHeight' : 'clientWidth';
      return rootEl.value[property];
    }
    onMounted(() => {
      if (!rootEl.value) return;
      if (props.side === 'start') {
        setScrollAmount(getScrollSize());
      } else if (props.side === 'both') {
        setScrollAmount(getScrollSize() / 2 - getContainerSize() / 2);
      }
    });
    function setStatus(side, status) {
      if (side === 'start') {
        startStatus.value = status;
      } else if (side === 'end') {
        endStatus.value = status;
      } else if (side === 'both') {
        startStatus.value = status;
        endStatus.value = status;
      }
    }
    function getStatus(side) {
      return side === 'start' ? startStatus.value : endStatus.value;
    }
    let previousScrollSize = 0;
    function handleIntersect(side, _isIntersecting) {
      isIntersecting.value = _isIntersecting;
      if (isIntersecting.value) {
        intersecting(side);
      }
    }
    function intersecting(side) {
      if (props.mode !== 'manual' && !isIntersecting.value) return;
      const status = getStatus(side);
      if (!rootEl.value || ['empty', 'loading'].includes(status)) return;
      previousScrollSize = getScrollSize();
      setStatus(side, 'loading');
      function done(status) {
        setStatus(side, status);
        nextTick(() => {
          if (status === 'empty' || status === 'error') return;
          if (status === 'ok' && side === 'start') {
            setScrollAmount(getScrollSize() - previousScrollSize + getScrollAmount());
          }
          if (props.mode !== 'manual') {
            nextTick(() => {
              // Browser takes 2 - 3 animation frames to trigger IntersectionObserver after
              // VInfiniteScrollIntersect leaves the viewpoint. So far I couldn't come up
              // with a better solution than using 3 nested window.requestAnimationFrame. (#17475)
              window.requestAnimationFrame(() => {
                window.requestAnimationFrame(() => {
                  window.requestAnimationFrame(() => {
                    intersecting(side);
                  });
                });
              });
            });
          }
        });
      }
      emit('load', {
        side,
        done
      });
    }
    const {
      t
    } = useLocale();
    function renderSide(side, status) {
      if (props.side !== side && props.side !== 'both') return;
      const onClick = () => intersecting(side);
      const slotProps = {
        side,
        props: {
          onClick,
          color: props.color
        }
      };
      if (status === 'error') return slots.error?.(slotProps);
      if (status === 'empty') return slots.empty?.(slotProps) ?? createElementVNode("div", null, [t(props.emptyText)]);
      if (props.mode === 'manual') {
        if (status === 'loading') {
          return slots.loading?.(slotProps) ?? createVNode(VProgressCircular, {
            "indeterminate": true,
            "color": props.color
          }, null);
        }
        return slots['load-more']?.(slotProps) ?? createVNode(VBtn, {
          "variant": "outlined",
          "color": props.color,
          "onClick": onClick
        }, {
          default: () => [t(props.loadMoreText)]
        });
      }
      return slots.loading?.(slotProps) ?? createVNode(VProgressCircular, {
        "indeterminate": true,
        "color": props.color
      }, null);
    }
    const {
      dimensionStyles
    } = useDimension(props);
    useRender(() => {
      const Tag = props.tag;
      const hasStartIntersect = props.side === 'start' || props.side === 'both';
      const hasEndIntersect = props.side === 'end' || props.side === 'both';
      const intersectMode = props.mode === 'intersect';
      return createVNode(Tag, {
        "ref": rootEl,
        "class": normalizeClass(['v-infinite-scroll', `v-infinite-scroll--${props.direction}`, {
          'v-infinite-scroll--start': hasStartIntersect,
          'v-infinite-scroll--end': hasEndIntersect
        }]),
        "style": normalizeStyle(dimensionStyles.value)
      }, {
        default: () => [createElementVNode("div", {
          "class": "v-infinite-scroll__side"
        }, [renderSide('start', startStatus.value)]), hasStartIntersect && intersectMode && createVNode(VInfiniteScrollIntersect, {
          "key": "start",
          "side": "start",
          "onIntersect": handleIntersect,
          "rootMargin": margin.value
        }, null), slots.default?.(), hasEndIntersect && intersectMode && createVNode(VInfiniteScrollIntersect, {
          "key": "end",
          "side": "end",
          "onIntersect": handleIntersect,
          "rootMargin": margin.value
        }, null), createElementVNode("div", {
          "class": "v-infinite-scroll__side"
        }, [renderSide('end', endStatus.value)])]
      });
    });
    function reset(side) {
      const effectiveSide = side ?? props.side;
      setStatus(effectiveSide, 'ok');
      nextTick(() => {
        if (effectiveSide !== 'end') {
          setScrollAmount(getScrollSize() - previousScrollSize + getScrollAmount());
        }
        if (props.mode !== 'manual') {
          nextTick(() => {
            // See #17475
            window.requestAnimationFrame(() => {
              window.requestAnimationFrame(() => {
                window.requestAnimationFrame(() => {
                  if (effectiveSide === 'both') {
                    intersecting('start');
                    intersecting('end');
                  } else {
                    intersecting(effectiveSide);
                  }
                });
              });
            });
          });
        }
      });
    }
    return {
      reset
    };
  }
});

// Types

const VItemGroupSymbol = Symbol.for('vuetify:v-item-group');
const makeVItemGroupProps = propsFactory({
  ...makeComponentProps(),
  ...makeGroupProps({
    selectedClass: 'v-item--selected'
  }),
  ...makeTagProps(),
  ...makeThemeProps()
}, 'VItemGroup');
const VItemGroup = genericComponent()({
  name: 'VItemGroup',
  props: makeVItemGroupProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      isSelected,
      select,
      next,
      prev,
      selected
    } = useGroup(props, VItemGroupSymbol);
    return () => createVNode(props.tag, {
      "class": normalizeClass(['v-item-group', themeClasses.value, props.class]),
      "style": normalizeStyle(props.style)
    }, {
      default: () => [slots.default?.({
        isSelected,
        select,
        next,
        prev,
        selected: selected.value
      })]
    });
  }
});

// Composables
const VItem = genericComponent()({
  name: 'VItem',
  props: makeGroupItemProps(),
  emits: {
    'group:selected': val => true
  },
  setup(props, {
    slots
  }) {
    const {
      isSelected,
      select,
      toggle,
      selectedClass,
      value,
      disabled
    } = useGroupItem(props, VItemGroupSymbol);
    return () => slots.default?.({
      isSelected: isSelected.value,
      selectedClass: selectedClass.value,
      select,
      toggle,
      value: value.value,
      disabled: disabled.value
    });
  }
});

const makeVLayoutProps = propsFactory({
  ...makeComponentProps(),
  ...makeDimensionProps(),
  ...makeLayoutProps()
}, 'VLayout');
const VLayout = genericComponent()({
  name: 'VLayout',
  props: makeVLayoutProps(),
  setup(props, {
    slots
  }) {
    const {
      layoutClasses,
      layoutStyles,
      getLayoutItem,
      items,
      layoutRef
    } = createLayout(props);
    const {
      dimensionStyles
    } = useDimension(props);
    useRender(() => createElementVNode("div", {
      "ref": layoutRef,
      "class": normalizeClass([layoutClasses.value, props.class]),
      "style": normalizeStyle([dimensionStyles.value, layoutStyles.value, props.style])
    }, [slots.default?.()]));
    return {
      getLayoutItem,
      items
    };
  }
});

// Types

const makeVLayoutItemProps = propsFactory({
  position: {
    type: String,
    required: true
  },
  size: {
    type: [Number, String],
    default: 300
  },
  modelValue: Boolean,
  ...makeComponentProps(),
  ...makeLayoutItemProps()
}, 'VLayoutItem');
const VLayoutItem = genericComponent()({
  name: 'VLayoutItem',
  props: makeVLayoutItemProps(),
  setup(props, {
    slots
  }) {
    const {
      layoutItemStyles
    } = useLayoutItem({
      id: props.name,
      order: computed(() => parseInt(props.order, 10)),
      position: toRef(() => props.position),
      elementSize: toRef(() => props.size),
      layoutSize: toRef(() => props.size),
      active: toRef(() => props.modelValue),
      absolute: toRef(() => props.absolute)
    });
    return () => createElementVNode("div", {
      "class": normalizeClass(['v-layout-item', props.class]),
      "style": normalizeStyle([layoutItemStyles.value, props.style])
    }, [slots.default?.()]);
  }
});

// Types

const makeVLazyProps = propsFactory({
  modelValue: Boolean,
  options: {
    type: Object,
    // For more information on types, navigate to:
    // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
    default: () => ({
      root: undefined,
      rootMargin: undefined,
      threshold: undefined
    })
  },
  ...makeComponentProps(),
  ...makeDimensionProps(),
  ...makeTagProps(),
  ...makeTransitionProps({
    transition: 'fade-transition'
  })
}, 'VLazy');
const VLazy = genericComponent()({
  name: 'VLazy',
  directives: {
    vIntersect: Intersect
  },
  props: makeVLazyProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const {
      dimensionStyles
    } = useDimension(props);
    const isActive = useProxiedModel(props, 'modelValue');
    function onIntersect(isIntersecting) {
      if (isActive.value) return;
      isActive.value = isIntersecting;
    }
    useRender(() => withDirectives(createVNode(props.tag, {
      "class": normalizeClass(['v-lazy', props.class]),
      "style": normalizeStyle([dimensionStyles.value, props.style])
    }, {
      default: () => [isActive.value && createVNode(MaybeTransition, {
        "transition": props.transition,
        "appear": true
      }, {
        default: () => [slots.default?.()]
      })]
    }), [[Intersect, {
      handler: onIntersect,
      options: props.options
    }, null]]));
    return {};
  }
});

const makeVLocaleProviderProps = propsFactory({
  locale: String,
  fallbackLocale: String,
  messages: Object,
  rtl: {
    type: Boolean,
    default: undefined
  },
  ...makeComponentProps()
}, 'VLocaleProvider');
const VLocaleProvider = genericComponent()({
  name: 'VLocaleProvider',
  props: makeVLocaleProviderProps(),
  setup(props, {
    slots
  }) {
    const {
      rtlClasses
    } = provideLocale(props);
    useRender(() => createElementVNode("div", {
      "class": normalizeClass(['v-locale-provider', rtlClasses.value, props.class]),
      "style": normalizeStyle(props.style)
    }, [slots.default?.()]));
    return {};
  }
});

const makeVMainProps = propsFactory({
  scrollable: Boolean,
  ...makeComponentProps(),
  ...makeDimensionProps(),
  ...makeTagProps({
    tag: 'main'
  })
}, 'VMain');
const VMain = genericComponent()({
  name: 'VMain',
  props: makeVMainProps(),
  setup(props, {
    slots
  }) {
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      mainStyles
    } = useLayout();
    const {
      ssrBootStyles
    } = useSsrBoot();
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-main', {
        'v-main--scrollable': props.scrollable
      }, props.class]),
      "style": normalizeStyle([mainStyles.value, ssrBootStyles.value, dimensionStyles.value, props.style])
    }, {
      default: () => [props.scrollable ? createElementVNode("div", {
        "class": "v-main__scroller"
      }, [slots.default?.()]) : slots.default?.()]
    }));
    return {};
  }
});

// Utilities

// Types

function useSticky({
  rootEl,
  isSticky,
  layoutItemStyles
}) {
  const isStuck = shallowRef(false);
  const stuckPosition = shallowRef(0);
  const stickyStyles = computed(() => {
    const side = typeof isStuck.value === 'boolean' ? 'top' : isStuck.value;
    return [isSticky.value ? {
      top: 'auto',
      bottom: 'auto',
      height: undefined
    } : undefined, isStuck.value ? {
      [side]: convertToUnit(stuckPosition.value)
    } : {
      top: layoutItemStyles.value.top
    }];
  });
  onMounted(() => {
    watch(isSticky, val => {
      if (val) {
        window.addEventListener('scroll', onScroll, {
          passive: true
        });
      } else {
        window.removeEventListener('scroll', onScroll);
      }
    }, {
      immediate: true
    });
  });
  onBeforeUnmount(() => {
    window.removeEventListener('scroll', onScroll);
  });
  let lastScrollTop = 0;
  function onScroll() {
    const direction = lastScrollTop > window.scrollY ? 'up' : 'down';
    const rect = rootEl.value.getBoundingClientRect();
    const layoutTop = parseFloat(layoutItemStyles.value.top ?? 0);
    const top = window.scrollY - Math.max(0, stuckPosition.value - layoutTop);
    const bottom = rect.height + Math.max(stuckPosition.value, layoutTop) - window.scrollY - window.innerHeight;
    const bodyScroll = parseFloat(getComputedStyle(rootEl.value).getPropertyValue('--v-body-scroll-y')) || 0;
    if (rect.height < window.innerHeight - layoutTop) {
      isStuck.value = 'top';
      stuckPosition.value = layoutTop;
    } else if (direction === 'up' && isStuck.value === 'bottom' || direction === 'down' && isStuck.value === 'top') {
      stuckPosition.value = window.scrollY + rect.top - bodyScroll;
      isStuck.value = true;
    } else if (direction === 'down' && bottom <= 0) {
      stuckPosition.value = 0;
      isStuck.value = 'bottom';
    } else if (direction === 'up' && top <= 0) {
      if (!bodyScroll) {
        stuckPosition.value = rect.top + top;
        isStuck.value = 'top';
      } else if (isStuck.value !== 'top') {
        stuckPosition.value = -top + bodyScroll + layoutTop;
        isStuck.value = 'top';
      }
    }
    lastScrollTop = window.scrollY;
  }
  return {
    isStuck,
    stickyStyles
  };
}

// Utilities
const HORIZON = 100; // ms
const HISTORY = 20; // number of samples to keep

/** @see https://android.googlesource.com/platform/frameworks/native/+/master/libs/input/VelocityTracker.cpp */
function kineticEnergyToVelocity(work) {
  const sqrt2 = 1.41421356237;
  return (work < 0 ? -1 : 1.0) * Math.sqrt(Math.abs(work)) * sqrt2;
}

/**
 * Returns pointer velocity in px/s
 */
function calculateImpulseVelocity(samples) {
  // The input should be in reversed time order (most recent sample at index i=0)
  if (samples.length < 2) {
    // if 0 or 1 points, velocity is zero
    return 0;
  }
  // if (samples[1].t > samples[0].t) {
  //   // Algorithm will still work, but not perfectly
  //   consoleWarn('Samples provided to calculateImpulseVelocity in the wrong order')
  // }
  if (samples.length === 2) {
    // if 2 points, basic linear calculation
    if (samples[1].t === samples[0].t) {
      // consoleWarn(`Events have identical time stamps t=${samples[0].t}, setting velocity = 0`)
      return 0;
    }
    return (samples[1].d - samples[0].d) / (samples[1].t - samples[0].t);
  }
  // Guaranteed to have at least 3 points here
  // start with the oldest sample and go forward in time
  let work = 0;
  for (let i = samples.length - 1; i > 0; i--) {
    if (samples[i].t === samples[i - 1].t) {
      // consoleWarn(`Events have identical time stamps t=${samples[i].t}, skipping sample`)
      continue;
    }
    const vprev = kineticEnergyToVelocity(work); // v[i-1]
    const vcurr = (samples[i].d - samples[i - 1].d) / (samples[i].t - samples[i - 1].t); // v[i]
    work += (vcurr - vprev) * Math.abs(vcurr);
    if (i === samples.length - 1) {
      work *= 0.5;
    }
  }
  return kineticEnergyToVelocity(work) * 1000;
}
function useVelocity() {
  const touches = {};
  function addMovement(e) {
    Array.from(e.changedTouches).forEach(touch => {
      const samples = touches[touch.identifier] ?? (touches[touch.identifier] = new CircularBuffer(HISTORY));
      samples.push([e.timeStamp, touch]);
    });
  }
  function endTouch(e) {
    Array.from(e.changedTouches).forEach(touch => {
      delete touches[touch.identifier];
    });
  }
  function getVelocity(id) {
    const samples = touches[id]?.values().reverse();
    if (!samples) {
      throw new Error(`No samples for touch id ${id}`);
    }
    const newest = samples[0];
    const x = [];
    const y = [];
    for (const val of samples) {
      if (newest[0] - val[0] > HORIZON) break;
      x.push({
        t: val[0],
        d: val[1].clientX
      });
      y.push({
        t: val[0],
        d: val[1].clientY
      });
    }
    return {
      x: calculateImpulseVelocity(x),
      y: calculateImpulseVelocity(y),
      get direction() {
        const {
          x,
          y
        } = this;
        const [absX, absY] = [Math.abs(x), Math.abs(y)];
        return absX > absY && x >= 0 ? 'right' : absX > absY && x <= 0 ? 'left' : absY > absX && y >= 0 ? 'down' : absY > absX && y <= 0 ? 'up' : oops$1();
      }
    };
  }
  return {
    addMovement,
    endTouch,
    getVelocity
  };
}
function oops$1() {
  throw new Error();
}

// Composables

// Types

function useTouch({
  el,
  isActive,
  isTemporary,
  width,
  touchless,
  position
}) {
  onMounted(() => {
    window.addEventListener('touchstart', onTouchstart, {
      passive: true
    });
    window.addEventListener('touchmove', onTouchmove, {
      passive: false
    });
    window.addEventListener('touchend', onTouchend, {
      passive: true
    });
  });
  onBeforeUnmount(() => {
    window.removeEventListener('touchstart', onTouchstart);
    window.removeEventListener('touchmove', onTouchmove);
    window.removeEventListener('touchend', onTouchend);
  });
  const isHorizontal = computed(() => ['left', 'right'].includes(position.value));
  const {
    addMovement,
    endTouch,
    getVelocity
  } = useVelocity();
  let maybeDragging = false;
  const isDragging = shallowRef(false);
  const dragProgress = shallowRef(0);
  const offset = shallowRef(0);
  let start;
  function getOffset(pos, active) {
    return (position.value === 'left' ? pos : position.value === 'right' ? document.documentElement.clientWidth - pos : position.value === 'top' ? pos : position.value === 'bottom' ? document.documentElement.clientHeight - pos : oops()) - (active ? width.value : 0);
  }
  function getProgress(pos, limit = true) {
    const progress = position.value === 'left' ? (pos - offset.value) / width.value : position.value === 'right' ? (document.documentElement.clientWidth - pos - offset.value) / width.value : position.value === 'top' ? (pos - offset.value) / width.value : position.value === 'bottom' ? (document.documentElement.clientHeight - pos - offset.value) / width.value : oops();
    return limit ? clamp(progress) : progress;
  }
  function onTouchstart(e) {
    if (touchless.value) return;
    const touchX = e.changedTouches[0].clientX;
    const touchY = e.changedTouches[0].clientY;
    const touchZone = 25;
    const inTouchZone = position.value === 'left' ? touchX < touchZone : position.value === 'right' ? touchX > document.documentElement.clientWidth - touchZone : position.value === 'top' ? touchY < touchZone : position.value === 'bottom' ? touchY > document.documentElement.clientHeight - touchZone : oops();
    const inElement = isActive.value && (position.value === 'left' ? touchX < width.value : position.value === 'right' ? touchX > document.documentElement.clientWidth - width.value : position.value === 'top' ? touchY < width.value : position.value === 'bottom' ? touchY > document.documentElement.clientHeight - width.value : oops());
    if (inTouchZone || inElement || isActive.value && isTemporary.value) {
      start = [touchX, touchY];
      offset.value = getOffset(isHorizontal.value ? touchX : touchY, isActive.value);
      dragProgress.value = getProgress(isHorizontal.value ? touchX : touchY);
      maybeDragging = offset.value > -20 && offset.value < 80;
      endTouch(e);
      addMovement(e);
    }
  }
  function onTouchmove(e) {
    const touchX = e.changedTouches[0].clientX;
    const touchY = e.changedTouches[0].clientY;
    if (maybeDragging) {
      if (!e.cancelable) {
        maybeDragging = false;
        return;
      }
      const dx = Math.abs(touchX - start[0]);
      const dy = Math.abs(touchY - start[1]);
      const thresholdMet = isHorizontal.value ? dx > dy && dx > 3 : dy > dx && dy > 3;
      if (thresholdMet) {
        isDragging.value = true;
        maybeDragging = false;
      } else if ((isHorizontal.value ? dy : dx) > 3) {
        maybeDragging = false;
      }
    }
    if (!isDragging.value) return;
    e.preventDefault();
    addMovement(e);
    const progress = getProgress(isHorizontal.value ? touchX : touchY, false);
    dragProgress.value = Math.max(0, Math.min(1, progress));
    if (progress > 1) {
      offset.value = getOffset(isHorizontal.value ? touchX : touchY, true);
    } else if (progress < 0) {
      offset.value = getOffset(isHorizontal.value ? touchX : touchY, false);
    }
  }
  function onTouchend(e) {
    maybeDragging = false;
    if (!isDragging.value) return;
    addMovement(e);
    isDragging.value = false;
    const velocity = getVelocity(e.changedTouches[0].identifier);
    const vx = Math.abs(velocity.x);
    const vy = Math.abs(velocity.y);
    const thresholdMet = isHorizontal.value ? vx > vy && vx > 400 : vy > vx && vy > 3;
    if (thresholdMet) {
      isActive.value = velocity.direction === ({
        left: 'right',
        right: 'left',
        top: 'down',
        bottom: 'up'
      }[position.value] || oops());
    } else {
      isActive.value = dragProgress.value > 0.5;
    }
  }
  const dragStyles = computed(() => {
    return isDragging.value ? {
      transform: position.value === 'left' ? `translateX(calc(-100% + ${dragProgress.value * width.value}px))` : position.value === 'right' ? `translateX(calc(100% - ${dragProgress.value * width.value}px))` : position.value === 'top' ? `translateY(calc(-100% + ${dragProgress.value * width.value}px))` : position.value === 'bottom' ? `translateY(calc(100% - ${dragProgress.value * width.value}px))` : oops(),
      transition: 'none'
    } : undefined;
  });
  useToggleScope(isDragging, () => {
    const transform = el.value?.style.transform ?? null;
    const transition = el.value?.style.transition ?? null;
    watchEffect(() => {
      el.value?.style.setProperty('transform', dragStyles.value?.transform || 'none');
      el.value?.style.setProperty('transition', dragStyles.value?.transition || null);
    });
    onScopeDispose(() => {
      el.value?.style.setProperty('transform', transform);
      el.value?.style.setProperty('transition', transition);
    });
  });
  return {
    isDragging,
    dragProgress,
    dragStyles
  };
}
function oops() {
  throw new Error();
}

// Types

const locations = ['start', 'end', 'left', 'right', 'top', 'bottom'];
const makeVNavigationDrawerProps = propsFactory({
  color: String,
  disableResizeWatcher: Boolean,
  disableRouteWatcher: Boolean,
  expandOnHover: Boolean,
  floating: Boolean,
  modelValue: {
    type: Boolean,
    default: null
  },
  permanent: Boolean,
  rail: {
    type: Boolean,
    default: null
  },
  railWidth: {
    type: [Number, String],
    default: 56
  },
  scrim: {
    type: [Boolean, String],
    default: true
  },
  image: String,
  temporary: Boolean,
  persistent: Boolean,
  touchless: Boolean,
  width: {
    type: [Number, String],
    default: 256
  },
  location: {
    type: String,
    default: 'start',
    validator: value => locations.includes(value)
  },
  sticky: Boolean,
  ...makeBorderProps(),
  ...makeComponentProps(),
  ...makeDelayProps(),
  ...makeDisplayProps({
    mobile: null
  }),
  ...makeElevationProps(),
  ...makeLayoutItemProps(),
  ...makeRoundedProps(),
  ...omit(makeFocusTrapProps(), ['disableInitialFocus']),
  ...makeTagProps({
    tag: 'nav'
  }),
  ...makeThemeProps()
}, 'VNavigationDrawer');
const VNavigationDrawer = genericComponent()({
  name: 'VNavigationDrawer',
  props: makeVNavigationDrawerProps(),
  emits: {
    'update:modelValue': val => true,
    'update:rail': val => true
  },
  setup(props, {
    attrs,
    emit,
    slots
  }) {
    const {
      isRtl
    } = useRtl();
    const {
      themeClasses
    } = provideTheme(props);
    const {
      borderClasses
    } = useBorder(props);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      displayClasses,
      mobile
    } = useDisplay(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const router = useRouter();
    const isActive = useProxiedModel(props, 'modelValue', null, v => !!v);
    const {
      ssrBootStyles
    } = useSsrBoot();
    const {
      scopeId
    } = useScopeId();
    const rootEl = ref();
    const isHovering = shallowRef(false);
    const {
      runOpenDelay,
      runCloseDelay
    } = useDelay(props, value => {
      isHovering.value = value;
    });
    const width = computed(() => {
      return props.rail && props.expandOnHover && isHovering.value ? Number(props.width) : Number(props.rail ? props.railWidth : props.width);
    });
    const location = computed(() => {
      return toPhysical(props.location, isRtl.value);
    });
    const isPersistent = toRef(() => props.persistent);
    const isTemporary = computed(() => !props.permanent && (mobile.value || props.temporary));
    const isSticky = computed(() => props.sticky && !isTemporary.value && location.value !== 'bottom');
    useFocusTrap(props, {
      isActive,
      localTop: isTemporary,
      contentEl: rootEl
    });
    useToggleScope(() => props.expandOnHover && props.rail != null, () => {
      watch(isHovering, val => emit('update:rail', !val));
    });
    useToggleScope(() => !props.disableResizeWatcher, () => {
      watch(isTemporary, val => !props.permanent && nextTick(() => isActive.value = !val));
    });
    useToggleScope(() => !props.disableRouteWatcher && !!router, () => {
      watch(router.currentRoute, () => isTemporary.value && (isActive.value = false));
    });
    watch(() => props.permanent, val => {
      if (val) isActive.value = true;
    });
    if (props.modelValue == null && !isTemporary.value) {
      isActive.value = props.permanent || !mobile.value;
    }
    const {
      isDragging,
      dragProgress
    } = useTouch({
      el: rootEl,
      isActive,
      isTemporary,
      width,
      touchless: toRef(() => props.touchless),
      position: location
    });
    const layoutSize = computed(() => {
      const size = isTemporary.value ? 0 : props.rail && props.expandOnHover ? Number(props.railWidth) : width.value;
      return isDragging.value ? size * dragProgress.value : size;
    });
    const {
      layoutItemStyles,
      layoutItemScrimStyles
    } = useLayoutItem({
      id: props.name,
      order: computed(() => parseInt(props.order, 10)),
      position: location,
      layoutSize,
      elementSize: width,
      active: readonly(isActive),
      disableTransitions: toRef(() => isDragging.value),
      absolute: computed(() =>
      // eslint-disable-next-line @typescript-eslint/no-use-before-define
      props.absolute || isSticky.value && typeof isStuck.value !== 'string')
    });
    const {
      isStuck,
      stickyStyles
    } = useSticky({
      rootEl,
      isSticky,
      layoutItemStyles
    });
    const scrimColor = useBackgroundColor(() => {
      return typeof props.scrim === 'string' ? props.scrim : null;
    });
    const scrimStyles = computed(() => ({
      ...(isDragging.value ? {
        opacity: dragProgress.value * 0.2,
        transition: 'none'
      } : undefined),
      ...layoutItemScrimStyles.value
    }));
    provideDefaults({
      VList: {
        bgColor: 'transparent'
      }
    });
    useRender(() => {
      const hasImage = slots.image || props.image;
      return createElementVNode(Fragment, null, [createVNode(props.tag, mergeProps({
        "ref": rootEl,
        "onMouseenter": runOpenDelay,
        "onMouseleave": runCloseDelay,
        "class": ['v-navigation-drawer', `v-navigation-drawer--${location.value}`, {
          'v-navigation-drawer--expand-on-hover': props.expandOnHover,
          'v-navigation-drawer--floating': props.floating,
          'v-navigation-drawer--is-hovering': isHovering.value,
          'v-navigation-drawer--rail': props.rail,
          'v-navigation-drawer--temporary': isTemporary.value,
          'v-navigation-drawer--persistent': isPersistent.value,
          'v-navigation-drawer--active': isActive.value,
          'v-navigation-drawer--sticky': isSticky.value
        }, themeClasses.value, backgroundColorClasses.value, borderClasses.value, displayClasses.value, elevationClasses.value, roundedClasses.value, props.class],
        "style": [backgroundColorStyles.value, layoutItemStyles.value, ssrBootStyles.value, stickyStyles.value, roundedStyles.value, props.style],
        "inert": !isActive.value
      }, scopeId, attrs), {
        default: () => [hasImage && createElementVNode("div", {
          "key": "image",
          "class": "v-navigation-drawer__img"
        }, [!slots.image ? createVNode(VImg, {
          "key": "image-img",
          "alt": "",
          "cover": true,
          "height": "inherit",
          "src": props.image
        }, null) : createVNode(VDefaultsProvider, {
          "key": "image-defaults",
          "disabled": !props.image,
          "defaults": {
            VImg: {
              alt: '',
              cover: true,
              height: 'inherit',
              src: props.image
            }
          }
        }, slots.image)]), slots.prepend && createElementVNode("div", {
          "class": "v-navigation-drawer__prepend"
        }, [slots.prepend?.()]), createElementVNode("div", {
          "class": "v-navigation-drawer__content"
        }, [slots.default?.()]), slots.append && createElementVNode("div", {
          "class": "v-navigation-drawer__append"
        }, [slots.append?.()])]
      }), createVNode(Transition, {
        "name": "fade-transition"
      }, {
        default: () => [isTemporary.value && (isDragging.value || isActive.value) && !!props.scrim && createElementVNode("div", mergeProps({
          "class": ['v-navigation-drawer__scrim', scrimColor.backgroundColorClasses.value],
          "style": [scrimStyles.value, scrimColor.backgroundColorStyles.value],
          "onClick": () => {
            if (isPersistent.value) return;
            isActive.value = false;
          }
        }, scopeId), null)]
      })]);
    });
    return {
      isStuck
    };
  }
});

// Composables
const VNoSsr = defineComponent({
  name: 'VNoSsr',
  setup(_, {
    slots
  }) {
    const show = useHydration();
    return () => show.value && slots.default?.();
  }
});

const NUMERAL_ZEROS = [0x0660,
// Arabic-Indic
0x06F0,
// Extended Arabic-Indic — Persian, Dari
0x0966,
// Devanagari
0x09E6,
// Bengali
0x0A66,
// Gurmukhi
0x0AE6,
// Gujarati
0x0B66,
// Oriya
0x0BE6,
// Tamil
0x0C66,
// Telugu
0x0CE6,
// Kannada
0x0D66,
// Malayalam
0x0E50,
// Thai
0x0ED0,
// Lao
0x0F20,
// Tibetan
0x1040,
// Myanmar
0x17E0,
// Khmer
0x1810,
// Mongolian
0xFF10 // Fullwidth
];
function normalizeDigits(str) {
  return str.replace(/[^\x20-\x7F]/g, char => {
    const code = char.codePointAt(0);
    for (const zero of NUMERAL_ZEROS) {
      if (code >= zero && code <= zero + 9) {
        return String(code - zero);
      }
    }
    return char;
  });
}
function formatNumber(val, options) {
  const {
    precision,
    minFractionDigits
  } = options;
  const formatter = new Intl.NumberFormat(options.locale, {
    minimumFractionDigits: minFractionDigits && precision != null ? Math.min(minFractionDigits, precision) : minFractionDigits ?? precision ?? undefined,
    maximumFractionDigits: precision ?? 20,
    // Intl defaults are dynamic (0, 2, 3)
    useGrouping: options.useGrouping
  });
  return formatter.formatToParts(val).map(p => {
    if (p.type === 'group') return options.groupSeparator;
    if (p.type === 'decimal') return options.decimalSeparator;
    return normalizeDigits(p.value);
  }).join('');
}

// Utilities
const HOLD_REPEAT = 50;
const HOLD_DELAY = 500;
function useHold({
  toggleUpDown
}) {
  let timeout = -1;
  let interval = -1;
  onScopeDispose(holdStop);
  function holdStart(value) {
    holdStop();
    tick(value);
    window.addEventListener('pointerup', holdStop);
    document.addEventListener('blur', holdStop);
    timeout = window.setTimeout(() => {
      interval = window.setInterval(() => tick(value), HOLD_REPEAT);
    }, HOLD_DELAY);
  }
  function holdStop() {
    if (!IN_BROWSER) return;
    window.clearTimeout(timeout);
    window.clearInterval(interval);
    window.removeEventListener('pointerup', holdStop);
    document.removeEventListener('blur', holdStop);
  }
  onScopeDispose(holdStop);
  function tick(value) {
    toggleUpDown(value === 'up');
  }
  return {
    holdStart,
    holdStop
  };
}

/* eslint-disable complexity */

function localizeMinusSign(text, minusSign) {
  return minusSign === '-' ? text : text.replace('-', minusSign);
}
function stripGrouping(text, groupSeparator) {
  return text.replaceAll(groupSeparator, '');
}

/** Fallback: fixed 3-digit groups */
function formatWithoutLocale(digits, groupSeparator, grouping) {
  if (grouping === 'min2' && digits.length <= 4) {
    return digits;
  }
  const groups = [];
  for (let i = digits.length; i > 0; i -= 3) {
    groups.unshift(digits.slice(Math.max(0, i - 3), i));
  }
  return groups.join(groupSeparator);
}
function addGrouping(raw, groupSeparator, decimalSeparator, grouping, locale) {
  if (!grouping) return raw;
  const decimalIndex = raw.indexOf(decimalSeparator);
  const integerPart = decimalIndex >= 0 ? raw.slice(0, decimalIndex) : raw;
  const rest = decimalIndex >= 0 ? raw.slice(decimalIndex) : '';
  const sign = integerPart.startsWith('-') ? '-' : '';
  const digits = sign ? integerPart.slice(1) : integerPart;
  if (!digits) return raw;
  if (locale) {
    const num = Number(digits);
    if (!Number.isFinite(num)) return raw;
    const grouped = new Intl.NumberFormat(locale, {
      useGrouping: grouping,
      numberingSystem: 'latn'
    }).formatToParts(num).map(p => p.type === 'group' ? groupSeparator : p.value).join('');
    return sign + grouped + rest;
  }
  return sign + formatWithoutLocale(digits, groupSeparator, grouping) + rest;
}

/** Count non-separator characters before displayPosition */
function toLogicalPosition(text, groupSeparator, displayPosition) {
  let logical = 0;
  for (let i = 0; i < displayPosition && i < text.length; i++) {
    if (text[i] !== groupSeparator) logical++;
  }
  return logical;
}
function toDisplayPosition(text, groupSeparator, logicalPosition) {
  let logical = 0;
  for (let i = 0; i <= text.length; i++) {
    if (logical === logicalPosition) return i;
    if (i < text.length && text[i] !== groupSeparator) logical++;
  }
  return text.length;
}

/**
 * Process a beforeinput event for plain (non-grouped) number input.
 * Returns { text, cursor } when the input needs correction, or null to let browser handle it.
 */
function processPlainInput(data, value, selectionStart, selectionEnd, options) {
  if (!data) return null;
  const {
    decimalSeparator,
    precision,
    minusSign
  } = options;
  value = normalizeMinusSign(value);
  const beforePart = value.slice(0, selectionStart);
  let cleanData = extractNumber(data, precision, decimalSeparator);
  if (cleanData.startsWith('-') && beforePart.length > 0) cleanData = cleanData.slice(1);
  if (cleanData.includes(decimalSeparator) && beforePart.includes(decimalSeparator)) {
    cleanData = cleanData.replace(decimalSeparator, '');
  }
  const candidate = beforePart + cleanData + value.slice(selectionEnd);
  const validPattern = new RegExp(`^-?\\d*${escapeForRegex(decimalSeparator)}?\\d*$`);
  if (!validPattern.test(candidate)) {
    return {
      text: localizeMinusSign(extractNumber(candidate, precision, decimalSeparator), minusSign),
      cursor: selectionStart
    };
  }
  if (precision != null && (candidate.split(decimalSeparator)[1]?.length ?? 0) > precision) {
    const text = extractNumber(candidate, precision, decimalSeparator);
    return {
      text: localizeMinusSign(text, minusSign),
      cursor: text === beforePart + value.slice(selectionEnd) ? selectionStart : selectionStart + cleanData.length
    };
  }
  if (cleanData === data) return null;
  return {
    text: localizeMinusSign(candidate, minusSign),
    cursor: selectionStart + cleanData.length
  };
}

/**
 * Process a beforeinput event for grouped number input.
 * Returns { text, cursor } to apply, or null for interactions that do not need override
 */
function processGroupedInput(inputType, data, value, selectionStart, selectionEnd, options) {
  const {
    groupSeparator,
    decimalSeparator,
    precision,
    grouping,
    locale,
    minusSign
  } = options;
  value = normalizeMinusSign(value);
  data = data && normalizeMinusSign(data);
  const raw = stripGrouping(value, groupSeparator);
  const logicalStart = toLogicalPosition(value, groupSeparator, selectionStart);
  const logicalEnd = toLogicalPosition(value, groupSeparator, selectionEnd);
  const hasSelection = logicalStart !== logicalEnd;
  let newRaw;
  let newLogicalCursor;
  switch (inputType) {
    case 'insertText':
      {
        if (!data) return null;
        newRaw = raw.slice(0, logicalStart) + data + raw.slice(logicalEnd);
        newLogicalCursor = logicalStart + data.length;
        break;
      }
    case 'insertFromPaste':
    case 'insertFromDrop':
      {
        if (!data) return null;
        const rawBefore = raw.slice(0, logicalStart);
        let cleanData = extractNumber(data, precision, decimalSeparator);
        if (cleanData.startsWith('-') && rawBefore.length > 0) {
          cleanData = cleanData.slice(1);
        }
        if (cleanData.includes(decimalSeparator) && rawBefore.includes(decimalSeparator)) {
          cleanData = cleanData.replace(decimalSeparator, '');
        }
        newRaw = rawBefore + cleanData + raw.slice(logicalEnd);
        newLogicalCursor = logicalStart + cleanData.length;
        break;
      }
    case 'deleteContentBackward':
      {
        if (hasSelection) {
          newRaw = raw.slice(0, logicalStart) + raw.slice(logicalEnd);
          newLogicalCursor = logicalStart;
        } else if (logicalStart > 0) {
          newRaw = raw.slice(0, logicalStart - 1) + raw.slice(logicalStart);
          newLogicalCursor = logicalStart - 1;
        } else {
          // At the start, nothing to delete
          newRaw = raw;
          newLogicalCursor = 0;
        }
        break;
      }
    case 'deleteContentForward':
      {
        if (hasSelection) {
          newRaw = raw.slice(0, logicalStart) + raw.slice(logicalEnd);
          newLogicalCursor = logicalStart;
        } else if (logicalStart < raw.length) {
          newRaw = raw.slice(0, logicalStart) + raw.slice(logicalStart + 1);
          newLogicalCursor = logicalStart;
        } else {
          // At the end, nothing to delete
          newRaw = raw;
          newLogicalCursor = logicalStart;
        }
        break;
      }
    case 'deleteByCut':
      {
        newRaw = raw.slice(0, logicalStart) + raw.slice(logicalEnd);
        newLogicalCursor = logicalStart;
        break;
      }
    case 'deleteWordBackward':
      {
        if (hasSelection) {
          newRaw = raw.slice(0, logicalStart) + raw.slice(logicalEnd);
          newLogicalCursor = logicalStart;
        } else {
          let deleteEnd = logicalStart;
          // Skip non-digits first (e.g., decimal separator)
          while (deleteEnd > 0 && !/\d/.test(raw[deleteEnd - 1])) deleteEnd--;
          // Then skip digits
          while (deleteEnd > 0 && /\d/.test(raw[deleteEnd - 1])) deleteEnd--;
          newRaw = raw.slice(0, deleteEnd) + raw.slice(logicalStart);
          newLogicalCursor = deleteEnd;
        }
        break;
      }
    case 'deleteWordForward':
      {
        if (hasSelection) {
          newRaw = raw.slice(0, logicalStart) + raw.slice(logicalEnd);
          newLogicalCursor = logicalStart;
        } else {
          let deleteEnd = logicalStart;
          while (deleteEnd < raw.length && !/\d/.test(raw[deleteEnd])) deleteEnd++;
          while (deleteEnd < raw.length && /\d/.test(raw[deleteEnd])) deleteEnd++;
          newRaw = raw.slice(0, logicalStart) + raw.slice(deleteEnd);
          newLogicalCursor = logicalStart;
        }
        break;
      }
    case 'deleteSoftLineBackward':
      {
        newRaw = raw.slice(logicalEnd);
        newLogicalCursor = 0;
        break;
      }
    case 'deleteSoftLineForward':
      {
        newRaw = raw.slice(0, logicalStart);
        newLogicalCursor = logicalStart;
        break;
      }
    default:
      return null;
  }
  const validPattern = new RegExp(`^-?\\d*${escapeForRegex(decimalSeparator)}?\\d*$`);
  if (!validPattern.test(newRaw)) {
    newRaw = extractNumber(newRaw, precision, decimalSeparator);
    newLogicalCursor = Math.min(newLogicalCursor, newRaw.length);
  }
  if (precision != null) {
    const parts = newRaw.split(decimalSeparator);
    if (parts[1]?.length > precision) {
      newRaw = parts[0] + decimalSeparator + parts[1].slice(0, precision);
      newLogicalCursor = Math.min(newLogicalCursor, newRaw.length);
    }
    if (precision === 0 && newRaw.endsWith(decimalSeparator)) {
      newRaw = newRaw.slice(0, -1);
      newLogicalCursor = Math.min(newLogicalCursor, newRaw.length);
    }
  }
  const formatted = addGrouping(newRaw, groupSeparator, decimalSeparator, grouping, locale);
  const cursor = toDisplayPosition(formatted, groupSeparator, newLogicalCursor);
  return {
    text: localizeMinusSign(formatted, minusSign),
    cursor
  };
}

// Types

const makeVNumberInputProps = propsFactory({
  controlVariant: {
    type: String,
    default: 'default'
  },
  inset: Boolean,
  hideInput: Boolean,
  modelValue: {
    type: Number,
    default: null
  },
  min: {
    type: Number,
    default: Number.MIN_SAFE_INTEGER
  },
  max: {
    type: Number,
    default: Number.MAX_SAFE_INTEGER
  },
  step: {
    type: Number,
    default: 1
  },
  precision: {
    type: Number,
    default: 0
  },
  minFractionDigits: {
    type: Number,
    default: null
  },
  decimalSeparator: {
    type: String,
    validator: v => !v || v.length === 1
  },
  grouping: {
    type: [Boolean, String],
    default: false
  },
  groupSeparator: {
    type: String,
    validator: v => !v || v.length === 1 && !/[0-9+-]/.test(v)
  },
  ...omit(makeVTextFieldProps(), ['modelValue', 'validationValue'])
}, 'VNumberInput');
const VNumberInput = genericComponent()({
  name: 'VNumberInput',
  props: {
    ...makeVNumberInputProps()
  },
  emits: {
    'update:focused': val => true,
    'update:modelValue': val => true
  },
  setup(props, {
    slots
  }) {
    const vTextFieldRef = ref();
    const {
      holdStart,
      holdStop
    } = useHold({
      toggleUpDown
    });
    const form = useForm(props);
    const controlsDisabled = computed(() => form.isDisabled.value || form.isReadonly.value);
    const isFocused = shallowRef(props.focused);
    const {
      current: locale,
      decimalSeparator: decimalSeparatorFromLocale,
      numericGroupSeparator: numericGroupSeparatorFromLocale
    } = useLocale();
    const decimalSeparator = computed(() => props.decimalSeparator?.[0] || decimalSeparatorFromLocale.value);
    const groupSeparator = computed(() => {
      const separator = props.groupSeparator?.[0] || numericGroupSeparatorFromLocale.value;
      if (separator !== decimalSeparator.value) return separator;
      if (props.grouping) {
        consoleWarn(`decimalSeparator and groupSeparator are both "${separator}", groups will not be separated`);
      }
      return '';
    });
    const minusSign = computed(() => new Intl.NumberFormat(locale.value).formatToParts(-1).find(p => p.type === 'minusSign')?.value ?? '-');
    function toNumber(val) {
      return Number(normalizeMinusSign(val ?? '').replaceAll(groupSeparator.value, '').replace(decimalSeparator.value, '.').replace(/[^0-9.-]/g, ''));
    }
    function correctPrecision(val, precision, trim = true) {
      precision ??= isFocused.value && trim ? undefined : props.precision ?? undefined;
      return formatNumber(val, {
        locale: locale.value,
        precision,
        minFractionDigits: props.minFractionDigits,
        useGrouping: props.grouping,
        decimalSeparator: decimalSeparator.value,
        groupSeparator: groupSeparator.value
      });
    }
    const model = useProxiedModel(props, 'modelValue', null, val => val ?? null, val => val == null ? val ?? null : clamp(Number(val), props.min, props.max));
    const _inputText = shallowRef(null);
    const _lastParsedValue = shallowRef(null);
    watch(model, val => {
      if (isFocused.value && !controlsDisabled.value && toNumber(_inputText.value) === val) ; else if (val == null) {
        _inputText.value = null;
        _lastParsedValue.value = null;
      } else if (!isNaN(val)) {
        _inputText.value = correctPrecision(val);
        _lastParsedValue.value = toNumber(_inputText.value);
      }
    }, {
      immediate: true
    });
    const inputText = computed({
      get: () => _inputText.value,
      set(val) {
        if (val === null || val === '') {
          model.value = null;
          _inputText.value = null;
          _lastParsedValue.value = null;
          return;
        }
        const parsedValue = toNumber(val);
        if (!isNaN(parsedValue)) {
          _inputText.value = val;
          _lastParsedValue.value = parsedValue;
          if (parsedValue <= props.max && parsedValue >= props.min) {
            model.value = parsedValue;
          }
        }
      }
    });
    const isOutOfRange = computed(() => {
      if (_lastParsedValue.value === null) return false;
      const numberFromText = toNumber(_inputText.value);
      return numberFromText !== clamp(numberFromText, props.min, props.max);
    });
    function stepResult(increment) {
      const current = toNumber(inputText.value);
      const stepped = current + (increment ? props.step : -props.step);
      return {
        current,
        stepped,
        next: clamp(stepped, props.min, props.max)
      };
    }
    const canIncrease = computed(() => {
      if (controlsDisabled.value) return false;
      if (model.value == null) return true;
      const {
        current,
        next
      } = stepResult(true);
      return next !== current;
    });
    const canDecrease = computed(() => {
      if (controlsDisabled.value) return false;
      if (model.value == null) return true;
      const {
        current,
        next
      } = stepResult(false);
      return next !== current;
    });
    const controlVariant = computed(() => {
      return props.hideInput ? 'stacked' : props.controlVariant;
    });
    const incrementIcon = toRef(() => controlVariant.value === 'split' ? '$plus' : '$collapse');
    const decrementIcon = toRef(() => controlVariant.value === 'split' ? '$minus' : '$expand');
    const controlNodeSize = toRef(() => controlVariant.value === 'split' ? 'default' : 'small');
    const controlNodeDefaultHeight = toRef(() => controlVariant.value === 'stacked' ? 'auto' : '100%');
    const incrementSlotProps = {
      props: {
        onClick: onControlClick,
        onPointerup: onControlMouseup,
        onPointerdown: onUpControlMousedown,
        onPointercancel: onControlMouseup
      }
    };
    const decrementSlotProps = {
      props: {
        onClick: onControlClick,
        onPointerup: onControlMouseup,
        onPointerdown: onDownControlMousedown,
        onPointercancel: onControlMouseup
      }
    };
    watch(() => [locale.value, decimalSeparator.value, groupSeparator.value, props.precision, props.minFractionDigits], () => formatInputValue());
    function inferPrecision(value) {
      if (value == null) return 0;
      const str = value.toString();
      const idx = str.indexOf('.') + 1;
      return idx ? str.length - idx : 0;
    }
    function emitChange() {
      vTextFieldRef.value?.controlRef?.dispatchEvent(new Event('change', {
        bubbles: true
      }));
    }
    function toggleUpDown(increment = true) {
      if (controlsDisabled.value) return;
      if (increment ? !canIncrease.value : !canDecrease.value) return;
      if (model.value == null) {
        inputText.value = correctPrecision(clamp(0, props.min, props.max));
        emitChange();
        return;
      }
      const {
        current,
        stepped,
        next
      } = stepResult(increment);
      inputText.value = next === stepped ? correctPrecision(next, Math.max(inferPrecision(current), inferPrecision(props.step))) : correctPrecision(next);
      emitChange();
    }
    function onBeforeinput(e) {
      if (controlsDisabled.value) return;
      const inputElement = e.target;
      const result = props.grouping ? processGroupedInput(e.inputType, e.data, inputElement.value ?? '', inputElement.selectionStart ?? 0, inputElement.selectionEnd ?? 0, {
        groupSeparator: groupSeparator.value,
        decimalSeparator: decimalSeparator.value,
        precision: props.precision,
        grouping: props.grouping,
        locale: locale.value,
        minusSign: minusSign.value
      }) : processPlainInput(e.data, inputElement.value ?? '', inputElement.selectionStart ?? 0, inputElement.selectionEnd ?? 0, {
        decimalSeparator: decimalSeparator.value,
        precision: props.precision,
        minusSign: minusSign.value
      });
      if (result === null) return;
      e.preventDefault();
      inputElement.value = result.text;
      inputElement.setSelectionRange(result.cursor, result.cursor);
      nextTick(() => inputText.value = result.text);
    }
    function onKeydown(e) {
      if (['Enter', 'ArrowLeft', 'ArrowRight', 'Backspace', 'Delete', 'Tab'].includes(e.key) || e.ctrlKey) return;
      if (['ArrowDown', 'ArrowUp'].includes(e.key)) {
        e.preventDefault();
        e.stopPropagation();
        toggleUpDown(e.key === 'ArrowUp');
      }
    }
    function onControlClick(e) {
      e.stopPropagation();
    }
    function onControlMouseup(e) {
      const el = e.currentTarget;
      el?.releasePointerCapture(e.pointerId);
      e.preventDefault();
      holdStop();
    }
    function onUpControlMousedown(e) {
      const el = e.currentTarget;
      el?.setPointerCapture(e.pointerId);
      e.preventDefault();
      e.stopPropagation();
      holdStart('up');
    }
    function onDownControlMousedown(e) {
      const el = e.currentTarget;
      el?.setPointerCapture(e.pointerId);
      e.preventDefault();
      e.stopPropagation();
      holdStart('down');
    }
    function clampModel() {
      if (controlsDisabled.value) return;
      if (!vTextFieldRef.value) return;
      const actualText = vTextFieldRef.value.value;
      const parsedValue = toNumber(actualText);
      if (actualText && !isNaN(parsedValue)) {
        inputText.value = correctPrecision(clamp(parsedValue, props.min, props.max));
      } else {
        inputText.value = null;
      }
    }
    function formatInputValue() {
      if (controlsDisabled.value) return;
      inputText.value = model.value !== null && !isNaN(model.value) ? correctPrecision(model.value, props.precision, false) : null;
    }
    function trimDecimalZeros() {
      if (controlsDisabled.value) return;
      if (model.value === null || isNaN(model.value)) {
        inputText.value = null;
        return;
      }
      inputText.value = correctPrecision(model.value);
    }
    function onFocus() {
      trimDecimalZeros();
    }
    function onBlur() {
      clampModel();
    }
    useRender(() => {
      const {
        modelValue: _,
        type,
        ...textFieldProps
      } = VTextField.filterProps(props);
      function incrementControlNode() {
        return !slots.increment ? createVNode(VBtn, {
          "aria-hidden": "true",
          "data-testid": "increment",
          "disabled": !canIncrease.value,
          "height": controlNodeDefaultHeight.value,
          "icon": incrementIcon.value,
          "key": "increment-btn",
          "onClick": onControlClick,
          "onPointerdown": onUpControlMousedown,
          "onPointerup": onControlMouseup,
          "onPointercancel": onControlMouseup,
          "size": controlNodeSize.value,
          "variant": "text",
          "tabindex": "-1"
        }, null) : createVNode(VDefaultsProvider, {
          "key": "increment-defaults",
          "defaults": {
            VBtn: {
              disabled: !canIncrease.value,
              height: controlNodeDefaultHeight.value,
              size: controlNodeSize.value,
              icon: incrementIcon.value,
              variant: 'text'
            }
          }
        }, {
          default: () => [slots.increment(incrementSlotProps)]
        });
      }
      function decrementControlNode() {
        return !slots.decrement ? createVNode(VBtn, {
          "aria-hidden": "true",
          "data-testid": "decrement",
          "disabled": !canDecrease.value,
          "height": controlNodeDefaultHeight.value,
          "icon": decrementIcon.value,
          "key": "decrement-btn",
          "onClick": onControlClick,
          "onPointerdown": onDownControlMousedown,
          "onPointerup": onControlMouseup,
          "onPointercancel": onControlMouseup,
          "size": controlNodeSize.value,
          "variant": "text",
          "tabindex": "-1"
        }, null) : createVNode(VDefaultsProvider, {
          "key": "decrement-defaults",
          "defaults": {
            VBtn: {
              disabled: !canDecrease.value,
              height: controlNodeDefaultHeight.value,
              size: controlNodeSize.value,
              icon: decrementIcon.value,
              variant: 'text'
            }
          }
        }, {
          default: () => [slots.decrement(decrementSlotProps)]
        });
      }
      function controlNode() {
        return createElementVNode("div", {
          "class": "v-number-input__control"
        }, [decrementControlNode(), createVNode(VDivider, {
          "vertical": controlVariant.value !== 'stacked'
        }, null), incrementControlNode()]);
      }
      function dividerNode() {
        return !props.hideInput && !props.inset ? createVNode(VDivider, {
          "vertical": true
        }, null) : undefined;
      }
      const appendInnerControl = controlVariant.value === 'split' ? createElementVNode("div", {
        "class": "v-number-input__control"
      }, [createVNode(VDivider, {
        "vertical": true
      }, null), incrementControlNode()]) : props.reverse || controlVariant.value === 'hidden' ? undefined : createElementVNode(Fragment, null, [dividerNode(), controlNode()]);
      const hasAppendInner = slots['append-inner'] || appendInnerControl;
      const prependInnerControl = controlVariant.value === 'split' ? createElementVNode("div", {
        "class": "v-number-input__control"
      }, [decrementControlNode(), createVNode(VDivider, {
        "vertical": true
      }, null)]) : props.reverse && controlVariant.value !== 'hidden' ? createElementVNode(Fragment, null, [controlNode(), dividerNode()]) : undefined;
      const hasPrependInner = slots['prepend-inner'] || prependInnerControl;
      return createVNode(VTextField, mergeProps({
        "ref": vTextFieldRef
      }, textFieldProps, {
        "modelValue": inputText.value,
        "onUpdate:modelValue": $event => inputText.value = $event,
        "focused": isFocused.value,
        "onUpdate:focused": $event => isFocused.value = $event,
        "validationValue": model.value,
        "error": props.error || isOutOfRange.value || undefined,
        "onBeforeinput": onBeforeinput,
        "onFocus": onFocus,
        "onBlur": onBlur,
        "onKeydown": onKeydown,
        "class": ['v-number-input', {
          'v-number-input--default': controlVariant.value === 'default',
          'v-number-input--hide-input': props.hideInput,
          'v-number-input--inset': props.inset,
          'v-number-input--reverse': props.reverse,
          'v-number-input--split': controlVariant.value === 'split',
          'v-number-input--stacked': controlVariant.value === 'stacked'
        }, props.class],
        "style": props.style,
        "inputmode": "decimal"
      }), {
        ...slots,
        'append-inner': hasAppendInner ? (...args) => createElementVNode(Fragment, null, [slots['append-inner']?.(...args), appendInnerControl]) : undefined,
        'prepend-inner': hasPrependInner ? (...args) => createElementVNode(Fragment, null, [prependInnerControl, slots['prepend-inner']?.(...args)]) : undefined
      });
    });
    return forwardRefs({}, vTextFieldRef);
  }
});

// Types

const VOtpInputSymbol = Symbol.for('vuetify:v-otp-input');

const makeVOtpFieldProps = propsFactory({
  index: {
    type: Number,
    required: true
  }
}, 'VOtpField');
const VOtpField = genericComponent()({
  name: 'VOtpField',
  props: makeVOtpFieldProps(),
  setup(props) {
    const otpInput = inject$1(VOtpInputSymbol);
    if (!otpInput) {
      throw new Error('[Vuetify] VOtpField must be used inside VOtpInput');
    }
    const slot = computed(() => otpInput.otpSlots.value[props.index]);
    const isHighlighted = computed(() => otpInput.isFocused.value && otpInput.focusAll.value && !slot.value?.isActive);
    useRender(() => {
      if (!slot.value) return createCommentVNode();
      return createVNode(VField, {
        "data-otp-index": props.index,
        "focused": slot.value.isActive || isHighlighted.value,
        "class": normalizeClass({
          'v-otp-input__field--highlighted': isHighlighted.value
        }),
        "onMousedown": e => e.preventDefault(),
        "onClick": () => otpInput.focusAt(props.index)
      }, {
        loader: undefined,
        default: () => createElementVNode("div", {
          "class": "v-otp-input__field"
        }, [createElementVNode("input", {
          "class": "v-otp-input__spacer",
          "aria-hidden": "true",
          "tabindex": "-1"
        }, null), slot.value.compositionChar ? createElementVNode("span", {
          "class": "v-otp-input__composition"
        }, [slot.value.compositionChar]) : slot.value.hasFakeCaret ? createElementVNode("span", {
          "class": "v-otp-input__caret"
        }, null) : createElementVNode("span", {
          "class": normalizeClass(!slot.value.char ? 'v-otp-input__placeholder' : undefined)
        }, [slot.value.char ?? slot.value.placeholderChar ?? ''])])
      });
    });
  }
});

// Utilities

// Types

function countSlotChildren(vnodes) {
  let count = 0;
  for (const vnode of vnodes) {
    if (vnode.type === Fragment && Array.isArray(vnode.children)) {
      count += countSlotChildren(vnode.children);
    } else {
      count++;
    }
  }
  return count;
}
const makeVOtpGroupProps = propsFactory({
  merged: {
    type: Boolean,
    default: null
  }
}, 'VOtpGroup');
const VOtpGroup = genericComponent()({
  name: 'VOtpGroup',
  props: makeVOtpGroupProps(),
  setup(props, {
    slots
  }) {
    const otpInput = inject$1(VOtpInputSymbol);
    const isMerged = computed(() => props.merged ?? otpInput?.merged.value ?? false);
    useRender(() => {
      const children = slots.default?.() ?? [];
      return createElementVNode("div", {
        "class": normalizeClass(['v-otp-group', {
          'v-otp-group--merged': isMerged.value
        }]),
        "style": normalizeStyle(isMerged.value ? {
          flex: countSlotChildren(children)
        } : undefined)
      }, [children]);
    });
  }
});

// Utilities
const VOtpSeparator = createSimpleFunctional('v-otp-input__divider');

// to be replaced by v0 implementation in v5.0


// Types

const OtpInputPatterns = {
  numeric: /[0-9]/,
  alpha: /[a-zA-Z]/,
  alphanumeric: /[a-zA-Z0-9]/,
  'unicode-alpha': /\p{L}/u,
  'unicode-alphanumeric': /[\p{L}\p{N}]/u
};
const IME_SCRIPT_RE = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Bopomofo}]/u;
const graphemeSegmenter = /* @__PURE__ */new Intl.Segmenter(undefined, {
  granularity: 'grapheme'
});
function useOtpInput(options) {
  const {
    value,
    length: _length = 6,
    pattern,
    type = 'number',
    masked = false,
    placeholder,
    isFocused = shallowRef(false)
  } = options;
  const selection = shallowRef(null);
  const composition = shallowRef('');
  const isComposing = shallowRef(false);
  let prevSelection = null;
  // Shift+Arrow anchor/focus tracked in grapheme space.
  let anchorG = null;
  let focusG = null;
  const length = toRef(() => Number(toValue(_length)));
  const isMasked = toRef(() => toValue(masked) || toValue(type) === 'password');
  const effectivePattern = toRef(() => {
    const p = toValue(pattern);
    if (p instanceof RegExp) return p;
    if (p != null) return OtpInputPatterns[p] ?? null;
    if (toValue(type) === 'number') return OtpInputPatterns.numeric;
    return null;
  });
  const inputMode = toRef(() => effectivePattern.value === OtpInputPatterns.numeric ? 'numeric' : 'text');

  // Selection is stored in code units (for `setSelectionRange`), but every slot
  // boundary works in grapheme space so emoji, ZWJ sequences and skin-tone
  // modifiers each occupy one slot.
  function graphemes(s) {
    return Array.from(graphemeSegmenter.segment(s), seg => seg.segment);
  }
  function codeUnitsToGraphemeIndex(s, pos) {
    let count = 0;
    for (const seg of graphemeSegmenter.segment(s)) {
      if (seg.index >= pos) break;
      count++;
    }
    return count;
  }
  function graphemeIndexToCodeUnits(s, gIndex) {
    if (gIndex <= 0) return 0;
    let count = 0;
    for (const seg of graphemeSegmenter.segment(s)) {
      if (count === gIndex) return seg.index;
      count++;
    }
    return s.length;
  }
  const slots = computed(() => {
    const chars = graphemes(value.value);
    const compositionChars = graphemes(composition.value);
    const placeholderChar = toValue(placeholder) ?? null;
    const currentSelection = selection.value;
    const startG = currentSelection ? codeUnitsToGraphemeIndex(value.value, currentSelection.start) : null;
    const endG = currentSelection ? codeUnitsToGraphemeIndex(value.value, currentSelection.end) : null;
    const compositionStart = startG ?? chars.length;
    return Array.from({
      length: length.value
    }, (_, i) => {
      const char = chars[i] ?? null;
      const displayChar = char !== null && isMasked.value ? '•' : char;
      let compositionChar = null;
      if (composition.value && i >= compositionStart) {
        const offset = i - compositionStart;
        const c = compositionChars[offset];
        if (c != null) compositionChar = isMasked.value ? '•' : c;
      }
      const isActive = isFocused.value && startG !== null && endG !== null && (startG === endG && i === startG || i >= startG && i < endG);
      return {
        char: displayChar,
        compositionChar,
        placeholderChar,
        isActive,
        hasFakeCaret: isActive && char === null && compositionChar === null
      };
    });
  });
  function filter(text) {
    const re = effectivePattern.value;
    if (!re) return text;
    return graphemes(text).filter(c => re.test(c)).join('');
  }
  function clampGraphemes(text, max) {
    const chars = graphemes(text);
    if (chars.length <= max) return text;
    return chars.slice(0, max).join('');
  }
  function isImeText(text) {
    return IME_SCRIPT_RE.test(text);
  }
  function setValue(text) {
    const next = clampGraphemes(filter(text), length.value);
    value.value = next;
    return next;
  }
  function insert(text, range) {
    const current = value.value;
    const start = range?.start ?? current.length;
    const end = range?.end ?? current.length;
    const filtered = filter(text);
    const next = clampGraphemes(current.slice(0, start) + filtered + current.slice(end), length.value);
    value.value = next;
    const insertEnd = Math.min(start + filtered.length, next.length);
    const insertEndG = codeUnitsToGraphemeIndex(next, insertEnd);
    const cursorG = Math.min(insertEndG, length.value - 1);
    const cursor = graphemeIndexToCodeUnits(next, cursorG);
    setSelection(cursor, insertEnd, 'forward');
    return next;
  }
  function deleteRange(start, end) {
    const current = value.value;
    const next = current.slice(0, start) + current.slice(end);
    value.value = next;
    const newEnd = Math.min(start + 1, next.length);
    setSelection(start, newEnd, 'forward');
    return next;
  }
  function bulkDelete(isBackward) {
    const current = value.value;
    const currentSelection = selection.value;
    const next = isBackward ? current.slice(currentSelection?.end ?? current.length) : current.slice(0, currentSelection?.start ?? 0);
    value.value = next;
    if (next.length === 0) setSelection(0, 0, 'none');else if (isBackward) setSelection(0, 1, 'forward');else setSelection(next.length, next.length, 'none');
    return next;
  }
  function setSelection(start, end, direction = 'none') {
    if (start === null || end === null) {
      selection.value = null;
      anchorG = null;
      focusG = null;
      return;
    }
    const next = {
      start,
      end,
      direction
    };
    selection.value = next;
    prevSelection = next;
    const startG = codeUnitsToGraphemeIndex(value.value, start);
    anchorG = startG;
    focusG = startG;
  }
  function clearSelection() {
    selection.value = null;
    anchorG = null;
    focusG = null;
  }
  function selectAtEnd() {
    const current = value.value;
    const graphemeCount = graphemes(current).length;
    let start;
    let end;
    if (graphemeCount >= length.value) {
      // Full: range over the last slot so it renders as active.
      start = graphemeIndexToCodeUnits(current, length.value - 1);
      end = current.length;
    } else {
      // Partial: single caret at the end of the typed content.
      start = current.length;
      end = current.length;
    }
    const next = {
      start,
      end,
      direction: 'forward'
    };
    selection.value = next;
    prevSelection = next;
    anchorG = graphemeCount >= length.value ? length.value - 1 : graphemeCount;
    focusG = anchorG;
    return next;
  }
  function selectSlot(index) {
    const current = value.value;
    const graphemeCount = graphemes(current).length;
    const clamped = Math.min(index, graphemeCount);
    const start = graphemeIndexToCodeUnits(current, clamped);
    const end = clamped < graphemeCount ? graphemeIndexToCodeUnits(current, clamped + 1) : current.length;
    const next = {
      start,
      end,
      direction: 'forward'
    };
    selection.value = next;
    prevSelection = next;
    anchorG = clamped;
    focusG = clamped;
    return next;
  }
  function moveCaret(direction) {
    const current = value.value;
    if (graphemes(current).length === 0) return null;
    const currentSelection = selection.value;
    const currentG = currentSelection ? codeUnitsToGraphemeIndex(current, currentSelection.start) : 0;
    return selectSlot(Math.max(0, currentG + direction));
  }
  function extendSelection(direction) {
    const current = value.value;
    const valueG = graphemes(current).length;
    if (valueG === 0) return null;
    const maxFocus = Math.min(length.value - 1, valueG);

    // Fallback when Shift+Arrow fires before anchor/focus were tracked.
    if (anchorG === null || focusG === null) {
      const currentSelection = selection.value;
      if (!currentSelection) return null;
      const selectionStartG = codeUnitsToGraphemeIndex(current, currentSelection.start);
      const selectionEndG = codeUnitsToGraphemeIndex(current, currentSelection.end);
      if (selectionEndG - selectionStartG <= 1) {
        anchorG = selectionStartG;
        focusG = selectionStartG;
      } else if (currentSelection.direction === 'backward') {
        anchorG = selectionEndG - 1;
        focusG = selectionStartG;
      } else {
        anchorG = selectionStartG;
        focusG = selectionEndG - 1;
      }
    }
    const newFocus = Math.max(0, Math.min(maxFocus, focusG + direction));
    focusG = newFocus;
    const minG = Math.min(anchorG, newFocus);
    const maxG = Math.max(anchorG, newFocus);
    const start = graphemeIndexToCodeUnits(current, minG);
    const end = maxG + 1 >= valueG ? current.length : graphemeIndexToCodeUnits(current, maxG + 1);
    const newDirection = newFocus < anchorG ? 'backward' : 'forward';
    const next = {
      start,
      end,
      direction: newDirection
    };
    selection.value = next;
    prevSelection = next;
    return next;
  }

  // Force the rendered selection to always cover at least one slot, so a slot
  // stays "active" when a caret would otherwise be between two.
  function syncSelection(raw) {
    if (isComposing.value) return selection.value;
    const {
      value: inputValue,
      selectionStart,
      selectionEnd,
      selectionDirection,
      maxLength
    } = raw;
    if (selectionStart === null || selectionEnd === null) {
      selection.value = null;
      prevSelection = null;
      return null;
    }
    const valueG = graphemes(inputValue).length;
    const startG = codeUnitsToGraphemeIndex(inputValue, selectionStart);
    const endG = codeUnitsToGraphemeIndex(inputValue, selectionEnd);
    let outStartG = -1;
    let outEndG = -1;
    let direction;
    if (valueG !== 0) {
      const isSingleCaret = startG === endG;
      const isInsertMode = startG === valueG && valueG < maxLength;
      if (isSingleCaret && !isInsertMode) {
        if (startG === 0) {
          outStartG = 0;
          outEndG = 1;
          direction = 'forward';
        } else if (startG === maxLength) {
          outStartG = startG - 1;
          outEndG = startG;
          direction = 'backward';
        } else if (maxLength > 1 && valueG > 1) {
          let offset = 0;
          if (prevSelection !== null) {
            const prevStartG = codeUnitsToGraphemeIndex(inputValue, prevSelection.start);
            const prevEndG = codeUnitsToGraphemeIndex(inputValue, prevSelection.end);
            direction = startG < prevEndG ? 'backward' : 'forward';
            const wasPreviouslyInserting = prevStartG === prevEndG && prevStartG < maxLength;
            // Multi-slot collapse: caret landed at an edge of the prior range,
            // user didn't navigate between slots, so don't shift the slot back.
            const wasMultiSlot = prevEndG - prevStartG > 1;
            if (direction === 'backward' && !wasPreviouslyInserting && !wasMultiSlot) {
              offset = -1;
            }
          }
          outStartG = offset + startG;
          outEndG = offset + startG + 1;
        }
      }
    }
    const finalStartG = outStartG !== -1 ? outStartG : startG;
    const finalEndG = outEndG !== -1 ? outEndG : endG;
    const finalStart = graphemeIndexToCodeUnits(inputValue, finalStartG);
    const finalEnd = graphemeIndexToCodeUnits(inputValue, finalEndG);
    const finalDirection = direction ?? selectionDirection ?? 'none';
    const next = {
      start: finalStart,
      end: finalEnd,
      direction: finalDirection
    };
    selection.value = next;
    prevSelection = next;
    // Reset anchor on plain navigation; preserve it during extendSelection's round-trip.
    if (finalEndG - finalStartG <= 1) {
      anchorG = finalStartG;
      focusG = finalStartG;
    }
    return next;
  }
  function startComposition() {
    isComposing.value = true;
    composition.value = '';
  }
  function updateComposition(data) {
    composition.value = IME_SCRIPT_RE.test(data) ? data : '';
  }
  function endComposition() {
    isComposing.value = false;
    composition.value = '';
  }
  function reset() {
    value.value = '';
    selection.value = null;
    composition.value = '';
    isComposing.value = false;
    prevSelection = null;
    anchorG = null;
    focusG = null;
  }
  return {
    value,
    length,
    slots,
    selection,
    composition,
    isComposing,
    isFocused,
    effectivePattern,
    inputMode,
    filter,
    isImeText,
    setValue,
    insert,
    deleteRange,
    bulkDelete,
    syncSelection,
    setSelection,
    clearSelection,
    selectAtEnd,
    selectSlot,
    moveCaret,
    extendSelection,
    startComposition,
    updateComposition,
    endComposition,
    reset
  };
}

const makeVOtpInputProps = propsFactory({
  autofocus: Boolean,
  divider: String,
  focusAll: Boolean,
  merged: Boolean,
  label: {
    type: String,
    default: '$vuetify.input.otp'
  },
  length: {
    type: [Number, String],
    default: 6
  },
  masked: Boolean,
  modelValue: {
    type: [Number, String],
    default: undefined
  },
  pattern: {
    type: [String, Object],
    default: undefined
  },
  placeholder: String,
  type: {
    type: String,
    default: 'number'
  },
  ...makeDensityProps(),
  ...makeDimensionProps(),
  ...makeFocusProps(),
  ...pick(makeVFieldProps({
    variant: 'outlined'
  }), ['baseColor', 'bgColor', 'class', 'color', 'disabled', 'error', 'loading', 'rounded', 'style', 'theme', 'variant'])
}, 'VOtpInput');
const VOtpInput = genericComponent()({
  name: 'VOtpInput',
  props: makeVOtpInputProps(),
  emits: {
    finish: value => true,
    'update:focused': value => true,
    'update:modelValue': value => true
  },
  setup(props, {
    attrs,
    emit,
    slots
  }) {
    const {
      densityClasses
    } = useDensity(props);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      isFocused
    } = useFocus(props);
    const {
      t
    } = useLocale();
    const {
      isRtl
    } = useRtl();
    const model = useProxiedModel(props, 'modelValue', '', val => val == null ? '' : String(val));
    const inputRef = ref();
    const length = toRef(() => Number(props.length));
    let focusAtPending = false;
    const otp = useOtpInput({
      value: model,
      length,
      pattern: () => props.pattern,
      type: () => props.type,
      masked: () => props.masked,
      placeholder: () => props.placeholder,
      isFocused
    });
    function applySelection() {
      const input = inputRef.value;
      const selection = otp.selection.value;
      if (!input || !selection) return;
      input.setSelectionRange(selection.start, selection.end, selection.direction);
    }
    function syncDOM() {
      const input = inputRef.value;
      if (!input) return;
      if (input.value !== otp.value.value) input.value = otp.value.value;
      applySelection();
    }
    function onSelectionChange() {
      const input = inputRef.value;
      if (!input) {
        otp.clearSelection();
        return;
      }
      const result = otp.syncSelection({
        value: input.value,
        selectionStart: input.selectionStart,
        selectionEnd: input.selectionEnd,
        selectionDirection: input.selectionDirection,
        // Slot count, not `input.maxLength` (code units).
        maxLength: length.value
      });
      if (!result) return;
      if (input.selectionStart !== result.start || input.selectionEnd !== result.end) {
        input.setSelectionRange(result.start, result.end, result.direction);
      }
    }
    function onInput(e) {
      const ev = e;
      const target = e.target;
      const composing = ev.isComposing || otp.isComposing.value;

      // CJK composition renders via the overlay until compositionend.
      if (composing && otp.isImeText(target.value)) return;

      // Non-CJK composition (dead keys, Samsung predictive, Chrome OTP autofill)
      // commits into the model now; don't end composition early or selection
      // will advance past the model length on the next selectionchange.
      const next = otp.setValue(target.value);
      if (target.value !== next) target.value = next;
    }
    function onCompositionstart() {
      otp.startComposition();
    }
    function onCompositionupdate(e) {
      otp.updateComposition(e.data ?? '');
    }
    function onCompositionend(e) {
      otp.endComposition();
      onInput(e);
    }
    function onFocus() {
      isFocused.value = true;
      if (focusAtPending) return;
      if (!inputRef.value) return;
      otp.selectAtEnd();
      applySelection();
    }
    function onBlur() {
      isFocused.value = false;
      otp.clearSelection();
    }
    function onKeydown(e) {
      if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
        const direction = (e.key === 'ArrowLeft' ? -1 : 1) * (isRtl.value ? -1 : 1);
        const moved = e.shiftKey ? otp.extendSelection(direction) : otp.moveCaret(direction);
        if (moved) {
          e.preventDefault();
          syncDOM();
        }
        return;
      }
      if (e.key !== 'Backspace' && e.key !== 'Delete') return;
      if (!e.metaKey && !e.ctrlKey && !e.altKey) return;
      e.preventDefault();
      otp.bulkDelete(e.key === 'Backspace');
      syncDOM();
    }
    function onBeforeinput(e) {
      if (e.inputType === 'insertText' && e.data && otp.effectivePattern.value && !otp.effectivePattern.value.test(e.data)) {
        e.preventDefault();
        return;
      }
      if (e.inputType === 'deleteContentForward') {
        e.preventDefault();
        const input = inputRef.value;
        if (!input) return;
        const selection = otp.selection.value;
        const start = selection?.start ?? 0;
        const end = selection?.end ?? input.value.length;
        otp.deleteRange(start, end);
        syncDOM();
        return;
      }
      const isBackward = ['deleteWordBackward', 'deleteSoftLineBackward', 'deleteHardLineBackward'].includes(e.inputType);
      const isForward = ['deleteWordForward', 'deleteSoftLineForward', 'deleteHardLineForward'].includes(e.inputType);
      if (!isBackward && !isForward) return;
      e.preventDefault();
      otp.bulkDelete(isBackward);
      syncDOM();
    }
    function onPaste(e) {
      e.preventDefault();
      const input = inputRef.value;
      if (!input) return;
      const text = e.clipboardData?.getData('text/plain').trim() ?? '';
      const selection = otp.selection.value;
      otp.insert(text, {
        start: selection?.start ?? 0,
        end: selection?.end ?? input.value.length
      });
      syncDOM();
    }
    function focusAt(index) {
      const input = inputRef.value;
      if (!input) return;
      focusAtPending = true;
      input.focus();
      focusAtPending = false;
      otp.selectSlot(index);
      applySelection();
    }
    function slotIndexAtPoint(x, y) {
      const slot = document.elementsFromPoint(x, y).find(el => el.hasAttribute('data-otp-index'));
      const index = slot ? Number(slot.getAttribute('data-otp-index')) : NaN;
      return Number.isNaN(index) ? null : index;
    }
    function onClick(e) {
      const index = slotIndexAtPoint(e.clientX, e.clientY);
      if (index != null) focusAt(index);
    }

    // selectionchange is not in InputHTMLAttributes types
    watch(inputRef, (input, _, onCleanup) => {
      if (!input) return;
      input.addEventListener('selectionchange', onSelectionChange);
      onCleanup(() => input.removeEventListener('selectionchange', onSelectionChange));
    }, {
      immediate: true
    });
    useToggleScope(() => props.autofocus, () => {
      const intersectScope = effectScope();
      intersectScope.run(() => {
        const {
          intersectionRef,
          isIntersecting
        } = useIntersectionObserver();
        watchEffect(() => {
          intersectionRef.value = inputRef.value;
        });
        watch(isIntersecting, v => {
          if (!v) return;
          intersectionRef.value?.focus();
          intersectScope.stop();
        });
      });
    });
    watch(model, val => {
      if (otp.isComposing.value) return;
      if (val.length === length.value) emit('finish', val);
    });
    provideDefaults({
      VField: {
        color: toRef(() => props.color),
        bgColor: toRef(() => props.color),
        baseColor: toRef(() => props.baseColor),
        disabled: toRef(() => props.disabled),
        error: toRef(() => props.error),
        variant: toRef(() => props.variant),
        rounded: toRef(() => props.rounded)
      }
    }, {
      scoped: true
    });
    provide(VOtpInputSymbol, {
      otpSlots: otp.slots,
      isFocused,
      focusAll: toRef(() => props.focusAll),
      divider: toRef(() => props.divider),
      merged: toRef(() => props.merged),
      focusAt
    });
    useRender(() => {
      const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
      return createElementVNode("div", mergeProps({
        "class": ['v-otp-input', {
          'v-otp-input--divided': !!props.divider
        }, densityClasses.value, props.class],
        "style": [props.style]
      }, rootAttrs), [createElementVNode("div", {
        "class": "v-otp-input__content",
        "style": normalizeStyle([dimensionStyles.value])
      }, [slots.fields ? slots.fields() : props.merged ? createVNode(VOtpGroup, {
        "merged": true
      }, {
        default: () => [Array.from({
          length: length.value
        }, (_, i) => createVNode(VOtpField, {
          "index": i,
          "key": i
        }, null))]
      }) : Array.from({
        length: length.value
      }, (_, i) => createElementVNode(Fragment, null, [(props.divider || slots.divider) && i !== 0 && createVNode(VOtpSeparator, {
        "key": `d-${i}`
      }, {
        default: () => [slots.divider?.({
          index: i - 1
        }) ?? props.divider]
      }), createVNode(VOtpField, {
        "index": i,
        "key": i
      }, null)])), createElementVNode("input", mergeProps({
        "ref": inputRef,
        "class": "v-otp-input__input",
        "type": "text",
        "inputmode": otp.inputMode.value,
        "dir": isRtl.value ? 'rtl' : 'ltr',
        "autocomplete": "one-time-code",
        "autocorrect": "off",
        "autocapitalize": "off",
        "spellcheck": false,
        "disabled": props.disabled,
        "aria-label": t(props.label),
        "value": model.value
      }, inputAttrs, {
        "onClick": onClick,
        "onInput": onInput,
        "onKeydown": onKeydown,
        "onBeforeinput": onBeforeinput,
        "onFocus": onFocus,
        "onBlur": onBlur,
        "onPaste": onPaste,
        "onCompositionstart": onCompositionstart,
        "onCompositionupdate": onCompositionupdate,
        "onCompositionend": onCompositionend
      }), null), createVNode(VOverlay, {
        "contained": true,
        "contentClass": "v-otp-input__loader",
        "modelValue": !!props.loading,
        "persistent": true
      }, {
        default: () => [slots.loader?.() ?? createVNode(VProgressCircular, {
          "color": typeof props.loading === 'boolean' ? undefined : props.loading,
          "indeterminate": true,
          "size": "24",
          "width": "2"
        }, null)]
      }), slots.default?.()])]);
    });
    return {
      blur: () => {
        inputRef.value?.blur();
      },
      focus: () => {
        inputRef.value?.focus();
      },
      reset: otp.reset,
      isFocused
    };
  }
});

// Types

function floor(val) {
  return Math.floor(Math.abs(val)) * Math.sign(val);
}
const makeVParallaxProps = propsFactory({
  scale: {
    type: [Number, String],
    default: 0.5
  },
  ...makeComponentProps()
}, 'VParallax');
const VParallax = genericComponent()({
  name: 'VParallax',
  props: makeVParallaxProps(),
  setup(props, {
    slots
  }) {
    const {
      intersectionRef,
      isIntersecting
    } = useIntersectionObserver();
    const {
      resizeRef,
      contentRect
    } = useResizeObserver();
    const {
      height: displayHeight
    } = useDisplay();
    const root = ref();
    watchEffect(() => {
      intersectionRef.value = resizeRef.value = root.value?.$el;
    });
    let scrollParent;
    watch(isIntersecting, val => {
      if (val) {
        scrollParent = getScrollParent(intersectionRef.value);
        scrollParent = scrollParent === document.scrollingElement ? document : scrollParent;
        scrollParent.addEventListener('scroll', onScroll, {
          passive: true
        });
        onScroll();
      } else {
        scrollParent.removeEventListener('scroll', onScroll);
      }
    });
    onBeforeUnmount(() => {
      scrollParent?.removeEventListener('scroll', onScroll);
    });
    watch(displayHeight, onScroll);
    watch(() => contentRect.value?.height, onScroll);
    const scale = computed(() => {
      return 1 - clamp(Number(props.scale));
    });
    let frame = -1;
    function onScroll() {
      if (!isIntersecting.value || PREFERS_REDUCED_MOTION()) return;
      cancelAnimationFrame(frame);
      frame = requestAnimationFrame(() => {
        const el = (root.value?.$el).querySelector('.v-img__img');
        if (!el) return;
        const scrollHeight = scrollParent instanceof Document ? document.documentElement.clientHeight : scrollParent.clientHeight;
        const scrollPos = scrollParent instanceof Document ? window.scrollY : scrollParent.scrollTop;
        const top = intersectionRef.value.getBoundingClientRect().top + scrollPos;
        const height = contentRect.value.height;
        const center = top + (height - scrollHeight) / 2;
        const translate = floor((scrollPos - center) * scale.value);
        const sizeScale = Math.max(1, (scale.value * (scrollHeight - height) + height) / height);
        el.style.setProperty('transform', `translateY(${translate}px) scale(${sizeScale})`);
      });
    }
    useRender(() => createVNode(VImg, {
      "class": normalizeClass(['v-parallax', {
        'v-parallax--active': isIntersecting.value
      }, props.class]),
      "style": normalizeStyle(props.style),
      "ref": root,
      "cover": true,
      "onLoadstart": onScroll,
      "onLoad": onScroll
    }, slots));
    return {};
  }
});

const VPullToRefresh = genericComponent()({
  name: 'VPullToRefresh',
  props: {
    disabled: Boolean,
    pullDownThreshold: {
      type: Number,
      default: 64
    }
  },
  emits: {
    load: options => true
  },
  setup(props, {
    slots,
    emit
  }) {
    let touchstartY = 0;
    let scrollParents = [];
    const touchDiff = shallowRef(0);
    const containerRef = ref();
    const refreshing = shallowRef(false);
    const goingUp = shallowRef(false);
    const touching = shallowRef(false);
    const canRefresh = computed(() => touchDiff.value >= props.pullDownThreshold && !refreshing.value);
    const topOffset = computed(() => clamp(touchDiff.value, 0, props.pullDownThreshold));
    function onTouchstart(e) {
      if (refreshing.value || props.disabled) return;
      touching.value = true;
      touchstartY = 'clientY' in e ? e.clientY : e.touches[0].clientY;
    }
    function onTouchmove(e) {
      if (refreshing.value || !touching.value || props.disabled) return;
      const touchY = 'clientY' in e ? e.clientY : e.touches[0].clientY;
      if (scrollParents.length && !scrollParents[0].scrollTop) {
        touchDiff.value = touchY - touchstartY;
      }
    }
    function onTouchend(e) {
      if (refreshing.value || props.disabled) return;
      touching.value = false;
      if (canRefresh.value) {
        function done() {
          if (!refreshing.value) return;
          touchDiff.value = 0;
          refreshing.value = false;
        }
        emit('load', {
          done
        });
        refreshing.value = true;
      } else {
        touchDiff.value = 0;
      }
    }
    onMounted(() => {
      scrollParents = getScrollParents(containerRef.value);
    });
    watch([topOffset, refreshing], () => {
      if (scrollParents.length) {
        const stopScrolling = topOffset.value && !refreshing.value;
        scrollParents.forEach(p => p.style.overflow = stopScrolling ? 'hidden' : 'auto');
      }
    });
    watch(topOffset, (newVal, oldVal) => {
      goingUp.value = newVal < oldVal;
    });
    useRender(() => {
      return createElementVNode("div", {
        "class": normalizeClass(['v-pull-to-refresh']),
        "onTouchstart": onTouchstart,
        "onTouchmove": onTouchmove,
        "onTouchend": onTouchend,
        "onMousedown": onTouchstart,
        "onMouseup": onTouchend,
        "onMouseleave": onTouchend,
        "onMousemove": onTouchmove,
        "ref": containerRef
      }, [createElementVNode("div", {
        "class": normalizeClass(['v-pull-to-refresh__pull-down', {
          'v-pull-to-refresh__pull-down--touching': touching.value
        }]),
        "style": {
          top: convertToUnit(-1 * props.pullDownThreshold + topOffset.value),
          height: convertToUnit(props.pullDownThreshold)
        }
      }, [slots.pullDownPanel ? slots.pullDownPanel({
        canRefresh: canRefresh.value,
        goingUp: goingUp.value,
        refreshing: refreshing.value
      }) : createElementVNode("div", {
        "class": normalizeClass(['v-pull-to-refresh__pull-down-default'])
      }, [refreshing.value ? createVNode(VProgressCircular, {
        "indeterminate": true,
        "active": false
      }, null) : createVNode(VIcon, {
        "icon": canRefresh.value || goingUp.value ? '$sortAsc' : '$sortDesc'
      }, null)])]), createElementVNode("div", {
        "class": normalizeClass(['v-pull-to-refresh__scroll-container', {
          'v-pull-to-refresh__scroll-container--touching': touching.value
        }]),
        "style": {
          top: convertToUnit(topOffset.value)
        }
      }, [slots.default?.()])]);
    });
  }
});

// Types

const makeVRadioProps = propsFactory({
  ...omit(makeVSelectionControlProps({
    falseIcon: '$radioOff',
    trueIcon: '$radioOn'
  }), ['indeterminate', 'indeterminateIcon'])
}, 'VRadio');
const VRadio = genericComponent()({
  name: 'VRadio',
  props: makeVRadioProps(),
  setup(props, {
    slots
  }) {
    useRender(() => {
      const controlProps = VSelectionControl.filterProps(props);
      return createVNode(VSelectionControl, mergeProps(controlProps, {
        "class": ['v-radio', props.class],
        "style": props.style,
        "type": "radio"
      }), slots);
    });
    return {};
  }
});

// Types

const makeVRadioGroupProps = propsFactory({
  height: {
    type: [Number, String],
    default: 'auto'
  },
  ...omit(makeVInputProps(), ['direction', 'glow']),
  ...omit(makeSelectionControlGroupProps(), ['multiple']),
  trueIcon: {
    type: IconValue,
    default: '$radioOn'
  },
  falseIcon: {
    type: IconValue,
    default: '$radioOff'
  },
  type: {
    type: String,
    default: 'radio'
  }
}, 'VRadioGroup');
const VRadioGroup = genericComponent()({
  name: 'VRadioGroup',
  inheritAttrs: false,
  props: makeVRadioGroupProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    attrs,
    slots
  }) {
    const uid = useId();
    const id = computed(() => props.id || `radio-group-${uid}`);
    const model = useProxiedModel(props, 'modelValue');
    const inputRef = ref();
    useRender(() => {
      const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
      const inputProps = VInput.filterProps(props);
      const controlProps = VSelectionControl.filterProps(props);
      const label = slots.label ? slots.label({
        label: props.label,
        props: {
          for: id.value
        }
      }) : props.label;
      return createVNode(VInput, mergeProps({
        "ref": inputRef,
        "class": ['v-radio-group', props.class],
        "style": props.style
      }, rootAttrs, inputProps, {
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "id": id.value
      }), {
        ...slots,
        default: ({
          id,
          messagesId,
          isDisabled,
          isReadonly
        }) => createElementVNode(Fragment, null, [label && createVNode(VLabel, {
          "id": id.value
        }, {
          default: () => [label]
        }), createVNode(VSelectionControlGroup, mergeProps(controlProps, {
          "id": id.value,
          "aria-describedby": messagesId.value,
          "defaultsTarget": "VRadio",
          "trueIcon": props.trueIcon,
          "falseIcon": props.falseIcon,
          "type": props.type,
          "disabled": isDisabled.value,
          "readonly": isReadonly.value,
          "aria-labelledby": label ? id.value : undefined,
          "multiple": false
        }, controlAttrs, {
          "modelValue": model.value,
          "onUpdate:modelValue": $event => model.value = $event
        }), slots)])
      });
    });
    return forwardRefs({}, inputRef);
  }
});

// Types

const makeVRangeSliderProps = propsFactory({
  ...makeFocusProps(),
  ...makeVInputProps(),
  ...makeSliderProps(),
  strict: Boolean,
  modelValue: {
    type: Array,
    default: () => [0, 0]
  }
}, 'VRangeSlider');
const VRangeSlider = genericComponent()({
  name: 'VRangeSlider',
  inheritAttrs: false,
  props: makeVRangeSliderProps(),
  emits: {
    'update:focused': value => true,
    'update:modelValue': value => true,
    end: value => true,
    start: value => true
  },
  setup(props, {
    slots,
    emit,
    attrs
  }) {
    const startThumbRef = ref();
    const stopThumbRef = ref();
    const inputRef = ref();
    const {
      rtlClasses
    } = useRtl();
    function getActiveThumb(e) {
      if (!startThumbRef.value || !stopThumbRef.value) return;
      const startOffset = getOffset(e, startThumbRef.value.$el, props.direction);
      const stopOffset = getOffset(e, stopThumbRef.value.$el, props.direction);
      const a = Math.abs(startOffset);
      const b = Math.abs(stopOffset);
      return a < b || a === b && startOffset < 0 ? startThumbRef.value.$el : stopThumbRef.value.$el;
    }
    const steps = useSteps(props);
    const model = useProxiedModel(props, 'modelValue', undefined, arr => {
      if (!arr?.length) return [0, 0];
      return arr.map(value => steps.roundValue(value));
    });
    const {
      activeThumbRef,
      hasLabels,
      max,
      min,
      mousePressed,
      onSliderMousedown,
      onSliderTouchstart,
      position,
      trackContainerRef,
      disabled,
      readonly
    } = useSlider({
      props,
      steps,
      onSliderStart: () => {
        if (disabled.value || readonly.value) {
          activeThumbRef.value?.blur();
          return;
        }
        emit('start', model.value);
      },
      onSliderEnd: ({
        value
      }) => {
        if (disabled.value || readonly.value) {
          activeThumbRef.value?.blur();
        } else {
          const newValue = activeThumbRef.value === startThumbRef.value?.$el ? [value, model.value[1]] : [model.value[0], value];
          if (!props.strict && newValue[0] < newValue[1]) {
            model.value = newValue;
          }
        }
        emit('end', model.value);
      },
      onSliderMove: ({
        value
      }) => {
        const [start, stop] = model.value;
        if (disabled.value || readonly.value) {
          activeThumbRef.value?.blur();
          return;
        }
        if (!props.strict && start === stop && start !== min.value) {
          activeThumbRef.value = value > start ? stopThumbRef.value?.$el : startThumbRef.value?.$el;
          activeThumbRef.value?.focus();
        }
        if (activeThumbRef.value === startThumbRef.value?.$el) {
          model.value = [Math.min(value, stop), stop];
        } else {
          model.value = [start, Math.max(start, value)];
        }
      },
      getActiveThumb
    });
    const {
      isFocused,
      focus,
      blur
    } = useFocus(props);
    const trackStart = computed(() => position(model.value[0]));
    const trackStop = computed(() => position(model.value[1]));
    useRender(() => {
      const inputProps = VInput.filterProps(props);
      const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
      const hasPrepend = !!(props.label || slots.label || slots.prepend);
      return createVNode(VInput, mergeProps({
        "class": ['v-slider', 'v-range-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,
        "ref": inputRef
      }, inputProps, rootAttrs, {
        "focused": isFocused.value
      }), {
        ...slots,
        prepend: hasPrepend ? slotProps => createElementVNode(Fragment, null, [slots.label?.(slotProps) ?? (props.label ? createVNode(VLabel, {
          "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}_start`,
          "name": props.name || id.value,
          "disabled": disabled.value,
          "readonly": readonly.value,
          "tabindex": "-1",
          "value": model.value[0]
        }, null), createElementVNode("input", {
          "id": `${id.value}_stop`,
          "name": props.name || id.value,
          "disabled": disabled.value,
          "readonly": readonly.value,
          "tabindex": "-1",
          "value": model.value[1]
        }, null), createVNode(VSliderTrack, {
          "ref": trackContainerRef,
          "start": trackStart.value,
          "stop": trackStop.value
        }, {
          'tick-label': slots['tick-label']
        }), createVNode(VSliderThumb, mergeProps({
          "ref": startThumbRef,
          "aria-describedby": messagesId.value,
          "focused": isFocused && activeThumbRef.value === startThumbRef.value?.$el,
          "modelValue": model.value[0],
          "onUpdate:modelValue": v => model.value = [v, model.value[1]],
          "onFocus": e => {
            focus();
            activeThumbRef.value = startThumbRef.value?.$el;

            // Make sure second thumb is focused if
            // the thumbs are on top of each other
            // and they are both at minimum value
            // but only if focused from outside.
            if (max.value !== min.value && model.value[0] === model.value[1] && model.value[1] === min.value && e.relatedTarget !== stopThumbRef.value?.$el) {
              startThumbRef.value?.$el.blur();
              stopThumbRef.value?.$el.focus();
            }
          },
          "onBlur": () => {
            blur();
            activeThumbRef.value = undefined;
          },
          "min": min.value,
          "max": model.value[1],
          "position": trackStart.value,
          "ripple": props.ripple
        }, inputAttrs), {
          'thumb-label': slots['thumb-label']
        }), createVNode(VSliderThumb, mergeProps({
          "ref": stopThumbRef,
          "aria-describedby": messagesId.value,
          "focused": isFocused && activeThumbRef.value === stopThumbRef.value?.$el,
          "modelValue": model.value[1],
          "onUpdate:modelValue": v => model.value = [model.value[0], v],
          "onFocus": e => {
            focus();
            activeThumbRef.value = stopThumbRef.value?.$el;

            // Make sure first thumb is focused if
            // the thumbs are on top of each other
            // and they are both at maximum value
            // but only if focused from outside.
            if (max.value !== min.value && model.value[0] === model.value[1] && model.value[0] === max.value && e.relatedTarget !== startThumbRef.value?.$el) {
              stopThumbRef.value?.$el.blur();
              startThumbRef.value?.$el.focus();
            }
          },
          "onBlur": () => {
            blur();
            activeThumbRef.value = undefined;
          },
          "min": model.value[0],
          "max": max.value,
          "position": trackStop.value,
          "ripple": props.ripple
        }, inputAttrs), {
          'thumb-label': slots['thumb-label']
        })])
      });
    });
    return forwardRefs({
      focus: () => startThumbRef.value?.$el.focus()
    }, inputRef);
  }
});

// Types

const makeVRatingProps = propsFactory({
  name: String,
  itemAriaLabel: {
    type: String,
    default: '$vuetify.rating.ariaLabel.item'
  },
  activeColor: String,
  color: String,
  clearable: Boolean,
  disabled: Boolean,
  emptyIcon: {
    type: IconValue,
    default: '$ratingEmpty'
  },
  fullIcon: {
    type: IconValue,
    default: '$ratingFull'
  },
  halfIncrements: Boolean,
  hover: Boolean,
  length: {
    type: [Number, String],
    default: 5
  },
  readonly: Boolean,
  modelValue: {
    type: [Number, String],
    default: 0
  },
  itemLabels: Array,
  itemLabelPosition: {
    type: String,
    default: 'top',
    validator: v => ['top', 'bottom'].includes(v)
  },
  ripple: Boolean,
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeSizeProps(),
  ...makeTagProps(),
  ...makeThemeProps()
}, 'VRating');
const VRating = genericComponent()({
  name: 'VRating',
  props: makeVRatingProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const {
      t
    } = useLocale();
    const {
      themeClasses
    } = provideTheme(props);
    const root = ref();
    const rating = useProxiedModel(props, 'modelValue');
    const normalizedValue = computed(() => clamp(parseFloat(rating.value), 0, Number(props.length)));
    const range = computed(() => createRange(Number(props.length), 1));
    const increments = computed(() => range.value.flatMap(v => props.halfIncrements ? [v - 0.5, v] : [v]));
    const hoverIndex = shallowRef(-1);
    const itemState = computed(() => increments.value.map(value => {
      const isHovering = props.hover && hoverIndex.value > -1;
      const isFilled = normalizedValue.value >= value;
      const isHovered = hoverIndex.value >= value;
      const isFullIcon = isHovering ? isHovered : isFilled;
      const icon = isFullIcon ? props.fullIcon : props.emptyIcon;
      const activeColor = props.activeColor ?? props.color;
      const color = isFilled || isHovered ? activeColor : props.color;
      return {
        isFilled,
        isHovered,
        icon,
        color,
        activeColor
      };
    }));
    const eventState = computed(() => [0, ...increments.value].map(value => {
      function onMouseenter() {
        hoverIndex.value = value;
      }
      function onMouseleave() {
        hoverIndex.value = -1;
      }
      function onClick() {
        if (props.disabled || props.readonly) return;
        rating.value = normalizedValue.value === value && props.clearable ? 0 : value;
      }
      return {
        onMouseenter: props.hover ? onMouseenter : undefined,
        onMouseleave: props.hover ? onMouseleave : undefined,
        onClick
      };
    }));
    const currentItemIndex = computed(() => {
      return props.halfIncrements ? 1 + Math.floor(Math.max(0, Number(rating.value ?? 0) - 0.5)) * 2 : Math.floor(Math.max(0, Number(rating.value ?? 0) - 1));
    });
    function moveCurrentFocus() {
      const currentItem = root.value?.querySelector('[tabindex="0"]');
      currentItem?.focus();
    }
    function onItemKeydown(event) {
      if (props.disabled || props.readonly) return;
      if (event.ctrlKey || event.altKey) return;
      const step = props.halfIncrements ? 0.5 : 1;
      if (event.key === 'ArrowRight') {
        const newValue = Math.min(Number(props.length), Number(rating.value ?? 0) + step);
        rating.value = newValue;
        nextTick(() => moveCurrentFocus());
      }
      if (event.key === 'ArrowLeft') {
        const newValue = Math.max(0, Number(rating.value ?? 0) - step);
        rating.value = newValue;
        nextTick(() => moveCurrentFocus());
      }
    }
    const uid = useId();
    const name = computed(() => props.name ?? `v-rating-${uid}`);
    function VRatingItem({
      value,
      index,
      showStar = true
    }) {
      const {
        onMouseenter,
        onMouseleave,
        onClick
      } = eventState.value[index + 1];
      const id = `${name.value}-${String(value).replace('.', '-')}`;
      const isFocusable = index === currentItemIndex.value;
      const btnProps = {
        color: itemState.value[index]?.color,
        density: props.density,
        disabled: props.disabled,
        icon: itemState.value[index]?.icon,
        ripple: props.ripple,
        size: props.size,
        variant: 'plain',
        tabindex: isFocusable ? 0 : -1,
        onKeydown: onItemKeydown
      };
      return createElementVNode(Fragment, null, [createElementVNode("label", {
        "for": id,
        "class": normalizeClass({
          'v-rating__item--half': props.halfIncrements && value % 1 > 0,
          'v-rating__item--full': props.halfIncrements && value % 1 === 0
        }),
        "onMouseenter": onMouseenter,
        "onMouseleave": onMouseleave,
        "onClick": onClick
      }, [createElementVNode("span", {
        "class": "v-rating__hidden"
      }, [t(props.itemAriaLabel, value, props.length)]), !showStar ? undefined : slots.item ? slots.item({
        ...itemState.value[index],
        props: btnProps,
        value,
        index,
        rating: normalizedValue.value
      }) : createVNode(VBtn, mergeProps({
        "aria-label": t(props.itemAriaLabel, value, props.length)
      }, btnProps), null)]), createElementVNode("input", {
        "class": "v-rating__hidden",
        "name": name.value,
        "id": id,
        "type": "radio",
        "value": value,
        "checked": normalizedValue.value === value,
        "tabindex": -1,
        "readonly": props.readonly,
        "disabled": props.disabled
      }, null)]);
    }
    function createLabel(labelProps) {
      if (slots['item-label']) return slots['item-label'](labelProps);
      if (labelProps.label) return createElementVNode("span", null, [labelProps.label]);
      return createElementVNode("span", null, [createTextVNode("\xA0")]);
    }
    useRender(() => {
      const hasLabels = !!props.itemLabels?.length || slots['item-label'];
      return createVNode(props.tag, {
        "class": normalizeClass(['v-rating', {
          'v-rating--hover': props.hover,
          'v-rating--readonly': props.readonly
        }, themeClasses.value, props.class]),
        "style": normalizeStyle(props.style),
        "ref": root
      }, {
        default: () => [createVNode(VRatingItem, {
          "value": 0,
          "index": -1,
          "showStar": false
        }, null), range.value.map((value, i) => createElementVNode("div", {
          "class": "v-rating__wrapper"
        }, [hasLabels && props.itemLabelPosition === 'top' ? createLabel({
          value,
          index: i,
          label: props.itemLabels?.[i]
        }) : undefined, createElementVNode("div", {
          "class": "v-rating__item"
        }, [props.halfIncrements ? createElementVNode(Fragment, null, [createVNode(VRatingItem, {
          "value": value - 0.5,
          "index": i * 2
        }, null), createVNode(VRatingItem, {
          "value": value,
          "index": i * 2 + 1
        }, null)]) : createVNode(VRatingItem, {
          "value": value,
          "index": i
        }, null)]), hasLabels && props.itemLabelPosition === 'bottom' ? createLabel({
          value,
          index: i,
          label: props.itemLabels?.[i]
        }) : undefined]))]
      });
    });
    return {};
  }
});

// Types

const rootTypes = {
  actions: 'button@2',
  article: 'heading, paragraph',
  avatar: 'avatar',
  button: 'button',
  card: 'image, heading',
  'card-avatar': 'image, list-item-avatar',
  chip: 'chip',
  'date-picker': 'list-item, heading, divider, date-picker-options, date-picker-days, actions',
  'date-picker-options': 'text, avatar@2',
  'date-picker-days': 'avatar@28',
  divider: 'divider',
  heading: 'heading',
  image: 'image',
  'list-item': 'text',
  'list-item-avatar': 'avatar, text',
  'list-item-two-line': 'sentences',
  'list-item-avatar-two-line': 'avatar, sentences',
  'list-item-three-line': 'paragraph',
  'list-item-avatar-three-line': 'avatar, paragraph',
  ossein: 'ossein',
  paragraph: 'text@3',
  sentences: 'text@2',
  subtitle: 'text',
  table: 'table-heading, table-thead, table-tbody, table-tfoot',
  'table-heading': 'chip, text',
  'table-thead': 'heading@6',
  'table-tbody': 'table-row-divider@6',
  'table-row-divider': 'table-row, divider',
  'table-row': 'text@6',
  'table-tfoot': 'text@2, avatar@2',
  text: 'text'
};
function genBone(type, children = []) {
  return createElementVNode("div", {
    "class": normalizeClass(['v-skeleton-loader__bone', `v-skeleton-loader__${type}`])
  }, [children]);
}
function genBones(bone) {
  // e.g. 'text@3'
  const [type, length] = bone.split('@');

  // Generate a length array based upon
  // value after @ in the bone string
  return Array.from({
    length
  }).map(() => genStructure(type));
}
function genStructure(type) {
  let children = [];
  if (!type) return children;

  // TODO: figure out a better way to type this
  const bone = rootTypes[type];

  // End of recursion, do nothing
  /* eslint-disable-next-line no-empty, brace-style */
  if (type === bone) ;
  // Array of values - e.g. 'heading, paragraph, text@2'
  else if (type.includes(',')) return mapBones(type);
  // Array of values - e.g. 'paragraph@4'
  else if (type.includes('@')) return genBones(type);
  // Array of values - e.g. 'card@2'
  else if (bone.includes(',')) children = mapBones(bone);
  // Array of values - e.g. 'list-item@2'
  else if (bone.includes('@')) children = genBones(bone);
  // Single value - e.g. 'card-heading'
  else if (bone) children.push(genStructure(bone));
  return [genBone(type, children)];
}
function mapBones(bones) {
  // Remove spaces and return array of structures
  return bones.replace(/\s/g, '').split(',').map(genStructure);
}
const makeVSkeletonLoaderProps = propsFactory({
  boilerplate: Boolean,
  color: String,
  loading: Boolean,
  loadingText: {
    type: String,
    default: '$vuetify.loading'
  },
  type: {
    type: [String, Array],
    default: 'ossein'
  },
  ...makeDimensionProps(),
  ...makeElevationProps(),
  ...makeThemeProps()
}, 'VSkeletonLoader');
const VSkeletonLoader = genericComponent()({
  name: 'VSkeletonLoader',
  inheritAttrs: false,
  props: makeVSkeletonLoaderProps(),
  setup(props, {
    attrs,
    slots
  }) {
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      themeClasses
    } = provideTheme(props);
    const {
      t
    } = useLocale();
    const items = computed(() => genStructure(wrapInArray(props.type).join(',')));
    useRender(() => {
      const isLoading = !slots.default || props.loading;
      const loadingProps = props.boilerplate || !isLoading ? {} : {
        ariaLive: 'polite',
        ariaLabel: t(props.loadingText),
        role: 'alert'
      };
      return isLoading ? createElementVNode("div", mergeProps({
        "class": ['v-skeleton-loader', {
          'v-skeleton-loader--boilerplate': props.boilerplate
        }, themeClasses.value, backgroundColorClasses.value, elevationClasses.value],
        "style": [backgroundColorStyles.value, dimensionStyles.value]
      }, loadingProps, attrs), [items.value]) : createElementVNode(Fragment, null, [slots.default?.()]);
    });
    return {};
  }
});

// Composables

// Types

const VSlideGroupItem = genericComponent()({
  name: 'VSlideGroupItem',
  props: makeGroupItemProps(),
  emits: {
    'group:selected': val => true
  },
  setup(props, {
    slots
  }) {
    const slideGroupItem = useGroupItem(props, VSlideGroupSymbol);
    return () => slots.default?.({
      isSelected: slideGroupItem.isSelected.value,
      select: slideGroupItem.select,
      toggle: slideGroupItem.toggle,
      selectedClass: slideGroupItem.selectedClass.value
    });
  }
});

// Composables

// Types

const VSnackbarQueueSymbol = Symbol.for('vuetify:v-snackbar-queue');
function useSnackbarQueue(props) {
  const items = ref(new Map());
  const gap = toRef(() => Number(props.gap));
  function register(id) {
    items.value.set(id, {
      height: 0,
      width: 0
    });
  }
  function unregister(id) {
    items.value.delete(id);
  }
  function setSize(id, height, width) {
    const item = items.value.get(id);
    if (!item || item.height === height && item.width === width) return;
    item.height = height;
    item.width = width;
  }
  const lastItemSize = computed(() => {
    for (const {
      width,
      height
    } of [...items.value.values()].toReversed()) {
      if (!width || !height) continue;
      return {
        width,
        height
      };
    }
    return {
      width: 0,
      height: 0
    };
  });
  function getOffset(id) {
    if (!items.value.has(id)) return null;
    let offset = 0;
    for (const [itemId, state] of [...items.value.entries()].toReversed()) {
      if (itemId === id) break;
      offset += state.height + gap.value;
    }
    return offset;
  }
  const state = {
    register,
    unregister,
    setSize,
    getOffset,
    items,
    gap,
    lastItemSize
  };
  provide(VSnackbarQueueSymbol, state);
  return state;
}
function useSnackbarItem(isActive, contentEl) {
  const queue = inject$1(VSnackbarQueueSymbol, null);
  if (!queue) return null;
  const id = useId();
  queue.register(id);
  onBeforeUnmount(() => queue.unregister(id));
  watch(isActive, val => !val && queue.unregister(id), {
    flush: 'sync'
  });
  const {
    resizeRef,
    contentRect
  } = useResizeObserver();
  watch(contentEl, el => {
    resizeRef.value = el ?? null;
  });
  watch(contentRect, rect => {
    if (rect?.width) queue.setSize(id, rect.height, rect.width);
  });
  const offset = computed(() => queue.getOffset(id));
  return {
    id,
    offset
  };
}

// Types

function useCountdown(milliseconds) {
  const time = shallowRef(milliseconds());
  let timer = -1;
  function clear() {
    clearInterval(timer);
  }
  function reset() {
    clear();
    nextTick(() => time.value = milliseconds());
  }
  function start(el) {
    const style = el ? getComputedStyle(el) : {
      transitionDuration: 0.2
    };
    const interval = parseFloat(style.transitionDuration) * 1000 || 200;
    clear();
    if (time.value <= 0) return;
    const startTime = performance.now();
    timer = window.setInterval(() => {
      const elapsed = performance.now() - startTime + interval;
      time.value = Math.max(milliseconds() - elapsed, 0);
      if (time.value <= 0) clear();
    }, interval);
  }
  onScopeDispose(clear);
  return {
    clear,
    time,
    start,
    reset
  };
}
const makeVSnackbarProps = propsFactory({
  collapsed: Object,
  loading: Boolean,
  prependAvatar: String,
  prependIcon: IconValue,
  queueGap: Number,
  queueIndex: Number,
  title: String,
  text: String,
  reverseTimer: Boolean,
  timer: {
    type: [Boolean, String],
    default: false
  },
  timerColor: String,
  timeout: {
    type: [Number, String],
    default: 5000
  },
  vertical: Boolean,
  ...makeLocationProps({
    location: 'bottom center'
  }),
  ...makePositionProps(),
  ...makeRoundedProps(),
  ...makeVariantProps(),
  ...makeThemeProps(),
  ...omit(makeVOverlayProps({
    closeOnBack: false,
    locationStrategy: null,
    transition: 'v-snackbar-transition'
  }), ['persistent', 'noClickAnimation', 'offset', 'retainFocus', 'captureFocus', 'disableInitialFocus', 'location', 'scrim', 'scrollStrategy', 'stickToTarget', 'viewportMargin'])
}, 'VSnackbar');
const VSnackbar = genericComponent()({
  name: 'VSnackbar',
  props: makeVSnackbarProps(),
  emits: {
    'update:modelValue': v => true
  },
  setup(props, {
    slots
  }) {
    const isActive = useProxiedModel(props, 'modelValue');
    const {
      positionClasses
    } = usePosition(props);
    const {
      scopeId
    } = useScopeId();
    const {
      themeClasses
    } = provideTheme(props);
    const {
      colorClasses,
      colorStyles,
      variantClasses
    } = useVariant(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const countdown = useCountdown(() => Number(props.timeout));
    const overlay = ref();
    const queueItem = useSnackbarItem(isActive, () => overlay.value?.contentEl);
    let _lastOffset;
    const timerRef = ref();
    const isHovering = shallowRef(false);
    const isFocused = shallowRef(false);
    const startY = shallowRef(0);
    const mainStyles = ref();
    const hasLayout = inject$1(VuetifyLayoutKey, undefined);
    useToggleScope(() => !!hasLayout, () => {
      const layout = useLayout();
      watchEffect(() => {
        mainStyles.value = layout.mainStyles.value;
      });
    });
    watch(isActive, startTimeout);
    watch(() => props.timeout, startTimeout);
    onMounted(() => {
      if (isActive.value) startTimeout();
    });
    let activeTimeout = -1;
    function startTimeout() {
      countdown.clear();
      window.clearTimeout(activeTimeout);
      const timeout = Number(props.timeout);
      if (!isActive.value || timeout === -1) return;
      countdown.reset();
      const element = refElement(timerRef.value);
      nextTick(() => countdown.start(element));
      activeTimeout = window.setTimeout(() => {
        isActive.value = false;
      }, timeout);
    }
    function clearTimeout() {
      countdown.reset();
      window.clearTimeout(activeTimeout);
    }
    function onPointerenter() {
      isHovering.value = true;
      clearTimeout();
    }
    function onPointerleave() {
      isHovering.value = false;
      if (!isFocused.value) startTimeout();
    }
    function onFocusin() {
      isFocused.value = true;
      clearTimeout();
    }
    function onFocusout(event) {
      const contentEl = overlay.value?.contentEl;
      if (contentEl?.contains(event.relatedTarget)) {
        return;
      }
      isFocused.value = false;
      if (!isHovering.value) startTimeout();
    }
    function onTouchstart(event) {
      startY.value = event.touches[0].clientY;
    }
    function onTouchend(event) {
      if (Math.abs(startY.value - event.changedTouches[0].clientY) > 50) {
        isActive.value = false;
      }
    }
    function onAfterLeave() {
      if (isHovering.value) onPointerleave();
      isFocused.value = false;
    }
    const locationClasses = computed(() => {
      return props.location.split(' ').reduce((acc, loc) => {
        acc[`v-snackbar--${loc}`] = true;
        return acc;
      }, {});
    });
    const queueDirection = computed(() => {
      const [side, align] = props.location.split(' ');
      return side === 'bottom' || ['left', 'right'].includes(side) && align === 'end' ? -1 : 1;
    });
    const collapsedStyles = computed(() => {
      if (!props.collapsed) return null;
      return {
        '--v-snackbar-collapsed-height': convertToUnit(props.collapsed.height),
        '--v-snackbar-collapsed-width': convertToUnit(props.collapsed.width)
      };
    });
    const offset = computed(() => {
      if (!queueItem) return undefined;
      if (queueItem.offset.value === null) {
        return _lastOffset;
      }
      return _lastOffset = convertToUnit(queueItem.offset.value);
    });
    const transition = computed(() => {
      if (typeof props.transition !== 'string' || !props.transition.endsWith('-auto')) {
        return props.transition;
      }
      const prefix = props.transition.replace('-auto', '');
      const [side, align] = props.location.split(' ');
      const axis = ['start', 'end', 'left', 'right'].includes(align) || ['left', 'right'].includes(side) ? 'x' : 'y';
      const reverse = ['end', 'right'].includes(align) || !['start', 'left'].includes(align) && ['bottom', 'right'].includes(side) ? '-reverse' : '';
      return `${prefix}-${axis}${reverse}-transition`;
    });
    useRender(() => {
      const overlayProps = VOverlay.filterProps({
        ...props,
        location: props.location,
        locationStrategy: props.locationStrategy ?? noop
      });
      const hasPrependMedia = !!(props.prependAvatar || props.prependIcon);
      const hasPrepend = !!(hasPrependMedia || props.loading || slots.prepend);
      const hasContent = !!(slots.default || slots.text || slots.title || props.text || props.title);
      return createVNode(VOverlay, mergeProps({
        "ref": overlay,
        "class": ['v-snackbar', {
          'v-snackbar--active': isActive.value,
          'v-snackbar--collapsed': !!props.collapsed,
          'v-snackbar--timer': !!props.timer,
          'v-snackbar--vertical': props.vertical
        }, locationClasses.value, positionClasses.value, props.class],
        "style": [mainStyles.value, {
          '--v-snackbar-offset': offset.value,
          '--v-snackbar-gap': convertToUnit(props.queueGap),
          '--v-snackbar-index': props.queueIndex,
          '--v-snackbar-direction': queueDirection.value
        }, collapsedStyles.value, props.style]
      }, overlayProps, {
        "transition": transition.value,
        "modelValue": isActive.value,
        "onUpdate:modelValue": $event => isActive.value = $event,
        "contentProps": mergeProps({
          class: ['v-snackbar__wrapper', themeClasses.value, colorClasses.value, roundedClasses.value, variantClasses.value],
          style: [colorStyles.value, roundedStyles.value],
          onPointerenter,
          onPointerleave,
          onFocusin,
          onFocusout
        }, overlayProps.contentProps),
        "persistent": true,
        "noClickAnimation": true,
        "scrim": false,
        "scrollStrategy": "none",
        "onTouchstartPassive": onTouchstart,
        "onTouchend": onTouchend,
        "onAfterLeave": onAfterLeave
      }, scopeId), {
        default: () => [genOverlays(false, 'v-snackbar'), slots.header && createElementVNode("div", {
          "class": "v-snackbar__header"
        }, [slots.header?.()]), props.timer && Number(props.timeout) > 0 && !isHovering.value && createElementVNode("div", {
          "key": "timer",
          "class": normalizeClass(['v-snackbar__timer', `v-snackbar__timer--${props.timer === 'bottom' ? 'bottom' : 'top'}`])
        }, [createVNode(VProgressLinear, {
          "ref": timerRef,
          "color": props.timerColor ?? 'info',
          "max": props.timeout,
          "modelValue": props.reverseTimer ? Number(props.timeout) - countdown.time.value : countdown.time.value
        }, null)]), hasPrepend && createVNode(VDefaultsProvider, {
          "key": "prepend-defaults",
          "disabled": !hasPrependMedia && !props.loading,
          "defaults": {
            VAvatar: {
              image: props.prependAvatar
            },
            VIcon: {
              icon: props.prependIcon
            },
            VProgressCircular: {
              indeterminate: true,
              size: 24,
              width: 3
            }
          }
        }, {
          default: () => [createElementVNode("div", {
            "class": "v-snackbar__prepend"
          }, [slots.prepend ? slots.prepend() : createElementVNode(Fragment, null, [props.loading && createVNode(VProgressCircular, null, null), !props.loading && props.prependAvatar && createVNode(VAvatar, null, null), !props.loading && props.prependIcon && createVNode(VIcon, null, null)])])]
        }), hasContent && createElementVNode("div", {
          "key": "content",
          "class": "v-snackbar__content",
          "role": "status",
          "aria-live": "polite"
        }, [slots.title?.() ?? (props.title ? createElementVNode("div", {
          "class": "v-snackbar__title",
          "key": "title"
        }, [props.title]) : ''), slots.text?.() ?? props.text, slots.default?.()]), slots.actions && createVNode(VDefaultsProvider, {
          "defaults": {
            VBtn: {
              variant: 'text',
              ripple: false,
              slim: true
            }
          }
        }, {
          default: () => [createElementVNode("div", {
            "class": "v-snackbar__actions"
          }, [slots.actions({
            isActive
          })])]
        })],
        activator: slots.activator
      });
    });
    return forwardRefs({}, overlay);
  }
});

// Utilities
function useDocumentVisibility() {
  const visibility = shallowRef(IN_BROWSER ? document.visibilityState : 'visible');
  if (IN_BROWSER) {
    const onVisibilityChange = () => {
      visibility.value = document.visibilityState;
    };
    document.addEventListener('visibilitychange', onVisibilityChange, {
      passive: true
    });
    onBeforeUnmount(() => {
      document.removeEventListener('visibilitychange', onVisibilityChange);
    });
  }
  return visibility;
}

// Types

const makeVSnackbarQueueProps = propsFactory({
  // TODO: Port this to Snackbar on dev
  closable: [Boolean, String],
  closeText: {
    type: String,
    default: '$vuetify.dismiss'
  },
  collapsed: Boolean,
  displayStrategy: {
    type: String,
    default: 'hold'
  },
  modelValue: {
    type: Array,
    default: () => []
  },
  totalVisible: {
    type: [Number, String],
    default: 1
  },
  gap: {
    type: [Number, String],
    default: 8
  },
  ...omit(makeVSnackbarProps(), ['modelValue', 'collapsed', 'queueIndex', 'queueGap'])
}, 'VSnackbarQueue');
const VSnackbarQueue = genericComponent()({
  name: 'VSnackbarQueue',
  inheritAttrs: false,
  props: makeVSnackbarQueueProps(),
  emits: {
    'update:modelValue': val => true
  },
  setup(props, {
    attrs,
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    const documentVisibility = useDocumentVisibility();
    const queue = useSnackbarQueue(props);
    const isHovered = shallowRef(false);
    const {
      runOpenDelay,
      runCloseDelay
    } = useDelay({
      openDelay: 0,
      closeDelay: 500
    }, val => {
      isHovered.value = val;
      updateDynamicProps();
    });
    let _lastId = 0;
    const visibleItems = ref([]);
    const limit = toRef(() => Number(props.totalVisible));
    watch(() => props.modelValue.length, showNext);
    function removeItem(id) {
      visibleItems.value = visibleItems.value.filter(x => x.id !== id);
      if (visibleItems.value.length === 0) {
        isHovered.value = false;
      }
      showNext();
    }
    function showNext() {
      if (!props.modelValue.length) return;
      const activeCount = visibleItems.value.filter(x => x.active).length;
      if (activeCount >= limit.value) {
        if (props.displayStrategy !== 'overflow') return;

        // Dismiss oldest active items to make room
        visibleItems.value.filter(x => x.active).slice(limit.value - 1).forEach(item => {
          item.active = false;
          item.onDismiss?.('overflow');
        });
      }
      const [next, ...rest] = props.modelValue;
      emit('update:modelValue', rest);
      const item = typeof next === 'string' ? {
        text: next
      } : next;
      const {
        promise,
        success,
        error,
        onDismiss,
        ...itemProps
      } = item;
      const newItem = {
        id: _lastId++,
        item: {
          ...(promise ? {
            timeout: -1,
            loading: true
          } : {}),
          ...itemProps
        },
        active: true,
        onDismiss
      };
      visibleItems.value.unshift(newItem);
      updateDynamicProps();
      promise?.then(data => {
        if (!newItem.active) return;
        newItem.item = success?.(data) ?? {
          ...newItem.item,
          timeout: 1
        };
        updateDynamicProps();
        triggerRef(visibleItems);
      }, data => {
        if (!newItem.active) return;
        newItem.item = error?.(data) ?? {
          ...newItem.item,
          timeout: 1
        };
        updateDynamicProps();
        triggerRef(visibleItems);
      });
    }
    function dismiss(id, reason) {
      const item = visibleItems.value.find(x => x.id === id);
      if (!item) return;
      item.active = false;
      item.onDismiss?.(reason);
      updateDynamicProps();
    }
    function clear() {
      emit('update:modelValue', []);
      visibleItems.value.toReversed().forEach((item, i) => setTimeout(() => {
        item.active = false;
        item.onDismiss?.('cleared');
      }, 100 * i));
    }
    const btnProps = computed(() => ({
      color: typeof props.closable === 'string' ? props.closable : undefined,
      text: t(props.closeText)
    }));
    function updateDynamicProps() {
      let activeIndex = 0;
      visibleItems.value.forEach(({
        item,
        active
      }) => {
        item.queueIndex = activeIndex;
        if (active) activeIndex++;
      });
      if (!props.collapsed || isHovered.value) {
        visibleItems.value.forEach(({
          item
        }) => item.collapsed = undefined);
        return;
      }
      for (const {
        item
      } of visibleItems.value) {
        item.collapsed = item.queueIndex > 0 ? {
          width: queue.lastItemSize.value.width,
          height: queue.lastItemSize.value.height
        } : undefined;
      }
    }
    watch(queue.lastItemSize, updateDynamicProps);
    watch(() => props.collapsed, updateDynamicProps);
    useRender(() => {
      const hasActions = !!(props.closable || slots.actions);
      const snackbarProps = omit(VSnackbar.filterProps(props), ['modelValue', 'collapsed']);
      const pauseAll = documentVisibility.value === 'hidden' || props.collapsed && isHovered.value;
      return createElementVNode(Fragment, null, [visibleItems.value.map(({
        id,
        item,
        active
      }) => slots.item ? createVNode(VDefaultsProvider, {
        "defaults": {
          VSnackbar: item
        }
      }, {
        default: () => [slots.item({
          item
        })]
      }) : createVNode(VSnackbar, mergeProps({
        "key": id
      }, attrs, snackbarProps, item, pauseAll ? {
        timeout: -1
      } : {}, {
        "queueGap": Number(props.gap),
        "contentProps": mergeProps(snackbarProps.contentProps, {
          onMouseenter: runOpenDelay,
          onMouseleave: () => runCloseDelay()
        }),
        "modelValue": active,
        "onUpdate:modelValue": () => dismiss(id, 'auto'),
        "onAfterLeave": () => removeItem(id)
      }), {
        header: slots.header ? () => slots.header?.({
          item
        }) : undefined,
        text: slots.text ? () => slots.text?.({
          item
        }) : undefined,
        actions: hasActions ? () => createElementVNode(Fragment, null, [!slots.actions ? createVNode(VBtn, mergeProps(btnProps.value, {
          "onClick": () => dismiss(id, 'dismissed')
        }), null) : createVNode(VDefaultsProvider, {
          "defaults": {
            VBtn: btnProps.value
          }
        }, {
          default: () => [slots.actions({
            item,
            props: {
              onClick: () => dismiss(id, 'dismissed')
            }
          })]
        })]) : undefined
      }))]);
    });
    return {
      clear
    };
  }
});

// Types

const makeVTooltipProps = propsFactory({
  id: String,
  interactive: Boolean,
  text: String,
  color: String,
  ...omit(makeVOverlayProps({
    closeOnBack: false,
    location: 'end',
    locationStrategy: 'connected',
    eager: true,
    minWidth: 0,
    offset: 10,
    openOnClick: false,
    openOnHover: true,
    origin: 'auto',
    scrim: false,
    scrollStrategy: 'reposition',
    transition: null
  }), ['absolute', 'retainFocus', 'captureFocus', 'disableInitialFocus'])
}, 'VTooltip');
const VTooltip = genericComponent()({
  name: 'VTooltip',
  props: makeVTooltipProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const isActive = useProxiedModel(props, 'modelValue');
    const {
      scopeId
    } = useScopeId();
    const {
      colorClasses,
      colorStyles
    } = useColor(() => ({
      background: props.color
    }));
    const uid = useId();
    const id = toRef(() => props.id || `v-tooltip-${uid}`);
    const overlay = ref();
    const location = computed(() => {
      return props.location.split(' ').length > 1 ? props.location : props.location + ' center';
    });
    const origin = computed(() => {
      return props.origin === 'auto' || props.origin === 'overlap' || props.origin.split(' ').length > 1 || props.location.split(' ').length > 1 ? props.origin : props.origin + ' center';
    });
    const transition = toRef(() => {
      if (props.transition != null) return props.transition;
      return isActive.value ? 'scale-transition' : 'fade-transition';
    });
    const activatorProps = computed(() => mergeProps({
      'aria-describedby': id.value
    }, props.activatorProps));
    useRender(() => {
      const overlayProps = VOverlay.filterProps(props);
      return createVNode(VOverlay, mergeProps({
        "ref": overlay,
        "class": ['v-tooltip', {
          'v-tooltip--interactive': props.interactive
        }, props.class],
        "style": [props.style],
        "id": id.value
      }, overlayProps, {
        "contentClass": [colorClasses.value, props.contentClass],
        "contentProps": mergeProps({
          style: [colorStyles.value]
        }, props.contentProps),
        "modelValue": isActive.value,
        "onUpdate:modelValue": $event => isActive.value = $event,
        "transition": transition.value,
        "absolute": true,
        "location": location.value,
        "origin": origin.value,
        "role": "tooltip",
        "activatorProps": activatorProps.value,
        "_disableGlobalStack": true
      }, scopeId), {
        activator: slots.activator,
        default: (...args) => slots.default?.(...args) ?? props.text
      });
    });
    return forwardRefs({}, overlay);
  }
});

// Types

const makeVSparklineTooltipProps = propsFactory({
  modelValue: Boolean,
  target: Object,
  index: {
    type: Number,
    default: null
  },
  value: {
    type: Number,
    default: 0
  },
  titleFormat: {
    type: Function,
    default: item => String(item.value)
  },
  offset: Number,
  contentClass: null,
  location: String
}, 'VSparklineTooltip');
const VSparklineTooltip = genericComponent()({
  name: 'VSparklineTooltip',
  props: makeVSparklineTooltipProps(),
  emits: {
    afterLeave: () => true
  },
  setup(props, {
    slots,
    emit
  }) {
    return () => createVNode(VTooltip, {
      "modelValue": props.modelValue,
      "target": props.target,
      "offset": props.offset,
      "contentClass": props.contentClass,
      "location": props.location,
      "onAfterLeave": () => emit('afterLeave')
    }, {
      default: () => [props.index !== null && (slots.default?.({
        index: props.index,
        value: props.value
      }) ?? props.titleFormat({
        index: props.index,
        value: props.value
      }))]
    });
  }
});

// Types

/**
 * Monotone cubic Hermite interpolation (Fritsch-Carlson) converted to cubic Bezier.
 * Prevents overshoot at local extrema (e.g. consecutive equal min/max values)
 * by zeroing tangents at turning points and applying an alpha-beta constraint.
 *
 * `smooth` controls tension: 0 = straight lines, 8 (default true) = full curve.
 */
function genMonotonePath(points, smooth, fill = false, height = 75) {
  if (points.length === 0) return '';
  const start = points[0];
  const end = points[points.length - 1];
  const prefix = fill ? `M${start.x} ${height - start.x + 2} L${start.x} ${start.y}` : `M${start.x} ${start.y}`;
  const suffix = fill ? `L${end.x} ${height - start.x + 2} Z` : '';
  if (smooth === 0 || points.length < 3) {
    return prefix + points.slice(1).map(point => `L${point.x} ${point.y}`).join('') + suffix;
  }
  const tension = Math.min(smooth / 8, 1);
  const n = points.length;
  const delta = [];
  for (let i = 0; i < n - 1; i++) {
    const dx = points[i + 1].x - points[i].x;
    delta[i] = dx === 0 ? 0 : (points[i + 1].y - points[i].y) / dx;
  }
  const tangent = new Array(n);
  tangent[0] = delta[0];
  tangent[n - 1] = delta[n - 2];
  for (let i = 1; i < n - 1; i++) {
    if (delta[i - 1] === 0 || delta[i] === 0 || delta[i - 1] > 0 !== delta[i] > 0) {
      tangent[i] = 0;
    } else {
      tangent[i] = (delta[i - 1] + delta[i]) / 2;
    }
  }
  for (let i = 0; i < n - 1; i++) {
    if (delta[i] === 0) {
      tangent[i] = 0;
      tangent[i + 1] = 0;
    } else {
      const alpha = tangent[i] / delta[i];
      const beta = tangent[i + 1] / delta[i];
      const squaredSum = alpha * alpha + beta * beta;
      if (squaredSum > 9) {
        const tau = 3 / Math.sqrt(squaredSum);
        tangent[i] = tau * alpha * delta[i];
        tangent[i + 1] = tau * beta * delta[i];
      }
    }
  }
  const curves = points.slice(1).map((curr, index) => {
    const prev = points[index];
    const dx = curr.x - prev.x;
    const controlPoint1X = prev.x + dx * tension / 3;
    const controlPoint1Y = prev.y + tangent[index] * dx * tension / 3;
    const controlPoint2X = curr.x - dx * tension / 3;
    const controlPoint2Y = curr.y - tangent[index + 1] * dx * tension / 3;
    return `C${controlPoint1X} ${controlPoint1Y} ${controlPoint2X} ${controlPoint2Y} ${curr.x} ${curr.y}`;
  });
  return prefix + curves.join('') + suffix;
}

// @ts-nocheck
/* eslint-disable */

// import { checkCollinear, getDistance, moveTo } from './math'

/**
 * From https://github.com/unsplash/react-trend/blob/master/src/helpers/DOM.helpers.js#L18
 */
function genRoundedPath(points, radius, fill = false, height = 75, consistentStructure = false) {
  if (points.length === 0) return '';
  const start = points.shift();
  const end = points[points.length - 1];
  return (fill ? `M${start.x} ${height - start.x + 2} L${start.x} ${start.y}` : `M${start.x} ${start.y}`) + points.map((point, index) => {
    const next = points[index + 1];
    const prev = points[index - 1] || start;
    const isCollinear = next && checkCollinear(next, point, prev);
    if (!next) {
      return consistentStructure ? `L${point.x} ${point.y}S${point.x} ${point.y} ${point.x} ${point.y}` : `L${point.x} ${point.y}`;
    }
    if (isCollinear && !consistentStructure) {
      return `L${point.x} ${point.y}`;
    }
    const threshold = Math.min(getDistance(prev, point), getDistance(next, point));
    const isTooCloseForRadius = threshold / 2 < radius;
    const radiusForPoint = isTooCloseForRadius ? threshold / 2 : radius;
    const before = moveTo(prev, point, radiusForPoint);
    const after = moveTo(next, point, radiusForPoint);
    return `L${before.x} ${before.y}S${point.x} ${point.y} ${after.x} ${after.y}`;
  }).join('') + (fill ? `L${end.x} ${height - start.x + 2} Z` : '');
}
function int(value) {
  return parseInt(value, 10);
}

/**
 * https://en.wikipedia.org/wiki/Collinearity
 * x=(x1+x2)/2
 * y=(y1+y2)/2
 */
function checkCollinear(p0, p1, p2) {
  return int(p0.x + p2.x) === int(2 * p1.x) && int(p0.y + p2.y) === int(2 * p1.y);
}
function getDistance(p1, p2) {
  return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}
function moveTo(to, from, radius) {
  const vector = {
    x: to.x - from.x,
    y: to.y - from.y
  };
  const length = Math.sqrt(vector.x * vector.x + vector.y * vector.y);
  const unitVector = {
    x: vector.x / length,
    y: vector.y / length
  };
  return {
    x: from.x + unitVector.x * radius,
    y: from.y + unitVector.y * radius
  };
}

// Utilities

// Types

const makeLineProps = propsFactory({
  animation: {
    type: [Boolean, Object],
    default: false
  },
  autoDraw: {
    type: [Boolean, String],
    default: false
  },
  autoDrawDuration: [Number, String],
  autoDrawEasing: {
    type: String,
    default: 'ease'
  },
  color: String,
  gradient: {
    type: Array,
    default: () => []
  },
  gradientDirection: {
    type: String,
    validator: val => ['top', 'bottom', 'left', 'right'].includes(val),
    default: 'top'
  },
  height: {
    type: [String, Number],
    default: 75
  },
  labels: {
    type: Array,
    default: () => []
  },
  labelSize: {
    type: [Number, String],
    default: 7
  },
  lineWidth: {
    type: [String, Number],
    default: 4
  },
  id: String,
  itemValue: {
    type: String,
    default: 'value'
  },
  modelValue: {
    type: Array,
    default: () => []
  },
  min: [String, Number],
  max: [String, Number],
  padding: {
    type: [String, Number],
    default: 8
  },
  markerSize: {
    type: [Number, String],
    default: 8
  },
  markerStroke: {
    type: String,
    default: '#fff'
  },
  inset: Boolean,
  showLabels: Boolean,
  showMarkers: Boolean,
  smooth: [Boolean, String, Number],
  smoothMode: {
    type: String,
    default: 'default'
  },
  interactive: Boolean,
  tooltip: {
    type: [Boolean, Object],
    default: false
  },
  width: {
    type: [Number, String],
    default: 300
  }
}, 'Line');
function resample(values, targetCount) {
  const length = values.length;
  if (length === 0) return Array(targetCount).fill(0);
  if (length === 1) return Array(targetCount).fill(values[0]);
  const result = [];
  for (let i = 0; i < targetCount; i++) {
    const t = i / (targetCount - 1) * (length - 1);
    const low = Math.floor(t);
    const high = Math.min(low + 1, length - 1);
    const fraction = t - low;
    result.push(values[low] + (values[high] - values[low]) * fraction);
  }
  return result;
}
function extendPoints(points, inset, totalWidth) {
  if (!inset || points.length < 2) return points;
  const first = points[0];
  const second = points[1];
  const last = points[points.length - 1];
  const secondLast = points[points.length - 2];
  const slopeStart = (second.y - first.y) / (second.x - first.x);
  const slopeEnd = (last.y - secondLast.y) / (last.x - secondLast.x);
  const ghostStart = {
    x: 0,
    y: first.y - first.x * slopeStart,
    value: first.value
  };
  const ghostEnd = {
    x: totalWidth,
    y: last.y + (totalWidth - last.x) * slopeEnd,
    value: last.value
  };
  return [ghostStart, ...points, ghostEnd];
}
function buildPath(points, options) {
  const smoothValue = typeof options.smooth === 'boolean' ? options.smooth ? 8 : 0 : Number(options.smooth ?? 0);

  // genRoundedPath mutates via shift(); slice defensively so callers don't have to
  const copy = points.slice();
  if (options.smoothMode === 'monotone') {
    return genMonotonePath(copy, smoothValue, options.fill, options.height);
  }
  return genRoundedPath(copy, smoothValue, options.fill, options.height, options.animation);
}

// Types

const makeVBarlineProps = propsFactory({
  autoLineWidth: Boolean,
  ...makeLineProps()
}, 'VBarline');
const VBarline = genericComponent()({
  name: 'VBarline',
  inheritAttrs: false,
  props: makeVBarlineProps(),
  emits: {
    'update:currentIndex': _index => true
  },
  setup(props, {
    slots,
    attrs,
    emit
  }) {
    const uid = useId();
    const id = computed(() => props.id || `barline-${uid}`);
    const autoDrawDuration = computed(() => Number(props.autoDrawDuration) || 500);
    const hasDrawn = ref(false);
    const clipRects = shallowRef([]);
    const animationDuration = computed(() => typeof props.animation === 'object' ? props.animation.duration ?? 300 : 300);
    const animationEasing = computed(() => typeof props.animation === 'object' ? props.animation.easing ?? 'ease' : 'ease');
    const hasLabels = computed(() => {
      return Boolean(props.showLabels || props.labels.length > 0 || !!slots?.label);
    });
    const lineWidth = computed(() => parseFloat(props.lineWidth) || 4);
    const items = computed(() => props.modelValue.map(item => getPropertyFromItem(item, props.itemValue, item)));
    const totalWidth = computed(() => Math.max(items.value.length * lineWidth.value, Number(props.width)));
    const boundary = computed(() => {
      return {
        minX: 0,
        maxX: totalWidth.value,
        minY: 0,
        maxY: parseInt(props.height, 10)
      };
    });
    function genBars(values, boundary) {
      const {
        minX,
        maxX,
        minY,
        maxY
      } = boundary;
      const totalValues = values.length;
      let maxValue = props.max != null ? Number(props.max) : Math.max(...values);
      let minValue = props.min != null ? Number(props.min) : Math.min(...values);
      if (minValue > 0 && props.min == null) minValue = 0;
      if (maxValue < 0 && props.max == null) maxValue = 0;
      const gridX = maxX / (totalValues === 1 ? 2 : totalValues);
      const gridY = (maxY - minY) / (maxValue - minValue || 1);
      const horizonY = maxY - Math.abs(minValue * gridY);
      return values.map((value, index) => {
        const height = Math.abs(gridY * value);
        return {
          x: minX + index * gridX,
          y: horizonY - height + Number(value < 0) * height,
          height,
          value
        };
      });
    }
    const bars = computed(() => genBars(items.value, boundary.value));
    const prevBarCount = ref(0);
    function applyTransition(el, duration, easing) {
      el.style.transition = `y ${duration}ms ${easing}, height ${duration}ms ${easing}`;
    }
    function collapseNewBars(bars, fromIndex, duration, easing) {
      for (let i = fromIndex; i < bars.length; i++) {
        const el = clipRects.value[i];
        if (!el) continue;

        // Snap to collapsed at bar's baseline
        el.style.transition = 'none';
        el.setAttribute('y', String(bars[i].y + bars[i].height));
        el.setAttribute('height', '0');
        el.getBoundingClientRect();

        // Animate to final state
        applyTransition(el, duration, easing);
        el.setAttribute('y', String(bars[i].y));
        el.setAttribute('height', String(bars[i].height));
      }
    }
    function applyBarsTransition(oldCount) {
      if (!props.animation) return;
      clipRects.value.forEach(el => {
        if (el) applyTransition(el, animationDuration.value, animationEasing.value);
      });
      if (bars.value.length > oldCount && oldCount > 0) {
        collapseNewBars(bars.value, oldCount, animationDuration.value, animationEasing.value);
      }
    }
    watch(() => props.modelValue, async () => {
      await nextTick();
      if (PREFERS_REDUCED_MOTION() || !clipRects.value.length) return;
      const oldCount = prevBarCount.value;
      prevBarCount.value = bars.value.length;

      // Animation-only mode (no auto-draw), or draw-once after first draw: just ensure transition is set
      if (!props.autoDraw || props.autoDraw === 'once' && hasDrawn.value) {
        applyBarsTransition(oldCount);
        return;
      }
      hasDrawn.value = true;
      const shouldDrawOnce = props.autoDraw === 'once';
      clipRects.value.forEach((el, i) => {
        const bar = bars.value[i];
        if (!el || !bar) return;

        // Snap to collapsed state
        el.style.transition = 'none';
        el.setAttribute('y', String(bar.y + bar.height));
        el.setAttribute('height', '0');
        el.getBoundingClientRect();

        // Animate to final state
        applyTransition(el, autoDrawDuration.value, props.autoDrawEasing);
        el.setAttribute('y', String(bar.y));
        el.setAttribute('height', String(bar.height));

        // After initial draw, switch to animation timing for subsequent changes
        if (shouldDrawOnce && props.animation) {
          el.addEventListener('transitionend', () => {
            applyTransition(el, animationDuration.value, animationEasing.value);
          }, {
            once: true
          });
        }
      });
    }, {
      immediate: true
    });
    const parsedLabels = computed(() => {
      return bars.value.map((bar, i) => ({
        x: bar.x,
        value: String(props.labels[i] ?? bar.value)
      }));
    });
    const offsetX = computed(() => bars.value.length === 1 ? (boundary.value.maxX - lineWidth.value) / 2 : (Math.abs(bars.value[0].x - bars.value[1].x) - lineWidth.value) / 2);
    const smooth = computed(() => typeof props.smooth === 'boolean' ? props.smooth ? 2 : 0 : Number(props.smooth));
    const columnWidth = computed(() => {
      const len = bars.value.length;
      return totalWidth.value / (len === 1 ? 2 : len);
    });

    // Hover / tooltip state
    const svgRef = shallowRef(null);
    const currentIndex = shallowRef(null);
    const tooltipVisible = shallowRef(false);
    const targetX = shallowRef(0);
    const targetY = shallowRef(0);
    const targetHeight = shallowRef(0);
    watch(currentIndex, index => {
      if (index === null) return;
      const bar = bars.value[index];
      if (!bar) return;
      targetX.value = bar.x + offsetX.value;
      targetY.value = bar.y;
      targetHeight.value = bar.height;
    });
    const transitionOptions = {
      duration: 150,
      transition: easingPatterns.easeOutQuad
    };
    const animatedX = useTransition(targetX, transitionOptions);
    const animatedY = useTransition(targetY, transitionOptions);
    const tooltipTarget = computed(() => {
      if (currentIndex.value === null || !svgRef.value) return undefined;
      const ctm = svgRef.value.getScreenCTM();
      if (!ctm) return undefined;
      const svgPoint = svgRef.value.createSVGPoint();
      svgPoint.x = animatedX.value + lineWidth.value / 2;
      svgPoint.y = animatedY.value;
      const {
        x,
        y
      } = svgPoint.matrixTransform(ctm);
      return [x, y];
    });
    const tooltipConfig = computed(() => ({
      showCrosshair: false,
      titleFormat: item => String(item.value),
      ...(typeof props.tooltip === 'object' ? props.tooltip : {})
    }));
    let frame = -1;
    function onSvgMousemove(e) {
      const target = e.currentTarget;
      cancelAnimationFrame(frame);
      frame = requestAnimationFrame(() => {
        const rect = target.getBoundingClientRect();
        const svgX = (e.clientX - rect.left) / rect.width * totalWidth.value;
        let nearest = 0;
        let minDist = Infinity;
        bars.value.forEach((bar, i) => {
          const barCenter = bar.x + offsetX.value + lineWidth.value / 2;
          const dist = Math.abs(barCenter - svgX);
          if (dist < minDist) {
            minDist = dist;
            nearest = i;
          }
        });
        currentIndex.value = nearest;
        emit('update:currentIndex', nearest);
        tooltipVisible.value = true;
      });
    }
    function onSvgMouseleave() {
      cancelAnimationFrame(frame);
      tooltipVisible.value = false;
      if (!props.tooltip) {
        currentIndex.value = null;
        emit('update:currentIndex', null);
      }
    }
    function onTooltipAfterLeave() {
      currentIndex.value = null;
      emit('update:currentIndex', null);
    }
    function setIndex(index) {
      currentIndex.value = index;
      emit('update:currentIndex', index);
      tooltipVisible.value = index !== null;
    }
    function onSvgFocus() {
      if (!bars.value.length) return;
      setIndex(bars.value.length - 1);
    }
    function onSvgBlur() {
      tooltipVisible.value = false;
      if (!props.tooltip) {
        setIndex(null);
      }
    }
    function onSvgKeydown(e) {
      if (!bars.value.length) return;
      const len = bars.value.length;
      if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
        e.preventDefault();
        const direction = e.key === 'ArrowLeft' ? -1 : 1;
        const current = currentIndex.value ?? (direction === 1 ? -1 : len);
        const next = Math.max(0, Math.min(len - 1, current + direction));
        setIndex(next);
      }
    }
    useRender(() => {
      const gradientData = !props.gradient.slice().length ? [''] : props.gradient.slice().reverse();
      return createElementVNode(Fragment, null, [createElementVNode("svg", mergeProps({
        "ref": svgRef,
        "display": "block",
        "tabindex": props.interactive ? 0 : undefined,
        "onMousemove": props.interactive ? onSvgMousemove : undefined,
        "onMouseleave": props.interactive ? onSvgMouseleave : undefined,
        "onFocus": props.interactive ? onSvgFocus : undefined,
        "onBlur": props.interactive ? onSvgBlur : undefined,
        "onKeydown": props.interactive ? onSvgKeydown : undefined
      }, attrs), [createElementVNode("defs", null, [createElementVNode("linearGradient", {
        "id": id.value,
        "gradientUnits": "userSpaceOnUse",
        "x1": props.gradientDirection === 'left' ? '100%' : '0',
        "y1": props.gradientDirection === 'top' ? '100%' : '0',
        "x2": props.gradientDirection === 'right' ? '100%' : '0',
        "y2": props.gradientDirection === 'bottom' ? '100%' : '0'
      }, [gradientData.map((color, index) => createElementVNode("stop", {
        "offset": index / Math.max(gradientData.length - 1, 1),
        "stop-color": color || 'currentColor'
      }, null))])]), createElementVNode("clipPath", {
        "id": `${id.value}-clip`
      }, [bars.value.map((item, i) => createElementVNode("rect", {
        "ref": el => {
          if (el) clipRects.value[i] = el;
        },
        "x": item.x + offsetX.value,
        "y": item.y,
        "width": lineWidth.value,
        "height": item.height,
        "rx": smooth.value,
        "ry": smooth.value
      }, null))]), hasLabels.value && createElementVNode("g", {
        "key": "labels",
        "style": {
          textAnchor: 'middle',
          dominantBaseline: 'mathematical',
          fill: 'currentColor'
        }
      }, [parsedLabels.value.map((item, i) => createElementVNode("text", {
        "x": item.x + offsetX.value + lineWidth.value / 2,
        "y": parseInt(props.height, 10) - 2 + (parseInt(props.labelSize, 10) || 7 * 0.75),
        "font-size": Number(props.labelSize) || 7
      }, [slots.label?.({
        index: i,
        value: item.value
      }) ?? item.value]))]), props.interactive && currentIndex.value !== null && createElementVNode("rect", {
        "key": "highlight",
        "x": animatedX.value - offsetX.value,
        "y": 0,
        "width": columnWidth.value,
        "height": props.height,
        "fill": "currentColor",
        "opacity": 0.1,
        "pointer-events": "none"
      }, null), createElementVNode("g", {
        "clip-path": `url(#${id.value}-clip)`,
        "fill": `url(#${id.value})`
      }, [createElementVNode("rect", {
        "x": 0,
        "y": 0,
        "width": totalWidth.value,
        "height": props.height
      }, null)])]), !!props.tooltip && createVNode(VSparklineTooltip, {
        "key": "tooltip",
        "modelValue": tooltipVisible.value,
        "target": tooltipTarget.value,
        "index": currentIndex.value,
        "value": currentIndex.value !== null ? bars.value[currentIndex.value].value : 0,
        "offset": tooltipConfig.value.offset,
        "contentClass": tooltipConfig.value.class,
        "titleFormat": tooltipConfig.value.titleFormat,
        "location": "top center",
        "onAfterLeave": onTooltipAfterLeave
      }, {
        default: slots.tooltip
      })]);
    });
  }
});

// Types

const makeVTrendlineProps = propsFactory({
  fill: Boolean,
  ...makeLineProps()
}, 'VTrendline');
const VTrendline = genericComponent()({
  name: 'VTrendline',
  inheritAttrs: false,
  props: makeVTrendlineProps(),
  emits: {
    'update:currentIndex': _index => true
  },
  setup(props, {
    slots,
    attrs,
    emit
  }) {
    const uid = useId();
    const id = computed(() => props.id || `trendline-${uid}`);
    const autoDrawDuration = computed(() => Number(props.autoDrawDuration) || (props.fill ? 500 : 2000));
    const hasDrawn = ref(false);
    const fillPath = ref(null);
    const strokePath = ref(null);
    const animationDuration = computed(() => typeof props.animation === 'object' ? props.animation.duration ?? 300 : 300);
    const animationEasing = computed(() => typeof props.animation === 'object' ? props.animation.easing ?? 'ease' : 'ease');
    function genPoints(values, boundary) {
      const {
        minX,
        maxX,
        minY,
        maxY
      } = boundary;
      if (values.length === 1) {
        values = [values[0], values[0]];
      }
      const totalValues = values.length;
      const maxValue = props.max != null ? Number(props.max) : Math.max(...values);
      const minValue = props.min != null ? Number(props.min) : Math.min(...values);
      const gridX = (maxX - minX) / (totalValues - 1);
      const gridY = (maxY - minY) / (maxValue - minValue || 1);
      return values.map((value, index) => ({
        x: minX + index * gridX,
        y: maxY - (value - minValue) * gridY,
        value
      }));
    }
    const hasLabels = computed(() => {
      return Boolean(props.showLabels || props.labels.length > 0 || !!slots?.label);
    });
    const totalWidth = computed(() => Number(props.width));
    const boundary = computed(() => {
      const padding = Number(props.padding);
      return {
        minX: padding,
        maxX: totalWidth.value - padding,
        minY: padding,
        maxY: parseInt(props.height, 10) - padding
      };
    });
    const items = computed(() => props.modelValue.map(item => getPropertyFromItem(item, props.itemValue, item)));

    // When animation is enabled, resample to a consistent point count
    // so the SVG path always has the same number of commands for CSS d transitions
    const sampleCount = ref(0);

    // When sampleCount grows (new dataset is longer than any seen before),
    // manually patch the DOM path to old-data-at-new-count before Vue re-renders,
    // so the browser sees same-structure paths and can CSS-transition between them.
    watch(items, (newVal, oldVal) => {
      if (!props.animation) return;
      const prevCount = sampleCount.value;
      if (newVal.length > prevCount) {
        sampleCount.value = newVal.length;
        if (prevCount > 0 && oldVal) {
          const oldResampled = resample(oldVal, sampleCount.value);
          for (const [pathRef, fill] of [[strokePath, false], [fillPath, true]]) {
            const path = pathRef.value;
            if (!path) continue;
            path.setAttribute('d', genPath(oldResampled, fill));
          }
        }
      }
    }, {
      immediate: true
    });
    const normalizedItems = computed(() => {
      if (!props.animation || !sampleCount.value || items.value.length === sampleCount.value) {
        return items.value;
      }
      return resample(items.value, sampleCount.value);
    });
    const points = computed(() => genPoints(normalizedItems.value, boundary.value));
    const extendedPoints = computed(() => extendPoints(points.value, props.inset, totalWidth.value));
    function genPath(input, fill) {
      const points = typeof input[0] === 'number' ? extendPoints(genPoints(input, boundary.value), props.inset, totalWidth.value) : input;
      return buildPath(points, {
        smooth: props.smooth,
        smoothMode: props.smoothMode,
        height: parseInt(props.height, 10),
        fill,
        animation: !!props.animation
      });
    }
    const parsedLabels = computed(() => {
      const labels = [];
      const len = points.value.length;
      for (let i = 0; labels.length < len; i++) {
        const point = points.value[i];
        let value = props.labels[i];
        if (!value) {
          value = point.value;
        }
        labels.push({
          x: point.x,
          value: String(value)
        });
      }
      return labels;
    });
    function applyDTransition(path, duration, easing) {
      path.style.transition = `d ${duration}ms ${easing}`;
    }
    watch(() => props.modelValue, async () => {
      await nextTick();
      if (PREFERS_REDUCED_MOTION()) return;

      // Animation-only mode (no auto-draw): just ensure d transition is set
      if (!props.autoDraw) {
        if (props.animation && strokePath.value) {
          for (const path of [fillPath.value, strokePath.value]) {
            if (path) applyDTransition(path, animationDuration.value, animationEasing.value);
          }
        }
        return;
      }
      if (!strokePath.value) return;
      if (props.autoDraw === 'once' && hasDrawn.value) return;
      hasDrawn.value = true;
      const shouldDrawOnce = props.autoDraw === 'once';
      if (!props.fill) {
        const path = strokePath.value;
        const length = path.getTotalLength();
        path.style.transition = 'none';
        path.style.strokeDasharray = `${length}`;
        path.style.strokeDashoffset = `${length}`;
        path.getBoundingClientRect();
        const dTransition = props.animation ? `, d ${animationDuration.value}ms ${animationEasing.value}` : '';
        path.style.transition = `stroke-dashoffset ${autoDrawDuration.value}ms ${props.autoDrawEasing}${dTransition}`;
        path.style.strokeDashoffset = '0';
        if (shouldDrawOnce) {
          path.addEventListener('transitionend', e => {
            if (e.propertyName !== 'stroke-dashoffset') return;
            path.style.strokeDasharray = '';
            path.style.strokeDashoffset = '';
            if (props.animation) {
              applyDTransition(path, animationDuration.value, animationEasing.value);
            } else {
              path.style.transition = '';
            }
          }, {
            once: true
          });
        }
      } else {
        for (const path of [fillPath.value, strokePath.value]) {
          if (!path) continue;
          path.style.transformOrigin = 'bottom center';
          path.style.transition = 'none';
          path.style.transform = `scaleY(0)`;
          path.getBoundingClientRect();
          const dTransition = props.animation ? `, d ${animationDuration.value}ms ${animationEasing.value}` : '';
          path.style.transition = `transform ${autoDrawDuration.value}ms ${props.autoDrawEasing}${dTransition}`;
          path.style.transform = `scaleY(1)`;
          if (shouldDrawOnce) {
            path.addEventListener('transitionend', e => {
              if (e.propertyName !== 'transform') return;
              path.style.transform = '';
              path.style.transformOrigin = '';
              if (props.animation) {
                applyDTransition(path, animationDuration.value, animationEasing.value);
              } else {
                path.style.transition = '';
              }
            }, {
              once: true
            });
          }
        }
      }
    }, {
      immediate: true
    });

    // Hover / tooltip state
    const svgRef = shallowRef(null);
    const currentIndex = shallowRef(null);
    const tooltipVisible = shallowRef(false);
    const currentPoint = computed(() => currentIndex.value !== null ? points.value[currentIndex.value] : null);
    function getPathLengthAtX(svgPath, targetX) {
      const total = svgPath.getTotalLength();
      let low = 0;
      let high = total;
      // 32 bisections ≈ sub-pixel accuracy on any reasonable chart width
      for (let i = 0; i < 32; i++) {
        const mid = (low + high) / 2;
        if (svgPath.getPointAtLength(mid).x < targetX) low = mid;else high = mid;
      }
      return (low + high) / 2;
    }
    const markerPathLength = shallowRef(0);
    watch(currentPoint, point => {
      if (!point || !strokePath.value) return;
      markerPathLength.value = getPathLengthAtX(strokePath.value, point.x);
    });
    const animatedLength = useTransition(markerPathLength, {
      duration: 150,
      transition: easingPatterns.easeOutQuad
    });
    const markerPoint = computed(() => {
      const {
        x,
        y
      } = strokePath.value?.getPointAtLength(animatedLength.value) ?? {
        x: 0,
        y: 0
      };
      return {
        x,
        y
      };
    });
    const tooltipTarget = computed(() => {
      if (!currentPoint.value || !svgRef.value) return undefined;
      const matrix = svgRef.value.getScreenCTM();
      if (!matrix) return undefined;
      const svgPoint = svgRef.value.createSVGPoint();
      svgPoint.x = markerPoint.value.x;
      svgPoint.y = markerPoint.value.y;
      const {
        x,
        y
      } = svgPoint.matrixTransform(matrix);
      return [x, y];
    });
    const tooltipConfig = computed(() => ({
      showCrosshair: true,
      offset: 16,
      titleFormat: item => String(item.value),
      ...(typeof props.tooltip === 'object' ? props.tooltip : {})
    }));
    let frame = -1;
    function onSvgMousemove(e) {
      const target = e.currentTarget;
      cancelAnimationFrame(frame);
      frame = requestAnimationFrame(() => {
        const rect = target.getBoundingClientRect();
        const svgX = (e.clientX - rect.left) / rect.width * Number(props.width);
        let nearest = 0;
        let minDist = Infinity;
        points.value.forEach((point, index) => {
          const dist = Math.abs(point.x - svgX);
          if (dist < minDist) {
            minDist = dist;
            nearest = index;
          }
        });
        currentIndex.value = nearest;
        emit('update:currentIndex', nearest);
        tooltipVisible.value = true;
      });
    }
    function onSvgMouseleave() {
      cancelAnimationFrame(frame);
      tooltipVisible.value = false;
      if (!props.tooltip) {
        currentIndex.value = null;
        emit('update:currentIndex', null);
      }
    }
    function onTooltipAfterLeave() {
      currentIndex.value = null;
      emit('update:currentIndex', null);
    }
    function setIndex(index) {
      currentIndex.value = index;
      emit('update:currentIndex', index);
      tooltipVisible.value = index !== null;
    }
    function onSvgFocus() {
      if (!points.value.length) return;
      setIndex(points.value.length - 1);
    }
    function onSvgBlur() {
      tooltipVisible.value = false;
      if (!props.tooltip) {
        setIndex(null);
      }
    }
    function onSvgKeydown(e) {
      if (!points.value.length) return;
      const length = points.value.length;
      if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
        e.preventDefault();
        const direction = e.key === 'ArrowLeft' ? -1 : 1;
        const current = currentIndex.value ?? (direction === 1 ? -1 : length);
        const next = Math.max(0, Math.min(length - 1, current + direction));
        setIndex(next);
      }
    }
    useRender(() => {
      const gradientData = !props.gradient.slice().length ? [''] : props.gradient.slice().reverse();
      const markerRadius = (parseFloat(props.markerSize) || 8) / 2;
      return createElementVNode(Fragment, null, [createElementVNode("svg", mergeProps({
        "ref": svgRef,
        "display": "block",
        "stroke-width": parseFloat(props.lineWidth) ?? 4,
        "tabindex": props.interactive ? 0 : undefined,
        "onMousemove": props.interactive ? onSvgMousemove : undefined,
        "onMouseleave": props.interactive ? onSvgMouseleave : undefined,
        "onFocus": props.interactive ? onSvgFocus : undefined,
        "onBlur": props.interactive ? onSvgBlur : undefined,
        "onKeydown": props.interactive ? onSvgKeydown : undefined
      }, attrs), [createElementVNode("defs", null, [createElementVNode("linearGradient", {
        "id": id.value,
        "gradientUnits": "userSpaceOnUse",
        "x1": props.gradientDirection === 'left' ? '100%' : '0',
        "y1": props.gradientDirection === 'top' ? '100%' : '0',
        "x2": props.gradientDirection === 'right' ? '100%' : '0',
        "y2": props.gradientDirection === 'bottom' ? '100%' : '0'
      }, [gradientData.map((color, index) => createElementVNode("stop", {
        "offset": index / Math.max(gradientData.length - 1, 1),
        "stop-color": color || 'currentColor'
      }, null))])]), hasLabels.value && createElementVNode("g", {
        "key": "labels",
        "style": {
          textAnchor: 'middle',
          dominantBaseline: 'mathematical',
          fill: 'currentColor'
        }
      }, [parsedLabels.value.map((item, i) => createElementVNode("text", {
        "x": item.x,
        "y": parseInt(props.height, 10) - 4 + (parseInt(props.labelSize, 10) || 7 * 0.75),
        "font-size": Number(props.labelSize) || 7
      }, [slots.label?.({
        index: i,
        value: item.value
      }) ?? item.value]))]), createElementVNode("path", {
        "key": "fill",
        "ref": props.fill ? fillPath : strokePath,
        "d": genPath(extendedPoints.value, props.fill),
        "fill": props.fill ? `url(#${id.value})` : 'none',
        "stroke": props.fill ? 'none' : `url(#${id.value})`
      }, null), props.fill && createElementVNode("path", {
        "key": "trendline",
        "ref": strokePath,
        "d": genPath(extendedPoints.value, false),
        "fill": "none",
        "stroke": "currentColor"
      }, null), props.showMarkers && createElementVNode("g", {
        "key": "markers"
      }, [points.value.map((point, i) => createElementVNode("circle", {
        "key": i,
        "cx": point.x,
        "cy": point.y,
        "r": markerRadius,
        "fill": "currentColor",
        "stroke": props.markerStroke,
        "stroke-width": 2,
        "pointer-events": "none"
      }, null))]), props.interactive && currentPoint.value && createElementVNode("g", {
        "key": "hover",
        "pointer-events": "none"
      }, [tooltipConfig.value.showCrosshair && createElementVNode("line", {
        "key": "crosshair-line",
        "x1": markerPoint.value.x,
        "y1": props.inset ? 0 : boundary.value.minY,
        "x2": markerPoint.value.x,
        "y2": props.inset ? parseInt(props.height, 10) : boundary.value.maxY,
        "stroke": "currentColor",
        "stroke-width": 1,
        "stroke-dasharray": "4 2",
        "opacity": 0.5
      }, null), createElementVNode("circle", {
        "key": "marker",
        "cx": markerPoint.value.x,
        "cy": markerPoint.value.y,
        "r": markerRadius,
        "fill": "currentColor",
        "stroke": props.markerStroke,
        "stroke-width": 2
      }, null)])]), !!props.tooltip && createVNode(VSparklineTooltip, {
        "key": "tooltip",
        "modelValue": tooltipVisible.value,
        "target": tooltipTarget.value,
        "index": currentIndex.value,
        "value": currentIndex.value !== null ? points.value[currentIndex.value].value : 0,
        "offset": tooltipConfig.value.offset,
        "contentClass": tooltipConfig.value.class,
        "titleFormat": tooltipConfig.value.titleFormat,
        "onAfterLeave": onTooltipAfterLeave
      }, {
        default: slots.tooltip
      })]);
    });
  }
});

// Types

const makeVSparklineProps = propsFactory({
  type: {
    type: String,
    default: 'trend'
  },
  ...makeVBarlineProps(),
  ...makeVTrendlineProps()
}, 'VSparkline');
const VSparkline = genericComponent()({
  name: 'VSparkline',
  props: makeVSparklineProps(),
  emits: {
    'update:currentIndex': _index => true
  },
  setup(props, {
    slots,
    emit
  }) {
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.color);
    const hasLabels = computed(() => {
      return Boolean(props.showLabels || props.labels.length > 0 || !!slots?.label);
    });
    const totalHeight = computed(() => {
      let height = parseInt(props.height, 10);
      if (hasLabels.value) height += parseInt(props.labelSize, 10) * 1.5;
      return height;
    });
    useRender(() => {
      const Tag = props.type === 'trend' ? VTrendline : VBarline;
      const lineProps = props.type === 'trend' ? VTrendline.filterProps(props) : VBarline.filterProps(props);
      return createVNode(Tag, mergeProps({
        "key": props.type,
        "class": textColorClasses.value,
        "style": textColorStyles.value,
        "viewBox": `0 0 ${props.width} ${totalHeight.value}`
      }, lineProps, {
        "onUpdate:currentIndex": v => emit('update:currentIndex', v)
      }), slots);
    });
  }
});

// Types

const makeVSpeedDialProps = propsFactory({
  ...makeComponentProps(),
  ...makeVMenuProps({
    offset: 8,
    minWidth: 0,
    openDelay: 0,
    closeDelay: 100,
    location: 'top center',
    transition: 'scale-transition'
  })
}, 'VSpeedDial');
const VSpeedDial = genericComponent()({
  name: 'VSpeedDial',
  props: makeVSpeedDialProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const model = useProxiedModel(props, 'modelValue');
    const menuRef = ref();
    const location = computed(() => {
      const [y, x = 'center'] = props.location?.split(' ') ?? [];
      return `${y} ${x}`;
    });
    const locationClasses = computed(() => ({
      [`v-speed-dial__content--${location.value.replace(' ', '-')}`]: true
    }));
    useRender(() => {
      const menuProps = VMenu.filterProps(props);
      return createVNode(VMenu, mergeProps(menuProps, {
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "class": props.class,
        "style": props.style,
        "contentClass": ['v-speed-dial__content', locationClasses.value, props.contentClass],
        "location": location.value,
        "ref": menuRef,
        "transition": "fade-transition"
      }), {
        ...slots,
        default: slotProps => createVNode(VDefaultsProvider, {
          "defaults": {
            VBtn: {
              size: 'small'
            }
          }
        }, {
          default: () => [createVNode(MaybeTransition, {
            "appear": true,
            "group": true,
            "transition": props.transition
          }, {
            default: () => [slots.default?.(slotProps)]
          })]
        })
      });
    });
    return {};
  }
});

// Types

const VStepperSymbol = Symbol.for('vuetify:v-stepper');

// Types

const makeVStepperActionsProps = propsFactory({
  color: String,
  disabled: {
    type: [Boolean, String],
    default: false
  },
  prevText: {
    type: String,
    default: '$vuetify.stepper.prev'
  },
  nextText: {
    type: String,
    default: '$vuetify.stepper.next'
  }
}, 'VStepperActions');
const VStepperActions = genericComponent()({
  name: 'VStepperActions',
  props: makeVStepperActionsProps(),
  emits: {
    'click:prev': () => true,
    'click:next': () => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    function onClickPrev() {
      emit('click:prev');
    }
    function onClickNext() {
      emit('click:next');
    }
    useRender(() => {
      const prevSlotProps = {
        onClick: onClickPrev
      };
      const nextSlotProps = {
        onClick: onClickNext
      };
      return createElementVNode("div", {
        "class": "v-stepper-actions"
      }, [createVNode(VDefaultsProvider, {
        "defaults": {
          VBtn: {
            disabled: ['prev', true].includes(props.disabled),
            text: t(props.prevText),
            variant: 'text'
          }
        }
      }, {
        default: () => [slots.prev?.({
          props: prevSlotProps
        }) ?? createVNode(VBtn, prevSlotProps, null)]
      }), createVNode(VDefaultsProvider, {
        "defaults": {
          VBtn: {
            color: props.color,
            disabled: ['next', true].includes(props.disabled),
            text: t(props.nextText),
            variant: 'tonal'
          }
        }
      }, {
        default: () => [slots.next?.({
          props: nextSlotProps
        }) ?? createVNode(VBtn, nextSlotProps, null)]
      })]);
    });
    return {};
  }
});

// Utilities
const VStepperHeader = createSimpleFunctional('v-stepper-header');

// Types

const makeStepperItemProps = propsFactory({
  color: String,
  title: String,
  subtitle: String,
  complete: Boolean,
  completeIcon: {
    type: IconValue,
    default: '$complete'
  },
  editable: Boolean,
  editIcon: {
    type: IconValue,
    default: '$edit'
  },
  error: Boolean,
  errorIcon: {
    type: IconValue,
    default: '$error'
  },
  icon: IconValue,
  ripple: {
    type: [Boolean, Object],
    default: true
  },
  rules: {
    type: Array,
    default: () => []
  }
}, 'StepperItem');
const makeVStepperItemProps = propsFactory({
  ...makeStepperItemProps(),
  ...makeGroupItemProps()
}, 'VStepperItem');
const VStepperItem = genericComponent()({
  name: 'VStepperItem',
  directives: {
    vRipple: Ripple
  },
  props: makeVStepperItemProps(),
  emits: {
    'group:selected': val => true
  },
  setup(props, {
    slots
  }) {
    const group = useGroupItem(props, VStepperSymbol, true);
    const step = computed(() => group?.value.value ?? props.value);
    const isValid = computed(() => props.rules.every(handler => handler() === true));
    const isClickable = computed(() => !props.disabled && props.editable);
    const canEdit = computed(() => !props.disabled && props.editable);
    const hasError = computed(() => props.error || !isValid.value);
    const hasCompleted = computed(() => props.complete || props.rules.length > 0 && isValid.value);
    const icon = computed(() => {
      if (hasError.value) return props.errorIcon;
      if (hasCompleted.value) return props.completeIcon;
      if (group.isSelected.value && props.editable) return props.editIcon;
      return props.icon;
    });
    const slotProps = computed(() => ({
      canEdit: canEdit.value,
      hasError: hasError.value,
      hasCompleted: hasCompleted.value,
      title: props.title,
      subtitle: props.subtitle,
      step: step.value,
      value: props.value
    }));
    useRender(() => {
      const hasColor = (!group || group.isSelected.value || hasCompleted.value || canEdit.value) && !hasError.value && !props.disabled;
      const hasTitle = !!(props.title != null || slots.title);
      const hasSubtitle = !!(props.subtitle != null || slots.subtitle);
      function onClick() {
        group?.toggle();
      }
      return withDirectives(createElementVNode("button", {
        "class": normalizeClass(['v-stepper-item', {
          'v-stepper-item--complete': hasCompleted.value,
          'v-stepper-item--disabled': props.disabled,
          'v-stepper-item--error': hasError.value
        }, group?.selectedClass.value]),
        "disabled": !props.editable,
        "type": "button",
        "onClick": onClick
      }, [isClickable.value && genOverlays(true, 'v-stepper-item'), createVNode(VAvatar, {
        "key": "stepper-avatar",
        "class": "v-stepper-item__avatar",
        "color": hasColor ? props.color : undefined,
        "size": 24
      }, {
        default: () => [slots.icon?.(slotProps.value) ?? (icon.value ? createVNode(VIcon, {
          "icon": icon.value
        }, null) : step.value)]
      }), createElementVNode("div", {
        "class": "v-stepper-item__content"
      }, [hasTitle && createElementVNode("div", {
        "key": "title",
        "class": "v-stepper-item__title"
      }, [slots.title?.(slotProps.value) ?? props.title]), hasSubtitle && createElementVNode("div", {
        "key": "subtitle",
        "class": "v-stepper-item__subtitle"
      }, [slots.subtitle?.(slotProps.value) ?? props.subtitle]), slots.default?.(slotProps.value)])]), [[Ripple, props.editable && props.ripple, null]]);
    });
    return {};
  }
});

// Types

const makeVStepperWindowProps = propsFactory({
  ...omit(makeVWindowProps(), ['continuous', 'nextIcon', 'prevIcon', 'showArrows', 'touch', 'mandatory'])
}, 'VStepperWindow');
const VStepperWindow = genericComponent()({
  name: 'VStepperWindow',
  props: makeVStepperWindowProps(),
  emits: {
    'update:modelValue': v => true
  },
  setup(props, {
    slots
  }) {
    const group = inject$1(VStepperSymbol, null);
    const _model = useProxiedModel(props, 'modelValue');
    const model = computed({
      get() {
        // Always return modelValue if defined
        // or if not within a VStepper group
        if (_model.value != null || !group) return _model.value;

        // If inside of a VStepper, find the currently selected
        // item by id. Item value may be assigned by its index
        return group.items.value.find(item => group.selected.value.includes(item.id))?.value;
      },
      set(val) {
        _model.value = val;
      }
    });
    useRender(() => {
      const windowProps = VWindow.filterProps(props);
      return createVNode(VWindow, mergeProps({
        "_as": "VStepperWindow"
      }, windowProps, {
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "class": ['v-stepper-window', props.class],
        "style": props.style,
        "mandatory": false,
        "touch": false
      }), slots);
    });
    return {};
  }
});

const makeVStepperWindowItemProps = propsFactory({
  ...makeVWindowItemProps()
}, 'VStepperWindowItem');
const VStepperWindowItem = genericComponent()({
  name: 'VStepperWindowItem',
  props: makeVStepperWindowItemProps(),
  setup(props, {
    slots
  }) {
    useRender(() => {
      const windowItemProps = VWindowItem.filterProps(props);
      return createVNode(VWindowItem, mergeProps({
        "_as": "VStepperWindowItem"
      }, windowItemProps, {
        "class": ['v-stepper-window-item', props.class],
        "style": props.style
      }), slots);
    });
    return {};
  }
});

// Types

const makeStepperProps = propsFactory({
  altLabels: Boolean,
  bgColor: String,
  completeIcon: IconValue,
  editIcon: IconValue,
  editable: Boolean,
  errorIcon: IconValue,
  hideActions: Boolean,
  items: {
    type: Array,
    default: () => []
  },
  itemTitle: {
    type: [String, Array, Function],
    default: 'title'
  },
  itemValue: {
    type: [String, Array, Function],
    default: 'value'
  },
  itemProps: {
    type: [Boolean, String, Array, Function],
    default: 'props'
  },
  nonLinear: Boolean,
  flat: Boolean,
  ...makeDisplayProps()
}, 'Stepper');
const makeVStepperProps = propsFactory({
  ...makeStepperProps(),
  ...makeGroupProps({
    mandatory: 'force',
    selectedClass: 'v-stepper-item--selected'
  }),
  ...makeVSheetProps(),
  ...pick(makeVStepperActionsProps(), ['prevText', 'nextText'])
}, 'VStepper');
const VStepper = genericComponent()({
  name: 'VStepper',
  props: makeVStepperProps(),
  emits: {
    'update:modelValue': v => true
  },
  setup(props, {
    slots
  }) {
    const {
      items: _items,
      next,
      prev,
      selected
    } = useGroup(props, VStepperSymbol);
    const {
      displayClasses,
      mobile
    } = useDisplay(props);
    const {
      completeIcon,
      editIcon,
      errorIcon,
      color,
      editable,
      prevText,
      nextText
    } = toRefs(props);
    const items = computed(() => props.items.map((item, index) => {
      const title = getPropertyFromItem(item, props.itemTitle, item);
      const value = getPropertyFromItem(item, props.itemValue, index + 1);
      const itemProps = props.itemProps === true ? item : getPropertyFromItem(item, props.itemProps);
      const _props = {
        title,
        value,
        ...itemProps
      };
      return {
        title: _props.title,
        value: _props.value,
        props: _props,
        raw: item
      };
    }));
    const activeIndex = computed(() => {
      return _items.value.findIndex(item => selected.value.includes(item.id));
    });
    const disabled = computed(() => {
      if (props.disabled) return props.disabled;
      if (activeIndex.value === 0) return 'prev';
      if (activeIndex.value === _items.value.length - 1) return 'next';
      return false;
    });
    provideDefaults({
      VStepperItem: {
        editable,
        errorIcon,
        completeIcon,
        editIcon,
        prevText,
        nextText
      },
      VStepperActions: {
        color,
        disabled,
        prevText,
        nextText
      }
    });
    useRender(() => {
      const sheetProps = VSheet.filterProps(props);
      const hasHeader = !!(slots.header || props.items.length);
      const hasWindow = props.items.length > 0;
      const hasActions = !props.hideActions && !!(hasWindow || slots.actions);
      return createVNode(VSheet, mergeProps(sheetProps, {
        "color": props.bgColor,
        "class": ['v-stepper', {
          'v-stepper--alt-labels': props.altLabels,
          'v-stepper--flat': props.flat,
          'v-stepper--non-linear': props.nonLinear,
          'v-stepper--mobile': mobile.value
        }, displayClasses.value, props.class],
        "style": props.style
      }), {
        default: () => [hasHeader && createVNode(VStepperHeader, {
          "key": "stepper-header"
        }, {
          default: () => [items.value.map(({
            raw,
            ...item
          }, index) => createElementVNode(Fragment, null, [!!index && createVNode(VDivider, null, null), createVNode(VStepperItem, item.props, {
            default: slots[`header-item.${item.value}`] ?? slots.header,
            icon: slots.icon,
            title: slots.title,
            subtitle: slots.subtitle
          })]))]
        }), hasWindow && createVNode(VStepperWindow, {
          "key": "stepper-window"
        }, {
          default: () => [items.value.map(item => createVNode(VStepperWindowItem, {
            "value": item.value
          }, {
            default: () => slots[`item.${item.value}`]?.(item) ?? slots.item?.(item)
          }))]
        }), slots.default?.({
          prev,
          next
        }), hasActions && (slots.actions?.({
          next,
          prev
        }) ?? createVNode(VStepperActions, {
          "key": "stepper-actions",
          "onClick:prev": prev,
          "onClick:next": next
        }, slots))]
      });
    });
    return {
      prev,
      next
    };
  }
});

// Types

const makeVStepperVerticalActionsProps = propsFactory({
  ...makeVStepperActionsProps()
}, 'VStepperActions');
const VStepperVerticalActions = genericComponent()({
  name: 'VStepperVerticalActions',
  props: makeVStepperVerticalActionsProps(),
  emits: {
    'click:prev': () => true,
    'click:next': () => true
  },
  setup(props, {
    emit,
    slots
  }) {
    function onClickPrev() {
      emit('click:prev');
    }
    function onClickNext() {
      emit('click:next');
    }
    useRender(() => {
      const stepperActionsProps = VStepperActions.filterProps(props);
      return createVNode(VStepperActions, mergeProps({
        "class": "v-stepper-vertical-actions"
      }, stepperActionsProps, {
        "onClick:prev": onClickPrev,
        "onClick:next": onClickNext
      }), slots);
    });
    return {};
  }
});

// Types

const makeVStepperVerticalItemProps = propsFactory({
  hideActions: Boolean,
  ...makeStepperItemProps(),
  ...omit(makeVExpansionPanelProps({
    expandIcon: '',
    collapseIcon: ''
  }), ['hideActions'])
}, 'VStepperVerticalItem');
const VStepperVerticalItem = genericComponent()({
  name: 'VStepperVerticalItem',
  props: makeVStepperVerticalItemProps(),
  emits: {
    'click:next': () => true,
    'click:prev': () => true,
    'click:finish': () => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const vExpansionPanelRef = ref();
    const step = computed(() => !isNaN(parseInt(props.value)) ? Number(props.value) : props.value);
    const groupItem = computed(() => vExpansionPanelRef.value?.groupItem);
    const isValid = computed(() => props.rules.every(handler => handler() === true));
    const canEdit = computed(() => !props.disabled && props.editable);
    const hasError = computed(() => props.error || !isValid.value);
    const hasCompleted = computed(() => props.complete || props.rules.length > 0 && isValid.value);
    const disabled = computed(() => {
      if (props.disabled) return props.disabled;
      if (groupItem.value?.isFirst.value) return 'prev';
      return false;
    });
    const icon = computed(() => {
      if (hasError.value) return props.errorIcon;
      if (hasCompleted.value) return props.completeIcon;
      if (groupItem.value?.isSelected.value && props.editable) return props.editIcon;
      return props.icon;
    });
    const slotProps = computed(() => ({
      canEdit: canEdit.value,
      hasError: hasError.value,
      hasCompleted: hasCompleted.value,
      title: props.title,
      subtitle: props.subtitle,
      step: step.value
    }));
    const actionProps = computed(() => ({
      ...slotProps.value,
      prev: onClickPrev,
      next: onClickNext
    }));
    function onClickNext() {
      emit('click:next');
      if (groupItem.value?.isLast.value) return;
      groupItem.value.group.next();
    }
    function onClickPrev() {
      emit('click:prev');
      groupItem.value.group.prev();
    }
    useRender(() => {
      const hasColor = (!groupItem.value || groupItem.value?.isSelected.value || hasCompleted.value || canEdit.value) && !hasError.value && !props.disabled;
      const hasActions = !props.hideActions || !!slots.actions;
      const expansionPanelProps = VExpansionPanel.filterProps(props);
      return createVNode(VExpansionPanel, mergeProps({
        "_as": "VStepperVerticalItem",
        "ref": vExpansionPanelRef
      }, expansionPanelProps, {
        "class": ['v-stepper-vertical-item', {
          'v-stepper-vertical-item--complete': hasCompleted.value,
          'v-stepper-vertical-item--disabled': props.disabled,
          'v-stepper-vertical-item--editable': canEdit.value,
          'v-stepper-vertical-item--error': hasError.value
        }, props.class],
        "readonly": !props.editable,
        "style": props.style,
        "color": "",
        "hideActions": false,
        "value": step.value
      }), {
        title: () => createElementVNode(Fragment, null, [createVNode(VAvatar, {
          "key": "stepper-avatar",
          "class": "v-stepper-vertical-item__avatar",
          "color": hasColor ? props.color : undefined,
          "size": 24,
          "start": true
        }, {
          default: () => [slots.icon?.(slotProps.value) ?? (icon.value ? createVNode(VIcon, {
            "icon": icon.value
          }, null) : step.value)]
        }), createElementVNode("div", null, [createElementVNode("div", {
          "class": "v-stepper-vertical-item__title"
        }, [slots.title?.(slotProps.value) ?? props.title]), createElementVNode("div", {
          "class": "v-stepper-vertical-item__subtitle"
        }, [slots.subtitle?.(slotProps.value) ?? props.subtitle])])]),
        text: () => createElementVNode(Fragment, null, [slots.default?.(slotProps.value) ?? props.text, hasActions && createVNode(VDefaultsProvider, {
          "defaults": {
            VStepperVerticalActions: {
              disabled: disabled.value,
              finish: groupItem.value?.isLast.value
            }
          }
        }, {
          default: () => [slots.actions?.(actionProps.value) ?? createVNode(VStepperVerticalActions, {
            "onClick:next": onClickNext,
            "onClick:prev": onClickPrev
          }, {
            prev: slots.prev ? () => slots.prev?.(actionProps.value) : undefined,
            next: slots.next ? () => slots.next?.(actionProps.value) : undefined
          })]
        })])
      });
    });
    return {};
  }
});

// Types

const makeVStepperVerticalProps = propsFactory({
  prevText: {
    type: String,
    default: '$vuetify.stepper.prev'
  },
  nextText: {
    type: String,
    default: '$vuetify.stepper.next'
  },
  ...makeStepperProps(),
  ...omit(makeVExpansionPanelsProps({
    mandatory: 'force',
    variant: 'accordion'
  }), ['static'])
}, 'VStepperVertical');
const VStepperVertical = genericComponent()({
  name: 'VStepperVertical',
  props: makeVStepperVerticalProps(),
  emits: {
    'update:modelValue': val => true
  },
  setup(props, {
    slots
  }) {
    const vExpansionPanelsRef = ref();
    const {
      color,
      eager,
      editable,
      prevText,
      nextText,
      hideActions
    } = toRefs(props);
    const model = useProxiedModel(props, 'modelValue');
    const items = computed(() => props.items.map((item, index) => {
      const title = getPropertyFromItem(item, props.itemTitle, item);
      const value = getPropertyFromItem(item, props.itemValue, index + 1);
      const itemProps = props.itemProps === true ? item : getPropertyFromItem(item, props.itemProps);
      const _props = {
        title,
        value,
        ...itemProps
      };
      return {
        title: _props.title,
        value: _props.value,
        props: _props,
        raw: item
      };
    }));
    provideDefaults({
      VStepperVerticalItem: {
        color,
        eager,
        editable,
        hideActions,
        static: true
      },
      VStepperVerticalActions: {
        color,
        nextText,
        prevText
      }
    });
    useRender(() => {
      const expansionPanelProps = VExpansionPanels.filterProps(props);
      return createVNode(VExpansionPanels, mergeProps(expansionPanelProps, {
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "ref": vExpansionPanelsRef,
        "class": ['v-stepper', {
          'v-stepper--alt-labels': props.altLabels,
          'v-stepper--flat': props.flat,
          'v-stepper--non-linear': props.nonLinear,
          'v-stepper--mobile': props.mobile
        }, props.class],
        "style": props.style
      }), {
        ...slots,
        default: ({
          prev,
          next
        }) => {
          return createElementVNode(Fragment, null, [items.value.map(({
            raw,
            ...item
          }) => createVNode(VStepperVerticalItem, item.props, {
            ...slots,
            default: slots[`item.${item.value}`]
          })), slots.default?.({
            prev,
            next,
            step: model.value
          })]);
        }
      });
    });
    return {};
  }
});

// Types

const makeVSwitchProps = propsFactory({
  inset: {
    type: [Boolean, String],
    default: false
  },
  flat: Boolean,
  thumbColor: String,
  loading: {
    type: [Boolean, String],
    default: false
  },
  ...omit(makeVInputProps(), ['glow']),
  ...makeVSelectionControlProps(),
  ...makeSizeProps()
}, 'VSwitch');
const predefinedSizes = ['x-small', 'small', 'default', 'large', 'x-large'];
const iconSizes = {
  'x-small': 11,
  small: 14,
  default: 16,
  large: 18,
  'x-large': 22
};
const VSwitch = genericComponent()({
  name: 'VSwitch',
  inheritAttrs: false,
  props: makeVSwitchProps(),
  emits: {
    'update:focused': focused => true,
    'update:modelValue': value => true,
    'update:indeterminate': value => true
  },
  setup(props, {
    attrs,
    slots
  }) {
    const indeterminate = useProxiedModel(props, 'indeterminate');
    const model = useProxiedModel(props, 'modelValue');
    const {
      loaderClasses
    } = useLoader(props);
    const {
      isFocused,
      focus,
      blur
    } = useFocus(props);
    const {
      backgroundColorClasses: thumbColorClasses,
      backgroundColorStyles: thumbColorStyles
    } = useBackgroundColor(() => props.thumbColor);
    const control = ref();
    const inputRef = ref();
    const isForcedColorsModeActive = SUPPORTS_MATCH_MEDIA && window.matchMedia('(forced-colors: active)').matches;
    const loaderColor = toRef(() => {
      return typeof props.loading === 'string' && props.loading !== '' ? props.loading : props.color;
    });
    const uid = useId();
    const id = toRef(() => props.id || `switch-${uid}`);
    const isPredefinedSize = toRef(() => predefinedSizes.includes(props.size));
    const iconSize = toRef(() => {
      return isPredefinedSize.value ? iconSizes[props.size] : Math.round(16 * Number(props.size) / 32);
    });
    function onChange() {
      if (indeterminate.value) {
        indeterminate.value = false;
      }
    }
    function onTrackClick(e) {
      e.stopPropagation();
      e.preventDefault();
      control.value?.input?.click();
    }
    useRender(() => {
      const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
      const inputProps = VInput.filterProps(props);
      const controlProps = VSelectionControl.filterProps(props);
      const isMaterial = ['material', 'square'].includes(String(props.inset));
      const hasThumbColor = !isForcedColorsModeActive && !!props.thumbColor;
      return createVNode(VInput, mergeProps({
        "ref": inputRef,
        "class": ['v-switch', {
          'v-switch--flat': props.flat
        }, {
          'v-switch--inset': !!props.inset
        }, {
          'v-switch--inset-material': isMaterial
        }, {
          'v-switch--inset-square': props.inset === 'square'
        }, {
          'v-switch--indeterminate': indeterminate.value
        }, isPredefinedSize.value ? `v-switch--size-${props.size}` : undefined, loaderClasses.value, props.class]
      }, rootAttrs, inputProps, {
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "id": id.value,
        "focused": isFocused.value,
        "style": [{
          '--v-switch-scale': isPredefinedSize.value ? undefined : Number(props.size) / 32
        }, props.style]
      }), {
        ...slots,
        default: ({
          id,
          messagesId,
          isDisabled,
          isReadonly,
          isValid
        }) => {
          const slotProps = {
            model,
            isValid
          };
          return createVNode(VSelectionControl, mergeProps({
            "ref": control
          }, controlProps, {
            "modelValue": model.value,
            "onUpdate:modelValue": [$event => model.value = $event, onChange],
            "id": id.value,
            "aria-describedby": messagesId.value,
            "type": "checkbox",
            "aria-checked": indeterminate.value ? 'mixed' : undefined,
            "disabled": isDisabled.value,
            "readonly": isReadonly.value,
            "onFocus": focus,
            "onBlur": blur
          }, controlAttrs), {
            ...slots,
            default: ({
              backgroundColorClasses,
              backgroundColorStyles
            }) => createElementVNode("div", {
              "class": normalizeClass(['v-switch__track', !isForcedColorsModeActive ? backgroundColorClasses.value : undefined]),
              "style": normalizeStyle(backgroundColorStyles.value),
              "onClick": onTrackClick
            }, [slots['track-true'] && createElementVNode("div", {
              "key": "prepend",
              "class": "v-switch__track-true"
            }, [slots['track-true'](slotProps)]), slots['track-false'] && createElementVNode("div", {
              "key": "append",
              "class": "v-switch__track-false"
            }, [slots['track-false'](slotProps)])]),
            input: ({
              inputNode,
              icon,
              model: isSelected,
              backgroundColorClasses,
              backgroundColorStyles,
              textColorClasses,
              textColorStyles
            }) => createElementVNode(Fragment, null, [inputNode, createElementVNode("div", {
              "class": normalizeClass(['v-switch__thumb', {
                'v-switch__thumb--filled': icon || props.loading
              }, isForcedColorsModeActive ? undefined : hasThumbColor && isSelected.value ? thumbColorClasses.value : isMaterial ? backgroundColorClasses.value : props.inset ? undefined : backgroundColorClasses.value]),
              "style": normalizeStyle([hasThumbColor && isSelected.value ? thumbColorStyles.value : isMaterial ? backgroundColorClasses.value.length || backgroundColorStyles.value.backgroundColor ? {
                backgroundColor: 'currentColor'
              } : undefined : props.inset ? undefined : backgroundColorStyles.value])
            }, [slots.thumb ? createVNode(VDefaultsProvider, {
              "defaults": {
                VIcon: {
                  icon,
                  size: isMaterial ? iconSize.value : 'x-small'
                }
              }
            }, {
              default: () => [slots.thumb({
                ...slotProps,
                icon
              })]
            }) : createVNode(VScaleTransition, null, {
              default: () => [!props.loading ? icon && createVNode(VIcon, {
                "key": String(icon),
                "class": normalizeClass(isMaterial ? textColorClasses.value : undefined),
                "style": normalizeStyle(isMaterial ? textColorStyles.value : undefined),
                "icon": icon,
                "size": isMaterial ? iconSize.value : 'x-small'
              }, null) : createVNode(LoaderSlot, {
                "name": "v-switch",
                "active": true,
                "color": isValid.value === false ? undefined : loaderColor.value
              }, {
                default: slotProps => slots.loader ? slots.loader(slotProps) : createVNode(VProgressCircular, {
                  "active": slotProps.isActive,
                  "color": slotProps.color,
                  "indeterminate": true,
                  "size": iconSize.value,
                  "width": "2"
                }, null)
              })]
            })])])
          });
        }
      });
    });
    return forwardRefs({}, inputRef);
  }
});

const makeVSystemBarProps = propsFactory({
  color: String,
  height: [Number, String],
  window: Boolean,
  ...makeComponentProps(),
  ...makeElevationProps(),
  ...makeLayoutItemProps(),
  ...makeRoundedProps(),
  ...makeTagProps(),
  ...makeThemeProps()
}, 'VSystemBar');
const VSystemBar = genericComponent()({
  name: 'VSystemBar',
  props: makeVSystemBarProps(),
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props);
    const {
      ssrBootStyles
    } = useSsrBoot();
    const height = computed(() => props.height ?? (props.window ? 32 : 24));
    const {
      layoutItemStyles
    } = useLayoutItem({
      id: props.name,
      order: computed(() => parseInt(props.order, 10)),
      position: shallowRef('top'),
      layoutSize: height,
      elementSize: height,
      active: computed(() => true),
      absolute: toRef(() => props.absolute)
    });
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-system-bar', {
        'v-system-bar--window': props.window
      }, themeClasses.value, backgroundColorClasses.value, elevationClasses.value, roundedClasses.value, props.class]),
      "style": normalizeStyle([backgroundColorStyles.value, layoutItemStyles.value, ssrBootStyles.value, roundedStyles.value, props.style])
    }, slots));
    return {};
  }
});

// Types

const VTabsSymbol = Symbol.for('vuetify:v-tabs');

// Types

const makeVTabProps = propsFactory({
  fixed: Boolean,
  sliderColor: String,
  sliderTransition: String,
  sliderTransitionDuration: [String, Number],
  hideSlider: Boolean,
  inset: Boolean,
  direction: {
    type: String,
    default: 'horizontal'
  },
  ...omit(makeVBtnProps({
    selectedClass: 'v-tab--selected',
    variant: 'text'
  }), ['active', 'block', 'flat', 'location', 'position', 'symbol'])
}, 'VTab');
const VTab = genericComponent()({
  name: 'VTab',
  props: makeVTabProps(),
  setup(props, {
    slots,
    attrs
  }) {
    const {
      textColorClasses: sliderColorClasses,
      textColorStyles: sliderColorStyles
    } = useTextColor(() => props.sliderColor);
    const {
      backgroundColorClasses: insetColorClasses,
      backgroundColorStyles: insetColorStyles
    } = useBackgroundColor(() => props.sliderColor);
    const rootEl = ref();
    const sliderEl = ref();
    const isHorizontal = computed(() => props.direction === 'horizontal');
    const isSelected = computed(() => rootEl.value?.group?.isSelected.value ?? false);
    function fade(nextEl, prevEl) {
      return {
        opacity: [0, 1]
      };
    }
    function grow(nextEl, prevEl) {
      return props.direction === 'vertical' ? {
        transform: ['scaleY(0)', 'scaleY(1)']
      } : {
        transform: ['scaleX(0)', 'scaleX(1)']
      };
    }
    function shift(nextEl, prevEl) {
      const prevBox = prevEl.getBoundingClientRect();
      const nextBox = nextEl.getBoundingClientRect();
      const xy = isHorizontal.value ? 'x' : 'y';
      const XY = isHorizontal.value ? 'X' : 'Y';
      const rightBottom = isHorizontal.value ? 'right' : 'bottom';
      const widthHeight = isHorizontal.value ? 'width' : 'height';
      const prevPos = prevBox[xy];
      const nextPos = nextBox[xy];
      const delta = prevPos > nextPos ? prevBox[rightBottom] - nextBox[rightBottom] : prevBox[xy] - nextBox[xy];
      const origin = Math.sign(delta) > 0 ? isHorizontal.value ? 'right' : 'bottom' : Math.sign(delta) < 0 ? isHorizontal.value ? 'left' : 'top' : 'center';
      const size = Math.abs(delta) + (Math.sign(delta) < 0 ? prevBox[widthHeight] : nextBox[widthHeight]);
      const scale = size / Math.max(prevBox[widthHeight], nextBox[widthHeight]) || 0;
      const initialScale = prevBox[widthHeight] / nextBox[widthHeight] || 0;
      const sigma = 1.5;
      return {
        transform: [`translate${XY}(${delta}px) scale${XY}(${initialScale})`, `translate${XY}(${delta / sigma}px) scale${XY}(${(scale - 1) / sigma + 1})`, 'none'],
        transformOrigin: Array(3).fill(origin)
      };
    }
    function updateSlider({
      value
    }) {
      if (value) {
        const prevEl = rootEl.value?.$el.parentElement?.querySelector('.v-tab--selected .v-tab__slider');
        const nextEl = sliderEl.value;
        if (!prevEl || !nextEl) return;
        const color = getComputedStyle(prevEl).backgroundColor;
        const keyframes = {
          fade,
          grow,
          shift
        }[props.sliderTransition ?? 'shift'] ?? shift;
        const duration = Number(props.sliderTransitionDuration) || ({
          fade: 400,
          grow: 350,
          shift: 225
        }[props.sliderTransition ?? 'shift'] ?? 225);
        animate(nextEl, {
          backgroundColor: [color, color],
          ...keyframes(nextEl, prevEl)
        }, {
          duration,
          easing: standardEasing
        });
      }
    }
    useRender(() => {
      const btnProps = VBtn.filterProps(props);
      return createVNode(VBtn, mergeProps({
        "symbol": VTabsSymbol,
        "ref": rootEl,
        "class": ['v-tab', props.class, isSelected.value && props.inset ? insetColorClasses.value : []],
        "style": [props.style, isSelected.value && props.inset ? insetColorStyles.value : [], {
          backgroundColor: isSelected.value && props.inset ? 'transparent !important' : undefined
        }],
        "tabindex": isSelected.value ? 0 : -1,
        "role": "tab",
        "aria-selected": String(isSelected.value),
        "active": false
      }, btnProps, attrs, {
        "block": props.fixed,
        "maxWidth": props.fixed ? 300 : undefined,
        "onGroup:selected": updateSlider
      }), {
        ...slots,
        default: () => createElementVNode(Fragment, null, [slots.default?.() ?? props.text, !props.hideSlider && createElementVNode("div", {
          "ref": sliderEl,
          "class": normalizeClass(['v-tab__slider', props.inset ? insetColorClasses.value : sliderColorClasses.value]),
          "style": normalizeStyle([sliderColorStyles.value, props.inset ? insetColorStyles.value : sliderColorClasses.value])
        }, null)])
      });
    });
    return forwardRefs({}, rootEl);
  }
});

const makeVTabsWindowProps = propsFactory({
  ...omit(makeVWindowProps(), ['continuous', 'nextIcon', 'prevIcon', 'showArrows', 'touch', 'mandatory'])
}, 'VTabsWindow');
const VTabsWindow = genericComponent()({
  name: 'VTabsWindow',
  props: makeVTabsWindowProps(),
  emits: {
    'update:modelValue': v => true
  },
  setup(props, {
    slots
  }) {
    const group = inject$1(VTabsSymbol, null);
    const _model = useProxiedModel(props, 'modelValue');
    const model = computed({
      get() {
        // Always return modelValue if defined
        // or if not within a VTabs group
        if (_model.value != null || !group) return _model.value;

        // If inside of a VTabs, find the currently selected
        // item by id. Item value may be assigned by its index
        return group.items.value.find(item => group.selected.value.includes(item.id))?.value;
      },
      set(val) {
        _model.value = val;
      }
    });
    useRender(() => {
      const windowProps = VWindow.filterProps(props);
      return createVNode(VWindow, mergeProps({
        "_as": "VTabsWindow"
      }, windowProps, {
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "class": ['v-tabs-window', props.class],
        "style": props.style,
        "mandatory": false,
        "touch": false
      }), slots);
    });
    return {};
  }
});

const makeVTabsWindowItemProps = propsFactory({
  ...makeVWindowItemProps()
}, 'VTabsWindowItem');
const VTabsWindowItem = genericComponent()({
  name: 'VTabsWindowItem',
  props: makeVTabsWindowItemProps(),
  setup(props, {
    slots
  }) {
    useRender(() => {
      const windowItemProps = VWindowItem.filterProps(props);
      return createVNode(VWindowItem, mergeProps({
        "_as": "VTabsWindowItem"
      }, windowItemProps, {
        "class": ['v-tabs-window-item', props.class],
        "style": props.style
      }), slots);
    });
    return {};
  }
});

// Types

function parseItems(items) {
  if (!items) return [];
  return items.map(item => {
    if (!isObject(item)) return {
      text: item,
      value: item
    };
    return item;
  });
}
const makeVTabsProps = propsFactory({
  alignTabs: {
    type: String,
    default: 'start'
  },
  color: String,
  fixedTabs: Boolean,
  items: {
    type: Array,
    default: () => []
  },
  stacked: Boolean,
  bgColor: String,
  grow: Boolean,
  height: {
    type: [Number, String],
    default: undefined
  },
  hideSlider: Boolean,
  inset: Boolean,
  insetPadding: [String, Number],
  insetRadius: [String, Number],
  sliderColor: String,
  ...pick(makeVTabProps(), ['spaced', 'sliderTransition', 'sliderTransitionDuration']),
  ...makeVSlideGroupProps({
    mandatory: 'force',
    selectedClass: 'v-tab-item--selected'
  }),
  ...makeDensityProps(),
  ...makeTagProps()
}, 'VTabs');
const VTabs = genericComponent()({
  name: 'VTabs',
  props: makeVTabsProps(),
  emits: {
    'update:modelValue': v => true
  },
  setup(props, {
    attrs,
    slots
  }) {
    const model = useProxiedModel(props, 'modelValue');
    const items = computed(() => parseItems(props.items));
    const {
      densityClasses
    } = useDensity(props);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.bgColor);
    const {
      scopeId
    } = useScopeId();
    provideDefaults({
      VTab: {
        color: toRef(props, 'color'),
        direction: toRef(props, 'direction'),
        stacked: toRef(props, 'stacked'),
        fixed: toRef(props, 'fixedTabs'),
        inset: toRef(props, 'inset'),
        sliderColor: toRef(props, 'sliderColor'),
        sliderTransition: toRef(props, 'sliderTransition'),
        sliderTransitionDuration: toRef(props, 'sliderTransitionDuration'),
        hideSlider: toRef(props, 'hideSlider')
      }
    });
    useRender(() => {
      const slideGroupProps = VSlideGroup.filterProps(props);
      const hasWindow = !!(slots.window || props.items.length > 0);
      return createElementVNode(Fragment, null, [createVNode(VSlideGroup, mergeProps(slideGroupProps, {
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "class": ['v-tabs', `v-tabs--${props.direction}`, `v-tabs--align-tabs-${props.alignTabs}`, {
          'v-tabs--fixed-tabs': props.fixedTabs,
          'v-tabs--grow': props.grow,
          'v-tabs--inset': props.inset,
          'v-tabs--stacked': props.stacked
        }, densityClasses.value, backgroundColorClasses.value, props.class],
        "style": [{
          '--v-tabs-height': convertToUnit(props.height),
          '--v-tabs-inset-padding': props.inset ? convertToUnit(props.insetPadding) : undefined,
          '--v-tabs-inset-radius': props.inset ? convertToUnit(props.insetRadius) : undefined
        }, backgroundColorStyles.value, props.style],
        "role": "tablist",
        "symbol": VTabsSymbol
      }, scopeId, attrs), {
        default: slots.default ?? (() => items.value.map(item => slots.tab?.({
          item
        }) ?? createVNode(VTab, mergeProps(item, {
          "key": item.text,
          "value": item.value,
          "spaced": props.spaced
        }), {
          default: slots[`tab.${item.value}`] ? () => slots[`tab.${item.value}`]?.({
            item
          }) : undefined
        }))),
        prev: slots.prev,
        next: slots.next
      }), hasWindow && createVNode(VTabsWindow, mergeProps({
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "key": "tabs-window"
      }, scopeId), {
        default: () => [items.value.map(item => slots.item?.({
          item
        }) ?? createVNode(VTabsWindowItem, {
          "value": item.value
        }, {
          default: () => slots[`item.${item.value}`]?.({
            item
          })
        })), slots.window?.()]
      })]);
    });
    return {};
  }
});

// Types

const makeVTextareaProps = propsFactory({
  autoGrow: Boolean,
  autofocus: Boolean,
  counter: [Boolean, Number, String],
  counterValue: Function,
  prefix: String,
  placeholder: String,
  persistentPlaceholder: Boolean,
  persistentCounter: Boolean,
  noResize: Boolean,
  rows: {
    type: [Number, String],
    default: 5,
    validator: v => !isNaN(parseFloat(v))
  },
  maxHeight: {
    type: [Number, String],
    validator: v => !isNaN(parseFloat(v))
  },
  maxRows: {
    type: [Number, String],
    validator: v => !isNaN(parseFloat(v))
  },
  suffix: String,
  modelModifiers: Object,
  ...makeAutocompleteProps(),
  ...omit(makeVInputProps(), ['direction']),
  ...makeVFieldProps()
}, 'VTextarea');
const VTextarea = genericComponent()({
  name: 'VTextarea',
  directives: {
    vIntersect: Intersect
  },
  inheritAttrs: false,
  props: makeVTextareaProps(),
  emits: {
    'click:control': e => true,
    'mousedown:control': e => true,
    'update:focused': focused => true,
    'update:modelValue': val => true,
    'update:rows': rows => true
  },
  setup(props, {
    attrs,
    emit,
    slots
  }) {
    const model = useProxiedModel(props, 'modelValue');
    const {
      isFocused,
      focus,
      blur
    } = useFocus(props);
    const {
      onIntersect
    } = useAutofocus(props);
    const counterValue = computed(() => {
      return typeof props.counterValue === 'function' ? props.counterValue(model.value) : (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 undefined;
      return props.counter;
    });
    const vInputRef = ref();
    const vFieldRef = ref();
    const controlHeight = shallowRef('');
    const textareaRef = ref();
    const scrollbarWidth = ref(0);
    const {
      platform
    } = useDisplay();
    const autocomplete = useAutocomplete(props);
    const isActive = computed(() => props.persistentPlaceholder || isFocused.value || props.active);
    function onFocus() {
      if (autocomplete.isSuppressing.value) {
        autocomplete.update();
      }
      if (textareaRef.value !== getActiveElement()) {
        textareaRef.value?.focus();
      }
      if (!isFocused.value) focus();
    }
    function onControlClick(e) {
      onFocus();
      emit('click:control', e);
    }
    function onControlMousedown(e) {
      emit('mousedown:control', e);
    }
    function onClear(e) {
      e.stopPropagation();
      onFocus();
      nextTick(() => {
        model.value = '';
        callEvent(props['onClick:clear'], e);
      });
    }
    function onInput(e) {
      const el = e.target;
      if (!props.modelModifiers?.trim) {
        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) {
          // #22307 - Whitespace has been removed from the
          // start, offset the caret position to compensate
          offset = value.length - el.value.length;
        }
        if (start != null) el.selectionStart = start - offset;
        if (end != null) el.selectionEnd = end - offset;
      });
    }
    const sizerRef = ref();
    const rows = ref(Number(props.rows));
    const isPlainOrUnderlined = computed(() => ['plain', 'underlined'].includes(props.variant));
    watchEffect(() => {
      if (!props.autoGrow) rows.value = Number(props.rows);
    });
    function calculateInputHeight() {
      nextTick(() => {
        if (!textareaRef.value) return;
        if (platform.value.firefox) {
          scrollbarWidth.value = 12;
          return;
        }
        const {
          offsetWidth,
          clientWidth
        } = textareaRef.value;
        scrollbarWidth.value = Math.max(0, offsetWidth - clientWidth);
      });
      if (!props.autoGrow) return;
      nextTick(() => {
        if (!sizerRef.value || !vFieldRef.value) return;
        const style = getComputedStyle(sizerRef.value);
        const fieldStyle = getComputedStyle(vFieldRef.value.$el);
        const padding = parseFloat(style.getPropertyValue('--v-field-padding-top')) + parseFloat(style.getPropertyValue('--v-input-padding-top')) + parseFloat(style.getPropertyValue('--v-field-padding-bottom'));
        const height = sizerRef.value.scrollHeight;
        const lineHeight = parseFloat(style.lineHeight);
        const minHeight = Math.max(parseFloat(props.rows) * lineHeight + padding, parseFloat(fieldStyle.getPropertyValue('--v-input-control-height')));
        const maxHeight = props.maxHeight ? parseFloat(props.maxHeight) : parseFloat(props.maxRows) * lineHeight + padding || Infinity;
        const newHeight = clamp(height ?? 0, minHeight, maxHeight);
        rows.value = Math.floor((newHeight - padding) / lineHeight);
        controlHeight.value = convertToUnit(newHeight);
      });
    }
    onMounted(calculateInputHeight);
    watch(model, calculateInputHeight);
    watch(() => props.rows, calculateInputHeight);
    watch(() => props.maxHeight, calculateInputHeight);
    watch(() => props.maxRows, calculateInputHeight);
    watch(() => props.density, calculateInputHeight);
    watch(rows, val => {
      emit('update:rows', val);
    });
    let observer;
    watch(sizerRef, val => {
      if (val) {
        observer = new ResizeObserver(calculateInputHeight);
        observer.observe(sizerRef.value);
      } else {
        observer?.disconnect();
      }
    });
    onBeforeUnmount(() => {
      observer?.disconnect();
    });
    useRender(() => {
      const hasCounter = !!(slots.counter || props.counter || props.counterValue);
      const hasDetails = props.hideDetails !== true && !!(slots.details || hasCounter && (props.persistentCounter || props.hideDetails === false || isFocused.value));
      const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
      const {
        modelValue: _,
        ...inputProps
      } = VInput.filterProps(props);
      const fieldProps = {
        ...VField.filterProps(props),
        'onClick:clear': onClear
      };
      return createVNode(VInput, mergeProps({
        "ref": vInputRef,
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "class": ['v-textarea v-text-field', {
          'v-textarea--prefixed': props.prefix,
          'v-textarea--suffixed': props.suffix,
          'v-text-field--prefixed': props.prefix,
          'v-text-field--suffixed': props.suffix,
          'v-textarea--auto-grow': props.autoGrow,
          'v-textarea--no-resize': props.noResize || props.autoGrow,
          'v-input--plain-underlined': isPlainOrUnderlined.value
        }, props.class],
        "style": [{
          '--v-textarea-max-height': props.maxHeight ? convertToUnit(props.maxHeight) : undefined,
          '--v-textarea-scroll-bar-width': convertToUnit(scrollbarWidth.value)
        }, props.style]
      }, rootAttrs, inputProps, {
        "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
        "focused": isFocused.value,
        "indentDetails": props.indentDetails ?? !isPlainOrUnderlined.value
      }), {
        ...slots,
        default: ({
          id,
          isDisabled,
          isDirty,
          isReadonly,
          isValid,
          hasDetails
        }) => createVNode(VField, mergeProps({
          "ref": vFieldRef,
          "style": {
            '--v-textarea-control-height': controlHeight.value
          },
          "onClick": onControlClick,
          "onMousedown": onControlMousedown,
          "onClick:prependInner": props['onClick:prependInner'],
          "onClick:appendInner": props['onClick:appendInner']
        }, fieldProps, {
          "id": id.value,
          "active": isActive.value || isDirty.value,
          "labelId": `${id.value}-label`,
          "centerAffix": rows.value === 1 && !isPlainOrUnderlined.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
          }) => createElementVNode(Fragment, null, [props.prefix && createElementVNode("span", {
            "class": "v-text-field__prefix"
          }, [props.prefix]), withDirectives(createElementVNode("textarea", mergeProps({
            "ref": val => textareaRef.value = controlRef.value = val,
            "class": fieldClass,
            "value": model.value,
            "onInput": onInput,
            "autofocus": props.autofocus,
            "readonly": isReadonly.value,
            "disabled": isDisabled.value,
            "placeholder": props.placeholder,
            "rows": props.rows,
            "name": autocomplete.fieldName.value,
            "autocomplete": autocomplete.fieldAutocomplete.value,
            "onFocus": onFocus,
            "onBlur": blur,
            "aria-labelledby": `${id.value}-label`
          }, slotProps, inputAttrs), null), [[Intersect, {
            handler: onIntersect
          }, null, {
            once: true
          }]]), props.autoGrow && withDirectives(createElementVNode("textarea", {
            "class": normalizeClass([fieldClass, 'v-textarea__sizer']),
            "id": `${slotProps.id}-sizer`,
            "onUpdate:modelValue": $event => model.value = $event,
            "ref": sizerRef,
            "readonly": true,
            "aria-hidden": "true"
          }, null), [[vModelText, model.value]]), props.suffix && createElementVNode("span", {
            "class": "v-text-field__suffix"
          }, [props.suffix])])
        }),
        details: hasDetails ? slotProps => createElementVNode(Fragment, null, [slots.details?.(slotProps), hasCounter && createElementVNode(Fragment, null, [createElementVNode("span", null, null), createVNode(VCounter, {
          "active": props.persistentCounter || isFocused.value,
          "value": counterValue.value,
          "max": max.value,
          "disabled": props.disabled
        }, slots.counter)])]) : undefined
      });
    });
    return forwardRefs({}, vInputRef, vFieldRef, textareaRef);
  }
});

const makeVThemeProviderProps = propsFactory({
  withBackground: Boolean,
  ...makeComponentProps(),
  ...makeThemeProps(),
  ...makeTagProps()
}, 'VThemeProvider');
const VThemeProvider = genericComponent()({
  name: 'VThemeProvider',
  props: makeVThemeProviderProps(),
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    return () => {
      if (!props.withBackground) return slots.default?.();
      return createVNode(props.tag, {
        "class": normalizeClass(['v-theme-provider', themeClasses.value, props.class]),
        "style": normalizeStyle(props.style)
      }, {
        default: () => [slots.default?.()]
      });
    };
  }
});

const makeVTimelineDividerProps = propsFactory({
  dotColor: String,
  fillDot: Boolean,
  hideDot: Boolean,
  icon: IconValue,
  iconColor: String,
  lineColor: String,
  ...makeComponentProps(),
  ...makeRoundedProps(),
  ...makeSizeProps(),
  ...makeElevationProps()
}, 'VTimelineDivider');
const VTimelineDivider = genericComponent()({
  name: 'VTimelineDivider',
  props: makeVTimelineDividerProps(),
  setup(props, {
    slots
  }) {
    const {
      sizeClasses,
      sizeStyles
    } = useSize(props, 'v-timeline-divider__dot');
    const {
      backgroundColorStyles,
      backgroundColorClasses
    } = useBackgroundColor(() => props.dotColor);
    const {
      roundedClasses,
      roundedStyles
    } = useRounded(props, 'v-timeline-divider__dot');
    const {
      elevationClasses
    } = useElevation(props);
    const {
      backgroundColorClasses: lineColorClasses,
      backgroundColorStyles: lineColorStyles
    } = useBackgroundColor(() => props.lineColor);
    useRender(() => createElementVNode("div", {
      "class": normalizeClass(['v-timeline-divider', {
        'v-timeline-divider--fill-dot': props.fillDot
      }, props.class]),
      "style": normalizeStyle(props.style)
    }, [createElementVNode("div", {
      "class": normalizeClass(['v-timeline-divider__before', lineColorClasses.value]),
      "style": normalizeStyle(lineColorStyles.value)
    }, null), !props.hideDot && createElementVNode("div", {
      "key": "dot",
      "class": normalizeClass(['v-timeline-divider__dot', elevationClasses.value, roundedClasses.value, sizeClasses.value]),
      "style": normalizeStyle([sizeStyles.value, roundedStyles.value])
    }, [createElementVNode("div", {
      "class": normalizeClass(['v-timeline-divider__inner-dot', backgroundColorClasses.value, roundedClasses.value]),
      "style": normalizeStyle([backgroundColorStyles.value, roundedStyles.value])
    }, [!slots.default ? createVNode(VIcon, {
      "key": "icon",
      "color": props.iconColor,
      "icon": props.icon,
      "size": props.size
    }, null) : createVNode(VDefaultsProvider, {
      "key": "icon-defaults",
      "disabled": !props.icon,
      "defaults": {
        VIcon: {
          color: props.iconColor,
          icon: props.icon,
          size: props.size
        }
      }
    }, slots.default)])]), createElementVNode("div", {
      "class": normalizeClass(['v-timeline-divider__after', lineColorClasses.value]),
      "style": normalizeStyle(lineColorStyles.value)
    }, null)]));
    return {};
  }
});

// Types

// Types

const makeVTimelineItemProps = propsFactory({
  density: String,
  dotColor: String,
  fillDot: Boolean,
  hideDot: Boolean,
  hideOpposite: {
    type: Boolean,
    default: undefined
  },
  icon: IconValue,
  iconColor: String,
  lineInset: [Number, String],
  side: {
    type: String,
    validator: v => v == null || ['start', 'end'].includes(v)
  },
  ...makeComponentProps(),
  ...makeDimensionProps(),
  ...makeElevationProps(),
  ...makeRoundedProps(),
  ...makeSizeProps(),
  ...makeTagProps()
}, 'VTimelineItem');
const VTimelineItem = genericComponent()({
  name: 'VTimelineItem',
  props: makeVTimelineItemProps(),
  setup(props, {
    slots
  }) {
    const {
      dimensionStyles
    } = useDimension(props);
    const dotSize = shallowRef(0);
    const dotRef = ref();
    watch(dotRef, newValue => {
      if (!newValue) return;
      dotSize.value = newValue.$el.querySelector('.v-timeline-divider__dot')?.getBoundingClientRect().width ?? 0;
    }, {
      flush: 'post'
    });
    useRender(() => createElementVNode("div", {
      "class": normalizeClass(['v-timeline-item', {
        'v-timeline-item--fill-dot': props.fillDot,
        'v-timeline-item--side-start': props.side === 'start',
        'v-timeline-item--side-end': props.side === 'end'
      }, props.class]),
      "style": normalizeStyle([{
        '--v-timeline-dot-size': convertToUnit(dotSize.value),
        '--v-timeline-line-inset': props.lineInset ? `calc(var(--v-timeline-dot-size) / 2 + ${convertToUnit(props.lineInset)})` : convertToUnit(0)
      }, props.style])
    }, [createElementVNode("div", {
      "class": "v-timeline-item__body",
      "style": normalizeStyle(dimensionStyles.value)
    }, [slots.default?.()]), createVNode(VTimelineDivider, {
      "ref": dotRef,
      "hideDot": props.hideDot,
      "icon": props.icon,
      "iconColor": props.iconColor,
      "size": props.size,
      "elevation": props.elevation,
      "dotColor": props.dotColor,
      "fillDot": props.fillDot,
      "rounded": props.rounded
    }, {
      default: slots.icon
    }), props.density !== 'compact' && createElementVNode("div", {
      "class": "v-timeline-item__opposite"
    }, [!props.hideOpposite && slots.opposite?.()])]));
    return {};
  }
});

const makeVTimelineProps = propsFactory({
  align: {
    type: String,
    default: 'center',
    validator: v => ['center', 'start'].includes(v)
  },
  direction: {
    type: String,
    default: 'vertical',
    validator: v => ['vertical', 'horizontal'].includes(v)
  },
  justify: {
    type: String,
    default: 'auto',
    validator: v => ['auto', 'center'].includes(v)
  },
  side: {
    type: String,
    validator: v => v == null || ['start', 'end'].includes(v)
  },
  lineThickness: {
    type: [String, Number],
    default: 2
  },
  lineColor: String,
  truncateLine: {
    type: String,
    validator: v => ['start', 'end', 'both'].includes(v)
  },
  ...pick(makeVTimelineItemProps({
    lineInset: 0
  }), ['dotColor', 'fillDot', 'hideOpposite', 'iconColor', 'lineInset', 'size']),
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeTagProps(),
  ...makeThemeProps()
}, 'VTimeline');
const VTimeline = genericComponent()({
  name: 'VTimeline',
  props: makeVTimelineProps(),
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      densityClasses
    } = useDensity(props);
    const {
      rtlClasses
    } = useRtl();
    provideDefaults({
      VTimelineDivider: {
        lineColor: toRef(() => props.lineColor)
      },
      VTimelineItem: {
        density: toRef(() => props.density),
        dotColor: toRef(() => props.dotColor),
        fillDot: toRef(() => props.fillDot),
        hideOpposite: toRef(() => props.hideOpposite),
        iconColor: toRef(() => props.iconColor),
        lineColor: toRef(() => props.lineColor),
        lineInset: toRef(() => props.lineInset),
        size: toRef(() => props.size)
      }
    });
    const sideClasses = computed(() => {
      const side = props.side ? props.side : props.density !== 'default' ? 'end' : null;
      return side && `v-timeline--side-${side}`;
    });
    const truncateClasses = computed(() => {
      const classes = ['v-timeline--truncate-line-start', 'v-timeline--truncate-line-end'];
      switch (props.truncateLine) {
        case 'both':
          return classes;
        case 'start':
          return classes[0];
        case 'end':
          return classes[1];
        default:
          return null;
      }
    });
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-timeline', `v-timeline--${props.direction}`, `v-timeline--align-${props.align}`, `v-timeline--justify-${props.justify}`, truncateClasses.value, {
        'v-timeline--inset-line': !!props.lineInset
      }, themeClasses.value, densityClasses.value, sideClasses.value, rtlClasses.value, props.class]),
      "style": normalizeStyle([{
        '--v-timeline-line-thickness': convertToUnit(props.lineThickness)
      }, props.style])
    }, slots));
    return {};
  }
});

// Types

const makeVTimePickerClockProps = propsFactory({
  allowedValues: Function,
  ampm: Boolean,
  color: String,
  disabled: Boolean,
  displayedValue: null,
  double: Boolean,
  format: {
    type: Function,
    default: val => val
  },
  max: {
    type: Number,
    required: true
  },
  min: {
    type: Number,
    required: true
  },
  scrollable: Boolean,
  readonly: Boolean,
  rotate: {
    type: Number,
    default: 0
  },
  step: {
    type: Number,
    default: 1
  },
  modelValue: {
    type: Number
  }
}, 'VTimePickerClock');
const VTimePickerClock = genericComponent()({
  name: 'VTimePickerClock',
  props: makeVTimePickerClockProps(),
  emits: {
    change: val => true,
    input: val => true
  },
  setup(props, {
    emit
  }) {
    const clockRef = ref(null);
    const innerClockRef = ref(null);
    const inputValue = ref(undefined);
    const isDragging = ref(false);
    const valueOnMouseDown = ref(null);
    const valueOnMouseUp = ref(null);
    const emitChangeDebounced = debounce(value => emit('change', value), 750);
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.color);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => props.color);
    const count = computed(() => props.max - props.min + 1);
    const roundCount = computed(() => props.double ? count.value / 2 : count.value);
    const degreesPerUnit = computed(() => 360 / roundCount.value);
    const degrees = computed(() => degreesPerUnit.value * Math.PI / 180);
    const displayedValue = computed(() => props.modelValue == null ? props.min : props.modelValue);
    const innerRadiusScale = computed(() => 0.62);
    const genChildren = computed(() => {
      const children = [];
      for (let value = props.min; value <= props.max; value = value + props.step) {
        children.push(value);
      }
      return children;
    });
    watch(() => props.modelValue, val => {
      inputValue.value = val;
    });
    function update(value) {
      if (inputValue.value !== value) {
        inputValue.value = value;
      }
      emit('input', value);
    }
    function isAllowed(value) {
      return !props.allowedValues || props.allowedValues(value);
    }
    function wheel(e) {
      if (!props.scrollable || props.disabled) return;
      e.preventDefault();
      const delta = Math.sign(-e.deltaY || 1);
      let value = displayedValue.value;
      do {
        value = value + delta;
        value = (value - props.min + count.value) % count.value + props.min;
      } while (!isAllowed(value) && value !== displayedValue.value);
      if (value !== props.displayedValue) {
        update(value);
      }
      emitChangeDebounced(value);
    }
    function isInner(value) {
      return props.double && value - props.min >= roundCount.value;
    }
    function handScale(value) {
      return isInner(value) ? innerRadiusScale.value : 1;
    }
    function getPosition(value) {
      const rotateRadians = props.rotate * Math.PI / 180;
      return {
        x: Math.sin((value - props.min) * degrees.value + rotateRadians) * handScale(value),
        y: -Math.cos((value - props.min) * degrees.value + rotateRadians) * handScale(value)
      };
    }
    function angleToValue(angle, insideClick) {
      const value = (Math.round(angle / degreesPerUnit.value) + (insideClick ? roundCount.value : 0)) % count.value + props.min;

      // Necessary to fix edge case when selecting left part of the value(s) at 12 o'clock
      if (angle < 360 - degreesPerUnit.value / 2) return value;
      return insideClick ? props.max - roundCount.value + 1 : props.min;
    }
    function getTransform(i) {
      const {
        x,
        y
      } = getPosition(i);
      return {
        left: `${Math.round(50 + x * 50)}%`,
        top: `${Math.round(50 + y * 50)}%`
      };
    }
    function euclidean(p0, p1) {
      const dx = p1.x - p0.x;
      const dy = p1.y - p0.y;
      return Math.sqrt(dx * dx + dy * dy);
    }
    function angle(center, p1) {
      const value = 2 * Math.atan2(p1.y - center.y - euclidean(center, p1), p1.x - center.x);
      return Math.abs(value * 180 / Math.PI);
    }
    function setMouseDownValue(value) {
      if (valueOnMouseDown.value === null) {
        valueOnMouseDown.value = value;
      }
      valueOnMouseUp.value = value;
      update(value);
    }
    function onDragMove(e) {
      e.preventDefault();
      if (!isDragging.value && e.type !== 'click' || !clockRef.value) return;
      const {
        width,
        top,
        left
      } = clockRef.value?.getBoundingClientRect();
      const {
        width: innerWidth
      } = innerClockRef.value?.getBoundingClientRect() ?? {
        width: 0
      };
      const {
        clientX,
        clientY
      } = 'touches' in e ? e.touches[0] : e;
      const center = {
        x: width / 2,
        y: -width / 2
      };
      const coords = {
        x: clientX - left,
        y: top - clientY
      };
      const handAngle = Math.round(angle(center, coords) - props.rotate + 360) % 360;
      const insideClick = props.double && euclidean(center, coords) < (innerWidth + innerWidth * innerRadiusScale.value) / 4;
      const checksCount = Math.ceil(15 / degreesPerUnit.value);
      let value;
      for (let i = 0; i < checksCount; i++) {
        value = angleToValue(handAngle + i * degreesPerUnit.value, insideClick);
        if (isAllowed(value)) return setMouseDownValue(value);
        value = angleToValue(handAngle - i * degreesPerUnit.value, insideClick);
        if (isAllowed(value)) return setMouseDownValue(value);
      }
    }
    function onMouseDown(e) {
      if (props.disabled) return;
      e.preventDefault();
      window.addEventListener('mousemove', onDragMove);
      window.addEventListener('touchmove', onDragMove);
      window.addEventListener('mouseup', onMouseUp);
      window.addEventListener('touchend', onMouseUp);
      valueOnMouseDown.value = null;
      valueOnMouseUp.value = null;
      isDragging.value = true;
      onDragMove(e);
    }
    function onMouseUp(e) {
      e.stopPropagation();
      removeListeners();
      isDragging.value = false;
      if (valueOnMouseUp.value !== null && isAllowed(valueOnMouseUp.value)) {
        emit('change', valueOnMouseUp.value);
      }
    }
    function removeListeners() {
      if (!IN_BROWSER) return;
      window.removeEventListener('mousemove', onDragMove);
      window.removeEventListener('touchmove', onDragMove);
      window.removeEventListener('mouseup', onMouseUp);
      window.removeEventListener('touchend', onMouseUp);
    }
    onScopeDispose(removeListeners);
    useRender(() => {
      return createElementVNode("div", {
        "class": normalizeClass([{
          'v-time-picker-clock': true,
          'v-time-picker-clock--indeterminate': props.modelValue == null,
          'v-time-picker-clock--readonly': props.readonly
        }]),
        "onMousedown": onMouseDown,
        "onTouchstart": onMouseDown,
        "onWheel": wheel,
        "ref": clockRef
      }, [createElementVNode("div", {
        "class": "v-time-picker-clock__inner",
        "ref": innerClockRef
      }, [createElementVNode("div", {
        "class": normalizeClass([{
          'v-time-picker-clock__hand': true,
          'v-time-picker-clock__hand--inner': isInner(props.modelValue)
        }, textColorClasses.value]),
        "style": normalizeStyle([{
          transform: `rotate(${props.rotate + degreesPerUnit.value * (displayedValue.value - props.min)}deg) scaleY(${handScale(displayedValue.value)})`
        }, textColorStyles.value])
      }, null), genChildren.value.map(value => {
        const isActive = value === displayedValue.value;
        return createElementVNode("div", {
          "class": normalizeClass([{
            'v-time-picker-clock__item': true,
            'v-time-picker-clock__item--active': isActive,
            'v-time-picker-clock__item--disabled': props.disabled || !isAllowed(value)
          }, isActive && backgroundColorClasses.value]),
          "style": normalizeStyle([getTransform(value), isActive && backgroundColorStyles.value])
        }, [createElementVNode("span", null, [props.format(value)])]);
      })])]);
    });
  }
});

// Types

const makeVTimePickerFieldProps = propsFactory({
  active: Boolean,
  color: String,
  disabled: Boolean,
  label: String,
  modelValue: String,
  error: String,
  showHint: Boolean,
  readonly: Boolean
}, 'VTimePickerField');
const VTimePickerField = genericComponent()({
  name: 'VTimePickerField',
  props: makeVTimePickerFieldProps(),
  emits: {
    'update:modelValue': v => true
  },
  setup(props, {
    emit
  }) {
    const {
      textColorClasses,
      textColorStyles
    } = useTextColor(() => props.color);
    const vTextInputRef = ref();
    const isFocused = shallowRef(false);
    function onKeydown(e) {
      if (['Backspace', 'Delete'].includes(e.key)) {
        e.preventDefault();
        const target = e.target;
        target.value = '';
        emit('update:modelValue', null);
      }
    }
    useRender(() => {
      return createVNode(VTextField, {
        "ref": vTextInputRef,
        "_as": "VTimePickerField",
        "autocomplete": "off",
        "class": normalizeClass(['v-time-picker-controls__time__field', {
          'v-time-picker-controls__time__field--active': props.active
        }, props.active ? textColorClasses.value : []]),
        "style": normalizeStyle(props.active ? textColorStyles.value : []),
        "disabled": props.disabled,
        "variant": "solo-filled",
        "inputmode": "numeric",
        "hideDetails": "auto",
        "aria-label": props.label,
        "aria-invalid": !!props.error,
        "aria-errormessage": props.error,
        "error": !!props.error,
        "hint": props.showHint ? props.label : undefined,
        "persistentHint": true,
        "flat": true,
        "modelValue": props.modelValue ?? (isFocused.value ? '' : '--'),
        "onUpdate:modelValue": v => emit('update:modelValue', v),
        "onKeydown": onKeydown,
        "onFocus": () => isFocused.value = true,
        "onBlur": () => isFocused.value = false
      }, null);
    });
    return forwardRefs({}, vTextInputRef);
  }
});

// Types

function pad(n, length = 2) {
  return String(n).padStart(length, '0');
}
function convert24to12(hour) {
  return hour ? (hour - 1) % 12 + 1 : 12;
}
function convert12to24(hour, period) {
  return hour % 12 + (period === 'pm' ? 12 : 0);
}
function extractInteger(v) {
  const digits = v.replaceAll(/\D/g, '');
  return digits.length > 0 ? Number(digits) : null;
}
function incrementHour(hour, increment, period) {
  {
    if (hour === 23 && increment) {
      return {
        value: 0
      };
    }
    if (hour === 0 && !increment) {
      return {
        value: 23
      };
    }
  }
  return {
    value: hour + (increment ? 1 : -1)
  };
}
function incrementMinuteOrSecond(val, increment) {
  if (val === 59 && increment) return 0;
  if (val === 0 && !increment) return 59;
  return val + (increment ? 1 : -1);
}

// Utilities

// Types

const makeTimeValidationProps = propsFactory({
  allowedHours: [Function, Array],
  allowedMinutes: [Function, Array],
  allowedSeconds: [Function, Array],
  max: String,
  min: String
}, 'time-validation');
function useTimeValidation(props) {
  const isAllowedHour = computed(() => {
    const minHour = props.min ? Number(props.min.split(':')[0]) : 0;
    const maxHour = props.max ? Number(props.max.split(':')[0]) : 23;
    return val => {
      if (val < minHour) return false;
      if (val > maxHour) return false;
      if (Array.isArray(props.allowedHours)) return props.allowedHours.includes(val);
      if (typeof props.allowedHours === 'function') return props.allowedHours(val);
      return true;
    };
  });
  const isAllowedMinute = computed(() => {
    const [minHour, minMinute] = props.min ? props.min.split(':').map(Number) : [0, 0];
    const [maxHour, maxMinute] = props.max ? props.max.split(':').map(Number) : [23, 59];
    const minTime = minHour * 60 + minMinute;
    const maxTime = maxHour * 60 + maxMinute;
    return (hour24hr, val) => {
      if (hour24hr !== null) {
        const time = 60 * hour24hr + val;
        if (time < minTime) return false;
        if (time > maxTime) return false;
      }
      if (Array.isArray(props.allowedMinutes)) return props.allowedMinutes.includes(val);
      if (typeof props.allowedMinutes === 'function') return props.allowedMinutes(val);
      return true;
    };
  });
  const isAllowedSecond = computed(() => {
    const [minHour, minMinute, minSecond] = props.min ? props.min.split(':').map(Number) : [0, 0, 0];
    const [maxHour, maxMinute, maxSecond] = props.max ? props.max.split(':').map(Number) : [23, 59, 59];
    const minTime = minHour * 3600 + minMinute * 60 + (minSecond || 0);
    const maxTime = maxHour * 3600 + maxMinute * 60 + (maxSecond || 0);
    return (hour24hr, minute, val) => {
      if (hour24hr !== null && minute !== null) {
        const time = 3600 * hour24hr + 60 * minute + val;
        if (time < minTime) return false;
        if (time > maxTime) return false;
      }
      if (Array.isArray(props.allowedSeconds)) return props.allowedSeconds.includes(val);
      if (typeof props.allowedSeconds === 'function') return props.allowedSeconds(val);
      return true;
    };
  });
  function findNextAllowed(type, value, increment, currentHour = null, currentMinute = null) {
    const isAllowed = type === 'hour' ? isAllowedHour.value : type === 'minute' ? v => isAllowedMinute.value(currentHour, v) : v => isAllowedSecond.value(currentHour, currentMinute, v);
    const nextValue = type === 'hour' ? v => incrementHour(v, increment).value : v => incrementMinuteOrSecond(v, increment);
    const limit = type === 'hour' ? 24 : 60;
    for (let i = 1; i <= limit; i++) {
      value = nextValue(value);
      if (isAllowed(value)) break;
    }
    return value;
  }
  return {
    isAllowedHour,
    isAllowedMinute,
    isAllowedSecond,
    findNextAllowed
  };
}

// Types

const makeVTimePickerControlsProps = propsFactory({
  ampm: Boolean,
  color: String,
  disabled: Boolean,
  inputHints: Boolean,
  hour: [Number, String],
  minute: [Number, String],
  second: [Number, String],
  period: String,
  readonly: Boolean,
  useSeconds: Boolean,
  value: Number,
  viewMode: String,
  ...makeTimeValidationProps()
}, 'VTimePickerControls');
const VTimePickerControls = genericComponent()({
  name: 'VTimePickerControls',
  props: makeVTimePickerControlsProps(),
  emits: {
    'update:period': data => true,
    'update:viewMode': data => true,
    'update:hour': v => true,
    'update:minute': v => true,
    'update:second': v => true
  },
  setup(props, {
    emit
  }) {
    const {
      t
    } = useLocale();
    const {
      isAllowedHour,
      isAllowedMinute,
      isAllowedSecond,
      findNextAllowed
    } = useTimeValidation(props);
    const currentHour = computed(() => props.hour !== null ? props.ampm ? convert12to24(Number(props.hour), props.period ?? 'am') : Number(props.hour) : null);
    const currentMinute = computed(() => props.minute !== null ? Number(props.minute) : null);
    const isHourValid = computed(() => {
      if (props.hour === null) return true;
      return isAllowedHour.value?.(Number(currentHour.value)) ?? true;
    });
    const isMinuteValid = computed(() => {
      if (props.minute === null) return true;
      return isAllowedMinute.value?.(currentHour.value, Number(props.minute)) ?? true;
    });
    const isSecondValid = computed(() => {
      if (props.second === null) return true;
      return isAllowedSecond.value?.(currentHour.value, currentMinute.value, Number(props.second)) ?? true;
    });
    const transformHours = {
      in: v => {
        if (v == null || isNaN(Number(v))) return null;
        const val = Number(v);
        return props.ampm ? pad(convert24to12(val)) : pad(val);
      },
      out: v => {
        if (isNaN(Number(v)) || v == null || v === '') return null;
        const val = typeof v === 'string' ? extractInteger(v) : Number(v);
        if (val === null) return null;
        return props.ampm ? convert12to24(val, props.period ?? 'am') : clamp(val, 0, 23);
      }
    };
    const hour = useProxiedModel(props, 'hour', undefined, transformHours.in, transformHours.out);
    const transformMinutesOrSeconds = {
      in: v => v != null && !isNaN(Number(v)) ? pad(`${v}`) : null,
      out: v => {
        if (isNaN(Number(v)) || v == null || v === '') return null;
        const val = typeof v === 'string' ? extractInteger(v) : Number(v);
        return val !== null ? clamp(val, 0, 59) : null;
      }
    };
    const minute = useProxiedModel(props, 'minute', undefined, transformMinutesOrSeconds.in, transformMinutesOrSeconds.out);
    const second = useProxiedModel(props, 'second', undefined, transformMinutesOrSeconds.in, transformMinutesOrSeconds.out);
    function onHourFieldKeydown(e) {
      if (!['ArrowUp', 'ArrowDown'].includes(e.key)) return;
      e.preventDefault();
      e.stopPropagation();
      const isAm = props.period === 'am';
      const current = props.ampm ? convert12to24(Number(hour.value ?? 0), isAm ? 'am' : 'pm') : Number(hour.value ?? 0);
      const next = findNextAllowed('hour', current, e.key === 'ArrowUp');
      const togglePeriod = isAm && next >= 12 || !isAm && next < 12;
      if (props.ampm && togglePeriod) {
        emit('update:period', props.period === 'am' ? 'pm' : 'am');
        nextTick(() => hour.value = pad(next));
      } else {
        hour.value = pad(next);
      }
    }
    function onMinuteFieldKeydown(e) {
      if (!['ArrowUp', 'ArrowDown'].includes(e.key)) return;
      e.preventDefault();
      e.stopPropagation();
      const current = Number(minute.value ?? 0);
      const next = findNextAllowed('minute', current, e.key === 'ArrowUp', currentHour.value);
      minute.value = pad(next);
    }
    function onSecondFieldKeydown(e) {
      if (!['ArrowUp', 'ArrowDown'].includes(e.key)) return;
      e.preventDefault();
      e.stopPropagation();
      const current = Number(second.value ?? 0);
      const next = findNextAllowed('second', current, e.key === 'ArrowUp', currentHour.value, currentMinute.value);
      second.value = pad(next);
    }
    function createInputInterceptor(valueTransformOut, compare, apply) {
      return e => {
        if (!e.data) return;
        const inputElement = e.target;
        const {
          value: existingTxt,
          selectionStart,
          selectionEnd
        } = inputElement ?? {};
        if (extractInteger(e.data) === null) {
          e.preventDefault();
          return;
        }
        const potentialNewInputVal = existingTxt ? existingTxt.slice(0, selectionStart) + e.data + existingTxt.slice(selectionEnd) : e.data;
        if (potentialNewInputVal.length > 2) {
          if (selectionStart === selectionEnd && selectionEnd === 0 && e.data.trim().startsWith('0')) {
            e.preventDefault();
            inputElement.value = potentialNewInputVal.trim().substring(0, 2);
            apply(inputElement.value);
            if (e.data.trim().length === 1) {
              inputElement.setSelectionRange(1, 1);
            }
            return;
          }
          if (selectionStart === selectionEnd && selectionEnd === 1 && existingTxt.startsWith('0')) {
            e.preventDefault();
            inputElement.value = potentialNewInputVal.trim().substring(0, 2);
            apply(inputElement.value);
            return;
          }
          const maxValue = props.viewMode === 'hour' ? props.ampm ? 12 : 23 : 59;
          const value = extractInteger(potentialNewInputVal);
          if (value > maxValue) {
            e.preventDefault();
            inputElement.value = pad(String(extractInteger(e.data)).substring(0, 2));
            apply(inputElement.value);
            return;
          }
        }
        const potentialNewNumber = valueTransformOut(potentialNewInputVal);
        if (compare(potentialNewNumber)) {
          // ignore input when results in the same number
          // prevents typing more digits
          e.preventDefault();
        }
      };
    }
    function setPeriod(val) {
      emit('update:period', val);
    }
    const hourInputRef = ref();
    const minuteInputRef = ref();
    const secondInputRef = ref();
    watch(() => props.viewMode, (_, old) => {
      switch (old) {
        case 'hour':
          hourInputRef.value.blur();
          break;
        case 'minute':
          minuteInputRef.value.blur();
          break;
        case 'second':
          secondInputRef.value.blur();
          break;
      }
    });
    const hourInputFilter = createInputInterceptor(transformHours.out, v => transformHours.in(v) === hour.value, v => hour.value = v);
    const minuteInputFilter = createInputInterceptor(transformMinutesOrSeconds.out, v => transformMinutesOrSeconds.in(v) === minute.value, v => minute.value = v);
    const secondInputFilter = createInputInterceptor(transformMinutesOrSeconds.out, v => transformMinutesOrSeconds.in(v) === second.value, v => second.value = v);
    useRender(() => {
      return createElementVNode("div", {
        "class": "v-time-picker-controls"
      }, [createElementVNode("div", {
        "class": normalizeClass({
          'v-time-picker-controls__time': true,
          'v-time-picker-controls__time--with-ampm': props.ampm,
          'v-time-picker-controls__time--with-seconds': props.useSeconds
        })
      }, [createVNode(VTimePickerField, {
        "ref": hourInputRef,
        "active": props.viewMode === 'hour',
        "color": props.color,
        "disabled": props.disabled,
        "label": t('$vuetify.timePicker.hour'),
        "showHint": props.inputHints,
        "error": isHourValid.value ? undefined : t('$vuetify.timePicker.notAllowed'),
        "modelValue": hour.value,
        "onUpdate:modelValue": v => hour.value = v,
        "onKeydown": onHourFieldKeydown,
        "onBeforeinput": hourInputFilter,
        "onFocus": () => emit('update:viewMode', 'hour')
      }, null), createElementVNode("span", {
        "class": "v-time-picker-controls__time__separator"
      }, [createTextVNode(":")]), createVNode(VTimePickerField, {
        "ref": minuteInputRef,
        "active": props.viewMode === 'minute',
        "color": props.color,
        "disabled": props.disabled,
        "label": t('$vuetify.timePicker.minute'),
        "showHint": props.inputHints,
        "error": isMinuteValid.value ? undefined : t('$vuetify.timePicker.notAllowed'),
        "modelValue": minute.value,
        "onUpdate:modelValue": v => minute.value = v,
        "onKeydown": onMinuteFieldKeydown,
        "onBeforeinput": minuteInputFilter,
        "onFocus": () => emit('update:viewMode', 'minute')
      }, null), props.useSeconds && createElementVNode("span", {
        "key": "secondsDivider",
        "class": "v-time-picker-controls__time__separator"
      }, [createTextVNode(":")]), props.useSeconds && createElementVNode(Fragment, null, [createVNode(VTimePickerField, {
        "key": "secondsVal",
        "ref": secondInputRef,
        "active": props.viewMode === 'second',
        "color": props.color,
        "disabled": props.disabled,
        "label": t('$vuetify.timePicker.second'),
        "showHint": props.inputHints,
        "error": isSecondValid.value ? undefined : t('$vuetify.timePicker.notAllowed'),
        "modelValue": second.value,
        "onUpdate:modelValue": v => second.value = v,
        "onKeydown": onSecondFieldKeydown,
        "onBeforeinput": secondInputFilter,
        "onFocus": () => emit('update:viewMode', 'second')
      }, null)]), props.ampm && createElementVNode("div", {
        "class": "v-time-picker-controls__ampm"
      }, [createVNode(VBtn, {
        "active": props.period === 'am',
        "color": props.period === 'am' ? props.color : undefined,
        "class": normalizeClass({
          'v-time-picker-controls__ampm__am': true,
          'v-time-picker-controls__ampm__btn': true,
          'v-time-picker-controls__ampm__btn__active': props.period === 'am'
        }),
        "disabled": props.disabled,
        "text": t('$vuetify.timePicker.am'),
        "variant": props.disabled && props.period === 'am' ? 'elevated' : 'tonal',
        "onClick": () => props.period !== 'am' ? setPeriod('am') : null
      }, null), createVNode(VBtn, {
        "active": props.period === 'pm',
        "color": props.period === 'pm' ? props.color : undefined,
        "class": normalizeClass({
          'v-time-picker-controls__ampm__pm': true,
          'v-time-picker-controls__ampm__btn': true,
          'v-time-picker-controls__ampm__btn__active': props.period === 'pm'
        }),
        "disabled": props.disabled,
        "text": t('$vuetify.timePicker.pm'),
        "variant": props.disabled && props.period === 'pm' ? 'elevated' : 'tonal',
        "onClick": () => props.period !== 'pm' ? setPeriod('pm') : null
      }, null)])])]);
    });
    return {};
  }
});

// Types

const makeVTimePickerProps = propsFactory({
  disabled: Boolean,
  format: {
    type: String,
    default: 'ampm'
  },
  viewMode: {
    type: String,
    default: 'hour'
  },
  period: {
    type: String,
    default: 'am',
    validator: v => ['am', 'pm'].includes(v)
  },
  modelValue: null,
  readonly: Boolean,
  scrollable: Boolean,
  useSeconds: Boolean,
  variant: {
    type: String,
    default: 'dial'
  },
  ...makeTimeValidationProps(),
  ...omit(makeVPickerProps({
    title: '$vuetify.timePicker.title'
  }), ['landscape']),
  ...makeDensityProps()
}, 'VTimePicker');
const VTimePicker = genericComponent()({
  name: 'VTimePicker',
  props: makeVTimePickerProps(),
  emits: {
    'update:hour': val => true,
    'update:minute': val => true,
    'update:period': val => true,
    'update:second': val => true,
    'update:modelValue': val => true,
    'update:viewMode': val => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    const {
      densityClasses
    } = useDensity(props);
    const inputHour = ref(null);
    const inputMinute = ref(null);
    const inputSecond = ref(null);
    const lazyInputHour = ref(null);
    const lazyInputMinute = ref(null);
    const lazyInputSecond = ref(null);
    const period = useProxiedModel(props, 'period', 'am');
    const viewMode = useProxiedModel(props, 'viewMode', 'hour');
    const controlsRef = ref(null);
    const clockRef = ref(null);
    const isAmPm = computed(() => {
      return props.format === 'ampm';
    });
    const {
      isAllowedHour,
      isAllowedMinute,
      isAllowedSecond
    } = useTimeValidation(props);
    const shouldClear = toRef(() => {
      return props.modelValue !== null && inputHour.value === null && inputMinute.value === null && (!props.useSeconds || inputSecond.value === null);
    });
    function emitValue() {
      const value = genValue();
      if (value !== null && value !== props.modelValue) {
        emit('update:modelValue', value);
      }
      if (shouldClear.value) {
        emit('update:modelValue', null);
      }
    }
    watch(inputHour, emitValue);
    watch(inputMinute, emitValue);
    watch(inputSecond, emitValue);
    watch(period, (newPeriod, oldPeriod) => {
      if (inputHour.value == null || newPeriod === oldPeriod) return;
      if (newPeriod === 'pm' && inputHour.value < 12) {
        inputHour.value = inputHour.value + 12;
      } else if (newPeriod === 'am' && inputHour.value >= 12) {
        inputHour.value = inputHour.value - 12;
      }
    });
    watch(() => props.modelValue, val => setInputData(val));
    watch(() => props.useSeconds, (val, old) => {
      if (old && !val && viewMode.value === 'second') {
        viewMode.value = 'minute';
      }
      if (!val && inputSecond.value !== null) {
        inputSecond.value = null;
      }
    });
    onMounted(() => {
      setInputData(props.modelValue);
    });
    function genValue() {
      if (inputHour.value != null && inputMinute.value != null && (!props.useSeconds || inputSecond.value != null)) {
        return `${pad(inputHour.value)}:${pad(inputMinute.value)}` + (props.useSeconds ? `:${pad(inputSecond.value)}` : '');
      }
      return null;
    }
    function setInputData(value) {
      if (value == null || value === '') {
        inputHour.value = null;
        inputMinute.value = null;
        inputSecond.value = null;
      } else if (value instanceof Date) {
        inputHour.value = value.getHours();
        inputMinute.value = value.getMinutes();
        inputSecond.value = value.getSeconds();
      } else {
        const [hour,, minute,, second, period] = value.trim().toLowerCase().match(/^(\d+):(\d+)(:(\d+))?([ap]m)?$/) || new Array(6);
        inputHour.value = period ? convert12to24(parseInt(hour, 10), period) : parseInt(hour, 10);
        inputMinute.value = parseInt(minute, 10);
        inputSecond.value = parseInt(second || 0, 10);
      }
      period.value = inputHour.value == null || inputHour.value < 12 ? 'am' : 'pm';
    }
    function onInput(value) {
      if (viewMode.value === 'hour') {
        inputHour.value = isAmPm.value ? convert12to24(value, period.value) : value;
      } else if (viewMode.value === 'minute') {
        inputMinute.value = value;
      } else {
        inputSecond.value = value;
      }
    }
    function onChange(value) {
      switch (viewMode.value || 'hour') {
        case 'hour':
          emit('update:hour', value);
          break;
        case 'minute':
          emit('update:minute', value);
          break;
        case 'second':
          emit('update:second', value);
          break;
      }
      const emitChange = inputHour.value !== null && inputMinute.value !== null && (props.useSeconds ? inputSecond.value !== null : true);
      if (viewMode.value === 'hour') {
        viewMode.value = 'minute';
      } else if (props.useSeconds && viewMode.value === 'minute') {
        viewMode.value = 'second';
      }
      if (inputHour.value === lazyInputHour.value && inputMinute.value === lazyInputMinute.value && (!props.useSeconds || inputSecond.value === lazyInputSecond.value)) return;
      const time = genValue();
      if (time === null) return;
      lazyInputHour.value = inputHour.value;
      lazyInputMinute.value = inputMinute.value;
      props.useSeconds && (lazyInputSecond.value = inputSecond.value);
      emitChange && emitValue();
    }
    useRender(() => {
      const pickerProps = omit(VPicker.filterProps(props), ['hideHeader']);
      const timePickerControlsProps = VTimePickerControls.filterProps(props);
      const timePickerClockProps = VTimePickerClock.filterProps(omit(props, ['format', 'modelValue', 'min', 'max']));
      const clockValidation = viewMode.value === 'hour' ? isAllowedHour.value : viewMode.value === 'minute' ? v => isAllowedMinute.value(inputHour.value, v) : v => isAllowedSecond.value(inputHour.value, inputMinute.value, v);
      return createVNode(VPicker, mergeProps(pickerProps, {
        "color": undefined,
        "class": ['v-time-picker', `v-time-picker--variant-${props.variant}`, props.class, densityClasses.value],
        "hideHeader": props.hideHeader && props.variant !== 'input',
        "style": props.style
      }), {
        title: () => slots.title?.() ?? createElementVNode("div", {
          "class": "v-time-picker__title"
        }, [t(props.title)]),
        header: () => createVNode(VTimePickerControls, mergeProps(timePickerControlsProps, {
          "ampm": isAmPm.value,
          "hour": inputHour.value,
          "minute": inputMinute.value,
          "period": period.value,
          "second": inputSecond.value,
          "viewMode": viewMode.value,
          "inputHints": props.variant === 'input',
          "onUpdate:hour": val => inputHour.value = val,
          "onUpdate:minute": val => inputMinute.value = val,
          "onUpdate:second": val => inputSecond.value = val,
          "onUpdate:period": val => period.value = val,
          "onUpdate:viewMode": value => viewMode.value = value,
          "ref": controlsRef
        }), null),
        default: () => createVNode(VTimePickerClock, mergeProps(timePickerClockProps, {
          "allowedValues": clockValidation,
          "double": viewMode.value === 'hour' && !isAmPm.value,
          "format": viewMode.value === 'hour' ? isAmPm.value ? convert24to12 : val => val : val => pad(val, 2),
          "max": viewMode.value === 'hour' ? isAmPm.value && period.value === 'am' ? 11 : 23 : 59,
          "min": viewMode.value === 'hour' && isAmPm.value && period.value === 'pm' ? 12 : 0,
          "size": 20,
          "step": viewMode.value === 'hour' ? 1 : 5,
          "modelValue": viewMode.value === 'hour' ? inputHour.value : viewMode.value === 'minute' ? inputMinute.value : inputSecond.value,
          "onChange": onChange,
          "onInput": onInput,
          "ref": clockRef
        }), null),
        actions: slots.actions
      });
    });
  }
});

const makeVToolbarItemsProps = propsFactory({
  ...makeComponentProps(),
  ...makeVariantProps({
    variant: 'text'
  })
}, 'VToolbarItems');
const VToolbarItems = genericComponent()({
  name: 'VToolbarItems',
  props: makeVToolbarItemsProps(),
  setup(props, {
    slots
  }) {
    provideDefaults({
      VBtn: {
        color: toRef(() => props.color),
        height: 'inherit',
        variant: toRef(() => props.variant)
      }
    });
    useRender(() => createElementVNode("div", {
      "class": normalizeClass(['v-toolbar-items', props.class]),
      "style": normalizeStyle(props.style)
    }, [slots.default?.()]));
    return {};
  }
});

// Types

const makeVTreeviewGroupProps = propsFactory({
  ...omit(makeVListGroupProps({
    collapseIcon: '$treeviewCollapse',
    expandIcon: '$treeviewExpand'
  }), ['subgroup'])
}, 'VTreeviewGroup');
const VTreeviewGroup = genericComponent()({
  name: 'VTreeviewGroup',
  props: makeVTreeviewGroupProps(),
  setup(props, {
    slots
  }) {
    const vListGroupRef = ref();
    const toggleIcon = computed(() => vListGroupRef.value?.isOpen ? props.collapseIcon : props.expandIcon);
    const activatorDefaults = computed(() => ({
      VTreeviewItem: {
        prependIcon: undefined,
        appendIcon: undefined,
        toggleIcon: toggleIcon.value
      }
    }));
    useRender(() => {
      const listGroupProps = VListGroup.filterProps(props);
      return createVNode(VListGroup, mergeProps(listGroupProps, {
        "ref": vListGroupRef,
        "class": ['v-treeview-group', props.class],
        "subgroup": true
      }), {
        ...slots,
        activator: slots.activator ? slotProps => createElementVNode(Fragment, null, [createVNode(VDefaultsProvider, {
          "defaults": activatorDefaults.value
        }, {
          default: () => [slots.activator?.(slotProps)]
        })]) : undefined
      });
    });
    return {};
  }
});

// Types

const VTreeviewSymbol = Symbol.for('vuetify:v-treeview');

// Types

const makeVTreeviewItemProps = propsFactory({
  loading: Boolean,
  hideActions: Boolean,
  hasCustomPrepend: Boolean,
  indentLines: Array,
  toggleIcon: IconValue,
  ...makeVListItemProps({
    slim: true
  })
}, 'VTreeviewItem');
const VTreeviewItem = genericComponent()({
  name: 'VTreeviewItem',
  props: makeVTreeviewItemProps(),
  emits: {
    toggleExpand: value => true
  },
  setup(props, {
    slots,
    emit
  }) {
    const visibleIds = inject$1(VTreeviewSymbol, {
      visibleIds: ref()
    }).visibleIds;
    const vListItemRef = ref();
    const isActivatableGroupActivator = computed(() => vListItemRef.value?.root.activatable.value && vListItemRef.value?.isGroupActivator);
    const isActivatable = computed(() => !props.disabled && props.link !== false && isActivatableGroupActivator.value);
    const isFiltered = computed(() => visibleIds.value && !visibleIds.value.has(toRaw(vListItemRef.value?.id)));
    function activateGroupActivator(e) {
      vListItemRef.value?.activate(!vListItemRef.value?.isActivated, e);
    }
    function onClickAction(e) {
      e.preventDefault();
      e.stopPropagation();
      emit('toggleExpand', e);
    }
    useRender(() => {
      const listItemProps = VListItem.filterProps(props);
      const hasPrepend = slots.prepend || props.toggleIcon || props.indentLines || props.prependIcon || props.prependAvatar;
      return createVNode(VListItem, mergeProps({
        "ref": vListItemRef
      }, listItemProps, {
        "active": vListItemRef.value?.isActivated || undefined,
        "class": ['v-treeview-item', {
          'v-treeview-item--activatable-group-activator': isActivatableGroupActivator.value,
          'v-treeview-item--filtered': isFiltered.value
        }, props.class],
        "role": "treeitem",
        "ripple": false,
        "onClick": isActivatable.value ? activateGroupActivator : undefined
      }), {
        ...slots,
        prepend: hasPrepend ? slotProps => {
          return createElementVNode(Fragment, null, [props.indentLines && props.indentLines.length > 0 ? createElementVNode("div", {
            "key": "indent-lines",
            "class": "v-treeview-indent-lines",
            "style": {
              '--v-indent-parts': props.indentLines.length
            }
          }, [props.indentLines.map(type => createElementVNode("div", {
            "class": normalizeClass(`v-treeview-indent-line v-treeview-indent-line--${type}`)
          }, null))]) : '', !props.hideActions && createVNode(VListItemAction, {
            "start": true
          }, {
            default: () => [props.toggleIcon ? createElementVNode(Fragment, null, [!slots.toggle ? createVNode(VBtn, {
              "key": "prepend-toggle",
              "density": "compact",
              "icon": props.toggleIcon,
              "loading": props.loading,
              "variant": "text",
              "onClick": onClickAction
            }, {
              loader: () => createVNode(VProgressCircular, {
                "indeterminate": "disable-shrink",
                "size": "20",
                "width": "2"
              }, null)
            }) : createVNode(VDefaultsProvider, {
              "key": "prepend-defaults",
              "defaults": {
                VBtn: {
                  density: 'compact',
                  icon: props.toggleIcon,
                  variant: 'text',
                  loading: props.loading
                },
                VProgressCircular: {
                  indeterminate: 'disable-shrink',
                  size: 20,
                  width: 2
                }
              }
            }, {
              default: () => [slots.toggle({
                ...slotProps,
                loading: props.loading,
                props: {
                  onClick: onClickAction
                }
              })]
            })]) : createElementVNode("div", {
              "class": "v-treeview-item__level"
            }, null)]
          }), !props.hasCustomPrepend ? createElementVNode(Fragment, null, [slots.prepend?.(slotProps), props.prependAvatar && createVNode(VAvatar, {
            "key": "prepend-avatar",
            "density": props.density,
            "image": props.prependAvatar
          }, null), props.prependIcon && createVNode(VIcon, {
            "key": "prepend-icon",
            "density": props.density,
            "icon": props.prependIcon
          }, null)]) : createVNode(VDefaultsProvider, {
            "key": "prepend-defaults",
            "defaults": {
              VAvatar: {
                density: props.density,
                image: props.appendAvatar
              },
              VIcon: {
                density: props.density,
                icon: props.appendIcon
              },
              VListItemAction: {
                start: true
              }
            }
          }, {
            default: () => [slots.prepend?.(slotProps)]
          })]);
        } : undefined
      });
    });
    return forwardRefs({}, vListItemRef);
  }
});

// Types

const makeVTreeviewChildrenProps = propsFactory({
  fluid: Boolean,
  disabled: Boolean,
  loadChildren: Function,
  loadingIcon: {
    type: String,
    default: '$loading'
  },
  items: Array,
  openOnClick: {
    type: Boolean,
    default: undefined
  },
  indeterminateIcon: {
    type: IconValue,
    default: '$checkboxIndeterminate'
  },
  falseIcon: IconValue,
  trueIcon: IconValue,
  returnObject: Boolean,
  activatable: Boolean,
  selectable: Boolean,
  selectedColor: String,
  selectStrategy: [String, Function, Object],
  index: Number,
  isLastGroup: Boolean,
  separateRoots: Boolean,
  parentIndentLines: Array,
  indentLinesVariant: String,
  path: {
    type: Array,
    default: () => []
  },
  ...pick(makeVTreeviewItemProps(), ['hideActions']),
  ...makeDensityProps()
}, 'VTreeviewChildren');
const VTreeviewChildren = genericComponent()({
  name: 'VTreeviewChildren',
  props: makeVTreeviewChildrenProps(),
  setup(props, {
    slots
  }) {
    const isLoading = reactive(new Set());
    const activatorItems = ref([]);
    const isClickOnOpen = computed(() => !props.disabled && (props.openOnClick != null ? props.openOnClick : props.selectable && !props.activatable));
    async function checkChildren(item) {
      try {
        if (!props.items?.length || !props.loadChildren) return;
        if (item?.children?.length === 0) {
          isLoading.add(item.value);
          await props.loadChildren(item.raw);
        }
      } finally {
        isLoading.delete(item.value);
      }
    }
    function selectItem(select, isSelected) {
      if (props.selectable) {
        select(isSelected);
      }
    }
    return () => slots.default?.() ?? props.items?.map((item, index, items) => {
      const {
        children,
        props: itemProps
      } = item;
      const loading = isLoading.has(item.value);
      const nextItemHasChildren = !!items.at(index + 1)?.children;
      const depth = props.path?.length ?? 0;
      const isLast = items.length - 1 === index;
      const nodePositionProps = {
        index,
        depth,
        isFirst: index === 0,
        isLast,
        path: [...props.path, index]
      };
      const indentLines = getIndentLines({
        depth,
        isLast,
        isLastGroup: props.isLastGroup,
        leafLinks: !props.hideActions && !props.fluid,
        separateRoots: props.separateRoots,
        parentIndentLines: props.parentIndentLines,
        variant: props.indentLinesVariant
      });
      const treeItemProps = {
        ...itemProps,
        hideActions: props.hideActions,
        indentLines: children ? indentLines.node : indentLines.leaf
      };
      const slotsWithItem = {
        toggle: slots.toggle ? slotProps => slots.toggle?.({
          ...slotProps,
          ...nodePositionProps,
          item: item.raw,
          internalItem: item,
          loading
        }) : undefined,
        prepend: slotProps => createElementVNode(Fragment, null, [props.selectable && (!children || children && !['leaf', 'single-leaf'].includes(props.selectStrategy)) && createVNode(VListItemAction, {
          "start": true
        }, {
          default: () => [createVNode(VCheckboxBtn, {
            "key": item.value,
            "modelValue": slotProps.isSelected,
            "disabled": props.disabled || itemProps.disabled,
            "loading": loading,
            "color": props.selectedColor,
            "density": props.density,
            "indeterminate": slotProps.isIndeterminate,
            "indeterminateIcon": props.indeterminateIcon,
            "falseIcon": props.falseIcon,
            "trueIcon": props.trueIcon,
            "onUpdate:modelValue": v => selectItem(slotProps.select, v),
            "onClick": e => e.stopPropagation(),
            "onKeydown": e => {
              if (!['Enter', 'Space'].includes(e.key)) return;
              e.stopPropagation();
              selectItem(slotProps.select, slotProps.isSelected);
            }
          }, null)]
        }), slots.prepend?.({
          ...slotProps,
          ...nodePositionProps,
          item: item.raw,
          internalItem: item
        })]),
        append: slots.append ? slotProps => slots.append?.({
          ...slotProps,
          ...nodePositionProps,
          item: item.raw,
          internalItem: item
        }) : undefined,
        title: slots.title ? slotProps => slots.title?.({
          ...slotProps,
          item: item.raw,
          internalItem: item
        }) : undefined,
        subtitle: slots.subtitle ? slotProps => slots.subtitle?.({
          ...slotProps,
          item: item.raw,
          internalItem: item
        }) : undefined
      };
      const treeviewGroupProps = VTreeviewGroup.filterProps(itemProps);
      const treeviewChildrenProps = VTreeviewChildren.filterProps({
        ...props,
        ...nodePositionProps
      });
      const footerProps = {
        hideActions: props.hideActions,
        indentLines: indentLines.footer
      };
      return children ? createVNode(VTreeviewGroup, mergeProps(treeviewGroupProps, {
        "value": props.returnObject ? item.raw : treeviewGroupProps?.value,
        "rawId": treeviewGroupProps?.value
      }), {
        activator: ({
          props: activatorProps,
          isOpen
        }) => {
          const listItemProps = {
            ...treeItemProps,
            ...activatorProps,
            value: treeItemProps?.value,
            ariaExpanded: isOpen,
            onToggleExpand: [() => checkChildren(item), activatorProps.onClick],
            onClick: props.disabled || treeItemProps.disabled ? undefined : isClickOnOpen.value ? [() => checkChildren(item), activatorProps.onClick] : () => selectItem(activatorItems.value[index]?.select, !activatorItems.value[index]?.isSelected)
          };
          return renderSlot(slots.header, {
            props: listItemProps,
            item: item.raw,
            internalItem: item,
            loading
          }, () => createVNode(VTreeviewItem, mergeProps({
            "ref": el => activatorItems.value[index] = el
          }, listItemProps, {
            "hasCustomPrepend": !!slots.prepend,
            "value": props.returnObject ? item.raw : itemProps.value,
            "loading": loading
          }), slotsWithItem));
        },
        default: () => createElementVNode(Fragment, null, [createVNode(VTreeviewChildren, mergeProps(treeviewChildrenProps, {
          "items": children,
          "indentLinesVariant": props.indentLinesVariant,
          "parentIndentLines": indentLines.children,
          "isLastGroup": nextItemHasChildren,
          "returnObject": props.returnObject
        }), slots), slots.footer?.({
          props: footerProps,
          item: item.raw,
          internalItem: item,
          loading
        })])
      }) : renderSlot(slots.item, {
        props: treeItemProps,
        item: item.raw,
        internalItem: item,
        ...nodePositionProps
      }, () => {
        if (item.type === 'divider') {
          return renderSlot(slots.divider, {
            props: item.raw
          }, () => createVNode(VDivider, item.props, null));
        }
        if (item.type === 'subheader') {
          return renderSlot(slots.subheader, {
            props: item.raw
          }, () => createVNode(VListSubheader, item.props, null));
        }
        return createVNode(VTreeviewItem, mergeProps(treeItemProps, {
          "hasCustomPrepend": !!slots.prepend,
          "value": props.returnObject ? toRaw(item.raw) : treeItemProps.value
        }), slotsWithItem);
      });
    });
  }
});

function flatten(items, flat = []) {
  for (const item of items) {
    flat.push(item);
    if (item.children) flatten(item.children, flat);
  }
  return flat;
}
const makeVTreeviewProps = propsFactory({
  openAll: Boolean,
  indentLines: [Boolean, String],
  indentLinesColor: String,
  indentLinesOpacity: [String, Number],
  search: String,
  hideNoData: Boolean,
  noDataText: {
    type: String,
    default: '$vuetify.noDataText'
  },
  ...makeFilterProps({
    filterKeys: ['title']
  }),
  ...omit(makeVTreeviewChildrenProps(), ['index', 'path', 'indentLinesVariant', 'parentIndentLines', 'isLastGroup']),
  ...omit(makeVListProps({
    collapseIcon: '$treeviewCollapse',
    expandIcon: '$treeviewExpand',
    slim: true
  }), ['nav', 'openStrategy']),
  modelValue: Array
}, 'VTreeview');
const VTreeview = genericComponent()({
  name: 'VTreeview',
  props: makeVTreeviewProps(),
  emits: {
    'update:opened': val => true,
    'update:activated': val => true,
    'update:selected': val => true,
    'update:modelValue': val => true,
    'click:open': value => true,
    'click:select': value => true
  },
  setup(props, {
    slots,
    emit
  }) {
    const {
      t
    } = useLocale();
    const {
      items
    } = useListItems(props);
    const activeColor = toRef(() => props.activeColor);
    const baseColor = toRef(() => props.baseColor);
    const color = toRef(() => props.color);
    const activated = useProxiedModel(props, 'activated');
    const _selected = useProxiedModel(props, 'selected');
    const selected = computed({
      get: () => props.modelValue ?? _selected.value,
      set(val) {
        _selected.value = val;
        emit('update:modelValue', val);
      }
    });
    const vListRef = ref();
    const opened = computed(() => props.openAll ? openAll(items.value) : props.opened);
    const flatItems = computed(() => flatten(items.value));
    const search = toRef(() => props.search);
    const {
      filteredItems
    } = useFilter(props, flatItems, search);
    const visibleIds = computed(() => {
      if (!search.value) return null;
      const getPath = vListRef.value?.getPath;
      if (!getPath) return null;
      return new Set(filteredItems.value.flatMap(item => {
        const itemVal = props.returnObject ? item.raw : item.props.value;
        return [...getPath(itemVal), ...getChildren(itemVal)].map(toRaw);
      }));
    });
    function getChildren(id) {
      const arr = [];
      const queue = (vListRef.value?.children.get(toRaw(id)) ?? []).slice();
      while (queue.length) {
        const child = queue.shift();
        if (!child) continue;
        arr.push(child);
        queue.push(...(vListRef.value?.children.get(child) ?? []).slice());
      }
      return arr;
    }
    function openAll(items) {
      let ids = [];
      for (const i of items) {
        if (!i.children) continue;
        ids.push(props.returnObject ? toRaw(i.raw) : i.value);
        if (i.children) {
          ids = ids.concat(openAll(i.children));
        }
      }
      return ids;
    }
    provide(VTreeviewSymbol, {
      visibleIds
    });
    provideDefaults({
      VTreeviewGroup: {
        activeColor,
        baseColor,
        color,
        collapseIcon: toRef(() => props.collapseIcon),
        expandIcon: toRef(() => props.expandIcon)
      },
      VTreeviewItem: {
        activeClass: toRef(() => props.activeClass),
        activeColor,
        baseColor,
        color,
        density: toRef(() => props.density),
        disabled: toRef(() => props.disabled),
        lines: toRef(() => props.lines),
        variant: toRef(() => props.variant)
      }
    });
    useRender(() => {
      const listProps = VList.filterProps(props);
      const treeviewChildrenProps = VTreeviewChildren.filterProps(props);
      const indentLinesVariant = typeof props.indentLines === 'boolean' ? 'default' : props.indentLines;
      return createVNode(VList, mergeProps({
        "ref": vListRef
      }, listProps, {
        "class": ['v-treeview', {
          'v-treeview--fluid': props.fluid
        }, props.class],
        "role": "tree",
        "openStrategy": "multiple",
        "style": [{
          '--v-treeview-indent-line-color': props.indentLinesColor,
          '--v-treeview-indent-line-opacity': props.indentLinesOpacity
        }, props.style],
        "opened": opened.value,
        "activated": activated.value,
        "onUpdate:activated": $event => activated.value = $event,
        "selected": selected.value,
        "onUpdate:selected": $event => selected.value = $event
      }), {
        default: () => [visibleIds.value?.size === 0 && !props.hideNoData && (slots['no-data']?.() ?? createVNode(VListItem, {
          "key": "no-data",
          "title": t(props.noDataText)
        }, null)), createVNode(VTreeviewChildren, mergeProps(treeviewChildrenProps, {
          "density": props.density,
          "returnObject": props.returnObject,
          "items": items.value,
          "parentIndentLines": props.indentLines ? [] : undefined,
          "indentLinesVariant": indentLinesVariant
        }), slots)]
      });
    });
    return {};
  }
});

// Composables

// Types

const VValidation = genericComponent()({
  name: 'VValidation',
  props: makeValidationProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const validation = useValidation(props, 'validation');
    return () => slots.default?.(validation);
  }
});

// Types

const makeVAvatarGroupProps = propsFactory({
  border: [Boolean, Number, String],
  gap: [Number, String],
  hoverable: Boolean,
  items: {
    type: Array,
    default: () => []
  },
  itemProps: {
    type: [Boolean, String, Array, Function],
    default: null
  },
  limit: [Number, String],
  overflowText: String,
  reverse: Boolean,
  size: [Number, String],
  vertical: Boolean,
  ...makeComponentProps(),
  ...makeTagProps()
}, 'VAvatarGroup');
const VAvatarGroup = genericComponent()({
  name: 'VAvatarGroup',
  props: makeVAvatarGroupProps(),
  setup(props, {
    slots
  }) {
    const limit = computed(() => props.limit !== null ? Number(props.limit) : null);
    const overflow = computed(() => {
      return limit.value && !isNaN(limit.value) && props.items.length > limit.value ? Math.max(0, props.items.length - limit.value + 1) : 0;
    });
    const items = computed(() => {
      const visibleItems = limit.value && overflow.value > 1 ? props.items.slice(0, limit.value - 1) : props.items;
      const orderedItems = props.reverse ? visibleItems.toReversed() : visibleItems;
      return orderedItems.map(item => {
        const avatarProps = props.itemProps === true ? isObject(item) ? item : {
          image: item
        } : getPropertyFromItem(item, props.itemProps, item);
        if (avatarProps != null) return avatarProps;
        if (!isObject(item)) return {
          image: item
        };
        return item;
      });
    });
    const overflowText = computed(() => props.overflowText ?? (overflow.value ? `+${overflow.value}` : ''));
    const overflowItem = () => slots.overflow?.({
      overflow: overflow.value
    }) ?? createVNode(VAvatar, {
      "class": "v-avatar-group__overflow",
      "text": overflowText.value
    }, null);
    useRender(() => createVNode(props.tag, {
      "class": normalizeClass(['v-avatar-group', `v-avatar-group--${props.vertical ? 'vertical' : 'horizontal'}`, {
        'v-avatar-group--hoverable': props.hoverable,
        'v-avatar-group--reverse': props.reverse
      }, props.class]),
      "style": normalizeStyle([{
        '--v-avatar-group-gap': convertToUnit(props.gap)
      }, props.style])
    }, {
      default: () => [slots.prepend?.(), createElementVNode("div", {
        "class": "v-avatar-group__content"
      }, [createVNode(VDefaultsProvider, {
        "defaults": {
          VAvatar: {
            size: props.size,
            border: props.border
          }
        }
      }, {
        default: () => [slots.default?.() ?? createElementVNode(Fragment, null, [props.reverse && overflowText.value && overflowItem(), items.value.map((item, index) => slots.item?.({
          props: item,
          index
        }) ?? createVNode(VAvatar, mergeProps({
          "key": index
        }, item), null)), !props.reverse && overflowText.value && overflowItem()])]
      })]), slots.append?.()]
    }));
    return {};
  }
});

// Utilities

// Types

const VCommandPaletteSymbol = Symbol.for('vuetify:command-palette');

// Types

const makeVCommandPaletteItemProps = propsFactory({
  item: {
    type: Object,
    required: true
  },
  index: {
    type: Number,
    required: true
  },
  onExecute: Function
}, 'VCommandPaletteItem');
const VCommandPaletteItem = genericComponent()({
  name: 'VCommandPaletteItem',
  props: makeVCommandPaletteItemProps(),
  setup(props, {
    slots
  }) {
    useRender(() => createVNode(VListItem, {
      "index": props.index,
      "value": props.item.value,
      "title": props.item.title,
      "subtitle": props.item.subtitle,
      "prependIcon": props.item.prependIcon,
      "prependAvatar": props.item.prependAvatar,
      "appendIcon": props.item.appendIcon,
      "appendAvatar": props.item.appendAvatar,
      "onClick": props.onExecute
    }, {
      prepend: slots.prepend,
      title: slots.title,
      append: slots.append ?? (props.item.hotkey ? () => createVNode(VHotkey, {
        "keys": props.item.hotkey
      }, null) : undefined)
    }));
  }
});

// Types

function isActionItem(item) {
  return !item.type || item.type === 'item';
}

// Utilities
function getItemKey(item) {
  if (!isActionItem(item)) return undefined;
  return item.value !== undefined ? String(item.value) : item.title;
}
function findFirstSelectableIndex(items) {
  return items.findIndex(item => isActionItem(item));
}
function useCommandPaletteNavigation(options) {
  const selectedIndex = ref(0);
  const selectedItemKey = shallowRef(undefined);
  watch(() => options.filteredItems.value, (newItems, oldItems) => {
    if (newItems.length === 0) {
      selectedIndex.value = -1;
      selectedItemKey.value = undefined;
      return;
    }
    if (selectedItemKey.value !== undefined) {
      const newIndex = newItems.findIndex(item => isActionItem(item) && getItemKey(item) === selectedItemKey.value);
      if (newIndex !== -1) {
        selectedIndex.value = newIndex;
        return;
      }
    }
    const firstSelectableIndex = findFirstSelectableIndex(newItems);
    if (firstSelectableIndex !== -1) {
      selectedIndex.value = firstSelectableIndex;
      selectedItemKey.value = getItemKey(newItems[firstSelectableIndex]);
      return;
    }
    selectedIndex.value = 0;
    selectedItemKey.value = undefined;
  }, {
    immediate: true
  });
  function getSelectedItem() {
    return options.filteredItems.value[selectedIndex.value];
  }
  function execute(index, event) {
    const item = options.filteredItems.value[index];
    if (item) {
      options.onItemClick(item, event);
    }
  }
  function executeSelected(event) {
    const item = getSelectedItem();
    if (item) {
      options.onItemClick(item, event);
    }
  }
  function reset() {
    const items = options.filteredItems.value;
    if (items.length === 0) {
      selectedIndex.value = -1;
      selectedItemKey.value = undefined;
      return;
    }
    const firstSelectableIndex = findFirstSelectableIndex(items);
    if (firstSelectableIndex !== -1) {
      selectedIndex.value = firstSelectableIndex;
      selectedItemKey.value = getItemKey(items[firstSelectableIndex]);
      return;
    }
    selectedIndex.value = 0;
    selectedItemKey.value = undefined;
  }
  function setSelectedIndex(index) {
    // Ignore VList's reset to -1 when we have items - we manage selection on filter changes
    if (index === -1 && options.filteredItems.value.length > 0) {
      return;
    }
    selectedIndex.value = index;
    const item = options.filteredItems.value[index];
    selectedItemKey.value = item ? getItemKey(item) : undefined;
  }
  return {
    selectedIndex: readonly(selectedIndex),
    getSelectedItem,
    execute,
    executeSelected,
    reset,
    setSelectedIndex
  };
}

// Types

const makeVCommandPaletteProps = propsFactory({
  modelValue: Boolean,
  search: String,
  items: {
    type: Array,
    default: () => []
  },
  placeholder: {
    type: String,
    default: '$vuetify.command.search'
  },
  inputIcon: {
    type: String,
    default: '$search'
  },
  hotkey: String,
  offsetTop: {
    type: [Number, String],
    default: '15vh'
  },
  closeOnSelect: {
    type: Boolean,
    default: true
  },
  noDataText: {
    type: String,
    default: '$vuetify.noDataText'
  },
  listProps: Object,
  ...makeFilterProps({
    filterKeys: ['title', 'subtitle']
  }),
  ...makeDensityProps(),
  ...omit(makeVDialogProps({
    location: 'top center',
    maxWidth: 500,
    origin: 'top center',
    viewportMargin: 16
  }), ['modelValue'])
}, 'VCommandPalette');
const VCommandPalette = genericComponent()({
  name: 'VCommandPalette',
  props: makeVCommandPaletteProps(),
  emits: {
    'update:modelValue': value => true,
    'update:search': value => true,
    'click:item': (item, event) => true,
    'before-select': payload => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    const isOpen = useProxiedModel(props, 'modelValue');
    const searchQuery = useProxiedModel(props, 'search');
    const searchInputRef = ref();
    const dialogRef = ref();
    const previouslyFocusedElement = shallowRef(null);
    const internalItems = computed(() => props.items.map((item, index) => ({
      value: index,
      type: item.type,
      raw: item,
      ...('title' in item && {
        title: item.title
      }),
      ...('subtitle' in item && {
        subtitle: item.subtitle
      })
    })));
    const {
      filteredItems: filterResult
    } = useFilter(props, internalItems, searchQuery);
    const filteredItems = computed(() => filterResult.value.map(item => item.raw));
    const itemsForList = computed(() => {
      return filteredItems.value.map((item, idx) => ({
        ...item,
        value: idx
      }));
    });
    function executeItem(item, event) {
      if ('onClick' in item && item.onClick) {
        item.onClick(event, item.value);
      }
      emit('click:item', item, event);
      if (!isActionItem(item) || !props.closeOnSelect) return;
      let shouldClose = true;
      emit('before-select', {
        item,
        event,
        preventDefault: () => {
          shouldClose = false;
        }
      });
      if (shouldClose) {
        isOpen.value = false;
      }
    }
    const navigation = useCommandPaletteNavigation({
      filteredItems,
      onItemClick: (item, event) => {
        executeItem(item, event);
      }
    });
    provide(VCommandPaletteSymbol, {
      items: computed(() => props.items),
      filteredItems,
      selectedIndex: navigation.selectedIndex,
      search: searchQuery,
      setSelectedIndex: navigation.setSelectedIndex
    });

    // Register main hotkey with cleanup - using toRef for reactivity
    const hotkeyUnsubscribe = useHotkey(toRef(props, 'hotkey'), () => {
      isOpen.value = !isOpen.value;
    });
    watchEffect(onCleanup => {
      if (!isOpen.value) {
        return;
      }
      const hotkeyUnsubscribes = [];
      function registerItemHotkeys(items) {
        items.forEach(item => {
          if (isActionItem(item) && item.hotkey) {
            const unsubscribe = useHotkey(item.hotkey, event => {
              event.preventDefault();
              executeItem(item, event);
            }, {
              inputs: true
            });
            hotkeyUnsubscribes.push(unsubscribe);
          }
        });
      }
      registerItemHotkeys(props.items);
      onCleanup(() => {
        hotkeyUnsubscribes.forEach(unsubscribe => unsubscribe?.());
      });
    });
    function findNextSelectableIndex(startIndex, direction) {
      const items = filteredItems.value;
      if (items.length === 0) return -1;
      let index = startIndex;
      const maxIterations = items.length;
      for (let i = 0; i < maxIterations; i++) {
        index += direction;
        if (index >= items.length) index = 0;
        if (index < 0) index = items.length - 1;
        if (isActionItem(items[index])) {
          return index;
        }
      }
      return -1;
    }
    function handleSearchKeydown(e) {
      switch (e.key) {
        case 'ArrowDown':
          {
            e.preventDefault();
            const nextIndex = findNextSelectableIndex(navigation.selectedIndex.value, 1);
            if (nextIndex !== -1) {
              navigation.setSelectedIndex(nextIndex);
            }
            break;
          }
        case 'ArrowUp':
          {
            e.preventDefault();
            const prevIndex = findNextSelectableIndex(navigation.selectedIndex.value, -1);
            if (prevIndex !== -1) {
              navigation.setSelectedIndex(prevIndex);
            }
            break;
          }
        case 'Enter':
          e.preventDefault();
          navigation.executeSelected(e);
          break;
        case 'Escape':
          e.preventDefault();
          isOpen.value = false;
          break;
      }
    }
    watch(isOpen, (newValue, oldValue) => {
      if (newValue && !oldValue) {
        previouslyFocusedElement.value = getActiveElement();
        searchQuery.value = '';
        navigation.reset();

        // Use requestAnimationFrame to ensure DOM is fully rendered
        nextTick(() => {
          requestAnimationFrame(() => {
            if (searchInputRef.value && typeof searchInputRef.value.focus === 'function') {
              searchInputRef.value.focus();
            }
          });
        });
      } else if (!newValue && oldValue) {
        nextTick(() => {
          previouslyFocusedElement.value?.focus({
            preventScroll: true
          });
          previouslyFocusedElement.value = null;
        });
      }
    }, {
      immediate: true
    });
    onUnmounted(() => {
      hotkeyUnsubscribe();
      previouslyFocusedElement.value = null;
    });
    useRender(() => {
      const dialogProps = VDialog.filterProps(omit(props, ['modelValue', 'class', 'style']));
      return createVNode(VDialog, mergeProps({
        "ref": dialogRef,
        "modelValue": isOpen.value,
        "onUpdate:modelValue": $event => isOpen.value = $event,
        "class": "v-command-palette",
        "style": {
          '--v-command-palette-top-offset': convertToUnit(props.offsetTop)
        },
        "scrollable": true
      }, dialogProps), {
        activator: slots.activator,
        default: () => createVNode(VSheet, {
          "class": normalizeClass(props.class),
          "style": normalizeStyle(props.style)
        }, {
          default: () => [slots.prepend?.(), createElementVNode("div", {
            "class": "v-command-palette__input-container"
          }, [slots.input?.() ?? createVNode(VTextField, {
            "ref": searchInputRef,
            "modelValue": searchQuery.value,
            "onUpdate:modelValue": $event => searchQuery.value = $event,
            "density": props.density,
            "placeholder": t(props.placeholder),
            "prependInnerIcon": props.inputIcon,
            "autocomplete": "off",
            "autofocus": true,
            "singleLine": true,
            "hideDetails": true,
            "variant": "solo",
            "flat": true,
            "bgColor": "transparent",
            "onKeydown": handleSearchKeydown
          }, {
            'append-inner': slots['input.append-inner']
          })]), createElementVNode("div", {
            "class": "v-command-palette__content"
          }, [filteredItems.value.length > 0 ? createVNode(VList, mergeProps({
            "key": "list",
            "class": "v-command-palette__list",
            "density": props.density,
            "items": itemsForList.value,
            "itemType": "type",
            "itemProps": true,
            "activatable": true
          }, props.listProps, {
            "navigationStrategy": "track",
            "navigationIndex": navigation.selectedIndex.value,
            "onUpdate:navigationIndex": navigation.setSelectedIndex
          }), {
            prepend: slots['list.prepend'],
            subheader: slots['list.subheader'],
            item: ({
              props: itemProps
            }) => slots.item?.({
              item: itemProps,
              index: itemProps.index
            }) ?? createVNode(VCommandPaletteItem, {
              "key": `item-${itemProps.index}`,
              "item": itemProps,
              "index": itemProps.index,
              "onExecute": event => navigation.execute(itemProps.index, event)
            }, {
              prepend: slots['item.prepend'] ? () => slots['item.prepend']?.({
                item: itemProps,
                index: itemProps.index
              }) : undefined,
              title: slots['item.title'] ? () => slots['item.title']?.({
                item: itemProps,
                index: itemProps.index
              }) : undefined,
              append: slots['item.append'] ? () => slots['item.append']?.({
                item: itemProps,
                index: itemProps.index
              }) : undefined
            })
          }) : createElementVNode("div", {
            "key": "no-data",
            "class": "v-command-palette__no-data"
          }, [slots['no-data']?.() || t(props.noDataText)])]), slots.append?.()]
        })
      });
    });
  }
});

// Types

const datePickerForwardedKeys = ['min', 'max', 'allowedDates', 'allowedMonths', 'allowedYears', 'weekdays', 'firstDayOfWeek', 'firstDayOfYear', 'weekdayFormat', 'weeksInMonth', 'hideWeekdays', 'showWeek', 'color', 'readonly', 'disabled', 'prevIcon', 'nextIcon', 'transition', 'reverseTransition', 'controlHeight'];
const makeVDateRangePickerProps = propsFactory({
  independentMonths: Boolean,
  modelValue: null,
  ...makeVPickerProps({
    title: '$vuetify.datePicker.title'
  }),
  ...pick(makeVDatePickerProps(), datePickerForwardedKeys)
}, 'VDateRangePicker');
const VDateRangePicker = genericComponent()({
  name: 'VDateRangePicker',
  props: makeVDateRangePickerProps(),
  emits: {
    'update:modelValue': _value => true
  },
  setup(props, {
    slots
  }) {
    const adapter = useDate();
    const model = useProxiedModel(props, 'modelValue', []);
    const today = adapter.date();
    const leftMonth = shallowRef(adapter.getMonth(today));
    const leftYear = shallowRef(adapter.getYear(today));
    const rightMonth = shallowRef(0);
    const rightYear = shallowRef(0);
    function shiftMonth(month, year, delta) {
      const total = month + delta + year * 12;
      return {
        month: (total % 12 + 12) % 12,
        year: Math.floor(total / 12)
      };
    }
    function syncRightFromLeft() {
      const next = shiftMonth(leftMonth.value, leftYear.value, 1);
      rightMonth.value = next.month;
      rightYear.value = next.year;
    }
    function syncLeftFromRight() {
      const previous = shiftMonth(rightMonth.value, rightYear.value, -1);
      leftMonth.value = previous.month;
      leftYear.value = previous.year;
    }
    const leftIndex = computed(() => leftYear.value * 12 + leftMonth.value);
    const rightIndex = computed(() => rightYear.value * 12 + rightMonth.value);
    const leftNextDisabled = computed(() => leftIndex.value + 1 >= rightIndex.value);
    const rightPrevDisabled = computed(() => rightIndex.value - 1 <= leftIndex.value);
    const rootRef = shallowRef();
    const leftPickerRef = shallowRef();
    const rightPickerRef = shallowRef();
    const previewValue = shallowRef();
    function panelContaining(iso) {
      if (leftPickerRef.value?.$el?.querySelector(`[data-v-date="${iso}"]`)) return leftPickerRef.value;
      if (rightPickerRef.value?.$el?.querySelector(`[data-v-date="${iso}"]`)) return rightPickerRef.value;
      return null;
    }
    function isMonthInView(date) {
      const month = adapter.getMonth(date);
      const year = adapter.getYear(date);
      return month === leftMonth.value && year === leftYear.value || month === rightMonth.value && year === rightYear.value;
    }
    function navigateToSelection() {
      const dates = model.value;
      if (!dates.length) return;
      const first = adapter.date(dates[0]);
      const last = adapter.date(dates[dates.length - 1]);
      leftMonth.value = adapter.getMonth(first);
      leftYear.value = adapter.getYear(first);
      if (!props.independentMonths) {
        syncRightFromLeft();
        return;
      }
      const firstIndex = leftIndex.value;
      const lastIndex = adapter.getYear(last) * 12 + adapter.getMonth(last);
      const targetRightIndex = Math.max(lastIndex, firstIndex + 1);
      rightYear.value = Math.floor(targetRightIndex / 12);
      rightMonth.value = targetRightIndex - rightYear.value * 12;
    }
    syncRightFromLeft();
    navigateToSelection();
    let syncing = false;
    watch([leftMonth, leftYear], () => {
      if (syncing || props.independentMonths) return;
      syncing = true;
      syncRightFromLeft();
      syncing = false;
    });
    watch([rightMonth, rightYear], () => {
      if (syncing || props.independentMonths) return;
      syncing = true;
      syncLeftFromRight();
      syncing = false;
    });

    // Re-pair the panels when independent-months turns OFF. Preserve the right panel if it
    // holds the range start; otherwise default to right = left + 1.
    watch(() => props.independentMonths, (value, oldValue) => {
      if (value || !oldValue) return;
      const start = model.value[0];
      if (start != null) {
        const startIndex = adapter.getYear(start) * 12 + adapter.getMonth(start);
        if (startIndex === rightIndex.value) {
          syncing = true;
          syncLeftFromRight();
          syncing = false;
          return;
        }
      }
      syncing = true;
      syncRightFromLeft();
      syncing = false;
    });
    watch(model, val => {
      const dates = val;
      if (!dates.length) return;
      const first = adapter.date(dates[0]);
      const last = adapter.date(dates[dates.length - 1]);
      if (isMonthInView(first) && isMonthInView(last)) return;
      navigateToSelection();
    });
    function focusCell(iso) {
      panelContaining(iso)?.focusDate(iso);
    }
    function onBoundaryNavigate({
      direction,
      targetIsoDate
    }) {
      if (panelContaining(targetIsoDate)) {
        focusCell(targetIsoDate);
        return;
      }

      // Outer boundary: shift whichever panel needs to move to bring the target into view.
      const target = adapter.date(targetIsoDate);
      const targetMonth = adapter.getMonth(target);
      const targetYear = adapter.getYear(target);
      const targetIndex = targetYear * 12 + targetMonth;
      if (targetIndex < leftIndex.value) {
        const wouldCollide = props.independentMonths && rightIndex.value <= targetIndex;
        leftMonth.value = targetMonth;
        leftYear.value = targetYear;
        if (wouldCollide) {
          const next = shiftMonth(targetMonth, targetYear, 1);
          rightMonth.value = next.month;
          rightYear.value = next.year;
        }
      } else if (targetIndex > rightIndex.value) {
        const wouldCollide = props.independentMonths && leftIndex.value >= targetIndex;
        rightMonth.value = targetMonth;
        rightYear.value = targetYear;
        if (wouldCollide) {
          const previous = shiftMonth(targetMonth, targetYear, -1);
          leftMonth.value = previous.month;
          leftYear.value = previous.year;
        }
      } else {
        // Target sits in the independent-months gap: direction tells us which panel to move.
        const goingBack = direction === 'left' || direction === 'up';
        if (goingBack) {
          rightMonth.value = targetMonth;
          rightYear.value = targetYear;
        } else {
          leftMonth.value = targetMonth;
          leftYear.value = targetYear;
        }
      }
      nextTick(() => focusCell(targetIsoDate));
    }
    useRender(() => {
      const pickerProps = VPicker.filterProps(props);
      const datePickerProps = pick(props, datePickerForwardedKeys);
      return createVNode(VPicker, mergeProps({
        "ref": rootRef
      }, pickerProps, {
        "class": ['v-date-range-picker', props.class],
        "style": props.style,
        "hideHeader": true
      }), {
        default: () => createElementVNode(Fragment, null, [createVNode(VDatePicker, mergeProps({
          "ref": leftPickerRef
        }, datePickerProps, {
          "modelValue": model.value,
          "onUpdate:modelValue": $event => model.value = $event,
          "month": leftMonth.value,
          "onUpdate:month": $event => leftMonth.value = $event,
          "year": leftYear.value,
          "onUpdate:year": $event => leftYear.value = $event,
          "class": "v-date-range-picker__panel",
          "multiple": "range",
          "noAutoNavigation": true,
          "showAdjacentMonths": false,
          "hideHeader": true,
          "previewValue": previewValue.value,
          "onUpdate:previewValue": value => previewValue.value = value,
          "onBoundaryNavigate": onBoundaryNavigate
        }), {
          controls: ({
            monthYearText,
            prevMonth,
            nextMonth,
            disabled
          }) => createElementVNode(Fragment, null, [createVNode(VBtn, {
            "density": "comfortable",
            "disabled": disabled.includes('prev-month'),
            "icon": props.prevIcon,
            "variant": "text",
            "onClick": prevMonth
          }, null), createVNode(VSpacer, null, null), createElementVNode("div", null, [monthYearText]), createVNode(VSpacer, null, null), createVNode(VBtn, {
            "class": normalizeClass({
              'v-date-range-picker__nav-hidden': !props.independentMonths
            }),
            "density": "comfortable",
            "disabled": !props.independentMonths || leftNextDisabled.value || disabled.includes('next-month'),
            "icon": props.nextIcon,
            "variant": "text",
            "onClick": nextMonth
          }, null)])
        }), createElementVNode("div", {
          "class": "v-date-range-picker__divider",
          "role": "separator"
        }, null), createVNode(VDatePicker, mergeProps({
          "ref": rightPickerRef
        }, datePickerProps, {
          "modelValue": model.value,
          "onUpdate:modelValue": $event => model.value = $event,
          "month": rightMonth.value,
          "onUpdate:month": $event => rightMonth.value = $event,
          "year": rightYear.value,
          "onUpdate:year": $event => rightYear.value = $event,
          "class": "v-date-range-picker__panel",
          "multiple": "range",
          "noAutoNavigation": true,
          "showAdjacentMonths": false,
          "hideHeader": true,
          "previewValue": previewValue.value,
          "onUpdate:previewValue": value => previewValue.value = value,
          "onBoundaryNavigate": onBoundaryNavigate
        }), {
          controls: ({
            monthYearText,
            prevMonth,
            nextMonth,
            disabled
          }) => createElementVNode(Fragment, null, [createVNode(VBtn, {
            "class": normalizeClass({
              'v-date-range-picker__nav-hidden': !props.independentMonths
            }),
            "density": "comfortable",
            "disabled": !props.independentMonths || rightPrevDisabled.value || disabled.includes('prev-month'),
            "icon": props.prevIcon,
            "variant": "text",
            "onClick": prevMonth
          }, null), createVNode(VSpacer, null, null), createElementVNode("div", null, [monthYearText]), createVNode(VSpacer, null, null), createVNode(VBtn, {
            "density": "comfortable",
            "disabled": disabled.includes('next-month'),
            "icon": props.nextIcon,
            "variant": "text",
            "onClick": nextMonth
          }, null)])
        })]),
        actions: slots.footer
      });
    });
    return {};
  }
});

// Composables

// Types

function toISO(year, month) {
  return `${year}-${String(month + 1).padStart(2, '0')}`;
}
function compareISO(a, b) {
  return a < b ? -1 : a > b ? 1 : 0;
}
function useMonthPicker(props, model) {
  const adapter = useDate();
  const year = shallowRef(adapter.getYear(adapter.date()));
  const range = useRangePicker({
    multiple: toRef(() => props.multiple),
    model,
    compare: compareISO
  });
  function getMonthValue(monthIndex) {
    return toISO(year.value, monthIndex);
  }
  function selectMonth(monthIndex) {
    range.select(getMonthValue(monthIndex));
  }
  const disablePrevYear = computed(() => {
    if (!props.min) return false;
    const minYear = parseInt(props.min.split('-')[0], 10);
    return year.value <= minYear;
  });
  const disableNextYear = computed(() => {
    if (!props.max) return false;
    const maxYear = parseInt(props.max.split('-')[0], 10);
    return year.value >= maxYear;
  });
  function prevYear() {
    if (disablePrevYear.value) return;
    year.value--;
  }
  function nextYear() {
    if (disableNextYear.value) return;
    year.value++;
  }
  watch(model, val => {
    if (val.length === 0) return;
    const last = val[val.length - 1];
    const [y] = last.split('-').map(v => parseInt(v, 10));
    year.value = y;
  }, {
    immediate: true
  });
  return {
    year,
    disablePrevYear,
    disableNextYear,
    selectMonth,
    prevYear,
    nextYear,
    getMonthValue,
    range
  };
}

// Types

const makeVMonthPickerProps = propsFactory({
  disabled: Boolean,
  readonly: Boolean,
  selectedIcon: {
    type: IconValue,
    default: '$complete'
  },
  nextIcon: {
    type: IconValue,
    default: '$next'
  },
  prevIcon: {
    type: IconValue,
    default: '$prev'
  },
  modeIcon: {
    type: IconValue,
    default: '$subgroup'
  },
  modelValue: null,
  headerColor: String,
  min: String,
  max: String,
  multiple: [Boolean, String],
  allowedMonths: [Array, Function],
  allowedYears: [Array, Function],
  monthsColumns: {
    type: [Number, String],
    default: 4
  },
  yearsColumns: {
    type: [Number, String],
    default: 3
  },
  transition: {
    type: String,
    default: 'picker-transition'
  },
  reverseTransition: {
    type: String,
    default: 'picker-reverse-transition'
  },
  ...omit(makeVPickerProps({
    title: '$vuetify.monthPicker.title'
  }), ['landscape'])
}, 'VMonthPicker');
const VMonthPicker = genericComponent()({
  name: 'VMonthPicker',
  props: makeVMonthPickerProps(),
  emits: {
    'update:modelValue': value => true
  },
  setup(props, {
    slots
  }) {
    const model = useProxiedModel(props, 'modelValue', undefined, v => wrapInArray(v), v => props.multiple ? v : v[0]);
    const adapter = useDate();
    const {
      t
    } = useLocale();
    const now = adapter.date();
    const currentYear = adapter.getYear(now);
    const currentMonth = adapter.getMonth(now);
    const isReverse = shallowRef(false);
    const transition = toRef(() => {
      return !isReverse.value ? props.transition : props.reverseTransition;
    });
    const {
      year,
      disablePrevYear,
      disableNextYear,
      prevYear,
      nextYear,
      selectMonth,
      getMonthValue,
      range
    } = useMonthPicker(props, model);
    const viewMode = shallowRef('months');
    function toggleViewMode() {
      viewMode.value = viewMode.value === 'years' ? 'months' : 'years';
    }
    function onUpdateYear(v) {
      year.value = v;
      // Brief delay so the year-grid click feedback is visible before the view swaps
      setTimeout(() => {
        viewMode.value = 'months';
      }, 100);
    }
    const headerText = computed(() => {
      const values = model.value;
      if (values.length === 0) {
        return props.multiple === 'range' ? t('$vuetify.monthPicker.range.title') : t('$vuetify.monthPicker.header');
      }
      if (props.multiple === 'range' && values.length === 2) {
        const startDate = adapter.parseISO(`${values[0]}-01`);
        const endDate = adapter.parseISO(`${values[1]}-01`);
        const start = `${adapter.format(startDate, 'monthShort')} ${adapter.format(startDate, 'year')}`;
        const end = `${adapter.format(endDate, 'monthShort')} ${adapter.format(endDate, 'year')}`;
        return `${start} – ${end}`;
      }
      if (props.multiple && values.length > 1) {
        return t('$vuetify.monthPicker.itemsSelected', values.length);
      }
      const last = values[values.length - 1];
      return adapter.format(adapter.parseISO(`${last}-01`), 'monthAndYear');
    });
    const headerColor = toRef(() => props.headerColor ?? props.color);
    const {
      backgroundColorClasses: rangeColorClasses,
      backgroundColorStyles: rangeColorStyles
    } = useBackgroundColor(() => props.color);
    const headerTransition = toRef(() => `date-picker-header${isReverse.value ? '-reverse' : ''}-transition`);
    watch(year, (newVal, oldVal) => {
      isReverse.value = newVal < oldVal;
    });
    const months = computed(() => {
      let date = adapter.startOfYear(adapter.date());
      date = adapter.setYear(date, year.value);
      return createRange(12).map(i => {
        const text = adapter.format(date, 'monthShort');
        const label = adapter.format(date, 'month');
        const isDisabled = !!(!isMonthAllowed(i) || props.min && adapter.isAfter(adapter.startOfMonth(adapter.date(props.min + '-01')), date) || props.max && adapter.isAfter(date, adapter.startOfMonth(adapter.date(props.max + '-01'))));
        date = adapter.getNextMonth(date);
        return {
          isCurrent: year.value === currentYear && i === currentMonth,
          isDisabled,
          text,
          label,
          value: i
        };
      });
    });
    const isListView = computed(() => Number(props.monthsColumns) === 1);
    const monthRows = computed(() => {
      const cols = Number(props.monthsColumns) || 4;
      return chunkArray(months.value, cols);
    });
    function isMonthAllowed(month) {
      if (Array.isArray(props.allowedMonths) && props.allowedMonths.length) {
        return props.allowedMonths.includes(month);
      }
      if (typeof props.allowedMonths === 'function') {
        return props.allowedMonths(month);
      }
      return true;
    }
    function initialFocusMonth(current) {
      const isVisible = m => !m.isDisabled;
      if (current != null) {
        const cur = months.value.find(m => m.value === current);
        if (cur && !cur.isDisabled) return current;
      }
      const selected = months.value.find(m => isVisible(m) && model.value.some(v => v === getMonthValue(m.value)));
      if (selected) return selected.value;
      if (year.value === currentYear) {
        const today = months.value.find(m => m.value === currentMonth && isVisible(m));
        if (today) return today.value;
      }
      return months.value.find(isVisible)?.value;
    }
    function onMonthSelect(index) {
      selectMonth(index);
    }
    const {
      containerProps,
      selectItem,
      focusItem,
      clear
    } = useGridSelection({
      items: () => months.value,
      columns: () => Number(props.monthsColumns) || 4,
      initialValue: initialFocusMonth,
      itemAttribute: 'data-v-month',
      onSelect: onMonthSelect,
      onNavigation: (...args) => onMonthNavigation(...args),
      onHighlight: value => range.setPreview(value != null ? getMonthValue(value) : undefined)
    });
    function onMonthNavigation(direction, e, curIndex) {
      if (curIndex == null) return false;
      if (direction === 'left' && curIndex === 0 && !disablePrevYear.value) {
        e.preventDefault();
        prevYear();
        nextTick(() => focusItem(11));
        return true;
      }
      if (direction === 'right' && curIndex === 11 && !disableNextYear.value) {
        e.preventDefault();
        nextYear();
        nextTick(() => focusItem(0));
        return true;
      }
      return false;
    }
    watch(year, () => clear());
    useRender(() => {
      const pickerProps = VPicker.filterProps(props);
      return createVNode(VPicker, mergeProps(pickerProps, {
        "class": ['v-month-picker', {
          'v-month-picker--list': isListView.value,
          'v-month-picker--years': viewMode.value === 'years'
        }, props.class],
        "color": headerColor.value,
        "title": t(props.title),
        "style": [{
          '--v-month-picker-months-columns': props.monthsColumns,
          '--v-month-picker-years-columns': props.yearsColumns
        }, props.style]
      }), {
        header: () => createVNode(VDatePickerHeader, {
          "color": headerColor.value,
          "header": headerText.value,
          "transition": headerTransition.value
        }, null),
        default: () => createElementVNode(Fragment, null, [createVNode(VDefaultsProvider, {
          "defaults": {
            VBtn: {
              variant: 'text'
            }
          }
        }, {
          default: () => [createElementVNode("div", {
            "class": "v-month-picker__controls"
          }, [createVNode(VBtn, {
            "disabled": props.disabled || viewMode.value === 'years' || disablePrevYear.value,
            "icon": props.prevIcon,
            "aria-label": t('$vuetify.monthPicker.ariaLabel.previousYear'),
            "onClick": prevYear
          }, null), createVNode(VBtn, {
            "disabled": props.disabled,
            "text": year.value,
            "appendIcon": props.modeIcon,
            "rounded": true,
            "aria-label": t('$vuetify.monthPicker.ariaLabel.selectYear'),
            "onClick": toggleViewMode
          }, null), createVNode(VBtn, {
            "disabled": props.disabled || viewMode.value === 'years' || disableNextYear.value,
            "icon": props.nextIcon,
            "aria-label": t('$vuetify.monthPicker.ariaLabel.nextYear'),
            "onClick": nextYear
          }, null)])]
        }), createVNode(VFadeTransition, {
          "hideOnLeave": true
        }, {
          default: () => [viewMode.value === 'years' ? createVNode(VDatePickerYears, {
            "key": "years",
            "color": props.color,
            "modelValue": year.value,
            "min": props.min ? `${props.min}-01` : undefined,
            "max": props.max ? `${props.max}-01` : undefined,
            "allowedYears": props.allowedYears,
            "onUpdate:modelValue": onUpdateYear
          }, null) : createElementVNode("div", {
            "key": "months",
            "class": "v-month-picker__months flex-grow-1"
          }, [createVNode(MaybeTransition, {
            "name": transition.value
          }, {
            default: () => [createElementVNode("div", mergeProps({
              "key": year.value,
              "class": "v-month-picker__months-content",
              "onMouseleave": range.clearPreview
            }, containerProps.value), [monthRows.value.map((row, rowIndex) => {
              const cols = Number(props.monthsColumns) || 4;
              return createElementVNode("div", {
                "class": "v-month-picker__months-row"
              }, [row.map((month, colIndex) => {
                const index = rowIndex * cols + colIndex;
                const monthValue = getMonthValue(index);
                const rangeStart = range.isRangeStart(monthValue);
                const rangeEnd = range.isRangeEnd(monthValue);
                const rangeMiddle = range.isRangeMiddle(monthValue);
                const previewStart = range.isPreviewStart(monthValue);
                const previewEnd = range.isPreviewEnd(monthValue);
                const previewMiddle = range.isPreviewMiddle(monthValue);
                const previewed = range.isInPreviewRange(monthValue);
                const selected = range.isSelected(monthValue) && !rangeMiddle;
                const variant = isListView.value ? selected ? 'tonal' : 'text' : selected ? 'flat' : month.isCurrent ? 'outlined' : 'text';
                const icon = isListView.value && selected ? props.selectedIcon : undefined;
                const btnProps = {
                  color: selected || month.isCurrent && !isListView.value ? props.color : undefined,
                  disabled: props.disabled || month.isDisabled,
                  readonly: props.readonly,
                  rounded: isListView.value ? 0 : true,
                  text: isListView.value ? month.label : month.text,
                  prependIcon: icon,
                  variant,
                  ripple: false,
                  tabindex: -1,
                  'aria-label': month.isCurrent ? t('$vuetify.monthPicker.ariaLabel.currentMonth', month.label) : month.label,
                  'aria-current': month.isCurrent ? 'date' : undefined,
                  'aria-selected': selected,
                  'data-v-month': month.isDisabled ? undefined : month.value,
                  onMousedown: e => e.preventDefault(),
                  // preserve virtual focus
                  onClick: () => selectItem(index),
                  onMouseenter: () => range.setPreview(monthValue)
                };
                const hasRangeBg = rangeStart || rangeEnd || rangeMiddle;
                const hasPreviewBg = previewStart || previewEnd || previewMiddle;
                return createElementVNode("div", {
                  "class": normalizeClass(['v-month-picker__month', {
                    'v-month-picker__month--current': month.isCurrent,
                    'v-month-picker__month--selected': selected,
                    'v-month-picker__month--range-start': rangeStart,
                    'v-month-picker__month--range-end': rangeEnd,
                    'v-month-picker__month--range-middle': rangeMiddle,
                    'v-month-picker__month--preview-start': previewStart,
                    'v-month-picker__month--preview-end': previewEnd,
                    'v-month-picker__month--preview-middle': previewMiddle,
                    'v-month-picker__month--previewed': previewed
                  }])
                }, [(hasRangeBg || hasPreviewBg) && createElementVNode("div", {
                  "key": "range-background",
                  "class": normalizeClass(['v-month-picker__range-bg', hasRangeBg ? 'v-month-picker__range-bg--range' : 'v-month-picker__range-bg--preview', rangeColorClasses.value]),
                  "style": normalizeStyle(rangeColorStyles.value)
                }, null), slots.month?.({
                  month,
                  i: index,
                  props: btnProps
                }) ?? createVNode(VBtn, btnProps, null)]);
              })]);
            })])]
          })])]
        })]),
        actions: slots.actions
      });
    });
    return {};
  }
});

// Types

const makeVHeatmapCellProps = propsFactory({
  item: {
    type: Object,
    required: true
  },
  x: {
    type: Number,
    required: true
  },
  y: {
    type: Number,
    required: true
  },
  width: {
    type: Number,
    required: true
  },
  height: {
    type: Number,
    required: true
  },
  disabled: Boolean,
  cellProps: Object
}, 'VHeatmapCell');
const VHeatmapCell = genericComponent()({
  name: 'VHeatmapCell',
  props: makeVHeatmapCellProps(),
  setup(props, {
    slots
  }) {
    useRender(() => {
      const {
        title,
        ...cellAttrs
      } = props.cellProps ?? {};
      return createElementVNode("g", mergeProps({
        "class": ['v-heatmap__cell', {
          'v-heatmap__cell--disabled': props.disabled
        }],
        "transform": `translate(${props.x},${props.y})`,
        "style": {
          '--v-heatmap-cell-color': props.item.color
        }
      }, cellAttrs), [title && createElementVNode("title", {
        "key": "title"
      }, [title]), createElementVNode("rect", {
        "class": "v-heatmap__cell-underlay",
        "width": props.width,
        "height": props.height,
        "fill": "transparent"
      }, null), createElementVNode("g", {
        "class": "v-heatmap__cell-content"
      }, [createElementVNode("rect", {
        "class": "v-heatmap__cell-rect",
        "width": props.width,
        "height": props.height
      }, null), slots.default && createElementVNode("foreignObject", {
        "class": "v-heatmap__cell-overlay",
        "width": props.width,
        "height": props.height
      }, [createElementVNode("div", null, [slots.default({
        item: props.item
      })])])])]);
    });
  }
});

// Utilities

// Types

const makeVHeatmapLegendCellProps = propsFactory({
  color: String,
  bucketIndex: Number,
  disabled: Boolean,
  width: {
    type: [Number, String],
    default: 24
  },
  height: {
    type: [Number, String],
    default: 24
  },
  rounded: [Number, String]
}, 'VHeatmapLegendCell');
function toPx$1(value, defaultValue) {
  if (value == null || value === '') return defaultValue;
  const parsed = parseFloat(value);
  return Number.isFinite(parsed) ? parsed : defaultValue;
}
const VHeatmapLegendCell = defineComponent({
  name: 'VHeatmapLegendCell',
  props: makeVHeatmapLegendCellProps(),
  setup(props, {
    slots,
    attrs
  }) {
    const width = toRef(() => toPx$1(props.width, 24));
    const height = toRef(() => toPx$1(props.height, 24));
    useRender(() => {
      const hasBucket = props.bucketIndex != null && props.bucketIndex >= 0;
      const style = {
        '--v-heatmap-cell-radius': convertToUnit(props.rounded)
      };
      if (hasBucket) {
        style['--v-heatmap-cell-color'] = `var(--v-heatmap-color-bucket-${props.bucketIndex})`;
      } else if (props.color) {
        style['--v-heatmap-cell-color'] = props.color;
      }
      return createElementVNode("svg", {
        "class": normalizeClass(['v-heatmap__cell', 'v-heatmap__cell--standalone', {
          'v-heatmap__cell--disabled': props.disabled
        }]),
        "width": width.value,
        "height": height.value,
        "viewBox": `0 0 ${width.value} ${height.value}`,
        "style": normalizeStyle([style, attrs.style])
      }, [createElementVNode("rect", {
        "class": "v-heatmap__cell-rect",
        "width": width.value,
        "height": height.value
      }, null), slots.default && createElementVNode("foreignObject", {
        "class": "v-heatmap__cell-overlay",
        "width": width.value,
        "height": height.value
      }, [createElementVNode("div", null, [slots.default()])])]);
    });
  }
});

// Utilities

// `increasing` / `decreasing` intentionally omitted
// linear-gradient disagrees with the color-mix

function isLinearColorScale(scale) {
  return !!scale && !Array.isArray(scale) && 'from' in scale && 'to' in scale;
}
function getInterpolationMethod(scale) {
  const space = scale.colorSpace ?? 'srgb';
  const hue = scale.hueInterpolation && 'hsl|hwb|lch|oklch'.includes(space) ? ` ${scale.hueInterpolation} hue` : '';
  return `in ${space}${hue}`;
}

// Utilities

// Types

function usePivot(props, options = {}) {
  const transformCell = options.transformCell ?? (cell => cell);
  const rows = computed(() => {
    const rowsProp = toValue(props.rows);
    if (rowsProp) return [...rowsProp];
    const items = toValue(props.items);
    const itemRow = unref(props.itemRow);
    const set = new Set();
    for (const item of items) set.add(getPropertyFromItem(item, itemRow));
    return [...set];
  });

  // True when itemColumn resolves to a value for at least one item — i.e. columns are
  // explicit. When false, columns are inferred from row-key wrapping (calendar-style).
  const hasExplicitColumns = computed(() => {
    const itemColumn = unref(props.itemColumn);
    if (itemColumn == null) return false;
    const columnsProp = toValue(props.columns);
    if (columnsProp?.length) return true;
    const items = toValue(props.items);
    return items.some(item => getPropertyFromItem(item, itemColumn) != null);
  });

  // groups and rowItems are co-derived (pushToRow runs inline while columns build),
  // so they share a single internal computed.
  const grouped = computed(() => {
    const items = toValue(props.items);
    const itemRow = unref(props.itemRow);
    const itemColumn = unref(props.itemColumn);
    const itemValue = unref(props.itemValue);
    const groupBy = unref(props.groupBy);
    const columnsProp = toValue(props.columns);
    const rowKeys = rows.value;
    const explicit = hasExplicitColumns.value;
    const rowIndexByKey = new Map(rowKeys.map((k, i) => [k, i]));
    const groupMap = new Map();
    for (const item of items) {
      const rawKey = groupBy != null ? getPropertyFromItem(item, groupBy) : '';
      const key = String(rawKey ?? '');
      if (!groupMap.has(key)) groupMap.set(key, {
        label: key,
        items: []
      });
      groupMap.get(key).items.push(item);
    }
    const groups = [];
    const rowItems = new Map();
    function makeCell(item, rowKey, columnKey, groupKey) {
      const cell = transformCell({
        value: getPropertyFromItem(item, itemValue),
        raw: item,
        row: rowKey,
        column: columnKey,
        groupKey
      });
      if (!rowItems.has(rowKey)) rowItems.set(rowKey, []);
      rowItems.get(rowKey).push(cell);
      return cell;
    }
    function buildExplicitColumns(sourceItems, groupKey) {
      const groupItems = [];
      const columnKeys = columnsProp ? [...columnsProp] : [...new Set(sourceItems.map(item => getPropertyFromItem(item, itemColumn)))];
      const columns = columnKeys.map(key => ({
        key: String(key),
        cells: Array(rowKeys.length).fill(null),
        items: []
      }));
      const columnIndexByKey = new Map(columnKeys.map((k, i) => [k, i]));
      for (const item of sourceItems) {
        const rowKey = getPropertyFromItem(item, itemRow);
        const columnKey = getPropertyFromItem(item, itemColumn);
        const rowIndex = rowIndexByKey.get(rowKey);
        const columnIndex = columnIndexByKey.get(columnKey);
        if (rowIndex === undefined || columnIndex === undefined) continue;
        const cell = makeCell(item, rowKey, columnKey, groupKey);
        columns[columnIndex].cells[rowIndex] = cell;
        columns[columnIndex].items.push(cell);
        groupItems.push(cell);
      }
      return {
        columns,
        groupItems
      };
    }

    // Start a new column whenever the row key wraps
    function buildInferredColumns(sourceItems, groupKey) {
      const columns = [];
      const groupItems = [];
      let currentCells = Array(rowKeys.length).fill(null);
      let currentItems = [];
      let columnIndex = 0;
      let lastRowIndex = -1;
      for (const item of sourceItems) {
        const rowKey = getPropertyFromItem(item, itemRow);
        const rowIndex = rowIndexByKey.get(rowKey);
        if (rowIndex === undefined) continue;
        if (rowIndex <= lastRowIndex) {
          columns.push({
            key: String(columnIndex),
            cells: currentCells,
            items: currentItems
          });
          columnIndex++;
          currentCells = Array(rowKeys.length).fill(null);
          currentItems = [];
        }
        const cell = makeCell(item, rowKey, columnIndex, groupKey);
        currentCells[rowIndex] = cell;
        currentItems.push(cell);
        groupItems.push(cell);
        lastRowIndex = rowIndex;
      }
      if (currentCells.some(c => c !== null)) {
        columns.push({
          key: String(columnIndex),
          cells: currentCells,
          items: currentItems
        });
      }
      return {
        columns,
        groupItems
      };
    }
    for (const [groupKey, {
      label,
      items: sourceItems
    }] of groupMap) {
      const {
        columns,
        groupItems
      } = explicit ? buildExplicitColumns(sourceItems, groupKey) : buildInferredColumns(sourceItems, groupKey);
      groups.push({
        key: groupKey,
        label,
        columns,
        items: groupItems
      });
    }
    return {
      groups,
      rowItems
    };
  });
  return {
    rows,
    hasExplicitColumns,
    groups: toRef(() => grouped.value.groups),
    rowItems: toRef(() => grouped.value.rowItems)
  };
}

// Composables
function toPx(value, defaultValue) {
  if (value == null || value === '') return defaultValue;
  const parsed = parseFloat(value);
  return Number.isFinite(parsed) ? parsed : defaultValue;
}

// Reassign only on structural change so consumer computeds don't invalidate on identity churn.
function setIfChanged(ref, next) {
  const prev = ref.value;
  if (prev === next) return;
  if (prev == null || next == null) {
    ref.value = next;
    return;
  }
  if (Array.isArray(prev) && Array.isArray(next)) {
    if (prev.length !== next.length || prev.some((v, i) => v !== next[i])) ref.value = next;
    return;
  }
  const keys = Object.keys(next);
  if (keys.some(k => prev[k] !== next[k])) ref.value = next;
}
function useHeatmap(props) {
  const bucketBoundaries = shallowRef([]);
  const bucketColors = shallowRef([]);
  const linearRange = shallowRef(null);
  const linearColors = shallowRef(null);
  const colorSpaceClass = shallowRef('');
  function clearBucketState() {
    if (bucketBoundaries.value.length) bucketBoundaries.value = [];
    if (bucketColors.value.length) bucketColors.value = [];
  }
  function clearLinearState() {
    if (linearRange.value) linearRange.value = null;
    if (linearColors.value) linearColors.value = null;
    if (colorSpaceClass.value) colorSpaceClass.value = '';
  }
  function applyLinearScale(scale) {
    clearBucketState();
    setIfChanged(linearRange, {
      fromMin: scale.from.min,
      toMin: scale.to.min
    });
    setIfChanged(linearColors, {
      from: scale.from.color,
      to: scale.to.color,
      method: getInterpolationMethod(scale)
    });
    const space = scale.colorSpace ?? 'srgb';
    const hue = scale.hueInterpolation && 'hsl hwb lch oklch'.includes(space) ? `-${scale.hueInterpolation}` : '';
    colorSpaceClass.value = `${space}${hue}`;
  }
  function applyBucketScale(scale) {
    clearLinearState();
    setIfChanged(bucketBoundaries, scale.map(stop => stop.min));
    setIfChanged(bucketColors, scale.map(stop => stop.color));
  }
  watchEffect(() => {
    const scale = toValue(props.thresholds);
    if (isLinearColorScale(scale)) applyLinearScale(scale);else if (Array.isArray(scale)) applyBucketScale(scale);else {
      clearBucketState();
      clearLinearState();
    }
  });
  const {
    rows,
    rowItems,
    hasExplicitColumns,
    groups: pivotGroups
  } = usePivot(props, {
    transformCell: cell => {
      const value = Number(cell.value) || 0;
      let bucketIndex = -1;
      let mixPercentage;
      const range = linearRange.value;
      if (range) {
        const span = range.toMin - range.fromMin;
        if (span === 0 && cell.value !== null) {
          mixPercentage = value >= range.toMin ? 100 : 0;
        } else {
          mixPercentage = Number(clamp((value - range.fromMin) / span).toFixed(2)) * 100;
        }
      } else {
        const boundaries = bucketBoundaries.value;
        for (let i = boundaries.length - 1; i >= 0; i--) {
          if (value >= boundaries[i]) {
            bucketIndex = i;
            break;
          }
        }
      }
      return {
        ...cell,
        value,
        bucketIndex,
        mixPercentage,
        get color() {
          if (cell.value === null) {
            return undefined;
          }
          const linear = linearColors.value;
          if (linear && this.mixPercentage != null) {
            if (this.mixPercentage <= 0) return linear.from;
            if (this.mixPercentage >= 100) return linear.to;
            return `color-mix(${linear.method}, ${linear.from}, ${linear.to} ${this.mixPercentage}%)`;
          }
          if (this.bucketIndex < 0) return undefined;
          return bucketColors.value[this.bucketIndex];
        }
      };
    }
  });
  const cellWidth = toRef(() => toPx(Array.isArray(props.cellSize) ? props.cellSize[0] : props.cellSize, 26));
  const cellHeight = toRef(() => toPx(Array.isArray(props.cellSize) ? props.cellSize[1] : props.cellSize, 26));
  const gap = toRef(() => toPx(props.gap, 6));
  const cellStep = toRef(() => cellWidth.value + gap.value);
  const rowStep = toRef(() => cellHeight.value + gap.value);
  const groupGap = toRef(() => toPx(props.groupGap, 0));

  // Calendar months that start mid-week overlap the previous group's last column so weeks stay flush.
  const groups = computed(() => {
    const cellWidthPx = cellWidth.value;
    const gapPx = gap.value;
    const stepPx = cellStep.value;
    const groupGapPx = groupGap.value;
    let cursor = 0;
    return pivotGroups.value.map((group, groupIndex) => {
      const columnCount = group.columns.length;
      const width = columnCount * cellWidthPx + Math.max(0, columnCount - 1) * gapPx;
      const hasOverlap = groupIndex > 0 && group.columns[0]?.cells[0] == null;
      if (groupIndex > 0) {
        cursor += hasOverlap ? groupGapPx - cellWidthPx : gapPx + groupGapPx;
      }
      const x = cursor;
      cursor += width;
      return {
        ...group,
        x,
        width,
        hasOverlap,
        labelOffset: groupGapPx > 0 && hasOverlap ? stepPx : 0
      };
    });
  });
  const totalWidth = toRef(() => {
    const last = groups.value[groups.value.length - 1];
    return last ? last.x + last.width : 0;
  });
  const totalHeight = toRef(() => {
    const rowCount = rows.value.length;
    return rowCount * cellHeight.value + Math.max(0, rowCount - 1) * gap.value;
  });
  return {
    rows,
    rowItems,
    groups,
    hasExplicitColumns,
    cellWidth,
    cellHeight,
    gap,
    cellStep,
    rowStep,
    totalWidth,
    totalHeight,
    bucketBoundaries,
    bucketColors,
    linearColors,
    colorSpaceClass
  };
}

// Types

const makeVHeatmapLegendProps = propsFactory({
  cellSize: {
    type: [Number, String, Array],
    default: undefined
  },
  labels: {
    type: Array,
    default: () => ['$vuetify.heatmap.less', '$vuetify.heatmap.more']
  },
  thresholds: {
    type: [Array, Object],
    default: () => []
  },
  activeBuckets: {
    type: Array,
    required: true
  },
  rounded: [Number, String]
}, 'VHeatmapLegend');
const VHeatmapLegend = defineComponent({
  name: 'VHeatmapLegend',
  props: makeVHeatmapLegendProps(),
  emits: {
    'click:threshold': index => true
  },
  setup(props, {
    emit
  }) {
    const {
      t
    } = useLocale();
    useRender(() => {
      const cellWidth = Array.isArray(props.cellSize) ? props.cellSize[0] : props.cellSize;
      const cellHeight = Array.isArray(props.cellSize) ? props.cellSize[1] : props.cellSize;
      const linear = isLinearColorScale(props.thresholds) ? props.thresholds : null;
      const buckets = !linear && Array.isArray(props.thresholds) ? props.thresholds : null;
      const style = {
        '--v-heatmap-cell-width': convertToUnit(cellWidth),
        '--v-heatmap-cell-height': convertToUnit(cellHeight)
      };
      if (linear) {
        style['--v-heatmap-color-start'] = linear.from.color;
        style['--v-heatmap-color-end'] = linear.to.color;
      }
      if (buckets) {
        buckets.forEach((stop, i) => {
          style[`--v-heatmap-color-bucket-${i}`] = stop.color;
        });
      }
      return createElementVNode("div", {
        "class": "v-heatmap-legend",
        "style": normalizeStyle(style)
      }, [props.labels[0] && createElementVNode("div", {
        "key": "legend-label-start",
        "class": "v-heatmap-legend__label"
      }, [t(props.labels[0])]), linear ? createElementVNode("div", {
        "key": "legend-gradient",
        "class": "v-heatmap-legend__gradient",
        "style": {
          background: `linear-gradient(${getInterpolationMethod(linear)} to right, var(--v-heatmap-color-start), var(--v-heatmap-color-end))`
        }
      }, null) : props.thresholds.map(({
        min
      }, i) => createVNode(VHeatmapLegendCell, {
        "key": min,
        "class": "v-heatmap-legend__cell",
        "bucketIndex": i,
        "disabled": !props.activeBuckets.includes(i),
        "rounded": props.rounded,
        "width": cellWidth,
        "height": cellHeight,
        "onClick": () => emit('click:threshold', i)
      }, null)), props.labels[1] && createElementVNode("div", {
        "key": "legend-label-end",
        "class": "v-heatmap-legend__label"
      }, [t(props.labels[1])])]);
    });
  }
});

// Types

const makeVHeatmapProps = propsFactory({
  cellSize: {
    type: [Number, String, Array],
    default: 26
  },
  gap: {
    type: [Number, String],
    default: 6
  },
  groupGap: {
    type: [Number, String],
    default: 0
  },
  rounded: [Number, String],
  hideColumnHeaders: Boolean,
  hideRowHeaders: Boolean,
  legend: {
    type: [Boolean, Object],
    default: false
  },
  hover: Boolean,
  hoverScale: {
    type: [Number, String],
    default: 0.85
  },
  items: {
    type: Array,
    default: () => []
  },
  itemValue: {
    type: [String, Array, Function],
    default: 'value'
  },
  itemRow: {
    type: [String, Array, Function],
    default: 'row'
  },
  itemColumn: {
    type: [String, Array, Function],
    default: 'column'
  },
  groupBy: [String, Array, Function],
  itemProps: [Object, Function],
  thresholds: {
    type: [Array, Object],
    default: () => []
  },
  emptyColor: String,
  rows: Array,
  columns: Array,
  ...makeThemeProps()
}, 'VHeatmap');
const VHeatmap = genericComponent()({
  name: 'VHeatmap',
  props: makeVHeatmapProps(),
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      rows,
      rowItems,
      groups,
      hasExplicitColumns,
      cellWidth,
      cellHeight,
      gap,
      cellStep,
      rowStep,
      totalWidth,
      totalHeight,
      bucketColors,
      linearColors,
      colorSpaceClass,
      bucketBoundaries
    } = useHeatmap(props);
    const activeBuckets = ref([]);
    const colorProperties = computed(() => {
      const style = {};
      const buckets = bucketColors.value;
      const linear = linearColors.value;
      for (let i = 0; i < buckets.length; i++) {
        style[`--v-heatmap-color-bucket-${i}`] = buckets[i];
      }
      if (linear) {
        style['--v-heatmap-color-start'] = linear.from;
        style['--v-heatmap-color-end'] = linear.to;
      }
      return style;
    });
    watch(bucketBoundaries, val => {
      activeBuckets.value = val.map((_, i) => i);
    }, {
      immediate: true
    });
    function toggle(index) {
      const position = activeBuckets.value.indexOf(index);
      if (position >= 0) activeBuckets.value.splice(position, 1);else activeBuckets.value.push(index);
    }
    function isDisabled(cell) {
      if (cell.bucketIndex < 0) return false;
      return !activeBuckets.value.includes(cell.bucketIndex);
    }
    useRender(() => {
      const radius = convertToUnit(props.rounded);
      const hasGroupLabels = !props.hideColumnHeaders && (!!slots['group-header'] || groups.value.some(group => group.label));
      const hasColumnHeaders = !props.hideColumnHeaders && hasExplicitColumns.value;
      const itemProps = props.itemProps;
      const hasCellSlot = !!slots.cell;
      const space = colorSpaceClass.value;
      return createElementVNode("div", {
        "class": normalizeClass(['v-heatmap', {
          'v-heatmap--hover': props.hover,
          'v-heatmap--hide-column-headers': props.hideColumnHeaders,
          'v-heatmap--hide-row-headers': props.hideRowHeaders,
          'v-heatmap--has-group-labels': hasGroupLabels,
          'v-heatmap--has-column-headers': hasColumnHeaders
        }, space && `v-heatmap--color-space-${space}`, themeClasses.value]),
        "style": {
          '--v-heatmap-cell-width': `${cellWidth.value}px`,
          '--v-heatmap-cell-height': `${cellHeight.value}px`,
          '--v-heatmap-cell-gap': `${gap.value}px`,
          '--v-heatmap-cell-radius': radius,
          '--v-heatmap-hover-scale': props.hover ? Number(props.hoverScale) : undefined,
          '--v-heatmap-rows-count': rows.value.length,
          '--v-heatmap-empty-color': props.emptyColor,
          ...colorProperties.value
        }
      }, [createElementVNode("div", {
        "class": "v-heatmap__body"
      }, [hasGroupLabels && createElementVNode("div", {
        "class": "v-heatmap__group-labels",
        "key": "group-labels",
        "style": {
          width: `${totalWidth.value}px`
        }
      }, [groups.value.map(group => createElementVNode("div", {
        "key": group.key,
        "class": "v-heatmap__group-label",
        "style": {
          insetInlineStart: `${group.x}px`,
          width: `${group.width}px`,
          paddingInlineStart: group.labelOffset ? `${group.labelOffset}px` : undefined
        }
      }, [slots['group-header']?.({
        group,
        items: group.items
      }) ?? group.label]))]), hasColumnHeaders && createElementVNode("div", {
        "class": "v-heatmap__column-headers",
        "key": "column-headers",
        "style": {
          width: `${totalWidth.value}px`
        }
      }, [groups.value.flatMap(group => group.columns.map((col, index) => createElementVNode("div", {
        "key": `column-header-${group.key}-${col.key}`,
        "class": "v-heatmap__column-header",
        "style": {
          insetInlineStart: `${group.x + index * cellStep.value}px`,
          width: `${cellWidth.value}px`
        }
      }, [slots['column-header']?.({
        column: col.key,
        index,
        items: col.items
      }) ?? col.key])))]), !props.hideRowHeaders && createElementVNode("div", {
        "class": "v-heatmap__row-headers",
        "key": "row-headers"
      }, [rows.value.map((row, index) => createElementVNode("div", {
        "key": `row-header-${index}`,
        "class": "v-heatmap__row-header"
      }, [slots['row-header']?.({
        row,
        index,
        items: rowItems.value.get(row) ?? []
      }) ?? row]))]), createElementVNode("svg", {
        "class": "v-heatmap__grid",
        "width": totalWidth.value,
        "height": totalHeight.value,
        "viewBox": `0 0 ${totalWidth.value} ${totalHeight.value}`
      }, [groups.value.flatMap(group => group.columns.flatMap((col, columnIndex) => col.cells.map((cell, rowIndex) => {
        if (!cell) return null;
        const cellProps = (typeof itemProps === 'function' ? itemProps(cell) : itemProps) ?? {};
        return createVNode(VHeatmapCell, {
          "key": `${group.key}-${columnIndex}-${rowIndex}`,
          "item": cell,
          "x": group.x + columnIndex * cellStep.value,
          "y": rowIndex * rowStep.value,
          "width": cellWidth.value,
          "height": cellHeight.value,
          "disabled": isDisabled(cell),
          "cellProps": cellProps
        }, hasCellSlot ? {
          default: () => slots.cell({
            item: cell
          })
        } : undefined);
      })))])]), props.legend && (slots.legend?.({
        thresholds: props.thresholds,
        activeBuckets: activeBuckets.value,
        toggle
      }) ?? createVNode(VHeatmapLegend, {
        "cellSize": (typeof props.legend === 'object' ? props.legend.cellSize : undefined) ?? props.cellSize,
        "thresholds": props.thresholds,
        "activeBuckets": activeBuckets.value,
        "rounded": props.rounded,
        "labels": typeof props.legend === 'object' ? props.legend.labels : undefined,
        "onClick:threshold": toggle
      }, null))]);
    });
  }
});

// Types

const makeVMaskInputProps = propsFactory({
  returnMaskedValue: Boolean,
  ...makeVTextFieldProps(),
  ...makeMaskProps()
}, 'VMaskInput');
const VMaskInput = genericComponent()({
  name: 'VMaskInput',
  props: makeVMaskInputProps(),
  emits: {
    'update:modelValue': val => true
  },
  setup(props, {
    slots,
    emit
  }) {
    const vTextFieldRef = ref();
    const inputAction = shallowRef();
    const caretPosition = shallowRef(0);
    const mask = useMask(props);
    const returnMaskedValue = computed(() => props.mask && props.returnMaskedValue);
    const model = useProxiedModel(props, 'modelValue', undefined,
    // Always display masked value in input when mask is applied
    val => props.mask ? mask.mask(mask.unmask(val)) : val, val => {
      if (props.mask) {
        // E.g. mask is #-# and the input value is '2-23'
        // model-value should be enforced to '2-2'
        const newMaskedValue = mask.mask(mask.unmask(val));
        const newUnmaskedValue = mask.unmask(newMaskedValue);
        const newCaretPosition = getNewCaretPosition({
          oldValue: model.value,
          newValue: newMaskedValue,
          oldCaret: caretPosition.value
        });
        vTextFieldRef.value.value = newMaskedValue;
        vTextFieldRef.value.setSelectionRange(newCaretPosition, newCaretPosition);
        return returnMaskedValue.value ? mask.mask(newUnmaskedValue) : newUnmaskedValue;
      }
      return val;
    });
    const validationValue = toRef(() => returnMaskedValue.value ? model.value : mask.unmask(model.value));
    function getNewCaretPosition({
      oldValue,
      newValue,
      oldCaret
    }) {
      if (!newValue) return 0;
      if (!oldValue) return newValue.length;
      let newCaret;
      if (inputAction.value === 'Backspace') {
        newCaret = oldCaret - 1;
        while (newCaret > 0 && mask.isDelimiter(newValue, newCaret - 1)) newCaret--;
      } else if (inputAction.value === 'Delete') {
        newCaret = oldCaret;
      } else {
        // insertion
        newCaret = oldCaret + 1;
        while (mask.isDelimiter(newValue, newCaret)) newCaret++;
        if (mask.isDelimiter(newValue, oldCaret)) newCaret++;
      }
      return newCaret;
    }
    onBeforeMount(() => {
      if (props.returnMaskedValue) {
        emit('update:modelValue', model.value);
      }
    });
    function onKeyDown(e) {
      if (e.metaKey) return;
      const inputElement = e.target;
      caretPosition.value = inputElement.selectionStart || 0;
      inputAction.value = e.key;
      const hasSelection = inputElement.selectionStart !== inputElement.selectionEnd;
      if (e.key === 'Backspace' && hasSelection) {
        e.preventDefault();
        deleteSelection(e);
      }
    }
    async function onCut(e) {
      e.preventDefault();
      await copySelectionToClipboard(e);
      await deleteSelection(e);
    }
    async function onPaste(e) {
      e.preventDefault();
      const inputElement = e.target;
      const pastedString = e.clipboardData?.getData('text') || '';
      if (!pastedString) return;
      const pastedCharacters = [...pastedString];
      const hasSelection = inputElement.selectionStart !== inputElement.selectionEnd;
      if (hasSelection) {
        replaceSelection(inputElement, pastedCharacters);
      } else {
        insertCharacters(inputElement, pastedCharacters);
      }
    }
    async function copySelectionToClipboard(e) {
      const inputElement = e.target;
      const start = inputElement.selectionStart || 0;
      const end = inputElement.selectionEnd || 0;
      const selectedText = inputElement.value.substring(start, end);
      await navigator.clipboard.writeText(selectedText);
    }
    async function deleteSelection(e) {
      const inputElement = e.target;
      const curStart = inputElement.selectionStart || 0;
      caretPosition.value = inputElement.selectionEnd || 0;
      while (caretPosition.value > curStart) {
        const success = await simulateBackspace(inputElement);
        if (!success) break;
      }
    }
    async function simulateBackspace(inputElement) {
      inputAction.value = 'Backspace';
      model.value = inputElement.value.slice(0, caretPosition.value - 1) + inputElement.value.slice(caretPosition.value);
      inputAction.value = '';
      if (caretPosition.value === inputElement.selectionEnd) return false;
      caretPosition.value = inputElement.selectionEnd || 0;
      await nextTick();
      return true;
    }
    async function insertCharacters(inputElement, pastedCharacters) {
      for (let i = 0; i < pastedCharacters.length; i++) {
        await insertCharacter(inputElement, pastedCharacters[i]);
      }
    }
    async function insertCharacter(inputElement, character) {
      caretPosition.value = inputElement.selectionEnd || 0;
      model.value = inputElement.value.slice(0, caretPosition.value) + character + inputElement.value.slice(caretPosition.value);
      await nextTick();
    }
    async function replaceSelection(inputElement, pastedCharacters) {
      caretPosition.value = inputElement.selectionStart || 0;
      for (let i = 0; i < pastedCharacters.length; i++) {
        const nextIndex = await replaceCharacter(caretPosition.value, pastedCharacters[i]);
        if (nextIndex !== -1) {
          caretPosition.value = nextIndex;
        }
      }
    }
    async function replaceCharacter(index, character) {
      let targetIndex = index;

      // Find next non-delimiter position
      while (targetIndex < model.value.length && mask.isDelimiter(model.value, targetIndex)) {
        targetIndex++;
      }
      const newValue = model.value.slice(0, targetIndex) + character + model.value.slice(targetIndex + 1);
      if (mask.isValid(newValue)) {
        model.value = newValue;
        await nextTick();
        return targetIndex + 1;
      }
      return -1;
    }
    useRender(() => {
      const textFieldProps = VTextField.filterProps(props);
      return createVNode(VTextField, mergeProps(textFieldProps, {
        "modelValue": model.value,
        "onUpdate:modelValue": $event => model.value = $event,
        "ref": vTextFieldRef,
        "class": ['v-mask-input', props.class],
        "style": props.style,
        "validationValue": validationValue.value,
        "onCut": onCut,
        "onPaste": onPaste,
        "onKeydown": onKeyDown
      }), {
        ...slots
      });
    });
    return forwardRefs({}, vTextFieldRef);
  }
});

/*
 * Credits: Alexander Milevski https://github.com/w8r/svg-arc-corners
 */

function pointOnArc(center, radius, angle) {
  const radians = (angle - 90) * Math.PI / 180.0;
  return [center[0] + radius * Math.cos(radians), center[1] + radius * Math.sin(radians)];
}
function drawCircle([x, y], r, width) {
  const innerRadius = r - width;
  return ['M', x - r, y, 'A', r, r, 0, 1, 0, x + r, y, 'A', r, r, 0, 1, 0, x - r, y, 'M', x - innerRadius, y, 'A', innerRadius, innerRadius, 0, 1, 0, x + innerRadius, y, 'A', innerRadius, innerRadius, 0, 1, 0, x - innerRadius, y, 'Z'];
}
function simpleArc(center, r, startAngle, endAngle) {
  const start = pointOnArc(center, r, startAngle);
  const end = pointOnArc(center, r, endAngle);
  const sweep = endAngle - startAngle > 180 ? 1 : 0;
  return [`M${start[0]} ${start[1]}`, `A${r} ${r} 0 ${sweep} 1 ${end[0]} ${end[1]}`, `L${center[0]} ${center[1]}Z`].join(' ');
}
function roundedArc(center, radius, startAngle, endAngle, width, rounding) {
  width = Math.min(radius, width);
  if (Math.abs(endAngle - startAngle) === 360) {
    return drawCircle(center, radius, width).join(' ');
  }
  if (rounding === 0 && radius === width) {
    return simpleArc(center, radius, startAngle, endAngle);
  }
  const innerR = radius - width;
  const circumference = Math.abs(endAngle - startAngle);
  rounding = Math.min(width / 2, rounding);
  if (360 * (rounding / (Math.PI * (radius - width))) > Math.abs(startAngle - endAngle)) {
    rounding = circumference / 360 * innerR * Math.PI;
  }

  // inner and outer radiuses
  const innerR2 = innerR + rounding;
  const outerRadius = radius - rounding;

  // butts corner points
  const oStart = pointOnArc(center, outerRadius, startAngle);
  const oEnd = pointOnArc(center, outerRadius, endAngle);
  const iStart = pointOnArc(center, innerR2, startAngle);
  const iEnd = pointOnArc(center, innerR2, endAngle);
  const iSection = innerR ? 360 * (rounding / (2 * Math.PI * innerR)) : 0;
  const oSection = 360 * (rounding / (2 * Math.PI * radius));

  // arcs endpoints
  const iArcStart = pointOnArc(center, innerR, startAngle + iSection);
  const iArcEnd = pointOnArc(center, innerR, endAngle - iSection);
  const oArcStart = pointOnArc(center, radius, startAngle + oSection);
  const oArcEnd = pointOnArc(center, radius, endAngle - oSection);
  const arcSweep1 = circumference > 180 + 2 * oSection ? 1 : 0;
  const arcSweep2 = circumference > 180 + 2 * iSection ? 1 : 0;
  return [
  // begin path
  'M', oStart[0], oStart[1],
  // outer start corner
  'A', rounding, rounding, 0, 0, 1, oArcStart[0], oArcStart[1],
  // outer main arc
  'A', radius, radius, 0, arcSweep1, 1, oArcEnd[0], oArcEnd[1],
  // outer end corner
  'A', rounding, rounding, 0, 0, 1, oEnd[0], oEnd[1],
  // end butt
  'L', iEnd[0], iEnd[1],
  // inner end corner
  'A', rounding, rounding, 0, 0, 1, iArcEnd[0], iArcEnd[1],
  // inner arc
  'A', innerR, innerR, 0, arcSweep2, 0, iArcStart[0], iArcStart[1],
  // inner start corner
  'A', rounding, rounding, 0, 0, 1, iStart[0], iStart[1], 'Z' // end path
  ].join(' ');
}

// Utilities

// Types

function formatTextTemplate(template, item) {
  return item ? template.replaceAll('[title]', item.title).replaceAll('[value]', String(item.value)) : undefined;
}
function usePieArc(props, isHovering) {
  const hoverZoomRatio = toRef(() => clamp(Number(props.hoverScale ?? 0), 0, 0.25));
  const normalizedValue = toRef(() => clamp(props.value - 100 * Number(props.gap ?? 0) / 360, 0.01, 99.99));
  const normalizedInnerCut = toRef(() => {
    const min = Number(props.rounded ?? 0) > 0 ? 0.2 : 0;
    return clamp(Number(props.innerCut ?? 0) / 100, min, 1);
  });
  const radians = computed(() => (360 * (-normalizedValue.value / 100) + 90) * (Math.PI / 180));
  const arcWidth = computed(() => 50 * (1 - normalizedInnerCut.value) * (isHovering.value ? 1 : 1 - hoverZoomRatio.value));
  const outerX = toRef(() => 50 + 50 * Math.cos(radians.value));
  const outerY = toRef(() => 50 - 50 * Math.sin(radians.value));
  return {
    hoverZoomRatio,
    normalizedValue,
    normalizedInnerCut,
    outerX,
    outerY,
    arcWidth
  };
}
function useOuterSlicePath({
  angle,
  radius,
  size,
  width,
  rounded
}) {
  return computed(() => roundedArc([50, 50], toValue(radius), toValue(angle), toValue(angle) + 360 * toValue(size) / 100,
  // angle end,
  toValue(width), toValue(rounded)));
}
function useInnerSlicePath({
  angle,
  radius,
  size
}) {
  return computed(() => simpleArc([50, 50], toValue(radius), toValue(angle), toValue(angle) + 360 * toValue(size) / 100 // angle end,
  ));
}

// Types

const makeVPieSegmentProps = propsFactory({
  active: Boolean,
  rotate: [Number, String],
  value: {
    type: Number,
    default: 0
  },
  color: String,
  innerCut: [Number, String],
  hoverScale: {
    type: [Number, String],
    default: 0.05
  },
  gap: [Number, String],
  rounded: [Number, String],
  animation: {
    type: [Boolean, Object],
    default: false
  },
  pattern: String,
  hideSlice: Boolean,
  ...makeRevealProps()
}, 'VPieSegment');
const VPieSegment = genericComponent()({
  name: 'VPieSegment',
  props: makeVPieSegmentProps(),
  emits: {
    'update:active': val => true
  },
  setup(props) {
    const isActive = useProxiedModel(props, 'active');
    const {
      state: revealState,
      duration: revealDuration
    } = useReveal(props);
    const transitionConfig = computed(() => {
      const defaultEasing = 'easeInOutCubic';
      const defaultDuration = 400;
      const easingName = typeof props.animation === 'object' ? props.animation.easing ?? defaultEasing : defaultEasing;
      return {
        duration: ['initial', 'pending'].includes(revealState.value) ? revealDuration.value : typeof props.animation === 'object' ? props.animation.duration : props.animation ? defaultDuration : 0,
        transition: easingPatterns[easingName]
      };
    });
    const {
      hoverZoomRatio,
      normalizedValue,
      normalizedInnerCut,
      outerX,
      outerY,
      arcWidth
    } = usePieArc(props, isActive);
    const arcSize = toRef(() => revealState.value === 'initial' ? 0 : normalizedValue.value);
    const currentArcSize = useTransition(arcSize, transitionConfig);
    const angle = toRef(() => revealState.value === 'initial' ? 0 : Number(props.rotate ?? 0) + Number(props.gap ?? 0) / 2);
    const currentAngle = useTransition(angle, transitionConfig);
    const arcRadius = toRef(() => 50 * (isActive.value ? 1 : 1 - hoverZoomRatio.value));
    const currentArcRadius = useTransition(arcRadius, transitionConfig);
    const currentArcWidth = useTransition(arcWidth, transitionConfig);
    const outerSlicePath = useOuterSlicePath({
      angle: currentAngle,
      radius: currentArcRadius,
      size: currentArcSize,
      width: currentArcWidth,
      rounded: () => Number(props.rounded ?? 0)
    });
    const innerSlicePath = useInnerSlicePath({
      angle: currentAngle,
      radius: () => currentArcRadius.value - currentArcWidth.value,
      size: currentArcSize
    });
    const overlayPath = toRef(() => `M 50 0 A 50 50 0 ${normalizedValue.value > 50 ? 1 : 0} 1 ${outerX.value} ${outerY.value} L 50 50`);
    return () => createElementVNode("g", {
      "class": "v-pie-segment",
      "style": {
        color: props.color
      }
    }, [createElementVNode("path", {
      "key": "outer-slice",
      "fill": "currentColor",
      "shape-rendering": "geometricPrecision",
      "d": outerSlicePath.value
    }, null), props.pattern && createElementVNode("path", {
      "key": "pattern-overlay",
      "shape-rendering": "geometricPrecision",
      "fill": props.pattern,
      "d": outerSlicePath.value
    }, null), !props.hideSlice && normalizedInnerCut.value > 0 && createElementVNode("path", {
      "key": "inner-slice",
      "fill": "oklch(from currentColor l c h / calc(alpha / 2))",
      "d": innerSlicePath.value
    }, null), ['disabled', 'done'].includes(revealState.value) && createElementVNode("path", {
      "transform": `rotate(${currentAngle.value} 50 50)`,
      "class": "v-pie-segment__overlay",
      "d": overlayPath.value,
      "onMouseenter": () => isActive.value = true,
      "onMouseleave": () => isActive.value = false
    }, null)]);
  }
});

// Types

const makeVPieTooltipProps = propsFactory({
  modelValue: Boolean,
  target: Object,
  item: {
    type: Object,
    default: null
  },
  titleFormat: {
    type: [String, Function],
    default: '[title]'
  },
  subtitleFormat: {
    type: [String, Function],
    default: '[value]'
  },
  ...makeTransitionProps(),
  ...pick(makeVTooltipProps(), ['offset'])
}, 'VPieTooltip');
const VPieTooltip = genericComponent()({
  name: 'VPieTooltip',
  props: makeVPieTooltipProps(),
  setup(props, {
    slots
  }) {
    const tooltipTitleFormatFunction = toRef(() => segment => {
      return typeof props.titleFormat === 'function' ? props.titleFormat(segment) : formatTextTemplate(props.titleFormat, segment);
    });
    const tooltipSubtitleFormatFunction = toRef(() => segment => {
      return typeof props.subtitleFormat === 'function' ? props.subtitleFormat(segment) : formatTextTemplate(props.subtitleFormat, segment);
    });
    return () => createVNode(VTooltip, {
      "offset": props.offset,
      "modelValue": props.modelValue,
      "target": props.target,
      "contentClass": "v-pie__tooltip-content"
    }, {
      default: () => [!!props.item && (slots.default?.({
        item: props.item
      }) ?? createVNode(MaybeTransition, {
        "transition": props.transition,
        "mode": "out-in"
      }, {
        default: () => [createVNode(VListItem, {
          "key": props.item.key,
          "density": "compact",
          "title": tooltipTitleFormatFunction.value(props.item),
          "subtitle": tooltipSubtitleFormatFunction.value(props.item)
        }, {
          prepend: slots.prepend ? () => slots.prepend({
            item: props.item
          }) : undefined
        })]
      }))]
    });
  }
});

// Types

const makeVPieProps = propsFactory({
  title: String,
  bgColor: String,
  items: {
    type: Array,
    default: () => []
  },
  palette: {
    type: Array,
    default: () => []
  },
  itemKey: {
    type: String,
    default: 'key'
  },
  itemValue: {
    type: String,
    default: 'value'
  },
  itemTitle: {
    type: String,
    default: 'title'
  },
  size: {
    type: [Number, String],
    default: 250
  },
  rotate: [Number, String],
  gaugeCut: [Number, String],
  legend: {
    type: [Boolean, Object],
    default: false
  },
  tooltip: {
    type: [Boolean, Object],
    default: false
  },
  ...makeDensityProps(),
  ...pick(makeVPieSegmentProps(), ['animation', 'gap', 'rounded', 'innerCut', 'hoverScale', 'hideSlice', 'reveal'])
}, 'VPie');
const VPie = genericComponent()({
  name: 'VPie',
  directives: {
    vClickOutside: ClickOutside
  },
  props: makeVPieProps(),
  setup(props, {
    slots
  }) {
    const legendConfig = computed(() => ({
      visible: !!props.legend,
      position: 'bottom',
      textFormat: '[title]',
      ...(typeof props.legend === 'object' ? props.legend : {})
    }));
    const {
      colorClasses,
      colorStyles
    } = useColor(() => ({
      background: props.bgColor
    }));
    const textColorStyles = toRef(() => pick(colorStyles.value, ['color', 'caretColor']));
    const legendAvatarSize = toRef(() => ({
      default: 20,
      comfortable: 18,
      compact: 16
    })[props.density ?? 'default']);
    const legendDirection = toRef(() => ['left', 'right'].includes(legendConfig.value.position) ? 'vertical' : 'horizontal');
    const legendMode = toRef(() => !legendConfig.value.visible ? 'hidden' : legendConfig.value.position);
    const legendTextFormatFunction = toRef(() => item => {
      return typeof legendConfig.value.textFormat === 'function' ? legendConfig.value.textFormat(item) : formatTextTemplate(legendConfig.value.textFormat, item);
    });
    const arcs = computed(() => {
      // hidden items get (value: 0) to trigger disappearing animation
      return props.items.filter(Boolean).map((item, index) => {
        return {
          key: item[props.itemKey],
          color: item.color ?? colorFromPalette(index),
          value: item[props.itemValue],
          title: String(item[props.itemTitle]),
          pattern: item.pattern ?? patternFromPalette(index),
          raw: item
        };
      });
    });
    const visibleItemsKeys = shallowRef([]);
    watch(() => arcs.value.length, () => {
      // reset when number of items changes
      visibleItemsKeys.value = arcs.value.map(a => a.key);
    }, {
      immediate: true
    });
    const visibleItems = computed(() => {
      // hidden items get (value: 0) to trigger disappearing animation
      return arcs.value.map(item => {
        return isVisible(item) ? item : {
          ...item,
          value: 0
        };
      });
    });
    const total = computed(() => visibleItems.value.reduce((sum, item) => sum + item.value, 0));
    const gaugeCut = toRef(() => Number(props.gaugeCut ?? 0));
    const gaugeOffset = computed(() => (1 - Math.cos(Math.PI * Math.min(90, gaugeCut.value / 2) / 180)) / 2);
    const rotateDeg = computed(() => `${gaugeCut.value ? 180 + gaugeCut.value / 2 : props.rotate ?? 0}deg`);
    function arcOffset(index) {
      return visibleItems.value.slice(0, index).reduce((acc, s) => acc + (total.value > 0 ? s.value / total.value : 0) * (360 - gaugeCut.value), 0);
    }
    function arcSize(v) {
      return v / total.value * (100 - gaugeCut.value / 3.6);
    }
    function colorFromPalette(index) {
      if (props.palette.length === 0) return undefined;
      const paletteItem = props.palette[index % props.palette.length];
      return typeof paletteItem === 'object' ? paletteItem.color : paletteItem;
    }
    function patternFromPalette(index) {
      if (props.palette.length === 0) return undefined;
      const paletteItem = props.palette[index % props.palette.length];
      return typeof paletteItem === 'object' ? paletteItem.pattern : undefined;
    }
    function isVisible(item) {
      return visibleItemsKeys.value.includes(item.key);
    }
    function toggle(item) {
      if (isVisible(item)) {
        visibleItemsKeys.value = visibleItemsKeys.value.filter(x => x !== item.key);
      } else {
        visibleItemsKeys.value = [...visibleItemsKeys.value, item.key];
      }
    }
    const activeItemKey = shallowRef(null);
    const tooltipItem = shallowRef(null);
    const tooltipVisible = shallowRef(false);
    const tooltipTarget = shallowRef([0, 0]);
    let mouseLeaveTimeout = null;
    function setItemActive(item, active) {
      activeItemKey.value = active ? item.key : null;
      if (props.tooltip) {
        setTooltip(item, active);
      }
    }
    function setTooltip(item, active) {
      clearTimeout(mouseLeaveTimeout);
      if (active) {
        tooltipVisible.value = true;
        tooltipItem.value = item;
      } else {
        mouseLeaveTimeout = setTimeout(() => {
          tooltipVisible.value = false;

          // intentionally reusing timeout here
          mouseLeaveTimeout = setTimeout(() => {
            tooltipItem.value = null;
          }, 500);
        }, 100);
      }
    }
    let frame = -1;
    function onSvgMousemove({
      clientX,
      clientY
    }) {
      cancelAnimationFrame(frame);
      frame = requestAnimationFrame(() => {
        tooltipTarget.value = [clientX, clientY];
      });
    }
    function onSvgTouchstart({
      touches
    }) {
      if (!touches) return;
      const {
        clientX,
        clientY
      } = touches[0];
      tooltipTarget.value = [clientX, clientY];
    }
    function onSvgClickOutside() {
      activeItemKey.value = null;
      tooltipVisible.value = false;
    }
    return () => {
      const segmentProps = pick(props, ['animation', 'gap', 'rounded', 'hideSlice', 'reveal', 'innerCut', 'hoverScale']);
      const defaultTooltipTransition = {
        name: 'fade-transition',
        duration: 150
      };
      const tooltipProps = {
        item: tooltipItem.value,
        modelValue: tooltipVisible.value,
        titleFormat: typeof props.tooltip === 'object' ? props.tooltip.titleFormat : '[title]',
        subtitleFormat: typeof props.tooltip === 'object' ? props.tooltip.subtitleFormat : '[value]',
        transition: typeof props.tooltip === 'object' ? props.tooltip.transition : defaultTooltipTransition,
        offset: typeof props.tooltip === 'object' ? props.tooltip.offset : 16,
        target: tooltipTarget.value
      };
      const legendDefaults = {
        VChipGroup: {
          direction: legendDirection.value
        },
        VChip: {
          density: props.density
        },
        VAvatar: {
          size: legendAvatarSize.value
        }
      };
      const tooltipDefaults = {
        VAvatar: {
          size: typeof props.tooltip === 'object' ? props.tooltip.avatarSize ?? 28 : 28
        }
      };
      const avatarSlot = ({
        item
      }) => createVNode(VAvatar, {
        "color": item.color,
        "start": true
      }, {
        default: () => [item.pattern && createElementVNode("svg", {
          "height": "40",
          "width": "40"
        }, [createElementVNode("rect", {
          "width": "40",
          "height": "40",
          "fill": item.pattern
        }, null)])]
      });
      return createElementVNode("div", {
        "class": normalizeClass(['v-pie', `v-pie--legend-${legendMode.value}`]),
        "style": {
          '--v-pie-size': convertToUnit(props.size)
        }
      }, [slots.title?.() ?? (props.title && createElementVNode("div", {
        "class": "v-pie__title"
      }, [props.title])), createElementVNode("div", {
        "class": normalizeClass(['v-pie__content', colorClasses.value]),
        "style": normalizeStyle([{
          transform: `rotate(${rotateDeg.value})`,
          marginBottom: `calc(-1 * ${convertToUnit(props.size)} * ${gaugeOffset.value})`
        }, textColorStyles.value])
      }, [createElementVNode("div", {
        "class": normalizeClass(['v-pie__content-underlay', colorClasses.value]),
        "style": normalizeStyle(colorStyles.value)
      }, null), withDirectives(createElementVNode("svg", {
        "xmlns": "http://www.w3.org/2000/svg",
        "viewBox": "0 0 100 100",
        "class": "v-pie__segments",
        "onMousemove": onSvgMousemove,
        "onTouchstart": onSvgTouchstart
      }, [arcs.value.map((item, index) => createVNode(VPieSegment, mergeProps(segmentProps, {
        "key": item.key,
        "active": activeItemKey.value === item.key,
        "color": item.color,
        "value": isVisible(item) ? arcSize(item.value) : 0,
        "rotate": arcOffset(index),
        "pattern": item.pattern,
        "onUpdate:active": val => setItemActive(item, val),
        "onTouchend": () => setItemActive(item, true)
      }), null))]), [[ClickOutside, {
        handler: onSvgClickOutside
      }]]), createElementVNode("div", {
        "class": "v-pie__center-content",
        "style": {
          transform: `translate(-50%, -50%)
                  rotate(-${rotateDeg.value})
                  translateY(calc(-100% * ${gaugeOffset.value}))`
        }
      }, [createElementVNode("div", null, [slots.center?.({
        total: total.value
      })])])]), legendConfig.value.visible && createVNode(VDefaultsProvider, {
        "key": "legend",
        "defaults": legendDefaults
      }, {
        default: () => [createElementVNode("div", {
          "class": "v-pie__legend"
        }, [slots.legend?.({
          isActive: isVisible,
          toggle,
          items: arcs.value,
          total: total.value
        }) ?? createVNode(VChipGroup, {
          "column": true,
          "multiple": true,
          "modelValue": visibleItemsKeys.value,
          "onUpdate:modelValue": $event => visibleItemsKeys.value = $event
        }, {
          default: () => [arcs.value.map(item => createVNode(VChip, {
            "value": item.key
          }, {
            prepend: () => avatarSlot({
              item
            }),
            default: () => createElementVNode("div", {
              "class": "v-pie__legend__text"
            }, [slots['legend-text']?.({
              item,
              total: total.value
            }) ?? legendTextFormatFunction.value(item)])
          }))]
        })])]
      }), !!props.tooltip && createVNode(VDefaultsProvider, {
        "defaults": tooltipDefaults
      }, {
        default: () => [createVNode(VPieTooltip, tooltipProps, {
          default: slots.tooltip ? slotProps => slots.tooltip?.({
            ...slotProps,
            total: total.value
          }) : undefined,
          prepend: avatarSlot
        })]
      })]);
    };
  }
});

// Types

const makeVProgressProps = propsFactory({
  type: {
    type: String,
    default: 'linear'
  },
  label: String,
  detailsPosition: {
    type: String,
    default: 'top'
  },
  valueFormat: {
    type: [String, Function],
    default: '[percent]%'
  },
  max: {
    type: [Number, String],
    default: 100
  },
  absolute: Boolean,
  hideLabel: Boolean,
  hideValue: Boolean,
  indeterminate: Boolean,
  rounded: Boolean,
  ...pick(makeVProgressLinearProps(), [
  // relevant props shared between linear and circular
  'modelValue', 'color', 'bgColor', 'theme']),
  ...makeComponentProps()
}, 'VProgress');
function formatValue(format, value, max, percent) {
  if (typeof format === 'function') return format({
    value,
    max,
    percent
  });
  return format.replaceAll('[value]', String(value)).replaceAll('[max]', String(max)).replaceAll('[percent]', String(Math.round(percent)));
}
const VProgress = genericComponent()({
  name: 'VProgress',
  props: makeVProgressProps(),
  setup(props, {
    slots
  }) {
    const isLinear = toRef(() => props.type === 'linear');
    const max = toRef(() => parseFloat(props.max) || 100);
    const normalizedValue = computed(() => clamp(parseFloat(props.modelValue), 0, max.value));
    const percent = computed(() => normalizedValue.value / max.value * 100);
    const formattedValue = toRef(() => formatValue(props.valueFormat, normalizedValue.value, max.value, percent.value));
    useRender(() => {
      const hasDetails = !!(props.label || slots.label) && !(props.hideLabel && props.hideValue);
      const scopeProps = {
        max: max.value,
        percent: percent.value,
        value: normalizedValue.value,
        formattedValue: formattedValue.value
      };
      const progressProps = {
        role: 'progressbar',
        'aria-label': props.label,
        'aria-valuenow': props.indeterminate ? undefined : normalizedValue.value,
        'aria-valuemin': 0,
        'aria-valuemax': max.value,
        'aria-valuetext': props.indeterminate ? undefined : formattedValue.value
      };
      function progressComponent() {
        if (isLinear.value) {
          const linearProps = VProgressLinear.filterProps(props);
          return createVNode(VProgressLinear, mergeProps(linearProps, {
            "modelValue": props.modelValue,
            "aria-hidden": "true"
          }), null);
        }
        const circularProps = VProgressCircular.filterProps(omit(props, ['indeterminate']));
        return createVNode(VProgressCircular, mergeProps(circularProps, {
          "modelValue": percent.value,
          "aria-hidden": "true",
          "indeterminate": props.indeterminate
        }), null);
      }
      return createElementVNode("div", mergeProps({
        "class": ['v-progress', {
          'v-progress--absolute': props.absolute
        }, props.class],
        "style": props.style
      }, progressProps), [hasDetails && createElementVNode("div", {
        "key": "details",
        "class": normalizeClass(['v-progress__details', `v-progress__details--location-${props.detailsPosition}`]),
        "aria-hidden": "true"
      }, [!props.hideLabel && createElementVNode("div", {
        "key": "label",
        "class": "v-progress__label"
      }, [slots.label?.(scopeProps) ?? props.label]), !props.hideValue && createElementVNode("div", {
        "key": "value",
        "class": "v-progress__value"
      }, [slots.value?.(scopeProps) ?? formattedValue.value])]), slots.default?.(scopeProps) ?? progressComponent(), props.absolute && hasDetails && createElementVNode("div", {
        "key": "spacer",
        "class": "v-progress__spacer",
        "style": {
          order: props.detailsPosition === 'bottom' ? -1 : 2
        }
      }, null)]);
    });
    return {};
  }
});

// Utilities

// Types

function useDirectiveComponent(component, props) {
  const concreteComponent = typeof component === 'string' ? resolveComponent(component) : component;
  const hook = mountComponent(concreteComponent, props);
  return {
    mounted: hook,
    updated: hook,
    unmounted(el) {
      render(null, el);
    }
  };
}
function mountComponent(component, props) {
  return function (el, binding, vnode) {
    const _props = typeof props === 'function' ? props(binding) : props;
    const text = binding.value?.text ?? binding.value ?? _props?.text;
    const value = isObject(binding.value) ? binding.value : {};

    // Get the children from the props or directive value, or the element's children
    const children = () => text ?? el.textContent;

    // If vnode.ctx is the same as the instance, then we're bound to a plain element
    // and need to find the nearest parent component instance to inherit provides from
    const provides = (vnode.ctx === binding.instance.$ ? findComponentParent(vnode, binding.instance.$)?.provides : vnode.ctx?.provides) ?? binding.instance.$.provides;
    const node = h(component, mergeProps(_props, value), children);
    node.appContext = Object.assign(Object.create(null), binding.instance.$.appContext, {
      provides
    });
    render(node, el);
  };
}
function findComponentParent(vnode, root) {
  // Walk the tree from root until we find the child vnode
  const stack = new Set();
  const walk = children => {
    for (const child of children) {
      if (!child) continue;
      if (child === vnode || child.el && vnode.el && child.el === vnode.el) {
        return true;
      }
      stack.add(child);
      let result;
      if (child.suspense) {
        result = walk([child.ssContent]);
      } else if (Array.isArray(child.children)) {
        result = walk(child.children);
      } else if (child.component?.vnode) {
        result = walk([child.component?.subTree]);
      }
      if (result) {
        return result;
      }
      stack.delete(child);
    }
    return false;
  };
  if (!walk([root.subTree])) {
    consoleError('Could not find original vnode, component will not inherit provides');
    return root;
  }

  // Return the first component parent
  const result = Array.from(stack).reverse();
  for (const child of result) {
    if (child.component) {
      return child.component;
    }
  }
  return root;
}

// Components

// Types

const Tooltip = useDirectiveComponent(VTooltip, binding => {
  const disabled = isObject(binding.value) ? !binding.value.text : ['', false, null].includes(binding.value); // undefined means true

  return {
    activator: disabled ? null : 'parent',
    location: binding.arg?.replace('-', ' '),
    text: typeof binding.value === 'boolean' ? undefined : binding.value
  };
});

// Types

const makeVVideoVolumeProps = propsFactory({
  inline: Boolean,
  label: String,
  direction: {
    type: String,
    default: 'vertical'
  },
  modelValue: {
    type: Number,
    default: 0
  },
  menuProps: Object,
  sliderProps: Object,
  onClick: EventProp(),
  ...makeComponentProps()
}, 'VVideoVolume');
const VVideoVolume = genericComponent()({
  name: 'VVideoVolume',
  directives: {
    vTooltip: Tooltip
  },
  props: makeVVideoVolumeProps(),
  emits: {
    'update:modelValue': val => true
  },
  setup(props, {
    attrs
  }) {
    const {
      t
    } = useLocale();
    const volume = useProxiedModel(props, 'modelValue');
    const volumeIcon = toRef(() => volume.value > 70 ? '$volumeHigh' : volume.value > 40 ? '$volumeMedium' : volume.value > 10 ? '$volumeLow' : '$volumeOff');
    const containerRef = ref();
    const menu = shallowRef(false);
    useRender(() => {
      const sliderDefaults = {
        hideDetails: true,
        step: 5,
        thumbSize: 16
      };
      return createElementVNode("div", {
        "class": normalizeClass(['v-video-volume', {
          'v-video-volume--inline': props.inline
        }, props.class]),
        "style": normalizeStyle(props.style),
        "ref": containerRef
      }, [withDirectives(createVNode(VIconBtn, mergeProps({
        "icon": volumeIcon.value,
        "aria-label": props.label,
        "onClick": props.onClick
      }, attrs), {
        default: () => [createVNode(VIcon, null, null), !props.inline && createVNode(VMenu, {
          "modelValue": menu.value,
          "onUpdate:modelValue": $event => menu.value = $event,
          "activator": "parent",
          "attach": containerRef.value,
          "closeOnContentClick": false,
          "location": props.menuProps?.location ?? 'top center',
          "offset": "8"
        }, {
          default: () => [createElementVNode("div", {
            "class": normalizeClass(['v-video-volume__menu', `v-video-volume__menu--${props.direction}`])
          }, [createVNode(VSlider, mergeProps({
            "direction": props.direction,
            "aria-label": t('$vuetify.video.volume'),
            "modelValue": volume.value,
            "onUpdate:modelValue": v => volume.value = v
          }, sliderDefaults, props.sliderProps), null)])]
        })]
      }), [[Tooltip, {
        text: props.label,
        location: 'top',
        disabled: menu.value
      }]]), props.inline && createVNode(VSlider, mergeProps({
        "class": "v-video-volume-inline__slider",
        "minWidth": "50",
        "aria-label": t('$vuetify.video.volume'),
        "modelValue": volume.value,
        "onUpdate:modelValue": v => volume.value = v,
        "onKeydown": e => {
          e.stopPropagation();
        }
      }, sliderDefaults, props.sliderProps), null)]);
    });
  }
});

// Types

const allowedVariants$1 = ['hidden', 'default', 'tube', 'mini'];
const makeVVideoControlsProps = propsFactory({
  color: String,
  backgroundColor: String,
  trackColor: String,
  playing: Boolean,
  hidePlay: Boolean,
  hideVolume: Boolean,
  hideFullscreen: Boolean,
  hideProgressBar: Boolean,
  fullscreen: Boolean,
  floating: Boolean,
  splitTime: Boolean,
  pills: Boolean,
  detached: Boolean,
  progress: {
    type: Number,
    default: 0
  },
  duration: {
    type: Number,
    default: 0
  },
  volume: [Number, String],
  variant: {
    type: String,
    default: 'default',
    validator: v => allowedVariants$1.includes(v)
  },
  volumeProps: Object,
  ...makeDensityProps(),
  ...makeElevationProps(),
  ...makeThemeProps()
}, 'VVideoControls');
const VVideoControls = genericComponent()({
  name: 'VVideoControls',
  directives: {
    vTooltip: Tooltip
  },
  props: makeVVideoControlsProps(),
  emits: {
    'update:playing': val => true,
    'update:progress': val => true,
    'update:volume': val => true,
    skip: val => true,
    'click:fullscreen': () => true
  },
  setup(props, {
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    const {
      themeClasses,
      current: currentTheme
    } = provideTheme(props);
    const {
      densityClasses
    } = useDensity(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(() => {
      const fallbackBackground = props.detached ? 'surface' : undefined;
      return props.backgroundColor ?? fallbackBackground;
    });
    const trackColor = toRef(() => {
      if (props.trackColor) {
        return props.trackColor;
      }
      const fallback = currentTheme.value.dark || !props.pills ? undefined : 'surface';
      return (props.pills ? props.backgroundColor : props.color) ?? fallback;
    });
    const playing = useProxiedModel(props, 'playing');
    const progress = useProxiedModel(props, 'progress');
    const volume = useProxiedModel(props, 'volume', 0, v => Number(v ?? 0));
    const lastVolume = shallowRef();
    const currentTime = computed(() => {
      const secondsElapsed = Math.round(props.progress / 100 * props.duration);
      return {
        elapsed: formatTime(secondsElapsed),
        remaining: formatTime(props.duration - secondsElapsed),
        total: formatTime(props.duration)
      };
    });
    const labels = computed(() => {
      const playIconLocaleKey = playing.value ? 'pause' : 'play';
      const volumeIconLocaleKey = props.volumeProps?.inline ? volume.value ? 'mute' : 'unmute' : 'showVolume';
      const fullscreenIconLocaleKey = props.fullscreen ? 'exitFullscreen' : 'enterFullscreen';
      return {
        seek: t('$vuetify.video.seek'),
        volume: t('$vuetify.video.volume'),
        playAction: t(`$vuetify.video.${playIconLocaleKey}`),
        volumeAction: t(`$vuetify.video.${volumeIconLocaleKey}`),
        fullscreenAction: t(`$vuetify.video.${fullscreenIconLocaleKey}`)
      };
    });
    function play() {
      playing.value = true;
    }
    function pause() {
      playing.value = false;
    }
    function skipTo(v) {
      progress.value = v;
    }
    function toggleMuted() {
      if (volume.value) {
        lastVolume.value = volume.value;
        volume.value = 0;
      } else {
        volume.value = lastVolume.value ?? 100;
      }
    }
    function toggleFullscreen() {
      emit('click:fullscreen');
    }
    useRender(() => {
      const sizes = props.pills ? [42, 36, 30] : [32, 28, 24];
      const innerDefaults = {
        VIconBtn: {
          size: props.density === 'compact' ? sizes[2] : props.density === 'comfortable' ? sizes[1] : sizes[0],
          iconSize: props.density === 'compact' ? 20 : props.density === 'comfortable' ? 24 : 26,
          variant: 'text',
          color: props.color
        },
        VSlider: {
          thumbSize: props.variant === 'tube' ? 10 : 16,
          hideDetails: true
        }
      };
      const regularBtnSize = innerDefaults.VIconBtn.size;
      const playBtnSize = props.pills ? regularBtnSize + 8 : regularBtnSize;
      const pillClasses = ['v-video-control__pill', props.pills ? elevationClasses.value : [], props.pills ? backgroundColorClasses.value : []];
      const pillStyles = props.pills ? backgroundColorStyles.value : [];
      const slotProps = {
        play,
        pause,
        playing: playing.value,
        progress: progress.value,
        currentTime: currentTime.value,
        skipTo,
        volume,
        toggleMuted,
        fullscreen: props.fullscreen,
        toggleFullscreen,
        labels: labels.value
      };
      return createElementVNode("div", {
        "class": normalizeClass(['v-video-controls', `v-video-controls--variant-${props.variant}`, {
          'v-video-controls--pills': props.pills
        }, {
          'v-video-controls--detached': props.detached
        }, {
          'v-video-controls--floating': props.floating
        }, {
          'v-video-controls--fullscreen': props.fullscreen
        }, {
          'v-video-controls--split-time': props.splitTime
        }, !props.pills ? backgroundColorClasses.value : [], props.detached && !props.pills ? elevationClasses.value : [], densityClasses.value, themeClasses.value]),
        "style": normalizeStyle([!props.pills ? backgroundColorStyles.value : [], {
          '--v-video-controls-pill-height': `${regularBtnSize}px`
        }])
      }, [createVNode(VDefaultsProvider, {
        "defaults": innerDefaults
      }, {
        default: () => [slots.default?.(slotProps) ?? createElementVNode(Fragment, null, [props.variant !== 'mini' && createElementVNode(Fragment, null, [!props.hidePlay && createElementVNode("div", {
          "class": normalizeClass([pillClasses, 'v-video__action-play']),
          "style": normalizeStyle(pillStyles)
        }, [withDirectives(createVNode(VIconBtn, {
          "icon": playing.value ? '$pause' : '$play',
          "size": playBtnSize,
          "aria-label": labels.value.playAction,
          "onClick": () => playing.value = !playing.value
        }, null), [[Tooltip, labels.value.playAction, 'top']])]), slots.prepend && createElementVNode("div", {
          "class": normalizeClass(pillClasses),
          "style": normalizeStyle(pillStyles)
        }, [slots.prepend(slotProps)]), props.splitTime ? createElementVNode("span", {
          "class": normalizeClass([pillClasses, 'v-video__time']),
          "style": normalizeStyle(pillStyles)
        }, [currentTime.value.elapsed]) : props.variant !== 'default' ? createElementVNode("span", {
          "class": normalizeClass([pillClasses, 'v-video__time']),
          "style": normalizeStyle(pillStyles)
        }, [currentTime.value.elapsed, createTextVNode(" / "), currentTime.value.total]) : '', props.hideProgressBar ? createVNode(VSpacer, null, null) : createVNode(VSlider, {
          "modelValue": props.progress,
          "noKeyboard": true,
          "color": trackColor.value ?? 'surface-variant',
          "trackColor": props.variant === 'tube' ? 'white' : undefined,
          "class": "v-video__track",
          "thumbLabel": "always",
          "aria-label": labels.value.seek,
          "onUpdate:modelValue": skipTo
        }, {
          'thumb-label': () => currentTime.value.elapsed
        }), props.variant === 'tube' && createVNode(VSpacer, null, null), props.splitTime ? createElementVNode("span", {
          "class": normalizeClass([pillClasses, 'v-video__time']),
          "style": normalizeStyle(pillStyles)
        }, [currentTime.value.remaining]) : '']), props.variant === 'mini' && createElementVNode(Fragment, null, [createVNode(VSpacer, null, null), slots.prepend && createElementVNode("div", {
          "class": normalizeClass(pillClasses),
          "style": normalizeStyle(pillStyles)
        }, [slots.prepend(slotProps)]), !props.hidePlay && createElementVNode("div", {
          "class": normalizeClass([pillClasses, 'v-video__action-play']),
          "style": normalizeStyle(pillStyles)
        }, [withDirectives(createVNode(VIconBtn, {
          "icon": playing.value ? '$pause' : '$play',
          "size": playBtnSize,
          "aria-label": labels.value.playAction,
          "onClick": () => playing.value = !playing.value
        }, null), [[Tooltip, labels.value.playAction, 'top']])])]), (!props.hideVolume || !props.hideFullscreen || slots.append) && createElementVNode("div", {
          "class": normalizeClass(pillClasses),
          "style": normalizeStyle(pillStyles)
        }, [!props.hideVolume && createVNode(VVideoVolume, mergeProps({
          "key": "volume-control",
          "sliderProps": {
            color: props.color
          },
          "modelValue": volume.value,
          "label": labels.value.volumeAction,
          "onUpdate:modelValue": v => volume.value = v,
          "onClick": () => props.volumeProps?.inline && toggleMuted()
        }, props.volumeProps), null), slots.append?.(slotProps), !props.hideFullscreen && withDirectives(createVNode(VIconBtn, {
          "icon": props.fullscreen ? '$fullscreenExit' : '$fullscreen',
          "aria-label": labels.value.fullscreenAction,
          "onClick": toggleFullscreen
        }, null), [[Tooltip, labels.value.fullscreenAction, 'top']])]), props.variant === 'mini' && createVNode(VSpacer, null, null)])]
      })]);
    });
    return {
      toggleMuted
    };
  }
});

// Types

const allowedVariants = ['background', 'player'];
const makeVVideoProps = propsFactory({
  aspectRatio: [String, Number],
  autoplay: Boolean,
  muted: Boolean,
  eager: Boolean,
  error: [Object, Boolean],
  src: String,
  srcObject: Object,
  type: String,
  // e.g. video/mp4
  image: String,
  hideOverlay: Boolean,
  noFullscreen: Boolean,
  startAt: [Number, String],
  variant: {
    type: String,
    default: 'player',
    validator: v => allowedVariants.includes(v)
  },
  controlsTransition: {
    type: [Boolean, String, Object],
    component: VFadeTransition
  },
  controlsVariant: {
    type: String,
    default: 'default'
  },
  controlsProps: {
    type: Object
  },
  rounded: [Boolean, Number, String, Array],
  ...makeComponentProps(),
  ...makeDensityProps(),
  ...makeDimensionProps(),
  ...makeThemeProps(),
  ...omit(makeVVideoControlsProps(), ['fullscreen', 'variant'])
}, 'VVideo');
const VVideo = genericComponent()({
  name: 'VVideo',
  inheritAttrs: false,
  props: makeVVideoProps(),
  emits: {
    error: val => true,
    loaded: element => true,
    'update:error': val => true,
    'update:playing': val => true,
    'update:progress': val => true,
    'update:volume': val => true
  },
  setup(props, {
    attrs,
    emit,
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      densityClasses
    } = useDensity(props);
    const {
      dimensionStyles
    } = useDimension(props);
    const {
      elevationClasses
    } = useElevation(props);
    const {
      ssr
    } = useDisplay();
    const roundedForContainer = toRef(() => Array.isArray(props.rounded) ? props.rounded[0] : props.rounded);
    const roundedForControls = toRef(() => Array.isArray(props.rounded) ? props.rounded.at(-1) : props.rounded ?? false);
    const {
      roundedClasses: roundedContainerClasses,
      roundedStyles: roundedContainerStyles
    } = useRounded(roundedForContainer);
    const {
      roundedClasses: roundedControlsClasses,
      roundedStyles: roundedControlsStyles
    } = useRounded(roundedForControls);
    const containerRef = ref();
    const videoRef = ref();
    const controlsRef = ref();
    const playing = useProxiedModel(props, 'playing');
    const progress = useProxiedModel(props, 'progress');
    const volume = useProxiedModel(props, 'volume', 0, v => Number(v ?? 0));
    const fullscreen = shallowRef(false);
    const waiting = shallowRef(false);
    const triggered = shallowRef(false);
    const startAfterLoad = shallowRef(false);
    const error = useProxiedModel(props, 'error');
    const state = shallowRef(props.autoplay ? 'loading' : 'idle');
    const duration = shallowRef(0);
    const fullscreenEnabled = toRef(() => !props.noFullscreen && !String(attrs.controlsList ?? '').includes('nofullscreen'));
    function onTimeupdate() {
      const {
        currentTime,
        duration
      } = videoRef.value;
      progress.value = duration === 0 ? 0 : 100 * currentTime / duration;
    }
    async function onTriggered() {
      await nextTick();
      if (!videoRef.value) return;
      videoRef.value.addEventListener('timeupdate', onTimeupdate);
      videoRef.value.volume = volume.value / 100;
      if (state.value !== 'loaded') {
        state.value = 'loading';
      }
    }
    function onVideoLoaded() {
      state.value = 'loaded';
      duration.value = videoRef.value.duration;
      const startTime = Number(props.startAt ?? 0);
      if (startTime && startTime <= duration.value) {
        videoRef.value.currentTime = startTime;
        progress.value = duration.value === 0 ? 0 : 100 * startTime / duration.value;
      }
      if (startAfterLoad.value) {
        setTimeout(() => playing.value = true, 100);
      }
      emit('loaded', videoRef.value);
    }
    function onVideoError(e) {
      state.value = 'error';
      error.value = videoRef.value.error;
    }
    watch(error, v => {
      if (v && state.value !== 'error') {
        videoRef.value?.pause();
        state.value = 'error';
      }
    }, {
      immediate: true
    });
    function retry() {
      if (state.value !== 'error') return;
      error.value = false;
      state.value = 'loading';
      triggered.value = true;
      videoRef.value?.load();
      if (!props.srcObject) {
        videoRef.value?.play();
      }
    }
    function onClick() {
      if (['loaded', 'error'].includes(state.value)) return;
      triggered.value = true;
      startAfterLoad.value = !startAfterLoad.value;
    }
    function onKeydown(e) {
      if (!videoRef.value || e.ctrlKey) return;
      if (e.key.startsWith('Arrow')) {
        e.preventDefault();
      }
      switch (true) {
        case e.key === ' ':
          {
            if (!['A', 'BUTTON'].includes(e.target?.tagName)) {
              e.preventDefault();
              playing.value = !playing.value;
            }
            break;
          }
        case e.key === 'ArrowRight':
          {
            const step = 10 * (e.shiftKey ? 6 : 1);
            videoRef.value.currentTime = Math.min(videoRef.value.currentTime + step, duration.value);
            // TODO: show skip indicator
            break;
          }
        case e.key === 'ArrowLeft':
          {
            const step = 10 * (e.shiftKey ? 6 : 1);
            videoRef.value.currentTime = Math.max(videoRef.value.currentTime - step, 0);
            // TODO: show skip indicator
            break;
          }
        case createRange(10).map(String).includes(e.key):
          {
            skipTo(Number(e.key) * 10);
            break;
          }
        case e.key === 'ArrowUp':
          {
            volume.value = Math.min(volume.value + 10, 100);
            // TODO: show volume change indicator
            break;
          }
        case e.key === 'ArrowDown':
          {
            volume.value = Math.max(volume.value - 10, 0);
            // TODO: show volume change indicator
            break;
          }
        case e.key === 'm':
          {
            controlsRef.value?.toggleMuted();
            break;
          }
        case e.key === 'f':
          {
            toggleFullscreen();
            break;
          }
      }
    }
    function skipTo(v) {
      if (!videoRef.value) return;
      progress.value = v;
      videoRef.value.currentTime = duration.value * v / 100;
    }
    watch(() => props.src, v => {
      progress.value = 0;
    });
    watch(() => props.srcObject, async v => {
      if (v) triggered.value = true;
      await nextTick();
      if (videoRef.value) videoRef.value.srcObject = v ?? null;
    });
    watch(videoRef, v => {
      if (v && props.srcObject) v.srcObject = props.srcObject;
    });
    watch(playing, v => {
      if (!videoRef.value) return;
      if (v) {
        videoRef.value.play();
      } else {
        videoRef.value.pause();
      }
    });
    watch(volume, v => {
      if (!videoRef.value) return;
      videoRef.value.volume = v / 100;
    });
    watch(triggered, () => onTriggered(), {
      once: true
    });
    watch(() => props.eager, v => v && (triggered.value = true), {
      immediate: true
    });
    onMounted(() => {
      if (props.autoplay && !ssr) {
        triggered.value = true;
        startAfterLoad.value = true;
      }
    });
    onBeforeUnmount(() => {
      videoRef.value?.removeEventListener('timeupdate', onTimeupdate);
      document.body.removeEventListener('keydown', fullscreenExitShortcut);
      document.removeEventListener('fullscreenchange', onFullscreenExit);
    });
    function focusSlider() {
      const container = videoRef.value?.closest('.v-video');
      const innerSlider = container?.querySelector('[role="slider"]');
      innerSlider?.focus();
    }
    function fullscreenExitShortcut(e) {
      if (['ESC', 'f'].includes(e.key)) {
        toggleFullscreen();
        document.body.removeEventListener('keydown', fullscreenExitShortcut);
      }
    }
    async function toggleFullscreen() {
      if (!fullscreenEnabled.value || !document.fullscreenEnabled) {
        return;
      }
      if (document.fullscreenElement) {
        document.exitFullscreen();
        onFullscreenExit();
      } else {
        await containerRef.value?.requestFullscreen();
        document.body.addEventListener('keydown', fullscreenExitShortcut);
        document.addEventListener('fullscreenchange', onFullscreenExit);
        fullscreen.value = true;
      }
    }
    function onFullscreenExit() {
      // event fires with a delay after requestFullscreen(), ignore first run
      if (document.fullscreenElement) return;
      focusSlider();
      fullscreen.value = false;
      document.body.removeEventListener('keydown', fullscreenExitShortcut);
      document.removeEventListener('fullscreenchange', onFullscreenExit);
    }
    function onVideoClick(e) {
      e.preventDefault();
      if (state.value === 'loaded') {
        playing.value = !playing.value;
        focusSlider();
      }
    }
    function onDoubleClick(e) {
      e.preventDefault();
      toggleFullscreen();
    }
    let lastTap = 0;
    function onTouchend(e) {
      const now = performance.now();
      if (now - lastTap < 500) {
        e.preventDefault();
        toggleFullscreen();
      } else {
        lastTap = now;
      }
    }
    useRender(() => {
      const showControls = state.value === 'loaded' && props.variant === 'player' && props.controlsVariant !== 'hidden';
      const posterTransition = props.variant === 'background' ? 'poster-fade-out' : 'fade-transition';
      const controlsProps = {
        ...VVideoControls.filterProps(omit(props, ['variant', 'rounded', 'hideVolume'])),
        rounded: Array.isArray(props.rounded) ? props.rounded.at(-1) : props.rounded,
        fullscreen: fullscreen.value,
        hideVolume: props.hideVolume || props.muted,
        hideFullscreen: props.hideFullscreen || !fullscreenEnabled.value,
        density: props.density,
        variant: props.controlsVariant,
        playing: playing.value,
        progress: progress.value,
        duration: duration.value,
        volume: volume.value,
        ...props.controlsProps
      };
      const controlsEventHandlers = {
        onSkip: v => skipTo(v),
        'onClick:fullscreen': () => toggleFullscreen(),
        'onUpdate:playing': v => playing.value = v,
        'onUpdate:progress': v => skipTo(v),
        'onUpdate:volume': v => volume.value = v,
        onClick: e => e.stopPropagation()
      };
      const controlslist = [attrs.controlslist, props.noFullscreen ? 'nofullscreen' : ''].filter(Boolean).join(' ');
      const loadingIndicator = createVNode(VProgressCircular, {
        "indeterminate": true,
        "color": props.color,
        "width": "3",
        "size": Math.min(100, Number(props.height) / 2 || 50)
      }, null);
      const overlayPlayIcon = createVNode(VIconBtn, {
        "icon": "$play",
        "size": "80",
        "color": "#fff",
        "variant": "outlined",
        "iconSize": "50",
        "class": normalizeClass(['v-video__center-icon', 'v-video__center-icon--play']),
        "onClick": onVideoClick
      }, null);
      const errorIconProps = {
        icon: '$warning',
        size: '70'
      };
      const activeOverlays = {
        playIcon: props.variant === 'player' && state.value === 'loaded' && !props.hideOverlay && !playing.value,
        poster: state.value !== 'loaded' && state.value !== 'error',
        loading: props.variant === 'player' && state.value !== 'error' && (state.value === 'loading' || waiting.value),
        error: props.variant === 'player' && state.value === 'error'
      };
      return createElementVNode("div", {
        "ref": containerRef,
        "class": normalizeClass(['v-video', `v-video--variant-${props.variant}`, `v-video--${state.value}`, {
          'v-video--playing': playing.value
        }, themeClasses.value, densityClasses.value, roundedContainerClasses.value, props.class]),
        "style": normalizeStyle([{
          '--v-video-aspect-ratio': props.aspectRatio
        }, props.variant === 'background' ? [] : pick(dimensionStyles.value, ['width', 'minWidth', 'maxWidth']), roundedContainerStyles.value, props.style]),
        "onKeydown": onKeydown,
        "onClick": onClick
      }, [createElementVNode("div", {
        "class": normalizeClass(['v-video__content', elevationClasses.value]),
        "style": normalizeStyle([props.variant === 'background' ? [] : dimensionStyles.value])
      }, [(props.eager || triggered.value) && createElementVNode("video", mergeProps({
        "key": "video-element",
        "class": ['v-video__video', roundedContainerClasses.value]
      }, omit(attrs, ['controlslist', 'class', 'style']), {
        "controlslist": controlslist,
        "autoplay": props.autoplay,
        "muted": props.muted,
        "playsinline": true,
        "ref": videoRef,
        "onLoadeddata": onVideoLoaded,
        "onError": onVideoError,
        "onPlay": () => playing.value = true,
        "onPause": () => playing.value = false,
        "onWaiting": () => waiting.value = true,
        "onPlaying": () => waiting.value = false,
        "onClick": onVideoClick,
        "onDblclick": onDoubleClick,
        "onTouchend": onTouchend
      }), [slots.sources?.() ?? createElementVNode("source", {
        "src": props.src,
        "type": props.type
      }, null)]), createVNode(Transition, {
        "name": "fade-transition"
      }, {
        default: () => [activeOverlays.playIcon && createElementVNode("div", {
          "class": "v-video__overlay-fill"
        }, [overlayPlayIcon])]
      }), props.variant === 'player' && !!slots.header && createElementVNode("div", {
        "key": "header",
        "class": "v-video__header"
      }, [slots.header()]), createVNode(MaybeTransition, {
        "transition": posterTransition
      }, {
        default: () => [activeOverlays.poster && createElementVNode("div", {
          "class": "v-video__overlay-fill"
        }, [createVNode(VImg, {
          "cover": true,
          "src": props.image
        }, {
          default: () => [createElementVNode("div", {
            "class": normalizeClass(['v-video__overlay-fill', ...roundedContainerClasses.value])
          }, [props.variant === 'player' && overlayPlayIcon])]
        })])]
      }), activeOverlays.loading && createElementVNode("div", {
        "key": "loading-overlay",
        "class": "v-video__overlay-fill"
      }, [loadingIndicator]), activeOverlays.error && createElementVNode("div", {
        "key": "error-overlay",
        "class": "v-video__overlay-fill"
      }, [slots.error ? createVNode(VDefaultsProvider, {
        "defaults": {
          VIcon: errorIconProps
        }
      }, {
        default: () => [slots.error?.({
          error: error.value
        })]
      }) : createVNode(VIcon, errorIconProps, null)])]), createVNode(MaybeTransition, {
        "key": "actions",
        "transition": props.controlsTransition
      }, {
        default: () => [showControls && createVNode(VVideoControls, mergeProps({
          "ref": controlsRef,
          "class": roundedControlsClasses.value,
          "style": roundedControlsStyles.value
        }, controlsProps, controlsEventHandlers), {
          default: slots.controls,
          prepend: slots.prepend,
          append: slots.append
        })]
      })]);
    });
    return {
      video: videoRef,
      ...forwardRefs({
        retry,
        skipTo,
        toggleFullscreen
      }, controlsRef)
    };
  }
});

var components = /*#__PURE__*/Object.freeze({
  __proto__: null,
  VAlert: VAlert,
  VAlertTitle: VAlertTitle,
  VApp: VApp,
  VAppBar: VAppBar,
  VAppBarNavIcon: VAppBarNavIcon,
  VAppBarTitle: VAppBarTitle,
  VAutocomplete: VAutocomplete,
  VAvatar: VAvatar,
  VAvatarGroup: VAvatarGroup,
  VBadge: VBadge,
  VBanner: VBanner,
  VBannerActions: VBannerActions,
  VBannerText: VBannerText,
  VBottomNavigation: VBottomNavigation,
  VBottomSheet: VBottomSheet,
  VBreadcrumbs: VBreadcrumbs,
  VBreadcrumbsDivider: VBreadcrumbsDivider,
  VBreadcrumbsItem: VBreadcrumbsItem,
  VBtn: VBtn,
  VBtnGroup: VBtnGroup,
  VBtnToggle: VBtnToggle,
  VCalendar: VCalendar,
  VCard: VCard,
  VCardActions: VCardActions,
  VCardItem: VCardItem,
  VCardSubtitle: VCardSubtitle,
  VCardText: VCardText,
  VCardTitle: VCardTitle,
  VCarousel: VCarousel,
  VCarouselItem: VCarouselItem,
  VCheckbox: VCheckbox,
  VCheckboxBtn: VCheckboxBtn,
  VChip: VChip,
  VChipGroup: VChipGroup,
  VClassIcon: VClassIcon,
  VCode: VCode,
  VCol: VCol,
  VColorInput: VColorInput,
  VColorPicker: VColorPicker,
  VCombobox: VCombobox,
  VCommandPalette: VCommandPalette,
  VCommandPaletteItem: VCommandPaletteItem,
  VComponentIcon: VComponentIcon,
  VConfirmEdit: VConfirmEdit,
  VContainer: VContainer,
  VCounter: VCounter,
  VDataIterator: VDataIterator,
  VDataTable: VDataTable,
  VDataTableFooter: VDataTableFooter,
  VDataTableHeaders: VDataTableHeaders,
  VDataTableRow: VDataTableRow,
  VDataTableRows: VDataTableRows,
  VDataTableServer: VDataTableServer,
  VDataTableVirtual: VDataTableVirtual,
  VDateInput: VDateInput,
  VDatePicker: VDatePicker,
  VDatePickerControls: VDatePickerControls,
  VDatePickerHeader: VDatePickerHeader,
  VDatePickerMonth: VDatePickerMonth,
  VDatePickerMonths: VDatePickerMonths,
  VDatePickerYears: VDatePickerYears,
  VDateRangePicker: VDateRangePicker,
  VDefaultsProvider: VDefaultsProvider,
  VDialog: VDialog,
  VDialogBottomTransition: VDialogBottomTransition,
  VDialogTopTransition: VDialogTopTransition,
  VDialogTransition: VDialogTransition,
  VDivider: VDivider,
  VEmptyState: VEmptyState,
  VExpandBothTransition: VExpandBothTransition,
  VExpandTransition: VExpandTransition,
  VExpandXTransition: VExpandXTransition,
  VExpansionPanel: VExpansionPanel,
  VExpansionPanelText: VExpansionPanelText,
  VExpansionPanelTitle: VExpansionPanelTitle,
  VExpansionPanels: VExpansionPanels,
  VFab: VFab,
  VFabTransition: VFabTransition,
  VFadeTransition: VFadeTransition,
  VField: VField,
  VFieldLabel: VFieldLabel,
  VFileInput: VFileInput,
  VFileUpload: VFileUpload,
  VFileUploadDropzone: VFileUploadDropzone,
  VFileUploadItem: VFileUploadItem,
  VFileUploadList: VFileUploadList,
  VFooter: VFooter,
  VForm: VForm,
  VHeatmap: VHeatmap,
  VHeatmapCell: VHeatmapCell,
  VHeatmapLegend: VHeatmapLegend,
  VHeatmapLegendCell: VHeatmapLegendCell,
  VHighlight: VHighlight,
  VHotkey: VHotkey,
  VHover: VHover,
  VIcon: VIcon,
  VIconBtn: VIconBtn,
  VImg: VImg,
  VInfiniteScroll: VInfiniteScroll,
  VInput: VInput,
  VItem: VItem,
  VItemGroup: VItemGroup,
  VKbd: VKbd,
  VLabel: VLabel,
  VLayout: VLayout,
  VLayoutItem: VLayoutItem,
  VLazy: VLazy,
  VLigatureIcon: VLigatureIcon,
  VList: VList,
  VListGroup: VListGroup,
  VListImg: VListImg,
  VListItem: VListItem,
  VListItemAction: VListItemAction,
  VListItemMedia: VListItemMedia,
  VListItemSubtitle: VListItemSubtitle,
  VListItemTitle: VListItemTitle,
  VListSubheader: VListSubheader,
  VLocaleProvider: VLocaleProvider,
  VMain: VMain,
  VMaskInput: VMaskInput,
  VMenu: VMenu,
  VMessages: VMessages,
  VMonthPicker: VMonthPicker,
  VNavigationDrawer: VNavigationDrawer,
  VNoSsr: VNoSsr,
  VNumberInput: VNumberInput,
  VOtpField: VOtpField,
  VOtpGroup: VOtpGroup,
  VOtpInput: VOtpInput,
  VOtpSeparator: VOtpSeparator,
  VOverlay: VOverlay,
  VPagination: VPagination,
  VParallax: VParallax,
  VPicker: VPicker,
  VPickerTitle: VPickerTitle,
  VPie: VPie,
  VPieSegment: VPieSegment,
  VPieTooltip: VPieTooltip,
  VProgress: VProgress,
  VProgressCircular: VProgressCircular,
  VProgressLinear: VProgressLinear,
  VPullToRefresh: VPullToRefresh,
  VRadio: VRadio,
  VRadioGroup: VRadioGroup,
  VRangeSlider: VRangeSlider,
  VRating: VRating,
  VResponsive: VResponsive,
  VRow: VRow,
  VScaleTransition: VScaleTransition,
  VScrollXReverseTransition: VScrollXReverseTransition,
  VScrollXTransition: VScrollXTransition,
  VScrollYReverseTransition: VScrollYReverseTransition,
  VScrollYTransition: VScrollYTransition,
  VSelect: VSelect,
  VSelectionControl: VSelectionControl,
  VSelectionControlGroup: VSelectionControlGroup,
  VSheet: VSheet,
  VSkeletonLoader: VSkeletonLoader,
  VSlideGroup: VSlideGroup,
  VSlideGroupItem: VSlideGroupItem,
  VSlideXReverseTransition: VSlideXReverseTransition,
  VSlideXTransition: VSlideXTransition,
  VSlideYReverseTransition: VSlideYReverseTransition,
  VSlideYTransition: VSlideYTransition,
  VSlider: VSlider,
  VSnackbar: VSnackbar,
  VSnackbarQueue: VSnackbarQueue,
  VSpacer: VSpacer,
  VSparkline: VSparkline,
  VSparklineTooltip: VSparklineTooltip,
  VSpeedDial: VSpeedDial,
  VStepper: VStepper,
  VStepperActions: VStepperActions,
  VStepperHeader: VStepperHeader,
  VStepperItem: VStepperItem,
  VStepperVertical: VStepperVertical,
  VStepperVerticalActions: VStepperVerticalActions,
  VStepperVerticalItem: VStepperVerticalItem,
  VStepperWindow: VStepperWindow,
  VStepperWindowItem: VStepperWindowItem,
  VSvgIcon: VSvgIcon,
  VSwitch: VSwitch,
  VSystemBar: VSystemBar,
  VTab: VTab,
  VTable: VTable,
  VTabs: VTabs,
  VTabsWindow: VTabsWindow,
  VTabsWindowItem: VTabsWindowItem,
  VTextField: VTextField,
  VTextarea: VTextarea,
  VThemeProvider: VThemeProvider,
  VTimePicker: VTimePicker,
  VTimePickerClock: VTimePickerClock,
  VTimePickerControls: VTimePickerControls,
  VTimeline: VTimeline,
  VTimelineItem: VTimelineItem,
  VToolbar: VToolbar,
  VToolbarItems: VToolbarItems,
  VToolbarTitle: VToolbarTitle,
  VTooltip: VTooltip,
  VTreeview: VTreeview,
  VTreeviewGroup: VTreeviewGroup,
  VTreeviewItem: VTreeviewItem,
  VValidation: VValidation,
  VVideo: VVideo,
  VVideoControls: VVideoControls,
  VVideoVolume: VVideoVolume,
  VVirtualScroll: VVirtualScroll,
  VWindow: VWindow,
  VWindowItem: VWindowItem
});

// Types

function mounted$1(el, binding) {
  const modifiers = binding.modifiers || {};
  const value = binding.value;
  const {
    once,
    immediate,
    ...modifierKeys
  } = modifiers;
  const defaultValue = !Object.keys(modifierKeys).length;
  const {
    handler,
    options
  } = typeof value === 'object' ? value : {
    handler: value,
    options: {
      attributes: modifierKeys?.attr ?? defaultValue,
      characterData: modifierKeys?.char ?? defaultValue,
      childList: modifierKeys?.child ?? defaultValue,
      subtree: modifierKeys?.sub ?? defaultValue
    }
  };
  const observer = new MutationObserver((mutations = [], observer) => {
    handler?.(mutations, observer);
    if (once) unmounted$1(el, binding);
  });
  if (immediate) handler?.([], observer);
  el._mutate = Object(el._mutate);
  el._mutate[binding.instance.$.uid] = {
    observer
  };
  observer.observe(el, options);
}
function unmounted$1(el, binding) {
  if (!el._mutate?.[binding.instance.$.uid]) return;
  el._mutate[binding.instance.$.uid].observer.disconnect();
  delete el._mutate[binding.instance.$.uid];
}
const Mutate = {
  mounted: mounted$1,
  unmounted: unmounted$1
};

// Types

function mounted(el, binding) {
  const {
    self = false
  } = binding.modifiers ?? {};
  const value = binding.value;
  const options = typeof value === 'object' && value.options || {
    passive: true
  };
  const handler = typeof value === 'function' || 'handleEvent' in value ? value : value.handler;
  const target = self ? el : binding.arg ? document.querySelector(binding.arg) : window;
  if (!target) return;
  target.addEventListener('scroll', handler, options);
  el._onScroll = Object(el._onScroll);
  el._onScroll[binding.instance.$.uid] = {
    handler,
    options,
    // Don't reference self
    target: self ? undefined : target
  };
}
function unmounted(el, binding) {
  if (!el._onScroll?.[binding.instance.$.uid]) return;
  const {
    handler,
    options,
    target = el
  } = el._onScroll[binding.instance.$.uid];
  target.removeEventListener('scroll', handler, options);
  delete el._onScroll[binding.instance.$.uid];
}
function updated(el, binding) {
  if (binding.value === binding.oldValue) return;
  unmounted(el, binding);
  mounted(el, binding);
}
const Scroll = {
  mounted,
  unmounted,
  updated
};

var directives = /*#__PURE__*/Object.freeze({
  __proto__: null,
  ClickOutside: ClickOutside,
  Intersect: Intersect,
  Mutate: Mutate,
  Resize: Resize,
  Ripple: Ripple,
  Scroll: Scroll,
  Tooltip: Tooltip,
  Touch: Touch
});

// Composables

// Types

const aliases = {
  collapse: 'mdi-chevron-up',
  complete: 'mdi-check',
  cancel: 'mdi-close-circle',
  close: 'mdi-close',
  delete: 'mdi-close-circle',
  // delete (e.g. v-chip close)
  clear: 'mdi-close-circle',
  success: 'mdi-check-circle',
  info: 'mdi-information',
  warning: 'mdi-alert-circle',
  error: 'mdi-close-circle',
  prev: 'mdi-chevron-left',
  next: 'mdi-chevron-right',
  checkboxOn: 'mdi-checkbox-marked',
  checkboxOff: 'mdi-checkbox-blank-outline',
  checkboxIndeterminate: 'mdi-minus-box',
  delimiter: 'mdi-circle',
  // for carousel
  sortAsc: 'mdi-arrow-up',
  sortDesc: 'mdi-arrow-down',
  expand: 'mdi-chevron-down',
  menu: 'mdi-menu',
  subgroup: 'mdi-menu-down',
  dropdown: 'mdi-menu-down',
  radioOn: 'mdi-radiobox-marked',
  radioOff: 'mdi-radiobox-blank',
  edit: 'mdi-pencil',
  ratingEmpty: 'mdi-star-outline',
  ratingFull: 'mdi-star',
  ratingHalf: 'mdi-star-half-full',
  loading: 'mdi-cached',
  first: 'mdi-page-first',
  last: 'mdi-page-last',
  unfold: 'mdi-unfold-more-horizontal',
  file: 'mdi-paperclip',
  plus: 'mdi-plus',
  minus: 'mdi-minus',
  calendar: 'mdi-calendar',
  treeviewCollapse: 'mdi-menu-down',
  treeviewExpand: 'mdi-menu-right',
  tableGroupCollapse: 'mdi-chevron-down',
  tableGroupExpand: 'mdi-chevron-right',
  eyeDropper: 'mdi-eyedropper',
  upload: 'mdi-cloud-upload',
  color: 'mdi-palette',
  command: 'mdi-apple-keyboard-command',
  ctrl: 'mdi-apple-keyboard-control',
  space: 'mdi-keyboard-space',
  shift: 'mdi-apple-keyboard-shift',
  alt: 'mdi-apple-keyboard-option',
  enter: 'mdi-keyboard-return',
  arrowup: 'mdi-arrow-up',
  arrowdown: 'mdi-arrow-down',
  arrowleft: 'mdi-arrow-left',
  arrowright: 'mdi-arrow-right',
  backspace: 'mdi-backspace',
  play: 'mdi-play',
  pause: 'mdi-pause',
  fullscreen: 'mdi-fullscreen',
  fullscreenExit: 'mdi-fullscreen-exit',
  volumeHigh: 'mdi-volume-high',
  volumeMedium: 'mdi-volume-medium',
  volumeLow: 'mdi-volume-low',
  volumeOff: 'mdi-volume-variant-off',
  search: 'mdi-magnify'
};
const mdi = {
  // Not using mergeProps here, functional components merge props by default (?)
  component: props => h(VClassIcon, {
    ...props,
    class: 'mdi'
  })
};

// Composables

// Types

function genDefaults() {
  return {
    svg: {
      component: VSvgIcon
    },
    class: {
      component: VClassIcon
    }
  };
}
function createIcons(options) {
  const sets = genDefaults();
  const defaultSet = options?.defaultSet ?? 'mdi';
  if (defaultSet === 'mdi' && !sets.mdi) {
    sets.mdi = mdi;
  }
  return mergeDeep({
    defaultSet,
    sets,
    aliases: {
      ...aliases,
      /* eslint-disable max-len */
      vuetify: ['M8.2241 14.2009L12 21L22 3H14.4459L8.2241 14.2009Z', ['M7.26303 12.4733L7.00113 12L2 3H12.5261C12.5261 3 12.5261 3 12.5261 3L7.26303 12.4733Z', 0.6]],
      'vuetify-outline': 'svg:M7.26 12.47 12.53 3H2L7.26 12.47ZM14.45 3 8.22 14.2 12 21 22 3H14.45ZM18.6 5 12 16.88 10.51 14.2 15.62 5ZM7.26 8.35 5.4 5H9.13L7.26 8.35Z',
      'vuetify-play': ['m6.376 13.184-4.11-7.192C1.505 4.66 2.467 3 4.003 3h8.532l-.953 1.576-.006.01-.396.677c-.429.732-.214 1.507.194 2.015.404.503 1.092.878 1.869.806a3.72 3.72 0 0 1 1.005.022c.276.053.434.143.523.237.138.146.38.635-.25 2.09-.893 1.63-1.553 1.722-1.847 1.677-.213-.033-.468-.158-.756-.406a4.95 4.95 0 0 1-.8-.927c-.39-.564-1.04-.84-1.66-.846-.625-.006-1.316.27-1.693.921l-.478.826-.911 1.506Z', ['M9.093 11.552c.046-.079.144-.15.32-.148a.53.53 0 0 1 .43.207c.285.414.636.847 1.046 1.2.405.35.914.662 1.516.754 1.334.205 2.502-.698 3.48-2.495l.014-.028.013-.03c.687-1.574.774-2.852-.005-3.675-.37-.391-.861-.586-1.333-.676a5.243 5.243 0 0 0-1.447-.044c-.173.016-.393-.073-.54-.257-.145-.18-.127-.316-.082-.392l.393-.672L14.287 3h5.71c1.536 0 2.499 1.659 1.737 2.992l-7.997 13.996c-.768 1.344-2.706 1.344-3.473 0l-3.037-5.314 1.377-2.278.004-.006.004-.007.481-.831Z', 0.6]]
      /* eslint-enable max-len */
    }
  }, options);
}

// Composables
function createVuetify$1(vuetify = {}) {
  const {
    blueprint,
    ...rest
  } = vuetify;
  const options = mergeDeep(blueprint, rest);
  const {
    aliases = {},
    components = {},
    directives = {}
  } = options;
  const scope = effectScope();
  return scope.run(() => {
    const defaults = createDefaults(options.defaults);
    const display = createDisplay(options.display, options.ssr);
    const theme = createTheme(options.theme);
    const icons = createIcons(options.icons);
    const locale = createLocale(options.locale);
    const date = createDate(options.date, locale);
    const goTo = createGoTo(options.goTo, locale);
    function install(app) {
      for (const key in directives) {
        app.directive(key, directives[key]);
      }
      for (const key in components) {
        app.component(key, components[key]);
      }
      for (const key in aliases) {
        app.component(key, defineComponent({
          ...aliases[key],
          name: key,
          aliasName: aliases[key].name
        }));
      }
      const appScope = effectScope();
      appScope.run(() => {
        theme.install(app);
      });
      app.onUnmount(() => appScope.stop());
      app.provide(DefaultsSymbol, defaults);
      app.provide(DisplaySymbol, display);
      app.provide(ThemeSymbol, theme);
      app.provide(IconSymbol, icons);
      app.provide(LocaleSymbol, locale);
      app.provide(DateOptionsSymbol, date.options);
      app.provide(DateAdapterSymbol, date.instance);
      app.provide(GoToSymbol, goTo);
      if (IN_BROWSER && options.ssr) {
        if (app.$nuxt) {
          app.$nuxt.hook('app:suspense:resolve', () => {
            display.update();
          });
        } else {
          const {
            mount
          } = app;
          app.mount = (...args) => {
            const vm = mount(...args);
            nextTick(() => display.update());
            app.mount = mount;
            return vm;
          };
        }
      }
      if (typeof __VUE_OPTIONS_API__ !== 'boolean' || __VUE_OPTIONS_API__) {
        app.mixin({
          computed: {
            $vuetify() {
              return reactive({
                defaults: inject.call(this, DefaultsSymbol),
                display: inject.call(this, DisplaySymbol),
                theme: inject.call(this, ThemeSymbol),
                icons: inject.call(this, IconSymbol),
                locale: inject.call(this, LocaleSymbol),
                date: inject.call(this, DateAdapterSymbol)
              });
            }
          }
        });
      }
    }
    function unmount() {
      scope.stop();
    }
    return {
      install,
      unmount,
      defaults,
      display,
      theme,
      icons,
      locale,
      date,
      goTo
    };
  });
}
const version$1 = "4.1.11";
createVuetify$1.version = version$1;

// Vue's inject() can only be used in setup
function inject(key) {
  const vm = this.$;
  const provides = vm.parent?.provides ?? vm.vnode.appContext?.provides;
  if (provides && key in provides) {
    return provides[key];
  }
}

// Icons

// Types

const md1 = {
  defaults: {
    global: {
      rounded: 'sm'
    },
    VAvatar: {
      rounded: 'circle'
    },
    VAutocomplete: {
      variant: 'underlined'
    },
    VBanner: {
      color: 'primary'
    },
    VBtn: {
      class: 'text-uppercase',
      color: 'primary',
      rounded: 0
    },
    VCheckbox: {
      color: 'secondary',
      indentDetails: false
    },
    VCombobox: {
      variant: 'underlined'
    },
    VDatePicker: {
      color: 'primary',
      controlHeight: 44,
      elevation: 1,
      rounded: 0,
      controlVariant: 'modal',
      VBtn: {
        color: 'high-emphasis',
        rounded: 'circle'
      }
    },
    VSelect: {
      variant: 'underlined'
    },
    VSlider: {
      color: 'primary',
      indentDetails: false
    },
    VSwitch: {
      indentDetails: false
    },
    VRadioGroup: {
      indentDetails: false
    },
    VRangeSlider: {
      indentDetails: false
    },
    VTabs: {
      color: 'primary'
    },
    VTextarea: {
      variant: 'underlined'
    },
    VTextField: {
      variant: 'underlined'
    },
    VToolbar: {
      VBtn: {
        color: null
      }
    }
  },
  icons: {
    defaultSet: 'mdi',
    sets: {
      mdi
    }
  },
  theme: {
    themes: {
      light: {
        colors: {
          primary: '#3F51B5',
          'primary-darken-1': '#303F9F',
          'primary-lighten-1': '#C5CAE9',
          secondary: '#FF4081',
          'secondary-darken-1': '#F50057',
          'secondary-lighten-1': '#FF80AB',
          accent: '#009688'
        }
      }
    }
  }
};

// Icons

// Types

const md2 = {
  defaults: {
    VAvatar: {
      rounded: 'circle'
    },
    VAutocomplete: {
      variant: 'filled'
    },
    VBanner: {
      color: 'primary'
    },
    VBtn: {
      class: 'text-uppercase',
      color: 'primary'
    },
    VCheckbox: {
      color: 'secondary',
      indentDetails: true
    },
    VCombobox: {
      variant: 'filled'
    },
    VDatePicker: {
      color: 'primary',
      controlHeight: 56,
      elevation: 2,
      rounded: 'md',
      controlVariant: 'modal',
      VBtn: {
        color: 'high-emphasis',
        rounded: 'circle'
      }
    },
    VRadioGroup: {
      indentDetails: true
    },
    VSelect: {
      variant: 'filled'
    },
    VSlider: {
      color: 'primary',
      indentDetails: true
    },
    VRangeSlider: {
      indentDetails: true
    },
    VSwitch: {
      indentDetails: true
    },
    VTabs: {
      color: 'primary'
    },
    VTextarea: {
      variant: 'filled'
    },
    VTextField: {
      variant: 'filled'
    },
    VToolbar: {
      VBtn: {
        color: null
      }
    }
  },
  icons: {
    defaultSet: 'mdi',
    sets: {
      mdi
    }
  },
  theme: {
    themes: {
      light: {
        colors: {
          primary: '#6200EE',
          'primary-darken-1': '#3700B3',
          secondary: '#03DAC6',
          'secondary-darken-1': '#018786',
          error: '#B00020'
        }
      }
    }
  }
};

// Icons

// Types

const md3 = {
  defaults: {
    VAppBar: {
      flat: true
    },
    VAutocomplete: {
      variant: 'outlined'
    },
    VBanner: {
      color: 'primary'
    },
    VBottomSheet: {
      contentClass: 'rounded-t-xl overflow-hidden'
    },
    VBtn: {
      color: 'primary',
      rounded: 'xl'
    },
    VBtnGroup: {
      rounded: 'xl',
      VBtn: {
        rounded: null
      }
    },
    VCard: {
      rounded: 'lg'
    },
    VCheckbox: {
      color: 'secondary',
      inset: true,
      indentDetails: true
    },
    VChip: {
      rounded: 'sm'
    },
    VCombobox: {
      variant: 'outlined'
    },
    VDateInput: {
      variant: 'outlined'
    },
    VDatePicker: {
      controlHeight: 48,
      color: 'primary',
      divided: true,
      headerColor: '',
      elevation: 1,
      rounded: 'xl',
      VBtn: {
        color: 'high-emphasis',
        rounded: 'circle'
      }
    },
    VFileInput: {
      variant: 'outlined'
    },
    VList: {
      prependGap: 16
    },
    VNavigationDrawer: {
      // VList: {
      //   nav: true,
      //   VListItem: {
      //     rounded: 'xl',
      //   },
      // },
    },
    VNumberInput: {
      variant: 'outlined',
      VBtn: {
        color: undefined,
        rounded: undefined
      }
    },
    VRadioGroup: {
      indentDetails: true
    },
    VSelect: {
      variant: 'outlined'
    },
    VSlider: {
      color: 'primary',
      indentDetails: true
    },
    VRangeSlider: {
      indentDetails: true
    },
    VSwitch: {
      indentDetails: true
    },
    VTabs: {
      color: 'primary'
    },
    VTextarea: {
      variant: 'outlined'
    },
    VTextField: {
      variant: 'outlined'
    },
    VToolbar: {
      VBtn: {
        color: null
      }
    }
  },
  icons: {
    defaultSet: 'mdi',
    sets: {
      mdi
    }
  },
  theme: {
    themes: {
      light: {
        colors: {
          primary: '#6750a4',
          secondary: '#b4b0bb',
          tertiary: '#7d5260',
          error: '#b3261e',
          surface: '#fffbfe'
        }
      }
    }
  }
};

var index = /*#__PURE__*/Object.freeze({
  __proto__: null,
  md1: md1,
  md2: md2,
  md3: md3
});

/* eslint-disable local-rules/sort-imports */

const version = "4.1.11";

/* eslint-disable local-rules/sort-imports */

const createVuetify = (options = {}) => {
  return createVuetify$1({
    components,
    directives,
    ...options
  });
};

export { index as blueprints, components, createVuetify, directives, useDate, useDefaults, useDisplay, useGoTo, useHotkey, useLayout, useLocale, useMask, useRtl, useTheme, version };
//# sourceMappingURL=vuetify-labs.esm.js.map