@bug-on/m3-expressive 1.0.0 → 1.2.0

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +41 -2
  2. package/README.md +20 -18
  3. package/dist/assets/material-symbols-self-hosted.css +27 -26
  4. package/dist/buttons.d.mts +2 -2
  5. package/dist/buttons.d.ts +2 -2
  6. package/dist/buttons.js +30 -1
  7. package/dist/buttons.js.map +1 -1
  8. package/dist/buttons.mjs +30 -1
  9. package/dist/buttons.mjs.map +1 -1
  10. package/dist/core-Bc5Wj_pc.d.ts +497 -0
  11. package/dist/core-D4048_K5.d.mts +497 -0
  12. package/dist/core.d.mts +6 -422
  13. package/dist/core.d.ts +6 -422
  14. package/dist/core.js +137 -68
  15. package/dist/core.js.map +1 -1
  16. package/dist/core.mjs +138 -69
  17. package/dist/core.mjs.map +1 -1
  18. package/dist/feedback.d.mts +54 -54
  19. package/dist/feedback.d.ts +54 -54
  20. package/dist/feedback.js.map +1 -1
  21. package/dist/feedback.mjs.map +1 -1
  22. package/dist/index.css +9 -1
  23. package/dist/index.d.mts +66 -4
  24. package/dist/index.d.ts +66 -4
  25. package/dist/index.js +214 -94
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +214 -95
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/layout.d.mts +40 -40
  30. package/dist/layout.d.ts +40 -40
  31. package/dist/layout.js +34 -5
  32. package/dist/layout.js.map +1 -1
  33. package/dist/layout.mjs +34 -5
  34. package/dist/layout.mjs.map +1 -1
  35. package/dist/material-symbols-self-hosted.css +27 -26
  36. package/dist/{md3-DFhj-NZj.d.mts → md3-Dty-Qcad.d.mts} +7 -1
  37. package/dist/{md3-DFhj-NZj.d.ts → md3-Dty-Qcad.d.ts} +7 -1
  38. package/dist/navigation.js.map +1 -1
  39. package/dist/navigation.mjs.map +1 -1
  40. package/dist/overlays.d.mts +2 -2
  41. package/dist/overlays.d.ts +2 -2
  42. package/dist/overlays.js +2 -2
  43. package/dist/overlays.js.map +1 -1
  44. package/dist/overlays.mjs +2 -2
  45. package/dist/overlays.mjs.map +1 -1
  46. package/dist/pickers.d.mts +241 -243
  47. package/dist/pickers.d.ts +241 -243
  48. package/dist/pickers.js +1 -1
  49. package/dist/pickers.js.map +1 -1
  50. package/dist/pickers.mjs +1 -1
  51. package/dist/pickers.mjs.map +1 -1
  52. package/dist/{side-sheet-modal-BY6VCC8p.d.mts → side-sheet-modal-64FGhDxL.d.mts} +20 -21
  53. package/dist/{side-sheet-modal-CglP6KYA.d.ts → side-sheet-modal-Bd5Qqvp9.d.ts} +20 -21
  54. package/dist/{split-button-trailing-uncheckable-C5CLCIKP.d.ts → split-button-trailing-uncheckable-BkPbiBo3.d.ts} +169 -152
  55. package/dist/{split-button-trailing-uncheckable-MXj_kyNt.d.mts → split-button-trailing-uncheckable-D_PLPb-u.d.mts} +169 -152
  56. package/dist/typography.css +5 -0
  57. package/package.json +5 -5
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import * as React59 from 'react';
3
3
  import { createContext, forwardRef, useState, useRef, useCallback, useMemo, useEffect, useLayoutEffect, useReducer, useContext, useId, cloneElement, createElement } from 'react';
4
+ import { hexFromArgb, Hct, SchemeExpressive, SchemeNeutral, SchemeMonochrome, SchemeContent, SchemeFidelity, SchemeVibrant, SchemeTonalSpot } from '@material/material-color-utilities';
4
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
- import { argbFromHex, themeFromSourceColor, hexFromArgb } from '@material/material-color-utilities';
6
6
  import { clsx } from 'clsx';
7
7
  import { twMerge } from 'tailwind-merge';
8
8
  import * as RxContextMenu from '@radix-ui/react-context-menu';
@@ -118,6 +118,143 @@ function useRipple(options = {}) {
118
118
  );
119
119
  return { rippleRef: ref, onPointerDown };
120
120
  }
121
+ function resolveMode(mode) {
122
+ if (mode !== "system") return mode;
123
+ if (typeof window === "undefined") return "light";
124
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
125
+ }
126
+ function createDynamicScheme(sourceColorHex, isDark, variant = "expressive", contrastLevel = 0) {
127
+ const hct = Hct.fromInt(argbFromHex(sourceColorHex));
128
+ const spec = "2025";
129
+ switch (variant) {
130
+ case "tonal_spot":
131
+ return new SchemeTonalSpot(hct, isDark, contrastLevel, spec);
132
+ case "vibrant":
133
+ return new SchemeVibrant(hct, isDark, contrastLevel, spec);
134
+ case "fidelity":
135
+ return new SchemeFidelity(hct, isDark, contrastLevel, spec);
136
+ case "content":
137
+ return new SchemeContent(hct, isDark, contrastLevel, spec);
138
+ case "monochrome":
139
+ return new SchemeMonochrome(hct, isDark, contrastLevel, spec);
140
+ case "neutral":
141
+ return new SchemeNeutral(hct, isDark, contrastLevel, spec);
142
+ default:
143
+ return new SchemeExpressive(hct, isDark, contrastLevel, spec);
144
+ }
145
+ }
146
+ function argbFromHex(hex) {
147
+ const sanitized = hex.replace(/^#/, "");
148
+ const r = Number.parseInt(sanitized.substring(0, 2), 16);
149
+ const g = Number.parseInt(sanitized.substring(2, 4), 16);
150
+ const b = Number.parseInt(sanitized.substring(4, 6), 16);
151
+ return (4278190080 | r << 16 | g << 8 | b) >>> 0;
152
+ }
153
+ function generateM3Theme(sourceColorHex, mode = "light", options = {}) {
154
+ const { variant = "expressive", contrastLevel = 0 } = options;
155
+ const isDark = mode === "dark";
156
+ const scheme = createDynamicScheme(
157
+ sourceColorHex,
158
+ isDark,
159
+ variant,
160
+ contrastLevel
161
+ );
162
+ const hex = (argb) => hexFromArgb(argb);
163
+ return {
164
+ // Primary
165
+ primary: hex(scheme.primary),
166
+ onPrimary: hex(scheme.onPrimary),
167
+ primaryContainer: hex(scheme.primaryContainer),
168
+ onPrimaryContainer: hex(scheme.onPrimaryContainer),
169
+ inversePrimary: hex(scheme.inversePrimary),
170
+ primaryFixed: hex(scheme.primaryFixed),
171
+ primaryFixedDim: hex(scheme.primaryFixedDim),
172
+ onPrimaryFixed: hex(scheme.onPrimaryFixed),
173
+ onPrimaryFixedVariant: hex(scheme.onPrimaryFixedVariant),
174
+ primaryDim: hex(scheme.primaryDim),
175
+ // Secondary
176
+ secondary: hex(scheme.secondary),
177
+ onSecondary: hex(scheme.onSecondary),
178
+ secondaryContainer: hex(scheme.secondaryContainer),
179
+ onSecondaryContainer: hex(scheme.onSecondaryContainer),
180
+ secondaryFixed: hex(scheme.secondaryFixed),
181
+ secondaryFixedDim: hex(scheme.secondaryFixedDim),
182
+ onSecondaryFixed: hex(scheme.onSecondaryFixed),
183
+ onSecondaryFixedVariant: hex(scheme.onSecondaryFixedVariant),
184
+ secondaryDim: hex(scheme.secondaryDim),
185
+ // Tertiary
186
+ tertiary: hex(scheme.tertiary),
187
+ onTertiary: hex(scheme.onTertiary),
188
+ tertiaryContainer: hex(scheme.tertiaryContainer),
189
+ onTertiaryContainer: hex(scheme.onTertiaryContainer),
190
+ tertiaryFixed: hex(scheme.tertiaryFixed),
191
+ tertiaryFixedDim: hex(scheme.tertiaryFixedDim),
192
+ onTertiaryFixed: hex(scheme.onTertiaryFixed),
193
+ onTertiaryFixedVariant: hex(scheme.onTertiaryFixedVariant),
194
+ tertiaryDim: hex(scheme.tertiaryDim),
195
+ // Error
196
+ error: hex(scheme.error),
197
+ onError: hex(scheme.onError),
198
+ errorContainer: hex(scheme.errorContainer),
199
+ onErrorContainer: hex(scheme.onErrorContainer),
200
+ // Surface
201
+ surface: hex(scheme.surface),
202
+ onSurface: hex(scheme.onSurface),
203
+ surfaceVariant: hex(scheme.surfaceVariant),
204
+ onSurfaceVariant: hex(scheme.onSurfaceVariant),
205
+ surfaceTint: hex(scheme.surfaceTint),
206
+ surfaceDim: hex(scheme.surfaceDim),
207
+ surfaceBright: hex(scheme.surfaceBright),
208
+ surfaceContainerLowest: hex(scheme.surfaceContainerLowest),
209
+ surfaceContainerLow: hex(scheme.surfaceContainerLow),
210
+ surfaceContainer: hex(scheme.surfaceContainer),
211
+ surfaceContainerHigh: hex(scheme.surfaceContainerHigh),
212
+ surfaceContainerHighest: hex(scheme.surfaceContainerHighest),
213
+ // Inverse
214
+ inverseSurface: hex(scheme.inverseSurface),
215
+ inverseOnSurface: hex(scheme.inverseOnSurface),
216
+ // Background
217
+ background: hex(scheme.background),
218
+ onBackground: hex(scheme.onBackground),
219
+ // Outline
220
+ outline: hex(scheme.outline),
221
+ outlineVariant: hex(scheme.outlineVariant),
222
+ // Utility
223
+ shadow: hex(scheme.shadow),
224
+ scrim: hex(scheme.scrim)
225
+ };
226
+ }
227
+ function applyTheme(sourceColorHex, mode = "light", root = document.documentElement, options = {}) {
228
+ const resolved = resolveMode(mode);
229
+ const colors = generateM3Theme(sourceColorHex, resolved, options);
230
+ for (const [key, value] of Object.entries(colors)) {
231
+ const kebabKey = key.replace(/[A-Z]/g, (m67) => `-${m67.toLowerCase()}`);
232
+ root.style.setProperty(`--md-sys-color-${kebabKey}`, value);
233
+ root.style.setProperty(`--color-m3-${kebabKey}`, value);
234
+ }
235
+ root.setAttribute("data-theme", resolved);
236
+ }
237
+
238
+ // src/lib/create-theme.ts
239
+ function createMd3ExpressiveTheme(options) {
240
+ const { seedColor, isDark = false, variant, contrastLevel } = options;
241
+ const themeOptions = { variant, contrastLevel };
242
+ const colorScheme = generateM3Theme(
243
+ seedColor,
244
+ isDark ? "dark" : "light",
245
+ themeOptions
246
+ );
247
+ const cssVariables = schemeToCssVariables(colorScheme);
248
+ return { cssVariables, colorScheme };
249
+ }
250
+ function schemeToCssVariables(scheme) {
251
+ const result = {};
252
+ for (const [key, value] of Object.entries(scheme)) {
253
+ const kebabKey = key.replace(/[A-Z]/g, (m67) => `-${m67.toLowerCase()}`);
254
+ result[`--md-sys-color-${kebabKey}`] = value;
255
+ }
256
+ return result;
257
+ }
121
258
  function MaterialSymbolsPreconnect({
122
259
  variants = ["outlined"]
123
260
  }) {
@@ -157,78 +294,6 @@ function MaterialSymbolsPreconnect({
157
294
  )
158
295
  ] });
159
296
  }
160
- function resolveMode(mode) {
161
- if (mode !== "system") return mode;
162
- if (typeof window === "undefined") return "light";
163
- return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
164
- }
165
- function generateM3Theme(sourceColorHex, mode = "light") {
166
- const sourceColor = argbFromHex(sourceColorHex);
167
- const theme = themeFromSourceColor(sourceColor);
168
- const scheme = mode === "light" ? theme.schemes.light : theme.schemes.dark;
169
- const palettes = theme.palettes;
170
- const tone = (palette, t) => hexFromArgb(palette.tone(t));
171
- return {
172
- primary: hexFromArgb(scheme.primary),
173
- onPrimary: hexFromArgb(scheme.onPrimary),
174
- primaryContainer: hexFromArgb(scheme.primaryContainer),
175
- onPrimaryContainer: hexFromArgb(scheme.onPrimaryContainer),
176
- inversePrimary: hexFromArgb(scheme.inversePrimary),
177
- primaryFixed: tone(palettes.primary, 90),
178
- primaryFixedDim: tone(palettes.primary, 80),
179
- onPrimaryFixed: tone(palettes.primary, 10),
180
- onPrimaryFixedVariant: tone(palettes.primary, 30),
181
- secondary: hexFromArgb(scheme.secondary),
182
- onSecondary: hexFromArgb(scheme.onSecondary),
183
- secondaryContainer: hexFromArgb(scheme.secondaryContainer),
184
- onSecondaryContainer: hexFromArgb(scheme.onSecondaryContainer),
185
- secondaryFixed: tone(palettes.secondary, 90),
186
- secondaryFixedDim: tone(palettes.secondary, 80),
187
- onSecondaryFixed: tone(palettes.secondary, 10),
188
- onSecondaryFixedVariant: tone(palettes.secondary, 30),
189
- tertiary: hexFromArgb(scheme.tertiary),
190
- onTertiary: hexFromArgb(scheme.onTertiary),
191
- tertiaryContainer: hexFromArgb(scheme.tertiaryContainer),
192
- onTertiaryContainer: hexFromArgb(scheme.onTertiaryContainer),
193
- tertiaryFixed: tone(palettes.tertiary, 90),
194
- tertiaryFixedDim: tone(palettes.tertiary, 80),
195
- onTertiaryFixed: tone(palettes.tertiary, 10),
196
- onTertiaryFixedVariant: tone(palettes.tertiary, 30),
197
- error: hexFromArgb(scheme.error),
198
- onError: hexFromArgb(scheme.onError),
199
- errorContainer: hexFromArgb(scheme.errorContainer),
200
- onErrorContainer: hexFromArgb(scheme.onErrorContainer),
201
- surface: hexFromArgb(scheme.surface),
202
- onSurface: hexFromArgb(scheme.onSurface),
203
- surfaceVariant: hexFromArgb(scheme.surfaceVariant),
204
- onSurfaceVariant: hexFromArgb(scheme.onSurfaceVariant),
205
- surfaceTint: hexFromArgb(scheme.primary),
206
- // Surface container roles from neutral palette tones
207
- surfaceContainerLowest: mode === "light" ? tone(palettes.neutral, 100) : tone(palettes.neutral, 4),
208
- surfaceContainerLow: mode === "light" ? tone(palettes.neutral, 96) : tone(palettes.neutral, 10),
209
- surfaceContainer: mode === "light" ? tone(palettes.neutral, 94) : tone(palettes.neutral, 12),
210
- surfaceContainerHigh: mode === "light" ? tone(palettes.neutral, 92) : tone(palettes.neutral, 17),
211
- surfaceContainerHighest: mode === "light" ? tone(palettes.neutral, 90) : tone(palettes.neutral, 22),
212
- inverseSurface: hexFromArgb(scheme.inverseSurface),
213
- inverseOnSurface: hexFromArgb(scheme.inverseOnSurface),
214
- background: hexFromArgb(scheme.background),
215
- onBackground: hexFromArgb(scheme.onBackground),
216
- outline: hexFromArgb(scheme.outline),
217
- outlineVariant: hexFromArgb(scheme.outlineVariant),
218
- shadow: hexFromArgb(scheme.shadow),
219
- scrim: hexFromArgb(scheme.scrim)
220
- };
221
- }
222
- function applyTheme(sourceColorHex, mode = "light", root = document.documentElement) {
223
- const resolved = resolveMode(mode);
224
- const colors = generateM3Theme(sourceColorHex, resolved);
225
- for (const [key, value] of Object.entries(colors)) {
226
- const kebabKey = key.replace(/[A-Z]/g, (m67) => `-${m67.toLowerCase()}`);
227
- root.style.setProperty(`--md-sys-color-${kebabKey}`, value);
228
- root.style.setProperty(`--color-m3-${kebabKey}`, value);
229
- }
230
- root.setAttribute("data-theme", resolved);
231
- }
232
297
  function cn(...inputs) {
233
298
  return twMerge(clsx(inputs));
234
299
  }
@@ -6559,6 +6624,35 @@ var BUTTON_COLOR_TOKENS = {
6559
6624
  default: "bg-transparent text-m3-primary",
6560
6625
  selected: "bg-transparent text-m3-primary",
6561
6626
  unselected: "bg-transparent text-m3-primary"
6627
+ },
6628
+ // ── MD3 Expressive accent variants ──────────────────────────────────────
6629
+ /**
6630
+ * High-chroma tertiary tone. Use for hero CTAs and expressive moments where
6631
+ * a distinct accent beyond primary is needed (e.g., hero chip, highlight fab).
6632
+ */
6633
+ tertiary: {
6634
+ default: "bg-m3-tertiary text-m3-on-tertiary",
6635
+ selected: "bg-m3-tertiary text-m3-on-tertiary",
6636
+ unselected: "bg-m3-tertiary-container text-m3-on-tertiary-container"
6637
+ },
6638
+ /**
6639
+ * Brand-stable primary fixed. Hue stays consistent across light and dark modes.
6640
+ * Ideal for badges, pill chips, and elements that must carry the brand color
6641
+ * regardless of the active theme.
6642
+ */
6643
+ "primary-fixed": {
6644
+ default: "bg-m3-primary-fixed text-m3-on-primary-fixed",
6645
+ selected: "bg-m3-primary-fixed text-m3-on-primary-fixed",
6646
+ unselected: "bg-m3-primary-fixed text-m3-on-primary-fixed-variant"
6647
+ },
6648
+ /**
6649
+ * Brand-stable tertiary fixed. Use for special-state indicators, achievement
6650
+ * badges, or accent pills that need a fixed tertiary hue across themes.
6651
+ */
6652
+ "tertiary-fixed": {
6653
+ default: "bg-m3-tertiary-fixed text-m3-on-tertiary-fixed",
6654
+ selected: "bg-m3-tertiary-fixed text-m3-on-tertiary-fixed",
6655
+ unselected: "bg-m3-tertiary-fixed text-m3-on-tertiary-fixed-variant"
6562
6656
  }
6563
6657
  };
6564
6658
  var MOTION_PROP_KEYS = [
@@ -6930,7 +7024,7 @@ var PILL_BORDER_RADIUS = 9999;
6930
7024
  var MIN_FLEX_GROW = 0.01;
6931
7025
  var PADDING_EXPAND_MULTIPLIER = 4;
6932
7026
  var CHECK_ICON_SIZE = 24;
6933
- var CHECK_ICON = /* @__PURE__ */ jsx(Icon, { name: "check", size: CHECK_ICON_SIZE, weight: 700 });
7027
+ var CHECK_ICON = /* @__PURE__ */ jsx(Icon, { name: "check", variant: "rounded", size: CHECK_ICON_SIZE, weight: 700 });
6934
7028
  var CHECK_ICON_GAP_MAP = {
6935
7029
  xs: 6,
6936
7030
  sm: 8,
@@ -9574,19 +9668,19 @@ var CardImpl = React59.forwardRef(
9574
9668
  const baseClass = cn(
9575
9669
  cardVariants({ variant }),
9576
9670
  // Disabled state:
9577
- // - pointer-events-none → hiệu hóa tương tác hoàn toàn
9671
+ // - pointer-events-none → disable interactions completely
9578
9672
  // - opacity-[0.38] → MD3 DisabledContainerOpacity
9579
9673
  disabled && "pointer-events-none opacity-[0.38]",
9580
9674
  className
9581
9675
  );
9582
9676
  const interactiveClass = cn(
9583
- // Xóa outline default, dùng state overlay & elevation của MD3 để biểu hiện focus
9677
+ // Remove default outline, use MD3 state overlay & elevation for focus
9584
9678
  "focus-visible:outline-none focus:outline-none group",
9585
- // Layer overlay base pseudo-element
9679
+ // Base pseudo-element overlay layer
9586
9680
  "before:absolute before:inset-0 before:pointer-events-none before:bg-m3-on-surface before:opacity-0 before:transition-opacity before:duration-200",
9587
- // Interactive states opacities
9681
+ // Interactive state opacities
9588
9682
  "hover:before:opacity-[0.08] focus-visible:before:opacity-[0.10] active:before:opacity-[0.10]",
9589
- // Outlined interactive card: đổi màu border sang m3-outline khi focus/press/hover
9683
+ // Outlined interactive card: change border color to m3-outline on focus/press/hover
9590
9684
  variant === "outlined" && "hover:border-m3-outline focus-visible:border-m3-outline active:border-m3-outline"
9591
9685
  );
9592
9686
  if (!isInteractive) {
@@ -12628,7 +12722,7 @@ var TimeInput = ({ state, className }) => {
12628
12722
  fontWeight: 400,
12629
12723
  lineHeight: 1,
12630
12724
  width: 24,
12631
- // Căn theo height của input field
12725
+ // Aligned with height of input field
12632
12726
  marginTop: `${(TP_SIZE.timeFieldHeight - 57) / 2}px`
12633
12727
  },
12634
12728
  "aria-hidden": true,
@@ -13442,7 +13536,7 @@ var DrawerContent = React59.forwardRef(
13442
13536
  m.div,
13443
13537
  __spreadProps(__spreadValues({
13444
13538
  className: cn(
13445
- // MD3 Bottom Sheet shape: chỉ bo góc trên
13539
+ // MD3 Bottom Sheet shape: top rounded corners only
13446
13540
  "fixed bottom-0 left-0 right-0 z-50",
13447
13541
  "rounded-t-[28px] bg-m3-surface-container-low",
13448
13542
  "flex flex-col overflow-hidden",
@@ -13471,7 +13565,7 @@ var DrawerContent = React59.forwardRef(
13471
13565
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-m3-primary",
13472
13566
  "transition-colors duration-200"
13473
13567
  ),
13474
- "aria-label": "\u0110\xF3ng b\u1EA3ng \u0111i\u1EC1u khi\u1EC3n",
13568
+ "aria-label": "Close drawer panel",
13475
13569
  children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 20, "aria-hidden": "true" })
13476
13570
  }
13477
13571
  ),
@@ -22314,6 +22408,8 @@ function MD3ThemeProvider({
22314
22408
  sourceColor: initialSourceColor = "#6750A4",
22315
22409
  defaultMode = "light",
22316
22410
  persistToLocalStorage = false,
22411
+ variant = "expressive",
22412
+ contrastLevel = 0,
22317
22413
  typography: typographyProp,
22318
22414
  fontFamily,
22319
22415
  fontVariationAxes,
@@ -22322,6 +22418,17 @@ function MD3ThemeProvider({
22322
22418
  const [sourceColor, setSourceColor] = useState(initialSourceColor);
22323
22419
  const [mode, setMode] = useState(defaultMode);
22324
22420
  const [isHydrated, setIsHydrated] = useState(!persistToLocalStorage);
22421
+ const [systemMode, setSystemMode] = useState("light");
22422
+ useEffect(() => {
22423
+ if (typeof window === "undefined") return;
22424
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
22425
+ const updateSystemMode = () => {
22426
+ setSystemMode(mediaQuery.matches ? "dark" : "light");
22427
+ };
22428
+ updateSystemMode();
22429
+ mediaQuery.addEventListener("change", updateSystemMode);
22430
+ return () => mediaQuery.removeEventListener("change", updateSystemMode);
22431
+ }, []);
22325
22432
  useEffect(() => {
22326
22433
  if (!persistToLocalStorage) return;
22327
22434
  const savedColor = localStorage.getItem(STORAGE_KEY_COLOR);
@@ -22333,25 +22440,37 @@ function MD3ThemeProvider({
22333
22440
  setMode(savedMode);
22334
22441
  setIsHydrated(true);
22335
22442
  }, [persistToLocalStorage]);
22443
+ const effectiveMode = mode === "system" ? systemMode : mode;
22336
22444
  useEffect(() => {
22337
22445
  if (!isHydrated) return;
22338
- applyTheme(sourceColor, mode);
22446
+ applyTheme(sourceColor, effectiveMode, document.documentElement, {
22447
+ variant,
22448
+ contrastLevel
22449
+ });
22339
22450
  if (persistToLocalStorage) {
22340
22451
  localStorage.setItem(STORAGE_KEY_COLOR, sourceColor);
22341
22452
  localStorage.setItem(STORAGE_KEY_MODE, mode);
22342
22453
  }
22343
- }, [sourceColor, mode, persistToLocalStorage, isHydrated]);
22344
- useEffect(() => {
22345
- if (mode !== "system" || typeof window === "undefined") return;
22346
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
22347
- const handleChange = () => applyTheme(sourceColor, "system");
22348
- mediaQuery.addEventListener("change", handleChange);
22349
- return () => mediaQuery.removeEventListener("change", handleChange);
22350
- }, [mode, sourceColor]);
22351
- const effectiveMode = resolveMode(mode);
22454
+ }, [
22455
+ sourceColor,
22456
+ mode,
22457
+ effectiveMode,
22458
+ persistToLocalStorage,
22459
+ isHydrated,
22460
+ variant,
22461
+ contrastLevel
22462
+ ]);
22352
22463
  const themeValue = useMemo(
22353
- () => ({ sourceColor, setSourceColor, mode, setMode, effectiveMode }),
22354
- [sourceColor, mode, effectiveMode]
22464
+ () => ({
22465
+ sourceColor,
22466
+ setSourceColor,
22467
+ mode,
22468
+ setMode,
22469
+ effectiveMode,
22470
+ variant,
22471
+ contrastLevel
22472
+ }),
22473
+ [sourceColor, mode, effectiveMode, variant, contrastLevel]
22355
22474
  );
22356
22475
  const typographyValue = useMemo(() => {
22357
22476
  if (typographyProp) return typographyProp;
@@ -23663,6 +23782,6 @@ function TooltipBox({
23663
23782
  ] });
23664
23783
  }
23665
23784
 
23666
- export { ANGLE_EPSILON, APP_BAR_BOTTOM_SPRING, APP_BAR_COLORS, APP_BAR_COLOR_TRANSITION, APP_BAR_ENTER_ALWAYS_SPRING, APP_BAR_TITLE_FADE, AppBarColumn, AppBarOverflowIndicator, AppBarRow, AppBarTokens, BUTTON_COLOR_TOKENS, BUTTON_SIZE_TOKENS, Badge, BadgedBox, BottomAppBar, BottomDockedToolbar, BottomSheet, BottomSheetModal, Button, ButtonGroup, CHECK_ICON_VARIANTS, Card, Checkbox, Chip, CodeBlock, ContextMenu, ContextMenuContent, ContextMenuTrigger, Cubic, DISTANCE_EPSILON, DIVIDER_COLOR, DIVIDER_PADDING, DP_CLASSES, DP_COLORS, DP_SHAPE, DP_SIZE, DatePicker, DatePickerDialog, DatePickerInput, DateRangePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogFullScreenContent, DialogHeader, DialogIcon, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Divider, DockedToolbar, DragHandle, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, ElevatedSplitButtonLeading, ElevatedSplitButtonTrailing, ElevatedSplitButtonTrailingUncheckable, ExtendedFAB, FAB, FABMenu, FABMenuItem, FABPosition, FAST_EFFECTS_TRANSITION, FAST_SPATIAL_SPRING, FLOAT_PI, FilledSplitButtonLeading, FilledSplitButtonTrailing, FilledSplitButtonTrailingUncheckable, GROUP_SHAPES, HorizontalFloatingToolbar, HorizontalFloatingToolbarWithFab, ITEM_SHAPE_CLASSES, Icon, IconButton, LIST_TOKENS, LargeFlexibleAppBar, List, ListContext, ListDivider, ListItem, LoadingIndicator, MD3CornerRadius, MD3Shapes, MD3ThemeProvider, MD3_EXPRESSIVE_FONT_VARIATION, MENU_CHECK_ICON_SIZE, MENU_CONTAINER_VARIANTS, MENU_GROUP_GAP, MENU_ICON_SIZE, MENU_ITEM_MIN_HEIGHT, MENU_MAX_WIDTH, MENU_MIN_WIDTH, MaterialSymbolsPreconnect, MeasuredPolygon, MediumFlexibleAppBar, Menu, MenuContent, MenuDivider, MenuGroup, MenuItem, MenuProvider, MenuTrigger, Morph, MutableCubic, NavigationBar, NavigationBarItem, NavigationRail, NavigationRailItem, OutlinedSplitButtonLeading, OutlinedSplitButtonTrailing, OutlinedSplitButtonTrailingUncheckable, PlainTooltip, ProgressIndicator, RadioButton, RadioGroup, RangeSlider, RichTooltip, Ripple, RoundedPolygon, SEARCH_BAR_EXPAND_SPRING, SEARCH_COLORS, SEARCH_DOCKED_REVEAL_SPRING, SEARCH_FULLSCREEN_SPRING, SEARCH_TYPOGRAPHY, SEARCH_VIEW_SPRING, STANDARD_COLORS, SUBMENU_CONTAINER_VARIANTS, Scrim, ScrollArea, ScrollAreaScrollbar, Search, SearchAppBar, SearchBar, SearchTokens, SearchView, SearchViewContainer, SearchViewDocked, SearchViewFullScreen, ShapeIcon, ShapeMedia, ShapeMediaServer, ShapeSvg, SideSheet, SideSheetModal, Slider, SliderColors, SliderTokens, SmallAppBar, Snackbar, SnackbarHost, SnackbarProvider, SplitButtonLayout, SplitButtonLeading, SplitButtonTrailing, SplitButtonTrailingUncheckable, SubMenu, Switch, SwitchColors, SwitchTokens, TP_CLASSES, TP_COLORS, TP_SHAPE, TP_SIZE, Tab, TableOfContents, Tabs, TabsColors, TabsContent, TabsList, TabsTokens, Text, TextField, TimeInput, TimePicker, TimePickerDialog, ToggleFAB, TonalSplitButtonLeading, TonalSplitButtonTrailing, TonalSplitButtonTrailingUncheckable, ToolbarDivider, ToolbarDividerTokens, ToolbarIconButton, ToolbarIconButtonTokens, TooltipBox, TooltipCaretShape, TooltipTokens, TriStateCheckbox, TypeScaleTokens, Typography, TypographyContext, TypographyKeyTokens, TypographyProvider, TypographyTokens, UNROUNDED, VIBRANT_COLORS, VerticalFloatingToolbar, VerticalFloatingToolbarWithFab, VerticalMenu, VerticalMenuContent, VerticalMenuDivider, VerticalMenuGroup, addPoints, appBarTypography, applyTheme, buildWavePath, circle, clockwise, cn, convex, cornerFeature, cornerRounding, createDoubleMapper, directionVector, distance, distanceSquared, dividePoint, dotProduct, edgeFeature, featureMapper, generateM3Theme, getDirection, getDistance, getDistanceSquared, getExpressiveShape, getListItemHeight, interpolate, interpolatePath, lerpPoint, pill, pillStar, point, positiveModulo, radialToCartesian, rectangle, resolveMode, rotate90, scalePoint, shouldTopAlign, square, standardFloatingToolbarColors, star, subtractPoints, toClipPath, toSvgPath, transformFeature, transformPoint, useAppBarScroll, useBottomSheet, useRipple as useDOMRipple, useDatePickerState, useDateRangePickerState, useFloatingToolbarScrollBehavior, useListContext, useMediaQuery, useMenuContext, useRipple2 as useRipple, useRippleState, useSearchKeyboard, useShapeMorph, useSnackbar, useSnackbarState, useTheme, useThemeMode, useTimePickerState, useTooltipPosition, useTooltipState, useTypography, vibrantFloatingToolbarColors };
23785
+ export { ANGLE_EPSILON, APP_BAR_BOTTOM_SPRING, APP_BAR_COLORS, APP_BAR_COLOR_TRANSITION, APP_BAR_ENTER_ALWAYS_SPRING, APP_BAR_TITLE_FADE, AppBarColumn, AppBarOverflowIndicator, AppBarRow, AppBarTokens, BUTTON_COLOR_TOKENS, BUTTON_SIZE_TOKENS, Badge, BadgedBox, BottomAppBar, BottomDockedToolbar, BottomSheet, BottomSheetModal, Button, ButtonGroup, CHECK_ICON_VARIANTS, Card, Checkbox, Chip, CodeBlock, ContextMenu, ContextMenuContent, ContextMenuTrigger, Cubic, DISTANCE_EPSILON, DIVIDER_COLOR, DIVIDER_PADDING, DP_CLASSES, DP_COLORS, DP_SHAPE, DP_SIZE, DatePicker, DatePickerDialog, DatePickerInput, DateRangePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogFullScreenContent, DialogHeader, DialogIcon, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Divider, DockedToolbar, DragHandle, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, ElevatedSplitButtonLeading, ElevatedSplitButtonTrailing, ElevatedSplitButtonTrailingUncheckable, ExtendedFAB, FAB, FABMenu, FABMenuItem, FABPosition, FAST_EFFECTS_TRANSITION, FAST_SPATIAL_SPRING, FLOAT_PI, FilledSplitButtonLeading, FilledSplitButtonTrailing, FilledSplitButtonTrailingUncheckable, GROUP_SHAPES, HorizontalFloatingToolbar, HorizontalFloatingToolbarWithFab, ITEM_SHAPE_CLASSES, Icon, IconButton, LIST_TOKENS, LargeFlexibleAppBar, List, ListContext, ListDivider, ListItem, LoadingIndicator, MD3CornerRadius, MD3Shapes, MD3ThemeProvider, MD3_EXPRESSIVE_FONT_VARIATION, MENU_CHECK_ICON_SIZE, MENU_CONTAINER_VARIANTS, MENU_GROUP_GAP, MENU_ICON_SIZE, MENU_ITEM_MIN_HEIGHT, MENU_MAX_WIDTH, MENU_MIN_WIDTH, MaterialSymbolsPreconnect, MeasuredPolygon, MediumFlexibleAppBar, Menu, MenuContent, MenuDivider, MenuGroup, MenuItem, MenuProvider, MenuTrigger, Morph, MutableCubic, NavigationBar, NavigationBarItem, NavigationRail, NavigationRailItem, OutlinedSplitButtonLeading, OutlinedSplitButtonTrailing, OutlinedSplitButtonTrailingUncheckable, PlainTooltip, ProgressIndicator, RadioButton, RadioGroup, RangeSlider, RichTooltip, Ripple, RoundedPolygon, SEARCH_BAR_EXPAND_SPRING, SEARCH_COLORS, SEARCH_DOCKED_REVEAL_SPRING, SEARCH_FULLSCREEN_SPRING, SEARCH_TYPOGRAPHY, SEARCH_VIEW_SPRING, STANDARD_COLORS, SUBMENU_CONTAINER_VARIANTS, Scrim, ScrollArea, ScrollAreaScrollbar, Search, SearchAppBar, SearchBar, SearchTokens, SearchView, SearchViewContainer, SearchViewDocked, SearchViewFullScreen, ShapeIcon, ShapeMedia, ShapeMediaServer, ShapeSvg, SideSheet, SideSheetModal, Slider, SliderColors, SliderTokens, SmallAppBar, Snackbar, SnackbarHost, SnackbarProvider, SplitButtonLayout, SplitButtonLeading, SplitButtonTrailing, SplitButtonTrailingUncheckable, SubMenu, Switch, SwitchColors, SwitchTokens, TP_CLASSES, TP_COLORS, TP_SHAPE, TP_SIZE, Tab, TableOfContents, Tabs, TabsColors, TabsContent, TabsList, TabsTokens, Text, TextField, TimeInput, TimePicker, TimePickerDialog, ToggleFAB, TonalSplitButtonLeading, TonalSplitButtonTrailing, TonalSplitButtonTrailingUncheckable, ToolbarDivider, ToolbarDividerTokens, ToolbarIconButton, ToolbarIconButtonTokens, TooltipBox, TooltipCaretShape, TooltipTokens, TriStateCheckbox, TypeScaleTokens, Typography, TypographyContext, TypographyKeyTokens, TypographyProvider, TypographyTokens, UNROUNDED, VIBRANT_COLORS, VerticalFloatingToolbar, VerticalFloatingToolbarWithFab, VerticalMenu, VerticalMenuContent, VerticalMenuDivider, VerticalMenuGroup, addPoints, appBarTypography, applyTheme, buildWavePath, circle, clockwise, cn, convex, cornerFeature, cornerRounding, createDoubleMapper, createMd3ExpressiveTheme, directionVector, distance, distanceSquared, dividePoint, dotProduct, edgeFeature, featureMapper, generateM3Theme, getDirection, getDistance, getDistanceSquared, getExpressiveShape, getListItemHeight, interpolate, interpolatePath, lerpPoint, pill, pillStar, point, positiveModulo, radialToCartesian, rectangle, resolveMode, rotate90, scalePoint, shouldTopAlign, square, standardFloatingToolbarColors, star, subtractPoints, toClipPath, toSvgPath, transformFeature, transformPoint, useAppBarScroll, useBottomSheet, useRipple as useDOMRipple, useDatePickerState, useDateRangePickerState, useFloatingToolbarScrollBehavior, useListContext, useMediaQuery, useMenuContext, useRipple2 as useRipple, useRippleState, useSearchKeyboard, useShapeMorph, useSnackbar, useSnackbarState, useTheme, useThemeMode, useTimePickerState, useTooltipPosition, useTooltipState, useTypography, vibrantFloatingToolbarColors };
23667
23786
  //# sourceMappingURL=index.mjs.map
23668
23787
  //# sourceMappingURL=index.mjs.map