@vuetify/nightly 3.8.0-master.2025-04-06 → 3.8.1-dev.2025-04-12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vuetify.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.8.0-master.2025-04-06
2
+ * Vuetify v3.8.1-dev.2025-04-12
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
@@ -14,6 +14,7 @@
14
14
  const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
15
15
  const SUPPORTS_TOUCH = IN_BROWSER && ('ontouchstart' in window || window.navigator.maxTouchPoints > 0);
16
16
  const SUPPORTS_EYE_DROPPER = IN_BROWSER && 'EyeDropper' in window;
17
+ const SUPPORTS_MATCH_MEDIA = IN_BROWSER && 'matchMedia' in window && typeof window.matchMedia === 'function';
17
18
 
18
19
  function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
19
20
  function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
@@ -2758,6 +2759,7 @@
2758
2759
  function genDefaults$1() {
2759
2760
  return {
2760
2761
  defaultTheme: 'light',
2762
+ prefix: 'v-',
2761
2763
  variations: {
2762
2764
  colors: [],
2763
2765
  lighten: 0,
@@ -2839,7 +2841,10 @@
2839
2841
  }
2840
2842
  }
2841
2843
  },
2842
- stylesheetId: 'vuetify-theme-stylesheet'
2844
+ stylesheetId: 'vuetify-theme-stylesheet',
2845
+ scoped: false,
2846
+ unimportant: false,
2847
+ utilities: true
2843
2848
  };
2844
2849
  }
2845
2850
  function parseThemeOptions() {
@@ -2859,93 +2864,175 @@
2859
2864
  themes
2860
2865
  });
2861
2866
  }
2867
+ function createCssClass(lines, selector, content, scope) {
2868
+ lines.push(`${getScopedSelector(selector, scope)} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
2869
+ }
2870
+ function genCssVariables(theme, prefix) {
2871
+ const lightOverlay = theme.dark ? 2 : 1;
2872
+ const darkOverlay = theme.dark ? 1 : 2;
2873
+ const variables = [];
2874
+ for (const [key, value] of Object.entries(theme.colors)) {
2875
+ const rgb = parseColor(value);
2876
+ variables.push(`--${prefix}theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2877
+ if (!key.startsWith('on-')) {
2878
+ variables.push(`--${prefix}theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2879
+ }
2880
+ }
2881
+ for (const [key, value] of Object.entries(theme.variables)) {
2882
+ const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
2883
+ const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
2884
+ variables.push(`--${prefix}${key}: ${rgb ?? value}`);
2885
+ }
2886
+ return variables;
2887
+ }
2888
+ function genVariation(name, color, variations) {
2889
+ const object = {};
2890
+ if (variations) {
2891
+ for (const variation of ['lighten', 'darken']) {
2892
+ const fn = variation === 'lighten' ? lighten : darken;
2893
+ for (const amount of createRange(variations[variation], 1)) {
2894
+ object[`${name}-${variation}-${amount}`] = RGBtoHex(fn(parseColor(color), amount));
2895
+ }
2896
+ }
2897
+ }
2898
+ return object;
2899
+ }
2900
+ function genVariations(colors, variations) {
2901
+ if (!variations) return {};
2902
+ let variationColors = {};
2903
+ for (const name of variations.colors) {
2904
+ const color = colors[name];
2905
+ if (!color) continue;
2906
+ variationColors = {
2907
+ ...variationColors,
2908
+ ...genVariation(name, color, variations)
2909
+ };
2910
+ }
2911
+ return variationColors;
2912
+ }
2913
+ function genOnColors(colors) {
2914
+ const onColors = {};
2915
+ for (const color of Object.keys(colors)) {
2916
+ if (color.startsWith('on-') || colors[`on-${color}`]) continue;
2917
+ const onColor = `on-${color}`;
2918
+ const colorVal = parseColor(colors[color]);
2919
+ onColors[onColor] = getForeground(colorVal);
2920
+ }
2921
+ return onColors;
2922
+ }
2923
+ function getScopedSelector(selector, scope) {
2924
+ if (!scope) return selector;
2925
+ const scopeSelector = `:where(${scope})`;
2926
+ return selector === ':root' ? scopeSelector : `${scopeSelector} ${selector}`;
2927
+ }
2928
+ function upsertStyles(id, cspNonce, styles) {
2929
+ const styleEl = getOrCreateStyleElement(id, cspNonce);
2930
+ if (!styleEl) return;
2931
+ styleEl.innerHTML = styles;
2932
+ }
2933
+ function getOrCreateStyleElement(id, cspNonce) {
2934
+ if (!IN_BROWSER) return null;
2935
+ let style = document.getElementById(id);
2936
+ if (!style) {
2937
+ style = document.createElement('style');
2938
+ style.id = id;
2939
+ style.type = 'text/css';
2940
+ if (cspNonce) style.setAttribute('nonce', cspNonce);
2941
+ document.head.appendChild(style);
2942
+ }
2943
+ return style;
2944
+ }
2862
2945
 
2863
2946
  // Composables
2864
2947
  function createTheme(options) {
2865
2948
  const parsedOptions = parseThemeOptions(options);
2866
- const name = vue.ref(parsedOptions.defaultTheme);
2949
+ const _name = vue.shallowRef(parsedOptions.defaultTheme);
2867
2950
  const themes = vue.ref(parsedOptions.themes);
2951
+ const systemName = vue.shallowRef('light');
2952
+ const name = vue.computed({
2953
+ get() {
2954
+ return _name.value === 'system' ? systemName.value : _name.value;
2955
+ },
2956
+ set(val) {
2957
+ _name.value = val;
2958
+ }
2959
+ });
2868
2960
  const computedThemes = vue.computed(() => {
2869
2961
  const acc = {};
2870
2962
  for (const [name, original] of Object.entries(themes.value)) {
2871
- const theme = acc[name] = {
2963
+ const colors = {
2964
+ ...original.colors,
2965
+ ...genVariations(original.colors, parsedOptions.variations)
2966
+ };
2967
+ acc[name] = {
2872
2968
  ...original,
2873
2969
  colors: {
2874
- ...original.colors
2970
+ ...colors,
2971
+ ...genOnColors(colors)
2875
2972
  }
2876
2973
  };
2877
- if (parsedOptions.variations) {
2878
- for (const name of parsedOptions.variations.colors) {
2879
- const color = theme.colors[name];
2880
- if (!color) continue;
2881
- for (const variation of ['lighten', 'darken']) {
2882
- const fn = variation === 'lighten' ? lighten : darken;
2883
- for (const amount of createRange(parsedOptions.variations[variation], 1)) {
2884
- theme.colors[`${name}-${variation}-${amount}`] = RGBtoHex(fn(parseColor(color), amount));
2885
- }
2886
- }
2887
- }
2888
- }
2889
- for (const color of Object.keys(theme.colors)) {
2890
- if (/^on-[a-z]/.test(color) || theme.colors[`on-${color}`]) continue;
2891
- const onColor = `on-${color}`;
2892
- const colorVal = parseColor(theme.colors[color]);
2893
- theme.colors[onColor] = getForeground(colorVal);
2894
- }
2895
2974
  }
2896
2975
  return acc;
2897
2976
  });
2898
2977
  const current = vue.computed(() => computedThemes.value[name.value]);
2899
- function createCssClass(lines, selector, content) {
2900
- lines.push(`${getScopedSelector(selector)} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
2901
- }
2902
- function getScopedSelector(selector) {
2903
- if (!parsedOptions.scope) {
2904
- return selector;
2905
- }
2906
- const scopeSelector = `:where(${parsedOptions.scope})`;
2907
- if (selector === ':root') {
2908
- return scopeSelector;
2909
- }
2910
- return `${scopeSelector} ${selector}`;
2911
- }
2912
2978
  const styles = vue.computed(() => {
2913
2979
  const lines = [];
2980
+ const important = parsedOptions.unimportant ? '' : ' !important';
2981
+ const scoped = parsedOptions.scoped ? parsedOptions.prefix : '';
2914
2982
  if (current.value?.dark) {
2915
- createCssClass(lines, ':root', ['color-scheme: dark']);
2983
+ createCssClass(lines, ':root', ['color-scheme: dark'], parsedOptions.scope);
2916
2984
  }
2917
- createCssClass(lines, ':root', genCssVariables(current.value));
2985
+ createCssClass(lines, ':root', genCssVariables(current.value, parsedOptions.prefix), parsedOptions.scope);
2918
2986
  for (const [themeName, theme] of Object.entries(computedThemes.value)) {
2919
- createCssClass(lines, `.v-theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme)]);
2920
- }
2921
- const bgLines = [];
2922
- const fgLines = [];
2923
- const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
2924
- for (const key of colors) {
2925
- if (/^on-[a-z]/.test(key)) {
2926
- createCssClass(fgLines, `.${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
2927
- } else {
2928
- createCssClass(bgLines, `.bg-${key}`, [`--v-theme-overlay-multiplier: var(--v-theme-${key}-overlay-multiplier)`, `background-color: rgb(var(--v-theme-${key})) !important`, `color: rgb(var(--v-theme-on-${key})) !important`]);
2929
- createCssClass(fgLines, `.text-${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
2930
- createCssClass(fgLines, `.border-${key}`, [`--v-border-color: var(--v-theme-${key})`]);
2987
+ createCssClass(lines, `.${parsedOptions.prefix}theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme, parsedOptions.prefix)], parsedOptions.scope);
2988
+ }
2989
+ if (parsedOptions.utilities) {
2990
+ const bgLines = [];
2991
+ const fgLines = [];
2992
+ const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
2993
+ for (const key of colors) {
2994
+ if (key.startsWith('on-')) {
2995
+ createCssClass(fgLines, `.${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
2996
+ } else {
2997
+ 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}))${important}`, `color: rgb(var(--${parsedOptions.prefix}theme-on-${key}))${important}`], parsedOptions.scope);
2998
+ createCssClass(fgLines, `.${scoped}text-${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
2999
+ createCssClass(fgLines, `.${scoped}border-${key}`, [`--${parsedOptions.prefix}border-color: var(--${parsedOptions.prefix}theme-${key})`], parsedOptions.scope);
3000
+ }
2931
3001
  }
3002
+ lines.push(...bgLines, ...fgLines);
2932
3003
  }
2933
- lines.push(...bgLines, ...fgLines);
2934
3004
  return lines.map((str, i) => i === 0 ? str : ` ${str}`).join('');
2935
3005
  });
2936
- function getHead() {
2937
- return {
2938
- style: [{
2939
- textContent: styles.value,
2940
- id: parsedOptions.stylesheetId,
2941
- nonce: parsedOptions.cspNonce || false
2942
- }]
2943
- };
3006
+ const themeClasses = vue.computed(() => parsedOptions.isDisabled ? undefined : `${parsedOptions.prefix}theme--${name.value}`);
3007
+ const themeNames = vue.computed(() => Object.keys(computedThemes.value));
3008
+ if (SUPPORTS_MATCH_MEDIA) {
3009
+ const media = window.matchMedia('(prefers-color-scheme: dark)');
3010
+ function updateSystemName() {
3011
+ systemName.value = media.matches ? 'dark' : 'light';
3012
+ }
3013
+ updateSystemName();
3014
+ media.addEventListener('change', updateSystemName, {
3015
+ passive: true
3016
+ });
3017
+ if (vue.getCurrentScope()) {
3018
+ vue.onScopeDispose(() => {
3019
+ media.removeEventListener('change', updateSystemName);
3020
+ });
3021
+ }
2944
3022
  }
2945
3023
  function install(app) {
2946
3024
  if (parsedOptions.isDisabled) return;
2947
3025
  const head = app._context.provides.usehead;
2948
3026
  if (head) {
3027
+ function getHead() {
3028
+ return {
3029
+ style: [{
3030
+ textContent: styles.value,
3031
+ id: parsedOptions.stylesheetId,
3032
+ nonce: parsedOptions.cspNonce || false
3033
+ }]
3034
+ };
3035
+ }
2949
3036
  if (head.push) {
2950
3037
  const entry = head.push(getHead);
2951
3038
  if (IN_BROWSER) {
@@ -2962,7 +3049,6 @@
2962
3049
  }
2963
3050
  }
2964
3051
  } else {
2965
- let styleEl = IN_BROWSER ? document.getElementById(parsedOptions.stylesheetId) : null;
2966
3052
  if (IN_BROWSER) {
2967
3053
  vue.watch(styles, updateStyles, {
2968
3054
  immediate: true
@@ -2971,30 +3057,55 @@
2971
3057
  updateStyles();
2972
3058
  }
2973
3059
  function updateStyles() {
2974
- if (typeof document !== 'undefined' && !styleEl) {
2975
- const el = document.createElement('style');
2976
- el.type = 'text/css';
2977
- el.id = parsedOptions.stylesheetId;
2978
- if (parsedOptions.cspNonce) el.setAttribute('nonce', parsedOptions.cspNonce);
2979
- styleEl = el;
2980
- document.head.appendChild(styleEl);
2981
- }
2982
- if (styleEl) styleEl.innerHTML = styles.value;
3060
+ upsertStyles(parsedOptions.stylesheetId, parsedOptions.cspNonce, styles.value);
2983
3061
  }
2984
3062
  }
2985
3063
  }
2986
- const themeClasses = vue.computed(() => parsedOptions.isDisabled ? undefined : `v-theme--${name.value}`);
3064
+ function change(themeName) {
3065
+ if (!themeNames.value.includes(themeName)) {
3066
+ consoleWarn(`Theme "${themeName}" not found on the Vuetify theme instance`);
3067
+ return;
3068
+ }
3069
+ name.value = themeName;
3070
+ }
3071
+ function cycle() {
3072
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : themeNames.value;
3073
+ const currentIndex = themeArray.indexOf(name.value);
3074
+ const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % themeArray.length;
3075
+ change(themeArray[nextIndex]);
3076
+ }
3077
+ function toggle() {
3078
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['light', 'dark'];
3079
+ cycle(themeArray);
3080
+ }
3081
+ const globalName = new Proxy(name, {
3082
+ get(target, prop) {
3083
+ return target[prop];
3084
+ },
3085
+ set(target, prop, val) {
3086
+ if (prop === 'value') {
3087
+ deprecate(`theme.global.name.value = ${val}`, `theme.change('${val}')`);
3088
+ }
3089
+ // @ts-expect-error
3090
+ target[prop] = val;
3091
+ return true;
3092
+ }
3093
+ });
2987
3094
  return {
2988
3095
  install,
3096
+ change,
3097
+ cycle,
3098
+ toggle,
2989
3099
  isDisabled: parsedOptions.isDisabled,
2990
3100
  name,
2991
3101
  themes,
2992
3102
  current,
2993
3103
  computedThemes,
3104
+ prefix: parsedOptions.prefix,
2994
3105
  themeClasses,
2995
3106
  styles,
2996
3107
  global: {
2997
- name,
3108
+ name: globalName,
2998
3109
  current
2999
3110
  }
3000
3111
  };
@@ -3003,11 +3114,9 @@
3003
3114
  getCurrentInstance('provideTheme');
3004
3115
  const theme = vue.inject(ThemeSymbol, null);
3005
3116
  if (!theme) throw new Error('Could not find Vuetify theme injection');
3006
- const name = vue.computed(() => {
3007
- return props.theme ?? theme.name.value;
3008
- });
3117
+ const name = vue.computed(() => props.theme ?? theme.name.value);
3009
3118
  const current = vue.computed(() => theme.themes.value[name.value]);
3010
- const themeClasses = vue.computed(() => theme.isDisabled ? undefined : `v-theme--${name.value}`);
3119
+ const themeClasses = vue.computed(() => theme.isDisabled ? undefined : `${theme.prefix}theme--${name.value}`);
3011
3120
  const newTheme = {
3012
3121
  ...theme,
3013
3122
  name,
@@ -3023,24 +3132,6 @@
3023
3132
  if (!theme) throw new Error('Could not find Vuetify theme injection');
3024
3133
  return theme;
3025
3134
  }
3026
- function genCssVariables(theme) {
3027
- const lightOverlay = theme.dark ? 2 : 1;
3028
- const darkOverlay = theme.dark ? 1 : 2;
3029
- const variables = [];
3030
- for (const [key, value] of Object.entries(theme.colors)) {
3031
- const rgb = parseColor(value);
3032
- variables.push(`--v-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
3033
- if (!key.startsWith('on-')) {
3034
- variables.push(`--v-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
3035
- }
3036
- }
3037
- for (const [key, value] of Object.entries(theme.variables)) {
3038
- const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
3039
- const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
3040
- variables.push(`--v-${key}: ${rgb ?? value}`);
3041
- }
3042
- return variables;
3043
- }
3044
3135
 
3045
3136
  const makeVAppProps = propsFactory({
3046
3137
  ...makeComponentProps(),
@@ -12550,7 +12641,12 @@
12550
12641
  }
12551
12642
  function calculateOffset(index) {
12552
12643
  index = clamp(index, 0, items.value.length - 1);
12553
- return offsets[index] || 0;
12644
+ const whole = Math.floor(index);
12645
+ const fraction = index % 1;
12646
+ const next = whole + 1;
12647
+ const wholeOffset = offsets[whole] || 0;
12648
+ const nextOffset = offsets[next] || wholeOffset;
12649
+ return wholeOffset + (nextOffset - wholeOffset) * fraction;
12554
12650
  }
12555
12651
  function calculateIndex(scrollTop) {
12556
12652
  return binaryClosest(offsets, scrollTop);
@@ -29218,7 +29314,7 @@
29218
29314
  };
29219
29315
  });
29220
29316
  }
29221
- const version$1 = "3.8.0-master.2025-04-06";
29317
+ const version$1 = "3.8.1-dev.2025-04-12";
29222
29318
  createVuetify$1.version = version$1;
29223
29319
 
29224
29320
  // Vue's inject() can only be used in setup
@@ -29243,7 +29339,7 @@
29243
29339
  ...options
29244
29340
  });
29245
29341
  };
29246
- const version = "3.8.0-master.2025-04-06";
29342
+ const version = "3.8.1-dev.2025-04-12";
29247
29343
  createVuetify.version = version;
29248
29344
 
29249
29345
  exports.blueprints = index;