@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.
@@ -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
  */
@@ -85,6 +85,7 @@
85
85
  const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
86
86
  const SUPPORTS_TOUCH = IN_BROWSER && ('ontouchstart' in window || window.navigator.maxTouchPoints > 0);
87
87
  const SUPPORTS_EYE_DROPPER = IN_BROWSER && 'EyeDropper' in window;
88
+ const SUPPORTS_MATCH_MEDIA = IN_BROWSER && 'matchMedia' in window && typeof window.matchMedia === 'function';
88
89
 
89
90
  function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
90
91
  function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
@@ -2285,6 +2286,7 @@
2285
2286
  function genDefaults$2() {
2286
2287
  return {
2287
2288
  defaultTheme: 'light',
2289
+ prefix: 'v-',
2288
2290
  variations: {
2289
2291
  colors: [],
2290
2292
  lighten: 0,
@@ -2366,7 +2368,10 @@
2366
2368
  }
2367
2369
  }
2368
2370
  },
2369
- stylesheetId: 'vuetify-theme-stylesheet'
2371
+ stylesheetId: 'vuetify-theme-stylesheet',
2372
+ scoped: false,
2373
+ unimportant: false,
2374
+ utilities: true
2370
2375
  };
2371
2376
  }
2372
2377
  function parseThemeOptions() {
@@ -2386,93 +2391,175 @@
2386
2391
  themes
2387
2392
  });
2388
2393
  }
2394
+ function createCssClass(lines, selector, content, scope) {
2395
+ lines.push(`${getScopedSelector(selector, scope)} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
2396
+ }
2397
+ function genCssVariables(theme, prefix) {
2398
+ const lightOverlay = theme.dark ? 2 : 1;
2399
+ const darkOverlay = theme.dark ? 1 : 2;
2400
+ const variables = [];
2401
+ for (const [key, value] of Object.entries(theme.colors)) {
2402
+ const rgb = parseColor(value);
2403
+ variables.push(`--${prefix}theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2404
+ if (!key.startsWith('on-')) {
2405
+ variables.push(`--${prefix}theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2406
+ }
2407
+ }
2408
+ for (const [key, value] of Object.entries(theme.variables)) {
2409
+ const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
2410
+ const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
2411
+ variables.push(`--${prefix}${key}: ${rgb ?? value}`);
2412
+ }
2413
+ return variables;
2414
+ }
2415
+ function genVariation(name, color, variations) {
2416
+ const object = {};
2417
+ if (variations) {
2418
+ for (const variation of ['lighten', 'darken']) {
2419
+ const fn = variation === 'lighten' ? lighten : darken;
2420
+ for (const amount of createRange(variations[variation], 1)) {
2421
+ object[`${name}-${variation}-${amount}`] = RGBtoHex(fn(parseColor(color), amount));
2422
+ }
2423
+ }
2424
+ }
2425
+ return object;
2426
+ }
2427
+ function genVariations(colors, variations) {
2428
+ if (!variations) return {};
2429
+ let variationColors = {};
2430
+ for (const name of variations.colors) {
2431
+ const color = colors[name];
2432
+ if (!color) continue;
2433
+ variationColors = {
2434
+ ...variationColors,
2435
+ ...genVariation(name, color, variations)
2436
+ };
2437
+ }
2438
+ return variationColors;
2439
+ }
2440
+ function genOnColors(colors) {
2441
+ const onColors = {};
2442
+ for (const color of Object.keys(colors)) {
2443
+ if (color.startsWith('on-') || colors[`on-${color}`]) continue;
2444
+ const onColor = `on-${color}`;
2445
+ const colorVal = parseColor(colors[color]);
2446
+ onColors[onColor] = getForeground(colorVal);
2447
+ }
2448
+ return onColors;
2449
+ }
2450
+ function getScopedSelector(selector, scope) {
2451
+ if (!scope) return selector;
2452
+ const scopeSelector = `:where(${scope})`;
2453
+ return selector === ':root' ? scopeSelector : `${scopeSelector} ${selector}`;
2454
+ }
2455
+ function upsertStyles(id, cspNonce, styles) {
2456
+ const styleEl = getOrCreateStyleElement(id, cspNonce);
2457
+ if (!styleEl) return;
2458
+ styleEl.innerHTML = styles;
2459
+ }
2460
+ function getOrCreateStyleElement(id, cspNonce) {
2461
+ if (!IN_BROWSER) return null;
2462
+ let style = document.getElementById(id);
2463
+ if (!style) {
2464
+ style = document.createElement('style');
2465
+ style.id = id;
2466
+ style.type = 'text/css';
2467
+ if (cspNonce) style.setAttribute('nonce', cspNonce);
2468
+ document.head.appendChild(style);
2469
+ }
2470
+ return style;
2471
+ }
2389
2472
 
2390
2473
  // Composables
2391
2474
  function createTheme(options) {
2392
2475
  const parsedOptions = parseThemeOptions(options);
2393
- const name = vue.ref(parsedOptions.defaultTheme);
2476
+ const _name = vue.shallowRef(parsedOptions.defaultTheme);
2394
2477
  const themes = vue.ref(parsedOptions.themes);
2478
+ const systemName = vue.shallowRef('light');
2479
+ const name = vue.computed({
2480
+ get() {
2481
+ return _name.value === 'system' ? systemName.value : _name.value;
2482
+ },
2483
+ set(val) {
2484
+ _name.value = val;
2485
+ }
2486
+ });
2395
2487
  const computedThemes = vue.computed(() => {
2396
2488
  const acc = {};
2397
2489
  for (const [name, original] of Object.entries(themes.value)) {
2398
- const theme = acc[name] = {
2490
+ const colors = {
2491
+ ...original.colors,
2492
+ ...genVariations(original.colors, parsedOptions.variations)
2493
+ };
2494
+ acc[name] = {
2399
2495
  ...original,
2400
2496
  colors: {
2401
- ...original.colors
2497
+ ...colors,
2498
+ ...genOnColors(colors)
2402
2499
  }
2403
2500
  };
2404
- if (parsedOptions.variations) {
2405
- for (const name of parsedOptions.variations.colors) {
2406
- const color = theme.colors[name];
2407
- if (!color) continue;
2408
- for (const variation of ['lighten', 'darken']) {
2409
- const fn = variation === 'lighten' ? lighten : darken;
2410
- for (const amount of createRange(parsedOptions.variations[variation], 1)) {
2411
- theme.colors[`${name}-${variation}-${amount}`] = RGBtoHex(fn(parseColor(color), amount));
2412
- }
2413
- }
2414
- }
2415
- }
2416
- for (const color of Object.keys(theme.colors)) {
2417
- if (/^on-[a-z]/.test(color) || theme.colors[`on-${color}`]) continue;
2418
- const onColor = `on-${color}`;
2419
- const colorVal = parseColor(theme.colors[color]);
2420
- theme.colors[onColor] = getForeground(colorVal);
2421
- }
2422
2501
  }
2423
2502
  return acc;
2424
2503
  });
2425
2504
  const current = vue.computed(() => computedThemes.value[name.value]);
2426
- function createCssClass(lines, selector, content) {
2427
- lines.push(`${getScopedSelector(selector)} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
2428
- }
2429
- function getScopedSelector(selector) {
2430
- if (!parsedOptions.scope) {
2431
- return selector;
2432
- }
2433
- const scopeSelector = `:where(${parsedOptions.scope})`;
2434
- if (selector === ':root') {
2435
- return scopeSelector;
2436
- }
2437
- return `${scopeSelector} ${selector}`;
2438
- }
2439
2505
  const styles = vue.computed(() => {
2440
2506
  const lines = [];
2507
+ const important = parsedOptions.unimportant ? '' : ' !important';
2508
+ const scoped = parsedOptions.scoped ? parsedOptions.prefix : '';
2441
2509
  if (current.value?.dark) {
2442
- createCssClass(lines, ':root', ['color-scheme: dark']);
2510
+ createCssClass(lines, ':root', ['color-scheme: dark'], parsedOptions.scope);
2443
2511
  }
2444
- createCssClass(lines, ':root', genCssVariables(current.value));
2512
+ createCssClass(lines, ':root', genCssVariables(current.value, parsedOptions.prefix), parsedOptions.scope);
2445
2513
  for (const [themeName, theme] of Object.entries(computedThemes.value)) {
2446
- createCssClass(lines, `.v-theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme)]);
2447
- }
2448
- const bgLines = [];
2449
- const fgLines = [];
2450
- const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
2451
- for (const key of colors) {
2452
- if (/^on-[a-z]/.test(key)) {
2453
- createCssClass(fgLines, `.${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
2454
- } else {
2455
- 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`]);
2456
- createCssClass(fgLines, `.text-${key}`, [`color: rgb(var(--v-theme-${key})) !important`]);
2457
- createCssClass(fgLines, `.border-${key}`, [`--v-border-color: var(--v-theme-${key})`]);
2514
+ createCssClass(lines, `.${parsedOptions.prefix}theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme, parsedOptions.prefix)], parsedOptions.scope);
2515
+ }
2516
+ if (parsedOptions.utilities) {
2517
+ const bgLines = [];
2518
+ const fgLines = [];
2519
+ const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
2520
+ for (const key of colors) {
2521
+ if (key.startsWith('on-')) {
2522
+ createCssClass(fgLines, `.${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
2523
+ } else {
2524
+ 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);
2525
+ createCssClass(fgLines, `.${scoped}text-${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
2526
+ createCssClass(fgLines, `.${scoped}border-${key}`, [`--${parsedOptions.prefix}border-color: var(--${parsedOptions.prefix}theme-${key})`], parsedOptions.scope);
2527
+ }
2458
2528
  }
2529
+ lines.push(...bgLines, ...fgLines);
2459
2530
  }
2460
- lines.push(...bgLines, ...fgLines);
2461
2531
  return lines.map((str, i) => i === 0 ? str : ` ${str}`).join('');
2462
2532
  });
2463
- function getHead() {
2464
- return {
2465
- style: [{
2466
- textContent: styles.value,
2467
- id: parsedOptions.stylesheetId,
2468
- nonce: parsedOptions.cspNonce || false
2469
- }]
2470
- };
2533
+ const themeClasses = vue.computed(() => parsedOptions.isDisabled ? undefined : `${parsedOptions.prefix}theme--${name.value}`);
2534
+ const themeNames = vue.computed(() => Object.keys(computedThemes.value));
2535
+ if (SUPPORTS_MATCH_MEDIA) {
2536
+ const media = window.matchMedia('(prefers-color-scheme: dark)');
2537
+ function updateSystemName() {
2538
+ systemName.value = media.matches ? 'dark' : 'light';
2539
+ }
2540
+ updateSystemName();
2541
+ media.addEventListener('change', updateSystemName, {
2542
+ passive: true
2543
+ });
2544
+ if (vue.getCurrentScope()) {
2545
+ vue.onScopeDispose(() => {
2546
+ media.removeEventListener('change', updateSystemName);
2547
+ });
2548
+ }
2471
2549
  }
2472
2550
  function install(app) {
2473
2551
  if (parsedOptions.isDisabled) return;
2474
2552
  const head = app._context.provides.usehead;
2475
2553
  if (head) {
2554
+ function getHead() {
2555
+ return {
2556
+ style: [{
2557
+ textContent: styles.value,
2558
+ id: parsedOptions.stylesheetId,
2559
+ nonce: parsedOptions.cspNonce || false
2560
+ }]
2561
+ };
2562
+ }
2476
2563
  if (head.push) {
2477
2564
  const entry = head.push(getHead);
2478
2565
  if (IN_BROWSER) {
@@ -2489,7 +2576,6 @@
2489
2576
  }
2490
2577
  }
2491
2578
  } else {
2492
- let styleEl = IN_BROWSER ? document.getElementById(parsedOptions.stylesheetId) : null;
2493
2579
  if (IN_BROWSER) {
2494
2580
  vue.watch(styles, updateStyles, {
2495
2581
  immediate: true
@@ -2498,30 +2584,55 @@
2498
2584
  updateStyles();
2499
2585
  }
2500
2586
  function updateStyles() {
2501
- if (typeof document !== 'undefined' && !styleEl) {
2502
- const el = document.createElement('style');
2503
- el.type = 'text/css';
2504
- el.id = parsedOptions.stylesheetId;
2505
- if (parsedOptions.cspNonce) el.setAttribute('nonce', parsedOptions.cspNonce);
2506
- styleEl = el;
2507
- document.head.appendChild(styleEl);
2508
- }
2509
- if (styleEl) styleEl.innerHTML = styles.value;
2587
+ upsertStyles(parsedOptions.stylesheetId, parsedOptions.cspNonce, styles.value);
2510
2588
  }
2511
2589
  }
2512
2590
  }
2513
- const themeClasses = vue.computed(() => parsedOptions.isDisabled ? undefined : `v-theme--${name.value}`);
2591
+ function change(themeName) {
2592
+ if (!themeNames.value.includes(themeName)) {
2593
+ consoleWarn(`Theme "${themeName}" not found on the Vuetify theme instance`);
2594
+ return;
2595
+ }
2596
+ name.value = themeName;
2597
+ }
2598
+ function cycle() {
2599
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : themeNames.value;
2600
+ const currentIndex = themeArray.indexOf(name.value);
2601
+ const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % themeArray.length;
2602
+ change(themeArray[nextIndex]);
2603
+ }
2604
+ function toggle() {
2605
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['light', 'dark'];
2606
+ cycle(themeArray);
2607
+ }
2608
+ const globalName = new Proxy(name, {
2609
+ get(target, prop) {
2610
+ return target[prop];
2611
+ },
2612
+ set(target, prop, val) {
2613
+ if (prop === 'value') {
2614
+ deprecate(`theme.global.name.value = ${val}`, `theme.change('${val}')`);
2615
+ }
2616
+ // @ts-expect-error
2617
+ target[prop] = val;
2618
+ return true;
2619
+ }
2620
+ });
2514
2621
  return {
2515
2622
  install,
2623
+ change,
2624
+ cycle,
2625
+ toggle,
2516
2626
  isDisabled: parsedOptions.isDisabled,
2517
2627
  name,
2518
2628
  themes,
2519
2629
  current,
2520
2630
  computedThemes,
2631
+ prefix: parsedOptions.prefix,
2521
2632
  themeClasses,
2522
2633
  styles,
2523
2634
  global: {
2524
- name,
2635
+ name: globalName,
2525
2636
  current
2526
2637
  }
2527
2638
  };
@@ -2530,11 +2641,9 @@
2530
2641
  getCurrentInstance('provideTheme');
2531
2642
  const theme = vue.inject(ThemeSymbol, null);
2532
2643
  if (!theme) throw new Error('Could not find Vuetify theme injection');
2533
- const name = vue.computed(() => {
2534
- return props.theme ?? theme.name.value;
2535
- });
2644
+ const name = vue.computed(() => props.theme ?? theme.name.value);
2536
2645
  const current = vue.computed(() => theme.themes.value[name.value]);
2537
- const themeClasses = vue.computed(() => theme.isDisabled ? undefined : `v-theme--${name.value}`);
2646
+ const themeClasses = vue.computed(() => theme.isDisabled ? undefined : `${theme.prefix}theme--${name.value}`);
2538
2647
  const newTheme = {
2539
2648
  ...theme,
2540
2649
  name,
@@ -2550,24 +2659,6 @@
2550
2659
  if (!theme) throw new Error('Could not find Vuetify theme injection');
2551
2660
  return theme;
2552
2661
  }
2553
- function genCssVariables(theme) {
2554
- const lightOverlay = theme.dark ? 2 : 1;
2555
- const darkOverlay = theme.dark ? 1 : 2;
2556
- const variables = [];
2557
- for (const [key, value] of Object.entries(theme.colors)) {
2558
- const rgb = parseColor(value);
2559
- variables.push(`--v-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2560
- if (!key.startsWith('on-')) {
2561
- variables.push(`--v-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2562
- }
2563
- }
2564
- for (const [key, value] of Object.entries(theme.variables)) {
2565
- const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
2566
- const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
2567
- variables.push(`--v-${key}: ${rgb ?? value}`);
2568
- }
2569
- return variables;
2570
- }
2571
2662
 
2572
2663
  const makeVAppProps = propsFactory({
2573
2664
  ...makeComponentProps(),
@@ -12285,7 +12376,12 @@
12285
12376
  }
12286
12377
  function calculateOffset(index) {
12287
12378
  index = clamp(index, 0, items.value.length - 1);
12288
- return offsets[index] || 0;
12379
+ const whole = Math.floor(index);
12380
+ const fraction = index % 1;
12381
+ const next = whole + 1;
12382
+ const wholeOffset = offsets[whole] || 0;
12383
+ const nextOffset = offsets[next] || wholeOffset;
12384
+ return wholeOffset + (nextOffset - wholeOffset) * fraction;
12289
12385
  }
12290
12386
  function calculateIndex(scrollTop) {
12291
12387
  return binaryClosest(offsets, scrollTop);
@@ -31542,7 +31638,7 @@
31542
31638
  };
31543
31639
  });
31544
31640
  }
31545
- const version$1 = "3.8.0-master.2025-04-06";
31641
+ const version$1 = "3.8.1-dev.2025-04-12";
31546
31642
  createVuetify$1.version = version$1;
31547
31643
 
31548
31644
  // Vue's inject() can only be used in setup
@@ -31827,7 +31923,7 @@
31827
31923
 
31828
31924
  /* eslint-disable local-rules/sort-imports */
31829
31925
 
31830
- const version = "3.8.0-master.2025-04-06";
31926
+ const version = "3.8.1-dev.2025-04-12";
31831
31927
 
31832
31928
  /* eslint-disable local-rules/sort-imports */
31833
31929