@carto/meridian-ds 4.4.1-alpha.fbe7378.320 → 5.0.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 +14 -2
  2. package/dist/components/index.cjs +82 -11
  3. package/dist/components/index.js +84 -13
  4. package/dist/metadata.json +3 -3
  5. package/dist/{palette-utils-BCQ0HY6h.js → palette-utils-BmPPGzZt.js} +5 -1
  6. package/dist/{palette-utils-m2Gb_Pd2.cjs → palette-utils-NhMBL9rx.cjs} +5 -1
  7. package/dist/theme/index.cjs +81 -53
  8. package/dist/theme/index.js +82 -54
  9. package/dist/types/components/Autocomplete/Autocomplete/Autocomplete.d.ts.map +1 -1
  10. package/dist/types/components/Autocomplete/Autocomplete/Autocomplete.stories.d.ts +1 -1
  11. package/dist/types/components/Autocomplete/Autocomplete/Autocomplete.stories.d.ts.map +1 -1
  12. package/dist/types/components/Autocomplete/AutocompleteList/AutocompleteList.d.ts.map +1 -1
  13. package/dist/types/components/Button/Button.d.ts +16 -4
  14. package/dist/types/components/Button/Button.d.ts.map +1 -1
  15. package/dist/types/components/Button/Button.stories.d.ts +3 -1
  16. package/dist/types/components/Button/Button.stories.d.ts.map +1 -1
  17. package/dist/types/components/DatePickers/types.d.ts +7 -1
  18. package/dist/types/components/DatePickers/types.d.ts.map +1 -1
  19. package/dist/types/components/Dialog/Dialog/Dialog.d.ts.map +1 -1
  20. package/dist/types/components/Dialog/Dialog/Dialog.stories.d.ts +5 -0
  21. package/dist/types/components/Dialog/Dialog/Dialog.stories.d.ts.map +1 -1
  22. package/dist/types/components/Dialog/DialogHeader/DialogHeader.stories.d.ts +10 -0
  23. package/dist/types/components/Dialog/DialogHeader/DialogHeader.stories.d.ts.map +1 -1
  24. package/dist/types/components/Dialog/DialogPaper/DialogPaper.d.ts.map +1 -1
  25. package/dist/types/components/IconButton/IconButton.d.ts.map +1 -1
  26. package/dist/types/components/Link/Link.d.ts +16 -4
  27. package/dist/types/components/Link/Link.d.ts.map +1 -1
  28. package/dist/types/components/Link/Link.stories.d.ts +3 -2
  29. package/dist/types/components/Link/Link.stories.d.ts.map +1 -1
  30. package/dist/types/components/List/ListSubheader/ListSubheader.d.ts.map +1 -1
  31. package/dist/types/components/Menu/MenuItem/MenuItem.d.ts +1 -1
  32. package/dist/types/components/Menu/MenuItem/MenuItem.d.ts.map +1 -1
  33. package/dist/types/components/SearchField/SearchField.d.ts.map +1 -1
  34. package/dist/types/components/SearchField/types.d.ts +2 -0
  35. package/dist/types/components/SearchField/types.d.ts.map +1 -1
  36. package/dist/types/components/SelectField/SelectField/SelectField.d.ts +1 -1
  37. package/dist/types/components/SelectField/SelectField/SelectField.d.ts.map +1 -1
  38. package/dist/types/components/SelectField/SelectField/SelectField.stories.d.ts +1 -1
  39. package/dist/types/components/SelectField/SelectField/SelectField.stories.d.ts.map +1 -1
  40. package/dist/types/components/Typography/Typography.d.ts +16 -4
  41. package/dist/types/components/Typography/Typography.d.ts.map +1 -1
  42. package/dist/types/components/Typography/Typography.stories.d.ts +7 -5
  43. package/dist/types/components/Typography/Typography.stories.d.ts.map +1 -1
  44. package/dist/types/components/UploadField/UploadField.d.ts.map +1 -1
  45. package/dist/types/theme/components/buttons.d.ts.map +1 -1
  46. package/dist/types/theme/components/date-pickers.d.ts.map +1 -1
  47. package/dist/types/theme/components/navigation.d.ts.map +1 -1
  48. package/dist/types/theme/components/stories/Divider.stories.d.ts +3 -22
  49. package/dist/types/theme/components/stories/Divider.stories.d.ts.map +1 -1
  50. package/dist/types/theme/tokens/TypographyTokens.stories.d.ts.map +1 -1
  51. package/dist/types/utils/palette-path.d.ts +4 -3
  52. package/dist/types/utils/palette-path.d.ts.map +1 -1
  53. package/dist/{utils-BkM2jqPv.js → utils-7LZAkgSl.js} +31 -29
  54. package/dist/{utils-DjaqQq9F.cjs → utils-DOVvVhN1.cjs} +30 -28
  55. package/dist/widgets/index.cjs +1 -1
  56. package/dist/widgets/index.js +1 -1
  57. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,8 +2,20 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
- - chore(deps): MUI v5 → v9 upgrade (integration branch) [sc-557186] [#485](https://github.com/CartoDB/meridian-ds/pull/485)
6
- - chore(deps): upgrade MUI core to v6 + prep peers/react-is [sc-563129] [#484](https://github.com/CartoDB/meridian-ds/pull/484)
5
+ ## 5.0
6
+
7
+ ### 5.0.0
8
+
9
+ - chore(deps): upgrade MUI core + MUI X from v5 to v9 [sc-557186] [#485](https://github.com/CartoDB/meridian-ds/pull/485), in three phases — v6 [#484](https://github.com/CartoDB/meridian-ds/pull/484), v7 [#505](https://github.com/CartoDB/meridian-ds/pull/505), v9 [#524](https://github.com/CartoDB/meridian-ds/pull/524).
10
+ - **BREAKING** chore(theme): dot-path palette colors are inert on MUI components — `color='text.secondary'` no longer resolves; move it to `sx`.
11
+ - **BREAKING** chore(fields): `InputProps` / `inputProps` are gone from every component inheriting `TextFieldProps`. Use `slotProps.input` or `slotProps.htmlInput`.
12
+ - **BREAKING** chore(Dialog): `PaperProps` removed — use `slotProps.paper`. The dialog role, `aria-label` and `data-*` now sit on the paper, so selectors keyed on `.MuiDialog-root` stop matching.
13
+ - **BREAKING** chore(Autocomplete): `renderTags` → `renderValue`, and `ListboxComponent` / `PaperComponent` / `MenuListProps` → `slots` / `slotProps`.
14
+ - **BREAKING** chore(MenuItem): `MenuItem` throws outside a `MenuList` or `Menu` — hand-rolled dropdown surfaces must wrap their rows.
15
+ - **BREAKING** chore(date-pickers): the field renders editable `role='spinbutton'` sections instead of a single `<input>`; `.MuiInputBase-root` and the `PickersYear` / `PickersMonth` wrappers no longer match; `DatePicker`'s `placeholder` is deprecated and reaches nobody. `AdapterDateFns` now requires date-fns v3/v4 — on v2, import `@mui/x-date-pickers/AdapterDateFnsV2`.
16
+ - **BREAKING** chore(icons): the filled `*Outline` icons are gone — rename to `*Outlined`.
17
+ - **BREAKING** chore(Divider): drop the `light` prop.
18
+ - **BREAKING** chore(theme): `cartoThemeOptions` is typed `ThemeOptions`, so its members are optional — read values from the exported `theme` instead.
7
19
 
8
20
  ## 4.0
9
21
 
@@ -3,11 +3,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
5
  const material = require("@mui/material");
6
- const paletteUtils = require("../palette-utils-m2Gb_Pd2.cjs");
6
+ const paletteUtils = require("../palette-utils-NhMBL9rx.cjs");
7
7
  const iconsMaterial = require("@mui/icons-material");
8
8
  const ArrowDown = require("../ArrowDown-84Oc8r9k.cjs");
9
9
  const ReactWindow = require("react-window");
10
- const utils = require("../utils-DjaqQq9F.cjs");
10
+ const utils = require("../utils-DOVvVhN1.cjs");
11
11
  const Search = require("../Search-BsaXrSzs.cjs");
12
12
  require("cartocolor");
13
13
  const reactCodemirror2 = require("react-codemirror2");
@@ -127,6 +127,7 @@ function _Button({
127
127
  );
128
128
  }
129
129
  const Button = React.forwardRef(_Button);
130
+ Button.displayName = "Button";
130
131
  const idCounter = {};
131
132
  function uniqueId(prefix = "$lodash$") {
132
133
  if (!idCounter[prefix]) {
@@ -432,11 +433,16 @@ function _SelectField({
432
433
  fullWidth,
433
434
  required,
434
435
  "aria-label": ariaLabel,
436
+ SelectDisplayProps,
435
437
  ...otherProps
436
438
  }, ref) {
437
439
  const isSmall = size === "small";
438
440
  const [defaultId] = React.useState(() => uniqueId("select-label-"));
439
441
  const ariaLabelledBy = label ? labelId ?? defaultId : void 0;
442
+ const [fallbackDisplayId] = React.useState(() => uniqueId("select-value-"));
443
+ const displayId = (SelectDisplayProps == null ? void 0 : SelectDisplayProps.id) ?? (name ? `mui-component-select-${name}` : fallbackDisplayId);
444
+ const isUnnamed = !ariaLabelledBy && !ariaLabel;
445
+ const selfLabelProps = isUnnamed ? { id: displayId, "aria-labelledby": displayId } : void 0;
440
446
  return /* @__PURE__ */ jsxRuntime.jsxs(
441
447
  material.FormControl,
442
448
  {
@@ -480,13 +486,18 @@ function _SelectField({
480
486
  ...otherProps,
481
487
  labelId: ariaLabelledBy,
482
488
  name,
489
+ SelectDisplayProps: { ...selfLabelProps, ...SelectDisplayProps },
483
490
  ref,
484
491
  size,
485
492
  fullWidth,
486
493
  displayEmpty: displayEmpty ?? !!placeholder,
487
494
  inputProps: {
488
495
  ...inputProps,
489
- "aria-label": ariaLabel
496
+ // Written only when set: an unconditional key means an *absent*
497
+ // `aria-label` prop overwrites one the caller put in `inputProps`.
498
+ // When both are given the dedicated prop still wins — it is the
499
+ // documented API, and that ranking is unchanged.
500
+ ...ariaLabel !== void 0 && { "aria-label": ariaLabel }
490
501
  },
491
502
  MenuProps: {
492
503
  ...menuProps,
@@ -986,6 +997,7 @@ function _Link({
986
997
  );
987
998
  }
988
999
  const Link = React.forwardRef(_Link);
1000
+ Link.displayName = "Link";
989
1001
  function _CircularProgress({
990
1002
  color = "primary",
991
1003
  size = 40,
@@ -1322,8 +1334,11 @@ const { FixedSizeList: FixedSizeList$1 } = ReactWindow__namespace;
1322
1334
  const List$1 = material.styled(material.MenuList, {
1323
1335
  // MenuList is a component, so emotion forwards every prop to it (unlike a
1324
1336
  // string tag, where invalid HTML attributes are dropped) — `hasFilters` would
1325
- // reach the underlying <ul>.
1326
- shouldForwardProp: (prop) => prop !== "hasFilters"
1337
+ // reach the underlying <ul>. `ownerState`/`theme`/`sx`/`as` mirror MUI's own
1338
+ // `slotShouldForwardProp`, which a custom `shouldForwardProp` replaces rather
1339
+ // than extends: as Autocomplete's `listbox` slot this receives the
1340
+ // Autocomplete's ownerState, which must not reach MenuList.
1341
+ shouldForwardProp: (prop) => !["ownerState", "theme", "sx", "as", "hasFilters"].includes(prop)
1327
1342
  })(({ theme, hasFilters }) => ({
1328
1343
  ...!hasFilters && {
1329
1344
  paddingTop: `${theme.spacing(1)} !important`
@@ -1623,7 +1638,14 @@ function _Autocomplete({
1623
1638
  slotProps: {
1624
1639
  ...slotProps,
1625
1640
  listbox: mergeSlotProps({
1626
- ownProps: { "aria-multiselectable": false },
1641
+ ownProps: {
1642
+ "aria-multiselectable": false,
1643
+ component: material.MenuList
1644
+ // `useAutocomplete`'s `singleRenderOption` emits Meridian MenuItems,
1645
+ // and on v9 a MenuItem throws without a MenuListContext. Set through
1646
+ // `component` rather than `slots.listbox`: swapping the slot would
1647
+ // drop the listbox's own styles (max-height/overflow) with it.
1648
+ },
1627
1649
  consumerProps: slotProps == null ? void 0 : slotProps.listbox
1628
1650
  })
1629
1651
  }
@@ -3313,7 +3335,25 @@ const dialogDimensionsBySize = {
3313
3335
  }
3314
3336
  };
3315
3337
  const DialogPaper = material.styled(material.Paper, {
3316
- shouldForwardProp: (prop) => !["fullScreen", "height", "width", "hasForm"].includes(prop)
3338
+ // `as` must stay with emotion: MUI renders the paper slot as
3339
+ // `<PaperSlot as={Paper} …>`, so forwarding `as` to Paper shadows a
3340
+ // consumer's `slotProps.paper.component` and a form dialog renders a div.
3341
+ //
3342
+ // `ownerState`/`theme`/`sx` mirror MUI's own `slotShouldForwardProp`, which a
3343
+ // custom `shouldForwardProp` replaces rather than extends. As the Dialog's
3344
+ // `paper` slot this receives the *Dialog's* ownerState; Paper spreads it over
3345
+ // its own, so `variant: 'elevation'` stops matching and neither the elevation
3346
+ // shadow nor the `outlined` border is emitted.
3347
+ shouldForwardProp: (prop) => ![
3348
+ "ownerState",
3349
+ "theme",
3350
+ "sx",
3351
+ "as",
3352
+ "fullScreen",
3353
+ "height",
3354
+ "width",
3355
+ "hasForm"
3356
+ ].includes(prop)
3317
3357
  })(
3318
3358
  ({
3319
3359
  fullScreen,
@@ -3325,6 +3365,22 @@ const DialogPaper = material.styled(material.Paper, {
3325
3365
  }) => ({
3326
3366
  "&.MuiPaper-root": {
3327
3367
  position: "relative",
3368
+ // MUI's Dialog paper styles are replaced, not composed, once this is the
3369
+ // `paper` slot — so carry the ones consumers depend on. Without
3370
+ // `overflowY` a fullScreen dialog cannot scroll and overflowing content is
3371
+ // unreachable.
3372
+ overflowY: "auto",
3373
+ outline: 0,
3374
+ // The focus trap focuses the paper when nothing inside autofocuses, and
3375
+ // Chromium treats that as `:focus-visible` — the global ring would frame
3376
+ // the whole dialog. It's a container, not a control.
3377
+ "&:focus-visible": {
3378
+ outline: "none !important"
3379
+ },
3380
+ "@media print": {
3381
+ overflowY: "visible",
3382
+ boxShadow: "none"
3383
+ },
3328
3384
  display: "flex",
3329
3385
  flexDirection: "column",
3330
3386
  margin: theme.spacing(5),
@@ -3431,6 +3487,7 @@ function _Dialog({
3431
3487
  hasForm,
3432
3488
  "aria-label": ariaLabel,
3433
3489
  "data-testid": dataTestId,
3490
+ slots,
3434
3491
  slotProps,
3435
3492
  ...props
3436
3493
  }, ref) {
@@ -3478,7 +3535,7 @@ function _Dialog({
3478
3535
  return /* @__PURE__ */ jsxRuntime.jsx(
3479
3536
  material.Dialog,
3480
3537
  {
3481
- slots: { paper: DialogPaper },
3538
+ slots: { ...slots, paper: DialogPaper },
3482
3539
  slotProps: {
3483
3540
  ...slotProps,
3484
3541
  paper: mergeSlotProps({
@@ -6467,6 +6524,7 @@ function _SearchField({
6467
6524
  size = "small",
6468
6525
  dense = false,
6469
6526
  slotProps,
6527
+ InputProps,
6470
6528
  startAdornment,
6471
6529
  endAdornment,
6472
6530
  onFocus,
@@ -6542,7 +6600,13 @@ function _SearchField({
6542
6600
  }
6543
6601
  )
6544
6602
  },
6545
- consumerProps: slotProps == null ? void 0 : slotProps.input
6603
+ // The deprecated `InputProps` feeds the same slot, ranked below
6604
+ // `slotProps.input` so the modern form wins. Without this it rode
6605
+ // `otherProps` onto the DOM once v9 stopped accepting it on TextField.
6606
+ consumerProps: mergeSlotProps({
6607
+ ownProps: InputProps ?? {},
6608
+ consumerProps: slotProps == null ? void 0 : slotProps.input
6609
+ })
6546
6610
  }),
6547
6611
  htmlInput: mergeSlotProps({
6548
6612
  ownProps: { role: "searchbox" },
@@ -7144,6 +7208,7 @@ function _UploadField({
7144
7208
  focused,
7145
7209
  nativeInputProps,
7146
7210
  "data-testid": dataTestId,
7211
+ slotProps,
7147
7212
  ...props
7148
7213
  }, ref) {
7149
7214
  const accept = _accept ?? DEFAULT_ACCEPT;
@@ -7176,7 +7241,13 @@ function _UploadField({
7176
7241
  dragOver,
7177
7242
  inProgress,
7178
7243
  hasFiles: Boolean(filesText),
7179
- slotProps: { input: inputEvents },
7244
+ slotProps: {
7245
+ ...slotProps,
7246
+ input: mergeSlotProps({
7247
+ ownProps: inputEvents,
7248
+ consumerProps: slotProps == null ? void 0 : slotProps.input
7249
+ })
7250
+ },
7180
7251
  buttonText,
7181
7252
  "data-testid": dataTestId
7182
7253
  }
@@ -7752,7 +7823,7 @@ function _ListSubheader({
7752
7823
  "data-disable-gutters": effectiveDisableGutters,
7753
7824
  "data-disable-padding": effectiveDisablePadding,
7754
7825
  children: /* @__PURE__ */ jsxRuntime.jsx(
7755
- material.Typography,
7826
+ paletteUtils.Typography,
7756
7827
  {
7757
7828
  ...mergeTypographyProps(
7758
7829
  DEFAULT_TYPOGRAPHY_PROPS,
@@ -1,13 +1,13 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import React, { forwardRef, useState, useRef, useEffect, useMemo, createElement, Fragment as Fragment$1, useCallback, useImperativeHandle, createContext, useContext } from "react";
3
- import { styled, Button as Button$1, CircularProgress as CircularProgress$1, Tooltip, Popper, Grow, Paper, ClickAwayListener, MenuList as MenuList$1, MenuItem, ButtonGroup as ButtonGroup$1, Box, TextField, InputAdornment, FormControl, InputLabel, FormHelperText, Select, Checkbox, Link as Link$1, ListItemText as ListItemText$1, IconButton as IconButton$1, ToggleButtonGroup as ToggleButtonGroup$1, Stack, Autocomplete as Autocomplete$1, Divider, ListItemIcon as ListItemIcon$1, createFilterOptions, alpha, useTheme, Toolbar as Toolbar$1, AppBar as AppBar$1, Dialog as Dialog$1, Chip as Chip$1, DialogTitle as DialogTitle$1, DialogContent as DialogContent$1, Fade, AlertTitle, Alert as Alert$2, DialogActions as DialogActions$1, Slide, Accordion, AccordionSummary, AccordionDetails, Avatar as Avatar$1, Menu as Menu$2, useMediaQuery, Portal, Snackbar as Snackbar$1, List as List$2, ListItemButton as ListItemButton$1, ListItem as ListItem$1, ListSubheader as ListSubheader$1, Typography as Typography$1, Popover } from "@mui/material";
3
+ import { styled, Button as Button$1, CircularProgress as CircularProgress$1, Tooltip, Popper, Grow, Paper, ClickAwayListener, MenuList as MenuList$1, MenuItem, ButtonGroup as ButtonGroup$1, Box, TextField, InputAdornment, FormControl, InputLabel, FormHelperText, Select, Checkbox, Link as Link$1, ListItemText as ListItemText$1, IconButton as IconButton$1, ToggleButtonGroup as ToggleButtonGroup$1, Stack, Autocomplete as Autocomplete$1, Divider, ListItemIcon as ListItemIcon$1, createFilterOptions, alpha, useTheme, Toolbar as Toolbar$1, AppBar as AppBar$1, Dialog as Dialog$1, Chip as Chip$1, DialogTitle as DialogTitle$1, DialogContent as DialogContent$1, Fade, AlertTitle, Alert as Alert$2, DialogActions as DialogActions$1, Slide, Accordion, AccordionSummary, AccordionDetails, Avatar as Avatar$1, Menu as Menu$2, useMediaQuery, Portal, Snackbar as Snackbar$1, List as List$2, ListItemButton as ListItemButton$1, ListItem as ListItem$1, ListSubheader as ListSubheader$1, Popover } from "@mui/material";
4
4
  import { ListItemAvatar, ListItemSecondaryAction } from "@mui/material";
5
- import { T as Typography, I as ICON_SIZE_SMALL, m as mergeSx, a as ICON_SIZE_MEDIUM, i as isPalettePath, M as MENU_ITEM_SIZE_EXTENDED, b as MENU_ITEM_SIZE_DEFAULT, c as MENU_LIST_MAX_SIZE, d as MENU_ITEM_SIZE_DENSE, A as APPBAR_SIZE, e as ICON_SIZE_LARGE, N as NOTIFICATION_DURATION_IN_MS, L as LIST_MAX_SIZE, f as LIST_ITEM_SIZE_DENSE, g as LIST_ITEM_SIZE_DEFAULT, h as LIST_OVERSCAN_ITEMS_COUNT, F as FontWeight, r as resolvePalettePath } from "../palette-utils-BCQ0HY6h.js";
5
+ import { T as Typography, I as ICON_SIZE_SMALL, m as mergeSx, a as ICON_SIZE_MEDIUM, i as isPalettePath, M as MENU_ITEM_SIZE_EXTENDED, b as MENU_ITEM_SIZE_DEFAULT, c as MENU_LIST_MAX_SIZE, d as MENU_ITEM_SIZE_DENSE, A as APPBAR_SIZE, e as ICON_SIZE_LARGE, N as NOTIFICATION_DURATION_IN_MS, L as LIST_MAX_SIZE, f as LIST_ITEM_SIZE_DENSE, g as LIST_ITEM_SIZE_DEFAULT, h as LIST_OVERSCAN_ITEMS_COUNT, F as FontWeight, r as resolvePalettePath } from "../palette-utils-BmPPGzZt.js";
6
6
  import { OpenInNewOutlined, VisibilityOffOutlined, VisibilityOutlined, Cancel, ContentCopyOutlined, AddCircleOutlineOutlined, MenuOutlined, MoreVertOutlined, HelpOutlineOutlined, ErrorOutlineOutlined, ArrowBackOutlined, CloseOutlined, Check, TodayOutlined, StopCircleOutlined, ArrowUpwardOutlined } from "@mui/icons-material";
7
7
  import { F as ForwardedComponent$1 } from "../ArrowDown-Bho9Ssnw.js";
8
8
  import * as ReactWindow from "react-window";
9
- import { u as useTranslationWithFallback, I as IconButton, M as MenuItem$1, g as getThemeColor, e as ellipsisStyles, S as SVG_SELECTOR } from "../utils-BkM2jqPv.js";
10
- import { T } from "../utils-BkM2jqPv.js";
9
+ import { u as useTranslationWithFallback, I as IconButton, M as MenuItem$1, g as getThemeColor, e as ellipsisStyles, S as SVG_SELECTOR } from "../utils-7LZAkgSl.js";
10
+ import { T } from "../utils-7LZAkgSl.js";
11
11
  import { F as ForwardedComponent, a as ForwardedComponent$2, b as ForwardedComponent$3, c as ForwardedComponent$4 } from "../Search-DXfTNnxj.js";
12
12
  import "cartocolor";
13
13
  import { Controlled, UnControlled } from "react-codemirror2";
@@ -110,6 +110,7 @@ function _Button({
110
110
  );
111
111
  }
112
112
  const Button = forwardRef(_Button);
113
+ Button.displayName = "Button";
113
114
  const idCounter = {};
114
115
  function uniqueId(prefix = "$lodash$") {
115
116
  if (!idCounter[prefix]) {
@@ -415,11 +416,16 @@ function _SelectField({
415
416
  fullWidth,
416
417
  required,
417
418
  "aria-label": ariaLabel,
419
+ SelectDisplayProps,
418
420
  ...otherProps
419
421
  }, ref) {
420
422
  const isSmall = size === "small";
421
423
  const [defaultId] = useState(() => uniqueId("select-label-"));
422
424
  const ariaLabelledBy = label ? labelId ?? defaultId : void 0;
425
+ const [fallbackDisplayId] = useState(() => uniqueId("select-value-"));
426
+ const displayId = (SelectDisplayProps == null ? void 0 : SelectDisplayProps.id) ?? (name ? `mui-component-select-${name}` : fallbackDisplayId);
427
+ const isUnnamed = !ariaLabelledBy && !ariaLabel;
428
+ const selfLabelProps = isUnnamed ? { id: displayId, "aria-labelledby": displayId } : void 0;
423
429
  return /* @__PURE__ */ jsxs(
424
430
  FormControl,
425
431
  {
@@ -463,13 +469,18 @@ function _SelectField({
463
469
  ...otherProps,
464
470
  labelId: ariaLabelledBy,
465
471
  name,
472
+ SelectDisplayProps: { ...selfLabelProps, ...SelectDisplayProps },
466
473
  ref,
467
474
  size,
468
475
  fullWidth,
469
476
  displayEmpty: displayEmpty ?? !!placeholder,
470
477
  inputProps: {
471
478
  ...inputProps,
472
- "aria-label": ariaLabel
479
+ // Written only when set: an unconditional key means an *absent*
480
+ // `aria-label` prop overwrites one the caller put in `inputProps`.
481
+ // When both are given the dedicated prop still wins — it is the
482
+ // documented API, and that ranking is unchanged.
483
+ ...ariaLabel !== void 0 && { "aria-label": ariaLabel }
473
484
  },
474
485
  MenuProps: {
475
486
  ...menuProps,
@@ -969,6 +980,7 @@ function _Link({
969
980
  );
970
981
  }
971
982
  const Link = forwardRef(_Link);
983
+ Link.displayName = "Link";
972
984
  function _CircularProgress({
973
985
  color = "primary",
974
986
  size = 40,
@@ -1305,8 +1317,11 @@ const { FixedSizeList: FixedSizeList$1 } = ReactWindow;
1305
1317
  const List$1 = styled(MenuList$1, {
1306
1318
  // MenuList is a component, so emotion forwards every prop to it (unlike a
1307
1319
  // string tag, where invalid HTML attributes are dropped) — `hasFilters` would
1308
- // reach the underlying <ul>.
1309
- shouldForwardProp: (prop) => prop !== "hasFilters"
1320
+ // reach the underlying <ul>. `ownerState`/`theme`/`sx`/`as` mirror MUI's own
1321
+ // `slotShouldForwardProp`, which a custom `shouldForwardProp` replaces rather
1322
+ // than extends: as Autocomplete's `listbox` slot this receives the
1323
+ // Autocomplete's ownerState, which must not reach MenuList.
1324
+ shouldForwardProp: (prop) => !["ownerState", "theme", "sx", "as", "hasFilters"].includes(prop)
1310
1325
  })(({ theme, hasFilters }) => ({
1311
1326
  ...!hasFilters && {
1312
1327
  paddingTop: `${theme.spacing(1)} !important`
@@ -1606,7 +1621,14 @@ function _Autocomplete({
1606
1621
  slotProps: {
1607
1622
  ...slotProps,
1608
1623
  listbox: mergeSlotProps({
1609
- ownProps: { "aria-multiselectable": false },
1624
+ ownProps: {
1625
+ "aria-multiselectable": false,
1626
+ component: MenuList$1
1627
+ // `useAutocomplete`'s `singleRenderOption` emits Meridian MenuItems,
1628
+ // and on v9 a MenuItem throws without a MenuListContext. Set through
1629
+ // `component` rather than `slots.listbox`: swapping the slot would
1630
+ // drop the listbox's own styles (max-height/overflow) with it.
1631
+ },
1610
1632
  consumerProps: slotProps == null ? void 0 : slotProps.listbox
1611
1633
  })
1612
1634
  }
@@ -3296,7 +3318,25 @@ const dialogDimensionsBySize = {
3296
3318
  }
3297
3319
  };
3298
3320
  const DialogPaper = styled(Paper, {
3299
- shouldForwardProp: (prop) => !["fullScreen", "height", "width", "hasForm"].includes(prop)
3321
+ // `as` must stay with emotion: MUI renders the paper slot as
3322
+ // `<PaperSlot as={Paper} …>`, so forwarding `as` to Paper shadows a
3323
+ // consumer's `slotProps.paper.component` and a form dialog renders a div.
3324
+ //
3325
+ // `ownerState`/`theme`/`sx` mirror MUI's own `slotShouldForwardProp`, which a
3326
+ // custom `shouldForwardProp` replaces rather than extends. As the Dialog's
3327
+ // `paper` slot this receives the *Dialog's* ownerState; Paper spreads it over
3328
+ // its own, so `variant: 'elevation'` stops matching and neither the elevation
3329
+ // shadow nor the `outlined` border is emitted.
3330
+ shouldForwardProp: (prop) => ![
3331
+ "ownerState",
3332
+ "theme",
3333
+ "sx",
3334
+ "as",
3335
+ "fullScreen",
3336
+ "height",
3337
+ "width",
3338
+ "hasForm"
3339
+ ].includes(prop)
3300
3340
  })(
3301
3341
  ({
3302
3342
  fullScreen,
@@ -3308,6 +3348,22 @@ const DialogPaper = styled(Paper, {
3308
3348
  }) => ({
3309
3349
  "&.MuiPaper-root": {
3310
3350
  position: "relative",
3351
+ // MUI's Dialog paper styles are replaced, not composed, once this is the
3352
+ // `paper` slot — so carry the ones consumers depend on. Without
3353
+ // `overflowY` a fullScreen dialog cannot scroll and overflowing content is
3354
+ // unreachable.
3355
+ overflowY: "auto",
3356
+ outline: 0,
3357
+ // The focus trap focuses the paper when nothing inside autofocuses, and
3358
+ // Chromium treats that as `:focus-visible` — the global ring would frame
3359
+ // the whole dialog. It's a container, not a control.
3360
+ "&:focus-visible": {
3361
+ outline: "none !important"
3362
+ },
3363
+ "@media print": {
3364
+ overflowY: "visible",
3365
+ boxShadow: "none"
3366
+ },
3311
3367
  display: "flex",
3312
3368
  flexDirection: "column",
3313
3369
  margin: theme.spacing(5),
@@ -3414,6 +3470,7 @@ function _Dialog({
3414
3470
  hasForm,
3415
3471
  "aria-label": ariaLabel,
3416
3472
  "data-testid": dataTestId,
3473
+ slots,
3417
3474
  slotProps,
3418
3475
  ...props
3419
3476
  }, ref) {
@@ -3461,7 +3518,7 @@ function _Dialog({
3461
3518
  return /* @__PURE__ */ jsx(
3462
3519
  Dialog$1,
3463
3520
  {
3464
- slots: { paper: DialogPaper },
3521
+ slots: { ...slots, paper: DialogPaper },
3465
3522
  slotProps: {
3466
3523
  ...slotProps,
3467
3524
  paper: mergeSlotProps({
@@ -6450,6 +6507,7 @@ function _SearchField({
6450
6507
  size = "small",
6451
6508
  dense = false,
6452
6509
  slotProps,
6510
+ InputProps,
6453
6511
  startAdornment,
6454
6512
  endAdornment,
6455
6513
  onFocus,
@@ -6525,7 +6583,13 @@ function _SearchField({
6525
6583
  }
6526
6584
  )
6527
6585
  },
6528
- consumerProps: slotProps == null ? void 0 : slotProps.input
6586
+ // The deprecated `InputProps` feeds the same slot, ranked below
6587
+ // `slotProps.input` so the modern form wins. Without this it rode
6588
+ // `otherProps` onto the DOM once v9 stopped accepting it on TextField.
6589
+ consumerProps: mergeSlotProps({
6590
+ ownProps: InputProps ?? {},
6591
+ consumerProps: slotProps == null ? void 0 : slotProps.input
6592
+ })
6529
6593
  }),
6530
6594
  htmlInput: mergeSlotProps({
6531
6595
  ownProps: { role: "searchbox" },
@@ -7127,6 +7191,7 @@ function _UploadField({
7127
7191
  focused,
7128
7192
  nativeInputProps,
7129
7193
  "data-testid": dataTestId,
7194
+ slotProps,
7130
7195
  ...props
7131
7196
  }, ref) {
7132
7197
  const accept = _accept ?? DEFAULT_ACCEPT;
@@ -7159,7 +7224,13 @@ function _UploadField({
7159
7224
  dragOver,
7160
7225
  inProgress,
7161
7226
  hasFiles: Boolean(filesText),
7162
- slotProps: { input: inputEvents },
7227
+ slotProps: {
7228
+ ...slotProps,
7229
+ input: mergeSlotProps({
7230
+ ownProps: inputEvents,
7231
+ consumerProps: slotProps == null ? void 0 : slotProps.input
7232
+ })
7233
+ },
7163
7234
  buttonText,
7164
7235
  "data-testid": dataTestId
7165
7236
  }
@@ -7735,7 +7806,7 @@ function _ListSubheader({
7735
7806
  "data-disable-gutters": effectiveDisableGutters,
7736
7807
  "data-disable-padding": effectiveDisablePadding,
7737
7808
  children: /* @__PURE__ */ jsx(
7738
- Typography$1,
7809
+ Typography,
7739
7810
  {
7740
7811
  ...mergeTypographyProps(
7741
7812
  DEFAULT_TYPOGRAPHY_PROPS,
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.4.1-alpha.fbe7378.320",
2
+ "version": "5.0.0",
3
3
  "conventions": "# Meridian usage conventions (for code-generating agents)\n\nSystem-level rules an agent should apply across all components.\n\nMeridian is the source of truth: when an existing codebase pattern contradicts Meridian, follow Meridian — don't replicate the contradicting local pattern.\n\n## Choosing a component\n\n- Don't hand-roll what the design system already provides. Before writing a\n custom component, a styled wrapper, or a block of primitives (a modal,\n chip/tag, card, empty state, dropdown, tooltip, copy-to-clipboard input,\n etc.), confirm no Meridian component covers it — reuse or extend the existing one instead of rebuilding it.\n- Prefer a Meridian component over a bare MUI one whenever a Meridian wrapper\n exists — the wrappers carry CARTO theming, a11y defaults, and narrowed APIs. MUI is correct for layout primitives (`Box`/`Grid`/`Stack`/`Container`) and for gaps Meridian doesn't fill (e.g. date pickers); \"prefer Meridian\" is not \"never MUI\".\n- Resolve \"which component\" by reading each one's `description` + `keywords`,\n then confirm with its `decisionTree` (the conditions that point elsewhere) and `limitations` (what it lacks — check before you downgrade to it).\n Don't infer selection from prop lists.\n\n## Icons\n\n- Source icons from Meridian's custom-icons first, then `@mui/icons-material`;\n add a local SVG only when neither has an equivalent. Don't duplicate an icon\n the design system already ships.\n- Find the right custom icon with `meridian_list_icons` — match by name or keyword (e.g. \"warehouse\" → `Bigquery`), import it from `@carto/meridian-ds/custom-icons`, and render `<Name />`. Every icon shares one prop type, `CustomIconProps` (MUI `SvgIconProps` — `color`/`fontSize`/`sx` — plus `width`/`height`).\n- To confirm a shortlisted icon by sight (or match an icon in a design you're implementing), call `meridian_get_screenshot` with `name: 'icons'` and Read the returned image path — a labeled grid of every icon.\n- Use the standard icon sizes — small 12px, medium (default) 18px, large 24px;\n a value off this scale (e.g. 16, 20) needs design sign-off. Prefer the\n outlined variants.\n- A new SVG must inherit, not bake in: set `fill='currentColor'` so it takes\n the parent's color, and use the standard size — don't hardcode\n color/opacity/dimensions.\n- For an icon color outside the palette `color` set, pass a theme token via\n `htmlColor` (e.g. `htmlColor={theme.palette.text.secondary}`) — never a\n hardcoded hex.\n\n## Accessibility\n\n- Any icon-only control needs an accessible name: `tooltip` or `aria-label`.\n- Don't disable a control without telling the user why — pair a disabled action with a tooltip explaining the requirement.\n- An `aria-label` must be human-readable text describing the control, not a test id in disguise — use a separate test hook for that.\n- User-facing strings (labels, `aria-label`, placeholders, messages) go through the app's i18n layer, not hardcoded literals.\n\n## Props\n\n- Two sources, both pinned to the installed `@carto/meridian-ds`: **exact props / types / JSDoc** come from the package's **type declarations** — read the `<Name>.d.ts` directly — while the **`meridian-design-system` MCP** (`meridian_*` tools) covers what types can't: which component, when, gotchas, and real examples.\n- A component's curation lists the high-value inherited MUI props worth knowing (`curation.mui`, e.g. `color`/`variant`/`size`); the rest of MUI's surface is available but rarely needed.\n- Don't use `sx`/inline styles to override a Meridian component's visual design (colors, typography, borders, sizing) — use its documented props and the theme tokens. (`sx` for layout/spacing on primitives is fine — see Styling.)\n- If no prop covers the visual change you need, treat it as a design-system gap: request the variant/behavior upstream in Meridian rather than permanently overriding the component locally — a local `styled()` of a Meridian component is a smell, not a fix.\n\n## Styling\n\n- Use theme tokens, never hardcoded values: colors from the palette (`text.*`, `background.*`, `divider`, semantic `*.main`) and spacing from the theme spacing scale — no raw hex/rgb or pixel literals for color or spacing. Use integer steps on the spacing scale (`theme.spacing(n)`, or `sx` numeric spacing like `px: 2` / `mt: 3` which resolve to it) — not fractional steps or raw px. Get the exact values — palette keys, spacing base, type ramp, `shape.borderRadius`, breakpoints, shadows — from `meridian_get_tokens`.\n- Text uses `<Typography variant=…>` (with the `weight` prop for emphasis), never hardcoded `fontSize`/`fontWeight`/`lineHeight`/`fontFamily`.\n- Meridian's type scale is custom and does not match MUI defaults (e.g. `body2`/`caption` differ from MUI's sizes, and there are Meridian-only variants like `code1`/`code2`/`code3` and `overlineDelicate`). Pick the variant by role from Typography's variant list (`meridian_get_examples('Typography')`) — don't assume a px size or map px → variant yourself.\n- `sx` is the right tool for one-off layout/spacing on primitives (`Box`/`Grid`/`Stack`), not the deprecated MUI system props\n (`<Box px={2}>` → `<Box sx={{ px: 2 }}>`). This is layout, distinct from restyling a Meridian component (see Props).\n\n## Examples\n\n- Never invent example code when a story exists — use the component's real story source (`meridian_get_examples`). The lead Usage story is the copy-paste starting point; the later stories are illustrative (variants, edge cases) and may carry story-arg shells, so don't copy one wholesale as your baseline.\n",
4
4
  "components": [
5
5
  {
@@ -330,7 +330,7 @@
330
330
  {
331
331
  "name": "Prefix",
332
332
  "id": "components-autocomplete-autocomplete--prefix",
333
- "summary": "Pin a fixed leading icon/adornment inside the input (params.InputProps.startAdornment)",
333
+ "summary": "Pin a fixed leading icon/adornment inside the input (params.slotProps.input.startAdornment)",
334
334
  "code": "import { Autocomplete, AutocompleteProps } from '@carto/meridian-ds/components'\nimport { AnalyticsOutlined } from '@mui/icons-material'\nimport { InputAdornment, TextField } from '@mui/material'\n\n// Story-only helpers, not exported by the package (stubbed so this compiles):\ndeclare const getTop100Films: any\n\nconst top100Films = getTop100Films()\n\nconst Prefix = ({\n label,\n variant,\n placeholder,\n helperText,\n error,\n size,\n required,\n disableCloseOnSelect,\n ...props\n}: AutocompleteProps<(typeof top100Films)[number]> &\n any) => {\n return (\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => {\n params.slotProps.input.startAdornment = (\n <InputAdornment position='start'>\n {<AnalyticsOutlined />}\n </InputAdornment>\n )\n return (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant={variant}\n error={error}\n size={size}\n required={required}\n />\n )\n }}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n )\n}"
335
335
  },
336
336
  {
@@ -2706,7 +2706,7 @@
2706
2706
  "subComponents": [
2707
2707
  {
2708
2708
  "name": "MenuItem",
2709
- "description": "A row inside a Menu/MenuList. Compose its content as children — `<ListItemIcon>` for a leading icon/avatar, `<ListItemText>` for the label (+ a caption Typography for secondary text), and a trailing element (e.g. a Tag). `subtitle` turns it into a non-interactive section header with a divider; `destructive` styles a dangerous action (delete) in red; `iconColor='primary'` recolors the icon to the theme text color, `'default'` keeps the icon's own color; `extended` gives a taller row for avatars/secondary text. Use this (not a bare ListItem) to keep a row interactive — and keep the content to an icon + text + a short trailing element: the whole row is one interactive target, so don't nest buttons or inputs (it breaks keyboard semantics)."
2709
+ "description": "A row inside a Menu/MenuList — it must have one as an ancestor, or MUI throws `MenuListContext is missing` (v9 made the context mandatory, and it is sealed, so this cannot be softened here). Compose its content as children — `<ListItemIcon>` for a leading icon/avatar, `<ListItemText>` for the label (+ a caption Typography for secondary text), and a trailing element (e.g. a Tag). `subtitle` turns it into a non-interactive section header with a divider; `destructive` styles a dangerous action (delete) in red; `iconColor='primary'` recolors the icon to the theme text color, `'default'` keeps the icon's own color; `extended` gives a taller row for avatars/secondary text. Use this (not a bare ListItem) to keep a row interactive — and keep the content to an icon + text + a short trailing element: the whole row is one interactive target, so don't nest buttons or inputs (it breaks keyboard semantics)."
2710
2710
  },
2711
2711
  {
2712
2712
  "name": "MenuItemFilter",
@@ -11,8 +11,11 @@ function mergeSx({
11
11
  own,
12
12
  consumer
13
13
  }) {
14
+ const applied = own.filter((entry) => Boolean(entry));
15
+ if (applied.length === 0) return consumer;
16
+ if (consumer === void 0) return applied;
14
17
  return [
15
- ...own,
18
+ ...applied,
16
19
  ...Array.isArray(consumer) ? consumer : [consumer]
17
20
  ];
18
21
  }
@@ -52,6 +55,7 @@ function _Typography({
52
55
  );
53
56
  }
54
57
  const Typography = forwardRef(_Typography);
58
+ Typography.displayName = "Typography";
55
59
  const SPACING = 8;
56
60
  const BREAKPOINTS = {
57
61
  XS: 320,
@@ -29,8 +29,11 @@ function mergeSx({
29
29
  own,
30
30
  consumer
31
31
  }) {
32
+ const applied = own.filter((entry) => Boolean(entry));
33
+ if (applied.length === 0) return consumer;
34
+ if (consumer === void 0) return applied;
32
35
  return [
33
- ...own,
36
+ ...applied,
34
37
  ...Array.isArray(consumer) ? consumer : [consumer]
35
38
  ];
36
39
  }
@@ -70,6 +73,7 @@ function _Typography({
70
73
  );
71
74
  }
72
75
  const Typography = React.forwardRef(_Typography);
76
+ Typography.displayName = "Typography";
73
77
  const SPACING = 8;
74
78
  const BREAKPOINTS = {
75
79
  XS: 320,