@mantine/core 9.4.1 → 9.4.2
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/cjs/components/Accordion/Accordion.cjs +5 -3
- package/cjs/components/Accordion/Accordion.cjs.map +1 -1
- package/cjs/components/Accordion/Accordion.context.cjs.map +1 -1
- package/cjs/components/Accordion/AccordionPanel/AccordionPanel.cjs +2 -1
- package/cjs/components/Accordion/AccordionPanel/AccordionPanel.cjs.map +1 -1
- package/cjs/components/AppShell/AppShellMediaStyles/assign-aside-variables/assign-aside-variables.cjs +2 -2
- package/cjs/components/AppShell/AppShellMediaStyles/assign-aside-variables/assign-aside-variables.cjs.map +1 -1
- package/cjs/components/AppShell/AppShellMediaStyles/assign-navbar-variables/assign-navbar-variables.cjs +2 -2
- package/cjs/components/AppShell/AppShellMediaStyles/assign-navbar-variables/assign-navbar-variables.cjs.map +1 -1
- package/cjs/components/Collapse/Collapse.cjs +23 -10
- package/cjs/components/Collapse/Collapse.cjs.map +1 -1
- package/cjs/components/Menubar/MenubarTarget/MenubarTarget.cjs +1 -1
- package/cjs/components/Menubar/MenubarTarget/MenubarTarget.cjs.map +1 -1
- package/cjs/components/ModalBase/ModalBase.cjs +3 -2
- package/cjs/components/ModalBase/ModalBase.cjs.map +1 -1
- package/cjs/components/Transition/Transition.cjs.map +1 -1
- package/cjs/components/Tree/FlatTreeNode.cjs +16 -3
- package/cjs/components/Tree/FlatTreeNode.cjs.map +1 -1
- package/cjs/components/Tree/Tree.module.cjs.map +1 -1
- package/cjs/components/Tree/TreeNode.cjs +17 -5
- package/cjs/components/Tree/TreeNode.cjs.map +1 -1
- package/cjs/components/Tree/flatten-tree-data/flatten-tree-data.cjs +1 -1
- package/cjs/components/Tree/flatten-tree-data/flatten-tree-data.cjs.map +1 -1
- package/cjs/components/TreeSelect/TreeSelectOption.cjs +5 -3
- package/cjs/components/TreeSelect/TreeSelectOption.cjs.map +1 -1
- package/cjs/components/TreeSelect/flatten-tree-select-data.cjs +1 -1
- package/cjs/components/TreeSelect/flatten-tree-select-data.cjs.map +1 -1
- package/esm/components/Accordion/Accordion.context.mjs.map +1 -1
- package/esm/components/Accordion/Accordion.mjs +5 -3
- package/esm/components/Accordion/Accordion.mjs.map +1 -1
- package/esm/components/Accordion/AccordionPanel/AccordionPanel.mjs +2 -1
- package/esm/components/Accordion/AccordionPanel/AccordionPanel.mjs.map +1 -1
- package/esm/components/AppShell/AppShellMediaStyles/assign-aside-variables/assign-aside-variables.mjs +2 -2
- package/esm/components/AppShell/AppShellMediaStyles/assign-aside-variables/assign-aside-variables.mjs.map +1 -1
- package/esm/components/AppShell/AppShellMediaStyles/assign-navbar-variables/assign-navbar-variables.mjs +2 -2
- package/esm/components/AppShell/AppShellMediaStyles/assign-navbar-variables/assign-navbar-variables.mjs.map +1 -1
- package/esm/components/Collapse/Collapse.mjs +23 -10
- package/esm/components/Collapse/Collapse.mjs.map +1 -1
- package/esm/components/Menubar/MenubarTarget/MenubarTarget.mjs +1 -1
- package/esm/components/Menubar/MenubarTarget/MenubarTarget.mjs.map +1 -1
- package/esm/components/ModalBase/ModalBase.mjs +3 -2
- package/esm/components/ModalBase/ModalBase.mjs.map +1 -1
- package/esm/components/Transition/Transition.mjs.map +1 -1
- package/esm/components/Tree/FlatTreeNode.mjs +16 -3
- package/esm/components/Tree/FlatTreeNode.mjs.map +1 -1
- package/esm/components/Tree/Tree.module.mjs.map +1 -1
- package/esm/components/Tree/TreeNode.mjs +17 -5
- package/esm/components/Tree/TreeNode.mjs.map +1 -1
- package/esm/components/Tree/flatten-tree-data/flatten-tree-data.mjs +1 -1
- package/esm/components/Tree/flatten-tree-data/flatten-tree-data.mjs.map +1 -1
- package/esm/components/TreeSelect/TreeSelectOption.mjs +5 -3
- package/esm/components/TreeSelect/TreeSelectOption.mjs.map +1 -1
- package/esm/components/TreeSelect/flatten-tree-select-data.mjs +1 -1
- package/esm/components/TreeSelect/flatten-tree-select-data.mjs.map +1 -1
- package/lib/components/Accordion/Accordion.context.d.ts +1 -0
- package/lib/components/Accordion/Accordion.d.ts +2 -0
- package/lib/components/Accordion/AccordionPanel/AccordionPanel.d.ts +2 -0
- package/lib/components/Collapse/Collapse.d.ts +6 -0
- package/lib/components/ModalBase/ModalBase.d.ts +7 -1
- package/lib/components/Transition/Transition.d.ts +2 -2
- package/lib/components/TreeSelect/TreeSelectOption.d.ts +4 -0
- package/package.json +2 -2
- package/styles/Tree.css +1 -1
- package/styles/Tree.layer.css +1 -1
- package/styles.css +1 -1
- package/styles.layer.css +1 -1
|
@@ -64,7 +64,7 @@ function MenubarTarget(props) {
|
|
|
64
64
|
ctx.openMenu(menuCtx.index, "hover");
|
|
65
65
|
ctx.setActiveIndex(menuCtx.index);
|
|
66
66
|
} else if (ctx.openIndex !== null && ctx.openIndex !== menuCtx.index) {
|
|
67
|
-
ctx.openMenu(menuCtx.index, "
|
|
67
|
+
ctx.openMenu(menuCtx.index, "click");
|
|
68
68
|
ctx.setActiveIndex(menuCtx.index);
|
|
69
69
|
}
|
|
70
70
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenubarTarget.mjs","names":[],"sources":["../../../../src/components/Menubar/MenubarTarget/MenubarTarget.tsx"],"sourcesContent":["import {\n createEventHandler,\n ElementProps,\n MantineStyleProp,\n useDirection,\n useProps,\n} from '../../../core';\nimport { Popover } from '../../Popover';\nimport { UnstyledButton } from '../../UnstyledButton';\nimport { useMenubarContext, useMenubarMenuContext } from '../Menubar.context';\n\nexport interface MenubarTargetProps extends ElementProps<'button'> {\n 'data-disabled'?: boolean;\n\n /** Target label */\n children: React.ReactNode;\n\n /** Inline styles applied to the target button */\n style?: MantineStyleProp;\n\n /** Key of the prop used to get element ref, useful for forwarding refs to custom components @default 'ref' */\n refProp?: string;\n}\n\nconst defaultProps = {\n refProp: 'ref',\n} satisfies Partial<MenubarTargetProps>;\n\nfunction isPrintableKey(event: React.KeyboardEvent) {\n return (\n event.key.length === 1 && event.key !== ' ' && !event.ctrlKey && !event.metaKey && !event.altKey\n );\n}\n\nfunction getTargetLabel(node: HTMLElement) {\n return (node.textContent ?? '').trim().toLowerCase();\n}\n\nexport function MenubarTarget(props: MenubarTargetProps) {\n const {\n children,\n refProp,\n className,\n style,\n disabled,\n 'data-disabled': dataDisabled,\n onClick,\n onMouseEnter,\n onMouseLeave,\n onFocus,\n onKeyDown,\n ...others\n } = useProps('MenubarTarget', defaultProps, props);\n\n const ctx = useMenubarContext();\n const menuCtx = useMenubarMenuContext();\n const { dir } = useDirection();\n\n const isDisabled = disabled || dataDisabled;\n const isActive = ctx.activeIndex === menuCtx.index;\n\n // Before the menu indexes resolve from the DOM (first render / SSR HTML), every target\n // would otherwise compute `tabIndex={-1}`, leaving the menubar with no tab stop until\n // effects run. Keep unresolved targets focusable so keyboard users can enter the menubar.\n const isUnresolvedTabStop = menuCtx.index === -1 && !isDisabled;\n\n const moveToAdjacent = (direction: 1 | -1) => {\n const nextIndex = ctx.getAdjacentIndex(menuCtx.index, direction);\n ctx.setActiveIndex(nextIndex);\n ctx.focusTarget(nextIndex);\n if (ctx.openIndex !== null) {\n ctx.openMenu(nextIndex, 'click');\n }\n };\n\n const openAndFocusItem = (itemPosition: 'first' | 'last') => {\n ctx.openMenu(menuCtx.index, 'click');\n ctx.setActiveIndex(menuCtx.index);\n ctx.focusMenuItem(menuCtx.index, itemPosition);\n };\n\n const typeAhead = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n const targets = ctx.getTargets();\n if (targets.length === 0) {\n return;\n }\n\n const char = event.key.toLowerCase();\n for (let offset = 1; offset <= targets.length; offset += 1) {\n const index = (menuCtx.index + offset) % targets.length;\n const node = targets[index];\n if (\n node &&\n !node.disabled &&\n !node.hasAttribute('data-disabled') &&\n getTargetLabel(node).startsWith(char)\n ) {\n event.preventDefault();\n ctx.setActiveIndex(index);\n node.focus();\n if (ctx.openIndex !== null) {\n ctx.openMenu(index, 'click');\n }\n break;\n }\n }\n };\n\n const handleClick = createEventHandler<any>(onClick, () => {\n if (isDisabled) {\n return;\n }\n if (ctx.openIndex === menuCtx.index && ctx.getOpenSource() !== 'hover') {\n ctx.closeMenu();\n } else {\n ctx.openMenu(menuCtx.index, 'click');\n ctx.setActiveIndex(menuCtx.index);\n }\n });\n\n const handleMouseEnter = createEventHandler<any>(onMouseEnter, () => {\n if (isDisabled) {\n return;\n }\n ctx.cancelClose();\n if (ctx.trigger === 'hover') {\n ctx.openMenu(menuCtx.index, 'hover');\n ctx.setActiveIndex(menuCtx.index);\n } else if (ctx.openIndex !== null && ctx.openIndex !== menuCtx.index) {\n ctx.openMenu(menuCtx.index, 'hover');\n ctx.setActiveIndex(menuCtx.index);\n }\n });\n\n const handleMouseLeave = createEventHandler<any>(onMouseLeave, () => {\n if (ctx.trigger === 'hover') {\n ctx.scheduleClose();\n }\n });\n\n const handleFocus = createEventHandler<any>(onFocus, () => ctx.setActiveIndex(menuCtx.index));\n\n const handleKeyDown = createEventHandler<any>(onKeyDown, (event) => {\n if (isDisabled) {\n return;\n }\n const forwardKey = dir === 'rtl' ? 'ArrowLeft' : 'ArrowRight';\n const backKey = dir === 'rtl' ? 'ArrowRight' : 'ArrowLeft';\n\n if (event.key === forwardKey) {\n event.preventDefault();\n moveToAdjacent(1);\n } else if (event.key === backKey) {\n event.preventDefault();\n moveToAdjacent(-1);\n } else if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n openAndFocusItem('first');\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n openAndFocusItem('last');\n } else if (event.key === 'Home') {\n event.preventDefault();\n const enabled = ctx.getEnabledIndexes();\n if (enabled.length > 0) {\n ctx.setActiveIndex(enabled[0]);\n ctx.focusTarget(enabled[0]);\n }\n } else if (event.key === 'End') {\n event.preventDefault();\n const enabled = ctx.getEnabledIndexes();\n if (enabled.length > 0) {\n const last = enabled[enabled.length - 1];\n ctx.setActiveIndex(last);\n ctx.focusTarget(last);\n }\n } else if (event.key === 'Escape') {\n if (menuCtx.opened) {\n ctx.closeMenu();\n }\n } else if (event.key === 'Tab') {\n if (menuCtx.opened) {\n ctx.closeMenu();\n }\n } else if (isPrintableKey(event)) {\n typeAhead(event);\n }\n });\n\n return (\n <Popover.Target refProp={refProp} popupType=\"menu\">\n <UnstyledButton\n {...others}\n unstyled={ctx.unstyled}\n role=\"menuitem\"\n tabIndex={isActive || isUnresolvedTabStop ? 0 : -1}\n disabled={disabled}\n data-menubar-target\n data-menubar-id={menuCtx.id}\n data-disabled={dataDisabled || undefined}\n data-expanded={menuCtx.opened || undefined}\n data-mantine-stop-propagation={menuCtx.opened || undefined}\n {...ctx.getStyles('target', { className, style })}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n >\n {children}\n </UnstyledButton>\n </Popover.Target>\n );\n}\n\nMenubarTarget.displayName = '@mantine/core/MenubarTarget';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MenubarTarget.mjs","names":[],"sources":["../../../../src/components/Menubar/MenubarTarget/MenubarTarget.tsx"],"sourcesContent":["import {\n createEventHandler,\n ElementProps,\n MantineStyleProp,\n useDirection,\n useProps,\n} from '../../../core';\nimport { Popover } from '../../Popover';\nimport { UnstyledButton } from '../../UnstyledButton';\nimport { useMenubarContext, useMenubarMenuContext } from '../Menubar.context';\n\nexport interface MenubarTargetProps extends ElementProps<'button'> {\n 'data-disabled'?: boolean;\n\n /** Target label */\n children: React.ReactNode;\n\n /** Inline styles applied to the target button */\n style?: MantineStyleProp;\n\n /** Key of the prop used to get element ref, useful for forwarding refs to custom components @default 'ref' */\n refProp?: string;\n}\n\nconst defaultProps = {\n refProp: 'ref',\n} satisfies Partial<MenubarTargetProps>;\n\nfunction isPrintableKey(event: React.KeyboardEvent) {\n return (\n event.key.length === 1 && event.key !== ' ' && !event.ctrlKey && !event.metaKey && !event.altKey\n );\n}\n\nfunction getTargetLabel(node: HTMLElement) {\n return (node.textContent ?? '').trim().toLowerCase();\n}\n\nexport function MenubarTarget(props: MenubarTargetProps) {\n const {\n children,\n refProp,\n className,\n style,\n disabled,\n 'data-disabled': dataDisabled,\n onClick,\n onMouseEnter,\n onMouseLeave,\n onFocus,\n onKeyDown,\n ...others\n } = useProps('MenubarTarget', defaultProps, props);\n\n const ctx = useMenubarContext();\n const menuCtx = useMenubarMenuContext();\n const { dir } = useDirection();\n\n const isDisabled = disabled || dataDisabled;\n const isActive = ctx.activeIndex === menuCtx.index;\n\n // Before the menu indexes resolve from the DOM (first render / SSR HTML), every target\n // would otherwise compute `tabIndex={-1}`, leaving the menubar with no tab stop until\n // effects run. Keep unresolved targets focusable so keyboard users can enter the menubar.\n const isUnresolvedTabStop = menuCtx.index === -1 && !isDisabled;\n\n const moveToAdjacent = (direction: 1 | -1) => {\n const nextIndex = ctx.getAdjacentIndex(menuCtx.index, direction);\n ctx.setActiveIndex(nextIndex);\n ctx.focusTarget(nextIndex);\n if (ctx.openIndex !== null) {\n ctx.openMenu(nextIndex, 'click');\n }\n };\n\n const openAndFocusItem = (itemPosition: 'first' | 'last') => {\n ctx.openMenu(menuCtx.index, 'click');\n ctx.setActiveIndex(menuCtx.index);\n ctx.focusMenuItem(menuCtx.index, itemPosition);\n };\n\n const typeAhead = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n const targets = ctx.getTargets();\n if (targets.length === 0) {\n return;\n }\n\n const char = event.key.toLowerCase();\n for (let offset = 1; offset <= targets.length; offset += 1) {\n const index = (menuCtx.index + offset) % targets.length;\n const node = targets[index];\n if (\n node &&\n !node.disabled &&\n !node.hasAttribute('data-disabled') &&\n getTargetLabel(node).startsWith(char)\n ) {\n event.preventDefault();\n ctx.setActiveIndex(index);\n node.focus();\n if (ctx.openIndex !== null) {\n ctx.openMenu(index, 'click');\n }\n break;\n }\n }\n };\n\n const handleClick = createEventHandler<any>(onClick, () => {\n if (isDisabled) {\n return;\n }\n if (ctx.openIndex === menuCtx.index && ctx.getOpenSource() !== 'hover') {\n ctx.closeMenu();\n } else {\n ctx.openMenu(menuCtx.index, 'click');\n ctx.setActiveIndex(menuCtx.index);\n }\n });\n\n const handleMouseEnter = createEventHandler<any>(onMouseEnter, () => {\n if (isDisabled) {\n return;\n }\n ctx.cancelClose();\n if (ctx.trigger === 'hover') {\n ctx.openMenu(menuCtx.index, 'hover');\n ctx.setActiveIndex(menuCtx.index);\n } else if (ctx.openIndex !== null && ctx.openIndex !== menuCtx.index) {\n // Hover-switching with trigger=\"click\" continues a click-driven interaction:\n // keep 'click' as the open source so that the next click on the target\n // closes the menu, same as a click-opened menu (desktop application pattern)\n ctx.openMenu(menuCtx.index, 'click');\n ctx.setActiveIndex(menuCtx.index);\n }\n });\n\n const handleMouseLeave = createEventHandler<any>(onMouseLeave, () => {\n if (ctx.trigger === 'hover') {\n ctx.scheduleClose();\n }\n });\n\n const handleFocus = createEventHandler<any>(onFocus, () => ctx.setActiveIndex(menuCtx.index));\n\n const handleKeyDown = createEventHandler<any>(onKeyDown, (event) => {\n if (isDisabled) {\n return;\n }\n const forwardKey = dir === 'rtl' ? 'ArrowLeft' : 'ArrowRight';\n const backKey = dir === 'rtl' ? 'ArrowRight' : 'ArrowLeft';\n\n if (event.key === forwardKey) {\n event.preventDefault();\n moveToAdjacent(1);\n } else if (event.key === backKey) {\n event.preventDefault();\n moveToAdjacent(-1);\n } else if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n openAndFocusItem('first');\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n openAndFocusItem('last');\n } else if (event.key === 'Home') {\n event.preventDefault();\n const enabled = ctx.getEnabledIndexes();\n if (enabled.length > 0) {\n ctx.setActiveIndex(enabled[0]);\n ctx.focusTarget(enabled[0]);\n }\n } else if (event.key === 'End') {\n event.preventDefault();\n const enabled = ctx.getEnabledIndexes();\n if (enabled.length > 0) {\n const last = enabled[enabled.length - 1];\n ctx.setActiveIndex(last);\n ctx.focusTarget(last);\n }\n } else if (event.key === 'Escape') {\n if (menuCtx.opened) {\n ctx.closeMenu();\n }\n } else if (event.key === 'Tab') {\n if (menuCtx.opened) {\n ctx.closeMenu();\n }\n } else if (isPrintableKey(event)) {\n typeAhead(event);\n }\n });\n\n return (\n <Popover.Target refProp={refProp} popupType=\"menu\">\n <UnstyledButton\n {...others}\n unstyled={ctx.unstyled}\n role=\"menuitem\"\n tabIndex={isActive || isUnresolvedTabStop ? 0 : -1}\n disabled={disabled}\n data-menubar-target\n data-menubar-id={menuCtx.id}\n data-disabled={dataDisabled || undefined}\n data-expanded={menuCtx.opened || undefined}\n data-mantine-stop-propagation={menuCtx.opened || undefined}\n {...ctx.getStyles('target', { className, style })}\n onClick={handleClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n >\n {children}\n </UnstyledButton>\n </Popover.Target>\n );\n}\n\nMenubarTarget.displayName = '@mantine/core/MenubarTarget';\n"],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ import { useModal } from "./use-modal.mjs";
|
|
|
8
8
|
import { RemoveScroll } from "react-remove-scroll";
|
|
9
9
|
import { jsx } from "react/jsx-runtime";
|
|
10
10
|
//#region packages/@mantine/core/src/components/ModalBase/ModalBase.tsx
|
|
11
|
-
function ModalBase({ keepMounted, opened, onClose, id, transitionProps, onExitTransitionEnd, onEnterTransitionEnd, trapFocus, closeOnEscape, returnFocus, closeOnClickOutside, withinPortal, portalProps, lockScroll, children, zIndex, shadow, padding, __vars, unstyled, removeScrollProps, ...others }) {
|
|
11
|
+
function ModalBase({ keepMounted, keepMountedMode = "activity", opened, onClose, id, transitionProps, onExitTransitionEnd, onEnterTransitionEnd, trapFocus, closeOnEscape, returnFocus, closeOnClickOutside, withinPortal, portalProps, lockScroll, children, zIndex, shadow, padding, __vars, unstyled, removeScrollProps, ...others }) {
|
|
12
12
|
const { _id, titleMounted, bodyMounted, shouldLockScroll, setTitleMounted, setBodyMounted } = useModal({
|
|
13
13
|
id,
|
|
14
14
|
transitionProps,
|
|
@@ -31,7 +31,8 @@ function ModalBase({ keepMounted, opened, onClose, id, transitionProps, onExitTr
|
|
|
31
31
|
onEnterTransitionEnd,
|
|
32
32
|
transitionProps: {
|
|
33
33
|
...transitionProps,
|
|
34
|
-
keepMounted
|
|
34
|
+
keepMounted,
|
|
35
|
+
keepMountedMode
|
|
35
36
|
},
|
|
36
37
|
getTitleId: () => `${_id}-title`,
|
|
37
38
|
getBodyId: () => `${_id}-body`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModalBase.mjs","names":[],"sources":["../../../src/components/ModalBase/ModalBase.tsx"],"sourcesContent":["import { RemoveScroll } from 'react-remove-scroll';\nimport {\n Box,\n BoxProps,\n ElementProps,\n getDefaultZIndex,\n getShadow,\n getSpacing,\n MantineShadow,\n MantineSize,\n MantineSpacing,\n} from '../../core';\nimport { BasePortalProps, OptionalPortal } from '../Portal';\nimport { TransitionOverride } from '../Transition';\nimport { ModalBaseProvider } from './ModalBase.context';\nimport { useModal } from './use-modal';\n\ntype RemoveScrollProps = Omit<React.ComponentProps<typeof RemoveScroll>, 'children'>;\n\nexport interface ModalBaseProps extends BoxProps, ElementProps<'div', 'title'> {\n unstyled?: boolean;\n\n /** If set modal/drawer is not unmounted from the DOM when hidden. `display: none` styles are applied instead. @default false */\n keepMounted?: boolean;\n\n /** Controls opened state */\n opened: boolean;\n\n /** Called when modal/drawer is closed */\n onClose: () => void;\n\n /** Id used to connect modal/drawer with body and title */\n id?: string;\n\n /** If set, scroll is locked when `opened={true}` @default true */\n lockScroll?: boolean;\n\n /** If set, focus is trapped within the modal/drawer @default true */\n trapFocus?: boolean;\n\n /** If set, the component is rendered inside `Portal` @default true */\n withinPortal?: boolean;\n\n /** Props passed down to the Portal component when `withinPortal` is set */\n portalProps?: BasePortalProps;\n\n /** Modal/drawer content */\n children?: React.ReactNode;\n\n /** If set, the modal/drawer is closed when user clicks on the overlay @default true */\n closeOnClickOutside?: boolean;\n\n /** Props added to the `Transition` component that used to animate overlay and body, use to configure duration and animation type, `{ duration: 200, transition: 'fade-down' }` by default */\n transitionProps?: TransitionOverride;\n\n /** Called when exit transition ends */\n onExitTransitionEnd?: () => void;\n\n /** Called when enter transition ends */\n onEnterTransitionEnd?: () => void;\n\n /** If set, `onClose` is called when user presses the escape key @default true */\n closeOnEscape?: boolean;\n\n /** If set, focus is returned to the last active element when `onClose` is called @default true */\n returnFocus?: boolean;\n\n /** `z-index` CSS property of the root element @default 200 */\n zIndex?: string | number;\n\n /** Key of `theme.shadows` or any valid CSS box-shadow value @default 'xl' */\n shadow?: MantineShadow;\n\n /** Key of `theme.spacing` or any valid CSS value to set content, header and footer padding @default 'md' */\n padding?: MantineSpacing;\n\n /** Controls width of the content area @default 'md' */\n size?: MantineSize | (string & {}) | number;\n\n /** Props passed down to react-remove-scroll, can be used to customize scroll lock behavior */\n removeScrollProps?: RemoveScrollProps;\n}\n\nexport function ModalBase({\n keepMounted,\n opened,\n onClose,\n id,\n transitionProps,\n onExitTransitionEnd,\n onEnterTransitionEnd,\n trapFocus,\n closeOnEscape,\n returnFocus,\n closeOnClickOutside,\n withinPortal,\n portalProps,\n lockScroll,\n children,\n zIndex,\n shadow,\n padding,\n __vars,\n unstyled,\n removeScrollProps,\n ...others\n}: ModalBaseProps) {\n const { _id, titleMounted, bodyMounted, shouldLockScroll, setTitleMounted, setBodyMounted } =\n useModal({ id, transitionProps, opened, trapFocus, closeOnEscape, onClose, returnFocus });\n\n const { key: removeScrollKey, ...otherRemoveScrollProps } = removeScrollProps || {};\n\n return (\n <OptionalPortal {...portalProps} withinPortal={withinPortal}>\n <ModalBaseProvider\n value={{\n opened,\n onClose,\n closeOnClickOutside,\n onExitTransitionEnd,\n onEnterTransitionEnd,\n transitionProps: { ...transitionProps, keepMounted },\n getTitleId: () => `${_id}-title`,\n getBodyId: () => `${_id}-body`,\n titleMounted,\n bodyMounted,\n setTitleMounted,\n setBodyMounted,\n trapFocus,\n closeOnEscape,\n zIndex,\n unstyled,\n }}\n >\n <RemoveScroll\n enabled={shouldLockScroll && lockScroll}\n key={removeScrollKey}\n {...otherRemoveScrollProps}\n >\n <Box\n {...others}\n id={_id}\n __vars={{\n ...__vars,\n '--mb-z-index': (zIndex || getDefaultZIndex('modal')).toString(),\n '--mb-shadow': getShadow(shadow),\n '--mb-padding': getSpacing(padding),\n }}\n >\n {children}\n </Box>\n </RemoveScroll>\n </ModalBaseProvider>\n </OptionalPortal>\n );\n}\n\nModalBase.displayName = '@mantine/core/ModalBase';\n"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"ModalBase.mjs","names":[],"sources":["../../../src/components/ModalBase/ModalBase.tsx"],"sourcesContent":["import { RemoveScroll } from 'react-remove-scroll';\nimport {\n Box,\n BoxProps,\n ElementProps,\n getDefaultZIndex,\n getShadow,\n getSpacing,\n MantineShadow,\n MantineSize,\n MantineSpacing,\n} from '../../core';\nimport { BasePortalProps, OptionalPortal } from '../Portal';\nimport { TransitionOverride } from '../Transition';\nimport { ModalBaseProvider } from './ModalBase.context';\nimport { useModal } from './use-modal';\n\ntype RemoveScrollProps = Omit<React.ComponentProps<typeof RemoveScroll>, 'children'>;\n\nexport interface ModalBaseProps extends BoxProps, ElementProps<'div', 'title'> {\n unstyled?: boolean;\n\n /** If set modal/drawer is not unmounted from the DOM when hidden. `display: none` styles are applied instead. @default false */\n keepMounted?: boolean;\n\n /** Controls how the modal/drawer is hidden when `keepMounted` is set:\n * `'activity'` - hidden with React 19 `Activity` component,\n * `'display-none'` - hidden with `display: none` styles\n * @default 'activity'\n */\n keepMountedMode?: 'activity' | 'display-none';\n\n /** Controls opened state */\n opened: boolean;\n\n /** Called when modal/drawer is closed */\n onClose: () => void;\n\n /** Id used to connect modal/drawer with body and title */\n id?: string;\n\n /** If set, scroll is locked when `opened={true}` @default true */\n lockScroll?: boolean;\n\n /** If set, focus is trapped within the modal/drawer @default true */\n trapFocus?: boolean;\n\n /** If set, the component is rendered inside `Portal` @default true */\n withinPortal?: boolean;\n\n /** Props passed down to the Portal component when `withinPortal` is set */\n portalProps?: BasePortalProps;\n\n /** Modal/drawer content */\n children?: React.ReactNode;\n\n /** If set, the modal/drawer is closed when user clicks on the overlay @default true */\n closeOnClickOutside?: boolean;\n\n /** Props added to the `Transition` component that used to animate overlay and body, use to configure duration and animation type, `{ duration: 200, transition: 'fade-down' }` by default */\n transitionProps?: TransitionOverride;\n\n /** Called when exit transition ends */\n onExitTransitionEnd?: () => void;\n\n /** Called when enter transition ends */\n onEnterTransitionEnd?: () => void;\n\n /** If set, `onClose` is called when user presses the escape key @default true */\n closeOnEscape?: boolean;\n\n /** If set, focus is returned to the last active element when `onClose` is called @default true */\n returnFocus?: boolean;\n\n /** `z-index` CSS property of the root element @default 200 */\n zIndex?: string | number;\n\n /** Key of `theme.shadows` or any valid CSS box-shadow value @default 'xl' */\n shadow?: MantineShadow;\n\n /** Key of `theme.spacing` or any valid CSS value to set content, header and footer padding @default 'md' */\n padding?: MantineSpacing;\n\n /** Controls width of the content area @default 'md' */\n size?: MantineSize | (string & {}) | number;\n\n /** Props passed down to react-remove-scroll, can be used to customize scroll lock behavior */\n removeScrollProps?: RemoveScrollProps;\n}\n\nexport function ModalBase({\n keepMounted,\n keepMountedMode = 'activity',\n opened,\n onClose,\n id,\n transitionProps,\n onExitTransitionEnd,\n onEnterTransitionEnd,\n trapFocus,\n closeOnEscape,\n returnFocus,\n closeOnClickOutside,\n withinPortal,\n portalProps,\n lockScroll,\n children,\n zIndex,\n shadow,\n padding,\n __vars,\n unstyled,\n removeScrollProps,\n ...others\n}: ModalBaseProps) {\n const { _id, titleMounted, bodyMounted, shouldLockScroll, setTitleMounted, setBodyMounted } =\n useModal({ id, transitionProps, opened, trapFocus, closeOnEscape, onClose, returnFocus });\n\n const { key: removeScrollKey, ...otherRemoveScrollProps } = removeScrollProps || {};\n\n return (\n <OptionalPortal {...portalProps} withinPortal={withinPortal}>\n <ModalBaseProvider\n value={{\n opened,\n onClose,\n closeOnClickOutside,\n onExitTransitionEnd,\n onEnterTransitionEnd,\n transitionProps: { ...transitionProps, keepMounted, keepMountedMode },\n getTitleId: () => `${_id}-title`,\n getBodyId: () => `${_id}-body`,\n titleMounted,\n bodyMounted,\n setTitleMounted,\n setBodyMounted,\n trapFocus,\n closeOnEscape,\n zIndex,\n unstyled,\n }}\n >\n <RemoveScroll\n enabled={shouldLockScroll && lockScroll}\n key={removeScrollKey}\n {...otherRemoveScrollProps}\n >\n <Box\n {...others}\n id={_id}\n __vars={{\n ...__vars,\n '--mb-z-index': (zIndex || getDefaultZIndex('modal')).toString(),\n '--mb-shadow': getShadow(shadow),\n '--mb-padding': getSpacing(padding),\n }}\n >\n {children}\n </Box>\n </RemoveScroll>\n </ModalBaseProvider>\n </OptionalPortal>\n );\n}\n\nModalBase.displayName = '@mantine/core/ModalBase';\n"],"mappings":";;;;;;;;;;AA0FA,SAAgB,UAAU,EACxB,aACA,kBAAkB,YAClB,QACA,SACA,IACA,iBACA,qBACA,sBACA,WACA,eACA,aACA,qBACA,cACA,aACA,YACA,UACA,QACA,QACA,SACA,QACA,UACA,mBACA,GAAG,UACc;CACjB,MAAM,EAAE,KAAK,cAAc,aAAa,kBAAkB,iBAAiB,mBACzE,SAAS;EAAE;EAAI;EAAiB;EAAQ;EAAW;EAAe;EAAS;CAAY,CAAC;CAE1F,MAAM,EAAE,KAAK,iBAAiB,GAAG,2BAA2B,qBAAqB,CAAC;CAElF,OACE,oBAAC,gBAAD;EAAgB,GAAI;EAA2B;YAC7C,oBAAC,mBAAD;GACE,OAAO;IACL;IACA;IACA;IACA;IACA;IACA,iBAAiB;KAAE,GAAG;KAAiB;KAAa;IAAgB;IACpE,kBAAkB,GAAG,IAAI;IACzB,iBAAiB,GAAG,IAAI;IACxB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF;aAEA,oBAAC,cAAD;IACE,SAAS,oBAAoB;IAE7B,GAAI;cAEJ,oBAAC,KAAD;KACE,GAAI;KACJ,IAAI;KACJ,QAAQ;MACN,GAAG;MACH,iBAAiB,UAAU,iBAAiB,OAAO,EAAA,CAAG,SAAS;MAC/D,eAAe,UAAU,MAAM;MAC/B,gBAAgB,WAAW,OAAO;KACpC;KAEC;IACE,CAAA;GACO,GAfP,eAeO;EACG,CAAA;CACL,CAAA;AAEpB;AAEA,UAAU,cAAc"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Transition.mjs","names":[],"sources":["../../../src/components/Transition/Transition.tsx"],"sourcesContent":["import { Activity } from 'react';\nimport { useMantineEnv } from '../../core';\nimport { getTransitionStyles } from './get-transition-styles/get-transition-styles';\nimport { MantineTransition } from './transitions';\nimport { useTransition } from './use-transition';\n\nexport interface TransitionProps {\n /** If set, the element is kept in the DOM when hidden. React 19 `Activity` is used to preserve state while the element is not visible. */\n keepMounted?: boolean;\n\n /**\n * Controls how the element is hidden when `keepMounted` is set:\n * `'activity'`
|
|
1
|
+
{"version":3,"file":"Transition.mjs","names":[],"sources":["../../../src/components/Transition/Transition.tsx"],"sourcesContent":["import { Activity } from 'react';\nimport { useMantineEnv } from '../../core';\nimport { getTransitionStyles } from './get-transition-styles/get-transition-styles';\nimport { MantineTransition } from './transitions';\nimport { useTransition } from './use-transition';\n\nexport interface TransitionProps {\n /** If set, the element is kept in the DOM when hidden. React 19 `Activity` is used to preserve state while the element is not visible. */\n keepMounted?: boolean;\n\n /**\n * Controls how the element is hidden when `keepMounted` is set:\n * `'activity'` - hidden with React 19 `Activity` component,\n * `'display-none'` - hidden with `display: none` styles\n * @default 'activity'\n */\n keepMountedMode?: 'activity' | 'display-none';\n\n /** Transition name or object */\n transition?: MantineTransition;\n\n /** Transition duration in ms @default 250 */\n duration?: number;\n\n /** Exit transition duration in ms @default 250 */\n exitDuration?: number;\n\n /** Transition timing function @default theme.transitionTimingFunction */\n timingFunction?: string;\n\n /** Determines whether component should be mounted to the DOM */\n mounted: boolean;\n\n /** Render function with transition styles argument */\n children: (styles: React.CSSProperties) => React.JSX.Element;\n\n /** Called when exit transition ends */\n onExited?: () => void;\n\n /** Called when exit transition starts */\n onExit?: () => void;\n\n /** Called when enter transition starts */\n onEnter?: () => void;\n\n /** Called when enter transition ends */\n onEntered?: () => void;\n\n /** Delay in ms before enter transition starts */\n enterDelay?: number;\n\n /** Delay in ms before exit transition starts */\n exitDelay?: number;\n}\n\nexport type TransitionOverride = Partial<Omit<TransitionProps, 'mounted'>>;\n\nexport function Transition({\n keepMounted,\n keepMountedMode = 'activity',\n transition = 'fade',\n duration = 250,\n exitDuration = duration,\n mounted,\n children,\n timingFunction = 'ease',\n onExit,\n onEntered,\n onEnter,\n onExited,\n enterDelay,\n exitDelay,\n}: TransitionProps) {\n const env = useMantineEnv();\n const { transitionDuration, transitionStatus, transitionTimingFunction } = useTransition({\n mounted,\n exitDuration,\n duration,\n timingFunction,\n onExit,\n onEntered,\n onEnter,\n onExited,\n enterDelay,\n exitDelay,\n });\n\n if (env === 'test') {\n return mounted ? <>{children({})}</> : keepMounted ? children({ display: 'none' }) : null;\n }\n\n if (transitionDuration === 0) {\n if (keepMounted) {\n if (keepMountedMode === 'display-none') {\n return mounted ? <>{children({})}</> : children({ display: 'none' });\n }\n\n return <Activity mode={mounted ? 'visible' : 'hidden'}>{children({})}</Activity>;\n }\n return mounted ? <>{children({})}</> : null;\n }\n\n const isExited = transitionStatus === 'exited';\n\n if (keepMounted) {\n const keepMountedChildren = children(\n isExited\n ? keepMountedMode === 'display-none'\n ? { display: 'none' }\n : {}\n : getTransitionStyles({\n transition,\n duration: transitionDuration,\n state: transitionStatus,\n timingFunction: transitionTimingFunction,\n })\n );\n\n if (keepMountedMode === 'display-none') {\n return keepMountedChildren;\n }\n\n return <Activity mode={isExited ? 'hidden' : 'visible'}>{keepMountedChildren}</Activity>;\n }\n\n return isExited ? null : (\n <>\n {children(\n getTransitionStyles({\n transition,\n duration: transitionDuration,\n state: transitionStatus,\n timingFunction: transitionTimingFunction,\n })\n )}\n </>\n );\n}\n\nTransition.displayName = '@mantine/core/Transition';\n\nexport namespace Transition {\n export type Props = TransitionProps;\n export type Override = TransitionOverride;\n}\n"],"mappings":";;;;;;;AAyDA,SAAgB,WAAW,EACzB,aACA,kBAAkB,YAClB,aAAa,QACb,WAAW,KACX,eAAe,UACf,SACA,UACA,iBAAiB,QACjB,QACA,WACA,SACA,UACA,YACA,aACkB;CAClB,MAAM,MAAM,cAAc;CAC1B,MAAM,EAAE,oBAAoB,kBAAkB,6BAA6B,cAAc;EACvF;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,IAAI,QAAQ,QACV,OAAO,UAAU,oBAAA,YAAA,EAAA,UAAG,SAAS,CAAC,CAAC,EAAI,CAAA,IAAI,cAAc,SAAS,EAAE,SAAS,OAAO,CAAC,IAAI;CAGvF,IAAI,uBAAuB,GAAG;EAC5B,IAAI,aAAa;GACf,IAAI,oBAAoB,gBACtB,OAAO,UAAU,oBAAA,YAAA,EAAA,UAAG,SAAS,CAAC,CAAC,EAAI,CAAA,IAAI,SAAS,EAAE,SAAS,OAAO,CAAC;GAGrE,OAAO,oBAAC,UAAD;IAAU,MAAM,UAAU,YAAY;cAAW,SAAS,CAAC,CAAC;GAAY,CAAA;EACjF;EACA,OAAO,UAAU,oBAAA,YAAA,EAAA,UAAG,SAAS,CAAC,CAAC,EAAI,CAAA,IAAI;CACzC;CAEA,MAAM,WAAW,qBAAqB;CAEtC,IAAI,aAAa;EACf,MAAM,sBAAsB,SAC1B,WACI,oBAAoB,iBAClB,EAAE,SAAS,OAAO,IAClB,CAAC,IACH,oBAAoB;GAClB;GACA,UAAU;GACV,OAAO;GACP,gBAAgB;EAClB,CAAC,CACP;EAEA,IAAI,oBAAoB,gBACtB,OAAO;EAGT,OAAO,oBAAC,UAAD;GAAU,MAAM,WAAW,WAAW;aAAY;EAA8B,CAAA;CACzF;CAEA,OAAO,WAAW,OAChB,oBAAA,YAAA,EAAA,UACG,SACC,oBAAoB;EAClB;EACA,UAAU;EACV,OAAO;EACP,gBAAgB;CAClB,CAAC,CACH,EACA,CAAA;AAEN;AAEA,WAAW,cAAc"}
|
|
@@ -23,14 +23,22 @@ const FlatTreeNode = memo(function FlatTreeNode({ node, level, parent, hasChildr
|
|
|
23
23
|
const root = findElementAncestor(event.currentTarget, "[data-tree-root]");
|
|
24
24
|
const nodes = root ? Array.from(root.querySelectorAll("[role=treeitem]")).filter((treeNode) => treeNode.style.display !== "none") : [];
|
|
25
25
|
const index = nodes.indexOf(event.currentTarget);
|
|
26
|
-
if (index !== -1)
|
|
26
|
+
if (index !== -1) {
|
|
27
|
+
const nextNode = nodes[index + 1];
|
|
28
|
+
nextNode?.setAttribute("data-focus-ring", "true");
|
|
29
|
+
nextNode?.focus();
|
|
30
|
+
}
|
|
27
31
|
} else if (hasChildren) tree.expand(node.value);
|
|
28
32
|
}
|
|
29
33
|
if (event.nativeEvent.code === "ArrowLeft") {
|
|
30
34
|
event.stopPropagation();
|
|
31
35
|
event.preventDefault();
|
|
32
36
|
if (expanded && hasChildren) tree.collapse(node.value);
|
|
33
|
-
else if (parent)
|
|
37
|
+
else if (parent) {
|
|
38
|
+
const parentElement = findElementAncestor(event.currentTarget, "[data-tree-root]")?.querySelector(`[role=treeitem][data-value="${CSS.escape(parent)}"]`);
|
|
39
|
+
parentElement?.setAttribute("data-focus-ring", "true");
|
|
40
|
+
parentElement?.focus();
|
|
41
|
+
}
|
|
34
42
|
}
|
|
35
43
|
if (event.nativeEvent.code === "ArrowDown" || event.nativeEvent.code === "ArrowUp") {
|
|
36
44
|
const root = findElementAncestor(event.currentTarget, "[data-tree-root]");
|
|
@@ -40,7 +48,9 @@ const FlatTreeNode = memo(function FlatTreeNode({ node, level, parent, hasChildr
|
|
|
40
48
|
const nodes = Array.from(root.querySelectorAll("[role=treeitem]")).filter((treeNode) => treeNode.style.display !== "none");
|
|
41
49
|
const index = nodes.indexOf(event.currentTarget);
|
|
42
50
|
if (index === -1) return;
|
|
43
|
-
nodes[event.nativeEvent.code === "ArrowDown" ? index + 1 : index - 1]
|
|
51
|
+
const nextNode = nodes[event.nativeEvent.code === "ArrowDown" ? index + 1 : index - 1];
|
|
52
|
+
nextNode?.setAttribute("data-focus-ring", "true");
|
|
53
|
+
nextNode?.focus();
|
|
44
54
|
}
|
|
45
55
|
if (event.nativeEvent.code === "Space") {
|
|
46
56
|
if (expandOnSpace) {
|
|
@@ -78,6 +88,9 @@ const FlatTreeNode = memo(function FlatTreeNode({ node, level, parent, hasChildr
|
|
|
78
88
|
"data-level": level,
|
|
79
89
|
tabIndex,
|
|
80
90
|
onKeyDown: handleKeyDown,
|
|
91
|
+
onBlur: (event) => {
|
|
92
|
+
if (!event.currentTarget.contains(event.relatedTarget)) event.currentTarget.removeAttribute("data-focus-ring");
|
|
93
|
+
},
|
|
81
94
|
children: [linesPath?.map((state, idx) => {
|
|
82
95
|
if (state === "none") return null;
|
|
83
96
|
const column = idx + 2;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FlatTreeNode.mjs","names":["classes"],"sources":["../../../src/components/Tree/FlatTreeNode.tsx"],"sourcesContent":["import { memo, useRef } from 'react';\nimport { findElementAncestor } from '../../core';\nimport type { FlatTreeLineState } from './flatten-tree-data/flatten-tree-data';\nimport type { RenderNode, TreeNodeData } from './Tree';\nimport type { TreeController } from './use-tree';\nimport classes from './Tree.module.css';\n\nexport interface FlatTreeNodeProps {\n /** Node data from tree data */\n node: TreeNodeData;\n\n /** Nesting level of the node, starts at 1 */\n level: number;\n\n /** Value of the parent node, `null` for root nodes */\n parent: string | null;\n\n /** Whether the node has children */\n hasChildren: boolean;\n\n /** Whether the node is expanded */\n expanded: boolean;\n\n /** Tree controller instance, return value of `useTree` hook */\n tree: TreeController;\n\n /** If set, tree node with children is expanded on click @default true */\n expandOnClick?: boolean;\n\n /** If set, tree node is selected on click @default false */\n selectOnClick?: boolean;\n\n /** If set, tree node with children is expanded on space key press @default true */\n expandOnSpace?: boolean;\n\n /** If set, tree node is checked on space key press @default false */\n checkOnSpace?: boolean;\n\n /** A function to render tree node label */\n renderNode?: RenderNode;\n\n /** Style to apply to the root element, used for virtualizer positioning */\n style?: React.CSSProperties;\n\n /** Tab index for the node */\n tabIndex?: number;\n\n /** Line state per ancestor + own level, computed by `flattenTreeData`.\n * When provided and the tree root has `data-with-lines`, connector lines are rendered. */\n linesPath?: FlatTreeLineState[];\n}\n\nexport const FlatTreeNode = memo(function FlatTreeNode({\n node,\n level,\n parent,\n hasChildren,\n expanded,\n tree,\n expandOnClick = true,\n selectOnClick,\n expandOnSpace = true,\n checkOnSpace,\n renderNode,\n style,\n tabIndex = -1,\n linesPath,\n}: FlatTreeNodeProps) {\n const ref = useRef<HTMLDivElement>(null);\n const isLoading = tree.isNodeLoading(node.value);\n const loadError = tree.getNodeLoadError(node.value);\n const selected = tree.selectedState.includes(node.value);\n\n const handleClick = (event: React.MouseEvent) => {\n event.stopPropagation();\n\n if (expandOnClick && hasChildren) {\n tree.toggleExpanded(node.value);\n }\n\n if (selectOnClick) {\n tree.select(node.value);\n }\n\n ref.current?.focus();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.nativeEvent.code === 'ArrowRight') {\n event.stopPropagation();\n event.preventDefault();\n\n if (expanded && hasChildren) {\n const root = findElementAncestor(event.currentTarget as HTMLElement, '[data-tree-root]');\n const nodes = root\n ? Array.from(root.querySelectorAll<HTMLElement>('[role=treeitem]')).filter(\n (treeNode) => treeNode.style.display !== 'none'\n )\n : [];\n const index = nodes.indexOf(event.currentTarget as HTMLElement);\n if (index !== -1) {\n nodes[index + 1]?.focus();\n }\n } else if (hasChildren) {\n tree.expand(node.value);\n }\n }\n\n if (event.nativeEvent.code === 'ArrowLeft') {\n event.stopPropagation();\n event.preventDefault();\n\n if (expanded && hasChildren) {\n tree.collapse(node.value);\n } else if (parent) {\n const root = findElementAncestor(event.currentTarget as HTMLElement, '[data-tree-root]');\n const parentElement = root?.querySelector<HTMLElement>(\n `[role=treeitem][data-value=\"${CSS.escape(parent)}\"]`\n );\n parentElement?.focus();\n }\n }\n\n if (event.nativeEvent.code === 'ArrowDown' || event.nativeEvent.code === 'ArrowUp') {\n const root = findElementAncestor(event.currentTarget as HTMLElement, '[data-tree-root]');\n\n if (!root) {\n return;\n }\n\n event.stopPropagation();\n event.preventDefault();\n const nodes = Array.from(root.querySelectorAll<HTMLElement>('[role=treeitem]')).filter(\n (treeNode) => treeNode.style.display !== 'none'\n );\n const index = nodes.indexOf(event.currentTarget as HTMLElement);\n\n if (index === -1) {\n return;\n }\n\n const nextIndex = event.nativeEvent.code === 'ArrowDown' ? index + 1 : index - 1;\n nodes[nextIndex]?.focus();\n }\n\n if (event.nativeEvent.code === 'Space') {\n if (expandOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n tree.toggleExpanded(node.value);\n }\n\n if (checkOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n if (tree.isNodeChecked(node.value)) {\n tree.uncheckNode(node.value);\n } else {\n tree.checkNode(node.value);\n }\n }\n }\n };\n\n const elementProps = {\n className: classes.label,\n style: {} as React.CSSProperties,\n onClick: handleClick,\n 'data-selected': selected || undefined,\n 'data-value': node.value,\n };\n\n return (\n <div\n ref={ref}\n className={classes.node}\n style={{\n ...({\n '--label-offset': `calc(var(--level-offset, var(--mantine-spacing-lg)) * ${level - 1})`,\n } as React.CSSProperties),\n ...style,\n }}\n role=\"treeitem\"\n aria-selected={selected}\n aria-expanded={hasChildren ? expanded : undefined}\n data-value={node.value}\n data-selected={selected || undefined}\n data-level={level}\n tabIndex={tabIndex}\n onKeyDown={handleKeyDown}\n >\n {linesPath?.map((state, idx) => {\n if (state === 'none') {\n return null;\n }\n const column = idx + 2;\n return (\n <span\n key={column}\n aria-hidden\n className={`${classes.flatLine}${state === 'closing' ? ` ${classes.flatLineClosing}` : ''}`}\n style={{ '--flat-line-column': column } as React.CSSProperties}\n />\n );\n })}\n {typeof renderNode === 'function' ? (\n renderNode({\n node,\n level,\n selected,\n isRoot: level === 1,\n tree,\n expanded,\n hasChildren,\n isLoading,\n loadError,\n elementProps,\n dragHandleProps: undefined,\n })\n ) : (\n <div {...elementProps}>{node.label}</div>\n )}\n </div>\n );\n});\n\nFlatTreeNode.displayName = '@mantine/core/FlatTreeNode';\n"],"mappings":";;;;;;AAoDA,MAAa,eAAe,KAAK,SAAS,aAAa,EACrD,MACA,OACA,QACA,aACA,UACA,MACA,gBAAgB,MAChB,eACA,gBAAgB,MAChB,cACA,YACA,OACA,WAAW,IACX,aACoB;CACpB,MAAM,MAAM,OAAuB,IAAI;CACvC,MAAM,YAAY,KAAK,cAAc,KAAK,KAAK;CAC/C,MAAM,YAAY,KAAK,iBAAiB,KAAK,KAAK;CAClD,MAAM,WAAW,KAAK,cAAc,SAAS,KAAK,KAAK;CAEvD,MAAM,eAAe,UAA4B;EAC/C,MAAM,gBAAgB;EAEtB,IAAI,iBAAiB,aACnB,KAAK,eAAe,KAAK,KAAK;EAGhC,IAAI,eACF,KAAK,OAAO,KAAK,KAAK;EAGxB,IAAI,SAAS,MAAM;CACrB;CAEA,MAAM,iBAAiB,UAA+B;EACpD,IAAI,MAAM,YAAY,SAAS,cAAc;GAC3C,MAAM,gBAAgB;GACtB,MAAM,eAAe;GAErB,IAAI,YAAY,aAAa;IAC3B,MAAM,OAAO,oBAAoB,MAAM,eAA8B,kBAAkB;IACvF,MAAM,QAAQ,OACV,MAAM,KAAK,KAAK,iBAA8B,iBAAiB,CAAC,CAAC,CAAC,QAC/D,aAAa,SAAS,MAAM,YAAY,MAC3C,IACA,CAAC;IACL,MAAM,QAAQ,MAAM,QAAQ,MAAM,aAA4B;IAC9D,IAAI,UAAU,
|
|
1
|
+
{"version":3,"file":"FlatTreeNode.mjs","names":["classes"],"sources":["../../../src/components/Tree/FlatTreeNode.tsx"],"sourcesContent":["import { memo, useRef } from 'react';\nimport { findElementAncestor } from '../../core';\nimport type { FlatTreeLineState } from './flatten-tree-data/flatten-tree-data';\nimport type { RenderNode, TreeNodeData } from './Tree';\nimport type { TreeController } from './use-tree';\nimport classes from './Tree.module.css';\n\nexport interface FlatTreeNodeProps {\n /** Node data from tree data */\n node: TreeNodeData;\n\n /** Nesting level of the node, starts at 1 */\n level: number;\n\n /** Value of the parent node, `null` for root nodes */\n parent: string | null;\n\n /** Whether the node has children */\n hasChildren: boolean;\n\n /** Whether the node is expanded */\n expanded: boolean;\n\n /** Tree controller instance, return value of `useTree` hook */\n tree: TreeController;\n\n /** If set, tree node with children is expanded on click @default true */\n expandOnClick?: boolean;\n\n /** If set, tree node is selected on click @default false */\n selectOnClick?: boolean;\n\n /** If set, tree node with children is expanded on space key press @default true */\n expandOnSpace?: boolean;\n\n /** If set, tree node is checked on space key press @default false */\n checkOnSpace?: boolean;\n\n /** A function to render tree node label */\n renderNode?: RenderNode;\n\n /** Style to apply to the root element, used for virtualizer positioning */\n style?: React.CSSProperties;\n\n /** Tab index for the node */\n tabIndex?: number;\n\n /** Line state per ancestor + own level, computed by `flattenTreeData`.\n * When provided and the tree root has `data-with-lines`, connector lines are rendered. */\n linesPath?: FlatTreeLineState[];\n}\n\nexport const FlatTreeNode = memo(function FlatTreeNode({\n node,\n level,\n parent,\n hasChildren,\n expanded,\n tree,\n expandOnClick = true,\n selectOnClick,\n expandOnSpace = true,\n checkOnSpace,\n renderNode,\n style,\n tabIndex = -1,\n linesPath,\n}: FlatTreeNodeProps) {\n const ref = useRef<HTMLDivElement>(null);\n const isLoading = tree.isNodeLoading(node.value);\n const loadError = tree.getNodeLoadError(node.value);\n const selected = tree.selectedState.includes(node.value);\n\n const handleClick = (event: React.MouseEvent) => {\n event.stopPropagation();\n\n if (expandOnClick && hasChildren) {\n tree.toggleExpanded(node.value);\n }\n\n if (selectOnClick) {\n tree.select(node.value);\n }\n\n ref.current?.focus();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.nativeEvent.code === 'ArrowRight') {\n event.stopPropagation();\n event.preventDefault();\n\n if (expanded && hasChildren) {\n const root = findElementAncestor(event.currentTarget as HTMLElement, '[data-tree-root]');\n const nodes = root\n ? Array.from(root.querySelectorAll<HTMLElement>('[role=treeitem]')).filter(\n (treeNode) => treeNode.style.display !== 'none'\n )\n : [];\n const index = nodes.indexOf(event.currentTarget as HTMLElement);\n if (index !== -1) {\n const nextNode = nodes[index + 1];\n nextNode?.setAttribute('data-focus-ring', 'true');\n nextNode?.focus();\n }\n } else if (hasChildren) {\n tree.expand(node.value);\n }\n }\n\n if (event.nativeEvent.code === 'ArrowLeft') {\n event.stopPropagation();\n event.preventDefault();\n\n if (expanded && hasChildren) {\n tree.collapse(node.value);\n } else if (parent) {\n const root = findElementAncestor(event.currentTarget as HTMLElement, '[data-tree-root]');\n const parentElement = root?.querySelector<HTMLElement>(\n `[role=treeitem][data-value=\"${CSS.escape(parent)}\"]`\n );\n parentElement?.setAttribute('data-focus-ring', 'true');\n parentElement?.focus();\n }\n }\n\n if (event.nativeEvent.code === 'ArrowDown' || event.nativeEvent.code === 'ArrowUp') {\n const root = findElementAncestor(event.currentTarget as HTMLElement, '[data-tree-root]');\n\n if (!root) {\n return;\n }\n\n event.stopPropagation();\n event.preventDefault();\n const nodes = Array.from(root.querySelectorAll<HTMLElement>('[role=treeitem]')).filter(\n (treeNode) => treeNode.style.display !== 'none'\n );\n const index = nodes.indexOf(event.currentTarget as HTMLElement);\n\n if (index === -1) {\n return;\n }\n\n const nextIndex = event.nativeEvent.code === 'ArrowDown' ? index + 1 : index - 1;\n const nextNode = nodes[nextIndex];\n nextNode?.setAttribute('data-focus-ring', 'true');\n nextNode?.focus();\n }\n\n if (event.nativeEvent.code === 'Space') {\n if (expandOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n tree.toggleExpanded(node.value);\n }\n\n if (checkOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n if (tree.isNodeChecked(node.value)) {\n tree.uncheckNode(node.value);\n } else {\n tree.checkNode(node.value);\n }\n }\n }\n };\n\n const elementProps = {\n className: classes.label,\n style: {} as React.CSSProperties,\n onClick: handleClick,\n 'data-selected': selected || undefined,\n 'data-value': node.value,\n };\n\n return (\n <div\n ref={ref}\n className={classes.node}\n style={{\n ...({\n '--label-offset': `calc(var(--level-offset, var(--mantine-spacing-lg)) * ${level - 1})`,\n } as React.CSSProperties),\n ...style,\n }}\n role=\"treeitem\"\n aria-selected={selected}\n aria-expanded={hasChildren ? expanded : undefined}\n data-value={node.value}\n data-selected={selected || undefined}\n data-level={level}\n tabIndex={tabIndex}\n onKeyDown={handleKeyDown}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget as HTMLElement)) {\n event.currentTarget.removeAttribute('data-focus-ring');\n }\n }}\n >\n {linesPath?.map((state, idx) => {\n if (state === 'none') {\n return null;\n }\n const column = idx + 2;\n return (\n <span\n key={column}\n aria-hidden\n className={`${classes.flatLine}${state === 'closing' ? ` ${classes.flatLineClosing}` : ''}`}\n style={{ '--flat-line-column': column } as React.CSSProperties}\n />\n );\n })}\n {typeof renderNode === 'function' ? (\n renderNode({\n node,\n level,\n selected,\n isRoot: level === 1,\n tree,\n expanded,\n hasChildren,\n isLoading,\n loadError,\n elementProps,\n dragHandleProps: undefined,\n })\n ) : (\n <div {...elementProps}>{node.label}</div>\n )}\n </div>\n );\n});\n\nFlatTreeNode.displayName = '@mantine/core/FlatTreeNode';\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tree.module.mjs","names":[],"sources":["../../../src/components/Tree/Tree.module.css"],"sourcesContent":[":where([data-tree-root]) {\n --level-offset: var(--mantine-spacing-lg);\n --tree-line-width: rem(1px);\n --tree-line-color: var(--mantine-color-default-border);\n}\n\n.root {\n margin: 0;\n padding: 0;\n user-select: none;\n}\n\n.subtree {\n margin: 0;\n padding: 0;\n}\n\n.node {\n cursor: pointer;\n list-style: none;\n margin: 0;\n padding: 0;\n outline: 0;\n\n &:focus-visible {\n > .label {\n outline: 2px solid var(--mantine-primary-color-filled);\n outline-offset: 2px;\n }\n }\n}\n\n.label {\n position: relative;\n padding-inline-start: var(--label-offset);\n\n &:where([data-selected]) {\n @mixin where-light {\n background-color: var(--mantine-color-gray-1);\n }\n\n @mixin where-dark {\n background-color: var(--mantine-color-dark-5);\n }\n }\n\n &:where([data-dragging]) {\n opacity: 0.4;\n }\n\n &:where([data-drag-over='before'])::before {\n content: '';\n position: absolute;\n top: -1px;\n inset-inline-start: var(--label-offset, 0);\n inset-inline-end: 0;\n height: 2px;\n background-color: var(--mantine-primary-color-filled);\n pointer-events: none;\n z-index: 1;\n }\n\n &:where([data-drag-over='after'])::after {\n content: '';\n position: absolute;\n bottom: -1px;\n inset-inline-start: var(--label-offset, 0);\n inset-inline-end: 0;\n height: 2px;\n background-color: var(--mantine-primary-color-filled);\n pointer-events: none;\n z-index: 1;\n }\n\n &:where([data-drag-over='inside']) {\n background-color: var(--mantine-primary-color-light);\n }\n}\n\n:where([data-with-lines]) {\n .node {\n position: relative;\n }\n\n /* Horizontal connector at the node's own level — applies to both nested and flat layouts */\n .node:not([data-level='1'])::before {\n content: '';\n position: absolute;\n top: rem(12px);\n inset-inline-start: calc(var(--label-offset) - var(--level-offset) / 2);\n width: calc(var(--level-offset) / 2);\n height: 0;\n border-top: var(--tree-line-width) solid var(--tree-line-color);\n pointer-events: none;\n z-index: 1;\n }\n\n /* Vertical line for nested layout (regular Tree): the line spans the parent <li>'s\n full height — including descendants — so ancestor columns stay continuous. */\n .subtree > .node {\n &::after {\n content: '';\n position: absolute;\n top: 0;\n bottom: 0;\n inset-inline-start: calc(var(--label-offset) - var(--level-offset) / 2);\n width: 0;\n border-inline-start: var(--tree-line-width) solid var(--tree-line-color);\n pointer-events: none;\n z-index: 1;\n }\n\n &:last-child::after {\n bottom: auto;\n height: rem(12px);\n }\n }\n\n .node:where([data-dragging]) {\n &::before,\n &::after {\n display: none;\n }\n\n .flatLine {\n display: none;\n }\n }\n}\n\n/* Vertical line markers rendered as DOM children by `FlatTreeNode` for flat layouts\n (e.g. virtualized trees) where ::after on a single node can't span ancestor rows.\n Each marker is positioned at column `--flat-line-column` and is only visible\n inside a `[data-with-lines]` tree. */\n.flatLine {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 0;\n inset-inline-start: calc((var(--flat-line-column) - 1.5) * var(--level-offset));\n border-inline-start: var(--tree-line-width) solid var(--tree-line-color);\n pointer-events: none;\n z-index: 1;\n display: none;\n}\n\n:where([data-with-lines]) .flatLine {\n display: block;\n}\n\n.flatLineClosing {\n bottom: auto;\n height: rem(12px);\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"Tree.module.mjs","names":[],"sources":["../../../src/components/Tree/Tree.module.css"],"sourcesContent":[":where([data-tree-root]) {\n --level-offset: var(--mantine-spacing-lg);\n --tree-line-width: rem(1px);\n --tree-line-color: var(--mantine-color-default-border);\n}\n\n.root {\n margin: 0;\n padding: 0;\n user-select: none;\n}\n\n.subtree {\n margin: 0;\n padding: 0;\n}\n\n.node {\n cursor: pointer;\n list-style: none;\n margin: 0;\n padding: 0;\n outline: 0;\n\n &:focus-visible,\n &[data-focus-ring]:focus {\n > .label {\n outline: 2px solid var(--mantine-primary-color-filled);\n outline-offset: 2px;\n }\n }\n}\n\n.label {\n position: relative;\n padding-inline-start: var(--label-offset);\n\n &:where([data-selected]) {\n @mixin where-light {\n background-color: var(--mantine-color-gray-1);\n }\n\n @mixin where-dark {\n background-color: var(--mantine-color-dark-5);\n }\n }\n\n &:where([data-dragging]) {\n opacity: 0.4;\n }\n\n &:where([data-drag-over='before'])::before {\n content: '';\n position: absolute;\n top: -1px;\n inset-inline-start: var(--label-offset, 0);\n inset-inline-end: 0;\n height: 2px;\n background-color: var(--mantine-primary-color-filled);\n pointer-events: none;\n z-index: 1;\n }\n\n &:where([data-drag-over='after'])::after {\n content: '';\n position: absolute;\n bottom: -1px;\n inset-inline-start: var(--label-offset, 0);\n inset-inline-end: 0;\n height: 2px;\n background-color: var(--mantine-primary-color-filled);\n pointer-events: none;\n z-index: 1;\n }\n\n &:where([data-drag-over='inside']) {\n background-color: var(--mantine-primary-color-light);\n }\n}\n\n:where([data-with-lines]) {\n .node {\n position: relative;\n }\n\n /* Horizontal connector at the node's own level — applies to both nested and flat layouts */\n .node:not([data-level='1'])::before {\n content: '';\n position: absolute;\n top: rem(12px);\n inset-inline-start: calc(var(--label-offset) - var(--level-offset) / 2);\n width: calc(var(--level-offset) / 2);\n height: 0;\n border-top: var(--tree-line-width) solid var(--tree-line-color);\n pointer-events: none;\n z-index: 1;\n }\n\n /* Vertical line for nested layout (regular Tree): the line spans the parent <li>'s\n full height — including descendants — so ancestor columns stay continuous. */\n .subtree > .node {\n &::after {\n content: '';\n position: absolute;\n top: 0;\n bottom: 0;\n inset-inline-start: calc(var(--label-offset) - var(--level-offset) / 2);\n width: 0;\n border-inline-start: var(--tree-line-width) solid var(--tree-line-color);\n pointer-events: none;\n z-index: 1;\n }\n\n &:last-child::after {\n bottom: auto;\n height: rem(12px);\n }\n }\n\n .node:where([data-dragging]) {\n &::before,\n &::after {\n display: none;\n }\n\n .flatLine {\n display: none;\n }\n }\n}\n\n/* Vertical line markers rendered as DOM children by `FlatTreeNode` for flat layouts\n (e.g. virtualized trees) where ::after on a single node can't span ancestor rows.\n Each marker is positioned at column `--flat-line-column` and is only visible\n inside a `[data-with-lines]` tree. */\n.flatLine {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 0;\n inset-inline-start: calc((var(--flat-line-column) - 1.5) * var(--level-offset));\n border-inline-start: var(--tree-line-width) solid var(--tree-line-color);\n pointer-events: none;\n z-index: 1;\n display: none;\n}\n\n:where([data-with-lines]) .flatLine {\n display: block;\n}\n\n.flatLineClosing {\n bottom: auto;\n height: rem(12px);\n}\n"],"mappings":""}
|
|
@@ -23,7 +23,7 @@ function isVisibleTreeNode(node, root) {
|
|
|
23
23
|
}
|
|
24
24
|
function TreeNode({ node, getStyles, rootIndex, controller, expandOnClick, selectOnClick, isSubtree, level = 1, renderNode, flatValues, allowRangeSelection, expandOnSpace, checkOnSpace, keepMounted, onDragDrop, allowDrop, withDragHandle, dragStateRef, data }) {
|
|
25
25
|
const ref = useRef(null);
|
|
26
|
-
const hasLoadedChildren = Array.isArray(node.children);
|
|
26
|
+
const hasLoadedChildren = Array.isArray(node.children) && node.children.length > 0;
|
|
27
27
|
const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;
|
|
28
28
|
const hasChildren = hasLoadedChildren || hasAsyncChildren;
|
|
29
29
|
const isLoading = controller.isNodeLoading(node.value);
|
|
@@ -64,14 +64,21 @@ function TreeNode({ node, getStyles, rootIndex, controller, expandOnClick, selec
|
|
|
64
64
|
if (event.nativeEvent.code === "ArrowRight") {
|
|
65
65
|
event.stopPropagation();
|
|
66
66
|
event.preventDefault();
|
|
67
|
-
if (isExpanded)
|
|
68
|
-
|
|
67
|
+
if (isExpanded) {
|
|
68
|
+
const nextNode = event.currentTarget.querySelector("[role=treeitem]");
|
|
69
|
+
nextNode?.setAttribute("data-focus-ring", "true");
|
|
70
|
+
nextNode?.focus();
|
|
71
|
+
} else controller.expand(node.value);
|
|
69
72
|
}
|
|
70
73
|
if (event.nativeEvent.code === "ArrowLeft") {
|
|
71
74
|
event.stopPropagation();
|
|
72
75
|
event.preventDefault();
|
|
73
76
|
if (isExpanded && hasChildren) controller.collapse(node.value);
|
|
74
|
-
else if (isSubtree)
|
|
77
|
+
else if (isSubtree) {
|
|
78
|
+
const parentNode = findElementAncestor(event.currentTarget, "[role=treeitem]");
|
|
79
|
+
parentNode?.setAttribute("data-focus-ring", "true");
|
|
80
|
+
parentNode?.focus();
|
|
81
|
+
}
|
|
75
82
|
}
|
|
76
83
|
if (event.nativeEvent.code === "ArrowDown" || event.nativeEvent.code === "ArrowUp") {
|
|
77
84
|
const root = findElementAncestor(event.currentTarget, "[data-tree-root]");
|
|
@@ -82,7 +89,9 @@ function TreeNode({ node, getStyles, rootIndex, controller, expandOnClick, selec
|
|
|
82
89
|
const index = nodes.indexOf(event.currentTarget);
|
|
83
90
|
if (index === -1) return;
|
|
84
91
|
const nextIndex = event.nativeEvent.code === "ArrowDown" ? index + 1 : index - 1;
|
|
85
|
-
nodes[nextIndex]
|
|
92
|
+
const nextNode = nodes[nextIndex];
|
|
93
|
+
nextNode?.setAttribute("data-focus-ring", "true");
|
|
94
|
+
nextNode?.focus();
|
|
86
95
|
if (event.shiftKey) {
|
|
87
96
|
const selectNode = nodes[nextIndex];
|
|
88
97
|
if (selectNode) controller.setSelectedState(getValuesRange(controller.anchorNode, selectNode.dataset.value, flatValues));
|
|
@@ -130,6 +139,9 @@ function TreeNode({ node, getStyles, rootIndex, controller, expandOnClick, selec
|
|
|
130
139
|
"data-level": level,
|
|
131
140
|
tabIndex: rootIndex === 0 ? 0 : -1,
|
|
132
141
|
onKeyDown: handleKeyDown,
|
|
142
|
+
onBlur: (event) => {
|
|
143
|
+
if (!event.currentTarget.contains(event.relatedTarget)) event.currentTarget.removeAttribute("data-focus-ring");
|
|
144
|
+
},
|
|
133
145
|
ref,
|
|
134
146
|
children: [
|
|
135
147
|
typeof renderNode === "function" ? renderNode({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeNode.mjs","names":[],"sources":["../../../src/components/Tree/TreeNode.tsx"],"sourcesContent":["import { Activity, useRef } from 'react';\nimport { Box, findElementAncestor, GetStylesApi } from '../../core';\nimport { Loader } from '../Loader';\nimport type { TreeDragDropPayload } from './move-tree-node/move-tree-node';\nimport type { RenderNode, TreeDragState, TreeFactory, TreeNodeData } from './Tree';\nimport type { TreeController } from './use-tree';\nimport { TreeAllowDrop, useTreeNodeDragDrop } from './use-tree-node-drag-drop';\n\nfunction getValuesRange(anchor: string | null, value: string | undefined, flatValues: string[]) {\n if (!anchor || !value) {\n return [];\n }\n\n const anchorIndex = flatValues.indexOf(anchor);\n const valueIndex = flatValues.indexOf(value);\n const start = Math.min(anchorIndex, valueIndex);\n const end = Math.max(anchorIndex, valueIndex);\n\n return flatValues.slice(start, end + 1);\n}\n\nfunction isVisibleTreeNode(node: HTMLElement, root: Element) {\n for (let current: HTMLElement | null = node; current && current !== root; ) {\n if (current.style.display === 'none') {\n return false;\n }\n current = current.parentElement;\n }\n\n return true;\n}\n\ninterface TreeNodeProps {\n node: TreeNodeData;\n getStyles: GetStylesApi<TreeFactory>;\n rootIndex: number | undefined;\n controller: TreeController;\n expandOnClick: boolean | undefined;\n flatValues: string[];\n isSubtree?: boolean;\n level?: number;\n renderNode: RenderNode | undefined;\n selectOnClick: boolean | undefined;\n allowRangeSelection: boolean | undefined;\n expandOnSpace: boolean | undefined;\n checkOnSpace: boolean | undefined;\n keepMounted: boolean | undefined;\n onDragDrop: ((payload: TreeDragDropPayload) => void) | undefined;\n allowDrop: TreeAllowDrop | undefined;\n withDragHandle: boolean | undefined;\n dragStateRef: React.RefObject<TreeDragState>;\n data: TreeNodeData[];\n}\n\nexport function TreeNode({\n node,\n getStyles,\n rootIndex,\n controller,\n expandOnClick,\n selectOnClick,\n isSubtree,\n level = 1,\n renderNode,\n flatValues,\n allowRangeSelection,\n expandOnSpace,\n checkOnSpace,\n keepMounted,\n onDragDrop,\n allowDrop,\n withDragHandle,\n dragStateRef,\n data,\n}: TreeNodeProps) {\n const ref = useRef<HTMLLIElement>(null);\n const hasLoadedChildren = Array.isArray(node.children);\n const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;\n const hasChildren = hasLoadedChildren || hasAsyncChildren;\n const isLoading = controller.isNodeLoading(node.value);\n const loadError = controller.getNodeLoadError(node.value);\n const isExpanded = controller.expandedState[node.value] || false;\n\n const nested = (node.children || []).map((child) => (\n <TreeNode\n key={child.value}\n node={child}\n flatValues={flatValues}\n getStyles={getStyles}\n rootIndex={undefined}\n level={level + 1}\n controller={controller}\n expandOnClick={expandOnClick}\n isSubtree\n renderNode={renderNode}\n selectOnClick={selectOnClick}\n allowRangeSelection={allowRangeSelection}\n expandOnSpace={expandOnSpace}\n checkOnSpace={checkOnSpace}\n keepMounted={keepMounted}\n onDragDrop={onDragDrop}\n allowDrop={allowDrop}\n withDragHandle={withDragHandle}\n dragStateRef={dragStateRef}\n data={data}\n />\n ));\n\n const { elementProps: dragElementProps, dragHandleProps } = useTreeNodeDragDrop({\n nodeValue: node.value,\n hasChildren,\n isExpanded,\n data,\n onDragDrop,\n dragStateRef,\n allowDrop,\n withDragHandle,\n });\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.nativeEvent.code === 'ArrowRight') {\n event.stopPropagation();\n event.preventDefault();\n\n if (isExpanded) {\n event.currentTarget.querySelector<HTMLLIElement>('[role=treeitem]')?.focus();\n } else {\n controller.expand(node.value);\n }\n }\n\n if (event.nativeEvent.code === 'ArrowLeft') {\n event.stopPropagation();\n event.preventDefault();\n if (isExpanded && hasChildren) {\n controller.collapse(node.value);\n } else if (isSubtree) {\n findElementAncestor(event.currentTarget as HTMLElement, '[role=treeitem]')?.focus();\n }\n }\n\n if (event.nativeEvent.code === 'ArrowDown' || event.nativeEvent.code === 'ArrowUp') {\n const root = findElementAncestor(event.currentTarget as HTMLElement, '[data-tree-root]');\n\n if (!root) {\n return;\n }\n\n event.stopPropagation();\n event.preventDefault();\n const nodes = Array.from(root.querySelectorAll<HTMLLIElement>('[role=treeitem]')).filter(\n (treeNode) => isVisibleTreeNode(treeNode, root)\n );\n const index = nodes.indexOf(event.currentTarget as HTMLLIElement);\n\n if (index === -1) {\n return;\n }\n\n const nextIndex = event.nativeEvent.code === 'ArrowDown' ? index + 1 : index - 1;\n nodes[nextIndex]?.focus();\n\n if (event.shiftKey) {\n const selectNode = nodes[nextIndex];\n\n if (selectNode) {\n controller.setSelectedState(\n getValuesRange(controller.anchorNode, selectNode.dataset.value, flatValues)\n );\n }\n }\n }\n\n if (event.nativeEvent.code === 'Space') {\n if (expandOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n controller.toggleExpanded(node.value);\n }\n\n if (checkOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n controller.isNodeChecked(node.value)\n ? controller.uncheckNode(node.value)\n : controller.checkNode(node.value);\n }\n }\n };\n\n const handleNodeClick = (event: React.MouseEvent) => {\n event.stopPropagation();\n\n if (allowRangeSelection && event.shiftKey && controller.anchorNode) {\n controller.setSelectedState(getValuesRange(controller.anchorNode, node.value, flatValues));\n ref.current?.focus();\n } else {\n if (expandOnClick) {\n controller.toggleExpanded(node.value);\n }\n\n selectOnClick && controller.select(node.value);\n ref.current?.focus();\n }\n };\n\n const selected = controller.selectedState.includes(node.value);\n const elementProps = {\n ...getStyles('label'),\n onClick: handleNodeClick,\n 'data-selected': selected || undefined,\n 'data-value': node.value,\n ...dragElementProps,\n };\n\n const withLoadingIndicator = isExpanded && isLoading && nested.length === 0;\n\n return (\n <li\n {...getStyles('node', {\n style: { '--label-offset': `calc(var(--level-offset) * ${level - 1})` },\n })}\n role=\"treeitem\"\n aria-selected={selected}\n data-value={node.value}\n data-selected={selected || undefined}\n data-level={level}\n tabIndex={rootIndex === 0 ? 0 : -1}\n onKeyDown={handleKeyDown}\n ref={ref}\n >\n {typeof renderNode === 'function' ? (\n renderNode({\n node,\n level,\n selected,\n isRoot: level === 1,\n tree: controller,\n expanded: isExpanded,\n hasChildren,\n isLoading,\n loadError,\n elementProps,\n dragHandleProps,\n })\n ) : (\n <div {...elementProps}>{node.label}</div>\n )}\n\n {withLoadingIndicator && (\n <Box component=\"ul\" role=\"group\" {...getStyles('subtree')} data-level={level}>\n <li\n {...getStyles('node', {\n style: { '--label-offset': `calc(var(--level-offset) * ${level})` },\n })}\n >\n <div {...getStyles('label')}>\n <Loader size={16} style={{ marginInlineStart: 4 }} />\n </div>\n </li>\n </Box>\n )}\n\n {keepMounted && nested.length > 0 ? (\n <Activity mode={isExpanded ? 'visible' : 'hidden'}>\n <Box component=\"ul\" role=\"group\" {...getStyles('subtree')} data-level={level}>\n {nested}\n </Box>\n </Activity>\n ) : (\n isExpanded &&\n nested.length > 0 && (\n <Box component=\"ul\" role=\"group\" {...getStyles('subtree')} data-level={level}>\n {nested}\n </Box>\n )\n )}\n </li>\n );\n}\n\nTreeNode.displayName = '@mantine/core/TreeNode';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TreeNode.mjs","names":[],"sources":["../../../src/components/Tree/TreeNode.tsx"],"sourcesContent":["import { Activity, useRef } from 'react';\nimport { Box, findElementAncestor, GetStylesApi } from '../../core';\nimport { Loader } from '../Loader';\nimport type { TreeDragDropPayload } from './move-tree-node/move-tree-node';\nimport type { RenderNode, TreeDragState, TreeFactory, TreeNodeData } from './Tree';\nimport type { TreeController } from './use-tree';\nimport { TreeAllowDrop, useTreeNodeDragDrop } from './use-tree-node-drag-drop';\n\nfunction getValuesRange(anchor: string | null, value: string | undefined, flatValues: string[]) {\n if (!anchor || !value) {\n return [];\n }\n\n const anchorIndex = flatValues.indexOf(anchor);\n const valueIndex = flatValues.indexOf(value);\n const start = Math.min(anchorIndex, valueIndex);\n const end = Math.max(anchorIndex, valueIndex);\n\n return flatValues.slice(start, end + 1);\n}\n\nfunction isVisibleTreeNode(node: HTMLElement, root: Element) {\n for (let current: HTMLElement | null = node; current && current !== root; ) {\n if (current.style.display === 'none') {\n return false;\n }\n current = current.parentElement;\n }\n\n return true;\n}\n\ninterface TreeNodeProps {\n node: TreeNodeData;\n getStyles: GetStylesApi<TreeFactory>;\n rootIndex: number | undefined;\n controller: TreeController;\n expandOnClick: boolean | undefined;\n flatValues: string[];\n isSubtree?: boolean;\n level?: number;\n renderNode: RenderNode | undefined;\n selectOnClick: boolean | undefined;\n allowRangeSelection: boolean | undefined;\n expandOnSpace: boolean | undefined;\n checkOnSpace: boolean | undefined;\n keepMounted: boolean | undefined;\n onDragDrop: ((payload: TreeDragDropPayload) => void) | undefined;\n allowDrop: TreeAllowDrop | undefined;\n withDragHandle: boolean | undefined;\n dragStateRef: React.RefObject<TreeDragState>;\n data: TreeNodeData[];\n}\n\nexport function TreeNode({\n node,\n getStyles,\n rootIndex,\n controller,\n expandOnClick,\n selectOnClick,\n isSubtree,\n level = 1,\n renderNode,\n flatValues,\n allowRangeSelection,\n expandOnSpace,\n checkOnSpace,\n keepMounted,\n onDragDrop,\n allowDrop,\n withDragHandle,\n dragStateRef,\n data,\n}: TreeNodeProps) {\n const ref = useRef<HTMLLIElement>(null);\n const hasLoadedChildren = Array.isArray(node.children) && node.children.length > 0;\n const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;\n const hasChildren = hasLoadedChildren || hasAsyncChildren;\n const isLoading = controller.isNodeLoading(node.value);\n const loadError = controller.getNodeLoadError(node.value);\n const isExpanded = controller.expandedState[node.value] || false;\n\n const nested = (node.children || []).map((child) => (\n <TreeNode\n key={child.value}\n node={child}\n flatValues={flatValues}\n getStyles={getStyles}\n rootIndex={undefined}\n level={level + 1}\n controller={controller}\n expandOnClick={expandOnClick}\n isSubtree\n renderNode={renderNode}\n selectOnClick={selectOnClick}\n allowRangeSelection={allowRangeSelection}\n expandOnSpace={expandOnSpace}\n checkOnSpace={checkOnSpace}\n keepMounted={keepMounted}\n onDragDrop={onDragDrop}\n allowDrop={allowDrop}\n withDragHandle={withDragHandle}\n dragStateRef={dragStateRef}\n data={data}\n />\n ));\n\n const { elementProps: dragElementProps, dragHandleProps } = useTreeNodeDragDrop({\n nodeValue: node.value,\n hasChildren,\n isExpanded,\n data,\n onDragDrop,\n dragStateRef,\n allowDrop,\n withDragHandle,\n });\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.nativeEvent.code === 'ArrowRight') {\n event.stopPropagation();\n event.preventDefault();\n\n if (isExpanded) {\n const nextNode = event.currentTarget.querySelector<HTMLLIElement>('[role=treeitem]');\n nextNode?.setAttribute('data-focus-ring', 'true');\n nextNode?.focus();\n } else {\n controller.expand(node.value);\n }\n }\n\n if (event.nativeEvent.code === 'ArrowLeft') {\n event.stopPropagation();\n event.preventDefault();\n if (isExpanded && hasChildren) {\n controller.collapse(node.value);\n } else if (isSubtree) {\n const parentNode = findElementAncestor(\n event.currentTarget as HTMLElement,\n '[role=treeitem]'\n );\n parentNode?.setAttribute('data-focus-ring', 'true');\n parentNode?.focus();\n }\n }\n\n if (event.nativeEvent.code === 'ArrowDown' || event.nativeEvent.code === 'ArrowUp') {\n const root = findElementAncestor(event.currentTarget as HTMLElement, '[data-tree-root]');\n\n if (!root) {\n return;\n }\n\n event.stopPropagation();\n event.preventDefault();\n const nodes = Array.from(root.querySelectorAll<HTMLLIElement>('[role=treeitem]')).filter(\n (treeNode) => isVisibleTreeNode(treeNode, root)\n );\n const index = nodes.indexOf(event.currentTarget as HTMLLIElement);\n\n if (index === -1) {\n return;\n }\n\n const nextIndex = event.nativeEvent.code === 'ArrowDown' ? index + 1 : index - 1;\n const nextNode = nodes[nextIndex];\n nextNode?.setAttribute('data-focus-ring', 'true');\n nextNode?.focus();\n\n if (event.shiftKey) {\n const selectNode = nodes[nextIndex];\n\n if (selectNode) {\n controller.setSelectedState(\n getValuesRange(controller.anchorNode, selectNode.dataset.value, flatValues)\n );\n }\n }\n }\n\n if (event.nativeEvent.code === 'Space') {\n if (expandOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n controller.toggleExpanded(node.value);\n }\n\n if (checkOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n controller.isNodeChecked(node.value)\n ? controller.uncheckNode(node.value)\n : controller.checkNode(node.value);\n }\n }\n };\n\n const handleNodeClick = (event: React.MouseEvent) => {\n event.stopPropagation();\n\n if (allowRangeSelection && event.shiftKey && controller.anchorNode) {\n controller.setSelectedState(getValuesRange(controller.anchorNode, node.value, flatValues));\n ref.current?.focus();\n } else {\n if (expandOnClick) {\n controller.toggleExpanded(node.value);\n }\n\n selectOnClick && controller.select(node.value);\n ref.current?.focus();\n }\n };\n\n const selected = controller.selectedState.includes(node.value);\n const elementProps = {\n ...getStyles('label'),\n onClick: handleNodeClick,\n 'data-selected': selected || undefined,\n 'data-value': node.value,\n ...dragElementProps,\n };\n\n const withLoadingIndicator = isExpanded && isLoading && nested.length === 0;\n\n return (\n <li\n {...getStyles('node', {\n style: { '--label-offset': `calc(var(--level-offset) * ${level - 1})` },\n })}\n role=\"treeitem\"\n aria-selected={selected}\n data-value={node.value}\n data-selected={selected || undefined}\n data-level={level}\n tabIndex={rootIndex === 0 ? 0 : -1}\n onKeyDown={handleKeyDown}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget as HTMLElement)) {\n event.currentTarget.removeAttribute('data-focus-ring');\n }\n }}\n ref={ref}\n >\n {typeof renderNode === 'function' ? (\n renderNode({\n node,\n level,\n selected,\n isRoot: level === 1,\n tree: controller,\n expanded: isExpanded,\n hasChildren,\n isLoading,\n loadError,\n elementProps,\n dragHandleProps,\n })\n ) : (\n <div {...elementProps}>{node.label}</div>\n )}\n\n {withLoadingIndicator && (\n <Box component=\"ul\" role=\"group\" {...getStyles('subtree')} data-level={level}>\n <li\n {...getStyles('node', {\n style: { '--label-offset': `calc(var(--level-offset) * ${level})` },\n })}\n >\n <div {...getStyles('label')}>\n <Loader size={16} style={{ marginInlineStart: 4 }} />\n </div>\n </li>\n </Box>\n )}\n\n {keepMounted && nested.length > 0 ? (\n <Activity mode={isExpanded ? 'visible' : 'hidden'}>\n <Box component=\"ul\" role=\"group\" {...getStyles('subtree')} data-level={level}>\n {nested}\n </Box>\n </Activity>\n ) : (\n isExpanded &&\n nested.length > 0 && (\n <Box component=\"ul\" role=\"group\" {...getStyles('subtree')} data-level={level}>\n {nested}\n </Box>\n )\n )}\n </li>\n );\n}\n\nTreeNode.displayName = '@mantine/core/TreeNode';\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ function flattenTreeDataTo(acc, data, expandedState, parent, level, ancestorIsLa
|
|
|
4
4
|
for (let i = 0; i < data.length; i++) {
|
|
5
5
|
const node = data[i];
|
|
6
6
|
const isLast = i === data.length - 1;
|
|
7
|
-
const hasLoadedChildren = Array.isArray(node.children);
|
|
7
|
+
const hasLoadedChildren = Array.isArray(node.children) && node.children.length > 0;
|
|
8
8
|
const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;
|
|
9
9
|
const hasChildren = hasLoadedChildren || hasAsyncChildren;
|
|
10
10
|
const expanded = expandedState[node.value] || false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flatten-tree-data.mjs","names":[],"sources":["../../../../src/components/Tree/flatten-tree-data/flatten-tree-data.ts"],"sourcesContent":["import type { TreeNodeData } from '../Tree';\nimport type { TreeExpandedState } from '../use-tree';\n\nexport type FlatTreeLineState = 'continuing' | 'closing' | 'none';\n\nexport interface FlattenedTreeNodeData {\n /** Node data from tree data */\n node: TreeNodeData;\n\n /** Nesting level of the node, starts at 1 */\n level: number;\n\n /** Value of the parent node, `null` for root nodes */\n parent: string | null;\n\n /** Whether the node has children */\n hasChildren: boolean;\n\n /** Whether the node is expanded */\n expanded: boolean;\n\n /** For each level from 2 to this node's `level`, indicates whether a connector\n * line should be drawn at that column for this row:\n * - `'continuing'`: full vertical line passes through this row\n * - `'closing'`: line ends at this row (truncated to the connector level)\n * - `'none'`: no line at this column for this row\n *\n * Index 0 corresponds to level 2, index 1 to level 3, etc.\n * Empty for level-1 (root) nodes. */\n linesPath: FlatTreeLineState[];\n}\n\nfunction flattenTreeDataTo(\n acc: FlattenedTreeNodeData[],\n data: TreeNodeData[],\n expandedState: TreeExpandedState,\n parent: string | null,\n level: number,\n ancestorIsLast: boolean[]\n): void {\n for (let i = 0; i < data.length; i++) {\n const node = data[i];\n const isLast = i === data.length - 1;\n const hasLoadedChildren = Array.isArray(node.children);\n const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;\n const hasChildren = hasLoadedChildren || hasAsyncChildren;\n const expanded = expandedState[node.value] || false;\n\n const linesPath: FlatTreeLineState[] = [];\n for (let l = 2; l <= level; l++) {\n if (l === level) {\n linesPath.push(isLast ? 'closing' : 'continuing');\n } else {\n linesPath.push(ancestorIsLast[l - 1] ? 'none' : 'continuing');\n }\n }\n\n acc.push({ node, level, parent, hasChildren, expanded, linesPath });\n\n if (expanded && hasLoadedChildren) {\n flattenTreeDataTo(acc, node.children!, expandedState, node.value, level + 1, [\n ...ancestorIsLast,\n isLast,\n ]);\n }\n }\n}\n\nexport function flattenTreeData(\n data: TreeNodeData[],\n expandedState: TreeExpandedState\n): FlattenedTreeNodeData[] {\n const result: FlattenedTreeNodeData[] = [];\n flattenTreeDataTo(result, data, expandedState, null, 1, []);\n return result;\n}\n"],"mappings":";;AAgCA,SAAS,kBACP,KACA,MACA,eACA,QACA,OACA,gBACM;CACN,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,OAAO,KAAK;EAClB,MAAM,SAAS,MAAM,KAAK,SAAS;EACnC,MAAM,oBAAoB,MAAM,QAAQ,KAAK,QAAQ;
|
|
1
|
+
{"version":3,"file":"flatten-tree-data.mjs","names":[],"sources":["../../../../src/components/Tree/flatten-tree-data/flatten-tree-data.ts"],"sourcesContent":["import type { TreeNodeData } from '../Tree';\nimport type { TreeExpandedState } from '../use-tree';\n\nexport type FlatTreeLineState = 'continuing' | 'closing' | 'none';\n\nexport interface FlattenedTreeNodeData {\n /** Node data from tree data */\n node: TreeNodeData;\n\n /** Nesting level of the node, starts at 1 */\n level: number;\n\n /** Value of the parent node, `null` for root nodes */\n parent: string | null;\n\n /** Whether the node has children */\n hasChildren: boolean;\n\n /** Whether the node is expanded */\n expanded: boolean;\n\n /** For each level from 2 to this node's `level`, indicates whether a connector\n * line should be drawn at that column for this row:\n * - `'continuing'`: full vertical line passes through this row\n * - `'closing'`: line ends at this row (truncated to the connector level)\n * - `'none'`: no line at this column for this row\n *\n * Index 0 corresponds to level 2, index 1 to level 3, etc.\n * Empty for level-1 (root) nodes. */\n linesPath: FlatTreeLineState[];\n}\n\nfunction flattenTreeDataTo(\n acc: FlattenedTreeNodeData[],\n data: TreeNodeData[],\n expandedState: TreeExpandedState,\n parent: string | null,\n level: number,\n ancestorIsLast: boolean[]\n): void {\n for (let i = 0; i < data.length; i++) {\n const node = data[i];\n const isLast = i === data.length - 1;\n const hasLoadedChildren = Array.isArray(node.children) && node.children.length > 0;\n const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;\n const hasChildren = hasLoadedChildren || hasAsyncChildren;\n const expanded = expandedState[node.value] || false;\n\n const linesPath: FlatTreeLineState[] = [];\n for (let l = 2; l <= level; l++) {\n if (l === level) {\n linesPath.push(isLast ? 'closing' : 'continuing');\n } else {\n linesPath.push(ancestorIsLast[l - 1] ? 'none' : 'continuing');\n }\n }\n\n acc.push({ node, level, parent, hasChildren, expanded, linesPath });\n\n if (expanded && hasLoadedChildren) {\n flattenTreeDataTo(acc, node.children!, expandedState, node.value, level + 1, [\n ...ancestorIsLast,\n isLast,\n ]);\n }\n }\n}\n\nexport function flattenTreeData(\n data: TreeNodeData[],\n expandedState: TreeExpandedState\n): FlattenedTreeNodeData[] {\n const result: FlattenedTreeNodeData[] = [];\n flattenTreeDataTo(result, data, expandedState, null, 1, []);\n return result;\n}\n"],"mappings":";;AAgCA,SAAS,kBACP,KACA,MACA,eACA,QACA,OACA,gBACM;CACN,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,OAAO,KAAK;EAClB,MAAM,SAAS,MAAM,KAAK,SAAS;EACnC,MAAM,oBAAoB,MAAM,QAAQ,KAAK,QAAQ,KAAK,KAAK,SAAS,SAAS;EACjF,MAAM,mBAAmB,CAAC,CAAC,KAAK,eAAe,CAAC;EAChD,MAAM,cAAc,qBAAqB;EACzC,MAAM,WAAW,cAAc,KAAK,UAAU;EAE9C,MAAM,YAAiC,CAAC;EACxC,KAAK,IAAI,IAAI,GAAG,KAAK,OAAO,KAC1B,IAAI,MAAM,OACR,UAAU,KAAK,SAAS,YAAY,YAAY;OAEhD,UAAU,KAAK,eAAe,IAAI,KAAK,SAAS,YAAY;EAIhE,IAAI,KAAK;GAAE;GAAM;GAAO;GAAQ;GAAa;GAAU;EAAU,CAAC;EAElE,IAAI,YAAY,mBACd,kBAAkB,KAAK,KAAK,UAAW,eAAe,KAAK,OAAO,QAAQ,GAAG,CAC3E,GAAG,gBACH,MACF,CAAC;CAEL;AACF;AAEA,SAAgB,gBACd,MACA,eACyB;CACzB,MAAM,SAAkC,CAAC;CACzC,kBAAkB,QAAQ,MAAM,eAAe,MAAM,GAAG,CAAC,CAAC;CAC1D,OAAO;AACT"}
|
|
@@ -13,8 +13,9 @@ const OPTION_GAP = 6;
|
|
|
13
13
|
function TreeSelectOption({ node, level, expanded, hasChildren, selected, checked, indeterminate, showCheckbox, isLastChild, lineGuides, withLines, onToggleExpand, renderNode, chevronAriaLabels }) {
|
|
14
14
|
const indentPx = (level - 1) * LEVEL_OFFSET;
|
|
15
15
|
const handleExpandClick = (event) => {
|
|
16
|
-
event
|
|
17
|
-
event
|
|
16
|
+
event?.stopPropagation();
|
|
17
|
+
event?.preventDefault();
|
|
18
|
+
if (!hasChildren) return;
|
|
18
19
|
onToggleExpand(node.value);
|
|
19
20
|
};
|
|
20
21
|
const handleExpandMouseDown = (event) => {
|
|
@@ -27,7 +28,8 @@ function TreeSelectOption({ node, level, expanded, hasChildren, selected, checke
|
|
|
27
28
|
hasChildren,
|
|
28
29
|
selected,
|
|
29
30
|
checked,
|
|
30
|
-
indeterminate
|
|
31
|
+
indeterminate,
|
|
32
|
+
expand: handleExpandClick
|
|
31
33
|
}) : null;
|
|
32
34
|
const lineElements = withLines && level > 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
33
35
|
lineGuides.map((show, g) => show ? /* @__PURE__ */ jsx("span", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeSelectOption.mjs","names":["classes"],"sources":["../../../src/components/TreeSelect/TreeSelectOption.tsx"],"sourcesContent":["import { AccordionChevron } from '../Accordion';\nimport { CheckboxIndicator } from '../Checkbox/CheckboxIndicator/CheckboxIndicator';\nimport { CheckIcon } from '../Checkbox/CheckIcon';\nimport { Combobox } from '../Combobox';\nimport type { TreeNodeData } from '../Tree';\nimport classes from './TreeSelect.module.css';\n\nconst LEVEL_OFFSET = 20;\nconst BASE_PADDING = 8;\nconst LINE_CONTENT_GAP = 5;\nconst OPTION_GAP = 6;\n\nexport interface TreeSelectChevronAriaLabels {\n /** aria-label for the expand button when the node is collapsed @default 'Expand' */\n expand?: string;\n\n /** aria-label for the expand button when the node is expanded @default 'Collapse' */\n collapse?: string;\n}\n\nexport interface TreeSelectOptionProps {\n node: TreeNodeData;\n level: number;\n expanded: boolean;\n hasChildren: boolean;\n selected: boolean;\n checked: boolean;\n indeterminate: boolean;\n showCheckbox: boolean;\n isLastChild: boolean;\n lineGuides: boolean[];\n withLines: boolean;\n onToggleExpand: (value: string) => void;\n renderNode?: (payload: TreeSelectRenderNodePayload) => React.ReactNode;\n chevronAriaLabels?: TreeSelectChevronAriaLabels;\n}\n\nexport interface TreeSelectRenderNodePayload {\n node: TreeNodeData;\n level: number;\n expanded: boolean;\n hasChildren: boolean;\n selected: boolean;\n checked: boolean;\n indeterminate: boolean;\n}\n\nexport function TreeSelectOption({\n node,\n level,\n expanded,\n hasChildren,\n selected,\n checked,\n indeterminate,\n showCheckbox,\n isLastChild,\n lineGuides,\n withLines,\n onToggleExpand,\n renderNode,\n chevronAriaLabels,\n}: TreeSelectOptionProps) {\n const indentPx = (level - 1) * LEVEL_OFFSET;\n\n const handleExpandClick = (event
|
|
1
|
+
{"version":3,"file":"TreeSelectOption.mjs","names":["classes"],"sources":["../../../src/components/TreeSelect/TreeSelectOption.tsx"],"sourcesContent":["import { AccordionChevron } from '../Accordion';\nimport { CheckboxIndicator } from '../Checkbox/CheckboxIndicator/CheckboxIndicator';\nimport { CheckIcon } from '../Checkbox/CheckIcon';\nimport { Combobox } from '../Combobox';\nimport type { TreeNodeData } from '../Tree';\nimport classes from './TreeSelect.module.css';\n\nconst LEVEL_OFFSET = 20;\nconst BASE_PADDING = 8;\nconst LINE_CONTENT_GAP = 5;\nconst OPTION_GAP = 6;\n\nexport interface TreeSelectChevronAriaLabels {\n /** aria-label for the expand button when the node is collapsed @default 'Expand' */\n expand?: string;\n\n /** aria-label for the expand button when the node is expanded @default 'Collapse' */\n collapse?: string;\n}\n\nexport interface TreeSelectOptionProps {\n node: TreeNodeData;\n level: number;\n expanded: boolean;\n hasChildren: boolean;\n selected: boolean;\n checked: boolean;\n indeterminate: boolean;\n showCheckbox: boolean;\n isLastChild: boolean;\n lineGuides: boolean[];\n withLines: boolean;\n onToggleExpand: (value: string) => void;\n renderNode?: (payload: TreeSelectRenderNodePayload) => React.ReactNode;\n chevronAriaLabels?: TreeSelectChevronAriaLabels;\n}\n\nexport interface TreeSelectRenderNodePayload {\n node: TreeNodeData;\n level: number;\n expanded: boolean;\n hasChildren: boolean;\n selected: boolean;\n checked: boolean;\n indeterminate: boolean;\n\n /** Toggles the expanded state of the node. Can be used to build a custom expand control\n * in `renderNode` without controlling the expanded state externally.\n * No-op for nodes without children. */\n expand: (event?: React.MouseEvent) => void;\n}\n\nexport function TreeSelectOption({\n node,\n level,\n expanded,\n hasChildren,\n selected,\n checked,\n indeterminate,\n showCheckbox,\n isLastChild,\n lineGuides,\n withLines,\n onToggleExpand,\n renderNode,\n chevronAriaLabels,\n}: TreeSelectOptionProps) {\n const indentPx = (level - 1) * LEVEL_OFFSET;\n\n const handleExpandClick = (event?: React.MouseEvent) => {\n event?.stopPropagation();\n event?.preventDefault();\n\n if (!hasChildren) {\n return;\n }\n\n onToggleExpand(node.value);\n };\n\n const handleExpandMouseDown = (event: React.MouseEvent) => {\n event.preventDefault();\n };\n\n const customContent = renderNode\n ? renderNode({\n node,\n level,\n expanded,\n hasChildren,\n selected,\n checked,\n indeterminate,\n expand: handleExpandClick,\n })\n : null;\n\n const lineElements =\n withLines && level > 1 ? (\n <>\n {lineGuides.map((show, g) =>\n show ? (\n <span\n key={`g${g}`}\n className={classes.guideLine}\n style={{ insetInlineStart: BASE_PADDING + (g + 1) * LEVEL_OFFSET - LEVEL_OFFSET / 2 }}\n />\n ) : null\n )}\n <span\n className={classes.branchVertical}\n data-last={isLastChild || undefined}\n style={{\n insetInlineStart: BASE_PADDING + (level - 1) * LEVEL_OFFSET - LEVEL_OFFSET / 2,\n }}\n />\n <span\n className={classes.branchHorizontal}\n style={{\n insetInlineStart: BASE_PADDING + (level - 1) * LEVEL_OFFSET - LEVEL_OFFSET / 2,\n width: LEVEL_OFFSET / 2,\n }}\n />\n </>\n ) : null;\n\n const isActive = selected || checked;\n const showCheckMark = !showCheckbox && isActive;\n\n const ariaChecked = showCheckbox ? (indeterminate && !checked ? 'mixed' : checked) : undefined;\n\n return (\n <Combobox.Option\n value={node.value}\n disabled={node.nodeProps?.disabled}\n active={isActive}\n className={classes.option}\n style={{\n paddingInlineStart:\n BASE_PADDING +\n indentPx +\n (withLines && level > 1 ? LINE_CONTENT_GAP : 0) +\n (!hasChildren ? OPTION_GAP : 0),\n }}\n aria-selected={isActive}\n aria-level={level}\n aria-expanded={hasChildren ? expanded : undefined}\n aria-checked={ariaChecked}\n >\n {lineElements}\n {customContent || (\n <>\n {hasChildren && (\n <span\n className={classes.expandIcon}\n data-expanded={expanded || undefined}\n onClick={handleExpandClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n handleExpandClick(e as any);\n }\n }}\n onMouseDown={handleExpandMouseDown}\n role=\"button\"\n tabIndex={-1}\n aria-label={\n expanded\n ? (chevronAriaLabels?.collapse ?? 'Collapse')\n : (chevronAriaLabels?.expand ?? 'Expand')\n }\n >\n <AccordionChevron size=\"80%\" />\n </span>\n )}\n {showCheckbox && (\n <CheckboxIndicator\n checked={checked || indeterminate}\n indeterminate={!checked && indeterminate}\n size=\"18px\"\n />\n )}\n <span className={classes.label}>{node.label}</span>\n {showCheckMark && <CheckIcon className={classes.checkIcon} />}\n </>\n )}\n </Combobox.Option>\n );\n}\n\nTreeSelectOption.displayName = '@mantine/core/TreeSelectOption';\n"],"mappings":";;;;;;;;AAOA,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,mBAAmB;AACzB,MAAM,aAAa;AA0CnB,SAAgB,iBAAiB,EAC/B,MACA,OACA,UACA,aACA,UACA,SACA,eACA,cACA,aACA,YACA,WACA,gBACA,YACA,qBACwB;CACxB,MAAM,YAAY,QAAQ,KAAK;CAE/B,MAAM,qBAAqB,UAA6B;EACtD,OAAO,gBAAgB;EACvB,OAAO,eAAe;EAEtB,IAAI,CAAC,aACH;EAGF,eAAe,KAAK,KAAK;CAC3B;CAEA,MAAM,yBAAyB,UAA4B;EACzD,MAAM,eAAe;CACvB;CAEA,MAAM,gBAAgB,aAClB,WAAW;EACT;EACA;EACA;EACA;EACA;EACA;EACA;EACA,QAAQ;CACV,CAAC,IACD;CAEJ,MAAM,eACJ,aAAa,QAAQ,IACnB,qBAAA,UAAA,EAAA,UAAA;EACG,WAAW,KAAK,MAAM,MACrB,OACE,oBAAC,QAAD;GAEE,WAAWA,0BAAQ;GACnB,OAAO,EAAE,kBAAkB,gBAAgB,IAAI,KAAK,eAAe,eAAe,EAAE;EACrF,GAHM,IAAI,GAGV,IACC,IACN;EACA,oBAAC,QAAD;GACE,WAAWA,0BAAQ;GACnB,aAAW,eAAe,KAAA;GAC1B,OAAO,EACL,kBAAkB,gBAAgB,QAAQ,KAAK,eAAe,eAAe,EAC/E;EACD,CAAA;EACD,oBAAC,QAAD;GACE,WAAWA,0BAAQ;GACnB,OAAO;IACL,kBAAkB,gBAAgB,QAAQ,KAAK,eAAe,eAAe;IAC7E,OAAO,eAAe;GACxB;EACD,CAAA;CACD,EAAA,CAAA,IACA;CAEN,MAAM,WAAW,YAAY;CAC7B,MAAM,gBAAgB,CAAC,gBAAgB;CAEvC,MAAM,cAAc,eAAgB,iBAAiB,CAAC,UAAU,UAAU,UAAW,KAAA;CAErF,OACE,qBAAC,SAAS,QAAV;EACE,OAAO,KAAK;EACZ,UAAU,KAAK,WAAW;EAC1B,QAAQ;EACR,WAAWA,0BAAQ;EACnB,OAAO,EACL,oBACE,eACA,YACC,aAAa,QAAQ,IAAI,mBAAmB,MAC5C,CAAC,cAAc,aAAa,GACjC;EACA,iBAAe;EACf,cAAY;EACZ,iBAAe,cAAc,WAAW,KAAA;EACxC,gBAAc;YAfhB,CAiBG,cACA,iBACC,qBAAA,UAAA,EAAA,UAAA;GACG,eACC,oBAAC,QAAD;IACE,WAAWA,0BAAQ;IACnB,iBAAe,YAAY,KAAA;IAC3B,SAAS;IACT,YAAY,MAAM;KAChB,IAAI,EAAE,QAAQ,SACZ,kBAAkB,CAAQ;IAE9B;IACA,aAAa;IACb,MAAK;IACL,UAAU;IACV,cACE,WACK,mBAAmB,YAAY,aAC/B,mBAAmB,UAAU;cAGpC,oBAAC,kBAAD,EAAkB,MAAK,MAAO,CAAA;GAC1B,CAAA;GAEP,gBACC,oBAAC,mBAAD;IACE,SAAS,WAAW;IACpB,eAAe,CAAC,WAAW;IAC3B,MAAK;GACN,CAAA;GAEH,oBAAC,QAAD;IAAM,WAAWA,0BAAQ;cAAQ,KAAK;GAAY,CAAA;GACjD,iBAAiB,oBAAC,WAAD,EAAW,WAAWA,0BAAQ,UAAY,CAAA;EAC5D,EAAA,CAAA,CAEW;;AAErB;AAEA,iBAAiB,cAAc"}
|
|
@@ -4,7 +4,7 @@ function flattenTo(acc, data, expandedState, parent, level, parentGuides) {
|
|
|
4
4
|
for (let i = 0; i < data.length; i++) {
|
|
5
5
|
const node = data[i];
|
|
6
6
|
const isLast = i === data.length - 1;
|
|
7
|
-
const hasLoadedChildren = Array.isArray(node.children);
|
|
7
|
+
const hasLoadedChildren = Array.isArray(node.children) && node.children.length > 0;
|
|
8
8
|
const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;
|
|
9
9
|
const hasChildren = hasLoadedChildren || hasAsyncChildren;
|
|
10
10
|
const expanded = expandedState[node.value] || false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flatten-tree-select-data.mjs","names":[],"sources":["../../../src/components/TreeSelect/flatten-tree-select-data.ts"],"sourcesContent":["import type { TreeNodeData } from '../Tree';\nimport type { TreeExpandedState } from '../Tree/use-tree';\n\nexport interface TreeSelectFlatNode {\n node: TreeNodeData;\n level: number;\n parent: string | null;\n hasChildren: boolean;\n expanded: boolean;\n isLastChild: boolean;\n lineGuides: boolean[];\n}\n\nfunction flattenTo(\n acc: TreeSelectFlatNode[],\n data: TreeNodeData[],\n expandedState: TreeExpandedState,\n parent: string | null,\n level: number,\n parentGuides: boolean[]\n): void {\n for (let i = 0; i < data.length; i++) {\n const node = data[i];\n const isLast = i === data.length - 1;\n const hasLoadedChildren = Array.isArray(node.children);\n const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;\n const hasChildren = hasLoadedChildren || hasAsyncChildren;\n const expanded = expandedState[node.value] || false;\n\n acc.push({\n node,\n level,\n parent,\n hasChildren,\n expanded,\n isLastChild: isLast,\n lineGuides: parentGuides,\n });\n\n if (expanded && hasLoadedChildren) {\n const childGuides = level >= 2 ? [...parentGuides, !isLast] : [];\n flattenTo(acc, node.children!, expandedState, node.value, level + 1, childGuides);\n }\n }\n}\n\nexport function flattenTreeSelectData(\n data: TreeNodeData[],\n expandedState: TreeExpandedState\n): TreeSelectFlatNode[] {\n const result: TreeSelectFlatNode[] = [];\n flattenTo(result, data, expandedState, null, 1, []);\n return result;\n}\n"],"mappings":";;AAaA,SAAS,UACP,KACA,MACA,eACA,QACA,OACA,cACM;CACN,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,OAAO,KAAK;EAClB,MAAM,SAAS,MAAM,KAAK,SAAS;EACnC,MAAM,oBAAoB,MAAM,QAAQ,KAAK,QAAQ;
|
|
1
|
+
{"version":3,"file":"flatten-tree-select-data.mjs","names":[],"sources":["../../../src/components/TreeSelect/flatten-tree-select-data.ts"],"sourcesContent":["import type { TreeNodeData } from '../Tree';\nimport type { TreeExpandedState } from '../Tree/use-tree';\n\nexport interface TreeSelectFlatNode {\n node: TreeNodeData;\n level: number;\n parent: string | null;\n hasChildren: boolean;\n expanded: boolean;\n isLastChild: boolean;\n lineGuides: boolean[];\n}\n\nfunction flattenTo(\n acc: TreeSelectFlatNode[],\n data: TreeNodeData[],\n expandedState: TreeExpandedState,\n parent: string | null,\n level: number,\n parentGuides: boolean[]\n): void {\n for (let i = 0; i < data.length; i++) {\n const node = data[i];\n const isLast = i === data.length - 1;\n const hasLoadedChildren = Array.isArray(node.children) && node.children.length > 0;\n const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;\n const hasChildren = hasLoadedChildren || hasAsyncChildren;\n const expanded = expandedState[node.value] || false;\n\n acc.push({\n node,\n level,\n parent,\n hasChildren,\n expanded,\n isLastChild: isLast,\n lineGuides: parentGuides,\n });\n\n if (expanded && hasLoadedChildren) {\n const childGuides = level >= 2 ? [...parentGuides, !isLast] : [];\n flattenTo(acc, node.children!, expandedState, node.value, level + 1, childGuides);\n }\n }\n}\n\nexport function flattenTreeSelectData(\n data: TreeNodeData[],\n expandedState: TreeExpandedState\n): TreeSelectFlatNode[] {\n const result: TreeSelectFlatNode[] = [];\n flattenTo(result, data, expandedState, null, 1, []);\n return result;\n}\n"],"mappings":";;AAaA,SAAS,UACP,KACA,MACA,eACA,QACA,OACA,cACM;CACN,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,OAAO,KAAK;EAClB,MAAM,SAAS,MAAM,KAAK,SAAS;EACnC,MAAM,oBAAoB,MAAM,QAAQ,KAAK,QAAQ,KAAK,KAAK,SAAS,SAAS;EACjF,MAAM,mBAAmB,CAAC,CAAC,KAAK,eAAe,CAAC;EAChD,MAAM,cAAc,qBAAqB;EACzC,MAAM,WAAW,cAAc,KAAK,UAAU;EAE9C,IAAI,KAAK;GACP;GACA;GACA;GACA;GACA;GACA,aAAa;GACb,YAAY;EACd,CAAC;EAED,IAAI,YAAY,mBAAmB;GACjC,MAAM,cAAc,SAAS,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,IAAI,CAAC;GAC/D,UAAU,KAAK,KAAK,UAAW,eAAe,KAAK,OAAO,QAAQ,GAAG,WAAW;EAClF;CACF;AACF;AAEA,SAAgB,sBACd,MACA,eACsB;CACtB,MAAM,SAA+B,CAAC;CACtC,UAAU,QAAQ,MAAM,eAAe,MAAM,GAAG,CAAC,CAAC;CAClD,OAAO;AACT"}
|
|
@@ -16,5 +16,6 @@ export interface AccordionContextValue {
|
|
|
16
16
|
variant: string | undefined;
|
|
17
17
|
unstyled: boolean | undefined;
|
|
18
18
|
keepMounted: boolean | undefined;
|
|
19
|
+
keepMountedMode: 'activity' | 'display-none' | undefined;
|
|
19
20
|
}
|
|
20
21
|
export declare const AccordionProvider: import("react").Context<AccordionContextValue | null>, useAccordionContext: () => AccordionContextValue;
|
|
@@ -39,6 +39,8 @@ export interface AccordionProps<Multiple extends boolean = false> extends BoxPro
|
|
|
39
39
|
radius?: MantineRadius;
|
|
40
40
|
/** If set to `false`, panels are unmounted when collapsed. By default, panels stay mounted when collapsed. @default true */
|
|
41
41
|
keepMounted?: boolean;
|
|
42
|
+
/** Controls how inactive panels content is hidden when `keepMounted` is `true`, `'activity'` – hidden with `Activity` component, `'display-none'` – hidden with `display: none` styles @default 'activity' */
|
|
43
|
+
keepMountedMode?: 'activity' | 'display-none';
|
|
42
44
|
}
|
|
43
45
|
export type AccordionFactory = Factory<{
|
|
44
46
|
props: AccordionProps;
|
|
@@ -7,6 +7,8 @@ export interface AccordionPanelProps extends BoxProps, CompoundStylesApiProps<Ac
|
|
|
7
7
|
onTransitionStart?: () => void;
|
|
8
8
|
/** If set, overrides the Accordion-level `keepMounted` value. When undefined (default), uses Accordion's `keepMounted` setting. */
|
|
9
9
|
keepMounted?: boolean;
|
|
10
|
+
/** If set, overrides the Accordion-level `keepMountedMode` value. When undefined (default), uses Accordion's `keepMountedMode` setting. */
|
|
11
|
+
keepMountedMode?: 'activity' | 'display-none';
|
|
10
12
|
}
|
|
11
13
|
export type AccordionPanelFactory = Factory<{
|
|
12
14
|
props: AccordionPanelProps;
|
|
@@ -16,6 +16,12 @@ export interface CollapseProps extends BoxProps, Omit<React.ComponentProps<'div'
|
|
|
16
16
|
animateOpacity?: boolean;
|
|
17
17
|
/** If set, the element is kept in the DOM when collapsed. When `true`, React 19 `Activity` is used to preserve state while collapsed. When `false`, the element is unmounted after the exit animation. @default true */
|
|
18
18
|
keepMounted?: boolean;
|
|
19
|
+
/** Controls how the element is hidden when `keepMounted` is set:
|
|
20
|
+
* `'activity'` – hidden with React 19 `Activity` component,
|
|
21
|
+
* `'display-none'` – hidden with `display: none` styles
|
|
22
|
+
* @default 'activity'
|
|
23
|
+
*/
|
|
24
|
+
keepMountedMode?: 'activity' | 'display-none';
|
|
19
25
|
}
|
|
20
26
|
export type CollapseFactory = Factory<{
|
|
21
27
|
props: CollapseProps;
|
|
@@ -7,6 +7,12 @@ export interface ModalBaseProps extends BoxProps, ElementProps<'div', 'title'> {
|
|
|
7
7
|
unstyled?: boolean;
|
|
8
8
|
/** If set modal/drawer is not unmounted from the DOM when hidden. `display: none` styles are applied instead. @default false */
|
|
9
9
|
keepMounted?: boolean;
|
|
10
|
+
/** Controls how the modal/drawer is hidden when `keepMounted` is set:
|
|
11
|
+
* `'activity'` - hidden with React 19 `Activity` component,
|
|
12
|
+
* `'display-none'` - hidden with `display: none` styles
|
|
13
|
+
* @default 'activity'
|
|
14
|
+
*/
|
|
15
|
+
keepMountedMode?: 'activity' | 'display-none';
|
|
10
16
|
/** Controls opened state */
|
|
11
17
|
opened: boolean;
|
|
12
18
|
/** Called when modal/drawer is closed */
|
|
@@ -46,7 +52,7 @@ export interface ModalBaseProps extends BoxProps, ElementProps<'div', 'title'> {
|
|
|
46
52
|
/** Props passed down to react-remove-scroll, can be used to customize scroll lock behavior */
|
|
47
53
|
removeScrollProps?: RemoveScrollProps;
|
|
48
54
|
}
|
|
49
|
-
export declare function ModalBase({ keepMounted, opened, onClose, id, transitionProps, onExitTransitionEnd, onEnterTransitionEnd, trapFocus, closeOnEscape, returnFocus, closeOnClickOutside, withinPortal, portalProps, lockScroll, children, zIndex, shadow, padding, __vars, unstyled, removeScrollProps, ...others }: ModalBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
55
|
+
export declare function ModalBase({ keepMounted, keepMountedMode, opened, onClose, id, transitionProps, onExitTransitionEnd, onEnterTransitionEnd, trapFocus, closeOnEscape, returnFocus, closeOnClickOutside, withinPortal, portalProps, lockScroll, children, zIndex, shadow, padding, __vars, unstyled, removeScrollProps, ...others }: ModalBaseProps): import("react/jsx-runtime").JSX.Element;
|
|
50
56
|
export declare namespace ModalBase {
|
|
51
57
|
var displayName: string;
|
|
52
58
|
}
|
|
@@ -4,8 +4,8 @@ export interface TransitionProps {
|
|
|
4
4
|
keepMounted?: boolean;
|
|
5
5
|
/**
|
|
6
6
|
* Controls how the element is hidden when `keepMounted` is set:
|
|
7
|
-
* `'activity'`
|
|
8
|
-
* `'display-none'`
|
|
7
|
+
* `'activity'` - hidden with React 19 `Activity` component,
|
|
8
|
+
* `'display-none'` - hidden with `display: none` styles
|
|
9
9
|
* @default 'activity'
|
|
10
10
|
*/
|
|
11
11
|
keepMountedMode?: 'activity' | 'display-none';
|
|
@@ -29,6 +29,10 @@ export interface TreeSelectRenderNodePayload {
|
|
|
29
29
|
selected: boolean;
|
|
30
30
|
checked: boolean;
|
|
31
31
|
indeterminate: boolean;
|
|
32
|
+
/** Toggles the expanded state of the node. Can be used to build a custom expand control
|
|
33
|
+
* in `renderNode` without controlling the expanded state externally.
|
|
34
|
+
* No-op for nodes without children. */
|
|
35
|
+
expand: (event?: React.MouseEvent) => void;
|
|
32
36
|
}
|
|
33
37
|
export declare function TreeSelectOption({ node, level, expanded, hasChildren, selected, checked, indeterminate, showCheckbox, isLastChild, lineGuides, withLines, onToggleExpand, renderNode, chevronAriaLabels, }: TreeSelectOptionProps): import("react/jsx-runtime").JSX.Element;
|
|
34
38
|
export declare namespace TreeSelectOption {
|