@react-md/core 7.0.1 → 7.0.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.
- package/dist/_base.scss +10 -4
- package/dist/form/Select.js +1 -2
- package/dist/form/Select.js.map +1 -1
- package/dist/form/utils.js +1 -1
- package/dist/form/utils.js.map +1 -1
- package/dist/icon/_icon.scss +19 -0
- package/dist/icon/configureMaterialSymbols.d.ts +1 -0
- package/dist/icon/configureMaterialSymbols.js +64 -0
- package/dist/icon/configureMaterialSymbols.js.map +1 -0
- package/dist/icon/getMaterialSymbolOption.d.ts +6 -0
- package/dist/icon/getMaterialSymbolOption.js +14 -0
- package/dist/icon/getMaterialSymbolOption.js.map +1 -0
- package/dist/icon/getMaterialSymbolsUrl.d.ts +58 -0
- package/dist/icon/getMaterialSymbolsUrl.js +32 -0
- package/dist/icon/getMaterialSymbolsUrl.js.map +1 -0
- package/dist/icon/symbols.d.ts +4 -0
- package/dist/icon/symbols.js +25 -0
- package/dist/icon/symbols.js.map +1 -0
- package/dist/layout/useExpandableLayout.d.ts +2 -2
- package/dist/layout/useExpandableLayout.js.map +1 -1
- package/dist/menu/MenuItemButton.js +1 -0
- package/dist/menu/MenuItemButton.js.map +1 -1
- package/dist/menu/MenuItemFileInput.js +1 -2
- package/dist/menu/MenuItemFileInput.js.map +1 -1
- package/dist/menu/MenuItemInputToggle.js +1 -1
- package/dist/menu/MenuItemInputToggle.js.map +1 -1
- package/dist/positioning/utils.js +0 -4
- package/dist/positioning/utils.js.map +1 -1
- package/dist/theme/_theme.scss +42 -3
- package/dist/transition/useMaxWidthTransition.d.ts +1 -1
- package/dist/transition/useMaxWidthTransition.js.map +1 -1
- package/dist/types.d.ts +5 -0
- package/dist/types.js.map +1 -1
- package/dist/window-splitter/styles.d.ts +2 -2
- package/dist/window-splitter/styles.js.map +1 -1
- package/package.json +51 -42
- package/src/form/Select.tsx +1 -2
- package/src/form/utils.ts +1 -1
- package/src/icon/configureMaterialSymbols.tsx +25 -0
- package/src/icon/getMaterialSymbolOption.ts +20 -0
- package/src/icon/getMaterialSymbolsUrl.ts +112 -0
- package/src/icon/symbols.ts +26 -0
- package/src/layout/useExpandableLayout.ts +6 -2
- package/src/menu/MenuItemButton.tsx +1 -0
- package/src/menu/MenuItemFileInput.tsx +1 -2
- package/src/menu/MenuItemInputToggle.tsx +1 -1
- package/src/positioning/utils.ts +0 -4
- package/src/transition/useMaxWidthTransition.ts +1 -1
- package/src/types.ts +6 -0
- package/src/window-splitter/styles.ts +2 -2
package/dist/_base.scss
CHANGED
|
@@ -330,8 +330,10 @@ $_layer-order: (
|
|
|
330
330
|
/// @include use-light-theme;
|
|
331
331
|
/// }
|
|
332
332
|
///
|
|
333
|
-
@
|
|
334
|
-
|
|
333
|
+
/// @param {Boolean} $disable-color-scheme-var [false] - Set to `true` to
|
|
334
|
+
/// disable setting the color-scheme var
|
|
335
|
+
@mixin use-light-theme($disable-color-scheme-var: false) {
|
|
336
|
+
@include theme.use-light-theme-colors($disable-color-scheme-var);
|
|
335
337
|
@include interaction.use-light-surface;
|
|
336
338
|
@include transition.transition-use-light-theme;
|
|
337
339
|
@include icon.use-light-theme;
|
|
@@ -355,8 +357,11 @@ $_layer-order: (
|
|
|
355
357
|
/// @include use-dark-theme;
|
|
356
358
|
/// }
|
|
357
359
|
///
|
|
358
|
-
|
|
359
|
-
|
|
360
|
+
///
|
|
361
|
+
/// @param {Boolean} $disable-color-scheme-var [false] - Set to `true` to
|
|
362
|
+
/// disable setting the color-scheme var
|
|
363
|
+
@mixin use-dark-theme($disable-color-scheme-var: false) {
|
|
364
|
+
@include theme.use-dark-theme-colors($disable-color-scheme-var);
|
|
360
365
|
@include interaction.use-dark-surface;
|
|
361
366
|
@include transition.transition-use-dark-theme;
|
|
362
367
|
@include icon.use-dark-theme;
|
|
@@ -514,6 +519,7 @@ $_layer-order: (
|
|
|
514
519
|
|
|
515
520
|
@if not theme.$disable-default-root-theme {
|
|
516
521
|
:root {
|
|
522
|
+
@include theme.default-color-scheme;
|
|
517
523
|
@include variables;
|
|
518
524
|
|
|
519
525
|
@if theme.$color-scheme == system {
|
package/dist/form/Select.js
CHANGED
|
@@ -133,13 +133,12 @@ const noop = ()=>{
|
|
|
133
133
|
})
|
|
134
134
|
}),
|
|
135
135
|
/*#__PURE__*/ _jsx("input", {
|
|
136
|
-
|
|
136
|
+
inert: true,
|
|
137
137
|
id: inputId,
|
|
138
138
|
ref: inputRefCallback,
|
|
139
139
|
type: "text",
|
|
140
140
|
autoComplete: autoComplete,
|
|
141
141
|
name: name,
|
|
142
|
-
tabIndex: -1,
|
|
143
142
|
disabled: disabled,
|
|
144
143
|
required: required,
|
|
145
144
|
placeholder: " ",
|
package/dist/form/Select.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/form/Select.tsx"],"sourcesContent":["\"use client\";\n\nimport { cnb } from \"cnbuilder\";\nimport {\n type ChangeEvent,\n type HTMLAttributes,\n type InputHTMLAttributes,\n type ReactElement,\n type ReactNode,\n type Ref,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nimport { type BoxProps } from \"../box/Box.js\";\nimport { IconRotator } from \"../icon/IconRotator.js\";\nimport { getIcon } from \"../icon/config.js\";\nimport { type MenuProps } from \"../menu/Menu.js\";\nimport { KeyboardMovementProvider } from \"../movement/useKeyboardMovementProvider.js\";\nimport {\n type LabelA11y,\n type PropsWithRef,\n type RequireAtLeastOne,\n} from \"../types.js\";\nimport { useEnsuredId } from \"../useEnsuredId.js\";\nimport { useEnsuredRef } from \"../useEnsuredRef.js\";\nimport { Listbox } from \"./Listbox.js\";\nimport { type OptionProps } from \"./Option.js\";\nimport { SelectedOption } from \"./SelectedOption.js\";\nimport {\n TextFieldContainer,\n type TextFieldContainerProps,\n} from \"./TextFieldContainer.js\";\nimport { getFormConfig } from \"./formConfig.js\";\nimport { label as labelStyles } from \"./labelStyles.js\";\nimport { select } from \"./selectStyles.js\";\nimport { extractOptionsFromChildren } from \"./selectUtils.js\";\nimport { textField } from \"./textFieldStyles.js\";\nimport { type UserAgentAutocompleteProps } from \"./types.js\";\nimport { useFormReset } from \"./useFormReset.js\";\nimport { useSelectCombobox } from \"./useSelectCombobox.js\";\nimport { triggerManualChangeEvent } from \"./utils.js\";\n\nconst EMPTY_STRING = \"\" as const;\nconst noop = (): void => {\n // do nothing\n};\n\n/**\n * @since 6.5.0\n */\nexport interface GetSelectedOptionChildrenOptions<\n Value extends string = string,\n> {\n value: \"\" | Value;\n\n /**\n * The option will be undefined if there is no value or matching option.\n */\n option: OptionProps | undefined;\n\n /**\n * This is a pass-through of the {@link SelectProps.placeholder}\n */\n placeholder?: ReactNode;\n\n /**\n * This is a pass-through of the {@link SelectProps.selectedOptionProps}\n */\n children?: ReactNode;\n}\n\n/**\n * @since 6.5.0\n */\nconst defaultGetSelectedOptionChildren = (\n options: GetSelectedOptionChildrenOptions\n): ReactNode => {\n const { children, option, placeholder } = options;\n\n return children ?? (option?.children || placeholder);\n};\n\n/**\n * This is a convenience type for casting the `event.currentTarget.value` of a\n * `Select`'s change event to be union of available values.\n *\n * Note: The change event does not provide any sort of validation on the value\n * so automation tools like Cypress, Playwright, or Selenium might set an\n * invalid value. This also does not work for numbers, so you will need to\n * implement that yourself.\n *\n * @example Simple Usage\n * ```tsx\n * import { Select, type SelectChangeEvent } from \"@react-md/core/form/Select\";\n * import { Option } from \"@react-md/core/form/Option\";\n * import type { ReactElement } from \"react\";\n *\n * type Value = \"\" | \"a\" | \"b\" | \"c\" | \"d\";\n *\n * function Example(): ReactElement {\n * const [value, setValue] = useState<Value>(\"\");\n *\n * const handleChange = (event: SelectChangeEvent<Value>): void => {\n * // No type error!\n * // `event.currentTarget.value`'s type is `Value` instead of a generic `string`\n * setValue(event.currentTarget.value);\n * };\n *\n * return (\n * <Select\n * label=\"Label\"\n * value={value}\n * onChange={handleChange}\n * >\n * <Option value=\"a\">First</Option>\n * <Option value=\"b\">Second</Option>\n * <Option value=\"c\">Third</Option>\n * <Option value=\"d\">Fourth</Option>\n * </Select>\n * );\n * }\n * ```\n * @since 6.0.0\n */\nexport type SelectChangeEvent<Value extends string> =\n ChangeEvent<HTMLInputElement> & { currentTarget: { value: Value } };\n\n/**\n * @since 6.0.0 Rewritten with a new API.\n */\nexport interface SelectProps<Value extends string>\n extends\n Omit<TextFieldContainerProps, \"label\">,\n Pick<InputHTMLAttributes<HTMLInputElement>, \"form\" | \"required\">,\n UserAgentAutocompleteProps {\n /**\n * @defaultValue `\"select-\" + useId()`\n */\n id?: string;\n\n /**\n * Optional placeholder text or element to render while no options have been\n * selected.\n */\n placeholder?: ReactNode;\n\n /**\n * Set this to a custom dropdown icon or `null` to not render a dropdown icon.\n *\n * @defaultValue `getIcon(\"dropdown\")`\n */\n icon?: ReactNode;\n\n /**\n * Set this value to fully control the value of the select component. The\n * {@link onChange} handler **must** also be provided if this prop exists.\n */\n value?: Value;\n\n /**\n * An optional default value when the value of the select component is\n * uncontrolled.\n *\n * @defaultValue `\"\"`\n */\n defaultValue?: Value;\n\n /** @see {@link SelectChangeEvent} */\n onChange?: (event: SelectChangeEvent<Value>) => void;\n\n /**\n * An optional floating label to display like other form fields.\n */\n label?: ReactNode;\n\n /**\n * Optional props to pass to the `<span>` that surrounds the {@link label}\n */\n labelProps?: PropsWithRef<HTMLAttributes<HTMLSpanElement>>;\n\n /**\n * An optional ref to pass to the hidden `<input type=\"text\" />` element that\n * stores the current value. This is really only useful if you'd like to keep\n * this component uncontrolled and access the value through\n * `inputRef.current.value`.\n */\n inputRef?: Ref<HTMLInputElement>;\n inputProps?: InputHTMLAttributes<HTMLInputElement>;\n\n /**\n * A ref for the container `<div>` element.\n */\n containerRef?: Ref<HTMLDivElement>;\n\n /**\n * Any additional props to provide to the `Menu` component that renders all\n * the `Option`s.\n *\n * The menu will always have these default values unless explicity\n * overwritten by this prop:\n *\n * - `aria-labelledby={label ? labelId : id}` -- this will be undefined if\n * `aria-label` is provided\n * - `anchor={BELOW_CENTER_ANCHOR}`\n * - `width=\"min\"`\n */\n menuProps?: PropsWithRef<\n Omit<MenuProps, \"visible\" | \"onRequestClose\" | \"fixedTo\">\n >;\n\n /**\n * Any additional props to pass to the div that contains the current visible\n * option.\n */\n selectedOptionProps?: BoxProps;\n\n /**\n * Set this to `true` if all the `Option` components should display the\n * selected icon after the children instead of before.\n *\n * @see {@link disableSelectedIcon} to remove the selected icon instead.\n *\n * @defaultValue `false`\n */\n selectedIconAfter?: boolean;\n\n /**\n * Set this to `true` to prevent the current option from rendering the\n * `leftAddon` in the `TextFieldContainer`.\n *\n * @defaultValue `false`\n */\n disableOptionAddon?: boolean;\n\n /**\n * Set this to `true` to update all the `Option` components to no longer\n * render an icon while selected.\n *\n * @defaultValue `false`\n */\n disableSelectedIcon?: boolean;\n\n /**\n * @since 6.5.0\n * @defaultValue `({ children, option, placeholder }) => children ?? (option?.children || placeholder)`\n */\n getSelectedOptionChildren?: (\n options: GetSelectedOptionChildrenOptions<Value>\n ) => ReactNode;\n\n /**\n * This should be the available `Option`s for the select to choose from. It\n * can also contain `OptGroup` or any other elements but only clicking on an\n * `Option` component will update the value.\n */\n children: ReactNode;\n}\n\n/**\n * **Client Component**\n *\n * @example Simple Example\n * ```tsx\n * import { Option } from \"@react-md/core/form/Option\";\n * import { Select } from \"@react-md/core/form/Select\";\n * import { useState, type ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const [value, setValue] = useState(\"\");\n *\n * return (\n * <Select\n * label=\"Select\"\n * value={value}\n * onChange={(event) => setValue(event.currentTarget.value)}\n * placeholder=\"Select a value\"\n * >\n * <Option value=\"a\">Option 1</Option>\n * <Option value=\"b\">Option 2</Option>\n * <Option value=\"c\">Option 3</Option>\n * <Option value=\"d\">Option 4</Option>\n * </Select>\n * );\n * }\n * ```\n *\n * @see {@link https://react-md.dev/components/select | Select Demos}\n * @since 6.0.0 Rewritten with a new API.\n */\nexport function Select<Value extends string>(\n props: RequireAtLeastOne<SelectProps<Value>, \"label\" | keyof LabelA11y>\n): ReactElement {\n const {\n id,\n form,\n autoCompleteValue,\n autoComplete = autoCompleteValue,\n name = autoCompleteValue,\n className,\n onClick,\n onFocus,\n onKeyDown,\n inputRef: propInputRef,\n inputProps,\n containerRef,\n placeholder,\n menuProps = {},\n label,\n labelProps = {},\n selectedOptionProps,\n getSelectedOptionChildren = defaultGetSelectedOptionChildren,\n icon: propIcon,\n value,\n defaultValue,\n theme: propTheme,\n onChange = noop,\n rightAddon: propRightAddon,\n active = false,\n required,\n selectedIconAfter = false,\n disableOptionAddon = false,\n disableSelectedIcon = false,\n children,\n ...remaining\n } = props;\n const { dense, error, disabled } = props;\n\n const comboboxId = useEnsuredId(id, \"select\");\n const inputId = useEnsuredId(inputProps?.id, \"select-value\");\n const selectLabelId = useEnsuredId(labelProps.id, \"select-label\");\n const labelId = label ? selectLabelId : undefined;\n\n const [localValue, setLocalValue] = useState(() => {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n\n return value !== undefined ? value : EMPTY_STRING;\n });\n const currentValue = value === undefined ? localValue : value;\n const initialValue = useRef(currentValue);\n const { options, currentOption } = extractOptionsFromChildren(\n children,\n currentValue\n );\n\n const { visible, comboboxProps, movementContext, getMenuProps } =\n useSelectCombobox({\n form,\n value: currentValue,\n values: options,\n onClick,\n onFocus,\n onKeyDown,\n disabled,\n popupId: menuProps.id,\n popupRef: menuProps.ref,\n comboboxId,\n comboboxRef: containerRef,\n });\n\n const [inputRef, inputRefCallback] = useEnsuredRef(propInputRef);\n useFormReset({\n form,\n elementRef: inputRef,\n defaultValue: initialValue.current,\n });\n\n const icon = getIcon(\"dropdown\", propIcon);\n const theme = getFormConfig(\"theme\", propTheme);\n let rightAddon = propRightAddon;\n if (rightAddon === undefined && icon) {\n rightAddon = <IconRotator rotated={visible}>{icon}</IconRotator>;\n }\n\n const { ref: listboxRef, ...listboxProps } = getMenuProps(menuProps);\n let listboxLabelledBy = menuProps[\"aria-labelledby\"];\n const listboxLabel = menuProps[\"aria-label\"];\n if (!listboxLabel && !listboxLabelledBy) {\n listboxLabelledBy = labelId || comboboxId;\n }\n\n return (\n <KeyboardMovementProvider value={movementContext}>\n <TextFieldContainer\n aria-labelledby={labelId}\n {...remaining}\n {...comboboxProps}\n label={!!label}\n theme={theme}\n active={active || visible}\n className={cnb(\"rmd-select-container\", className)}\n rightAddon={rightAddon}\n >\n <SelectedOption\n option={currentOption}\n disableAddon={disableOptionAddon}\n {...selectedOptionProps}\n >\n {getSelectedOptionChildren({\n value: currentValue,\n option: currentOption,\n placeholder,\n children: selectedOptionProps?.children,\n })}\n </SelectedOption>\n <input\n aria-hidden\n id={inputId}\n ref={inputRefCallback}\n type=\"text\"\n autoComplete={autoComplete}\n name={name}\n tabIndex={-1}\n disabled={disabled}\n required={required}\n placeholder=\" \"\n {...inputProps}\n value={value}\n defaultValue={defaultValue}\n className={cnb(select({ theme }), textField())}\n onChange={(event) => {\n onChange(event as SelectChangeEvent<Value>);\n if (value !== undefined) {\n return;\n }\n\n const nextValue = event.currentTarget.value;\n const nextOption = options.find((option) => option === nextValue);\n\n setLocalValue(nextOption ?? initialValue.current);\n }}\n />\n {label && (\n <span\n {...labelProps}\n id={labelId}\n className={labelStyles({\n dense,\n error,\n disabled,\n active: active || visible,\n floating: true,\n floatingActive: !!placeholder || !!currentOption,\n className: labelProps.className,\n })}\n >\n {label}\n </span>\n )}\n </TextFieldContainer>\n <Listbox\n {...listboxProps}\n aria-label={listboxLabel}\n aria-labelledby={listboxLabelledBy as string}\n nodeRef={listboxRef}\n value={currentValue}\n setValue={useCallback(\n (option: \"\" | Value) => {\n triggerManualChangeEvent(inputRef.current, option);\n },\n [inputRef]\n )}\n selectedIconAfter={selectedIconAfter}\n disableSelectedIcon={disableSelectedIcon}\n >\n {children}\n </Listbox>\n </KeyboardMovementProvider>\n );\n}\n"],"names":["cnb","useCallback","useRef","useState","IconRotator","getIcon","KeyboardMovementProvider","useEnsuredId","useEnsuredRef","Listbox","SelectedOption","TextFieldContainer","getFormConfig","label","labelStyles","select","extractOptionsFromChildren","textField","useFormReset","useSelectCombobox","triggerManualChangeEvent","EMPTY_STRING","noop","defaultGetSelectedOptionChildren","options","children","option","placeholder","Select","props","id","form","autoCompleteValue","autoComplete","name","className","onClick","onFocus","onKeyDown","inputRef","propInputRef","inputProps","containerRef","menuProps","labelProps","selectedOptionProps","getSelectedOptionChildren","icon","propIcon","value","defaultValue","theme","propTheme","onChange","rightAddon","propRightAddon","active","required","selectedIconAfter","disableOptionAddon","disableSelectedIcon","remaining","dense","error","disabled","comboboxId","inputId","selectLabelId","labelId","undefined","localValue","setLocalValue","currentValue","initialValue","currentOption","visible","comboboxProps","movementContext","getMenuProps","values","popupId","popupRef","ref","comboboxRef","inputRefCallback","elementRef","current","rotated","listboxRef","listboxProps","listboxLabelledBy","listboxLabel","aria-labelledby","disableAddon","input","aria-hidden","type","tabIndex","event","nextValue","currentTarget","nextOption","find","span","floating","floatingActive","aria-label","nodeRef","setValue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/form/Select.tsx"],"sourcesContent":["\"use client\";\n\nimport { cnb } from \"cnbuilder\";\nimport {\n type ChangeEvent,\n type HTMLAttributes,\n type InputHTMLAttributes,\n type ReactElement,\n type ReactNode,\n type Ref,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nimport { type BoxProps } from \"../box/Box.js\";\nimport { IconRotator } from \"../icon/IconRotator.js\";\nimport { getIcon } from \"../icon/config.js\";\nimport { type MenuProps } from \"../menu/Menu.js\";\nimport { KeyboardMovementProvider } from \"../movement/useKeyboardMovementProvider.js\";\nimport {\n type LabelA11y,\n type PropsWithRef,\n type RequireAtLeastOne,\n} from \"../types.js\";\nimport { useEnsuredId } from \"../useEnsuredId.js\";\nimport { useEnsuredRef } from \"../useEnsuredRef.js\";\nimport { Listbox } from \"./Listbox.js\";\nimport { type OptionProps } from \"./Option.js\";\nimport { SelectedOption } from \"./SelectedOption.js\";\nimport {\n TextFieldContainer,\n type TextFieldContainerProps,\n} from \"./TextFieldContainer.js\";\nimport { getFormConfig } from \"./formConfig.js\";\nimport { label as labelStyles } from \"./labelStyles.js\";\nimport { select } from \"./selectStyles.js\";\nimport { extractOptionsFromChildren } from \"./selectUtils.js\";\nimport { textField } from \"./textFieldStyles.js\";\nimport { type UserAgentAutocompleteProps } from \"./types.js\";\nimport { useFormReset } from \"./useFormReset.js\";\nimport { useSelectCombobox } from \"./useSelectCombobox.js\";\nimport { triggerManualChangeEvent } from \"./utils.js\";\n\nconst EMPTY_STRING = \"\" as const;\nconst noop = (): void => {\n // do nothing\n};\n\n/**\n * @since 6.5.0\n */\nexport interface GetSelectedOptionChildrenOptions<\n Value extends string = string,\n> {\n value: \"\" | Value;\n\n /**\n * The option will be undefined if there is no value or matching option.\n */\n option: OptionProps | undefined;\n\n /**\n * This is a pass-through of the {@link SelectProps.placeholder}\n */\n placeholder?: ReactNode;\n\n /**\n * This is a pass-through of the {@link SelectProps.selectedOptionProps}\n */\n children?: ReactNode;\n}\n\n/**\n * @since 6.5.0\n */\nconst defaultGetSelectedOptionChildren = (\n options: GetSelectedOptionChildrenOptions\n): ReactNode => {\n const { children, option, placeholder } = options;\n\n return children ?? (option?.children || placeholder);\n};\n\n/**\n * This is a convenience type for casting the `event.currentTarget.value` of a\n * `Select`'s change event to be union of available values.\n *\n * Note: The change event does not provide any sort of validation on the value\n * so automation tools like Cypress, Playwright, or Selenium might set an\n * invalid value. This also does not work for numbers, so you will need to\n * implement that yourself.\n *\n * @example Simple Usage\n * ```tsx\n * import { Select, type SelectChangeEvent } from \"@react-md/core/form/Select\";\n * import { Option } from \"@react-md/core/form/Option\";\n * import type { ReactElement } from \"react\";\n *\n * type Value = \"\" | \"a\" | \"b\" | \"c\" | \"d\";\n *\n * function Example(): ReactElement {\n * const [value, setValue] = useState<Value>(\"\");\n *\n * const handleChange = (event: SelectChangeEvent<Value>): void => {\n * // No type error!\n * // `event.currentTarget.value`'s type is `Value` instead of a generic `string`\n * setValue(event.currentTarget.value);\n * };\n *\n * return (\n * <Select\n * label=\"Label\"\n * value={value}\n * onChange={handleChange}\n * >\n * <Option value=\"a\">First</Option>\n * <Option value=\"b\">Second</Option>\n * <Option value=\"c\">Third</Option>\n * <Option value=\"d\">Fourth</Option>\n * </Select>\n * );\n * }\n * ```\n * @since 6.0.0\n */\nexport type SelectChangeEvent<Value extends string> =\n ChangeEvent<HTMLInputElement> & { currentTarget: { value: Value } };\n\n/**\n * @since 6.0.0 Rewritten with a new API.\n */\nexport interface SelectProps<Value extends string>\n extends\n Omit<TextFieldContainerProps, \"label\">,\n Pick<InputHTMLAttributes<HTMLInputElement>, \"form\" | \"required\">,\n UserAgentAutocompleteProps {\n /**\n * @defaultValue `\"select-\" + useId()`\n */\n id?: string;\n\n /**\n * Optional placeholder text or element to render while no options have been\n * selected.\n */\n placeholder?: ReactNode;\n\n /**\n * Set this to a custom dropdown icon or `null` to not render a dropdown icon.\n *\n * @defaultValue `getIcon(\"dropdown\")`\n */\n icon?: ReactNode;\n\n /**\n * Set this value to fully control the value of the select component. The\n * {@link onChange} handler **must** also be provided if this prop exists.\n */\n value?: Value;\n\n /**\n * An optional default value when the value of the select component is\n * uncontrolled.\n *\n * @defaultValue `\"\"`\n */\n defaultValue?: Value;\n\n /** @see {@link SelectChangeEvent} */\n onChange?: (event: SelectChangeEvent<Value>) => void;\n\n /**\n * An optional floating label to display like other form fields.\n */\n label?: ReactNode;\n\n /**\n * Optional props to pass to the `<span>` that surrounds the {@link label}\n */\n labelProps?: PropsWithRef<HTMLAttributes<HTMLSpanElement>>;\n\n /**\n * An optional ref to pass to the hidden `<input type=\"text\" />` element that\n * stores the current value. This is really only useful if you'd like to keep\n * this component uncontrolled and access the value through\n * `inputRef.current.value`.\n */\n inputRef?: Ref<HTMLInputElement>;\n inputProps?: InputHTMLAttributes<HTMLInputElement>;\n\n /**\n * A ref for the container `<div>` element.\n */\n containerRef?: Ref<HTMLDivElement>;\n\n /**\n * Any additional props to provide to the `Menu` component that renders all\n * the `Option`s.\n *\n * The menu will always have these default values unless explicity\n * overwritten by this prop:\n *\n * - `aria-labelledby={label ? labelId : id}` -- this will be undefined if\n * `aria-label` is provided\n * - `anchor={BELOW_CENTER_ANCHOR}`\n * - `width=\"min\"`\n */\n menuProps?: PropsWithRef<\n Omit<MenuProps, \"visible\" | \"onRequestClose\" | \"fixedTo\">\n >;\n\n /**\n * Any additional props to pass to the div that contains the current visible\n * option.\n */\n selectedOptionProps?: BoxProps;\n\n /**\n * Set this to `true` if all the `Option` components should display the\n * selected icon after the children instead of before.\n *\n * @see {@link disableSelectedIcon} to remove the selected icon instead.\n *\n * @defaultValue `false`\n */\n selectedIconAfter?: boolean;\n\n /**\n * Set this to `true` to prevent the current option from rendering the\n * `leftAddon` in the `TextFieldContainer`.\n *\n * @defaultValue `false`\n */\n disableOptionAddon?: boolean;\n\n /**\n * Set this to `true` to update all the `Option` components to no longer\n * render an icon while selected.\n *\n * @defaultValue `false`\n */\n disableSelectedIcon?: boolean;\n\n /**\n * @since 6.5.0\n * @defaultValue `({ children, option, placeholder }) => children ?? (option?.children || placeholder)`\n */\n getSelectedOptionChildren?: (\n options: GetSelectedOptionChildrenOptions<Value>\n ) => ReactNode;\n\n /**\n * This should be the available `Option`s for the select to choose from. It\n * can also contain `OptGroup` or any other elements but only clicking on an\n * `Option` component will update the value.\n */\n children: ReactNode;\n}\n\n/**\n * **Client Component**\n *\n * @example Simple Example\n * ```tsx\n * import { Option } from \"@react-md/core/form/Option\";\n * import { Select } from \"@react-md/core/form/Select\";\n * import { useState, type ReactElement } from \"react\";\n *\n * function Example(): ReactElement {\n * const [value, setValue] = useState(\"\");\n *\n * return (\n * <Select\n * label=\"Select\"\n * value={value}\n * onChange={(event) => setValue(event.currentTarget.value)}\n * placeholder=\"Select a value\"\n * >\n * <Option value=\"a\">Option 1</Option>\n * <Option value=\"b\">Option 2</Option>\n * <Option value=\"c\">Option 3</Option>\n * <Option value=\"d\">Option 4</Option>\n * </Select>\n * );\n * }\n * ```\n *\n * @see {@link https://react-md.dev/components/select | Select Demos}\n * @since 6.0.0 Rewritten with a new API.\n */\nexport function Select<Value extends string>(\n props: RequireAtLeastOne<SelectProps<Value>, \"label\" | keyof LabelA11y>\n): ReactElement {\n const {\n id,\n form,\n autoCompleteValue,\n autoComplete = autoCompleteValue,\n name = autoCompleteValue,\n className,\n onClick,\n onFocus,\n onKeyDown,\n inputRef: propInputRef,\n inputProps,\n containerRef,\n placeholder,\n menuProps = {},\n label,\n labelProps = {},\n selectedOptionProps,\n getSelectedOptionChildren = defaultGetSelectedOptionChildren,\n icon: propIcon,\n value,\n defaultValue,\n theme: propTheme,\n onChange = noop,\n rightAddon: propRightAddon,\n active = false,\n required,\n selectedIconAfter = false,\n disableOptionAddon = false,\n disableSelectedIcon = false,\n children,\n ...remaining\n } = props;\n const { dense, error, disabled } = props;\n\n const comboboxId = useEnsuredId(id, \"select\");\n const inputId = useEnsuredId(inputProps?.id, \"select-value\");\n const selectLabelId = useEnsuredId(labelProps.id, \"select-label\");\n const labelId = label ? selectLabelId : undefined;\n\n const [localValue, setLocalValue] = useState(() => {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n\n return value !== undefined ? value : EMPTY_STRING;\n });\n const currentValue = value === undefined ? localValue : value;\n const initialValue = useRef(currentValue);\n const { options, currentOption } = extractOptionsFromChildren(\n children,\n currentValue\n );\n\n const { visible, comboboxProps, movementContext, getMenuProps } =\n useSelectCombobox({\n form,\n value: currentValue,\n values: options,\n onClick,\n onFocus,\n onKeyDown,\n disabled,\n popupId: menuProps.id,\n popupRef: menuProps.ref,\n comboboxId,\n comboboxRef: containerRef,\n });\n\n const [inputRef, inputRefCallback] = useEnsuredRef(propInputRef);\n useFormReset({\n form,\n elementRef: inputRef,\n defaultValue: initialValue.current,\n });\n\n const icon = getIcon(\"dropdown\", propIcon);\n const theme = getFormConfig(\"theme\", propTheme);\n let rightAddon = propRightAddon;\n if (rightAddon === undefined && icon) {\n rightAddon = <IconRotator rotated={visible}>{icon}</IconRotator>;\n }\n\n const { ref: listboxRef, ...listboxProps } = getMenuProps(menuProps);\n let listboxLabelledBy = menuProps[\"aria-labelledby\"];\n const listboxLabel = menuProps[\"aria-label\"];\n if (!listboxLabel && !listboxLabelledBy) {\n listboxLabelledBy = labelId || comboboxId;\n }\n\n return (\n <KeyboardMovementProvider value={movementContext}>\n <TextFieldContainer\n aria-labelledby={labelId}\n {...remaining}\n {...comboboxProps}\n label={!!label}\n theme={theme}\n active={active || visible}\n className={cnb(\"rmd-select-container\", className)}\n rightAddon={rightAddon}\n >\n <SelectedOption\n option={currentOption}\n disableAddon={disableOptionAddon}\n {...selectedOptionProps}\n >\n {getSelectedOptionChildren({\n value: currentValue,\n option: currentOption,\n placeholder,\n children: selectedOptionProps?.children,\n })}\n </SelectedOption>\n <input\n inert\n id={inputId}\n ref={inputRefCallback}\n type=\"text\"\n autoComplete={autoComplete}\n name={name}\n disabled={disabled}\n required={required}\n placeholder=\" \"\n {...inputProps}\n value={value}\n defaultValue={defaultValue}\n className={cnb(select({ theme }), textField())}\n onChange={(event) => {\n onChange(event as SelectChangeEvent<Value>);\n if (value !== undefined) {\n return;\n }\n\n const nextValue = event.currentTarget.value;\n const nextOption = options.find((option) => option === nextValue);\n\n setLocalValue(nextOption ?? initialValue.current);\n }}\n />\n {label && (\n <span\n {...labelProps}\n id={labelId}\n className={labelStyles({\n dense,\n error,\n disabled,\n active: active || visible,\n floating: true,\n floatingActive: !!placeholder || !!currentOption,\n className: labelProps.className,\n })}\n >\n {label}\n </span>\n )}\n </TextFieldContainer>\n <Listbox\n {...listboxProps}\n aria-label={listboxLabel}\n aria-labelledby={listboxLabelledBy as string}\n nodeRef={listboxRef}\n value={currentValue}\n setValue={useCallback(\n (option: \"\" | Value) => {\n triggerManualChangeEvent(inputRef.current, option);\n },\n [inputRef]\n )}\n selectedIconAfter={selectedIconAfter}\n disableSelectedIcon={disableSelectedIcon}\n >\n {children}\n </Listbox>\n </KeyboardMovementProvider>\n );\n}\n"],"names":["cnb","useCallback","useRef","useState","IconRotator","getIcon","KeyboardMovementProvider","useEnsuredId","useEnsuredRef","Listbox","SelectedOption","TextFieldContainer","getFormConfig","label","labelStyles","select","extractOptionsFromChildren","textField","useFormReset","useSelectCombobox","triggerManualChangeEvent","EMPTY_STRING","noop","defaultGetSelectedOptionChildren","options","children","option","placeholder","Select","props","id","form","autoCompleteValue","autoComplete","name","className","onClick","onFocus","onKeyDown","inputRef","propInputRef","inputProps","containerRef","menuProps","labelProps","selectedOptionProps","getSelectedOptionChildren","icon","propIcon","value","defaultValue","theme","propTheme","onChange","rightAddon","propRightAddon","active","required","selectedIconAfter","disableOptionAddon","disableSelectedIcon","remaining","dense","error","disabled","comboboxId","inputId","selectLabelId","labelId","undefined","localValue","setLocalValue","currentValue","initialValue","currentOption","visible","comboboxProps","movementContext","getMenuProps","values","popupId","popupRef","ref","comboboxRef","inputRefCallback","elementRef","current","rotated","listboxRef","listboxProps","listboxLabelledBy","listboxLabel","aria-labelledby","disableAddon","input","inert","type","event","nextValue","currentTarget","nextOption","find","span","floating","floatingActive","aria-label","nodeRef","setValue"],"mappings":"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"}
|
package/dist/form/utils.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* @since 6.0.0 Uses `form.requestSubmit` instead of clicking the submit button
|
|
22
22
|
*/ export function tryToSubmitRelatedForm(event, formId) {
|
|
23
23
|
const { currentTarget } = event;
|
|
24
|
-
let form
|
|
24
|
+
let form;
|
|
25
25
|
if (formId) {
|
|
26
26
|
form = document.getElementById(formId);
|
|
27
27
|
} else {
|
package/dist/form/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/form/utils.ts"],"sourcesContent":["import { type KeyboardEvent } from \"react\";\n\n/**\n * This util should be used to implement the native \"Enter\" keypress behavior\n * for \"fake\" form components to submit the form if exists.\n *\n * The way this will work will be:\n * - attempt to find a form by querying for a parent form element. if no parent\n * form element can be found, try to use the `formId` in a\n * `document.getElementById`\n * - if a form element is found, find the submit button within the form. If\n * there are no submit buttons within the form, try to find a submit button in\n * the document that is linked to this form by `form={formId}`\n * - if the submit button was found, click it to trigger the form submit\n * behavior\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/requestSubmit\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit\n * @internal\n * @since 2.7.0\n * @since 6.0.0 No longer returns a boolean, added the `formId` parameter, and\n * moved into the form package.\n * @since 6.0.0 Uses `form.requestSubmit` instead of clicking the submit button\n */\nexport function tryToSubmitRelatedForm<E extends HTMLElement>(\n event: KeyboardEvent<E>,\n formId: string | undefined\n): void {\n const { currentTarget } = event;\n let form: HTMLElement | null
|
|
1
|
+
{"version":3,"sources":["../../src/form/utils.ts"],"sourcesContent":["import { type KeyboardEvent } from \"react\";\n\n/**\n * This util should be used to implement the native \"Enter\" keypress behavior\n * for \"fake\" form components to submit the form if exists.\n *\n * The way this will work will be:\n * - attempt to find a form by querying for a parent form element. if no parent\n * form element can be found, try to use the `formId` in a\n * `document.getElementById`\n * - if a form element is found, find the submit button within the form. If\n * there are no submit buttons within the form, try to find a submit button in\n * the document that is linked to this form by `form={formId}`\n * - if the submit button was found, click it to trigger the form submit\n * behavior\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/requestSubmit\n * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit\n * @internal\n * @since 2.7.0\n * @since 6.0.0 No longer returns a boolean, added the `formId` parameter, and\n * moved into the form package.\n * @since 6.0.0 Uses `form.requestSubmit` instead of clicking the submit button\n */\nexport function tryToSubmitRelatedForm<E extends HTMLElement>(\n event: KeyboardEvent<E>,\n formId: string | undefined\n): void {\n const { currentTarget } = event;\n let form: HTMLElement | null;\n if (formId) {\n form = document.getElementById(formId);\n } else {\n form = currentTarget.closest(\"form\");\n }\n\n if (!form || !(form instanceof HTMLFormElement)) {\n return;\n }\n\n // eslint-disable-next-line no-param-reassign\n formId = formId || form.id;\n let submit = form.querySelector<HTMLButtonElement>('[type=\"submit\"]');\n if (!submit && formId) {\n submit = document.querySelector<HTMLButtonElement>(\n `[type=\"submit\"][form=\"${formId}\"]`\n );\n }\n\n form.requestSubmit(submit);\n}\n\n/**\n * @internal\n * @since 6.0.0\n */\nexport type EditableHTMLElement = HTMLInputElement | HTMLTextAreaElement;\n\n/**\n * @internal\n * @since 6.0.0\n */\nexport type ChangeableHTMLElement = EditableHTMLElement | HTMLSelectElement;\n\n/**\n * @internal\n * @since 6.0.0\n */\nexport function isChangeableHTMLElement(\n element: Element | null\n): element is ChangeableHTMLElement {\n return !!element && \"value\" in element;\n}\n\n/**\n * This is used to trigger a change event for a form element.\n *\n * @internal\n * @see https://stackoverflow.com/a/46012210\n * @since 6.0.0\n */\nexport function triggerManualChangeEvent(\n element: ChangeableHTMLElement | null,\n value: string | number\n): void {\n if (!element) {\n return;\n }\n\n const prototype = Object.getPrototypeOf(element);\n const setter = Object.getOwnPropertyDescriptor(prototype, \"value\")?.set;\n if (!setter) {\n return;\n }\n\n setter.call(element, value);\n const event = new Event(\"input\", { bubbles: true });\n element.dispatchEvent(event);\n}\n"],"names":["tryToSubmitRelatedForm","event","formId","currentTarget","form","document","getElementById","closest","HTMLFormElement","id","submit","querySelector","requestSubmit","isChangeableHTMLElement","element","triggerManualChangeEvent","value","prototype","Object","getPrototypeOf","setter","getOwnPropertyDescriptor","set","call","Event","bubbles","dispatchEvent"],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,OAAO,SAASA,uBACdC,KAAuB,EACvBC,MAA0B;IAE1B,MAAM,EAAEC,aAAa,EAAE,GAAGF;IAC1B,IAAIG;IACJ,IAAIF,QAAQ;QACVE,OAAOC,SAASC,cAAc,CAACJ;IACjC,OAAO;QACLE,OAAOD,cAAcI,OAAO,CAAC;IAC/B;IAEA,IAAI,CAACH,QAAQ,CAAEA,CAAAA,gBAAgBI,eAAc,GAAI;QAC/C;IACF;IAEA,6CAA6C;IAC7CN,SAASA,UAAUE,KAAKK,EAAE;IAC1B,IAAIC,SAASN,KAAKO,aAAa,CAAoB;IACnD,IAAI,CAACD,UAAUR,QAAQ;QACrBQ,SAASL,SAASM,aAAa,CAC7B,CAAC,sBAAsB,EAAET,OAAO,EAAE,CAAC;IAEvC;IAEAE,KAAKQ,aAAa,CAACF;AACrB;AAcA;;;CAGC,GACD,OAAO,SAASG,wBACdC,OAAuB;IAEvB,OAAO,CAAC,CAACA,WAAW,WAAWA;AACjC;AAEA;;;;;;CAMC,GACD,OAAO,SAASC,yBACdD,OAAqC,EACrCE,KAAsB;IAEtB,IAAI,CAACF,SAAS;QACZ;IACF;IAEA,MAAMG,YAAYC,OAAOC,cAAc,CAACL;IACxC,MAAMM,SAASF,OAAOG,wBAAwB,CAACJ,WAAW,UAAUK;IACpE,IAAI,CAACF,QAAQ;QACX;IACF;IAEAA,OAAOG,IAAI,CAACT,SAASE;IACrB,MAAMf,QAAQ,IAAIuB,MAAM,SAAS;QAAEC,SAAS;IAAK;IACjDX,QAAQY,aAAa,CAACzB;AACxB"}
|
package/dist/icon/_icon.scss
CHANGED
|
@@ -44,6 +44,19 @@ $disable-svg: false !default;
|
|
|
44
44
|
/// @type Boolean
|
|
45
45
|
$disable-symbol: false !default;
|
|
46
46
|
|
|
47
|
+
/// Set to `true` if not using the material symbols or material icon fonts.
|
|
48
|
+
/// When this is false, the following code will be added to override the
|
|
49
|
+
/// default stylesheet:
|
|
50
|
+
///
|
|
51
|
+
/// ```scss
|
|
52
|
+
/// .rmd-icon[class*="material-"] {
|
|
53
|
+
/// @include use-var(font-size, size);
|
|
54
|
+
/// }
|
|
55
|
+
/// ```
|
|
56
|
+
///
|
|
57
|
+
/// @type Boolean
|
|
58
|
+
$disable-material-icons-font-fix: false !default;
|
|
59
|
+
|
|
47
60
|
/// Set to `true` to disable the dense icon sizes
|
|
48
61
|
/// @type Boolean
|
|
49
62
|
$disable-dense: false !default;
|
|
@@ -271,6 +284,12 @@ $_disable-icons: $disable-font and $disable-svg and $disable-symbol;
|
|
|
271
284
|
/// layer behavior
|
|
272
285
|
@mixin styles($disable-layer: false) {
|
|
273
286
|
@if not $_disable-icons {
|
|
287
|
+
@if not $disable-material-icons-font-fix {
|
|
288
|
+
.rmd-icon[class*="material-"] {
|
|
289
|
+
@include use-var(font-size, size);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
274
293
|
@include utils.optional-layer(icon, $disable-layer) {
|
|
275
294
|
@include theme.default-system-theme {
|
|
276
295
|
@include use-dark-theme;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/** @since 7.1.0 */ import { MaterialSymbol } from "./MaterialSymbol.js";
|
|
3
|
+
import { configureIcons } from "./config.js";
|
|
4
|
+
configureIcons({
|
|
5
|
+
back: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
6
|
+
name: "keyboard_arrow_left"
|
|
7
|
+
}),
|
|
8
|
+
clear: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
9
|
+
name: "close_small"
|
|
10
|
+
}),
|
|
11
|
+
close: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
12
|
+
name: "close"
|
|
13
|
+
}),
|
|
14
|
+
checkbox: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
15
|
+
name: "check_box_outline_blank"
|
|
16
|
+
}),
|
|
17
|
+
checkboxChecked: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
18
|
+
name: "check_box"
|
|
19
|
+
}),
|
|
20
|
+
checkboxIndeterminate: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
21
|
+
name: "indeterminate_check_box"
|
|
22
|
+
}),
|
|
23
|
+
dropdown: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
24
|
+
name: "arrow_drop_down"
|
|
25
|
+
}),
|
|
26
|
+
error: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
27
|
+
name: "error"
|
|
28
|
+
}),
|
|
29
|
+
expander: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
30
|
+
name: "keyboard_arrow_down"
|
|
31
|
+
}),
|
|
32
|
+
forward: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
33
|
+
name: "keyboard_arrow_right"
|
|
34
|
+
}),
|
|
35
|
+
menu: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
36
|
+
name: "menu"
|
|
37
|
+
}),
|
|
38
|
+
notification: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
39
|
+
name: "notifications"
|
|
40
|
+
}),
|
|
41
|
+
password: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
42
|
+
name: "visibility"
|
|
43
|
+
}),
|
|
44
|
+
radio: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
45
|
+
name: "radio_button_unchecked"
|
|
46
|
+
}),
|
|
47
|
+
radioChecked: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
48
|
+
name: "radio_button_checked"
|
|
49
|
+
}),
|
|
50
|
+
remove: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
51
|
+
name: "cancel"
|
|
52
|
+
}),
|
|
53
|
+
selected: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
54
|
+
name: "check"
|
|
55
|
+
}),
|
|
56
|
+
sort: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
57
|
+
name: "arrow_upward"
|
|
58
|
+
}),
|
|
59
|
+
upload: /*#__PURE__*/ _jsx(MaterialSymbol, {
|
|
60
|
+
name: "upload"
|
|
61
|
+
})
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=configureMaterialSymbols.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/icon/configureMaterialSymbols.tsx"],"sourcesContent":["/** @since 7.1.0 */\nimport { MaterialSymbol } from \"./MaterialSymbol.js\";\nimport { configureIcons } from \"./config.js\";\n\nconfigureIcons({\n back: <MaterialSymbol name=\"keyboard_arrow_left\" />,\n clear: <MaterialSymbol name=\"close_small\" />,\n close: <MaterialSymbol name=\"close\" />,\n checkbox: <MaterialSymbol name=\"check_box_outline_blank\" />,\n checkboxChecked: <MaterialSymbol name=\"check_box\" />,\n checkboxIndeterminate: <MaterialSymbol name=\"indeterminate_check_box\" />,\n dropdown: <MaterialSymbol name=\"arrow_drop_down\" />,\n error: <MaterialSymbol name=\"error\" />,\n expander: <MaterialSymbol name=\"keyboard_arrow_down\" />,\n forward: <MaterialSymbol name=\"keyboard_arrow_right\" />,\n menu: <MaterialSymbol name=\"menu\" />,\n notification: <MaterialSymbol name=\"notifications\" />,\n password: <MaterialSymbol name=\"visibility\" />,\n radio: <MaterialSymbol name=\"radio_button_unchecked\" />,\n radioChecked: <MaterialSymbol name=\"radio_button_checked\" />,\n remove: <MaterialSymbol name=\"cancel\" />,\n selected: <MaterialSymbol name=\"check\" />,\n sort: <MaterialSymbol name=\"arrow_upward\" />,\n upload: <MaterialSymbol name=\"upload\" />,\n});\n"],"names":["MaterialSymbol","configureIcons","back","name","clear","close","checkbox","checkboxChecked","checkboxIndeterminate","dropdown","error","expander","forward","menu","notification","password","radio","radioChecked","remove","selected","sort","upload"],"mappings":";AAAA,iBAAiB,GACjB,SAASA,cAAc,QAAQ,sBAAsB;AACrD,SAASC,cAAc,QAAQ,cAAc;AAE7CA,eAAe;IACbC,oBAAM,KAACF;QAAeG,MAAK;;IAC3BC,qBAAO,KAACJ;QAAeG,MAAK;;IAC5BE,qBAAO,KAACL;QAAeG,MAAK;;IAC5BG,wBAAU,KAACN;QAAeG,MAAK;;IAC/BI,+BAAiB,KAACP;QAAeG,MAAK;;IACtCK,qCAAuB,KAACR;QAAeG,MAAK;;IAC5CM,wBAAU,KAACT;QAAeG,MAAK;;IAC/BO,qBAAO,KAACV;QAAeG,MAAK;;IAC5BQ,wBAAU,KAACX;QAAeG,MAAK;;IAC/BS,uBAAS,KAACZ;QAAeG,MAAK;;IAC9BU,oBAAM,KAACb;QAAeG,MAAK;;IAC3BW,4BAAc,KAACd;QAAeG,MAAK;;IACnCY,wBAAU,KAACf;QAAeG,MAAK;;IAC/Ba,qBAAO,KAAChB;QAAeG,MAAK;;IAC5Bc,4BAAc,KAACjB;QAAeG,MAAK;;IACnCe,sBAAQ,KAAClB;QAAeG,MAAK;;IAC7BgB,wBAAU,KAACnB;QAAeG,MAAK;;IAC/BiB,oBAAM,KAACpB;QAAeG,MAAK;;IAC3BkB,sBAAQ,KAACrB;QAAeG,MAAK;;AAC/B"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal
|
|
3
|
+
* @since 7.1.0
|
|
4
|
+
*/ export function getMaterialSymbolOption(value, fallback) {
|
|
5
|
+
if (!value) {
|
|
6
|
+
return `${fallback}`;
|
|
7
|
+
}
|
|
8
|
+
if (typeof value === "number") {
|
|
9
|
+
return `${value}`;
|
|
10
|
+
}
|
|
11
|
+
return `${value.min}..${value.max}`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=getMaterialSymbolOption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/icon/getMaterialSymbolOption.ts"],"sourcesContent":["import { type GoogleFontsAPIValueOrRange } from \"./getMaterialSymbolsUrl.js\";\n\n/**\n * @internal\n * @since 7.1.0\n */\nexport function getMaterialSymbolOption<T extends number>(\n value: GoogleFontsAPIValueOrRange<T> | undefined,\n fallback: T\n): string {\n if (!value) {\n return `${fallback}`;\n }\n\n if (typeof value === \"number\") {\n return `${value}`;\n }\n\n return `${value.min}..${value.max}`;\n}\n"],"names":["getMaterialSymbolOption","value","fallback","min","max"],"mappings":"AAEA;;;CAGC,GACD,OAAO,SAASA,wBACdC,KAAgD,EAChDC,QAAW;IAEX,IAAI,CAACD,OAAO;QACV,OAAO,GAAGC,UAAU;IACtB;IAEA,IAAI,OAAOD,UAAU,UAAU;QAC7B,OAAO,GAAGA,OAAO;IACnB;IAEA,OAAO,GAAGA,MAAME,GAAG,CAAC,EAAE,EAAEF,MAAMG,GAAG,EAAE;AACrC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type MaterialSymbolFamily, type MaterialSymbolName } from "./material.js";
|
|
2
|
+
import { type MaterialSymbolFill, type MaterialSymbolGrade, type MaterialSymbolOpticalSize, type MaterialSymbolWeight } from "./materialConfig.js";
|
|
3
|
+
/**
|
|
4
|
+
* @since 7.1.0
|
|
5
|
+
*/
|
|
6
|
+
export type GoogleFontsAPIValueOrRange<T extends number> = T | {
|
|
7
|
+
min: T;
|
|
8
|
+
max: T;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* @since 7.1.0
|
|
12
|
+
*/
|
|
13
|
+
export interface MaterialSymbolsGoogleFontUrlOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Provide this value if the `MATERIAL_CONFIG.family` is not the default.
|
|
16
|
+
*
|
|
17
|
+
* @defaultValue `"outlined"`
|
|
18
|
+
*/
|
|
19
|
+
family?: MaterialSymbolFamily | readonly MaterialSymbolFamily[];
|
|
20
|
+
/**
|
|
21
|
+
* Provide this value if the `MATERIAL_CONFIG.fill` is not the default.
|
|
22
|
+
*
|
|
23
|
+
* @defaultValue `0`
|
|
24
|
+
*/
|
|
25
|
+
fill?: GoogleFontsAPIValueOrRange<MaterialSymbolFill>;
|
|
26
|
+
/**
|
|
27
|
+
* Provide this value if the `MATERIAL_CONFIG.grade` is not the default.
|
|
28
|
+
*
|
|
29
|
+
* @defaultValue `0`
|
|
30
|
+
*/
|
|
31
|
+
grade?: GoogleFontsAPIValueOrRange<MaterialSymbolGrade>;
|
|
32
|
+
/**
|
|
33
|
+
* Provide this value if the `MATERIAL_CONFIG.weight` is not the default.
|
|
34
|
+
*
|
|
35
|
+
* @defaultValue `400`
|
|
36
|
+
*/
|
|
37
|
+
weight?: GoogleFontsAPIValueOrRange<MaterialSymbolWeight>;
|
|
38
|
+
/**
|
|
39
|
+
* Provide this value if the `MATERIAL_CONFIG.opticalSize` is not the default.
|
|
40
|
+
*
|
|
41
|
+
* @defaultValue `48`
|
|
42
|
+
*/
|
|
43
|
+
opticalSize?: GoogleFontsAPIValueOrRange<MaterialSymbolOpticalSize>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* @since 7.1.0
|
|
47
|
+
*/
|
|
48
|
+
export interface MaterialSymbolsUrlOptions extends MaterialSymbolsGoogleFontUrlOptions {
|
|
49
|
+
/**
|
|
50
|
+
* @see {@link DEFAULT_MATERIAL_SYMBOL_NAMES}
|
|
51
|
+
* @defaultValue `DEFAULT_MATERIAL_SYMBOL_NAMES`
|
|
52
|
+
*/
|
|
53
|
+
names?: readonly MaterialSymbolName[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* @since 7.1.0
|
|
57
|
+
*/
|
|
58
|
+
export declare function getMaterialSymbolsUrl(options?: MaterialSymbolsUrlOptions): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { alphaNumericSort } from "../utils/alphaNumericSort.js";
|
|
2
|
+
import { getMaterialSymbolOption } from "./getMaterialSymbolOption.js";
|
|
3
|
+
import { MATERIAL_CONFIG } from "./materialConfig.js";
|
|
4
|
+
import { DEFAULT_MATERIAL_SYMBOL_NAMES } from "./symbols.js";
|
|
5
|
+
/**
|
|
6
|
+
* @since 7.1.0
|
|
7
|
+
*/ export function getMaterialSymbolsUrl(options = {}) {
|
|
8
|
+
// the names have to be sorted for the google fonts api
|
|
9
|
+
const names = alphaNumericSort([
|
|
10
|
+
...new Set(options.names ?? DEFAULT_MATERIAL_SYMBOL_NAMES)
|
|
11
|
+
]);
|
|
12
|
+
const fill = getMaterialSymbolOption(options.fill, MATERIAL_CONFIG.fill);
|
|
13
|
+
const grade = getMaterialSymbolOption(options.grade, MATERIAL_CONFIG.grade);
|
|
14
|
+
const weight = getMaterialSymbolOption(options.weight, MATERIAL_CONFIG.weight);
|
|
15
|
+
const opticalSize = getMaterialSymbolOption(options.opticalSize, MATERIAL_CONFIG.opticalSize);
|
|
16
|
+
const specs = `:opsz,wght,FILL,GRAD@${opticalSize},${weight},${fill},${grade}`;
|
|
17
|
+
const families = typeof options.family === "string" || options.family === undefined ? [
|
|
18
|
+
options.family ?? MATERIAL_CONFIG.family
|
|
19
|
+
] : options.family;
|
|
20
|
+
let familiesQs = "";
|
|
21
|
+
for (const [i, family] of families.entries()){
|
|
22
|
+
const variant = family.charAt(0).toUpperCase() + family.slice(1);
|
|
23
|
+
familiesQs += (i === 0 ? "" : "&") + "family=Material+Symbols+" + variant;
|
|
24
|
+
}
|
|
25
|
+
let iconNames = "";
|
|
26
|
+
if (names.length > 0) {
|
|
27
|
+
iconNames = `&icon_names=${names.join(",")}`;
|
|
28
|
+
}
|
|
29
|
+
return `https://fonts.googleapis.com/css2?${familiesQs}${specs}${iconNames}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=getMaterialSymbolsUrl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/icon/getMaterialSymbolsUrl.ts"],"sourcesContent":["import { alphaNumericSort } from \"../utils/alphaNumericSort.js\";\nimport { getMaterialSymbolOption } from \"./getMaterialSymbolOption.js\";\nimport {\n type MaterialSymbolFamily,\n type MaterialSymbolName,\n} from \"./material.js\";\nimport {\n MATERIAL_CONFIG,\n type MaterialSymbolFill,\n type MaterialSymbolGrade,\n type MaterialSymbolOpticalSize,\n type MaterialSymbolWeight,\n} from \"./materialConfig.js\";\nimport { DEFAULT_MATERIAL_SYMBOL_NAMES } from \"./symbols.js\";\n\n/**\n * @since 7.1.0\n */\nexport type GoogleFontsAPIValueOrRange<T extends number> =\n | T\n | { min: T; max: T };\n\n/**\n * @since 7.1.0\n */\nexport interface MaterialSymbolsGoogleFontUrlOptions {\n /**\n * Provide this value if the `MATERIAL_CONFIG.family` is not the default.\n *\n * @defaultValue `\"outlined\"`\n */\n family?: MaterialSymbolFamily | readonly MaterialSymbolFamily[];\n\n /**\n * Provide this value if the `MATERIAL_CONFIG.fill` is not the default.\n *\n * @defaultValue `0`\n */\n fill?: GoogleFontsAPIValueOrRange<MaterialSymbolFill>;\n\n /**\n * Provide this value if the `MATERIAL_CONFIG.grade` is not the default.\n *\n * @defaultValue `0`\n */\n grade?: GoogleFontsAPIValueOrRange<MaterialSymbolGrade>;\n\n /**\n * Provide this value if the `MATERIAL_CONFIG.weight` is not the default.\n *\n * @defaultValue `400`\n */\n weight?: GoogleFontsAPIValueOrRange<MaterialSymbolWeight>;\n\n /**\n * Provide this value if the `MATERIAL_CONFIG.opticalSize` is not the default.\n *\n * @defaultValue `48`\n */\n opticalSize?: GoogleFontsAPIValueOrRange<MaterialSymbolOpticalSize>;\n}\n\n/**\n * @since 7.1.0\n */\nexport interface MaterialSymbolsUrlOptions extends MaterialSymbolsGoogleFontUrlOptions {\n /**\n * @see {@link DEFAULT_MATERIAL_SYMBOL_NAMES}\n * @defaultValue `DEFAULT_MATERIAL_SYMBOL_NAMES`\n */\n names?: readonly MaterialSymbolName[];\n}\n\n/**\n * @since 7.1.0\n */\nexport function getMaterialSymbolsUrl(\n options: MaterialSymbolsUrlOptions = {}\n): string {\n // the names have to be sorted for the google fonts api\n const names = alphaNumericSort([\n ...new Set(options.names ?? DEFAULT_MATERIAL_SYMBOL_NAMES),\n ]);\n const fill = getMaterialSymbolOption(options.fill, MATERIAL_CONFIG.fill);\n const grade = getMaterialSymbolOption(options.grade, MATERIAL_CONFIG.grade);\n const weight = getMaterialSymbolOption(\n options.weight,\n MATERIAL_CONFIG.weight\n );\n const opticalSize = getMaterialSymbolOption(\n options.opticalSize,\n MATERIAL_CONFIG.opticalSize\n );\n const specs = `:opsz,wght,FILL,GRAD@${opticalSize},${weight},${fill},${grade}`;\n\n const families =\n typeof options.family === \"string\" || options.family === undefined\n ? [options.family ?? MATERIAL_CONFIG.family]\n : options.family;\n let familiesQs = \"\";\n for (const [i, family] of families.entries()) {\n const variant = family.charAt(0).toUpperCase() + family.slice(1);\n familiesQs += (i === 0 ? \"\" : \"&\") + \"family=Material+Symbols+\" + variant;\n }\n\n let iconNames = \"\";\n if (names.length > 0) {\n iconNames = `&icon_names=${names.join(\",\")}`;\n }\n\n return `https://fonts.googleapis.com/css2?${familiesQs}${specs}${iconNames}`;\n}\n"],"names":["alphaNumericSort","getMaterialSymbolOption","MATERIAL_CONFIG","DEFAULT_MATERIAL_SYMBOL_NAMES","getMaterialSymbolsUrl","options","names","Set","fill","grade","weight","opticalSize","specs","families","family","undefined","familiesQs","i","entries","variant","charAt","toUpperCase","slice","iconNames","length","join"],"mappings":"AAAA,SAASA,gBAAgB,QAAQ,+BAA+B;AAChE,SAASC,uBAAuB,QAAQ,+BAA+B;AAKvE,SACEC,eAAe,QAKV,sBAAsB;AAC7B,SAASC,6BAA6B,QAAQ,eAAe;AA4D7D;;CAEC,GACD,OAAO,SAASC,sBACdC,UAAqC,CAAC,CAAC;IAEvC,uDAAuD;IACvD,MAAMC,QAAQN,iBAAiB;WAC1B,IAAIO,IAAIF,QAAQC,KAAK,IAAIH;KAC7B;IACD,MAAMK,OAAOP,wBAAwBI,QAAQG,IAAI,EAAEN,gBAAgBM,IAAI;IACvE,MAAMC,QAAQR,wBAAwBI,QAAQI,KAAK,EAAEP,gBAAgBO,KAAK;IAC1E,MAAMC,SAAST,wBACbI,QAAQK,MAAM,EACdR,gBAAgBQ,MAAM;IAExB,MAAMC,cAAcV,wBAClBI,QAAQM,WAAW,EACnBT,gBAAgBS,WAAW;IAE7B,MAAMC,QAAQ,CAAC,qBAAqB,EAAED,YAAY,CAAC,EAAED,OAAO,CAAC,EAAEF,KAAK,CAAC,EAAEC,OAAO;IAE9E,MAAMI,WACJ,OAAOR,QAAQS,MAAM,KAAK,YAAYT,QAAQS,MAAM,KAAKC,YACrD;QAACV,QAAQS,MAAM,IAAIZ,gBAAgBY,MAAM;KAAC,GAC1CT,QAAQS,MAAM;IACpB,IAAIE,aAAa;IACjB,KAAK,MAAM,CAACC,GAAGH,OAAO,IAAID,SAASK,OAAO,GAAI;QAC5C,MAAMC,UAAUL,OAAOM,MAAM,CAAC,GAAGC,WAAW,KAAKP,OAAOQ,KAAK,CAAC;QAC9DN,cAAc,AAACC,CAAAA,MAAM,IAAI,KAAK,GAAE,IAAK,6BAA6BE;IACpE;IAEA,IAAII,YAAY;IAChB,IAAIjB,MAAMkB,MAAM,GAAG,GAAG;QACpBD,YAAY,CAAC,YAAY,EAAEjB,MAAMmB,IAAI,CAAC,MAAM;IAC9C;IAEA,OAAO,CAAC,kCAAkC,EAAET,aAAaJ,QAAQW,WAAW;AAC9E"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 7.1.0
|
|
3
|
+
*/
|
|
4
|
+
export declare const DEFAULT_MATERIAL_SYMBOL_NAMES: ("error" | "cancel" | "close" | "visibility" | "menu" | "arrow_drop_down" | "arrow_upward" | "check" | "check_box" | "check_box_outline_blank" | "indeterminate_check_box" | "keyboard_arrow_down" | "keyboard_arrow_left" | "keyboard_arrow_right" | "notifications" | "radio_button_checked" | "radio_button_unchecked" | "upload" | "close_small")[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 7.1.0
|
|
3
|
+
*/ export const DEFAULT_MATERIAL_SYMBOL_NAMES = [
|
|
4
|
+
"keyboard_arrow_left",
|
|
5
|
+
"close_small",
|
|
6
|
+
"close",
|
|
7
|
+
"check_box_outline_blank",
|
|
8
|
+
"check_box",
|
|
9
|
+
"indeterminate_check_box",
|
|
10
|
+
"arrow_drop_down",
|
|
11
|
+
"error",
|
|
12
|
+
"keyboard_arrow_down",
|
|
13
|
+
"keyboard_arrow_right",
|
|
14
|
+
"menu",
|
|
15
|
+
"notifications",
|
|
16
|
+
"visibility",
|
|
17
|
+
"radio_button_unchecked",
|
|
18
|
+
"radio_button_checked",
|
|
19
|
+
"cancel",
|
|
20
|
+
"check",
|
|
21
|
+
"arrow_upward",
|
|
22
|
+
"upload"
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=symbols.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/icon/symbols.ts"],"sourcesContent":["import { type MaterialSymbolName } from \"./material.js\";\n\n/**\n * @since 7.1.0\n */\nexport const DEFAULT_MATERIAL_SYMBOL_NAMES = [\n \"keyboard_arrow_left\",\n \"close_small\",\n \"close\",\n \"check_box_outline_blank\",\n \"check_box\",\n \"indeterminate_check_box\",\n \"arrow_drop_down\",\n \"error\",\n \"keyboard_arrow_down\",\n \"keyboard_arrow_right\",\n \"menu\",\n \"notifications\",\n \"visibility\",\n \"radio_button_unchecked\",\n \"radio_button_checked\",\n \"cancel\",\n \"check\",\n \"arrow_upward\",\n \"upload\",\n] satisfies readonly MaterialSymbolName[];\n"],"names":["DEFAULT_MATERIAL_SYMBOL_NAMES"],"mappings":"AAEA;;CAEC,GACD,OAAO,MAAMA,gCAAgC;IAC3C;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,CAAyC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CSSTransitionElementProps } from "../transition/types.js";
|
|
2
|
-
import { type CssPosition, type UseStateInitializer } from "../types.js";
|
|
2
|
+
import { type CssPosition, type LiteralStringUnion, type UseStateInitializer } from "../types.js";
|
|
3
3
|
import { type LayoutNavProps } from "./LayoutNav.js";
|
|
4
4
|
import { type HorizontalLayoutTransitionOptions } from "./useHorizontalLayoutTransition.js";
|
|
5
5
|
import { type ProvidedLayoutNavToggleProps, type ProvidedTemporaryLayoutAppBarProps, type ProvidedTemporaryLayoutMainProps, type TemporaryLayoutImplementation, type TemporaryLayoutOptions } from "./useTemporaryLayout.js";
|
|
@@ -44,7 +44,7 @@ export interface ExpandableLayoutOptions extends TemporaryLayoutOptions {
|
|
|
44
44
|
*
|
|
45
45
|
* @defaultValue `"tablet"`
|
|
46
46
|
*/
|
|
47
|
-
temporaryUntil?: "tablet" | "desktop"
|
|
47
|
+
temporaryUntil?: LiteralStringUnion<"tablet" | "desktop">;
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
50
|
* @since 6.0.0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/layout/useExpandableLayout.ts"],"sourcesContent":["\"use client\";\n\nimport { cnb } from \"cnbuilder\";\n\nimport { useSsr } from \"../SsrProvider.js\";\nimport { useAppSize } from \"../media-queries/AppSizeProvider.js\";\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { type AppSize } from \"../media-queries/appSize.js\";\nimport { MEDIA_QUERY_CONFIG } from \"../media-queries/config.js\";\nimport { useMediaQuery } from \"../media-queries/useMediaQuery.js\";\nimport { type CSSTransitionElementProps } from \"../transition/types.js\";\nimport { type CssPosition, type UseStateInitializer } from \"../types.js\";\nimport { useToggle } from \"../useToggle.js\";\nimport { useDevEffect } from \"../utils/useDevEffect.js\";\nimport { type LayoutNavProps } from \"./LayoutNav.js\";\nimport {\n type HorizontalLayoutTransitionOptions,\n useHorizontalLayoutTransition,\n} from \"./useHorizontalLayoutTransition.js\";\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { type useResizableLayout } from \"./useResizableLayout.js\";\nimport {\n type ProvidedLayoutNavToggleProps,\n type ProvidedTemporaryLayoutAppBarProps,\n type ProvidedTemporaryLayoutMainProps,\n type TemporaryLayoutImplementation,\n type TemporaryLayoutOptions,\n useTemporaryLayout,\n} from \"./useTemporaryLayout.js\";\n\nlet loggedOnce = false;\n\n/**\n * @since 6.0.0\n */\nexport interface ExpandableLayoutOptions extends TemporaryLayoutOptions {\n /** @defaultValue `\"fixed\"` */\n appBarPosition?: CssPosition;\n\n /** @defaultValue `false` */\n defaultExpanded?: UseStateInitializer<boolean>;\n\n /**\n * Set this to `true` if the expandable navigation should be the full height\n * of the screen. This will also update the app bar so that it is not covered\n * by the navigation. The default behavior is to place the navigation below\n * the fixed header.\n *\n * Set this to `\"static\"` to make the navigation span the full height of the\n * screen and hide the button until the screen shrinks to the temporary\n * layout type.\n *\n * @defaultValue `false`\n */\n fullHeightNav?: boolean | \"static\";\n\n /** @see {@link HorizontalLayoutTransitionOptions} */\n transitionProps?: Omit<HorizontalLayoutTransitionOptions, \"transitionIn\">;\n\n /**\n * The default behavior is to use the temporary layout until the\n * {@link AppSize.isTablet} is `true`. Set this to `\"desktop\"` to use the\n * temporary layout until {@link AppSize.isDesktop} is `true`. Otherwise,\n * provide a media query string to use the temporary layout until the media\n * query matches\n *\n * @example Custom Media Query\n * ```tsx\n * useExpandableLayout({\n * ...options,\n * // display the expandable layout once the min-width is at least 1201px\n * temporaryUntil: \"screen and (min-width: 1201px)\",\n * });\n * ```\n *\n * @defaultValue `\"tablet\"`\n */\n temporaryUntil?: \"tablet\" | \"desktop\" | (string & {});\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ProvidedLayoutMainProps\n extends\n ProvidedTemporaryLayoutMainProps,\n CSSTransitionElementProps<HTMLElement> {}\n\n/**\n * @since 6.0.0\n */\nexport type ProvidedLayoutNavProps = Pick<\n LayoutNavProps,\n \"expanded\" | \"appBarOffset\"\n>;\n\n/**\n * @since 6.0.0\n */\nexport type ProvidedLayoutAppBarProps = ProvidedTemporaryLayoutAppBarProps &\n Partial<CSSTransitionElementProps<HTMLElement>>;\n\n/**\n * @since 6.0.0\n */\nexport interface ProvidedExpandableLayoutNavToggleProps extends ProvidedLayoutNavToggleProps {\n className: string;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ExpandableLayoutImplementation extends TemporaryLayoutImplementation {\n temporary: boolean;\n persistent: boolean;\n expanded: boolean;\n expandNavigation: () => void;\n collapseNavigation: () => void;\n toggleNavigation: () => void;\n appBarProps: ProvidedLayoutAppBarProps;\n mainProps: ProvidedLayoutMainProps;\n navToggleProps: ProvidedExpandableLayoutNavToggleProps;\n expandableNavProps: ProvidedLayoutNavProps;\n}\n\n/**\n * @example Main Usage\n * ```tsx\n * import { AppBarTitle } from \"@react-md/core/app-bar/AppBarTitle\";\n * import { Button } from \"@react-md/core/button/Button\";\n * import { LayoutAppBar } from \"@react-md/core/layout/LayoutAppBar\";\n * import { LayoutNav } from \"@react-md/core/layout/LayoutNav\";\n * import { Main } from \"@react-md/core/layout/Main\";\n * import { useExpandableLayout } from \"@react-md/core/layout/useExpandableLayout\";\n * import { Sheet } from \"@react-md/core/sheet/Sheet\";\n * import { type ReactElement, type ReactNode } from \"react\";\n *\n * import { CustomNavigation } from \"./CustomNavigation\";\n *\n * export interface LayoutProps {\n * children: ReactNode;\n * }\n *\n * export function Layout(props: LayoutProps): ReactElement {\n * const { children } = props;\n *\n * // choose whichever one for your app\n * // nextjs app dir\n * const pathname = usePathname();\n * // nextjs pages\n * const { pathname } = useRouter();\n * // react router\n * const { pathname } = useHistory();\n *\n * const {\n * temporary,\n * appBarProps,\n * expandableNavProps,\n * mainProps,\n * navToggleProps,\n * temporaryNavProps,\n * windowSplitterProps,\n * } = useExpandableLayout({ pathname });\n *\n * return (\n * <>\n * <LayoutAppBar {...appBarProps}>\n * <Button {...navToggleProps} />\n * <AppBarTitle>Hello, world!</AppBarTitle>\n * </LayoutAppBar>\n * <LayoutNav {...expandableNavProps}>\n * <CustomNavigation />\n * </LayoutNav>\n * {temporary && (\n * <Sheet {...temporaryNavProps}>\n * <CustomNavigation />\n * </Sheet>\n * )}\n * <Main {...mainProps}>{children}</Main>\n * </>\n * );\n * }\n * ```\n *\n * If you have a large navigation panel, you can conditionally render the\n * `LayoutNav` with the `persistent` boolean returned by the hook which will\n * ensure that the DOM has rehydrated before unmounting to prevent SSR errors.\n *\n * @example Safely Conditionally Rendering\n * ```diff\n * const {\n * temporary,\n * + persistent,\n * appBarProps,\n * expandableNavProps,\n * mainProps,\n * navToggleProps,\n * temporaryNavProps,\n * windowSplitterProps,\n * } = useExpandableLayout({ pathname });\n *\n * return (\n * <>\n * <LayoutAppBar {...appBarProps}>\n * <Button {...navToggleProps} />\n * <AppBarTitle>Hello, world!</AppBarTitle>\n * </LayoutAppBar>\n * - <LayoutNav {...expandableNavProps}>\n * - <CustomNavigation />\n * - </LayoutNav>\n * + {persistent && (\n * + <LayoutNav {...expandableNavProps}>\n * + <CustomNavigation />\n * + </LayoutNav>\n * + )}\n * {temporary && (\n * <Sheet {...temporaryNavProps}>\n * <CustomNavigation />\n * </Sheet>\n * )}\n * <Main {...mainProps}>{children}</Main>\n * </>\n * );\n * ```\n *\n * @see {@link https://react-md.dev/getting-started/layout | Layout Demos}\n * @since 6.0.0\n * @see {@link useResizableLayout}\n */\nexport function useExpandableLayout(\n options: ExpandableLayoutOptions\n): ExpandableLayoutImplementation {\n const {\n fullHeightNav = false,\n temporaryUntil = \"tablet\",\n transitionProps,\n defaultExpanded = fullHeightNav === \"static\",\n ...temporaryOptions\n } = options;\n\n const ssr = useSsr();\n const {\n appBarProps,\n mainProps,\n navToggleProps,\n temporaryNavProps,\n hideTemporaryNav,\n showTemporaryNav,\n visible,\n } = useTemporaryLayout(temporaryOptions);\n\n const {\n toggled: expanded,\n enable: expandNavigation,\n disable: collapseNavigation,\n toggle: toggleNavigation,\n } = useToggle(defaultExpanded);\n const { elementProps } = useHorizontalLayoutTransition({\n ...transitionProps,\n transitionIn: expanded,\n });\n const { isPhone, isDesktop } = useAppSize();\n const isAppSizeMatch =\n temporaryUntil === \"tablet\" || temporaryUntil === \"desktop\";\n const matches = useMediaQuery(temporaryUntil, isAppSizeMatch);\n const temporary = isAppSizeMatch\n ? isPhone || (temporaryUntil === \"desktop\" && !isDesktop)\n : !matches;\n\n useDevEffect(() => {\n if (process.env.NODE_ENV === \"test\") {\n return;\n }\n\n let query: string;\n if (temporaryUntil === \"tablet\" || temporaryUntil === \"desktop\") {\n const minWidth =\n temporaryUntil === \"tablet\"\n ? MEDIA_QUERY_CONFIG.tabletMinWidth\n : MEDIA_QUERY_CONFIG.desktopMinWidth;\n query = `screen and (min-width: ${minWidth})`;\n } else {\n query = temporaryUntil;\n }\n\n const timeout = globalThis.setTimeout(() => {\n let found = false;\n for (let i = 0; i < document.styleSheets.length; i++) {\n const sheet = document.styleSheets[i];\n\n try {\n const rules = sheet.cssRules;\n for (const rule of rules) {\n if (\n rule.cssText.includes(\".rmd-layout\") &&\n rule.cssText.includes(`@media ${query}`)\n ) {\n found = true;\n return;\n }\n }\n } catch {\n //\n }\n }\n\n if (!found && !loggedOnce) {\n loggedOnce = true;\n // eslint-disable-next-line no-console\n console.error(\n `The react-md expandable layout has set \\`temporaryUntil: \"${temporaryUntil}\"\\` but the corresponding styles have not been found.` +\n \" This usually means the `$layout-navigation-breakpoint` or `temporaryUntil` value should be updated match.\\n\\n\" +\n \"See https://react-md.dev/getting-started/layout#updating-the-layout-to-be-temporary-until-a-specific-breakpoint-optional \" +\n \"for more information.\"\n );\n }\n }, 3000);\n\n return () => {\n globalThis.clearTimeout(timeout);\n };\n }, [temporaryUntil]);\n\n return {\n visible,\n temporary,\n persistent: ssr || !temporary,\n hideTemporaryNav,\n showTemporaryNav,\n expanded,\n expandNavigation,\n collapseNavigation,\n toggleNavigation,\n appBarProps: {\n ...appBarProps,\n ...(fullHeightNav ? elementProps : {}),\n },\n mainProps: {\n ...mainProps,\n ...elementProps,\n },\n temporaryNavProps,\n expandableNavProps: {\n expanded,\n appBarOffset: !fullHeightNav,\n },\n navToggleProps: {\n ...navToggleProps,\n onClick() {\n if (temporary) {\n showTemporaryNav();\n } else {\n toggleNavigation();\n }\n },\n className: cnb(fullHeightNav === \"static\" && \"rmd-layout-nav-toggle\"),\n },\n };\n}\n"],"names":["cnb","useSsr","useAppSize","MEDIA_QUERY_CONFIG","useMediaQuery","useToggle","useDevEffect","useHorizontalLayoutTransition","useTemporaryLayout","loggedOnce","useExpandableLayout","options","fullHeightNav","temporaryUntil","transitionProps","defaultExpanded","temporaryOptions","ssr","appBarProps","mainProps","navToggleProps","temporaryNavProps","hideTemporaryNav","showTemporaryNav","visible","toggled","expanded","enable","expandNavigation","disable","collapseNavigation","toggle","toggleNavigation","elementProps","transitionIn","isPhone","isDesktop","isAppSizeMatch","matches","temporary","process","env","NODE_ENV","query","minWidth","tabletMinWidth","desktopMinWidth","timeout","globalThis","setTimeout","found","i","document","styleSheets","length","sheet","rules","cssRules","rule","cssText","includes","console","error","clearTimeout","persistent","expandableNavProps","appBarOffset","onClick","className"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/layout/useExpandableLayout.ts"],"sourcesContent":["\"use client\";\n\nimport { cnb } from \"cnbuilder\";\n\nimport { useSsr } from \"../SsrProvider.js\";\nimport { useAppSize } from \"../media-queries/AppSizeProvider.js\";\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { type AppSize } from \"../media-queries/appSize.js\";\nimport { MEDIA_QUERY_CONFIG } from \"../media-queries/config.js\";\nimport { useMediaQuery } from \"../media-queries/useMediaQuery.js\";\nimport { type CSSTransitionElementProps } from \"../transition/types.js\";\nimport {\n type CssPosition,\n type LiteralStringUnion,\n type UseStateInitializer,\n} from \"../types.js\";\nimport { useToggle } from \"../useToggle.js\";\nimport { useDevEffect } from \"../utils/useDevEffect.js\";\nimport { type LayoutNavProps } from \"./LayoutNav.js\";\nimport {\n type HorizontalLayoutTransitionOptions,\n useHorizontalLayoutTransition,\n} from \"./useHorizontalLayoutTransition.js\";\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { type useResizableLayout } from \"./useResizableLayout.js\";\nimport {\n type ProvidedLayoutNavToggleProps,\n type ProvidedTemporaryLayoutAppBarProps,\n type ProvidedTemporaryLayoutMainProps,\n type TemporaryLayoutImplementation,\n type TemporaryLayoutOptions,\n useTemporaryLayout,\n} from \"./useTemporaryLayout.js\";\n\nlet loggedOnce = false;\n\n/**\n * @since 6.0.0\n */\nexport interface ExpandableLayoutOptions extends TemporaryLayoutOptions {\n /** @defaultValue `\"fixed\"` */\n appBarPosition?: CssPosition;\n\n /** @defaultValue `false` */\n defaultExpanded?: UseStateInitializer<boolean>;\n\n /**\n * Set this to `true` if the expandable navigation should be the full height\n * of the screen. This will also update the app bar so that it is not covered\n * by the navigation. The default behavior is to place the navigation below\n * the fixed header.\n *\n * Set this to `\"static\"` to make the navigation span the full height of the\n * screen and hide the button until the screen shrinks to the temporary\n * layout type.\n *\n * @defaultValue `false`\n */\n fullHeightNav?: boolean | \"static\";\n\n /** @see {@link HorizontalLayoutTransitionOptions} */\n transitionProps?: Omit<HorizontalLayoutTransitionOptions, \"transitionIn\">;\n\n /**\n * The default behavior is to use the temporary layout until the\n * {@link AppSize.isTablet} is `true`. Set this to `\"desktop\"` to use the\n * temporary layout until {@link AppSize.isDesktop} is `true`. Otherwise,\n * provide a media query string to use the temporary layout until the media\n * query matches\n *\n * @example Custom Media Query\n * ```tsx\n * useExpandableLayout({\n * ...options,\n * // display the expandable layout once the min-width is at least 1201px\n * temporaryUntil: \"screen and (min-width: 1201px)\",\n * });\n * ```\n *\n * @defaultValue `\"tablet\"`\n */\n temporaryUntil?: LiteralStringUnion<\"tablet\" | \"desktop\">;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ProvidedLayoutMainProps\n extends\n ProvidedTemporaryLayoutMainProps,\n CSSTransitionElementProps<HTMLElement> {}\n\n/**\n * @since 6.0.0\n */\nexport type ProvidedLayoutNavProps = Pick<\n LayoutNavProps,\n \"expanded\" | \"appBarOffset\"\n>;\n\n/**\n * @since 6.0.0\n */\nexport type ProvidedLayoutAppBarProps = ProvidedTemporaryLayoutAppBarProps &\n Partial<CSSTransitionElementProps<HTMLElement>>;\n\n/**\n * @since 6.0.0\n */\nexport interface ProvidedExpandableLayoutNavToggleProps extends ProvidedLayoutNavToggleProps {\n className: string;\n}\n\n/**\n * @since 6.0.0\n */\nexport interface ExpandableLayoutImplementation extends TemporaryLayoutImplementation {\n temporary: boolean;\n persistent: boolean;\n expanded: boolean;\n expandNavigation: () => void;\n collapseNavigation: () => void;\n toggleNavigation: () => void;\n appBarProps: ProvidedLayoutAppBarProps;\n mainProps: ProvidedLayoutMainProps;\n navToggleProps: ProvidedExpandableLayoutNavToggleProps;\n expandableNavProps: ProvidedLayoutNavProps;\n}\n\n/**\n * @example Main Usage\n * ```tsx\n * import { AppBarTitle } from \"@react-md/core/app-bar/AppBarTitle\";\n * import { Button } from \"@react-md/core/button/Button\";\n * import { LayoutAppBar } from \"@react-md/core/layout/LayoutAppBar\";\n * import { LayoutNav } from \"@react-md/core/layout/LayoutNav\";\n * import { Main } from \"@react-md/core/layout/Main\";\n * import { useExpandableLayout } from \"@react-md/core/layout/useExpandableLayout\";\n * import { Sheet } from \"@react-md/core/sheet/Sheet\";\n * import { type ReactElement, type ReactNode } from \"react\";\n *\n * import { CustomNavigation } from \"./CustomNavigation\";\n *\n * export interface LayoutProps {\n * children: ReactNode;\n * }\n *\n * export function Layout(props: LayoutProps): ReactElement {\n * const { children } = props;\n *\n * // choose whichever one for your app\n * // nextjs app dir\n * const pathname = usePathname();\n * // nextjs pages\n * const { pathname } = useRouter();\n * // react router\n * const { pathname } = useHistory();\n *\n * const {\n * temporary,\n * appBarProps,\n * expandableNavProps,\n * mainProps,\n * navToggleProps,\n * temporaryNavProps,\n * windowSplitterProps,\n * } = useExpandableLayout({ pathname });\n *\n * return (\n * <>\n * <LayoutAppBar {...appBarProps}>\n * <Button {...navToggleProps} />\n * <AppBarTitle>Hello, world!</AppBarTitle>\n * </LayoutAppBar>\n * <LayoutNav {...expandableNavProps}>\n * <CustomNavigation />\n * </LayoutNav>\n * {temporary && (\n * <Sheet {...temporaryNavProps}>\n * <CustomNavigation />\n * </Sheet>\n * )}\n * <Main {...mainProps}>{children}</Main>\n * </>\n * );\n * }\n * ```\n *\n * If you have a large navigation panel, you can conditionally render the\n * `LayoutNav` with the `persistent` boolean returned by the hook which will\n * ensure that the DOM has rehydrated before unmounting to prevent SSR errors.\n *\n * @example Safely Conditionally Rendering\n * ```diff\n * const {\n * temporary,\n * + persistent,\n * appBarProps,\n * expandableNavProps,\n * mainProps,\n * navToggleProps,\n * temporaryNavProps,\n * windowSplitterProps,\n * } = useExpandableLayout({ pathname });\n *\n * return (\n * <>\n * <LayoutAppBar {...appBarProps}>\n * <Button {...navToggleProps} />\n * <AppBarTitle>Hello, world!</AppBarTitle>\n * </LayoutAppBar>\n * - <LayoutNav {...expandableNavProps}>\n * - <CustomNavigation />\n * - </LayoutNav>\n * + {persistent && (\n * + <LayoutNav {...expandableNavProps}>\n * + <CustomNavigation />\n * + </LayoutNav>\n * + )}\n * {temporary && (\n * <Sheet {...temporaryNavProps}>\n * <CustomNavigation />\n * </Sheet>\n * )}\n * <Main {...mainProps}>{children}</Main>\n * </>\n * );\n * ```\n *\n * @see {@link https://react-md.dev/getting-started/layout | Layout Demos}\n * @since 6.0.0\n * @see {@link useResizableLayout}\n */\nexport function useExpandableLayout(\n options: ExpandableLayoutOptions\n): ExpandableLayoutImplementation {\n const {\n fullHeightNav = false,\n temporaryUntil = \"tablet\",\n transitionProps,\n defaultExpanded = fullHeightNav === \"static\",\n ...temporaryOptions\n } = options;\n\n const ssr = useSsr();\n const {\n appBarProps,\n mainProps,\n navToggleProps,\n temporaryNavProps,\n hideTemporaryNav,\n showTemporaryNav,\n visible,\n } = useTemporaryLayout(temporaryOptions);\n\n const {\n toggled: expanded,\n enable: expandNavigation,\n disable: collapseNavigation,\n toggle: toggleNavigation,\n } = useToggle(defaultExpanded);\n const { elementProps } = useHorizontalLayoutTransition({\n ...transitionProps,\n transitionIn: expanded,\n });\n const { isPhone, isDesktop } = useAppSize();\n const isAppSizeMatch =\n temporaryUntil === \"tablet\" || temporaryUntil === \"desktop\";\n const matches = useMediaQuery(temporaryUntil, isAppSizeMatch);\n const temporary = isAppSizeMatch\n ? isPhone || (temporaryUntil === \"desktop\" && !isDesktop)\n : !matches;\n\n useDevEffect(() => {\n if (process.env.NODE_ENV === \"test\") {\n return;\n }\n\n let query: string;\n if (temporaryUntil === \"tablet\" || temporaryUntil === \"desktop\") {\n const minWidth =\n temporaryUntil === \"tablet\"\n ? MEDIA_QUERY_CONFIG.tabletMinWidth\n : MEDIA_QUERY_CONFIG.desktopMinWidth;\n query = `screen and (min-width: ${minWidth})`;\n } else {\n query = temporaryUntil;\n }\n\n const timeout = globalThis.setTimeout(() => {\n let found = false;\n for (let i = 0; i < document.styleSheets.length; i++) {\n const sheet = document.styleSheets[i];\n\n try {\n const rules = sheet.cssRules;\n for (const rule of rules) {\n if (\n rule.cssText.includes(\".rmd-layout\") &&\n rule.cssText.includes(`@media ${query}`)\n ) {\n found = true;\n return;\n }\n }\n } catch {\n //\n }\n }\n\n if (!found && !loggedOnce) {\n loggedOnce = true;\n // eslint-disable-next-line no-console\n console.error(\n `The react-md expandable layout has set \\`temporaryUntil: \"${temporaryUntil}\"\\` but the corresponding styles have not been found.` +\n \" This usually means the `$layout-navigation-breakpoint` or `temporaryUntil` value should be updated match.\\n\\n\" +\n \"See https://react-md.dev/getting-started/layout#updating-the-layout-to-be-temporary-until-a-specific-breakpoint-optional \" +\n \"for more information.\"\n );\n }\n }, 3000);\n\n return () => {\n globalThis.clearTimeout(timeout);\n };\n }, [temporaryUntil]);\n\n return {\n visible,\n temporary,\n persistent: ssr || !temporary,\n hideTemporaryNav,\n showTemporaryNav,\n expanded,\n expandNavigation,\n collapseNavigation,\n toggleNavigation,\n appBarProps: {\n ...appBarProps,\n ...(fullHeightNav ? elementProps : {}),\n },\n mainProps: {\n ...mainProps,\n ...elementProps,\n },\n temporaryNavProps,\n expandableNavProps: {\n expanded,\n appBarOffset: !fullHeightNav,\n },\n navToggleProps: {\n ...navToggleProps,\n onClick() {\n if (temporary) {\n showTemporaryNav();\n } else {\n toggleNavigation();\n }\n },\n className: cnb(fullHeightNav === \"static\" && \"rmd-layout-nav-toggle\"),\n },\n };\n}\n"],"names":["cnb","useSsr","useAppSize","MEDIA_QUERY_CONFIG","useMediaQuery","useToggle","useDevEffect","useHorizontalLayoutTransition","useTemporaryLayout","loggedOnce","useExpandableLayout","options","fullHeightNav","temporaryUntil","transitionProps","defaultExpanded","temporaryOptions","ssr","appBarProps","mainProps","navToggleProps","temporaryNavProps","hideTemporaryNav","showTemporaryNav","visible","toggled","expanded","enable","expandNavigation","disable","collapseNavigation","toggle","toggleNavigation","elementProps","transitionIn","isPhone","isDesktop","isAppSizeMatch","matches","temporary","process","env","NODE_ENV","query","minWidth","tabletMinWidth","desktopMinWidth","timeout","globalThis","setTimeout","found","i","document","styleSheets","length","sheet","rules","cssRules","rule","cssText","includes","console","error","clearTimeout","persistent","expandableNavProps","appBarOffset","onClick","className"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/menu/MenuItemButton.tsx"],"sourcesContent":["\"use client\";\n\nimport { type ReactElement, useEffect } from \"react\";\n\nimport { useHoverMode } from \"../hoverMode/useHoverMode.js\";\nimport { IconRotator } from \"../icon/IconRotator.js\";\nimport { getIcon } from \"../icon/config.js\";\nimport { useUserInteractionMode } from \"../interaction/UserInteractionModeProvider.js\";\nimport { useAppSize } from \"../media-queries/AppSizeProvider.js\";\nimport { useEnsuredId } from \"../useEnsuredId.js\";\nimport { type BaseMenuButtonProps } from \"./MenuButton.js\";\nimport { useMenuConfiguration } from \"./MenuConfigurationProvider.js\";\nimport { MenuItem, type MenuItemProps } from \"./MenuItem.js\";\nimport { useMenuVisibility } from \"./MenuVisibilityProvider.js\";\nimport { useMenuBarContext } from \"./useMenuBarProvider.js\";\n\nconst noop = (): void => {\n // do nothing\n};\n\n/**\n * @internal\n * @since 5.0.0\n */\nexport interface MenuItemButtonProps\n extends BaseMenuButtonProps, MenuItemProps {}\n\n/**\n * **Client Component**\n *\n * This is just an internal component that handles rendering a submenu as a\n * menuitem for a `DropdownMenu` with a conditional dropdown icon.\n *\n * @internal\n * @since 5.0.0\n */\nexport function MenuItemButton(props: MenuItemButtonProps): ReactElement {\n const {\n ref,\n id: propId,\n children,\n height: propHeight,\n onClick = noop,\n onKeyDown = noop,\n onMouseEnter = noop,\n onMouseLeave = noop,\n rightAddon: propRightAddon,\n iconRotatorProps,\n disableDropdownIcon = propRightAddon !== undefined,\n ...remaining\n } = props;\n const { disabled } = props;\n\n const id = useEnsuredId(propId, \"menuitem\");\n const mode = useUserInteractionMode();\n const { renderAsSheet } = useMenuConfiguration();\n const { isPhone } = useAppSize();\n const isSheet =\n renderAsSheet === true || (renderAsSheet === \"phone\" && isPhone);\n const {\n root,\n menubar,\n activeId,\n enableHoverMode,\n disableHoverMode,\n startDisableTimer,\n clearDisableTimer,\n leaveTimeoutRef,\n hoverTimeoutRef,\n } = useMenuBarContext();\n const { visible, setVisible, defaultFocusIndex } = useMenuVisibility();\n const { startShowFlow, clearVisibilityTimeout } = useHoverMode({\n setVisible,\n enableHoverMode,\n disableHoverMode,\n startDisableTimer,\n leaveTimeoutRef,\n hoverTimeoutRef,\n clearDisableTimer,\n });\n const { horizontal } = useMenuConfiguration();\n\n useEffect(() => {\n setVisible(id === activeId);\n }, [activeId, defaultFocusIndex, id, menubar, setVisible]);\n\n let height = propHeight;\n let rightAddon = propRightAddon;\n const dropdownIcon = getIcon(root ? \"dropdown\" : \"forward\");\n if (!disableDropdownIcon) {\n if (!height && !props.leftAddon) {\n height = \"normal\";\n }\n\n rightAddon = (\n <IconRotator {...iconRotatorProps} rotated={visible}>\n {dropdownIcon}\n </IconRotator>\n );\n }\n\n const updateVisibility = (nextVisible: boolean, focusIndex = 0): void => {\n defaultFocusIndex.current = focusIndex;\n setVisible(nextVisible);\n if (!menubar) {\n return;\n }\n\n if (nextVisible) {\n enableHoverMode(id);\n } else {\n disableHoverMode();\n }\n };\n\n return (\n <MenuItem\n {...remaining}\n aria-haspopup={isSheet ? \"dialog\" : \"menu\"}\n aria-expanded={visible || undefined}\n id={id}\n ref={ref}\n rightAddon={rightAddon}\n onClick={(event) => {\n onClick(event);\n\n event.stopPropagation();\n updateVisibility(!visible);\n }}\n onKeyDown={(event) => {\n onKeyDown(event);\n\n switch (event.key) {\n case \"ArrowDown\":\n if (horizontal || root) {\n event.preventDefault();\n event.stopPropagation();\n updateVisibility(true);\n }\n break;\n case \"ArrowRight\":\n if (!horizontal && !root) {\n event.preventDefault();\n event.stopPropagation();\n updateVisibility(true);\n }\n break;\n }\n }}\n onMouseEnter={(event) => {\n onMouseEnter(event);\n if (mode === \"touch\" || disabled || !menubar) {\n return;\n }\n\n defaultFocusIndex.current = 0;\n startShowFlow(id);\n }}\n onMouseLeave={(event) => {\n onMouseLeave(event);\n if (mode === \"touch\" || disabled || !menubar) {\n return;\n }\n\n clearVisibilityTimeout();\n }}\n >\n {children}\n </MenuItem>\n );\n}\n"],"names":["useEffect","useHoverMode","IconRotator","getIcon","useUserInteractionMode","useAppSize","useEnsuredId","useMenuConfiguration","MenuItem","useMenuVisibility","useMenuBarContext","noop","MenuItemButton","props","ref","id","propId","children","height","propHeight","onClick","onKeyDown","onMouseEnter","onMouseLeave","rightAddon","propRightAddon","iconRotatorProps","disableDropdownIcon","undefined","remaining","disabled","mode","renderAsSheet","isPhone","isSheet","root","menubar","activeId","enableHoverMode","disableHoverMode","startDisableTimer","clearDisableTimer","leaveTimeoutRef","hoverTimeoutRef","visible","setVisible","defaultFocusIndex","startShowFlow","clearVisibilityTimeout","horizontal","dropdownIcon","leftAddon","rotated","updateVisibility","nextVisible","focusIndex","current","aria-haspopup","aria-expanded","event","stopPropagation","key","preventDefault"],"mappings":"AAAA;;AAEA,SAA4BA,SAAS,QAAQ,QAAQ;AAErD,SAASC,YAAY,QAAQ,+BAA+B;AAC5D,SAASC,WAAW,QAAQ,yBAAyB;AACrD,SAASC,OAAO,QAAQ,oBAAoB;AAC5C,SAASC,sBAAsB,QAAQ,gDAAgD;AACvF,SAASC,UAAU,QAAQ,sCAAsC;AACjE,SAASC,YAAY,QAAQ,qBAAqB;AAElD,SAASC,oBAAoB,QAAQ,iCAAiC;AACtE,SAASC,QAAQ,QAA4B,gBAAgB;AAC7D,SAASC,iBAAiB,QAAQ,8BAA8B;AAChE,SAASC,iBAAiB,QAAQ,0BAA0B;AAE5D,MAAMC,OAAO;AACX,aAAa;AACf;AASA;;;;;;;;CAQC,GACD,OAAO,SAASC,eAAeC,KAA0B;IACvD,MAAM,EACJC,GAAG,EACHC,IAAIC,MAAM,EACVC,QAAQ,EACRC,QAAQC,UAAU,EAClBC,UAAUT,IAAI,EACdU,YAAYV,IAAI,EAChBW,eAAeX,IAAI,EACnBY,eAAeZ,IAAI,EACnBa,YAAYC,cAAc,EAC1BC,gBAAgB,EAChBC,sBAAsBF,mBAAmBG,SAAS,EAClD,GAAGC,WACJ,GAAGhB;IACJ,MAAM,EAAEiB,QAAQ,EAAE,GAAGjB;IAErB,MAAME,KAAKT,aAAaU,QAAQ;IAChC,MAAMe,OAAO3B;IACb,MAAM,EAAE4B,aAAa,EAAE,GAAGzB;IAC1B,MAAM,EAAE0B,OAAO,EAAE,GAAG5B;IACpB,MAAM6B,UACJF,kBAAkB,QAASA,kBAAkB,WAAWC;IAC1D,MAAM,EACJE,IAAI,EACJC,OAAO,EACPC,QAAQ,EACRC,eAAe,EACfC,gBAAgB,EAChBC,iBAAiB,EACjBC,iBAAiB,EACjBC,eAAe,EACfC,eAAe,EAChB,GAAGjC;IACJ,MAAM,EAAEkC,OAAO,EAAEC,UAAU,EAAEC,iBAAiB,EAAE,GAAGrC;IACnD,MAAM,EAAEsC,aAAa,EAAEC,sBAAsB,EAAE,GAAG/C,aAAa;QAC7D4C;QACAP;QACAC;QACAC;QACAE;QACAC;QACAF;IACF;IACA,MAAM,EAAEQ,UAAU,EAAE,GAAG1C;IAEvBP,UAAU;QACR6C,WAAW9B,OAAOsB;IACpB,GAAG;QAACA;QAAUS;QAAmB/B;QAAIqB;QAASS;KAAW;IAEzD,IAAI3B,SAASC;IACb,IAAIK,aAAaC;IACjB,MAAMyB,eAAe/C,QAAQgC,OAAO,aAAa;IACjD,IAAI,CAACR,qBAAqB;QACxB,IAAI,CAACT,UAAU,CAACL,MAAMsC,SAAS,EAAE;YAC/BjC,SAAS;QACX;QAEAM,2BACE,KAACtB;YAAa,GAAGwB,gBAAgB;YAAE0B,SAASR;sBACzCM;;IAGP;IAEA,MAAMG,mBAAmB,CAACC,aAAsBC,aAAa,CAAC;QAC5DT,kBAAkBU,OAAO,GAAGD;QAC5BV,WAAWS;QACX,IAAI,CAAClB,SAAS;YACZ;QACF;QAEA,IAAIkB,aAAa;YACfhB,gBAAgBvB;QAClB,OAAO;YACLwB;QACF;IACF;IAEA,qBACE,KAAC/B;QACE,GAAGqB,SAAS;QACb4B,iBAAevB,UAAU,WAAW;QACpCwB,iBAAed,WAAWhB;QAC1Bb,IAAIA;QACJD,KAAKA;
|
|
1
|
+
{"version":3,"sources":["../../src/menu/MenuItemButton.tsx"],"sourcesContent":["\"use client\";\n\nimport { type ReactElement, useEffect } from \"react\";\n\nimport { useHoverMode } from \"../hoverMode/useHoverMode.js\";\nimport { IconRotator } from \"../icon/IconRotator.js\";\nimport { getIcon } from \"../icon/config.js\";\nimport { useUserInteractionMode } from \"../interaction/UserInteractionModeProvider.js\";\nimport { useAppSize } from \"../media-queries/AppSizeProvider.js\";\nimport { useEnsuredId } from \"../useEnsuredId.js\";\nimport { type BaseMenuButtonProps } from \"./MenuButton.js\";\nimport { useMenuConfiguration } from \"./MenuConfigurationProvider.js\";\nimport { MenuItem, type MenuItemProps } from \"./MenuItem.js\";\nimport { useMenuVisibility } from \"./MenuVisibilityProvider.js\";\nimport { useMenuBarContext } from \"./useMenuBarProvider.js\";\n\nconst noop = (): void => {\n // do nothing\n};\n\n/**\n * @internal\n * @since 5.0.0\n */\nexport interface MenuItemButtonProps\n extends BaseMenuButtonProps, MenuItemProps {}\n\n/**\n * **Client Component**\n *\n * This is just an internal component that handles rendering a submenu as a\n * menuitem for a `DropdownMenu` with a conditional dropdown icon.\n *\n * @internal\n * @since 5.0.0\n */\nexport function MenuItemButton(props: MenuItemButtonProps): ReactElement {\n const {\n ref,\n id: propId,\n children,\n height: propHeight,\n onClick = noop,\n onKeyDown = noop,\n onMouseEnter = noop,\n onMouseLeave = noop,\n rightAddon: propRightAddon,\n iconRotatorProps,\n disableDropdownIcon = propRightAddon !== undefined,\n ...remaining\n } = props;\n const { disabled } = props;\n\n const id = useEnsuredId(propId, \"menuitem\");\n const mode = useUserInteractionMode();\n const { renderAsSheet } = useMenuConfiguration();\n const { isPhone } = useAppSize();\n const isSheet =\n renderAsSheet === true || (renderAsSheet === \"phone\" && isPhone);\n const {\n root,\n menubar,\n activeId,\n enableHoverMode,\n disableHoverMode,\n startDisableTimer,\n clearDisableTimer,\n leaveTimeoutRef,\n hoverTimeoutRef,\n } = useMenuBarContext();\n const { visible, setVisible, defaultFocusIndex } = useMenuVisibility();\n const { startShowFlow, clearVisibilityTimeout } = useHoverMode({\n setVisible,\n enableHoverMode,\n disableHoverMode,\n startDisableTimer,\n leaveTimeoutRef,\n hoverTimeoutRef,\n clearDisableTimer,\n });\n const { horizontal } = useMenuConfiguration();\n\n useEffect(() => {\n setVisible(id === activeId);\n }, [activeId, defaultFocusIndex, id, menubar, setVisible]);\n\n let height = propHeight;\n let rightAddon = propRightAddon;\n const dropdownIcon = getIcon(root ? \"dropdown\" : \"forward\");\n if (!disableDropdownIcon) {\n if (!height && !props.leftAddon) {\n height = \"normal\";\n }\n\n rightAddon = (\n <IconRotator {...iconRotatorProps} rotated={visible}>\n {dropdownIcon}\n </IconRotator>\n );\n }\n\n const updateVisibility = (nextVisible: boolean, focusIndex = 0): void => {\n defaultFocusIndex.current = focusIndex;\n setVisible(nextVisible);\n if (!menubar) {\n return;\n }\n\n if (nextVisible) {\n enableHoverMode(id);\n } else {\n disableHoverMode();\n }\n };\n\n return (\n <MenuItem\n {...remaining}\n aria-haspopup={isSheet ? \"dialog\" : \"menu\"}\n aria-expanded={visible || undefined}\n id={id}\n ref={ref}\n height={height}\n rightAddon={rightAddon}\n onClick={(event) => {\n onClick(event);\n\n event.stopPropagation();\n updateVisibility(!visible);\n }}\n onKeyDown={(event) => {\n onKeyDown(event);\n\n switch (event.key) {\n case \"ArrowDown\":\n if (horizontal || root) {\n event.preventDefault();\n event.stopPropagation();\n updateVisibility(true);\n }\n break;\n case \"ArrowRight\":\n if (!horizontal && !root) {\n event.preventDefault();\n event.stopPropagation();\n updateVisibility(true);\n }\n break;\n }\n }}\n onMouseEnter={(event) => {\n onMouseEnter(event);\n if (mode === \"touch\" || disabled || !menubar) {\n return;\n }\n\n defaultFocusIndex.current = 0;\n startShowFlow(id);\n }}\n onMouseLeave={(event) => {\n onMouseLeave(event);\n if (mode === \"touch\" || disabled || !menubar) {\n return;\n }\n\n clearVisibilityTimeout();\n }}\n >\n {children}\n </MenuItem>\n );\n}\n"],"names":["useEffect","useHoverMode","IconRotator","getIcon","useUserInteractionMode","useAppSize","useEnsuredId","useMenuConfiguration","MenuItem","useMenuVisibility","useMenuBarContext","noop","MenuItemButton","props","ref","id","propId","children","height","propHeight","onClick","onKeyDown","onMouseEnter","onMouseLeave","rightAddon","propRightAddon","iconRotatorProps","disableDropdownIcon","undefined","remaining","disabled","mode","renderAsSheet","isPhone","isSheet","root","menubar","activeId","enableHoverMode","disableHoverMode","startDisableTimer","clearDisableTimer","leaveTimeoutRef","hoverTimeoutRef","visible","setVisible","defaultFocusIndex","startShowFlow","clearVisibilityTimeout","horizontal","dropdownIcon","leftAddon","rotated","updateVisibility","nextVisible","focusIndex","current","aria-haspopup","aria-expanded","event","stopPropagation","key","preventDefault"],"mappings":"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"}
|