@aglyn/shared-ui-theme 1.0.0-beta.277 → 1.0.0-beta.283

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aglyn/shared-ui-theme",
3
- "version": "1.0.0-beta.277",
3
+ "version": "1.0.0-beta.283",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://aglyn.com",
6
6
  "repository": {
@@ -25,9 +25,9 @@
25
25
  "./package.json": "./package.json"
26
26
  },
27
27
  "dependencies": {
28
- "@aglyn/shared-data-types": "1.0.0-beta.277",
29
- "@aglyn/shared-util-tools": "1.0.0-beta.277",
30
- "@aglyn/shared-util-vendor": "1.0.0-beta.277",
28
+ "@aglyn/shared-data-types": "1.0.0-beta.283",
29
+ "@aglyn/shared-util-tools": "1.0.0-beta.283",
30
+ "@aglyn/shared-util-vendor": "1.0.0-beta.283",
31
31
  "@emotion/cache": "^11.14.0",
32
32
  "@emotion/react": "11.14.0",
33
33
  "@swc/helpers": "0.5.23",
@@ -19,6 +19,7 @@ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_wi
19
19
  import { alpha, createTheme, darken, getContrastRatio, lighten, responsiveFontSizes } from "../../vendor/mui.js";
20
20
  import { ACCENT_HOVER_FILL, ACCENT_HOVER_TEXT, hoverFillShade, inkOnFill } from "./accent-text.js";
21
21
  import { accessibleShade, contrastRatio, meetsContrast } from "./accessible-shade.js";
22
+ import { addPalettePathColorVariants } from "./palette-path-colors.js";
22
23
  var ContrastText = /*#__PURE__*/ function(ContrastText) {
23
24
  ContrastText["LIGHT"] = "rgba(0, 0, 0, 0.87)";
24
25
  ContrastText["DARK"] = "#FFFFFF";
@@ -301,6 +302,8 @@ function addShadeVariants(paletteColor, tonalOffset) {
301
302
  // After the shade repair, because both hover slots start from `dark` and
302
303
  // have to see the value that ships.
303
304
  ensureHoverShades(theme, themeOptions == null ? void 0 : themeOptions.palette);
305
+ // Last of the palette passes, so the shades they add are paths too.
306
+ addPalettePathColorVariants(theme);
304
307
  theme = responsiveFontSizes(theme, _extends({
305
308
  // Override to include `xs` and `xl` - default: ['sm', 'md', 'lg']
306
309
  breakpoints: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/shared/ui/theme/src/lib/util/create-responsive-theme.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2024 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CssVarsThemeOptions,\n extendTheme as muiExtendTheme,\n} from '@mui/material/styles'\nimport {\n alpha,\n createTheme,\n darken,\n getContrastRatio,\n lighten,\n type PaletteColor,\n type PaletteOptions,\n responsiveFontSizes,\n type Theme,\n type ThemeOptions,\n} from '../../vendor/mui'\nimport {\n ACCENT_HOVER_FILL,\n ACCENT_HOVER_TEXT,\n hoverFillShade,\n inkOnFill,\n} from './accent-text'\nimport {\n accessibleShade,\n contrastRatio,\n meetsContrast,\n type ShadeDirection,\n} from './accessible-shade'\n\nenum ContrastText {\n LIGHT = 'rgba(0, 0, 0, 0.87)',\n DARK = '#FFFFFF',\n}\n\ntype TonalOffset = number | { light?: number; dark?: number }\n\nfunction resolveTonalOffsets(tonalOffset: TonalOffset | undefined) {\n const offsetObj = typeof tonalOffset === 'number' ? undefined : tonalOffset\n const offsetNum = typeof tonalOffset === 'number' ? tonalOffset : undefined\n return {\n light: offsetObj?.light ?? offsetNum ?? 0.2,\n dark: offsetObj?.dark ?? (offsetNum ?? 0.2) * 1.5,\n }\n}\n\nfunction getContrastTextColor(background: string, contrastThreshold: number) {\n return getContrastRatio(background, ContrastText.DARK) >= (contrastThreshold ?? 3)\n ? ContrastText.DARK\n : ContrastText.LIGHT\n}\nfunction addShade(paletteColor: PaletteColor, shade: string, variant: string | undefined, tonalOffset: TonalOffset) {\n // Custom palette colors (tertiary, surface) are optional in host themes.\n if (!paletteColor?.main) return\n const { light: tonalOffsetLight, dark: tonalOffsetDark } =\n resolveTonalOffsets(tonalOffset)\n const indexed = paletteColor as unknown as Record<string, string>\n\n if (!indexed[shade]) {\n // eslint-disable-next-line no-prototype-builtins\n if (paletteColor.hasOwnProperty(variant)) {\n indexed[shade] = indexed[variant]\n } else if (shade === 'light') {\n paletteColor.light = lighten(paletteColor.main, tonalOffsetLight)\n } else if (shade === 'dark') {\n paletteColor.dark = darken(paletteColor.main, tonalOffsetDark)\n } else if (shade === 'contrastText') {\n paletteColor.contrastText = getContrastTextColor(\n paletteColor.main,\n tonalOffsetDark,\n )\n }\n }\n}\nfunction addShadeVariants(paletteColor: PaletteColor, tonalOffset?: TonalOffset) {\n addShade(paletteColor, 'dark', undefined, tonalOffset)\n addShade(paletteColor, 'light', undefined, tonalOffset)\n addShade(paletteColor, 'contrastText', undefined, tonalOffset)\n}\n\n/**\n * Colour families whose shades act as FOREGROUNDS — the `dark` slot carries\n * \"accessible accent text\" (AGL-1293 put the marketing brand blue there), so\n * its derivation must clear AA against the scheme's real backgrounds.\n *\n * `surface` is deliberately absent: its `light`/`dark` are surface STEPS\n * (panel fills, borders — see the designer's box styler), and walking them to\n * text contrast would repaint layout chrome, not fix any text.\n */\nconst FOREGROUND_COLOR_KEYS = [\n 'primary',\n 'secondary',\n 'tertiary',\n 'error',\n 'warning',\n 'info',\n 'success',\n] as const\n\n/** `contrastText` IS a text pairing wherever it lives, so `surface` joins here. */\nconst CONTRAST_TEXT_COLOR_KEYS = [...FOREGROUND_COLOR_KEYS, 'surface'] as const\n\n/**\n * Post-`createTheme` pass making DERIVED shades scheme- and AA-aware\n * (AGL-1297). Fixed tonal offsets derive `dark = darken(main, 0.3)` no\n * matter the scheme, which (a) misses 4.5:1 on real off-white surfaces and\n * (b) points the wrong way entirely in dark mode, where the accessible\n * direction for a foreground shade is LIGHTER.\n *\n * Invariants:\n * - Only slots ABSENT from the caller's `palette` input are ever touched;\n * an explicitly authored shade passes through byte-identical (the\n * marketing host's hand-set `primary.dark` values depend on this).\n * - A derived value that already clears 4.5:1 against both\n * `background.default` and `background.paper` is kept byte-identical, so\n * themes that were fine yesterday do not shift.\n * - A failing derived `dark` is re-seeded at the tonal offset from `main`\n * in the scheme's foreground direction (darken in light, lighten in\n * dark), then walked in HSL lightness until it clears the bar.\n * - A light-scheme `light` is a background TINT — its ramp direction points\n * away from the text bar by design — so it keeps the tonal derivation.\n * In dark schemes `light` is foreground-capable and gets the same walk.\n * - Derived `contrastText` keeps the threshold choice unless that pairing\n * is below 4.5:1 against `main`; then it walks toward the pole with more\n * contrast headroom.\n */\nfunction ensureAccessibleShades(\n theme: Theme,\n inputPalette: PaletteOptions | undefined,\n) {\n const { palette } = theme\n const backgrounds = [\n palette.background?.default,\n palette.background?.paper,\n ].filter((background): background is string => typeof background === 'string')\n if (!backgrounds.length) return\n const mode: 'light' | 'dark' = palette.mode === 'dark' ? 'dark' : 'light'\n const foregroundDirection: ShadeDirection =\n mode === 'dark' ? 'lighten' : 'darken'\n const tonalOffsetDark = resolveTonalOffsets(palette.tonalOffset).dark\n const providedColors = inputPalette as\n | Record<string, unknown>\n | undefined\n\n for (const key of CONTRAST_TEXT_COLOR_KEYS) {\n const color = (palette as unknown as Record<string, PaletteColor>)[key]\n if (!color || typeof color.main !== 'string') continue\n const provided = providedColors?.[key]\n // A ColorPartial ramp (`{ 50…900 }`) is an author-owned scale — MUI maps\n // its shades straight across, so nothing in it counts as derived.\n if (provided && typeof provided === 'object' && !('main' in provided)) {\n continue\n }\n // Read with brackets, not dots: these keys come from an index signature,\n // and `json-editor` compiles this file under\n // `noPropertyAccessFromIndexSignature` (paths resolve to source, so a\n // consumer's flags check its dependencies). Dot access reds that build\n // while this project's own stays green — AGL-1323.\n const explicit = (provided ?? {}) as Record<string, unknown>\n const isForeground = (FOREGROUND_COLOR_KEYS as readonly string[]).includes(\n key,\n )\n\n try {\n if (\n isForeground &&\n !explicit['dark'] &&\n typeof color.dark === 'string' &&\n !meetsContrast(color.dark, backgrounds)\n ) {\n const seed =\n mode === 'dark' ? lighten(color.main, tonalOffsetDark) : color.dark\n color.dark = accessibleShade(seed, backgrounds, foregroundDirection)\n }\n if (\n isForeground &&\n mode === 'dark' &&\n !explicit['light'] &&\n typeof color.light === 'string' &&\n !meetsContrast(color.light, backgrounds)\n ) {\n color.light = accessibleShade(color.light, backgrounds, 'lighten')\n }\n if (\n !explicit['contrastText'] &&\n typeof color.contrastText === 'string' &&\n !meetsContrast(color.contrastText, [color.main])\n ) {\n const textDirection: ShadeDirection =\n contrastRatio('#fff', color.main) >= contrastRatio('#000', color.main)\n ? 'lighten'\n : 'darken'\n color.contrastText = accessibleShade(\n color.contrastText,\n [color.main],\n textDirection,\n )\n }\n } catch {\n // Unparseable colour (CSS variable, color-mix()): leave the derived\n // value alone rather than failing theme creation.\n }\n }\n}\n\n/**\n * Post-`createTheme` pass giving every palette color a defined HOVER\n * (AGL-3465): `palette[color].hover`, the fill ({@link ACCENT_HOVER_FILL}),\n * and `palette[color].hoverText`, the label ({@link ACCENT_HOVER_TEXT}).\n * The `MuiButton` and `MuiFab` overrides read both.\n *\n * - **The fill.** MUI fills a hovered contained Button and Fab with\n * `palette[color].dark`, which this theme uses as the accent-as-TEXT\n * shade: lighter than `main` in a dark scheme, so a white label on it\n * sinks to ~2:1. Every entry with a string `main` and `contrastText` gets\n * one — the built-in accents, `tertiary`, `surface`, and any custom color\n * a palette adds — so a color a component can be asked to wear always has\n * a hover that carries its own ink at AA.\n * - **The label.** A hovered text or outlined Button keeps `dark` as its\n * label and lays `main` at `action.hoverOpacity` under it. Foreground\n * colors get `dark` walked in the scheme's foreground direction until it\n * clears AA on that wash over both `background.default` and\n * `background.paper`; it stays `dark`, byte-identical, wherever `dark`\n * already does. `surface` gets none: its `dark` is a surface step, not\n * text, so it has no label to protect.\n *\n * A slot the caller authored passes through untouched.\n */\nfunction ensureHoverShades(\n theme: Theme,\n inputPalette: PaletteOptions | undefined,\n) {\n const palette = theme.palette as unknown as Record<string, unknown>\n const providedColors = inputPalette as Record<string, unknown> | undefined\n const tonalOffsetDark = resolveTonalOffsets(theme.palette.tonalOffset).dark\n const foregroundDirection: ShadeDirection =\n theme.palette.mode === 'dark' ? 'lighten' : 'darken'\n const backgrounds = [\n theme.palette.background?.default,\n theme.palette.background?.paper,\n ].filter((background): background is string => typeof background === 'string')\n const hoverOpacity = theme.palette.action?.hoverOpacity ?? 0\n\n for (const [key, value] of Object.entries(palette)) {\n if (!value || typeof value !== 'object') continue\n const color = value as Record<string, unknown>\n const { main, dark, contrastText } = color\n if (typeof main !== 'string' || typeof contrastText !== 'string') continue\n const provided = (providedColors?.[key] ?? {}) as Record<string, unknown>\n try {\n if (typeof provided[ACCENT_HOVER_FILL] !== 'string') {\n color[ACCENT_HOVER_FILL] = hoverFillShade(\n {\n main,\n contrastText,\n dark: typeof dark === 'string' ? dark : undefined,\n },\n tonalOffsetDark,\n )\n }\n if (\n typeof provided[ACCENT_HOVER_TEXT] !== 'string' &&\n (FOREGROUND_COLOR_KEYS as readonly string[]).includes(key) &&\n typeof dark === 'string' &&\n backgrounds.length\n ) {\n const wash = alpha(main, hoverOpacity)\n color[ACCENT_HOVER_TEXT] = accessibleShade(\n dark,\n backgrounds.map((background) => inkOnFill(wash, background)),\n foregroundDirection,\n )\n }\n } catch {\n // Unparseable colour (CSS variable, color-mix()): no slot, so the\n // component overrides fall back to MUI's own hover for this color.\n }\n }\n}\n\n/**\n * MUI's own default `responsiveFontSizes` variant list, spelled out because\n * passing `variants` replaces it rather than extending it.\n */\nconst RAMPED_MUI_VARIANTS = [\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'subtitle1',\n 'subtitle2',\n 'body1',\n 'body2',\n 'caption',\n 'button',\n 'overline',\n] as const\n\n/**\n * The brand's custom display rungs, which MUI cannot know about.\n *\n * Only variants whose size genuinely needs to shrink belong here. `lede`,\n * `bodyCompact` and `micro` are body-scale text that reads the same at every\n * width and are deliberately absent.\n */\nconst RAMPED_DISPLAY_VARIANTS = ['displayXl'] as const\n\nexport type CreateResponsiveThemeOptions = {\n themeOptions?: ThemeOptions\n responsiveFontSizesOptions?: Parameters<typeof responsiveFontSizes>[1]\n}\n\n/**\n * START EXAMPLE – OVERRIDE DEFAULT PROPS ↓\n * ⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄\n * ```typescript\n * const theme = createMuiTheme({\n * props: {\n * // Name of the component ⚛️\n * MuiButtonBase: {\n * // The default props to change\n * disableRipple: true, // No more ripple, on the whole application 💣!\n * },\n * },\n * })\n * ```\n * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n * END EXAMPLE – OVERRIDE DEFAULT PROPS ↑\n *\n * START EXAMPLE – OVERRIDE DEFAULT STYLES ↓\n * ⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄\n * ```typescript\n * const theme = createMuiTheme({\n * overrides: {\n * // Style sheet name ⚛️\n * MuiButton: {\n * // Name of the rule\n * text: {\n * // Some CSS\n * color: 'white',\n * },\n * },\n * MuiCssBaseline: {\n * '@global': {\n * html: {\n * WebkitFontSmoothing: 'auto',\n * },\n * },\n * },\n * },\n * })\n * ```\n * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n * END EXAMPLE – OVERRIDE DEFAULT STYLES ↑\n *\n * @param {ThemeOptions} options\n * @returns {Theme}\n */\nexport function createResponsiveTheme(\n options: CreateResponsiveThemeOptions,\n): Theme {\n const { themeOptions, responsiveFontSizesOptions } = options\n let theme = createTheme(themeOptions)\n addShadeVariants(theme.palette.tertiary, theme.palette.tonalOffset)\n addShadeVariants(theme.palette.surface, theme.palette.tonalOffset)\n // `tint` is deliberately absent from BOTH shade passes (AGL-1244). It is a\n // group of string leaves rather than a PaletteColor — no `main` to ramp\n // from, no `contrastText` to pair — so `addShadeVariants` would no-op and\n // `ensureAccessibleShades` (which keys off `CONTRAST_TEXT_COLOR_KEYS`) never\n // sees it. Both correct: a 90%-desaturated wash is authored, not derived,\n // and walking it to a text-contrast bar would repaint the fill.\n // Scheme- and AA-aware repair of DERIVED shades only (AGL-1297); explicit\n // palette values pass through byte-identical.\n ensureAccessibleShades(theme, themeOptions?.palette)\n // After the shade repair, because both hover slots start from `dark` and\n // have to see the value that ships.\n ensureHoverShades(theme, themeOptions?.palette)\n\n theme = responsiveFontSizes(theme, {\n // Override to include `xs` and `xl` - default: ['sm', 'md', 'lg']\n breakpoints: ['xs', 'sm', 'md', 'lg', 'xl'],\n // MUI only ramps the variants it ships, so a CUSTOM display variant would\n // keep its desktop size on a phone — `displayXl` at 72px on a 375px\n // screen. Passing `variants` REPLACES MUI's default list, so the defaults\n // are spelled out here and ours appended; drop one and that variant\n // silently stops scaling.\n variants: [...RAMPED_MUI_VARIANTS, ...RAMPED_DISPLAY_VARIANTS],\n ...responsiveFontSizesOptions,\n })\n\n return theme\n}\n\nexport function createResponsiveCssVarTheme(\n light: Theme,\n dark: Theme,\n options?: CssVarsThemeOptions,\n) {\n const { palette: lightPalette, ...lightTheme } = light\n const { palette: darkPalette } = dark\n\n return muiExtendTheme({\n ...lightTheme,\n // Allow setMode() to work by driving the color scheme via a CSS class on\n // <html> instead of the OS-level @media query (the default 'media' selector\n // makes setMode() a no-op because media queries can't be overridden in JS).\n colorSchemeSelector: 'class',\n ...options,\n colorSchemes: {\n ...options?.colorSchemes,\n light: { palette: lightPalette, ...((options?.colorSchemes?.light ?? {}) as object) },\n dark: { palette: darkPalette, ...((options?.colorSchemes?.dark ?? {}) as object) },\n },\n })\n}\n\nexport default createResponsiveTheme\n"],"names":["extendTheme","muiExtendTheme","alpha","createTheme","darken","getContrastRatio","lighten","responsiveFontSizes","ACCENT_HOVER_FILL","ACCENT_HOVER_TEXT","hoverFillShade","inkOnFill","accessibleShade","contrastRatio","meetsContrast","ContrastText","resolveTonalOffsets","tonalOffset","offsetObj","undefined","offsetNum","light","dark","getContrastTextColor","background","contrastThreshold","addShade","paletteColor","shade","variant","main","tonalOffsetLight","tonalOffsetDark","indexed","hasOwnProperty","contrastText","addShadeVariants","FOREGROUND_COLOR_KEYS","CONTRAST_TEXT_COLOR_KEYS","ensureAccessibleShades","theme","inputPalette","palette","backgrounds","default","paper","filter","length","mode","foregroundDirection","providedColors","key","color","provided","explicit","isForeground","includes","seed","textDirection","ensureHoverShades","hoverOpacity","action","value","Object","entries","wash","map","RAMPED_MUI_VARIANTS","RAMPED_DISPLAY_VARIANTS","createResponsiveTheme","options","themeOptions","responsiveFontSizesOptions","tertiary","surface","breakpoints","variants","createResponsiveCssVarTheme","lightPalette","lightTheme","darkPalette","colorSchemeSelector","colorSchemes"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../../libs/shared/ui/theme/src/lib/util/create-responsive-theme.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2024 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CssVarsThemeOptions,\n extendTheme as muiExtendTheme,\n} from '@mui/material/styles'\nimport {\n alpha,\n createTheme,\n darken,\n getContrastRatio,\n lighten,\n type PaletteColor,\n type PaletteOptions,\n responsiveFontSizes,\n type Theme,\n type ThemeOptions,\n} from '../../vendor/mui'\nimport {\n ACCENT_HOVER_FILL,\n ACCENT_HOVER_TEXT,\n hoverFillShade,\n inkOnFill,\n} from './accent-text'\nimport {\n accessibleShade,\n contrastRatio,\n meetsContrast,\n type ShadeDirection,\n} from './accessible-shade'\nimport { addPalettePathColorVariants } from './palette-path-colors'\n\nenum ContrastText {\n LIGHT = 'rgba(0, 0, 0, 0.87)',\n DARK = '#FFFFFF',\n}\n\ntype TonalOffset = number | { light?: number; dark?: number }\n\nfunction resolveTonalOffsets(tonalOffset: TonalOffset | undefined) {\n const offsetObj = typeof tonalOffset === 'number' ? undefined : tonalOffset\n const offsetNum = typeof tonalOffset === 'number' ? tonalOffset : undefined\n return {\n light: offsetObj?.light ?? offsetNum ?? 0.2,\n dark: offsetObj?.dark ?? (offsetNum ?? 0.2) * 1.5,\n }\n}\n\nfunction getContrastTextColor(background: string, contrastThreshold: number) {\n return getContrastRatio(background, ContrastText.DARK) >= (contrastThreshold ?? 3)\n ? ContrastText.DARK\n : ContrastText.LIGHT\n}\nfunction addShade(paletteColor: PaletteColor, shade: string, variant: string | undefined, tonalOffset: TonalOffset) {\n // Custom palette colors (tertiary, surface) are optional in host themes.\n if (!paletteColor?.main) return\n const { light: tonalOffsetLight, dark: tonalOffsetDark } =\n resolveTonalOffsets(tonalOffset)\n const indexed = paletteColor as unknown as Record<string, string>\n\n if (!indexed[shade]) {\n // eslint-disable-next-line no-prototype-builtins\n if (paletteColor.hasOwnProperty(variant)) {\n indexed[shade] = indexed[variant]\n } else if (shade === 'light') {\n paletteColor.light = lighten(paletteColor.main, tonalOffsetLight)\n } else if (shade === 'dark') {\n paletteColor.dark = darken(paletteColor.main, tonalOffsetDark)\n } else if (shade === 'contrastText') {\n paletteColor.contrastText = getContrastTextColor(\n paletteColor.main,\n tonalOffsetDark,\n )\n }\n }\n}\nfunction addShadeVariants(paletteColor: PaletteColor, tonalOffset?: TonalOffset) {\n addShade(paletteColor, 'dark', undefined, tonalOffset)\n addShade(paletteColor, 'light', undefined, tonalOffset)\n addShade(paletteColor, 'contrastText', undefined, tonalOffset)\n}\n\n/**\n * Colour families whose shades act as FOREGROUNDS — the `dark` slot carries\n * \"accessible accent text\" (AGL-1293 put the marketing brand blue there), so\n * its derivation must clear AA against the scheme's real backgrounds.\n *\n * `surface` is deliberately absent: its `light`/`dark` are surface STEPS\n * (panel fills, borders — see the designer's box styler), and walking them to\n * text contrast would repaint layout chrome, not fix any text.\n */\nconst FOREGROUND_COLOR_KEYS = [\n 'primary',\n 'secondary',\n 'tertiary',\n 'error',\n 'warning',\n 'info',\n 'success',\n] as const\n\n/** `contrastText` IS a text pairing wherever it lives, so `surface` joins here. */\nconst CONTRAST_TEXT_COLOR_KEYS = [...FOREGROUND_COLOR_KEYS, 'surface'] as const\n\n/**\n * Post-`createTheme` pass making DERIVED shades scheme- and AA-aware\n * (AGL-1297). Fixed tonal offsets derive `dark = darken(main, 0.3)` no\n * matter the scheme, which (a) misses 4.5:1 on real off-white surfaces and\n * (b) points the wrong way entirely in dark mode, where the accessible\n * direction for a foreground shade is LIGHTER.\n *\n * Invariants:\n * - Only slots ABSENT from the caller's `palette` input are ever touched;\n * an explicitly authored shade passes through byte-identical (the\n * marketing host's hand-set `primary.dark` values depend on this).\n * - A derived value that already clears 4.5:1 against both\n * `background.default` and `background.paper` is kept byte-identical, so\n * themes that were fine yesterday do not shift.\n * - A failing derived `dark` is re-seeded at the tonal offset from `main`\n * in the scheme's foreground direction (darken in light, lighten in\n * dark), then walked in HSL lightness until it clears the bar.\n * - A light-scheme `light` is a background TINT — its ramp direction points\n * away from the text bar by design — so it keeps the tonal derivation.\n * In dark schemes `light` is foreground-capable and gets the same walk.\n * - Derived `contrastText` keeps the threshold choice unless that pairing\n * is below 4.5:1 against `main`; then it walks toward the pole with more\n * contrast headroom.\n */\nfunction ensureAccessibleShades(\n theme: Theme,\n inputPalette: PaletteOptions | undefined,\n) {\n const { palette } = theme\n const backgrounds = [\n palette.background?.default,\n palette.background?.paper,\n ].filter((background): background is string => typeof background === 'string')\n if (!backgrounds.length) return\n const mode: 'light' | 'dark' = palette.mode === 'dark' ? 'dark' : 'light'\n const foregroundDirection: ShadeDirection =\n mode === 'dark' ? 'lighten' : 'darken'\n const tonalOffsetDark = resolveTonalOffsets(palette.tonalOffset).dark\n const providedColors = inputPalette as\n | Record<string, unknown>\n | undefined\n\n for (const key of CONTRAST_TEXT_COLOR_KEYS) {\n const color = (palette as unknown as Record<string, PaletteColor>)[key]\n if (!color || typeof color.main !== 'string') continue\n const provided = providedColors?.[key]\n // A ColorPartial ramp (`{ 50…900 }`) is an author-owned scale — MUI maps\n // its shades straight across, so nothing in it counts as derived.\n if (provided && typeof provided === 'object' && !('main' in provided)) {\n continue\n }\n // Read with brackets, not dots: these keys come from an index signature,\n // and `json-editor` compiles this file under\n // `noPropertyAccessFromIndexSignature` (paths resolve to source, so a\n // consumer's flags check its dependencies). Dot access reds that build\n // while this project's own stays green — AGL-1323.\n const explicit = (provided ?? {}) as Record<string, unknown>\n const isForeground = (FOREGROUND_COLOR_KEYS as readonly string[]).includes(\n key,\n )\n\n try {\n if (\n isForeground &&\n !explicit['dark'] &&\n typeof color.dark === 'string' &&\n !meetsContrast(color.dark, backgrounds)\n ) {\n const seed =\n mode === 'dark' ? lighten(color.main, tonalOffsetDark) : color.dark\n color.dark = accessibleShade(seed, backgrounds, foregroundDirection)\n }\n if (\n isForeground &&\n mode === 'dark' &&\n !explicit['light'] &&\n typeof color.light === 'string' &&\n !meetsContrast(color.light, backgrounds)\n ) {\n color.light = accessibleShade(color.light, backgrounds, 'lighten')\n }\n if (\n !explicit['contrastText'] &&\n typeof color.contrastText === 'string' &&\n !meetsContrast(color.contrastText, [color.main])\n ) {\n const textDirection: ShadeDirection =\n contrastRatio('#fff', color.main) >= contrastRatio('#000', color.main)\n ? 'lighten'\n : 'darken'\n color.contrastText = accessibleShade(\n color.contrastText,\n [color.main],\n textDirection,\n )\n }\n } catch {\n // Unparseable colour (CSS variable, color-mix()): leave the derived\n // value alone rather than failing theme creation.\n }\n }\n}\n\n/**\n * Post-`createTheme` pass giving every palette color a defined HOVER\n * (AGL-3465): `palette[color].hover`, the fill ({@link ACCENT_HOVER_FILL}),\n * and `palette[color].hoverText`, the label ({@link ACCENT_HOVER_TEXT}).\n * The `MuiButton` and `MuiFab` overrides read both.\n *\n * - **The fill.** MUI fills a hovered contained Button and Fab with\n * `palette[color].dark`, which this theme uses as the accent-as-TEXT\n * shade: lighter than `main` in a dark scheme, so a white label on it\n * sinks to ~2:1. Every entry with a string `main` and `contrastText` gets\n * one — the built-in accents, `tertiary`, `surface`, and any custom color\n * a palette adds — so a color a component can be asked to wear always has\n * a hover that carries its own ink at AA.\n * - **The label.** A hovered text or outlined Button keeps `dark` as its\n * label and lays `main` at `action.hoverOpacity` under it. Foreground\n * colors get `dark` walked in the scheme's foreground direction until it\n * clears AA on that wash over both `background.default` and\n * `background.paper`; it stays `dark`, byte-identical, wherever `dark`\n * already does. `surface` gets none: its `dark` is a surface step, not\n * text, so it has no label to protect.\n *\n * A slot the caller authored passes through untouched.\n */\nfunction ensureHoverShades(\n theme: Theme,\n inputPalette: PaletteOptions | undefined,\n) {\n const palette = theme.palette as unknown as Record<string, unknown>\n const providedColors = inputPalette as Record<string, unknown> | undefined\n const tonalOffsetDark = resolveTonalOffsets(theme.palette.tonalOffset).dark\n const foregroundDirection: ShadeDirection =\n theme.palette.mode === 'dark' ? 'lighten' : 'darken'\n const backgrounds = [\n theme.palette.background?.default,\n theme.palette.background?.paper,\n ].filter((background): background is string => typeof background === 'string')\n const hoverOpacity = theme.palette.action?.hoverOpacity ?? 0\n\n for (const [key, value] of Object.entries(palette)) {\n if (!value || typeof value !== 'object') continue\n const color = value as Record<string, unknown>\n const { main, dark, contrastText } = color\n if (typeof main !== 'string' || typeof contrastText !== 'string') continue\n const provided = (providedColors?.[key] ?? {}) as Record<string, unknown>\n try {\n if (typeof provided[ACCENT_HOVER_FILL] !== 'string') {\n color[ACCENT_HOVER_FILL] = hoverFillShade(\n {\n main,\n contrastText,\n dark: typeof dark === 'string' ? dark : undefined,\n },\n tonalOffsetDark,\n )\n }\n if (\n typeof provided[ACCENT_HOVER_TEXT] !== 'string' &&\n (FOREGROUND_COLOR_KEYS as readonly string[]).includes(key) &&\n typeof dark === 'string' &&\n backgrounds.length\n ) {\n const wash = alpha(main, hoverOpacity)\n color[ACCENT_HOVER_TEXT] = accessibleShade(\n dark,\n backgrounds.map((background) => inkOnFill(wash, background)),\n foregroundDirection,\n )\n }\n } catch {\n // Unparseable colour (CSS variable, color-mix()): no slot, so the\n // component overrides fall back to MUI's own hover for this color.\n }\n }\n}\n\n/**\n * MUI's own default `responsiveFontSizes` variant list, spelled out because\n * passing `variants` replaces it rather than extending it.\n */\nconst RAMPED_MUI_VARIANTS = [\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'subtitle1',\n 'subtitle2',\n 'body1',\n 'body2',\n 'caption',\n 'button',\n 'overline',\n] as const\n\n/**\n * The brand's custom display rungs, which MUI cannot know about.\n *\n * Only variants whose size genuinely needs to shrink belong here. `lede`,\n * `bodyCompact` and `micro` are body-scale text that reads the same at every\n * width and are deliberately absent.\n */\nconst RAMPED_DISPLAY_VARIANTS = ['displayXl'] as const\n\nexport type CreateResponsiveThemeOptions = {\n themeOptions?: ThemeOptions\n responsiveFontSizesOptions?: Parameters<typeof responsiveFontSizes>[1]\n}\n\n/**\n * START EXAMPLE – OVERRIDE DEFAULT PROPS ↓\n * ⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄\n * ```typescript\n * const theme = createMuiTheme({\n * props: {\n * // Name of the component ⚛️\n * MuiButtonBase: {\n * // The default props to change\n * disableRipple: true, // No more ripple, on the whole application 💣!\n * },\n * },\n * })\n * ```\n * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n * END EXAMPLE – OVERRIDE DEFAULT PROPS ↑\n *\n * START EXAMPLE – OVERRIDE DEFAULT STYLES ↓\n * ⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄\n * ```typescript\n * const theme = createMuiTheme({\n * overrides: {\n * // Style sheet name ⚛️\n * MuiButton: {\n * // Name of the rule\n * text: {\n * // Some CSS\n * color: 'white',\n * },\n * },\n * MuiCssBaseline: {\n * '@global': {\n * html: {\n * WebkitFontSmoothing: 'auto',\n * },\n * },\n * },\n * },\n * })\n * ```\n * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n * END EXAMPLE – OVERRIDE DEFAULT STYLES ↑\n *\n * @param {ThemeOptions} options\n * @returns {Theme}\n */\nexport function createResponsiveTheme(\n options: CreateResponsiveThemeOptions,\n): Theme {\n const { themeOptions, responsiveFontSizesOptions } = options\n let theme = createTheme(themeOptions)\n addShadeVariants(theme.palette.tertiary, theme.palette.tonalOffset)\n addShadeVariants(theme.palette.surface, theme.palette.tonalOffset)\n // `tint` is deliberately absent from BOTH shade passes (AGL-1244). It is a\n // group of string leaves rather than a PaletteColor — no `main` to ramp\n // from, no `contrastText` to pair — so `addShadeVariants` would no-op and\n // `ensureAccessibleShades` (which keys off `CONTRAST_TEXT_COLOR_KEYS`) never\n // sees it. Both correct: a 90%-desaturated wash is authored, not derived,\n // and walking it to a text-contrast bar would repaint the fill.\n // Scheme- and AA-aware repair of DERIVED shades only (AGL-1297); explicit\n // palette values pass through byte-identical.\n ensureAccessibleShades(theme, themeOptions?.palette)\n // After the shade repair, because both hover slots start from `dark` and\n // have to see the value that ships.\n ensureHoverShades(theme, themeOptions?.palette)\n // Last of the palette passes, so the shades they add are paths too.\n addPalettePathColorVariants(theme)\n\n theme = responsiveFontSizes(theme, {\n // Override to include `xs` and `xl` - default: ['sm', 'md', 'lg']\n breakpoints: ['xs', 'sm', 'md', 'lg', 'xl'],\n // MUI only ramps the variants it ships, so a CUSTOM display variant would\n // keep its desktop size on a phone — `displayXl` at 72px on a 375px\n // screen. Passing `variants` REPLACES MUI's default list, so the defaults\n // are spelled out here and ours appended; drop one and that variant\n // silently stops scaling.\n variants: [...RAMPED_MUI_VARIANTS, ...RAMPED_DISPLAY_VARIANTS],\n ...responsiveFontSizesOptions,\n })\n\n return theme\n}\n\nexport function createResponsiveCssVarTheme(\n light: Theme,\n dark: Theme,\n options?: CssVarsThemeOptions,\n) {\n const { palette: lightPalette, ...lightTheme } = light\n const { palette: darkPalette } = dark\n\n return muiExtendTheme({\n ...lightTheme,\n // Allow setMode() to work by driving the color scheme via a CSS class on\n // <html> instead of the OS-level @media query (the default 'media' selector\n // makes setMode() a no-op because media queries can't be overridden in JS).\n colorSchemeSelector: 'class',\n ...options,\n colorSchemes: {\n ...options?.colorSchemes,\n light: { palette: lightPalette, ...((options?.colorSchemes?.light ?? {}) as object) },\n dark: { palette: darkPalette, ...((options?.colorSchemes?.dark ?? {}) as object) },\n },\n })\n}\n\nexport default createResponsiveTheme\n"],"names":["extendTheme","muiExtendTheme","alpha","createTheme","darken","getContrastRatio","lighten","responsiveFontSizes","ACCENT_HOVER_FILL","ACCENT_HOVER_TEXT","hoverFillShade","inkOnFill","accessibleShade","contrastRatio","meetsContrast","addPalettePathColorVariants","ContrastText","resolveTonalOffsets","tonalOffset","offsetObj","undefined","offsetNum","light","dark","getContrastTextColor","background","contrastThreshold","addShade","paletteColor","shade","variant","main","tonalOffsetLight","tonalOffsetDark","indexed","hasOwnProperty","contrastText","addShadeVariants","FOREGROUND_COLOR_KEYS","CONTRAST_TEXT_COLOR_KEYS","ensureAccessibleShades","theme","inputPalette","palette","backgrounds","default","paper","filter","length","mode","foregroundDirection","providedColors","key","color","provided","explicit","isForeground","includes","seed","textDirection","ensureHoverShades","hoverOpacity","action","value","Object","entries","wash","map","RAMPED_MUI_VARIANTS","RAMPED_DISPLAY_VARIANTS","createResponsiveTheme","options","themeOptions","responsiveFontSizesOptions","tertiary","surface","breakpoints","variants","createResponsiveCssVarTheme","lightPalette","lightTheme","darkPalette","colorSchemeSelector","colorSchemes"],"mappings":";;AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAEEA,eAAeC,cAAc,QACxB,uBAAsB;AAC7B,SACEC,KAAK,EACLC,WAAW,EACXC,MAAM,EACNC,gBAAgB,EAChBC,OAAO,EAGPC,mBAAmB,QAGd,sBAAkB;AACzB,SACEC,iBAAiB,EACjBC,iBAAiB,EACjBC,cAAc,EACdC,SAAS,QACJ,mBAAe;AACtB,SACEC,eAAe,EACfC,aAAa,EACbC,aAAa,QAER,wBAAoB;AAC3B,SAASC,2BAA2B,QAAQ,2BAAuB;AAEnE,IAAA,AAAKC,sCAAAA;;;WAAAA;EAAAA;AAOL,SAASC,oBAAoBC,WAAoC;QAItDC;IAHT,MAAMA,YAAY,OAAOD,gBAAgB,WAAWE,YAAYF;IAChE,MAAMG,YAAY,OAAOH,gBAAgB,WAAWA,cAAcE;IAClE,OAAO;QACLE,KAAK,GAAEH,gBAAAA,6BAAAA,UAAWG,KAAK,oBAAID,qBAApBF,OAAiC;QACxCI,IAAI,WAAEJ,6BAAAA,UAAWI,IAAI,oBAAI,CAACF,oBAAAA,YAAa,OAAO;IAChD;AACF;AAEA,SAASG,qBAAqBC,UAAkB,EAAEC,iBAAyB;IACzE,OAAOrB,iBAAiBoB,2BAAmCC,4BAAAA,oBAAqB;AAGlF;AACA,SAASC,SAASC,YAA0B,EAAEC,KAAa,EAAEC,OAA2B,EAAEZ,WAAwB;IAChH,yEAAyE;IACzE,IAAI,EAACU,gCAAAA,aAAcG,IAAI,GAAE;IACzB,MAAM,EAAET,OAAOU,gBAAgB,EAAET,MAAMU,eAAe,EAAE,GACtDhB,oBAAoBC;IACtB,MAAMgB,UAAUN;IAEhB,IAAI,CAACM,OAAO,CAACL,MAAM,EAAE;QACnB,iDAAiD;QACjD,IAAID,aAAaO,cAAc,CAACL,UAAU;YACxCI,OAAO,CAACL,MAAM,GAAGK,OAAO,CAACJ,QAAQ;QACnC,OAAO,IAAID,UAAU,SAAS;YAC5BD,aAAaN,KAAK,GAAGhB,QAAQsB,aAAaG,IAAI,EAAEC;QAClD,OAAO,IAAIH,UAAU,QAAQ;YAC3BD,aAAaL,IAAI,GAAGnB,OAAOwB,aAAaG,IAAI,EAAEE;QAChD,OAAO,IAAIJ,UAAU,gBAAgB;YACnCD,aAAaQ,YAAY,GAAGZ,qBAC1BI,aAAaG,IAAI,EACjBE;QAEJ;IACF;AACF;AACA,SAASI,iBAAiBT,YAA0B,EAAEV,WAAyB;IAC7ES,SAASC,cAAc,QAAQR,WAAWF;IAC1CS,SAASC,cAAc,SAASR,WAAWF;IAC3CS,SAASC,cAAc,gBAAgBR,WAAWF;AACpD;AAEA;;;;;;;;CAQC,GACD,MAAMoB,wBAAwB;IAC5B;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,iFAAiF,GACjF,MAAMC,2BAA2B;OAAID;IAAuB;CAAU;AAEtE;;;;;;;;;;;;;;;;;;;;;;;CAuBC,GACD,SAASE,uBACPC,KAAY,EACZC,YAAwC;QAItCC,qBACAA;IAHF,MAAM,EAAEA,OAAO,EAAE,GAAGF;IACpB,MAAMG,cAAc;SAClBD,sBAAAA,QAAQlB,UAAU,qBAAlBkB,oBAAoBE,OAAO;SAC3BF,uBAAAA,QAAQlB,UAAU,qBAAlBkB,qBAAoBG,KAAK;KAC1B,CAACC,MAAM,CAAC,CAACtB,aAAqC,OAAOA,eAAe;IACrE,IAAI,CAACmB,YAAYI,MAAM,EAAE;IACzB,MAAMC,OAAyBN,QAAQM,IAAI,KAAK,SAAS,SAAS;IAClE,MAAMC,sBACJD,SAAS,SAAS,YAAY;IAChC,MAAMhB,kBAAkBhB,oBAAoB0B,QAAQzB,WAAW,EAAEK,IAAI;IACrE,MAAM4B,iBAAiBT;IAIvB,KAAK,MAAMU,OAAOb,yBAA0B;QAC1C,MAAMc,QAAQ,AAACV,OAAmD,CAACS,IAAI;QACvE,IAAI,CAACC,SAAS,OAAOA,MAAMtB,IAAI,KAAK,UAAU;QAC9C,MAAMuB,WAAWH,kCAAAA,cAAgB,CAACC,IAAI;QACtC,yEAAyE;QACzE,kEAAkE;QAClE,IAAIE,YAAY,OAAOA,aAAa,YAAY,CAAE,CAAA,UAAUA,QAAO,GAAI;YACrE;QACF;QACA,yEAAyE;QACzE,6CAA6C;QAC7C,sEAAsE;QACtE,uEAAuE;QACvE,mDAAmD;QACnD,MAAMC,WAAYD,mBAAAA,WAAY,CAAC;QAC/B,MAAME,eAAe,AAAClB,sBAA4CmB,QAAQ,CACxEL;QAGF,IAAI;YACF,IACEI,gBACA,CAACD,QAAQ,CAAC,OAAO,IACjB,OAAOF,MAAM9B,IAAI,KAAK,YACtB,CAACT,cAAcuC,MAAM9B,IAAI,EAAEqB,cAC3B;gBACA,MAAMc,OACJT,SAAS,SAAS3C,QAAQ+C,MAAMtB,IAAI,EAAEE,mBAAmBoB,MAAM9B,IAAI;gBACrE8B,MAAM9B,IAAI,GAAGX,gBAAgB8C,MAAMd,aAAaM;YAClD;YACA,IACEM,gBACAP,SAAS,UACT,CAACM,QAAQ,CAAC,QAAQ,IAClB,OAAOF,MAAM/B,KAAK,KAAK,YACvB,CAACR,cAAcuC,MAAM/B,KAAK,EAAEsB,cAC5B;gBACAS,MAAM/B,KAAK,GAAGV,gBAAgByC,MAAM/B,KAAK,EAAEsB,aAAa;YAC1D;YACA,IACE,CAACW,QAAQ,CAAC,eAAe,IACzB,OAAOF,MAAMjB,YAAY,KAAK,YAC9B,CAACtB,cAAcuC,MAAMjB,YAAY,EAAE;gBAACiB,MAAMtB,IAAI;aAAC,GAC/C;gBACA,MAAM4B,gBACJ9C,cAAc,QAAQwC,MAAMtB,IAAI,KAAKlB,cAAc,QAAQwC,MAAMtB,IAAI,IACjE,YACA;gBACNsB,MAAMjB,YAAY,GAAGxB,gBACnByC,MAAMjB,YAAY,EAClB;oBAACiB,MAAMtB,IAAI;iBAAC,EACZ4B;YAEJ;QACF,EAAE,eAAM;QACN,oEAAoE;QACpE,kDAAkD;QACpD;IACF;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;CAsBC,GACD,SAASC,kBACPnB,KAAY,EACZC,YAAwC;;QAQtCD,2BACAA,4BAEmBA;IATrB,MAAME,UAAUF,MAAME,OAAO;IAC7B,MAAMQ,iBAAiBT;IACvB,MAAMT,kBAAkBhB,oBAAoBwB,MAAME,OAAO,CAACzB,WAAW,EAAEK,IAAI;IAC3E,MAAM2B,sBACJT,MAAME,OAAO,CAACM,IAAI,KAAK,SAAS,YAAY;IAC9C,MAAML,cAAc;SAClBH,4BAAAA,MAAME,OAAO,CAAClB,UAAU,qBAAxBgB,0BAA0BI,OAAO;SACjCJ,6BAAAA,MAAME,OAAO,CAAClB,UAAU,qBAAxBgB,2BAA0BK,KAAK;KAChC,CAACC,MAAM,CAAC,CAACtB,aAAqC,OAAOA,eAAe;IACrE,MAAMoC,wBAAepB,wBAAAA,MAAME,OAAO,CAACmB,MAAM,qBAApBrB,sBAAsBoB,YAAY,mBAAI;IAE3D,KAAK,MAAM,CAACT,KAAKW,MAAM,IAAIC,OAAOC,OAAO,CAACtB,SAAU;;QAClD,IAAI,CAACoB,SAAS,OAAOA,UAAU,UAAU;QACzC,MAAMV,QAAQU;QACd,MAAM,EAAEhC,IAAI,EAAER,IAAI,EAAEa,YAAY,EAAE,GAAGiB;QACrC,IAAI,OAAOtB,SAAS,YAAY,OAAOK,iBAAiB,UAAU;QAClE,MAAMkB,oBAAYH,kCAAAA,cAAgB,CAACC,IAAI,oBAAI,CAAC;QAC5C,IAAI;YACF,IAAI,OAAOE,QAAQ,CAAC9C,kBAAkB,KAAK,UAAU;gBACnD6C,KAAK,CAAC7C,kBAAkB,GAAGE,eACzB;oBACEqB;oBACAK;oBACAb,MAAM,OAAOA,SAAS,WAAWA,OAAOH;gBAC1C,GACAa;YAEJ;YACA,IACE,OAAOqB,QAAQ,CAAC7C,kBAAkB,KAAK,YACvC,AAAC6B,sBAA4CmB,QAAQ,CAACL,QACtD,OAAO7B,SAAS,YAChBqB,YAAYI,MAAM,EAClB;gBACA,MAAMkB,OAAOhE,MAAM6B,MAAM8B;gBACzBR,KAAK,CAAC5C,kBAAkB,GAAGG,gBACzBW,MACAqB,YAAYuB,GAAG,CAAC,CAAC1C,aAAed,UAAUuD,MAAMzC,cAChDyB;YAEJ;QACF,EAAE,eAAM;QACN,kEAAkE;QAClE,mEAAmE;QACrE;IACF;AACF;AAEA;;;CAGC,GACD,MAAMkB,sBAAsB;IAC1B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED;;;;;;CAMC,GACD,MAAMC,0BAA0B;IAAC;CAAY;AAO7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6CC,GACD,OAAO,SAASC,sBACdC,OAAqC;IAErC,MAAM,EAAEC,YAAY,EAAEC,0BAA0B,EAAE,GAAGF;IACrD,IAAI9B,QAAQtC,YAAYqE;IACxBnC,iBAAiBI,MAAME,OAAO,CAAC+B,QAAQ,EAAEjC,MAAME,OAAO,CAACzB,WAAW;IAClEmB,iBAAiBI,MAAME,OAAO,CAACgC,OAAO,EAAElC,MAAME,OAAO,CAACzB,WAAW;IACjE,2EAA2E;IAC3E,wEAAwE;IACxE,0EAA0E;IAC1E,6EAA6E;IAC7E,0EAA0E;IAC1E,gEAAgE;IAChE,0EAA0E;IAC1E,8CAA8C;IAC9CsB,uBAAuBC,OAAO+B,gCAAAA,aAAc7B,OAAO;IACnD,yEAAyE;IACzE,oCAAoC;IACpCiB,kBAAkBnB,OAAO+B,gCAAAA,aAAc7B,OAAO;IAC9C,oEAAoE;IACpE5B,4BAA4B0B;IAE5BA,QAAQlC,oBAAoBkC,OAAO;QACjC,kEAAkE;QAClEmC,aAAa;YAAC;YAAM;YAAM;YAAM;YAAM;SAAK;QAC3C,0EAA0E;QAC1E,oEAAoE;QACpE,0EAA0E;QAC1E,oEAAoE;QACpE,0BAA0B;QAC1BC,UAAU;eAAIT;eAAwBC;SAAwB;OAC3DI;IAGL,OAAOhC;AACT;AAEA,OAAO,SAASqC,4BACdxD,KAAY,EACZC,IAAW,EACXgD,OAA6B;;QAcYA,uBACFA;IAbvC,MAAM,EAAE5B,SAASoC,YAAY,EAAiB,GAAGzD,OAAf0D,8CAAe1D;;;IACjD,MAAM,EAAEqB,SAASsC,WAAW,EAAE,GAAG1D;IAEjC,OAAOtB,eAAe,aACjB+E;QACH,yEAAyE;QACzE,4EAA4E;QAC5E,4EAA4E;QAC5EE,qBAAqB;OAClBX;QACHY,cAAc,aACTZ,2BAAAA,QAASY,YAAY;YACxB7D,OAAO;gBAAEqB,SAASoC;uBAAmBR,4BAAAA,wBAAAA,QAASY,YAAY,qBAArBZ,sBAAuBjD,KAAK,mBAAI,CAAC;YACtEC,MAAM;gBAAEoB,SAASsC;wBAAkBV,4BAAAA,yBAAAA,QAASY,YAAY,qBAArBZ,uBAAuBhD,IAAI,oBAAI,CAAC;;;AAGzE;AAEA,eAAe+C,sBAAqB"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { Theme } from '../../vendor/mui';
18
+ /** Every `<group>.<key>` path whose value in this palette is a color string. */
19
+ export declare function palettePathColors(palette: Theme['palette']): string[];
20
+ /**
21
+ * `<Typography color="text.secondary">`, and every other palette path, painted
22
+ * again. MUI 9's Typography no longer runs system props: its `color` matches
23
+ * only a palette name (`primary`) or `textPrimary`/`textSecondary`/
24
+ * `textDisabled`, and a path such as `text.secondary` is dropped, so the text
25
+ * takes its parent's color. Close to 2,500 places across the console and
26
+ * sites were written that way when MUI 6 read the path as a palette lookup;
27
+ * each path becomes a theme variant here instead, the one place every theme
28
+ * passes through. Variants the options already give MuiTypography come first,
29
+ * and a path one of them names is left to it.
30
+ */
31
+ export declare function addPalettePathColorVariants(theme: Theme): void;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ /**
17
+ * The palette groups a `color="<group>.<key>"` may name: every string leaf
18
+ * of each, read from the theme itself so a custom color (tertiary, surface)
19
+ * is covered the moment it exists.
20
+ */ const PALETTE_PATH_GROUPS = [
21
+ 'text',
22
+ 'primary',
23
+ 'secondary',
24
+ 'tertiary',
25
+ 'surface',
26
+ 'error',
27
+ 'warning',
28
+ 'info',
29
+ 'success',
30
+ 'grey',
31
+ 'common',
32
+ 'background',
33
+ 'action'
34
+ ];
35
+ /** Every `<group>.<key>` path whose value in this palette is a color string. */ export function palettePathColors(palette) {
36
+ const groups = palette;
37
+ return PALETTE_PATH_GROUPS.flatMap((group)=>{
38
+ var _groups_group;
39
+ return Object.entries((_groups_group = groups[group]) != null ? _groups_group : {}).filter(([, value])=>typeof value === 'string').map(([key])=>`${group}.${key}`);
40
+ });
41
+ }
42
+ /** A palette path's value, from the CSS variables where the theme has them. */ function readPalettePath(theme, path) {
43
+ var _ref;
44
+ var _theme_vars, _palette_group;
45
+ const [group, key] = path.split('.');
46
+ const palette = (_ref = (_theme_vars = theme.vars) == null ? void 0 : _theme_vars.palette) != null ? _ref : theme.palette;
47
+ const value = (_palette_group = palette[group]) == null ? void 0 : _palette_group[key];
48
+ return typeof value === 'string' ? value : undefined;
49
+ }
50
+ /**
51
+ * `<Typography color="text.secondary">`, and every other palette path, painted
52
+ * again. MUI 9's Typography no longer runs system props: its `color` matches
53
+ * only a palette name (`primary`) or `textPrimary`/`textSecondary`/
54
+ * `textDisabled`, and a path such as `text.secondary` is dropped, so the text
55
+ * takes its parent's color. Close to 2,500 places across the console and
56
+ * sites were written that way when MUI 6 read the path as a palette lookup;
57
+ * each path becomes a theme variant here instead, the one place every theme
58
+ * passes through. Variants the options already give MuiTypography come first,
59
+ * and a path one of them names is left to it.
60
+ */ export function addPalettePathColorVariants(theme) {
61
+ var _theme, _components, _components1, _MuiTypography, _typography_variants;
62
+ const components = (_components = (_theme = theme).components) != null ? _components : _theme.components = {};
63
+ const typography = (_MuiTypography = (_components1 = components).MuiTypography) != null ? _MuiTypography : _components1.MuiTypography = {};
64
+ const variants = [
65
+ ...(_typography_variants = typography.variants) != null ? _typography_variants : []
66
+ ];
67
+ const named = new Set(variants.map((variant)=>typeof variant.props === 'object' ? variant.props.color : undefined));
68
+ for (const path of palettePathColors(theme.palette)){
69
+ if (named.has(path)) continue;
70
+ variants.push({
71
+ // The path is not one of Typography's declared colors, which is the
72
+ // whole point: the type names the declared ones only.
73
+ props: {
74
+ color: path
75
+ },
76
+ // MUI hands a variant's style its own base theme type; the theme is ours.
77
+ style: ({ theme: current })=>({
78
+ color: readPalettePath(current, path)
79
+ })
80
+ });
81
+ }
82
+ typography.variants = variants;
83
+ }
84
+
85
+ //# sourceMappingURL=palette-path-colors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../libs/shared/ui/theme/src/lib/util/palette-path-colors.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Theme } from '../../vendor/mui'\n\n/**\n * The palette groups a `color=\"<group>.<key>\"` may name: every string leaf\n * of each, read from the theme itself so a custom color (tertiary, surface)\n * is covered the moment it exists.\n */\nconst PALETTE_PATH_GROUPS = [\n 'text',\n 'primary',\n 'secondary',\n 'tertiary',\n 'surface',\n 'error',\n 'warning',\n 'info',\n 'success',\n 'grey',\n 'common',\n 'background',\n 'action',\n] as const\n\n/** Every `<group>.<key>` path whose value in this palette is a color string. */\nexport function palettePathColors(palette: Theme['palette']): string[] {\n const groups = palette as unknown as Record<string, Record<string, unknown> | undefined>\n return PALETTE_PATH_GROUPS.flatMap((group) =>\n Object.entries(groups[group] ?? {})\n .filter(([, value]) => typeof value === 'string')\n .map(([key]) => `${group}.${key}`),\n )\n}\n\n/** A palette path's value, from the CSS variables where the theme has them. */\nfunction readPalettePath(theme: Theme, path: string): string | undefined {\n const [group, key] = path.split('.')\n const palette = (theme.vars?.palette ?? theme.palette) as unknown as Record<string, Record<string, unknown> | undefined>\n const value = palette[group]?.[key]\n return typeof value === 'string' ? value : undefined\n}\n\n/**\n * `<Typography color=\"text.secondary\">`, and every other palette path, painted\n * again. MUI 9's Typography no longer runs system props: its `color` matches\n * only a palette name (`primary`) or `textPrimary`/`textSecondary`/\n * `textDisabled`, and a path such as `text.secondary` is dropped, so the text\n * takes its parent's color. Close to 2,500 places across the console and\n * sites were written that way when MUI 6 read the path as a palette lookup;\n * each path becomes a theme variant here instead, the one place every theme\n * passes through. Variants the options already give MuiTypography come first,\n * and a path one of them names is left to it.\n */\nexport function addPalettePathColorVariants(theme: Theme): void {\n const components = (theme.components ??= {})\n const typography = (components.MuiTypography ??= {})\n const variants = [...(typography.variants ?? [])]\n const named = new Set(\n variants.map((variant) => (typeof variant.props === 'object' ? (variant.props as { color?: unknown }).color : undefined)),\n )\n for (const path of palettePathColors(theme.palette)) {\n if (named.has(path)) continue\n variants.push({\n // The path is not one of Typography's declared colors, which is the\n // whole point: the type names the declared ones only.\n props: { color: path as never },\n // MUI hands a variant's style its own base theme type; the theme is ours.\n style: ({ theme: current }) => ({ color: readPalettePath(current as unknown as Theme, path) }),\n })\n }\n typography.variants = variants\n}\n"],"names":["PALETTE_PATH_GROUPS","palettePathColors","palette","groups","flatMap","group","Object","entries","filter","value","map","key","readPalettePath","theme","path","split","vars","undefined","addPalettePathColorVariants","components","typography","MuiTypography","variants","named","Set","variant","props","color","has","push","style","current"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAID;;;;CAIC,GACD,MAAMA,sBAAsB;IAC1B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,8EAA8E,GAC9E,OAAO,SAASC,kBAAkBC,OAAyB;IACzD,MAAMC,SAASD;IACf,OAAOF,oBAAoBI,OAAO,CAAC,CAACC;YACnBF;eAAfG,OAAOC,OAAO,EAACJ,gBAAAA,MAAM,CAACE,MAAM,YAAbF,gBAAiB,CAAC,GAC9BK,MAAM,CAAC,CAAC,GAAGC,MAAM,GAAK,OAAOA,UAAU,UACvCC,GAAG,CAAC,CAAC,CAACC,IAAI,GAAK,GAAGN,MAAM,CAAC,EAAEM,KAAK;;AAEvC;AAEA,6EAA6E,GAC7E,SAASC,gBAAgBC,KAAY,EAAEC,IAAY;;QAEhCD,aACHX;IAFd,MAAM,CAACG,OAAOM,IAAI,GAAGG,KAAKC,KAAK,CAAC;IAChC,MAAMb,mBAAWW,cAAAA,MAAMG,IAAI,qBAAVH,YAAYX,OAAO,mBAAIW,MAAMX,OAAO;IACrD,MAAMO,SAAQP,iBAAAA,OAAO,CAACG,MAAM,qBAAdH,cAAgB,CAACS,IAAI;IACnC,OAAO,OAAOF,UAAU,WAAWA,QAAQQ;AAC7C;AAEA;;;;;;;;;;CAUC,GACD,OAAO,SAASC,4BAA4BL,KAAY;QAClCA,QAAAA,aACAM,cAAAA,gBACEC;IAFtB,MAAMD,cAAcN,cAAAA,CAAAA,SAAAA,OAAMM,UAAU,YAAhBN,cAAAA,OAAMM,UAAU,GAAK,CAAC;IAC1C,MAAMC,cAAcD,iBAAAA,CAAAA,eAAAA,YAAWE,aAAa,YAAxBF,iBAAAA,aAAWE,aAAa,GAAK,CAAC;IAClD,MAAMC,WAAW;YAAKF,uBAAAA,WAAWE,QAAQ,YAAnBF,uBAAuB,EAAE;KAAE;IACjD,MAAMG,QAAQ,IAAIC,IAChBF,SAASZ,GAAG,CAAC,CAACe,UAAa,OAAOA,QAAQC,KAAK,KAAK,WAAW,AAACD,QAAQC,KAAK,CAAyBC,KAAK,GAAGV;IAEhH,KAAK,MAAMH,QAAQb,kBAAkBY,MAAMX,OAAO,EAAG;QACnD,IAAIqB,MAAMK,GAAG,CAACd,OAAO;QACrBQ,SAASO,IAAI,CAAC;YACZ,oEAAoE;YACpE,sDAAsD;YACtDH,OAAO;gBAAEC,OAAOb;YAAc;YAC9B,0EAA0E;YAC1EgB,OAAO,CAAC,EAAEjB,OAAOkB,OAAO,EAAE,GAAM,CAAA;oBAAEJ,OAAOf,gBAAgBmB,SAA6BjB;gBAAM,CAAA;QAC9F;IACF;IACAM,WAAWE,QAAQ,GAAGA;AACxB"}