@vuetify/nightly 3.8.1-dev.2025-04-07 → 3.8.1-dev.2025-04-13

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.1-dev.2025-04-07
2
+ * Vuetify v3.8.1-dev.2025-04-13
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() {
@@ -2389,21 +2394,21 @@
2389
2394
  function createCssClass(lines, selector, content, scope) {
2390
2395
  lines.push(`${getScopedSelector(selector, scope)} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
2391
2396
  }
2392
- function genCssVariables(theme) {
2397
+ function genCssVariables(theme, prefix) {
2393
2398
  const lightOverlay = theme.dark ? 2 : 1;
2394
2399
  const darkOverlay = theme.dark ? 1 : 2;
2395
2400
  const variables = [];
2396
2401
  for (const [key, value] of Object.entries(theme.colors)) {
2397
2402
  const rgb = parseColor(value);
2398
- variables.push(`--v-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2403
+ variables.push(`--${prefix}theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2399
2404
  if (!key.startsWith('on-')) {
2400
- variables.push(`--v-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2405
+ variables.push(`--${prefix}theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2401
2406
  }
2402
2407
  }
2403
2408
  for (const [key, value] of Object.entries(theme.variables)) {
2404
2409
  const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
2405
2410
  const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
2406
- variables.push(`--v-${key}: ${rgb ?? value}`);
2411
+ variables.push(`--${prefix}${key}: ${rgb ?? value}`);
2407
2412
  }
2408
2413
  return variables;
2409
2414
  }
@@ -2447,7 +2452,8 @@
2447
2452
  const scopeSelector = `:where(${scope})`;
2448
2453
  return selector === ':root' ? scopeSelector : `${scopeSelector} ${selector}`;
2449
2454
  }
2450
- function upsertStyles(styleEl, styles) {
2455
+ function upsertStyles(id, cspNonce, styles) {
2456
+ const styleEl = getOrCreateStyleElement(id, cspNonce);
2451
2457
  if (!styleEl) return;
2452
2458
  styleEl.innerHTML = styles;
2453
2459
  }
@@ -2467,8 +2473,17 @@
2467
2473
  // Composables
2468
2474
  function createTheme(options) {
2469
2475
  const parsedOptions = parseThemeOptions(options);
2470
- const name = vue.shallowRef(parsedOptions.defaultTheme);
2476
+ const _name = vue.shallowRef(parsedOptions.defaultTheme);
2471
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
+ });
2472
2487
  const computedThemes = vue.computed(() => {
2473
2488
  const acc = {};
2474
2489
  for (const [name, original] of Object.entries(themes.value)) {
@@ -2489,28 +2504,49 @@
2489
2504
  const current = vue.computed(() => computedThemes.value[name.value]);
2490
2505
  const styles = vue.computed(() => {
2491
2506
  const lines = [];
2507
+ const important = parsedOptions.unimportant ? '' : ' !important';
2508
+ const scoped = parsedOptions.scoped ? parsedOptions.prefix : '';
2492
2509
  if (current.value?.dark) {
2493
2510
  createCssClass(lines, ':root', ['color-scheme: dark'], parsedOptions.scope);
2494
2511
  }
2495
- createCssClass(lines, ':root', genCssVariables(current.value), parsedOptions.scope);
2512
+ createCssClass(lines, ':root', genCssVariables(current.value, parsedOptions.prefix), parsedOptions.scope);
2496
2513
  for (const [themeName, theme] of Object.entries(computedThemes.value)) {
2497
- createCssClass(lines, `.v-theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme)], parsedOptions.scope);
2498
- }
2499
- const bgLines = [];
2500
- const fgLines = [];
2501
- const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
2502
- for (const key of colors) {
2503
- if (key.startsWith('on-')) {
2504
- createCssClass(fgLines, `.${key}`, [`color: rgb(var(--v-theme-${key})) !important`], parsedOptions.scope);
2505
- } else {
2506
- 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`], parsedOptions.scope);
2507
- createCssClass(fgLines, `.text-${key}`, [`color: rgb(var(--v-theme-${key})) !important`], parsedOptions.scope);
2508
- createCssClass(fgLines, `.border-${key}`, [`--v-border-color: var(--v-theme-${key})`], parsedOptions.scope);
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
+ }
2509
2528
  }
2529
+ lines.push(...bgLines, ...fgLines);
2510
2530
  }
2511
- lines.push(...bgLines, ...fgLines);
2512
2531
  return lines.map((str, i) => i === 0 ? str : ` ${str}`).join('');
2513
2532
  });
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
+ }
2549
+ }
2514
2550
  function install(app) {
2515
2551
  if (parsedOptions.isDisabled) return;
2516
2552
  const head = app._context.provides.usehead;
@@ -2548,22 +2584,55 @@
2548
2584
  updateStyles();
2549
2585
  }
2550
2586
  function updateStyles() {
2551
- upsertStyles(getOrCreateStyleElement(parsedOptions.stylesheetId, parsedOptions.cspNonce), styles.value);
2587
+ upsertStyles(parsedOptions.stylesheetId, parsedOptions.cspNonce, styles.value);
2552
2588
  }
2553
2589
  }
2554
2590
  }
2555
- 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
+ });
2556
2621
  return {
2557
2622
  install,
2623
+ change,
2624
+ cycle,
2625
+ toggle,
2558
2626
  isDisabled: parsedOptions.isDisabled,
2559
2627
  name,
2560
2628
  themes,
2561
2629
  current,
2562
2630
  computedThemes,
2631
+ prefix: parsedOptions.prefix,
2563
2632
  themeClasses,
2564
2633
  styles,
2565
2634
  global: {
2566
- name,
2635
+ name: globalName,
2567
2636
  current
2568
2637
  }
2569
2638
  };
@@ -2574,7 +2643,7 @@
2574
2643
  if (!theme) throw new Error('Could not find Vuetify theme injection');
2575
2644
  const name = vue.computed(() => props.theme ?? theme.name.value);
2576
2645
  const current = vue.computed(() => theme.themes.value[name.value]);
2577
- const themeClasses = vue.computed(() => theme.isDisabled ? undefined : `v-theme--${name.value}`);
2646
+ const themeClasses = vue.computed(() => theme.isDisabled ? undefined : `${theme.prefix}theme--${name.value}`);
2578
2647
  const newTheme = {
2579
2648
  ...theme,
2580
2649
  name,
@@ -31569,7 +31638,7 @@
31569
31638
  };
31570
31639
  });
31571
31640
  }
31572
- const version$1 = "3.8.1-dev.2025-04-07";
31641
+ const version$1 = "3.8.1-dev.2025-04-13";
31573
31642
  createVuetify$1.version = version$1;
31574
31643
 
31575
31644
  // Vue's inject() can only be used in setup
@@ -31854,7 +31923,7 @@
31854
31923
 
31855
31924
  /* eslint-disable local-rules/sort-imports */
31856
31925
 
31857
- const version = "3.8.1-dev.2025-04-07";
31926
+ const version = "3.8.1-dev.2025-04-13";
31858
31927
 
31859
31928
  /* eslint-disable local-rules/sort-imports */
31860
31929