@windmorph/react 0.2.1 → 0.2.3

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 (55) hide show
  1. package/dist/components/autocomplete/Autocomplete.js +1 -1
  2. package/dist/components/autocomplete/Autocomplete.js.map +1 -1
  3. package/dist/components/carousel/carousel-styles.d.ts +6 -15
  4. package/dist/components/carousel/carousel-styles.js +4 -7
  5. package/dist/components/carousel/carousel-styles.js.map +1 -1
  6. package/dist/components/checkbox/checkbox-tokens.d.ts +1 -1
  7. package/dist/components/date-picker/DatePicker.js +11 -4
  8. package/dist/components/date-picker/DatePicker.js.map +1 -1
  9. package/dist/components/date-picker/date-picker-styles.d.ts +3 -3
  10. package/dist/components/fab-menu/FabMenu.js +2 -2
  11. package/dist/components/fab-menu/FabMenu.js.map +1 -1
  12. package/dist/components/list/List.d.ts +9 -0
  13. package/dist/components/list/List.js +7 -4
  14. package/dist/components/list/List.js.map +1 -1
  15. package/dist/components/list/list-styles.js +6 -6
  16. package/dist/components/list/list-styles.js.map +1 -1
  17. package/dist/components/list/list-tokens.d.ts +1 -1
  18. package/dist/components/list/list-tokens.js +50 -0
  19. package/dist/components/list/list-tokens.js.map +1 -1
  20. package/dist/components/menu/Menu.d.ts +13 -0
  21. package/dist/components/menu/Menu.js +14 -1
  22. package/dist/components/menu/Menu.js.map +1 -1
  23. package/dist/components/navigation/NavigationRail.js +52 -15
  24. package/dist/components/navigation/NavigationRail.js.map +1 -1
  25. package/dist/components/navigation/navigation-styles.js +1 -1
  26. package/dist/components/navigation/navigation-styles.js.map +1 -1
  27. package/dist/components/search/SearchBar.js +19 -34
  28. package/dist/components/search/SearchBar.js.map +1 -1
  29. package/dist/components/search/SearchField.d.ts +111 -0
  30. package/dist/components/search/SearchField.js +128 -0
  31. package/dist/components/search/SearchField.js.map +1 -0
  32. package/dist/components/search/search-field-frame.js +36 -0
  33. package/dist/components/search/search-field-frame.js.map +1 -0
  34. package/dist/components/search/search-styles.d.ts +58 -0
  35. package/dist/components/search/search-styles.js +29 -4
  36. package/dist/components/search/search-styles.js.map +1 -1
  37. package/dist/components/select/search-list.js +8 -13
  38. package/dist/components/select/search-list.js.map +1 -1
  39. package/dist/components/slider/Slider.js +5 -1
  40. package/dist/components/slider/Slider.js.map +1 -1
  41. package/dist/components/snackbar/snackbar-tokens.d.ts +1 -1
  42. package/dist/components/text-field/TextField.js +19 -5
  43. package/dist/components/text-field/TextField.js.map +1 -1
  44. package/dist/components/text-field/text-field-styles.js +2 -2
  45. package/dist/components/text-field/text-field-styles.js.map +1 -1
  46. package/dist/components/toolbar/toolbar-styles.js +2 -2
  47. package/dist/components/toolbar/toolbar-styles.js.map +1 -1
  48. package/dist/index.d.ts +3 -2
  49. package/dist/index.js +3 -2
  50. package/dist/primitives/use-m3-interaction.js +10 -6
  51. package/dist/primitives/use-m3-interaction.js.map +1 -1
  52. package/dist/styles/generated/components.css +5 -0
  53. package/dist/styles/utilities.css +22 -15
  54. package/dist/styles.compiled.css +1 -1
  55. package/package.json +1 -1
@@ -256,7 +256,7 @@ function Autocomplete(props) {
256
256
  openOnPress();
257
257
  },
258
258
  ref: inputRef,
259
- className: cn("min-w-[48px] flex-1 bg-transparent p-0 text-body-large outline-none", "text-[color:var(--_md-comp-text-field-input-text-color)]", "caret-[color:var(--_md-comp-text-field-caret-color)]", "placeholder:text-on-surface-variant placeholder:opacity-100", label ? "placeholder:opacity-0 placeholder:transition-opacity group-data-floated/field:placeholder:opacity-100 placeholder:[transition-duration:var(--md-sys-motion-spring-effects-fast-duration)] placeholder:[transition-timing-function:var(--md-sys-motion-spring-effects-fast-easing)]" : "", "group-data-invalid/field:caret-error group-data-[field-state=disabled]/field:text-on-surface/38", classNames?.input)
259
+ className: cn("min-w-[48px] flex-1 bg-transparent p-0 text-body-large outline-none", "text-[color:var(--_md-comp-text-field-input-text-color)]", "caret-[color:var(--_md-comp-text-field-caret-color)]", "text-ellipsis placeholder:text-on-surface-variant placeholder:opacity-100 placeholder:text-ellipsis", label ? "placeholder:opacity-0 placeholder:transition-opacity group-data-floated/field:placeholder:opacity-100 placeholder:[transition-duration:var(--md-sys-motion-spring-effects-fast-duration)] placeholder:[transition-timing-function:var(--md-sys-motion-spring-effects-fast-easing)]" : "", "group-data-invalid/field:caret-error group-data-[field-state=disabled]/field:text-on-surface/38", classNames?.input)
260
260
  })]
261
261
  })
262
262
  }), /* @__PURE__ */ jsx(OptionPopover, {
@@ -1 +1 @@
1
- {"version":3,"file":"Autocomplete.js","names":[],"sources":["../../../src/components/autocomplete/Autocomplete.tsx"],"sourcesContent":["'use client';\n\nimport {\n useMemo,\n useRef,\n type AriaAttributes,\n type CSSProperties,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n} from 'react';\nimport {\n mergeProps,\n useButton,\n useComboBox,\n useFocusRing,\n useHover,\n useObjectRef,\n ListKeyboardDelegate,\n type AriaComboBoxOptions,\n} from 'react-aria';\nimport {\n useComboBoxState,\n type ComboBoxProps,\n type ComboBoxStateOptions,\n type SelectionMode,\n} from 'react-stately/useComboBoxState';\nimport { TouchTarget } from '../../primitives/TouchTarget';\nimport { assertCollectionChildren } from '../../utils/assert-collection-children';\nimport type { Density } from '../../tokens/density';\nimport { cn } from '../../utils/cn';\nimport { renderedDescription } from '../../utils/rendered-description';\nimport { matchesSearch } from '../../utils/search';\nimport {\n ariaFlag,\n pickDescriptionAria,\n splitRootProps,\n type WrapperRootDOMProps,\n} from '../../utils/root-props';\nimport { usePreloadLoadingIndicator } from '../loading-indicator/lazy-loading-indicator';\nimport { InputChip } from '../chip/Chip';\nimport {\n DropdownArrow,\n FieldShell,\n fieldState,\n type FieldShellClassNames,\n} from '../select/field-shell';\nimport {\n FOCUSABLE_DISABLED_OPTIONS,\n OptionList,\n OptionPopover,\n type OptionListClassNames,\n} from '../select/option-list';\nimport { useSelectionCap } from '../select/selection-cap';\nimport type { TextFieldVariant } from '../text-field/text-field-styles';\n\n/** Words the Autocomplete shows or announces; override them for other languages. */\nexport interface AutocompleteLabels {\n /** Shown when no option matches what was typed. @default \"No results\" */\n noResults: string;\n /** The loading indicator's name. @default \"Loading options\" */\n loading: string;\n /** The arrow button's name. @default \"Show options\" */\n showOptions: string;\n /** A chip's remove button; the chip's text follows it (\"Remove London\"). @default \"Remove\" */\n remove: string;\n /** With `clearable`: the clear button's name. @default \"Clear\" */\n clear: string;\n /** The error icon's name (M3: \"Error\"). @default \"Error\" */\n error: string;\n}\n\n/** Elements that keep their own presses; a press anywhere else on the field opens it. */\nconst INTERACTIVE = 'input, textarea, button, a, [role=\"button\"]';\n\nconst DEFAULT_LABELS: AutocompleteLabels = {\n noResults: 'No results',\n loading: 'Loading options',\n showOptions: 'Show options',\n remove: 'Remove',\n clear: 'Clear',\n error: 'Error',\n};\n\nexport interface AutocompleteClassNames extends FieldShellClassNames, OptionListClassNames {\n /** The text `<input>`. */\n input?: string;\n /** With `selectionMode=\"multiple\"`: each chosen option's input chip. */\n chip?: string;\n /** With `clearable`: the clear button. */\n clear?: string;\n}\n\n/** Material Symbols `close`. */\nconst ClearIcon = () => (\n <svg viewBox=\"0 -960 960 960\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z\" />\n </svg>\n);\n\n/** React Aria props this API names the library's way (`disabled`, `readOnly`…), or leaves out. */\ntype RenamedProps =\n | 'isDisabled'\n | 'isRequired'\n | 'isInvalid'\n | 'isReadOnly'\n | 'label'\n | 'description'\n | 'validationState'\n | 'allowsCustomValue'\n // React Stately's deprecated single-selection API; `value` / `defaultValue` / `onChange` replace it.\n | 'selectedKey'\n | 'defaultSelectedKey'\n | 'onSelectionChange';\n\nexport type AutocompleteProps<T extends object, M extends SelectionMode = 'single'> = Omit<\n ComboBoxProps<T, M>,\n RenamedProps\n> &\n Pick<AriaComboBoxOptions<T, M>, 'id' | 'name' | 'form'> &\n Omit<WrapperRootDOMProps, keyof ComboBoxProps<T, M>> & {\n /** The `<input>`'s id, for a `<label for>` or an error summary's link. */\n id?: string;\n /** The container style, as `TextField`'s: a filled surface or an outline. @default \"filled\" */\n variant?: TextFieldVariant;\n /**\n * Free text: whatever is typed stays as the field's text when no option matches, instead\n * of returning to the chosen option's. @default false\n */\n allowCustomValue?: boolean;\n /**\n * Web density, `0` to `-3`: each step takes 4px off the field (56px at 0, 44px at -3) and\n * off its menu's options (44px at 0, 32px at -3). Left out, it takes the density of the\n * nearest `ThemeProvider` or `ThemeScope`. M3 asks for density to be the reader's choice\n * rather than a default, so prefer setting it there, from a setting.\n * @default 0\n */\n density?: Density;\n /** The field's label. Give `aria-label` instead when there's no visible label. */\n label?: ReactNode;\n /** Accessible name when there's no visible label. */\n 'aria-label'?: string;\n /** Shown in the empty input. With a `label`, it appears once the label floats (on focus). */\n placeholder?: string;\n /**\n * Helper text below the field. Replaced visually by the error when invalid, and shown in\n * the error colour while the field is invalid.\n */\n supportingText?: ReactNode;\n /** Marks the field invalid (in addition to `validate` and `required`). */\n invalid?: boolean;\n /** A value is required: adds the `*` to the label and validates on submit. */\n required?: boolean;\n /** Disables the field: it can't be focused or edited. @default false */\n disabled?: boolean;\n /** The value can be read and copied but not changed; the menu doesn't open. @default false */\n readOnly?: boolean;\n /**\n * Read as `invalid` when that's left out, for a form library that sets the attribute, so\n * the field shows its error state as well as announcing it.\n */\n 'aria-invalid'?: AriaAttributes['aria-invalid'];\n /** Read as `required` when that's left out, for a form library that sets the attribute. */\n 'aria-required'?: AriaAttributes['aria-required'];\n /** Read as `readOnly` when that's left out, for a form library that sets the attribute. */\n 'aria-readonly'?: AriaAttributes['aria-readonly'];\n /** Decorative icon at the start, in a 48px box. */\n leadingIcon?: ReactNode;\n /**\n * The icon shown before the arrow while the field is invalid (M3 strongly recommends one).\n * Defaults to Material Symbols `error`, named by `labels.error`; `false` turns it off.\n */\n errorIcon?: ReactNode | false;\n /**\n * A clear button (M3's clear icon) that appears while there's typed text and empties it,\n * and a single choice with it. It's skipped by Tab, since the text can be deleted from\n * the keyboard.\n * @default false\n */\n clearable?: boolean;\n /**\n * With `selectionMode=\"multiple\"`, the most options that can be chosen; the rest show as\n * disabled until one is removed.\n */\n maxSelections?: number;\n /**\n * Shows a loading indicator in the list, e.g. while options load for what was typed.\n * The indicator's code loads when it first shows, and ahead of that when the field is\n * hovered or focused while this prop is set at all, so pass `loading={false}` (rather than\n * leaving it out) on a field that loads options.\n */\n loading?: boolean;\n /**\n * Whether an option matches what was typed. Defaults to a match anywhere in its text,\n * ignoring case and accents (\"zurich\" finds \"Zürich\"). Not used with controlled `items`.\n */\n filter?: (textValue: string, inputValue: string) => boolean;\n /** Words the Autocomplete shows or announces, for other languages. */\n labels?: Partial<AutocompleteLabels>;\n /** Classes for the root element, merged with `classNames.root`; consumer classes win. */\n className?: string;\n /** Classes for each part, by slot. */\n classNames?: AutocompleteClassNames;\n /** Inline styles for the root element. */\n style?: CSSProperties;\n /** Ref to the root `<div>` element. Use `inputRef` for the input itself. */\n ref?: Ref<HTMLDivElement>;\n /** Ref to the text `<input>`, e.g. for form libraries. */\n inputRef?: Ref<HTMLInputElement>;\n };\n\n/**\n * The arrow's press moves focus to the input (React Aria does it on a touch press) without\n * scrolling the page: a press on a field partly off-screen scrolled it into view\n * (2026-10-15). The input's `focus` asks for `preventScroll` only while the press runs.\n */\nfunction withFocusInPlace(input: HTMLInputElement | null, run: () => void) {\n if (!input) return run();\n input.focus = (options) =>\n HTMLElement.prototype.focus.call(input, { ...options, preventScroll: true });\n try {\n run();\n } finally {\n Reflect.deleteProperty(input, 'focus');\n }\n}\n\n/**\n * M3 exposed dropdown menu, editable (Compose's `ExposedDropdownMenuBox` with a\n * `PrimaryEditable` anchor): type in the field and the menu below shows the matching\n * options. Single or multiple selection (chosen options as M3 input chips in the field),\n * accent-insensitive filtering by default, options loaded from a server through `items`,\n * `onInputChange` and `loading`, and free text with `allowCustomValue` (React Aria\n * `useComboBox`).\n *\n * @example\n * <Autocomplete label=\"City\" defaultItems={cities}>\n * {(city) => <AutocompleteItem key={city.id}>{city.name}</AutocompleteItem>}\n * </Autocomplete>\n */\nexport function Autocomplete<T extends object, M extends SelectionMode = 'single'>(\n props: AutocompleteProps<T, M>,\n) {\n const {\n variant = 'filled',\n density,\n label,\n placeholder,\n supportingText,\n invalid: invalidProp,\n required: requiredProp,\n disabled = false,\n readOnly: readOnlyProp,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-readonly': ariaReadonly,\n leadingIcon,\n errorIcon,\n clearable = false,\n maxSelections,\n loading,\n labels: labelsProp,\n className,\n classNames,\n style,\n ref,\n inputRef: inputRefProp,\n errorMessage,\n filter,\n allowCustomValue,\n ...otherProps\n } = props;\n // Items given as elements (not `items` with a render function) must come from a client.\n if (typeof props.children !== 'function') {\n assertCollectionChildren(\n props.children,\n 'Autocomplete',\n 'AutocompleteItem and AutocompleteSection elements',\n );\n }\n const { root: rootData, rest } = splitRootProps(otherProps, { wrapper: true });\n const invalid = invalidProp ?? ariaFlag(ariaInvalid);\n const required = requiredProp ?? ariaFlag(ariaRequired);\n const readOnly = readOnlyProp ?? ariaFlag(ariaReadonly) ?? false;\n const labels = { ...DEFAULT_LABELS, ...labelsProp };\n const stately = rest as Omit<ComboBoxProps<T, M>, RenamedProps>;\n const multiple = stately.selectionMode === 'multiple';\n const cap = useSelectionCap({\n multiple,\n maxSelections,\n value: stately.value,\n defaultValue: stately.defaultValue,\n onChange: stately.onChange,\n });\n\n const inputRef = useObjectRef(inputRefProp);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const listBoxRef = useRef<HTMLUListElement>(null);\n const popoverRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n // A field that takes `loading` (it loads options) preloads the indicator on hover or focus.\n usePreloadLoadingIndicator(containerRef, loading !== undefined);\n\n const ariaProps = {\n ...stately,\n ...cap.valueProps,\n label,\n description: supportingText,\n errorMessage,\n isInvalid: invalid,\n isRequired: required,\n isDisabled: disabled,\n isReadOnly: readOnly,\n allowsCustomValue: allowCustomValue,\n // The arrow keys wrap at the ends of the list, as in menus and lists.\n shouldFocusWrap: true,\n placeholder,\n inputRef,\n buttonRef,\n listBoxRef,\n popoverRef,\n } as AriaComboBoxOptions<T, M>;\n\n const state = useComboBoxState<T, M>({\n ...(ariaProps as unknown as ComboBoxStateOptions<T, M>),\n ...FOCUSABLE_DISABLED_OPTIONS,\n defaultFilter: filter ?? matchesSearch,\n allowsEmptyCollection: true,\n });\n const { collection } = state;\n const { disabledKeys } = state.selectionManager;\n const keyboardDelegate = useMemo(\n () =>\n new ListKeyboardDelegate({\n collection,\n disabledKeys,\n disabledBehavior: 'selection',\n ref: listBoxRef,\n }),\n [collection, disabledKeys],\n );\n const {\n buttonProps,\n inputProps,\n listBoxProps,\n labelProps,\n valueProps,\n descriptionProps,\n errorMessageProps,\n isInvalid,\n validationErrors,\n validationDetails,\n } = useComboBox<T, M>(\n {\n ...ariaProps,\n // The input's arrow keys reach disabled options too (M3: they \"can receive focus\").\n keyboardDelegate,\n },\n state,\n );\n const arrowPress = buttonProps.onPress;\n const { buttonProps: arrowProps } = useButton(\n {\n ...buttonProps,\n onPress:\n arrowPress && ((event) => withFocusInPlace(inputRef.current, () => arrowPress(event))),\n },\n buttonRef,\n );\n // A touch on the arrow, opening the list on its click (see the arrow's handlers).\n const fingerOnArrowRef = useRef(false);\n const { focusProps, isFocused } = useFocusRing({ within: true, isTextInput: true });\n const { hoverProps, isHovered } = useHover({ isDisabled: disabled });\n\n const chips = multiple ? state.selectedItems : [];\n const removeChip = (key: string | number) => state.selectionManager.toggleSelection(key);\n // Backspace in an empty input removes the last chip, as in other chip inputs.\n const onKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n const last = chips.at(-1);\n if (event.key === 'Backspace' && state.inputValue === '' && last && !readOnly) {\n event.preventDefault();\n removeChip(last.key);\n }\n };\n\n // M3: \"A menu should open when a person … Selects an element, such as … a text field\", as\n // Compose's editable anchor opens on press. A press on the input or the field opens the\n // whole list, as the arrow does; keyboard focus alone doesn't (unless `menuTrigger=\"focus\"`),\n // and `menuTrigger=\"manual\"` leaves opening to the arrow and the arrow keys.\n const openOnPress = () => {\n if (!state.isOpen && !disabled && !readOnly && ariaProps.menuTrigger !== 'manual') {\n state.open(null, 'manual');\n }\n };\n\n const focused = isFocused || state.isOpen;\n const floated = focused || state.inputValue !== '' || chips.length > 0;\n const showClear = clearable && state.inputValue !== '' && !disabled && !readOnly;\n const clear = () => {\n if (!multiple) state.setValue(null);\n state.setInputValue('');\n // Back to the input in the same field, without scrolling the page (2026-10-15).\n inputRef.current?.focus({ preventScroll: true });\n };\n const resolvedError =\n typeof errorMessage === 'function'\n ? errorMessage({ isInvalid, validationErrors, validationDetails })\n : (errorMessage ?? validationErrors.join(' '));\n\n return (\n <>\n <FieldShell\n variant={variant}\n density={density}\n label={label}\n labelProps={labelProps}\n required={required}\n state={fieldState({ disabled, invalid: isInvalid, focused, hovered: isHovered })}\n floated={floated}\n open={state.isOpen}\n leadingIcon={leadingIcon}\n errorIcon={errorIcon}\n errorIconLabel={labels.error}\n readOnly={readOnly}\n trailing={\n <button\n {...arrowProps}\n // A finger opens the list on the click, with focus in the input. React Aria's\n // touch press never ended here in Chrome (the list stayed closed), and the mouse\n // events a tap emulates focused the arrow, out of the Tab order (2026-10-17). So a\n // touch keeps both away from the arrow; the mouse and the keyboard keep React\n // Aria's press, which opens on the press start.\n onPointerDown={(event) => {\n fingerOnArrowRef.current = event.pointerType !== 'mouse';\n if (!fingerOnArrowRef.current) return arrowProps.onPointerDown?.(event);\n event.preventDefault();\n }}\n onPointerCancel={() => {\n fingerOnArrowRef.current = false;\n }}\n onClick={(event) => {\n if (!fingerOnArrowRef.current) return arrowProps.onClick?.(event);\n fingerOnArrowRef.current = false;\n inputRef.current?.focus({ preventScroll: true });\n if (!disabled && !readOnly) state.toggle(null, 'manual');\n }}\n ref={buttonRef}\n aria-label={labels.showOptions}\n className=\"relative flex size-[40px] items-center justify-center rounded-corner-full outline-none state-layer focus-ring [&>svg]:size-[24px]\"\n >\n <TouchTarget />\n <DropdownArrow open={state.isOpen} />\n </button>\n }\n trailingAction={\n showClear ? (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-label={labels.clear}\n // Keeps focus (and the open menu) in the input.\n onPointerDown={(event) => event.preventDefault()}\n onClick={clear}\n className={cn(\n 'relative flex size-[40px] items-center justify-center rounded-corner-full text-on-surface-variant outline-none state-layer [&>svg]:size-[24px]',\n classNames?.clear,\n )}\n >\n <TouchTarget />\n <ClearIcon />\n </button>\n ) : null\n }\n supportingText={supportingText}\n descriptionProps={descriptionProps}\n errorText={resolvedError}\n errorMessageProps={errorMessageProps}\n showError={isInvalid && Boolean(resolvedError)}\n containerRef={containerRef}\n containerProps={mergeProps(hoverProps, focusProps)}\n onContainerPointerDown={(event) => {\n // A press anywhere on the field (its padding, a chip's label, the space between\n // chips) puts the caret in the input and opens the menu, as TextField and Select\n // react to the whole field. The input opens on its own click, and the buttons (the\n // arrow, clear, a chip's remove) keep their own presses. Presses in the menu reach\n // here through React's tree from its portal, and are left alone.\n const target = event.target as Element;\n if (event.currentTarget.contains(target) && !target.closest(INTERACTIVE) && !disabled) {\n event.preventDefault();\n // The field is where the press landed: the page never scrolls to it (2026-10-15).\n inputRef.current?.focus({ preventScroll: true });\n openOnPress();\n }\n }}\n rootProps={rootData}\n rootRef={ref}\n className={className}\n classNames={classNames}\n style={style}\n multiline={multiple}\n >\n <div\n className={cn(\n 'flex min-w-0 flex-1 flex-wrap items-center gap-[8px]',\n // A row of 32px input chips fits the 56px container (12px above and below), so a\n // first chip doesn't make the field taller and each further row adds 40px. A filled\n // field's floated label takes the top 24px, so there the row stays below it.\n multiple &&\n chips.length > 0 &&\n !(variant === 'filled' && label !== undefined && label !== null) &&\n '-my-[4px]',\n )}\n >\n {chips.map((item) => (\n <InputChip\n key={item.key}\n // The field's own density sets its padding around one 32px row of chips, so the\n // chips keep their size (the field's height is what density changes here).\n density={0}\n onRemove={() => removeChip(item.key)}\n labels={{ remove: labels.remove }}\n disabled={disabled || readOnly}\n className={classNames?.chip}\n >\n {item.textValue}\n </InputChip>\n ))}\n <input\n {...pickDescriptionAria(rest)}\n {...inputProps}\n aria-describedby={renderedDescription(inputProps['aria-describedby'], [\n !supportingText && descriptionProps.id,\n !(isInvalid && resolvedError) && errorMessageProps.id,\n // React Aria's element for the chosen values, which the chips show instead.\n valueProps.id,\n ])}\n onKeyDown={(event) => {\n onKeyDown(event);\n inputProps.onKeyDown?.(event);\n }}\n onClick={(event) => {\n inputProps.onClick?.(event);\n openOnPress();\n }}\n ref={inputRef}\n className={cn(\n // A zero flex basis with a 48px minimum: the input shares the chips' last row\n // while 48px are left there, and wraps to a row of its own only below that.\n 'min-w-[48px] flex-1 bg-transparent p-0 text-body-large outline-none',\n 'text-[color:var(--_md-comp-text-field-input-text-color)]',\n 'caret-[color:var(--_md-comp-text-field-caret-color)]',\n 'placeholder:text-on-surface-variant placeholder:opacity-100',\n label\n ? 'placeholder:opacity-0 placeholder:transition-opacity group-data-floated/field:placeholder:opacity-100 placeholder:[transition-duration:var(--md-sys-motion-spring-effects-fast-duration)] placeholder:[transition-timing-function:var(--md-sys-motion-spring-effects-fast-easing)]'\n : '',\n 'group-data-invalid/field:caret-error group-data-[field-state=disabled]/field:text-on-surface/38',\n classNames?.input,\n )}\n />\n </div>\n </FieldShell>\n <OptionPopover\n state={state}\n triggerRef={containerRef}\n popoverRef={popoverRef}\n nonModal\n density={density}\n >\n <OptionList\n animateFiltering\n listBoxProps={listBoxProps}\n state={state}\n listBoxRef={listBoxRef}\n emptyLabel={labels.noResults}\n loading={loading}\n loadingLabel={labels.loading}\n isBlocked={cap.isBlocked}\n classNames={classNames}\n />\n </OptionPopover>\n </>\n );\n}\n\nexport type { Key as AutocompleteKey } from 'react-stately';\n"],"mappings":"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"}
1
+ {"version":3,"file":"Autocomplete.js","names":[],"sources":["../../../src/components/autocomplete/Autocomplete.tsx"],"sourcesContent":["'use client';\n\nimport {\n useMemo,\n useRef,\n type AriaAttributes,\n type CSSProperties,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n} from 'react';\nimport {\n mergeProps,\n useButton,\n useComboBox,\n useFocusRing,\n useHover,\n useObjectRef,\n ListKeyboardDelegate,\n type AriaComboBoxOptions,\n} from 'react-aria';\nimport {\n useComboBoxState,\n type ComboBoxProps,\n type ComboBoxStateOptions,\n type SelectionMode,\n} from 'react-stately/useComboBoxState';\nimport { TouchTarget } from '../../primitives/TouchTarget';\nimport { assertCollectionChildren } from '../../utils/assert-collection-children';\nimport type { Density } from '../../tokens/density';\nimport { cn } from '../../utils/cn';\nimport { renderedDescription } from '../../utils/rendered-description';\nimport { matchesSearch } from '../../utils/search';\nimport {\n ariaFlag,\n pickDescriptionAria,\n splitRootProps,\n type WrapperRootDOMProps,\n} from '../../utils/root-props';\nimport { usePreloadLoadingIndicator } from '../loading-indicator/lazy-loading-indicator';\nimport { InputChip } from '../chip/Chip';\nimport {\n DropdownArrow,\n FieldShell,\n fieldState,\n type FieldShellClassNames,\n} from '../select/field-shell';\nimport {\n FOCUSABLE_DISABLED_OPTIONS,\n OptionList,\n OptionPopover,\n type OptionListClassNames,\n} from '../select/option-list';\nimport { useSelectionCap } from '../select/selection-cap';\nimport type { TextFieldVariant } from '../text-field/text-field-styles';\n\n/** Words the Autocomplete shows or announces; override them for other languages. */\nexport interface AutocompleteLabels {\n /** Shown when no option matches what was typed. @default \"No results\" */\n noResults: string;\n /** The loading indicator's name. @default \"Loading options\" */\n loading: string;\n /** The arrow button's name. @default \"Show options\" */\n showOptions: string;\n /** A chip's remove button; the chip's text follows it (\"Remove London\"). @default \"Remove\" */\n remove: string;\n /** With `clearable`: the clear button's name. @default \"Clear\" */\n clear: string;\n /** The error icon's name (M3: \"Error\"). @default \"Error\" */\n error: string;\n}\n\n/** Elements that keep their own presses; a press anywhere else on the field opens it. */\nconst INTERACTIVE = 'input, textarea, button, a, [role=\"button\"]';\n\nconst DEFAULT_LABELS: AutocompleteLabels = {\n noResults: 'No results',\n loading: 'Loading options',\n showOptions: 'Show options',\n remove: 'Remove',\n clear: 'Clear',\n error: 'Error',\n};\n\nexport interface AutocompleteClassNames extends FieldShellClassNames, OptionListClassNames {\n /** The text `<input>`. */\n input?: string;\n /** With `selectionMode=\"multiple\"`: each chosen option's input chip. */\n chip?: string;\n /** With `clearable`: the clear button. */\n clear?: string;\n}\n\n/** Material Symbols `close`. */\nconst ClearIcon = () => (\n <svg viewBox=\"0 -960 960 960\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z\" />\n </svg>\n);\n\n/** React Aria props this API names the library's way (`disabled`, `readOnly`…), or leaves out. */\ntype RenamedProps =\n | 'isDisabled'\n | 'isRequired'\n | 'isInvalid'\n | 'isReadOnly'\n | 'label'\n | 'description'\n | 'validationState'\n | 'allowsCustomValue'\n // React Stately's deprecated single-selection API; `value` / `defaultValue` / `onChange` replace it.\n | 'selectedKey'\n | 'defaultSelectedKey'\n | 'onSelectionChange';\n\nexport type AutocompleteProps<T extends object, M extends SelectionMode = 'single'> = Omit<\n ComboBoxProps<T, M>,\n RenamedProps\n> &\n Pick<AriaComboBoxOptions<T, M>, 'id' | 'name' | 'form'> &\n Omit<WrapperRootDOMProps, keyof ComboBoxProps<T, M>> & {\n /** The `<input>`'s id, for a `<label for>` or an error summary's link. */\n id?: string;\n /** The container style, as `TextField`'s: a filled surface or an outline. @default \"filled\" */\n variant?: TextFieldVariant;\n /**\n * Free text: whatever is typed stays as the field's text when no option matches, instead\n * of returning to the chosen option's. @default false\n */\n allowCustomValue?: boolean;\n /**\n * Web density, `0` to `-3`: each step takes 4px off the field (56px at 0, 44px at -3) and\n * off its menu's options (44px at 0, 32px at -3). Left out, it takes the density of the\n * nearest `ThemeProvider` or `ThemeScope`. M3 asks for density to be the reader's choice\n * rather than a default, so prefer setting it there, from a setting.\n * @default 0\n */\n density?: Density;\n /** The field's label. Give `aria-label` instead when there's no visible label. */\n label?: ReactNode;\n /** Accessible name when there's no visible label. */\n 'aria-label'?: string;\n /** Shown in the empty input. With a `label`, it appears once the label floats (on focus). */\n placeholder?: string;\n /**\n * Helper text below the field. Replaced visually by the error when invalid, and shown in\n * the error colour while the field is invalid.\n */\n supportingText?: ReactNode;\n /** Marks the field invalid (in addition to `validate` and `required`). */\n invalid?: boolean;\n /** A value is required: adds the `*` to the label and validates on submit. */\n required?: boolean;\n /** Disables the field: it can't be focused or edited. @default false */\n disabled?: boolean;\n /** The value can be read and copied but not changed; the menu doesn't open. @default false */\n readOnly?: boolean;\n /**\n * Read as `invalid` when that's left out, for a form library that sets the attribute, so\n * the field shows its error state as well as announcing it.\n */\n 'aria-invalid'?: AriaAttributes['aria-invalid'];\n /** Read as `required` when that's left out, for a form library that sets the attribute. */\n 'aria-required'?: AriaAttributes['aria-required'];\n /** Read as `readOnly` when that's left out, for a form library that sets the attribute. */\n 'aria-readonly'?: AriaAttributes['aria-readonly'];\n /** Decorative icon at the start, in a 48px box. */\n leadingIcon?: ReactNode;\n /**\n * The icon shown before the arrow while the field is invalid (M3 strongly recommends one).\n * Defaults to Material Symbols `error`, named by `labels.error`; `false` turns it off.\n */\n errorIcon?: ReactNode | false;\n /**\n * A clear button (M3's clear icon) that appears while there's typed text and empties it,\n * and a single choice with it. It's skipped by Tab, since the text can be deleted from\n * the keyboard.\n * @default false\n */\n clearable?: boolean;\n /**\n * With `selectionMode=\"multiple\"`, the most options that can be chosen; the rest show as\n * disabled until one is removed.\n */\n maxSelections?: number;\n /**\n * Shows a loading indicator in the list, e.g. while options load for what was typed.\n * The indicator's code loads when it first shows, and ahead of that when the field is\n * hovered or focused while this prop is set at all, so pass `loading={false}` (rather than\n * leaving it out) on a field that loads options.\n */\n loading?: boolean;\n /**\n * Whether an option matches what was typed. Defaults to a match anywhere in its text,\n * ignoring case and accents (\"zurich\" finds \"Zürich\"). Not used with controlled `items`.\n */\n filter?: (textValue: string, inputValue: string) => boolean;\n /** Words the Autocomplete shows or announces, for other languages. */\n labels?: Partial<AutocompleteLabels>;\n /** Classes for the root element, merged with `classNames.root`; consumer classes win. */\n className?: string;\n /** Classes for each part, by slot. */\n classNames?: AutocompleteClassNames;\n /** Inline styles for the root element. */\n style?: CSSProperties;\n /** Ref to the root `<div>` element. Use `inputRef` for the input itself. */\n ref?: Ref<HTMLDivElement>;\n /** Ref to the text `<input>`, e.g. for form libraries. */\n inputRef?: Ref<HTMLInputElement>;\n };\n\n/**\n * The arrow's press moves focus to the input (React Aria does it on a touch press) without\n * scrolling the page: a press on a field partly off-screen scrolled it into view\n * (2026-10-15). The input's `focus` asks for `preventScroll` only while the press runs.\n */\nfunction withFocusInPlace(input: HTMLInputElement | null, run: () => void) {\n if (!input) return run();\n input.focus = (options) =>\n HTMLElement.prototype.focus.call(input, { ...options, preventScroll: true });\n try {\n run();\n } finally {\n Reflect.deleteProperty(input, 'focus');\n }\n}\n\n/**\n * M3 exposed dropdown menu, editable (Compose's `ExposedDropdownMenuBox` with a\n * `PrimaryEditable` anchor): type in the field and the menu below shows the matching\n * options. Single or multiple selection (chosen options as M3 input chips in the field),\n * accent-insensitive filtering by default, options loaded from a server through `items`,\n * `onInputChange` and `loading`, and free text with `allowCustomValue` (React Aria\n * `useComboBox`).\n *\n * @example\n * <Autocomplete label=\"City\" defaultItems={cities}>\n * {(city) => <AutocompleteItem key={city.id}>{city.name}</AutocompleteItem>}\n * </Autocomplete>\n */\nexport function Autocomplete<T extends object, M extends SelectionMode = 'single'>(\n props: AutocompleteProps<T, M>,\n) {\n const {\n variant = 'filled',\n density,\n label,\n placeholder,\n supportingText,\n invalid: invalidProp,\n required: requiredProp,\n disabled = false,\n readOnly: readOnlyProp,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-readonly': ariaReadonly,\n leadingIcon,\n errorIcon,\n clearable = false,\n maxSelections,\n loading,\n labels: labelsProp,\n className,\n classNames,\n style,\n ref,\n inputRef: inputRefProp,\n errorMessage,\n filter,\n allowCustomValue,\n ...otherProps\n } = props;\n // Items given as elements (not `items` with a render function) must come from a client.\n if (typeof props.children !== 'function') {\n assertCollectionChildren(\n props.children,\n 'Autocomplete',\n 'AutocompleteItem and AutocompleteSection elements',\n );\n }\n const { root: rootData, rest } = splitRootProps(otherProps, { wrapper: true });\n const invalid = invalidProp ?? ariaFlag(ariaInvalid);\n const required = requiredProp ?? ariaFlag(ariaRequired);\n const readOnly = readOnlyProp ?? ariaFlag(ariaReadonly) ?? false;\n const labels = { ...DEFAULT_LABELS, ...labelsProp };\n const stately = rest as Omit<ComboBoxProps<T, M>, RenamedProps>;\n const multiple = stately.selectionMode === 'multiple';\n const cap = useSelectionCap({\n multiple,\n maxSelections,\n value: stately.value,\n defaultValue: stately.defaultValue,\n onChange: stately.onChange,\n });\n\n const inputRef = useObjectRef(inputRefProp);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const listBoxRef = useRef<HTMLUListElement>(null);\n const popoverRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n // A field that takes `loading` (it loads options) preloads the indicator on hover or focus.\n usePreloadLoadingIndicator(containerRef, loading !== undefined);\n\n const ariaProps = {\n ...stately,\n ...cap.valueProps,\n label,\n description: supportingText,\n errorMessage,\n isInvalid: invalid,\n isRequired: required,\n isDisabled: disabled,\n isReadOnly: readOnly,\n allowsCustomValue: allowCustomValue,\n // The arrow keys wrap at the ends of the list, as in menus and lists.\n shouldFocusWrap: true,\n placeholder,\n inputRef,\n buttonRef,\n listBoxRef,\n popoverRef,\n } as AriaComboBoxOptions<T, M>;\n\n const state = useComboBoxState<T, M>({\n ...(ariaProps as unknown as ComboBoxStateOptions<T, M>),\n ...FOCUSABLE_DISABLED_OPTIONS,\n defaultFilter: filter ?? matchesSearch,\n allowsEmptyCollection: true,\n });\n const { collection } = state;\n const { disabledKeys } = state.selectionManager;\n const keyboardDelegate = useMemo(\n () =>\n new ListKeyboardDelegate({\n collection,\n disabledKeys,\n disabledBehavior: 'selection',\n ref: listBoxRef,\n }),\n [collection, disabledKeys],\n );\n const {\n buttonProps,\n inputProps,\n listBoxProps,\n labelProps,\n valueProps,\n descriptionProps,\n errorMessageProps,\n isInvalid,\n validationErrors,\n validationDetails,\n } = useComboBox<T, M>(\n {\n ...ariaProps,\n // The input's arrow keys reach disabled options too (M3: they \"can receive focus\").\n keyboardDelegate,\n },\n state,\n );\n const arrowPress = buttonProps.onPress;\n const { buttonProps: arrowProps } = useButton(\n {\n ...buttonProps,\n onPress:\n arrowPress && ((event) => withFocusInPlace(inputRef.current, () => arrowPress(event))),\n },\n buttonRef,\n );\n // A touch on the arrow, opening the list on its click (see the arrow's handlers).\n const fingerOnArrowRef = useRef(false);\n const { focusProps, isFocused } = useFocusRing({ within: true, isTextInput: true });\n const { hoverProps, isHovered } = useHover({ isDisabled: disabled });\n\n const chips = multiple ? state.selectedItems : [];\n const removeChip = (key: string | number) => state.selectionManager.toggleSelection(key);\n // Backspace in an empty input removes the last chip, as in other chip inputs.\n const onKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n const last = chips.at(-1);\n if (event.key === 'Backspace' && state.inputValue === '' && last && !readOnly) {\n event.preventDefault();\n removeChip(last.key);\n }\n };\n\n // M3: \"A menu should open when a person … Selects an element, such as … a text field\", as\n // Compose's editable anchor opens on press. A press on the input or the field opens the\n // whole list, as the arrow does; keyboard focus alone doesn't (unless `menuTrigger=\"focus\"`),\n // and `menuTrigger=\"manual\"` leaves opening to the arrow and the arrow keys.\n const openOnPress = () => {\n if (!state.isOpen && !disabled && !readOnly && ariaProps.menuTrigger !== 'manual') {\n state.open(null, 'manual');\n }\n };\n\n const focused = isFocused || state.isOpen;\n const floated = focused || state.inputValue !== '' || chips.length > 0;\n const showClear = clearable && state.inputValue !== '' && !disabled && !readOnly;\n const clear = () => {\n if (!multiple) state.setValue(null);\n state.setInputValue('');\n // Back to the input in the same field, without scrolling the page (2026-10-15).\n inputRef.current?.focus({ preventScroll: true });\n };\n const resolvedError =\n typeof errorMessage === 'function'\n ? errorMessage({ isInvalid, validationErrors, validationDetails })\n : (errorMessage ?? validationErrors.join(' '));\n\n return (\n <>\n <FieldShell\n variant={variant}\n density={density}\n label={label}\n labelProps={labelProps}\n required={required}\n state={fieldState({ disabled, invalid: isInvalid, focused, hovered: isHovered })}\n floated={floated}\n open={state.isOpen}\n leadingIcon={leadingIcon}\n errorIcon={errorIcon}\n errorIconLabel={labels.error}\n readOnly={readOnly}\n trailing={\n <button\n {...arrowProps}\n // A finger opens the list on the click, with focus in the input. React Aria's\n // touch press never ended here in Chrome (the list stayed closed), and the mouse\n // events a tap emulates focused the arrow, out of the Tab order (2026-10-17). So a\n // touch keeps both away from the arrow; the mouse and the keyboard keep React\n // Aria's press, which opens on the press start.\n onPointerDown={(event) => {\n fingerOnArrowRef.current = event.pointerType !== 'mouse';\n if (!fingerOnArrowRef.current) return arrowProps.onPointerDown?.(event);\n event.preventDefault();\n }}\n onPointerCancel={() => {\n fingerOnArrowRef.current = false;\n }}\n onClick={(event) => {\n if (!fingerOnArrowRef.current) return arrowProps.onClick?.(event);\n fingerOnArrowRef.current = false;\n inputRef.current?.focus({ preventScroll: true });\n if (!disabled && !readOnly) state.toggle(null, 'manual');\n }}\n ref={buttonRef}\n aria-label={labels.showOptions}\n className=\"relative flex size-[40px] items-center justify-center rounded-corner-full outline-none state-layer focus-ring [&>svg]:size-[24px]\"\n >\n <TouchTarget />\n <DropdownArrow open={state.isOpen} />\n </button>\n }\n trailingAction={\n showClear ? (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-label={labels.clear}\n // Keeps focus (and the open menu) in the input.\n onPointerDown={(event) => event.preventDefault()}\n onClick={clear}\n className={cn(\n 'relative flex size-[40px] items-center justify-center rounded-corner-full text-on-surface-variant outline-none state-layer [&>svg]:size-[24px]',\n classNames?.clear,\n )}\n >\n <TouchTarget />\n <ClearIcon />\n </button>\n ) : null\n }\n supportingText={supportingText}\n descriptionProps={descriptionProps}\n errorText={resolvedError}\n errorMessageProps={errorMessageProps}\n showError={isInvalid && Boolean(resolvedError)}\n containerRef={containerRef}\n containerProps={mergeProps(hoverProps, focusProps)}\n onContainerPointerDown={(event) => {\n // A press anywhere on the field (its padding, a chip's label, the space between\n // chips) puts the caret in the input and opens the menu, as TextField and Select\n // react to the whole field. The input opens on its own click, and the buttons (the\n // arrow, clear, a chip's remove) keep their own presses. Presses in the menu reach\n // here through React's tree from its portal, and are left alone.\n const target = event.target as Element;\n if (event.currentTarget.contains(target) && !target.closest(INTERACTIVE) && !disabled) {\n event.preventDefault();\n // The field is where the press landed: the page never scrolls to it (2026-10-15).\n inputRef.current?.focus({ preventScroll: true });\n openOnPress();\n }\n }}\n rootProps={rootData}\n rootRef={ref}\n className={className}\n classNames={classNames}\n style={style}\n multiline={multiple}\n >\n <div\n className={cn(\n 'flex min-w-0 flex-1 flex-wrap items-center gap-[8px]',\n // A row of 32px input chips fits the 56px container (12px above and below), so a\n // first chip doesn't make the field taller and each further row adds 40px. A filled\n // field's floated label takes the top 24px, so there the row stays below it.\n multiple &&\n chips.length > 0 &&\n !(variant === 'filled' && label !== undefined && label !== null) &&\n '-my-[4px]',\n )}\n >\n {chips.map((item) => (\n <InputChip\n key={item.key}\n // The field's own density sets its padding around one 32px row of chips, so the\n // chips keep their size (the field's height is what density changes here).\n density={0}\n onRemove={() => removeChip(item.key)}\n labels={{ remove: labels.remove }}\n disabled={disabled || readOnly}\n className={classNames?.chip}\n >\n {item.textValue}\n </InputChip>\n ))}\n <input\n {...pickDescriptionAria(rest)}\n {...inputProps}\n aria-describedby={renderedDescription(inputProps['aria-describedby'], [\n !supportingText && descriptionProps.id,\n !(isInvalid && resolvedError) && errorMessageProps.id,\n // React Aria's element for the chosen values, which the chips show instead.\n valueProps.id,\n ])}\n onKeyDown={(event) => {\n onKeyDown(event);\n inputProps.onKeyDown?.(event);\n }}\n onClick={(event) => {\n inputProps.onClick?.(event);\n openOnPress();\n }}\n ref={inputRef}\n className={cn(\n // A zero flex basis with a 48px minimum: the input shares the chips' last row\n // while 48px are left there, and wraps to a row of its own only below that.\n 'min-w-[48px] flex-1 bg-transparent p-0 text-body-large outline-none',\n 'text-[color:var(--_md-comp-text-field-input-text-color)]',\n 'caret-[color:var(--_md-comp-text-field-caret-color)]',\n // A long hint or value ends in an ellipsis, as a text field's (2026-11-11).\n 'text-ellipsis placeholder:text-on-surface-variant placeholder:opacity-100 placeholder:text-ellipsis',\n label\n ? 'placeholder:opacity-0 placeholder:transition-opacity group-data-floated/field:placeholder:opacity-100 placeholder:[transition-duration:var(--md-sys-motion-spring-effects-fast-duration)] placeholder:[transition-timing-function:var(--md-sys-motion-spring-effects-fast-easing)]'\n : '',\n 'group-data-invalid/field:caret-error group-data-[field-state=disabled]/field:text-on-surface/38',\n classNames?.input,\n )}\n />\n </div>\n </FieldShell>\n <OptionPopover\n state={state}\n triggerRef={containerRef}\n popoverRef={popoverRef}\n nonModal\n density={density}\n >\n <OptionList\n animateFiltering\n listBoxProps={listBoxProps}\n state={state}\n listBoxRef={listBoxRef}\n emptyLabel={labels.noResults}\n loading={loading}\n loadingLabel={labels.loading}\n isBlocked={cap.isBlocked}\n classNames={classNames}\n />\n </OptionPopover>\n </>\n );\n}\n\nexport type { Key as AutocompleteKey } from 'react-stately';\n"],"mappings":"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"}
@@ -43,15 +43,12 @@ export declare const carouselStyles: import("tailwind-variants").TVReturnType<{
43
43
  };
44
44
  false: {};
45
45
  };
46
- /** Full-bleed items fill the window edge to edge: no corners, focus ring inside. */
46
+ /** Full-bleed items fill the window edge to edge: no corners. */
47
47
  fullBleed: {
48
48
  true: {
49
49
  root: string;
50
- item: string;
51
- };
52
- false: {
53
- item: string;
54
50
  };
51
+ false: {};
55
52
  };
56
53
  }, {
57
54
  root: string[];
@@ -102,15 +99,12 @@ export declare const carouselStyles: import("tailwind-variants").TVReturnType<{
102
99
  };
103
100
  false: {};
104
101
  };
105
- /** Full-bleed items fill the window edge to edge: no corners, focus ring inside. */
102
+ /** Full-bleed items fill the window edge to edge: no corners. */
106
103
  fullBleed: {
107
104
  true: {
108
105
  root: string;
109
- item: string;
110
- };
111
- false: {
112
- item: string;
113
106
  };
107
+ false: {};
114
108
  };
115
109
  }, {
116
110
  root: string[];
@@ -161,15 +155,12 @@ export declare const carouselStyles: import("tailwind-variants").TVReturnType<{
161
155
  };
162
156
  false: {};
163
157
  };
164
- /** Full-bleed items fill the window edge to edge: no corners, focus ring inside. */
158
+ /** Full-bleed items fill the window edge to edge: no corners. */
165
159
  fullBleed: {
166
160
  true: {
167
161
  root: string;
168
- item: string;
169
- };
170
- false: {
171
- item: string;
172
162
  };
163
+ false: {};
173
164
  };
174
165
  }, {
175
166
  root: string[];
@@ -13,7 +13,7 @@ const carouselStyles = tv({
13
13
  "data-dragging:cursor-grabbing data-dragging:[scroll-snap-type:none] data-dragging:select-none",
14
14
  "[&::-webkit-scrollbar]:hidden"
15
15
  ],
16
- item: "flex shrink-0 rounded-(--m3-carousel-corner)",
16
+ item: "flex shrink-0 rounded-(--m3-carousel-corner) focus-ring-inset",
17
17
  mask: [
18
18
  "grid size-full overflow-hidden bg-surface [&>*]:[grid-area:1/1] [&>*]:size-full",
19
19
  "[--m3-carousel-item-corner:var(--m3-carousel-corner)]",
@@ -65,13 +65,10 @@ const carouselStyles = tv({
65
65
  true: { item: "cursor-pointer data-disabled:cursor-default" },
66
66
  false: {}
67
67
  },
68
- /** Full-bleed items fill the window edge to edge: no corners, focus ring inside. */
68
+ /** Full-bleed items fill the window edge to edge: no corners. */
69
69
  fullBleed: {
70
- true: {
71
- root: "[--m3-carousel-corner:0px] [--m3-carousel-pressed-corner:0px]",
72
- item: "focus-ring-inset"
73
- },
74
- false: { item: "focus-ring" }
70
+ true: { root: "[--m3-carousel-corner:0px] [--m3-carousel-pressed-corner:0px]" },
71
+ false: {}
75
72
  }
76
73
  },
77
74
  compoundVariants: [
@@ -1 +1 @@
1
- {"version":3,"file":"carousel-styles.js","names":[],"sources":["../../../src/components/carousel/carousel-styles.ts"],"sourcesContent":["import { tv, type VariantProps } from '../../utils/tv';\n\n/*\n * Values follow the M3 Expressive carousel spec (2026-10-13) and Compose Material 3\n * (carousel/Carousel.kt, Keylines.kt, Strategy.kt):\n *\n * - Multi-browse and hero: 16px leading and trailing padding, 8px top and bottom, 8px\n * between items. Uncontained (and multi-aspect): 16px leading padding only. Full-screen:\n * no padding, 16px between items and no corners. Small items are 40–56px.\n * - Snapping: hero and full-screen move one item at a time (`scroll-snap-stop: always`);\n * multi-browse flings across many items and then snaps; uncontained and multi-aspect\n * scroll freely unless `snap=\"item\"`.\n * - Uncontained (and multi-aspect) items keep one size and flow past the end edge; only\n * multi-browse and hero items follow keylines.\n * - Each item's mask is filled with `surface`, the spec's container colour, so transparent\n * or still-loading content never shows what's behind the carousel.\n * - Items are masked with 28px (extra-large) corners, as Compose's samples do with\n * `maskClip(MaterialTheme.shapes.extraLarge)`; the component token\n * `--md-comp-carousel-item-container-shape` (`carousel-tokens.ts`) sets them. A\n * pressed item's corners tighten to `--m3-carousel-pressed-corner` (20px, large-increased)\n * on the fast spatial spring, the spec's \"changes the shape slightly\".\n *\n * The carousel scrolls natively. Items keep their natural slots (the large item size), and\n * a library-owned mask layer inside each is translated and clipped to its keyline on every\n * scroll frame, so the root is never transformed. The state layer is a library-owned\n * element sharing the mask's grid cell, painted over the item (nothing is positioned).\n * Under the mask, a press area follows it, widened to 48px for a small item (40–56px):\n * M3's touch target, taken from the 8px spacing, so neighbours never overlap.\n * Every class is written out in full.\n */\n\n/** Variant definitions for {@link Carousel}. */\nexport const carouselStyles = tv({\n slots: {\n root: [\n 'flex min-h-0 min-w-0',\n '[--m3-carousel-corner:var(--_md-comp-carousel-item-container-shape)]',\n '[--m3-carousel-pressed-corner:var(--md-sys-shape-corner-large-increased)]',\n ],\n scroller: [\n 'flex min-h-0 min-w-0 flex-1 outline-none [scrollbar-width:none]',\n 'data-dragging:cursor-grabbing data-dragging:[scroll-snap-type:none] data-dragging:select-none',\n '[&::-webkit-scrollbar]:hidden',\n ],\n item: 'flex shrink-0 rounded-(--m3-carousel-corner)',\n mask: [\n 'grid size-full overflow-hidden bg-surface [&>*]:[grid-area:1/1] [&>*]:size-full',\n '[--m3-carousel-item-corner:var(--m3-carousel-corner)]',\n 'data-pressed:[--m3-carousel-item-corner:var(--m3-carousel-pressed-corner)]',\n '[transition-property:--m3-carousel-item-corner]',\n '[transition-duration:var(--md-sys-motion-spring-spatial-fast-duration)]',\n '[transition-timing-function:var(--md-sys-motion-spring-spatial-fast-easing)]',\n 'motion-reduce:[transition-duration:0s]',\n 'data-disabled:opacity-38',\n ],\n stateLayer:\n 'pointer-events-none state-layer [--m3-state-layer-color:var(--md-sys-color-on-surface)]',\n // The item's press area, laid under the mask in the same place (a negative end margin,\n // so nothing is positioned).\n hitArea: 'h-full w-full shrink-0 -me-[100%]',\n },\n variants: {\n orientation: {\n // Overscroll is contained on the carousel's own axis only, so a swipe across it\n // (a vertical swipe on a horizontal carousel) still scrolls the page (2026-10-15).\n horizontal: {\n scroller: 'flex-row overflow-x-auto overflow-y-hidden overscroll-x-contain',\n item: 'h-full',\n },\n vertical: { scroller: 'flex-col overflow-x-hidden overflow-y-auto', item: 'w-full' },\n },\n /** `single` stops at every item, `many` lets a fling cross several, `none` doesn't snap. */\n snapping: { single: {}, many: {}, none: {} },\n /** The mask is clipped by the keylines on every scroll frame; otherwise by CSS. */\n masked: {\n // Only the mask and the press area under it take presses, not the rest of the slot, so\n // a press between items never lands on an item whose slot reaches there.\n true: {\n item: 'pointer-events-none',\n mask: 'pointer-events-auto',\n hitArea: 'pointer-events-auto',\n },\n false: { mask: '[clip-path:inset(0_round_var(--m3-carousel-item-corner))]' },\n },\n /** Multi-aspect items keep their own width, between 9:16 and 16:9 of the height. */\n aspect: {\n true: {\n item: [\n 'w-max min-w-[calc(var(--m3-carousel-cross-size)*9/16)]',\n 'max-w-[calc(var(--m3-carousel-cross-size)*16/9)]',\n ],\n mask: '[&>*]:h-full [&>*]:w-auto [&>*]:min-w-full [&>*]:max-w-full [&>*]:object-cover',\n },\n false: {},\n },\n interactive: { true: { item: 'cursor-pointer data-disabled:cursor-default' }, false: {} },\n /** Full-bleed items fill the window edge to edge: no corners, focus ring inside. */\n fullBleed: {\n true: {\n root: '[--m3-carousel-corner:0px] [--m3-carousel-pressed-corner:0px]',\n item: 'focus-ring-inset',\n },\n false: { item: 'focus-ring' },\n },\n },\n compoundVariants: [\n {\n snapping: ['single', 'many'],\n orientation: 'horizontal',\n class: { scroller: 'snap-x snap-mandatory', item: 'snap-start' },\n },\n {\n snapping: ['single', 'many'],\n orientation: 'vertical',\n class: { scroller: 'snap-y snap-mandatory', item: 'snap-start' },\n },\n { snapping: 'single', class: { item: 'snap-always' } },\n // A full-screen vertical carousel fills the window, so past its last item a swipe goes\n // on to the page instead of trapping it.\n { orientation: 'vertical', fullBleed: false, class: { scroller: 'overscroll-y-contain' } },\n ],\n defaultVariants: {\n orientation: 'horizontal',\n snapping: 'single',\n masked: true,\n aspect: false,\n interactive: false,\n fullBleed: false,\n },\n});\n\n/**\n * The variants of {@link carouselStyles}, for building on its styles. They are the recipe's keys, not\n * component props: their names (`hasIcon`, `isOpen`…) follow the classes and may change.\n */\nexport type CarouselStyleProps = VariantProps<typeof carouselStyles>;\n"],"mappings":";;;AAgCA,MAAa,iBAAiB,GAAG;CAC/B,OAAO;EACL,MAAM;GACJ;GACA;GACA;EACF;EACA,UAAU;GACR;GACA;GACA;EACF;EACA,MAAM;EACN,MAAM;GACJ;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;EACA,YACE;EAGF,SAAS;CACX;CACA,UAAU;EACR,aAAa;GAGX,YAAY;IACV,UAAU;IACV,MAAM;GACR;GACA,UAAU;IAAE,UAAU;IAA8C,MAAM;GAAS;EACrF;;EAEA,UAAU;GAAE,QAAQ,CAAC;GAAG,MAAM,CAAC;GAAG,MAAM,CAAC;EAAE;;EAE3C,QAAQ;GAGN,MAAM;IACJ,MAAM;IACN,MAAM;IACN,SAAS;GACX;GACA,OAAO,EAAE,MAAM,4DAA4D;EAC7E;;EAEA,QAAQ;GACN,MAAM;IACJ,MAAM,CACJ,0DACA,kDACF;IACA,MAAM;GACR;GACA,OAAO,CAAC;EACV;EACA,aAAa;GAAE,MAAM,EAAE,MAAM,8CAA8C;GAAG,OAAO,CAAC;EAAE;;EAExF,WAAW;GACT,MAAM;IACJ,MAAM;IACN,MAAM;GACR;GACA,OAAO,EAAE,MAAM,aAAa;EAC9B;CACF;CACA,kBAAkB;EAChB;GACE,UAAU,CAAC,UAAU,MAAM;GAC3B,aAAa;GACb,OAAO;IAAE,UAAU;IAAyB,MAAM;GAAa;EACjE;EACA;GACE,UAAU,CAAC,UAAU,MAAM;GAC3B,aAAa;GACb,OAAO;IAAE,UAAU;IAAyB,MAAM;GAAa;EACjE;EACA;GAAE,UAAU;GAAU,OAAO,EAAE,MAAM,cAAc;EAAE;EAGrD;GAAE,aAAa;GAAY,WAAW;GAAO,OAAO,EAAE,UAAU,uBAAuB;EAAE;CAC3F;CACA,iBAAiB;EACf,aAAa;EACb,UAAU;EACV,QAAQ;EACR,QAAQ;EACR,aAAa;EACb,WAAW;CACb;AACF,CAAC"}
1
+ {"version":3,"file":"carousel-styles.js","names":[],"sources":["../../../src/components/carousel/carousel-styles.ts"],"sourcesContent":["import { tv, type VariantProps } from '../../utils/tv';\n\n/*\n * Values follow the M3 Expressive carousel spec (2026-10-13) and Compose Material 3\n * (carousel/Carousel.kt, Keylines.kt, Strategy.kt):\n *\n * - Multi-browse and hero: 16px leading and trailing padding, 8px top and bottom, 8px\n * between items. Uncontained (and multi-aspect): 16px leading padding only. Full-screen:\n * no padding, 16px between items and no corners. Small items are 40–56px.\n * - Snapping: hero and full-screen move one item at a time (`scroll-snap-stop: always`);\n * multi-browse flings across many items and then snaps; uncontained and multi-aspect\n * scroll freely unless `snap=\"item\"`.\n * - Uncontained (and multi-aspect) items keep one size and flow past the end edge; only\n * multi-browse and hero items follow keylines.\n * - Each item's mask is filled with `surface`, the spec's container colour, so transparent\n * or still-loading content never shows what's behind the carousel.\n * - Items are masked with 28px (extra-large) corners, as Compose's samples do with\n * `maskClip(MaterialTheme.shapes.extraLarge)`; the component token\n * `--md-comp-carousel-item-container-shape` (`carousel-tokens.ts`) sets them. A\n * pressed item's corners tighten to `--m3-carousel-pressed-corner` (20px, large-increased)\n * on the fast spatial spring, the spec's \"changes the shape slightly\".\n *\n * The carousel scrolls natively. Items keep their natural slots (the large item size), and\n * a library-owned mask layer inside each is translated and clipped to its keyline on every\n * scroll frame, so the root is never transformed. The state layer is a library-owned\n * element sharing the mask's grid cell, painted over the item (nothing is positioned).\n * Under the mask, a press area follows it, widened to 48px for a small item (40–56px):\n * M3's touch target, taken from the 8px spacing, so neighbours never overlap.\n * Every class is written out in full.\n */\n\n/** Variant definitions for {@link Carousel}. */\nexport const carouselStyles = tv({\n slots: {\n root: [\n 'flex min-h-0 min-w-0',\n '[--m3-carousel-corner:var(--_md-comp-carousel-item-container-shape)]',\n '[--m3-carousel-pressed-corner:var(--md-sys-shape-corner-large-increased)]',\n ],\n scroller: [\n 'flex min-h-0 min-w-0 flex-1 outline-none [scrollbar-width:none]',\n 'data-dragging:cursor-grabbing data-dragging:[scroll-snap-type:none] data-dragging:select-none',\n '[&::-webkit-scrollbar]:hidden',\n ],\n // The focus ring is drawn inside: items sit against the scroller's edges in every layout\n // (Compose keeps the padding in the keylines), so a ring outside was cut where they meet.\n item: 'flex shrink-0 rounded-(--m3-carousel-corner) focus-ring-inset',\n mask: [\n 'grid size-full overflow-hidden bg-surface [&>*]:[grid-area:1/1] [&>*]:size-full',\n '[--m3-carousel-item-corner:var(--m3-carousel-corner)]',\n 'data-pressed:[--m3-carousel-item-corner:var(--m3-carousel-pressed-corner)]',\n '[transition-property:--m3-carousel-item-corner]',\n '[transition-duration:var(--md-sys-motion-spring-spatial-fast-duration)]',\n '[transition-timing-function:var(--md-sys-motion-spring-spatial-fast-easing)]',\n 'motion-reduce:[transition-duration:0s]',\n 'data-disabled:opacity-38',\n ],\n stateLayer:\n 'pointer-events-none state-layer [--m3-state-layer-color:var(--md-sys-color-on-surface)]',\n // The item's press area, laid under the mask in the same place (a negative end margin,\n // so nothing is positioned).\n hitArea: 'h-full w-full shrink-0 -me-[100%]',\n },\n variants: {\n orientation: {\n // Overscroll is contained on the carousel's own axis only, so a swipe across it\n // (a vertical swipe on a horizontal carousel) still scrolls the page (2026-10-15).\n horizontal: {\n scroller: 'flex-row overflow-x-auto overflow-y-hidden overscroll-x-contain',\n item: 'h-full',\n },\n vertical: { scroller: 'flex-col overflow-x-hidden overflow-y-auto', item: 'w-full' },\n },\n /** `single` stops at every item, `many` lets a fling cross several, `none` doesn't snap. */\n snapping: { single: {}, many: {}, none: {} },\n /** The mask is clipped by the keylines on every scroll frame; otherwise by CSS. */\n masked: {\n // Only the mask and the press area under it take presses, not the rest of the slot, so\n // a press between items never lands on an item whose slot reaches there.\n true: {\n item: 'pointer-events-none',\n mask: 'pointer-events-auto',\n hitArea: 'pointer-events-auto',\n },\n false: { mask: '[clip-path:inset(0_round_var(--m3-carousel-item-corner))]' },\n },\n /** Multi-aspect items keep their own width, between 9:16 and 16:9 of the height. */\n aspect: {\n true: {\n item: [\n 'w-max min-w-[calc(var(--m3-carousel-cross-size)*9/16)]',\n 'max-w-[calc(var(--m3-carousel-cross-size)*16/9)]',\n ],\n mask: '[&>*]:h-full [&>*]:w-auto [&>*]:min-w-full [&>*]:max-w-full [&>*]:object-cover',\n },\n false: {},\n },\n interactive: { true: { item: 'cursor-pointer data-disabled:cursor-default' }, false: {} },\n /** Full-bleed items fill the window edge to edge: no corners. */\n fullBleed: {\n true: { root: '[--m3-carousel-corner:0px] [--m3-carousel-pressed-corner:0px]' },\n false: {},\n },\n },\n compoundVariants: [\n {\n snapping: ['single', 'many'],\n orientation: 'horizontal',\n class: { scroller: 'snap-x snap-mandatory', item: 'snap-start' },\n },\n {\n snapping: ['single', 'many'],\n orientation: 'vertical',\n class: { scroller: 'snap-y snap-mandatory', item: 'snap-start' },\n },\n { snapping: 'single', class: { item: 'snap-always' } },\n // A full-screen vertical carousel fills the window, so past its last item a swipe goes\n // on to the page instead of trapping it.\n { orientation: 'vertical', fullBleed: false, class: { scroller: 'overscroll-y-contain' } },\n ],\n defaultVariants: {\n orientation: 'horizontal',\n snapping: 'single',\n masked: true,\n aspect: false,\n interactive: false,\n fullBleed: false,\n },\n});\n\n/**\n * The variants of {@link carouselStyles}, for building on its styles. They are the recipe's keys, not\n * component props: their names (`hasIcon`, `isOpen`…) follow the classes and may change.\n */\nexport type CarouselStyleProps = VariantProps<typeof carouselStyles>;\n"],"mappings":";;;AAgCA,MAAa,iBAAiB,GAAG;CAC/B,OAAO;EACL,MAAM;GACJ;GACA;GACA;EACF;EACA,UAAU;GACR;GACA;GACA;EACF;EAGA,MAAM;EACN,MAAM;GACJ;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;EACA,YACE;EAGF,SAAS;CACX;CACA,UAAU;EACR,aAAa;GAGX,YAAY;IACV,UAAU;IACV,MAAM;GACR;GACA,UAAU;IAAE,UAAU;IAA8C,MAAM;GAAS;EACrF;;EAEA,UAAU;GAAE,QAAQ,CAAC;GAAG,MAAM,CAAC;GAAG,MAAM,CAAC;EAAE;;EAE3C,QAAQ;GAGN,MAAM;IACJ,MAAM;IACN,MAAM;IACN,SAAS;GACX;GACA,OAAO,EAAE,MAAM,4DAA4D;EAC7E;;EAEA,QAAQ;GACN,MAAM;IACJ,MAAM,CACJ,0DACA,kDACF;IACA,MAAM;GACR;GACA,OAAO,CAAC;EACV;EACA,aAAa;GAAE,MAAM,EAAE,MAAM,8CAA8C;GAAG,OAAO,CAAC;EAAE;;EAExF,WAAW;GACT,MAAM,EAAE,MAAM,gEAAgE;GAC9E,OAAO,CAAC;EACV;CACF;CACA,kBAAkB;EAChB;GACE,UAAU,CAAC,UAAU,MAAM;GAC3B,aAAa;GACb,OAAO;IAAE,UAAU;IAAyB,MAAM;GAAa;EACjE;EACA;GACE,UAAU,CAAC,UAAU,MAAM;GAC3B,aAAa;GACb,OAAO;IAAE,UAAU;IAAyB,MAAM;GAAa;EACjE;EACA;GAAE,UAAU;GAAU,OAAO,EAAE,MAAM,cAAc;EAAE;EAGrD;GAAE,aAAa;GAAY,WAAW;GAAO,OAAO,EAAE,UAAU,uBAAuB;EAAE;CAC3F;CACA,iBAAiB;EACf,aAAa;EACb,UAAU;EACV,QAAQ;EACR,QAAQ;EACR,aAAa;EACb,WAAW;CACb;AACF,CAAC"}
@@ -2,6 +2,6 @@ import { ComponentTokenSet } from "../../tokens/component.js";
2
2
  import "../../index.js";
3
3
  //#region src/components/checkbox/checkbox-tokens.d.ts
4
4
  /** The tokens of {@link Checkbox}: `--md-comp-checkbox-<part>`. */
5
- export declare const checkboxTokenSet: ComponentTokenSet<"selected-container-color" | "selected-icon-color" | "unselected-outline-color">;
5
+ export declare const checkboxTokenSet: ComponentTokenSet<"selected-icon-color" | "selected-container-color" | "unselected-outline-color">;
6
6
  //#endregion
7
7
  //# sourceMappingURL=checkbox-tokens.d.ts.map
@@ -381,11 +381,18 @@ function RangeMonthList({ state, styles, className, classNames }) {
381
381
  useLayoutEffect(() => {
382
382
  const list = listRef.current;
383
383
  if (!list) return;
384
+ let opened = list.getClientRects().length > 0;
384
385
  list.scrollTop = initialTop.current;
385
- const measure = () => setView({
386
- top: list.scrollTop,
387
- height: list.clientHeight
388
- });
386
+ const measure = () => {
387
+ if (!opened && list.clientHeight > 0) {
388
+ opened = true;
389
+ list.scrollTop = initialTop.current;
390
+ }
391
+ setView({
392
+ top: list.scrollTop,
393
+ height: list.clientHeight
394
+ });
395
+ };
389
396
  measure();
390
397
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
391
398
  observer?.observe(list);
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker.js","names":[],"sources":["../../../src/components/date-picker/DatePicker.tsx"],"sourcesContent":["'use client';\n\nimport {\n CalendarDate,\n createCalendar,\n getLocalTimeZone,\n maxDate,\n minDate,\n startOfWeek,\n toCalendarDate,\n today,\n type DateValue,\n} from '@internationalized/date';\nimport {\n useContext,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type HTMLAttributes,\n type ReactNode,\n type Ref,\n type TransitionEvent,\n} from 'react';\nimport {\n mergeProps,\n useCalendar,\n useDateFormatter,\n useLocale,\n useRangeCalendar,\n type AriaButtonProps,\n} from 'react-aria';\nimport {\n useCalendarState,\n useRangeCalendarState,\n type CalendarState,\n type RangeCalendarState,\n} from 'react-stately';\nimport { useControlledState } from 'react-stately/useControlledState';\nimport { DomDirectionLocale } from '../../primitives/DomDirectionLocale';\nimport { useSizeTransform } from './use-size-transform';\nimport { useViewExit } from './use-view-exit';\nimport { usePresence } from '../../primitives/use-presence';\nimport { cn } from '../../utils/cn';\nimport { mergeDataTokens } from '../../utils/merge-data-tokens';\nimport {\n splitRootProps,\n type DescriptionAria,\n type WrapperRootDOMProps,\n} from '../../utils/root-props';\nimport { Button } from '../button/Button';\nimport { IconButton } from '../icon-button/IconButton';\nimport { LazyTooltip } from '../tooltip/lazy-tooltip';\nimport { TooltipTrigger } from '../tooltip/tooltip-trigger';\nimport { CalendarGrid } from './CalendarGrid';\nimport { ChoiceButton, ShortcutIconButton, useMonthSwipe, usePickerKeys } from './calendar-parts';\nimport type { Density } from '../../tokens/density';\nimport { DateInput, type DateInputLabels } from './DateInput';\nimport { datePickerStyles } from './date-picker-styles';\nimport { PickerDialogContext } from './picker-dialog-context';\nimport {\n ArrowDropDownIcon,\n CalendarIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n EditIcon,\n} from './picker-icons';\n\n/** The picker's labels, for localisation. */\nexport interface DatePickerLabels extends DateInputLabels {\n /** The header's title in calendar mode. @default \"Select date\", or \"Select dates\" for a range */\n title: string;\n /**\n * The title in text input mode (the M3 modal date input's \"Enter date\").\n * @default \"Enter date\", or \"Enter dates\" for a range\n */\n inputTitle: string;\n /** Headline when nothing is selected. @default \"Selected date\" / \"Start date – End date\" */\n noSelection: string;\n /** The previous month button. @default \"Previous month\" */\n previousMonth: string;\n /** The next month button. @default \"Next month\" */\n nextMonth: string;\n /** Tooltip of the previous-month button, naming its shortcut. @default \"Previous month (Page Up)\" */\n previousMonthTooltip: string;\n /** Tooltip of the next-month button, naming its shortcut. @default \"Next month (Page Down)\" */\n nextMonthTooltip: string;\n /** The month and year button while the days show. @default \"Switch to selecting a year\" */\n showYears: string;\n /** The month and year button while the years show. @default \"Switch to selecting a day\" */\n showDays: string;\n /** Tooltip of the month and year button, naming its shortcut. @default \"Choose a year (Shift+Y)\" */\n yearsTooltip: string;\n /** Name of the year list. @default \"Year\" */\n yearList: string;\n /** The mode toggle in calendar mode. @default \"Switch to text input mode\" */\n inputMode: string;\n /** The mode toggle in text input mode. @default \"Switch to calendar input mode\" */\n calendarMode: string;\n /** Label of the input mode's field. @default \"Date\" */\n dateLabel: string;\n /** Label of a range's start field in input mode. @default \"Start date\" */\n startDateLabel: string;\n /**\n * Label of a range's end field in input mode, and the headline's end while a range is\n * being picked (\"Mar 20 – End date\"). @default \"End date\"\n */\n endDateLabel: string;\n}\n\nexport interface DatePickerClassNames {\n /** The picker's root; `className` is merged here too. */\n root?: string;\n /** The header: title, headline and mode toggle. */\n header?: string;\n /** The header's title (\"Select date\"). */\n title?: string;\n /** The header's headline: the chosen date or range. */\n headline?: string;\n /** The calendar or the text input below the header. */\n body?: string;\n /** The weekday names above the days. */\n weekday?: string;\n /** Each day of the calendar. */\n day?: string;\n /** Each year of the year list. */\n year?: string;\n /** The month and year button above the days, which shows the year list. */\n yearButton?: string;\n /** Each month's subhead in the range picker's scrolling month list. */\n monthSubhead?: string;\n}\n\nexport interface DateRangePickerClassNames extends DatePickerClassNames {\n /**\n * The band behind a range's days: each calendar cell it spans (`data-range` is `start`,\n * `middle` or `end`), whose background paints it.\n */\n rangeBand?: string;\n}\n\n// No `aria-description` and the like: the picker's root is a plain container, and no single\n// element in it stands for the whole picker.\ninterface DatePickerCommonProps extends Omit<WrapperRootDOMProps, DescriptionAria> {\n /** Earliest date allowed; earlier days are disabled. */\n min?: DateValue;\n /** Latest date allowed; later days are disabled. */\n max?: DateValue;\n /** Returns `true` for a day that can't be picked (it shows disabled). */\n isDateUnavailable?: (date: DateValue) => boolean;\n /** Show the header (title, headline and mode toggle). @default true */\n header?: boolean;\n /** Show the calendar ↔ text input toggle. @default true */\n modeToggle?: boolean;\n /** Start in calendar or text input mode. @default \"calendar\" */\n defaultMode?: 'calendar' | 'input';\n /**\n * First and last years of the year list (and of a range's month list). Years outside\n * `min` / `max` are shown disabled. @default [1900, 2100]\n */\n yearRange?: [number, number];\n /** Words the picker shows and announces, with English defaults. */\n labels?: Partial<DatePickerLabels>;\n /**\n * Web density of the input mode's text fields, `0` to `-3`: each step takes 4px off them\n * (56px at 0, 44px at -3). The calendar keeps its size: M3 doesn't make date pickers denser,\n * since their 48px day targets are part of their accessibility. Left out, the fields take\n * the density of the nearest `ThemeProvider` or `ThemeScope`.\n * @default 0\n */\n density?: Density;\n /** The root `<div>`'s id. */\n id?: string;\n /** Ref to the root `<div>` element. */\n ref?: Ref<HTMLDivElement>;\n /** Classes for the root element, merged with `classNames.root`; consumer classes win. */\n className?: string;\n /** Inline styles for the root element. */\n style?: CSSProperties;\n /** Classes for each part, by slot. */\n classNames?: DatePickerClassNames;\n /** `data-*` attributes go to the root. */\n [data: `data-${string}`]: string | number | boolean | undefined;\n}\n\nexport type DatePickerProps = DatePickerCommonProps & {\n /** The selected date (controlled); `null` for none. */\n value?: CalendarDate | null;\n /** Initial date when uncontrolled. @default null */\n defaultValue?: CalendarDate | null;\n /** Called with the date the user picks or types. */\n onChange?: (value: CalendarDate) => void;\n};\n\nexport interface DateRange {\n start: CalendarDate;\n end: CalendarDate;\n}\n\nexport type DateRangePickerProps = Omit<DatePickerCommonProps, 'classNames'> & {\n /** Classes for each part, by slot. */\n classNames?: DateRangePickerClassNames;\n /** The selected range (controlled); `null` for none. */\n value?: DateRange | null;\n /** Initial range when uncontrolled. @default null */\n defaultValue?: DateRange | null;\n /** Called with the range once both its start and end are picked or typed. */\n onChange?: (value: DateRange) => void;\n /**\n * `scroll` lists the months one under another and scrolls vertically, as the M3 modal\n * range picker does; `paged` shows one month at a time with previous / next buttons and\n * a year list, like the date picker. @default \"scroll\"\n */\n monthLayout?: 'scroll' | 'paged';\n};\n\n/**\n * M3 modal date picker (Compose's `DatePicker`): a header with the selected date, a month\n * grid you page with the arrows, a horizontal swipe or Page Up / Down, a year list, and a\n * text input mode. Put it in a {@link PickerDialog} for the modal form; {@link DateField}\n * is the docked form. Values are `@internationalized/date` dates.\n *\n * @example\n * <DatePicker value={date} onChange={setDate} />\n */\nexport function DatePicker(props: DatePickerProps) {\n return (\n <DomDirectionLocale>\n {(directionRef) => <SingleDatePicker {...props} directionRef={directionRef} />}\n </DomDirectionLocale>\n );\n}\n\n/**\n * M3 date range picker (Compose's `DateRangePicker`): select a start and an end date on a\n * vertically scrolling list of months, or type them in input mode.\n *\n * @example\n * <DateRangePicker value={range} onChange={setRange} />\n */\nexport function DateRangePicker(props: DateRangePickerProps) {\n return (\n <DomDirectionLocale>\n {(directionRef) => <RangeDatePicker {...props} directionRef={directionRef} />}\n </DomDirectionLocale>\n );\n}\n\ntype Inner<P> = P & { directionRef: (element: HTMLElement | null) => void };\n\nfunction SingleDatePicker(props: Inner<DatePickerProps>) {\n const { locale } = useLocale();\n const confirm = useContext(PickerDialogContext);\n const [value, setValue] = useControlledState(\n props.value,\n props.defaultValue ?? null,\n props.onChange as (value: CalendarDate | null) => void,\n );\n const state = useCalendarState({\n value,\n onChange: (date) => setValue(date as CalendarDate),\n minValue: props.min,\n maxValue: props.max,\n isDateUnavailable: props.isDateUnavailable,\n locale,\n createCalendar,\n });\n const formatter = useDateFormatter({ dateStyle: 'medium' });\n const labels = props.labels ?? {};\n const headline = value\n ? formatter.format(value.toDate(getLocalTimeZone()))\n : (labels.noSelection ?? 'Selected date');\n return (\n <PickerFrame\n {...props}\n range={false}\n state={state}\n headline={headline}\n input={\n <DateInput\n label={labels.dateLabel ?? 'Date'}\n value={value}\n onCommit={(date) => date && setValue(date)}\n onEnter={(date) => date && confirm?.requestConfirm()}\n min={props.min}\n max={props.max}\n isDateUnavailable={props.isDateUnavailable}\n labels={labels}\n density={props.density}\n className=\"w-full\"\n />\n }\n />\n );\n}\n\n/** Whole months from `from` to `to`. */\nconst monthsBetween = (from: CalendarDate, to: CalendarDate) =>\n (to.year - from.year) * 12 + (to.month - from.month);\n\nfunction RangeDatePicker({ monthLayout = 'scroll', ...props }: Inner<DateRangePickerProps>) {\n const { locale } = useLocale();\n const confirm = useContext(PickerDialogContext);\n const [value, setValue] = useControlledState(\n props.value,\n props.defaultValue ?? null,\n props.onChange as (value: DateRange | null) => void,\n );\n // The scrolling list shows every month of the year range (within min / max) at once.\n const [firstYear, lastYear] = props.yearRange ?? [1900, 2100];\n const scroll = monthLayout === 'scroll';\n const listStart = maxDate(\n new CalendarDate(firstYear, 1, 1),\n props.min ? toCalendarDate(props.min) : null,\n )!;\n const listEnd = minDate(\n new CalendarDate(lastYear, 12, 31),\n props.max ? toCalendarDate(props.max) : null,\n )!;\n const state = useRangeCalendarState({\n value,\n onChange: (range) => setValue(range as DateRange),\n minValue: scroll ? listStart : props.min,\n maxValue: scroll ? listEnd : props.max,\n isDateUnavailable: props.isDateUnavailable,\n visibleDuration: scroll ? { months: monthsBetween(listStart, listEnd) + 1 } : undefined,\n locale,\n createCalendar,\n });\n const formatter = useDateFormatter({ month: 'short', day: 'numeric' });\n const labels = props.labels ?? {};\n const format = (date: CalendarDate) => formatter.format(date.toDate(getLocalTimeZone()));\n // While a new range is being picked, its first day is the start and the end is still open\n // (Compose's headline: \"Mar 20 – End date\"), not the range it replaces.\n const anchor = state.anchorDate;\n const headline = anchor\n ? `${format(anchor)} – ${labels.endDateLabel ?? 'End date'}`\n : value\n ? `${format(value.start)} – ${format(value.end)}`\n : (labels.noSelection ?? 'Start date – End date');\n const common = {\n min: props.min,\n max: props.max,\n isDateUnavailable: props.isDateUnavailable,\n labels,\n density: props.density,\n className: 'w-full',\n };\n return (\n <PickerFrame\n {...props}\n range\n scroll={scroll}\n state={state}\n headline={headline}\n input={\n <>\n <DateInput\n {...common}\n label={labels.startDateLabel ?? 'Start date'}\n value={value?.start ?? null}\n onCommit={(start) =>\n start && setValue({ start, end: value && value.end >= start ? value.end : start })\n }\n />\n <DateInput\n {...common}\n label={labels.endDateLabel ?? 'End date'}\n value={value?.end ?? null}\n onCommit={(end) =>\n end && setValue({ start: value && value.start <= end ? value.start : end, end })\n }\n onEnter={(end) => end && value && confirm?.requestConfirm()}\n />\n </>\n }\n />\n );\n}\n\nfunction PickerFrame({\n range,\n scroll = false,\n state,\n headline,\n input,\n header = true,\n modeToggle = true,\n defaultMode = 'calendar',\n yearRange = [1900, 2100],\n labels = {},\n id,\n ref,\n className,\n style,\n classNames,\n directionRef,\n ...rest\n}: Inner<Omit<DatePickerCommonProps, 'classNames'>> & {\n classNames?: DateRangePickerClassNames | undefined;\n range: boolean;\n scroll?: boolean;\n state: CalendarState | RangeCalendarState;\n headline: string;\n input: ReactNode;\n value?: unknown;\n defaultValue?: unknown;\n onChange?: unknown;\n}) {\n const { root: data } = splitRootProps(rest, { wrapper: true });\n const [mode, setMode] = useState(defaultMode);\n // Set once the mode has been switched, so only a switch animates (not the first render).\n const [switched, setSwitched] = useState(false);\n const [years, setYears] = useState(false);\n // The picker's height follows the view on the default spatial spring (Compose's\n // `SizeTransform` in its display mode animation), as the views swap.\n const { attach: attachSize, capture: captureSize } = useSizeTransform<HTMLDivElement>(mode);\n // The outgoing view fades out as it slides away (Compose: up 48px as the input comes in,\n // down by its whole height as the calendar comes back), clipped with the new one.\n const {\n attachView: attachExitView,\n attachSlot: attachExitSlot,\n capture: captureExit,\n } = useViewExit(mode);\n const styles = datePickerStyles({ range });\n const title =\n mode === 'input'\n ? (labels.inputTitle ?? (range ? 'Enter dates' : 'Enter date'))\n : (labels.title ?? (range ? 'Select dates' : 'Select date'));\n const bodyProps = {\n styles,\n years,\n setYears,\n yearRange,\n labels,\n className: classNames?.body,\n classNames,\n };\n return (\n <div\n {...data}\n id={id}\n ref={(element) => {\n attachSize(element);\n directionRef(element);\n if (typeof ref === 'function') ref(element);\n else if (ref) ref.current = element;\n }}\n style={style}\n // The modal date picker's component tokens (date-picker-tokens.ts).\n data-tokens={mergeDataTokens('md-comp-date-picker-modal', data)}\n data-years={years || undefined}\n data-mode={mode}\n className={styles.root({ class: cn(classNames?.root, className) })}\n >\n {header && (\n <div className={styles.header({ class: classNames?.header })}>\n <div className={styles.title({ class: classNames?.title })}>{title}</div>\n <div className={styles.headlineRow()}>\n <div\n aria-live=\"polite\"\n data-slot=\"headline\"\n className={styles.headline({ class: classNames?.headline })}\n >\n {headline}\n </div>\n {modeToggle && (\n <IconButton\n variant=\"standard\"\n // The picker's surface isn't dense, only its input mode's fields.\n density={0}\n icon={mode === 'calendar' ? <EditIcon /> : <CalendarIcon />}\n aria-label={\n mode === 'calendar'\n ? (labels.inputMode ?? 'Switch to text input mode')\n : (labels.calendarMode ?? 'Switch to calendar input mode')\n }\n onPress={() => {\n captureSize();\n captureExit(mode === 'calendar' ? '-48px' : '100%');\n setSwitched(true);\n setMode(mode === 'calendar' ? 'input' : 'calendar');\n }}\n />\n )}\n </div>\n </div>\n )}\n <div className={styles.modeStack()}>\n <div\n key={mode}\n ref={attachExitView}\n data-enter={switched ? mode : undefined}\n className={styles.modeView()}\n >\n {mode === 'input' ? (\n <div className={styles.input({ class: classNames?.body })}>{input}</div>\n ) : range && scroll ? (\n <RangeMonthList state={state as RangeCalendarState} {...bodyProps} />\n ) : range ? (\n <RangeCalendarBody state={state as RangeCalendarState} {...bodyProps} />\n ) : (\n <SingleCalendarBody state={state as CalendarState} {...bodyProps} />\n )}\n </div>\n <div ref={attachExitSlot} aria-hidden=\"true\" inert className={styles.modeExit()} />\n </div>\n </div>\n );\n}\n\ninterface BodyProps {\n styles: ReturnType<typeof datePickerStyles>;\n years: boolean;\n setYears: (open: boolean) => void;\n yearRange: [number, number];\n labels: Partial<DatePickerLabels>;\n className?: string | undefined;\n classNames?: DateRangePickerClassNames | undefined;\n}\n\nfunction SingleCalendarBody({ state, ...props }: BodyProps & { state: CalendarState }) {\n const { calendarProps, prevButtonProps, nextButtonProps } = useCalendar({}, state);\n return (\n <CalendarBody\n {...props}\n state={state}\n calendarProps={calendarProps}\n prevButtonProps={prevButtonProps}\n nextButtonProps={nextButtonProps}\n />\n );\n}\n\nfunction RangeCalendarBody({ state, ...props }: BodyProps & { state: RangeCalendarState }) {\n const ref = useRef<HTMLDivElement>(null);\n const { calendarProps, prevButtonProps, nextButtonProps } = useRangeCalendar({}, state, ref);\n return (\n <CalendarBody\n {...props}\n bodyRef={ref}\n state={state}\n calendarProps={calendarProps}\n prevButtonProps={prevButtonProps}\n nextButtonProps={nextButtonProps}\n />\n );\n}\n\nfunction CalendarBody({\n state,\n calendarProps,\n prevButtonProps,\n nextButtonProps,\n styles,\n years,\n setYears,\n yearRange,\n labels,\n className,\n classNames,\n bodyRef,\n}: BodyProps & {\n state: CalendarState | RangeCalendarState;\n calendarProps: HTMLAttributes<HTMLElement>;\n prevButtonProps: AriaButtonProps;\n nextButtonProps: AriaButtonProps;\n bodyRef?: Ref<HTMLDivElement>;\n}) {\n const confirm = useContext(PickerDialogContext);\n const monthFormatter = useDateFormatter({ month: 'long', year: 'numeric' });\n const monthLabel = monthFormatter.format(state.visibleRange.start.toDate(getLocalTimeZone()));\n const menuRef = useRef<HTMLButtonElement>(null);\n const [focusYears, setFocusYears] = useState(false);\n // Compose shrinks the year list and fades it out (`shrinkVertically` + `fadeOut`); the\n // first of the two transitions to end removes it.\n const yearsPresence = usePresence(years, ['clip-path', 'opacity']);\n const { swipeProps, slideKey, slideDirection } = useMonthSwipe(state);\n const onKeyDownCapture = usePickerKeys(state, {\n onConfirm: confirm?.requestConfirm,\n onMonthMenu: () => menuRef.current?.focus(),\n onYearMenu: () => {\n setFocusYears(true);\n setYears(true);\n },\n });\n return (\n <div\n {...calendarProps}\n ref={bodyRef}\n onKeyDownCapture={onKeyDownCapture}\n className={styles.body({ class: className })}\n >\n <div className={styles.nav()}>\n <TooltipTrigger>\n <Button\n ref={menuRef}\n variant=\"text\"\n className={cn('text-on-surface-variant', classNames?.yearButton)}\n aria-label={`${monthLabel}, ${years ? (labels.showDays ?? 'Switch to selecting a day') : (labels.showYears ?? 'Switch to selecting a year')}`}\n onPress={() => {\n setFocusYears(false);\n setYears(!years);\n }}\n >\n {/* The drop-down arrow trails the label here, which Button's one leading icon can't do. */}\n <span className=\"inline-flex items-center gap-[8px]\">\n <span aria-live=\"polite\">{monthLabel}</span>\n <span\n aria-hidden=\"true\"\n className=\"inline-flex size-[20px] items-center justify-center\"\n >\n <span className={styles.yearButtonIcon()}>\n <ArrowDropDownIcon />\n </span>\n </span>\n </span>\n </Button>\n <LazyTooltip>{labels.yearsTooltip ?? 'Choose a year (Shift+Y)'}</LazyTooltip>\n </TooltipTrigger>\n {!years && (\n <div className={styles.navButtons()}>\n <ShortcutIconButton\n icon={<ChevronLeftIcon />}\n label={labels.previousMonth ?? 'Previous month'}\n tooltip={labels.previousMonthTooltip ?? 'Previous month (Page Up)'}\n onPress={prevButtonProps.onPress as () => void}\n disabled={prevButtonProps.isDisabled}\n />\n <ShortcutIconButton\n icon={<ChevronRightIcon />}\n label={labels.nextMonth ?? 'Next month'}\n tooltip={labels.nextMonthTooltip ?? 'Next month (Page Down)'}\n onPress={nextButtonProps.onPress as () => void}\n disabled={nextButtonProps.isDisabled}\n />\n </div>\n )}\n </div>\n {!years && (\n <div {...swipeProps} className={styles.swipe()}>\n <div key={slideKey} data-direction={slideDirection} className={styles.slide()}>\n <CalendarGrid state={state} styles={styles} classNames={classNames} />\n </div>\n </div>\n )}\n {/* Closing, the list stays over the grid until it has shrunk and faded away. */}\n {yearsPresence.isPresent && (\n <YearList\n state={state}\n styles={styles}\n yearRange={yearRange}\n className={classNames?.year}\n label={labels.yearList ?? 'Year'}\n autoFocus={focusYears}\n exiting={yearsPresence.isExiting}\n exitProps={yearsPresence.exitProps}\n onPick={() => setYears(false)}\n />\n )}\n </div>\n );\n}\n\n/**\n * The range picker's months, one under another in a vertical scroll (M3: \"To navigate\n * across months, scroll vertically\"), under a single weekday row. Only the months in view\n * (and the focused one) are rendered; the rest are spacers of the same fixed height.\n */\nfunction RangeMonthList({\n state,\n styles,\n className,\n classNames,\n}: BodyProps & { state: RangeCalendarState }) {\n const confirm = useContext(PickerDialogContext);\n const ref = useRef<HTMLDivElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const { calendarProps } = useRangeCalendar({}, state, ref);\n const { locale } = useLocale();\n const first = state.visibleRange.start;\n const count = monthsBetween(first, state.visibleRange.end) + 1;\n const focusedIndex = monthsBetween(first, state.focusedDate);\n const [view, setView] = useState(() => ({ top: focusedIndex * MONTH_HEIGHT, height: 0 }));\n const weekdays = useDateFormatter({ weekday: 'narrow' });\n const longWeekdays = useDateFormatter({ weekday: 'long' });\n const subhead = useDateFormatter({ month: 'long', year: 'numeric' });\n const onKeyDownCapture = usePickerKeys(state, {\n onConfirm: confirm?.requestConfirm,\n onMonthMenu: () => undefined,\n onYearMenu: () => undefined,\n });\n\n // Open on the focused month (the range's start, or today), then follow the scroll.\n const initialTop = useRef(view.top);\n useLayoutEffect(() => {\n const list = listRef.current;\n if (!list) return;\n list.scrollTop = initialTop.current;\n const measure = () => setView({ top: list.scrollTop, height: list.clientHeight });\n measure();\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(measure);\n observer?.observe(list);\n list.addEventListener('scroll', measure, { passive: true });\n return () => {\n observer?.disconnect();\n list.removeEventListener('scroll', measure);\n };\n }, []);\n\n const height = view.height || MONTH_HEIGHT;\n let from = Math.max(0, Math.floor(view.top / MONTH_HEIGHT) - 1);\n let to = Math.min(count - 1, Math.floor((view.top + height) / MONTH_HEIGHT) + 1);\n if (state.isFocused) {\n from = Math.min(from, focusedIndex);\n to = Math.max(to, focusedIndex);\n }\n const weekStart = startOfWeek(today(getLocalTimeZone()), locale);\n\n return (\n <div\n {...mergeProps(calendarProps, { onKeyDownCapture })}\n ref={ref}\n className={styles.body({ class: cn('min-h-0 flex-1', className) })}\n >\n <div aria-hidden=\"true\" className={styles.weekdayRow()}>\n {Array.from({ length: 7 }, (_, index) => {\n const day = weekStart.add({ days: index }).toDate(getLocalTimeZone());\n return (\n <span\n key={index}\n title={longWeekdays.format(day)}\n className={styles.weekdayCell({ class: classNames?.weekday })}\n >\n {weekdays.format(day)}\n </span>\n );\n })}\n </div>\n <div ref={listRef} className={styles.months()}>\n <div style={{ height: from * MONTH_HEIGHT }} />\n {Array.from({ length: to - from + 1 }, (_, i) => {\n const month = first.add({ months: from + i });\n return (\n <div key={month.toString()} className=\"h-[336px]\">\n <div\n aria-hidden=\"true\"\n className={styles.monthSubhead({ class: classNames?.monthSubhead })}\n >\n {subhead.format(month.toDate(getLocalTimeZone()))}\n </div>\n <CalendarGrid state={state} styles={styles} month={month} classNames={classNames} />\n </div>\n );\n })}\n <div style={{ height: (count - 1 - to) * MONTH_HEIGHT }} />\n </div>\n </div>\n );\n}\n\n/** A month in the scrolling list: its 48px subhead and six 48px weeks. */\nconst MONTH_HEIGHT = 336;\n\nfunction YearList({\n state,\n styles,\n yearRange,\n className,\n label,\n autoFocus,\n exiting,\n exitProps,\n onPick,\n}: {\n state: CalendarState | RangeCalendarState;\n styles: ReturnType<typeof datePickerStyles>;\n yearRange: [number, number];\n className: string | undefined;\n label: string;\n autoFocus: boolean;\n /** Closing: drawn over the grid, out of the accessibility tree and taking no presses. */\n exiting: boolean;\n exitProps: { onTransitionEnd: (event: TransitionEvent<HTMLElement>) => void };\n onPick: () => void;\n}) {\n const current = today(getLocalTimeZone()).year;\n const focusedYear = state.focusedDate.year;\n const minYear = state.minValue?.year ?? -Infinity;\n const maxYear = state.maxValue?.year ?? Infinity;\n return (\n <div\n {...exitProps}\n role=\"radiogroup\"\n aria-label={label}\n aria-hidden={exiting || undefined}\n inert={exiting || undefined}\n data-exiting={exiting || undefined}\n className={styles.years()}\n ref={(element) => {\n if (exiting) return;\n // Open on the focused year, as Compose scrolls the year list to it.\n const selected = element?.querySelector<HTMLElement>('[aria-checked=\"true\"]');\n selected?.scrollIntoView?.({ block: 'center' });\n if (autoFocus) selected?.focus({ preventScroll: true });\n }}\n >\n {Array.from({ length: yearRange[1] - yearRange[0] + 1 }, (_, i) => yearRange[0] + i).map(\n (year) => (\n <ChoiceButton\n key={year}\n selected={year === focusedYear}\n disabled={year < minYear || year > maxYear}\n data-current={year === current || undefined}\n steps={YEAR_STEPS}\n className={styles.year({ class: className })}\n onPick={() => {\n state.setFocusedDate(state.focusedDate.set({ year }));\n onPick();\n }}\n >\n {year}\n </ChoiceButton>\n ),\n )}\n </div>\n );\n}\n\n/** Three years to a row. */\nconst YEAR_STEPS = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -3, ArrowDown: 3 };\n"],"mappings":"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"}
1
+ {"version":3,"file":"DatePicker.js","names":[],"sources":["../../../src/components/date-picker/DatePicker.tsx"],"sourcesContent":["'use client';\n\nimport {\n CalendarDate,\n createCalendar,\n getLocalTimeZone,\n maxDate,\n minDate,\n startOfWeek,\n toCalendarDate,\n today,\n type DateValue,\n} from '@internationalized/date';\nimport {\n useContext,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type HTMLAttributes,\n type ReactNode,\n type Ref,\n type TransitionEvent,\n} from 'react';\nimport {\n mergeProps,\n useCalendar,\n useDateFormatter,\n useLocale,\n useRangeCalendar,\n type AriaButtonProps,\n} from 'react-aria';\nimport {\n useCalendarState,\n useRangeCalendarState,\n type CalendarState,\n type RangeCalendarState,\n} from 'react-stately';\nimport { useControlledState } from 'react-stately/useControlledState';\nimport { DomDirectionLocale } from '../../primitives/DomDirectionLocale';\nimport { useSizeTransform } from './use-size-transform';\nimport { useViewExit } from './use-view-exit';\nimport { usePresence } from '../../primitives/use-presence';\nimport { cn } from '../../utils/cn';\nimport { mergeDataTokens } from '../../utils/merge-data-tokens';\nimport {\n splitRootProps,\n type DescriptionAria,\n type WrapperRootDOMProps,\n} from '../../utils/root-props';\nimport { Button } from '../button/Button';\nimport { IconButton } from '../icon-button/IconButton';\nimport { LazyTooltip } from '../tooltip/lazy-tooltip';\nimport { TooltipTrigger } from '../tooltip/tooltip-trigger';\nimport { CalendarGrid } from './CalendarGrid';\nimport { ChoiceButton, ShortcutIconButton, useMonthSwipe, usePickerKeys } from './calendar-parts';\nimport type { Density } from '../../tokens/density';\nimport { DateInput, type DateInputLabels } from './DateInput';\nimport { datePickerStyles } from './date-picker-styles';\nimport { PickerDialogContext } from './picker-dialog-context';\nimport {\n ArrowDropDownIcon,\n CalendarIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n EditIcon,\n} from './picker-icons';\n\n/** The picker's labels, for localisation. */\nexport interface DatePickerLabels extends DateInputLabels {\n /** The header's title in calendar mode. @default \"Select date\", or \"Select dates\" for a range */\n title: string;\n /**\n * The title in text input mode (the M3 modal date input's \"Enter date\").\n * @default \"Enter date\", or \"Enter dates\" for a range\n */\n inputTitle: string;\n /** Headline when nothing is selected. @default \"Selected date\" / \"Start date – End date\" */\n noSelection: string;\n /** The previous month button. @default \"Previous month\" */\n previousMonth: string;\n /** The next month button. @default \"Next month\" */\n nextMonth: string;\n /** Tooltip of the previous-month button, naming its shortcut. @default \"Previous month (Page Up)\" */\n previousMonthTooltip: string;\n /** Tooltip of the next-month button, naming its shortcut. @default \"Next month (Page Down)\" */\n nextMonthTooltip: string;\n /** The month and year button while the days show. @default \"Switch to selecting a year\" */\n showYears: string;\n /** The month and year button while the years show. @default \"Switch to selecting a day\" */\n showDays: string;\n /** Tooltip of the month and year button, naming its shortcut. @default \"Choose a year (Shift+Y)\" */\n yearsTooltip: string;\n /** Name of the year list. @default \"Year\" */\n yearList: string;\n /** The mode toggle in calendar mode. @default \"Switch to text input mode\" */\n inputMode: string;\n /** The mode toggle in text input mode. @default \"Switch to calendar input mode\" */\n calendarMode: string;\n /** Label of the input mode's field. @default \"Date\" */\n dateLabel: string;\n /** Label of a range's start field in input mode. @default \"Start date\" */\n startDateLabel: string;\n /**\n * Label of a range's end field in input mode, and the headline's end while a range is\n * being picked (\"Mar 20 – End date\"). @default \"End date\"\n */\n endDateLabel: string;\n}\n\nexport interface DatePickerClassNames {\n /** The picker's root; `className` is merged here too. */\n root?: string;\n /** The header: title, headline and mode toggle. */\n header?: string;\n /** The header's title (\"Select date\"). */\n title?: string;\n /** The header's headline: the chosen date or range. */\n headline?: string;\n /** The calendar or the text input below the header. */\n body?: string;\n /** The weekday names above the days. */\n weekday?: string;\n /** Each day of the calendar. */\n day?: string;\n /** Each year of the year list. */\n year?: string;\n /** The month and year button above the days, which shows the year list. */\n yearButton?: string;\n /** Each month's subhead in the range picker's scrolling month list. */\n monthSubhead?: string;\n}\n\nexport interface DateRangePickerClassNames extends DatePickerClassNames {\n /**\n * The band behind a range's days: each calendar cell it spans (`data-range` is `start`,\n * `middle` or `end`), whose background paints it.\n */\n rangeBand?: string;\n}\n\n// No `aria-description` and the like: the picker's root is a plain container, and no single\n// element in it stands for the whole picker.\ninterface DatePickerCommonProps extends Omit<WrapperRootDOMProps, DescriptionAria> {\n /** Earliest date allowed; earlier days are disabled. */\n min?: DateValue;\n /** Latest date allowed; later days are disabled. */\n max?: DateValue;\n /** Returns `true` for a day that can't be picked (it shows disabled). */\n isDateUnavailable?: (date: DateValue) => boolean;\n /** Show the header (title, headline and mode toggle). @default true */\n header?: boolean;\n /** Show the calendar ↔ text input toggle. @default true */\n modeToggle?: boolean;\n /** Start in calendar or text input mode. @default \"calendar\" */\n defaultMode?: 'calendar' | 'input';\n /**\n * First and last years of the year list (and of a range's month list). Years outside\n * `min` / `max` are shown disabled. @default [1900, 2100]\n */\n yearRange?: [number, number];\n /** Words the picker shows and announces, with English defaults. */\n labels?: Partial<DatePickerLabels>;\n /**\n * Web density of the input mode's text fields, `0` to `-3`: each step takes 4px off them\n * (56px at 0, 44px at -3). The calendar keeps its size: M3 doesn't make date pickers denser,\n * since their 48px day targets are part of their accessibility. Left out, the fields take\n * the density of the nearest `ThemeProvider` or `ThemeScope`.\n * @default 0\n */\n density?: Density;\n /** The root `<div>`'s id. */\n id?: string;\n /** Ref to the root `<div>` element. */\n ref?: Ref<HTMLDivElement>;\n /** Classes for the root element, merged with `classNames.root`; consumer classes win. */\n className?: string;\n /** Inline styles for the root element. */\n style?: CSSProperties;\n /** Classes for each part, by slot. */\n classNames?: DatePickerClassNames;\n /** `data-*` attributes go to the root. */\n [data: `data-${string}`]: string | number | boolean | undefined;\n}\n\nexport type DatePickerProps = DatePickerCommonProps & {\n /** The selected date (controlled); `null` for none. */\n value?: CalendarDate | null;\n /** Initial date when uncontrolled. @default null */\n defaultValue?: CalendarDate | null;\n /** Called with the date the user picks or types. */\n onChange?: (value: CalendarDate) => void;\n};\n\nexport interface DateRange {\n start: CalendarDate;\n end: CalendarDate;\n}\n\nexport type DateRangePickerProps = Omit<DatePickerCommonProps, 'classNames'> & {\n /** Classes for each part, by slot. */\n classNames?: DateRangePickerClassNames;\n /** The selected range (controlled); `null` for none. */\n value?: DateRange | null;\n /** Initial range when uncontrolled. @default null */\n defaultValue?: DateRange | null;\n /** Called with the range once both its start and end are picked or typed. */\n onChange?: (value: DateRange) => void;\n /**\n * `scroll` lists the months one under another and scrolls vertically, as the M3 modal\n * range picker does; `paged` shows one month at a time with previous / next buttons and\n * a year list, like the date picker. @default \"scroll\"\n */\n monthLayout?: 'scroll' | 'paged';\n};\n\n/**\n * M3 modal date picker (Compose's `DatePicker`): a header with the selected date, a month\n * grid you page with the arrows, a horizontal swipe or Page Up / Down, a year list, and a\n * text input mode. Put it in a {@link PickerDialog} for the modal form; {@link DateField}\n * is the docked form. Values are `@internationalized/date` dates.\n *\n * @example\n * <DatePicker value={date} onChange={setDate} />\n */\nexport function DatePicker(props: DatePickerProps) {\n return (\n <DomDirectionLocale>\n {(directionRef) => <SingleDatePicker {...props} directionRef={directionRef} />}\n </DomDirectionLocale>\n );\n}\n\n/**\n * M3 date range picker (Compose's `DateRangePicker`): select a start and an end date on a\n * vertically scrolling list of months, or type them in input mode.\n *\n * @example\n * <DateRangePicker value={range} onChange={setRange} />\n */\nexport function DateRangePicker(props: DateRangePickerProps) {\n return (\n <DomDirectionLocale>\n {(directionRef) => <RangeDatePicker {...props} directionRef={directionRef} />}\n </DomDirectionLocale>\n );\n}\n\ntype Inner<P> = P & { directionRef: (element: HTMLElement | null) => void };\n\nfunction SingleDatePicker(props: Inner<DatePickerProps>) {\n const { locale } = useLocale();\n const confirm = useContext(PickerDialogContext);\n const [value, setValue] = useControlledState(\n props.value,\n props.defaultValue ?? null,\n props.onChange as (value: CalendarDate | null) => void,\n );\n const state = useCalendarState({\n value,\n onChange: (date) => setValue(date as CalendarDate),\n minValue: props.min,\n maxValue: props.max,\n isDateUnavailable: props.isDateUnavailable,\n locale,\n createCalendar,\n });\n const formatter = useDateFormatter({ dateStyle: 'medium' });\n const labels = props.labels ?? {};\n const headline = value\n ? formatter.format(value.toDate(getLocalTimeZone()))\n : (labels.noSelection ?? 'Selected date');\n return (\n <PickerFrame\n {...props}\n range={false}\n state={state}\n headline={headline}\n input={\n <DateInput\n label={labels.dateLabel ?? 'Date'}\n value={value}\n onCommit={(date) => date && setValue(date)}\n onEnter={(date) => date && confirm?.requestConfirm()}\n min={props.min}\n max={props.max}\n isDateUnavailable={props.isDateUnavailable}\n labels={labels}\n density={props.density}\n className=\"w-full\"\n />\n }\n />\n );\n}\n\n/** Whole months from `from` to `to`. */\nconst monthsBetween = (from: CalendarDate, to: CalendarDate) =>\n (to.year - from.year) * 12 + (to.month - from.month);\n\nfunction RangeDatePicker({ monthLayout = 'scroll', ...props }: Inner<DateRangePickerProps>) {\n const { locale } = useLocale();\n const confirm = useContext(PickerDialogContext);\n const [value, setValue] = useControlledState(\n props.value,\n props.defaultValue ?? null,\n props.onChange as (value: DateRange | null) => void,\n );\n // The scrolling list shows every month of the year range (within min / max) at once.\n const [firstYear, lastYear] = props.yearRange ?? [1900, 2100];\n const scroll = monthLayout === 'scroll';\n const listStart = maxDate(\n new CalendarDate(firstYear, 1, 1),\n props.min ? toCalendarDate(props.min) : null,\n )!;\n const listEnd = minDate(\n new CalendarDate(lastYear, 12, 31),\n props.max ? toCalendarDate(props.max) : null,\n )!;\n const state = useRangeCalendarState({\n value,\n onChange: (range) => setValue(range as DateRange),\n minValue: scroll ? listStart : props.min,\n maxValue: scroll ? listEnd : props.max,\n isDateUnavailable: props.isDateUnavailable,\n visibleDuration: scroll ? { months: monthsBetween(listStart, listEnd) + 1 } : undefined,\n locale,\n createCalendar,\n });\n const formatter = useDateFormatter({ month: 'short', day: 'numeric' });\n const labels = props.labels ?? {};\n const format = (date: CalendarDate) => formatter.format(date.toDate(getLocalTimeZone()));\n // While a new range is being picked, its first day is the start and the end is still open\n // (Compose's headline: \"Mar 20 – End date\"), not the range it replaces.\n const anchor = state.anchorDate;\n const headline = anchor\n ? `${format(anchor)} – ${labels.endDateLabel ?? 'End date'}`\n : value\n ? `${format(value.start)} – ${format(value.end)}`\n : (labels.noSelection ?? 'Start date – End date');\n const common = {\n min: props.min,\n max: props.max,\n isDateUnavailable: props.isDateUnavailable,\n labels,\n density: props.density,\n className: 'w-full',\n };\n return (\n <PickerFrame\n {...props}\n range\n scroll={scroll}\n state={state}\n headline={headline}\n input={\n <>\n <DateInput\n {...common}\n label={labels.startDateLabel ?? 'Start date'}\n value={value?.start ?? null}\n onCommit={(start) =>\n start && setValue({ start, end: value && value.end >= start ? value.end : start })\n }\n />\n <DateInput\n {...common}\n label={labels.endDateLabel ?? 'End date'}\n value={value?.end ?? null}\n onCommit={(end) =>\n end && setValue({ start: value && value.start <= end ? value.start : end, end })\n }\n onEnter={(end) => end && value && confirm?.requestConfirm()}\n />\n </>\n }\n />\n );\n}\n\nfunction PickerFrame({\n range,\n scroll = false,\n state,\n headline,\n input,\n header = true,\n modeToggle = true,\n defaultMode = 'calendar',\n yearRange = [1900, 2100],\n labels = {},\n id,\n ref,\n className,\n style,\n classNames,\n directionRef,\n ...rest\n}: Inner<Omit<DatePickerCommonProps, 'classNames'>> & {\n classNames?: DateRangePickerClassNames | undefined;\n range: boolean;\n scroll?: boolean;\n state: CalendarState | RangeCalendarState;\n headline: string;\n input: ReactNode;\n value?: unknown;\n defaultValue?: unknown;\n onChange?: unknown;\n}) {\n const { root: data } = splitRootProps(rest, { wrapper: true });\n const [mode, setMode] = useState(defaultMode);\n // Set once the mode has been switched, so only a switch animates (not the first render).\n const [switched, setSwitched] = useState(false);\n const [years, setYears] = useState(false);\n // The picker's height follows the view on the default spatial spring (Compose's\n // `SizeTransform` in its display mode animation), as the views swap.\n const { attach: attachSize, capture: captureSize } = useSizeTransform<HTMLDivElement>(mode);\n // The outgoing view fades out as it slides away (Compose: up 48px as the input comes in,\n // down by its whole height as the calendar comes back), clipped with the new one.\n const {\n attachView: attachExitView,\n attachSlot: attachExitSlot,\n capture: captureExit,\n } = useViewExit(mode);\n const styles = datePickerStyles({ range });\n const title =\n mode === 'input'\n ? (labels.inputTitle ?? (range ? 'Enter dates' : 'Enter date'))\n : (labels.title ?? (range ? 'Select dates' : 'Select date'));\n const bodyProps = {\n styles,\n years,\n setYears,\n yearRange,\n labels,\n className: classNames?.body,\n classNames,\n };\n return (\n <div\n {...data}\n id={id}\n ref={(element) => {\n attachSize(element);\n directionRef(element);\n if (typeof ref === 'function') ref(element);\n else if (ref) ref.current = element;\n }}\n style={style}\n // The modal date picker's component tokens (date-picker-tokens.ts).\n data-tokens={mergeDataTokens('md-comp-date-picker-modal', data)}\n data-years={years || undefined}\n data-mode={mode}\n className={styles.root({ class: cn(classNames?.root, className) })}\n >\n {header && (\n <div className={styles.header({ class: classNames?.header })}>\n <div className={styles.title({ class: classNames?.title })}>{title}</div>\n <div className={styles.headlineRow()}>\n <div\n aria-live=\"polite\"\n data-slot=\"headline\"\n className={styles.headline({ class: classNames?.headline })}\n >\n {headline}\n </div>\n {modeToggle && (\n <IconButton\n variant=\"standard\"\n // The picker's surface isn't dense, only its input mode's fields.\n density={0}\n icon={mode === 'calendar' ? <EditIcon /> : <CalendarIcon />}\n aria-label={\n mode === 'calendar'\n ? (labels.inputMode ?? 'Switch to text input mode')\n : (labels.calendarMode ?? 'Switch to calendar input mode')\n }\n onPress={() => {\n captureSize();\n captureExit(mode === 'calendar' ? '-48px' : '100%');\n setSwitched(true);\n setMode(mode === 'calendar' ? 'input' : 'calendar');\n }}\n />\n )}\n </div>\n </div>\n )}\n <div className={styles.modeStack()}>\n <div\n key={mode}\n ref={attachExitView}\n data-enter={switched ? mode : undefined}\n className={styles.modeView()}\n >\n {mode === 'input' ? (\n <div className={styles.input({ class: classNames?.body })}>{input}</div>\n ) : range && scroll ? (\n <RangeMonthList state={state as RangeCalendarState} {...bodyProps} />\n ) : range ? (\n <RangeCalendarBody state={state as RangeCalendarState} {...bodyProps} />\n ) : (\n <SingleCalendarBody state={state as CalendarState} {...bodyProps} />\n )}\n </div>\n <div ref={attachExitSlot} aria-hidden=\"true\" inert className={styles.modeExit()} />\n </div>\n </div>\n );\n}\n\ninterface BodyProps {\n styles: ReturnType<typeof datePickerStyles>;\n years: boolean;\n setYears: (open: boolean) => void;\n yearRange: [number, number];\n labels: Partial<DatePickerLabels>;\n className?: string | undefined;\n classNames?: DateRangePickerClassNames | undefined;\n}\n\nfunction SingleCalendarBody({ state, ...props }: BodyProps & { state: CalendarState }) {\n const { calendarProps, prevButtonProps, nextButtonProps } = useCalendar({}, state);\n return (\n <CalendarBody\n {...props}\n state={state}\n calendarProps={calendarProps}\n prevButtonProps={prevButtonProps}\n nextButtonProps={nextButtonProps}\n />\n );\n}\n\nfunction RangeCalendarBody({ state, ...props }: BodyProps & { state: RangeCalendarState }) {\n const ref = useRef<HTMLDivElement>(null);\n const { calendarProps, prevButtonProps, nextButtonProps } = useRangeCalendar({}, state, ref);\n return (\n <CalendarBody\n {...props}\n bodyRef={ref}\n state={state}\n calendarProps={calendarProps}\n prevButtonProps={prevButtonProps}\n nextButtonProps={nextButtonProps}\n />\n );\n}\n\nfunction CalendarBody({\n state,\n calendarProps,\n prevButtonProps,\n nextButtonProps,\n styles,\n years,\n setYears,\n yearRange,\n labels,\n className,\n classNames,\n bodyRef,\n}: BodyProps & {\n state: CalendarState | RangeCalendarState;\n calendarProps: HTMLAttributes<HTMLElement>;\n prevButtonProps: AriaButtonProps;\n nextButtonProps: AriaButtonProps;\n bodyRef?: Ref<HTMLDivElement>;\n}) {\n const confirm = useContext(PickerDialogContext);\n const monthFormatter = useDateFormatter({ month: 'long', year: 'numeric' });\n const monthLabel = monthFormatter.format(state.visibleRange.start.toDate(getLocalTimeZone()));\n const menuRef = useRef<HTMLButtonElement>(null);\n const [focusYears, setFocusYears] = useState(false);\n // Compose shrinks the year list and fades it out (`shrinkVertically` + `fadeOut`); the\n // first of the two transitions to end removes it.\n const yearsPresence = usePresence(years, ['clip-path', 'opacity']);\n const { swipeProps, slideKey, slideDirection } = useMonthSwipe(state);\n const onKeyDownCapture = usePickerKeys(state, {\n onConfirm: confirm?.requestConfirm,\n onMonthMenu: () => menuRef.current?.focus(),\n onYearMenu: () => {\n setFocusYears(true);\n setYears(true);\n },\n });\n return (\n <div\n {...calendarProps}\n ref={bodyRef}\n onKeyDownCapture={onKeyDownCapture}\n className={styles.body({ class: className })}\n >\n <div className={styles.nav()}>\n <TooltipTrigger>\n <Button\n ref={menuRef}\n variant=\"text\"\n className={cn('text-on-surface-variant', classNames?.yearButton)}\n aria-label={`${monthLabel}, ${years ? (labels.showDays ?? 'Switch to selecting a day') : (labels.showYears ?? 'Switch to selecting a year')}`}\n onPress={() => {\n setFocusYears(false);\n setYears(!years);\n }}\n >\n {/* The drop-down arrow trails the label here, which Button's one leading icon can't do. */}\n <span className=\"inline-flex items-center gap-[8px]\">\n <span aria-live=\"polite\">{monthLabel}</span>\n <span\n aria-hidden=\"true\"\n className=\"inline-flex size-[20px] items-center justify-center\"\n >\n <span className={styles.yearButtonIcon()}>\n <ArrowDropDownIcon />\n </span>\n </span>\n </span>\n </Button>\n <LazyTooltip>{labels.yearsTooltip ?? 'Choose a year (Shift+Y)'}</LazyTooltip>\n </TooltipTrigger>\n {!years && (\n <div className={styles.navButtons()}>\n <ShortcutIconButton\n icon={<ChevronLeftIcon />}\n label={labels.previousMonth ?? 'Previous month'}\n tooltip={labels.previousMonthTooltip ?? 'Previous month (Page Up)'}\n onPress={prevButtonProps.onPress as () => void}\n disabled={prevButtonProps.isDisabled}\n />\n <ShortcutIconButton\n icon={<ChevronRightIcon />}\n label={labels.nextMonth ?? 'Next month'}\n tooltip={labels.nextMonthTooltip ?? 'Next month (Page Down)'}\n onPress={nextButtonProps.onPress as () => void}\n disabled={nextButtonProps.isDisabled}\n />\n </div>\n )}\n </div>\n {!years && (\n <div {...swipeProps} className={styles.swipe()}>\n <div key={slideKey} data-direction={slideDirection} className={styles.slide()}>\n <CalendarGrid state={state} styles={styles} classNames={classNames} />\n </div>\n </div>\n )}\n {/* Closing, the list stays over the grid until it has shrunk and faded away. */}\n {yearsPresence.isPresent && (\n <YearList\n state={state}\n styles={styles}\n yearRange={yearRange}\n className={classNames?.year}\n label={labels.yearList ?? 'Year'}\n autoFocus={focusYears}\n exiting={yearsPresence.isExiting}\n exitProps={yearsPresence.exitProps}\n onPick={() => setYears(false)}\n />\n )}\n </div>\n );\n}\n\n/**\n * The range picker's months, one under another in a vertical scroll (M3: \"To navigate\n * across months, scroll vertically\"), under a single weekday row. Only the months in view\n * (and the focused one) are rendered; the rest are spacers of the same fixed height.\n */\nfunction RangeMonthList({\n state,\n styles,\n className,\n classNames,\n}: BodyProps & { state: RangeCalendarState }) {\n const confirm = useContext(PickerDialogContext);\n const ref = useRef<HTMLDivElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const { calendarProps } = useRangeCalendar({}, state, ref);\n const { locale } = useLocale();\n const first = state.visibleRange.start;\n const count = monthsBetween(first, state.visibleRange.end) + 1;\n const focusedIndex = monthsBetween(first, state.focusedDate);\n const [view, setView] = useState(() => ({ top: focusedIndex * MONTH_HEIGHT, height: 0 }));\n const weekdays = useDateFormatter({ weekday: 'narrow' });\n const longWeekdays = useDateFormatter({ weekday: 'long' });\n const subhead = useDateFormatter({ month: 'long', year: 'numeric' });\n const onKeyDownCapture = usePickerKeys(state, {\n onConfirm: confirm?.requestConfirm,\n onMonthMenu: () => undefined,\n onYearMenu: () => undefined,\n });\n\n // Open on the focused month (the range's start, or today), then follow the scroll.\n const initialTop = useRef(view.top);\n useLayoutEffect(() => {\n const list = listRef.current;\n if (!list) return;\n // A list out of sight (`display: none` above it) can't scroll, so it scrolls to the focused\n // month once it shows; it used to open on the range's first month.\n let opened = list.getClientRects().length > 0;\n list.scrollTop = initialTop.current;\n const measure = () => {\n if (!opened && list.clientHeight > 0) {\n opened = true;\n list.scrollTop = initialTop.current;\n }\n setView({ top: list.scrollTop, height: list.clientHeight });\n };\n measure();\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(measure);\n observer?.observe(list);\n list.addEventListener('scroll', measure, { passive: true });\n return () => {\n observer?.disconnect();\n list.removeEventListener('scroll', measure);\n };\n }, []);\n\n const height = view.height || MONTH_HEIGHT;\n let from = Math.max(0, Math.floor(view.top / MONTH_HEIGHT) - 1);\n let to = Math.min(count - 1, Math.floor((view.top + height) / MONTH_HEIGHT) + 1);\n if (state.isFocused) {\n from = Math.min(from, focusedIndex);\n to = Math.max(to, focusedIndex);\n }\n const weekStart = startOfWeek(today(getLocalTimeZone()), locale);\n\n return (\n <div\n {...mergeProps(calendarProps, { onKeyDownCapture })}\n ref={ref}\n className={styles.body({ class: cn('min-h-0 flex-1', className) })}\n >\n <div aria-hidden=\"true\" className={styles.weekdayRow()}>\n {Array.from({ length: 7 }, (_, index) => {\n const day = weekStart.add({ days: index }).toDate(getLocalTimeZone());\n return (\n <span\n key={index}\n title={longWeekdays.format(day)}\n className={styles.weekdayCell({ class: classNames?.weekday })}\n >\n {weekdays.format(day)}\n </span>\n );\n })}\n </div>\n <div ref={listRef} className={styles.months()}>\n <div style={{ height: from * MONTH_HEIGHT }} />\n {Array.from({ length: to - from + 1 }, (_, i) => {\n const month = first.add({ months: from + i });\n return (\n <div key={month.toString()} className=\"h-[336px]\">\n <div\n aria-hidden=\"true\"\n className={styles.monthSubhead({ class: classNames?.monthSubhead })}\n >\n {subhead.format(month.toDate(getLocalTimeZone()))}\n </div>\n <CalendarGrid state={state} styles={styles} month={month} classNames={classNames} />\n </div>\n );\n })}\n <div style={{ height: (count - 1 - to) * MONTH_HEIGHT }} />\n </div>\n </div>\n );\n}\n\n/** A month in the scrolling list: its 48px subhead and six 48px weeks. */\nconst MONTH_HEIGHT = 336;\n\nfunction YearList({\n state,\n styles,\n yearRange,\n className,\n label,\n autoFocus,\n exiting,\n exitProps,\n onPick,\n}: {\n state: CalendarState | RangeCalendarState;\n styles: ReturnType<typeof datePickerStyles>;\n yearRange: [number, number];\n className: string | undefined;\n label: string;\n autoFocus: boolean;\n /** Closing: drawn over the grid, out of the accessibility tree and taking no presses. */\n exiting: boolean;\n exitProps: { onTransitionEnd: (event: TransitionEvent<HTMLElement>) => void };\n onPick: () => void;\n}) {\n const current = today(getLocalTimeZone()).year;\n const focusedYear = state.focusedDate.year;\n const minYear = state.minValue?.year ?? -Infinity;\n const maxYear = state.maxValue?.year ?? Infinity;\n return (\n <div\n {...exitProps}\n role=\"radiogroup\"\n aria-label={label}\n aria-hidden={exiting || undefined}\n inert={exiting || undefined}\n data-exiting={exiting || undefined}\n className={styles.years()}\n ref={(element) => {\n if (exiting) return;\n // Open on the focused year, as Compose scrolls the year list to it.\n const selected = element?.querySelector<HTMLElement>('[aria-checked=\"true\"]');\n selected?.scrollIntoView?.({ block: 'center' });\n if (autoFocus) selected?.focus({ preventScroll: true });\n }}\n >\n {Array.from({ length: yearRange[1] - yearRange[0] + 1 }, (_, i) => yearRange[0] + i).map(\n (year) => (\n <ChoiceButton\n key={year}\n selected={year === focusedYear}\n disabled={year < minYear || year > maxYear}\n data-current={year === current || undefined}\n steps={YEAR_STEPS}\n className={styles.year({ class: className })}\n onPick={() => {\n state.setFocusedDate(state.focusedDate.set({ year }));\n onPick();\n }}\n >\n {year}\n </ChoiceButton>\n ),\n )}\n </div>\n );\n}\n\n/** Three years to a row. */\nconst YEAR_STEPS = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -3, ArrowDown: 3 };\n"],"mappings":"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"}
@@ -161,9 +161,9 @@ export declare const dockedDatePickerStyles: import("tailwind-variants").TVRetur
161
161
  header?: import("tailwind-variants").ClassValue;
162
162
  view?: import("tailwind-variants").ClassValue;
163
163
  item?: import("tailwind-variants").ClassValue;
164
+ list?: import("tailwind-variants").ClassValue;
164
165
  check?: import("tailwind-variants").ClassValue;
165
166
  menuIcon?: import("tailwind-variants").ClassValue;
166
- list?: import("tailwind-variants").ClassValue;
167
167
  group?: import("tailwind-variants").ClassValue;
168
168
  calendar?: import("tailwind-variants").ClassValue;
169
169
  menuButton?: import("tailwind-variants").ClassValue;
@@ -177,9 +177,9 @@ export declare const dockedDatePickerStyles: import("tailwind-variants").TVRetur
177
177
  header?: import("tailwind-variants").ClassValue;
178
178
  view?: import("tailwind-variants").ClassValue;
179
179
  item?: import("tailwind-variants").ClassValue;
180
+ list?: import("tailwind-variants").ClassValue;
180
181
  check?: import("tailwind-variants").ClassValue;
181
182
  menuIcon?: import("tailwind-variants").ClassValue;
182
- list?: import("tailwind-variants").ClassValue;
183
183
  group?: import("tailwind-variants").ClassValue;
184
184
  calendar?: import("tailwind-variants").ClassValue;
185
185
  menuButton?: import("tailwind-variants").ClassValue;
@@ -205,9 +205,9 @@ export declare const dockedDatePickerStyles: import("tailwind-variants").TVRetur
205
205
  header?: import("tailwind-variants").ClassValue;
206
206
  view?: import("tailwind-variants").ClassValue;
207
207
  item?: import("tailwind-variants").ClassValue;
208
+ list?: import("tailwind-variants").ClassValue;
208
209
  check?: import("tailwind-variants").ClassValue;
209
210
  menuIcon?: import("tailwind-variants").ClassValue;
210
- list?: import("tailwind-variants").ClassValue;
211
211
  group?: import("tailwind-variants").ClassValue;
212
212
  calendar?: import("tailwind-variants").ClassValue;
213
213
  menuButton?: import("tailwind-variants").ClassValue;
@@ -213,8 +213,8 @@ function FabMenu({ open, defaultOpen = false, onOpenChange, icon, openIcon, icon
213
213
  }
214
214
  /**
215
215
  * A `FabMenuItem`'s action for a `MenuItem`. Menu items are React Stately collection items,
216
- * which keep any prop; React Aria's `useMenuItem` runs an item's `onAction` and opens its
217
- * `href` through the router.
216
+ * which keep any prop: React Aria's `useMenuItem` runs an item's `onAction`, and an `href`
217
+ * makes the `MenuItem` a real link, followed through the router.
218
218
  */
219
219
  function menuItemAction({ onAction, href }) {
220
220
  return {