@womp/kookie-ui 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/codemods/type-0.20.py +73 -0
- package/components.css +1003 -2360
- package/dist/cjs/components/_internal/base-menu.props.d.ts +2 -2
- package/dist/cjs/components/_internal/base-menu.props.js +1 -1
- package/dist/cjs/components/_internal/base-menu.props.js.map +2 -2
- package/dist/cjs/components/_internal/base-menu.utils.d.ts.map +1 -1
- package/dist/cjs/components/_internal/base-menu.utils.js +1 -1
- package/dist/cjs/components/_internal/base-menu.utils.js.map +2 -2
- package/dist/cjs/components/_internal/menu-context.d.ts +5 -2
- package/dist/cjs/components/_internal/menu-context.d.ts.map +1 -1
- package/dist/cjs/components/_internal/menu-context.js +1 -1
- package/dist/cjs/components/_internal/menu-context.js.map +2 -2
- package/dist/cjs/components/alert-dialog.js +1 -1
- package/dist/cjs/components/alert-dialog.js.map +2 -2
- package/dist/cjs/components/badge.js +1 -1
- package/dist/cjs/components/badge.js.map +2 -2
- package/dist/cjs/components/blockquote.js +1 -1
- package/dist/cjs/components/blockquote.js.map +2 -2
- package/dist/cjs/components/blockquote.props.d.ts +2 -2
- package/dist/cjs/components/blockquote.props.js +1 -1
- package/dist/cjs/components/blockquote.props.js.map +2 -2
- package/dist/cjs/components/button.js +1 -1
- package/dist/cjs/components/button.js.map +2 -2
- package/dist/cjs/components/chatbar.js +1 -1
- package/dist/cjs/components/chatbar.js.map +2 -2
- package/dist/cjs/components/checkbox-group.js +1 -1
- package/dist/cjs/components/checkbox-group.js.map +2 -2
- package/dist/cjs/components/code.js +1 -1
- package/dist/cjs/components/code.js.map +2 -2
- package/dist/cjs/components/code.props.d.ts +2 -2
- package/dist/cjs/components/code.props.js +1 -1
- package/dist/cjs/components/code.props.js.map +2 -2
- package/dist/cjs/components/combobox.js +1 -1
- package/dist/cjs/components/combobox.js.map +2 -2
- package/dist/cjs/components/combobox.props.d.ts +1 -1
- package/dist/cjs/components/combobox.props.js +1 -1
- package/dist/cjs/components/combobox.props.js.map +2 -2
- package/dist/cjs/components/context-menu.js +1 -1
- package/dist/cjs/components/context-menu.js.map +2 -2
- package/dist/cjs/components/context-menu.props.js +1 -1
- package/dist/cjs/components/context-menu.props.js.map +2 -2
- package/dist/cjs/components/data-list.js +1 -1
- package/dist/cjs/components/data-list.js.map +2 -2
- package/dist/cjs/components/dialog.js +1 -1
- package/dist/cjs/components/dialog.js.map +2 -2
- package/dist/cjs/components/dropdown-menu.js +1 -1
- package/dist/cjs/components/dropdown-menu.js.map +2 -2
- package/dist/cjs/components/dropdown-menu.props.js +1 -1
- package/dist/cjs/components/dropdown-menu.props.js.map +2 -2
- package/dist/cjs/components/heading.js +1 -1
- package/dist/cjs/components/heading.js.map +2 -2
- package/dist/cjs/components/heading.props.d.ts +2 -2
- package/dist/cjs/components/heading.props.js +1 -1
- package/dist/cjs/components/heading.props.js.map +2 -2
- package/dist/cjs/components/icon-button.js +1 -1
- package/dist/cjs/components/icon-button.js.map +2 -2
- package/dist/cjs/components/index.js +3 -3
- package/dist/cjs/components/index.js.map +3 -3
- package/dist/cjs/components/kbd.js +1 -1
- package/dist/cjs/components/kbd.js.map +2 -2
- package/dist/cjs/components/kbd.props.d.ts +1 -1
- package/dist/cjs/components/kbd.props.js +1 -1
- package/dist/cjs/components/kbd.props.js.map +2 -2
- package/dist/cjs/components/link.js +1 -1
- package/dist/cjs/components/link.js.map +2 -2
- package/dist/cjs/components/link.props.d.ts +2 -2
- package/dist/cjs/components/link.props.js +1 -1
- package/dist/cjs/components/link.props.js.map +2 -2
- package/dist/cjs/components/message-scroller.js +1 -1
- package/dist/cjs/components/message-scroller.js.map +2 -2
- package/dist/cjs/components/notice.js +1 -1
- package/dist/cjs/components/notice.js.map +2 -2
- package/dist/cjs/components/radio-group.js +1 -1
- package/dist/cjs/components/radio-group.js.map +2 -2
- package/dist/cjs/components/sheet.js +1 -1
- package/dist/cjs/components/sheet.js.map +2 -2
- package/dist/cjs/components/sidebar.d.ts.map +1 -1
- package/dist/cjs/components/sidebar.js +1 -1
- package/dist/cjs/components/sidebar.js.map +3 -3
- package/dist/cjs/components/text.js +1 -1
- package/dist/cjs/components/text.js.map +2 -2
- package/dist/cjs/components/text.props.d.ts +2 -2
- package/dist/cjs/components/text.props.js +1 -1
- package/dist/cjs/components/text.props.js.map +2 -2
- package/dist/cjs/components/theme-panel.js +2 -2
- package/dist/cjs/components/theme-panel.js.map +2 -2
- package/dist/cjs/components/toggle-button.js +1 -1
- package/dist/cjs/components/toggle-button.js.map +2 -2
- package/dist/cjs/components/toggle-icon-button.js +1 -1
- package/dist/cjs/components/toggle-icon-button.js.map +2 -2
- package/dist/cjs/components/toolbar.js +1 -1
- package/dist/cjs/components/toolbar.js.map +2 -2
- package/dist/cjs/components/tooltip.js +1 -1
- package/dist/cjs/components/tooltip.js.map +2 -2
- package/dist/cjs/components/virtual-menu.d.ts +2 -1
- package/dist/cjs/components/virtual-menu.d.ts.map +1 -1
- package/dist/cjs/components/virtual-menu.js +1 -1
- package/dist/cjs/components/virtual-menu.js.map +2 -2
- package/dist/cjs/index.js +3 -3
- package/dist/cjs/index.js.map +3 -3
- package/dist/cjs/props/index.js +1 -1
- package/dist/cjs/props/index.js.map +2 -2
- package/dist/cjs/props/weight.prop.d.ts +1 -1
- package/dist/cjs/props/weight.prop.d.ts.map +1 -1
- package/dist/cjs/props/weight.prop.js +1 -1
- package/dist/cjs/props/weight.prop.js.map +2 -2
- package/dist/esm/chunk-2WSD2H23.js +2 -0
- package/dist/esm/chunk-2WSD2H23.js.map +7 -0
- package/dist/esm/{chunk-JZSXHYUU.js → chunk-33IRPFDK.js} +2 -2
- package/dist/esm/{chunk-32ATKZAP.js → chunk-3E6ADI2F.js} +2 -2
- package/dist/esm/{chunk-JBC6DT2X.js → chunk-74SNS4VY.js} +2 -2
- package/dist/esm/chunk-CD324U6G.js +2 -0
- package/dist/esm/chunk-CD324U6G.js.map +7 -0
- package/dist/esm/{chunk-DIR22XIX.js → chunk-CNMFVJNC.js} +2 -2
- package/dist/esm/{chunk-UUHTK35B.js → chunk-EUHAZKWY.js} +2 -2
- package/dist/esm/chunk-F7HK2QLM.js +2 -0
- package/dist/esm/{chunk-5AHQJB6H.js.map → chunk-F7HK2QLM.js.map} +2 -2
- package/dist/esm/{chunk-MZR6YBE7.js → chunk-GDACOD53.js} +2 -2
- package/dist/esm/chunk-GTXRD4FZ.js +2 -0
- package/dist/esm/{chunk-UUV5UNYL.js.map → chunk-GTXRD4FZ.js.map} +3 -3
- package/dist/esm/{chunk-BUBV3C6C.js → chunk-HJ6ACBXW.js} +2 -2
- package/dist/esm/{chunk-XTE22CXV.js → chunk-HJZNHNLX.js} +2 -2
- package/dist/esm/chunk-HK7RJPQ2.js +2 -0
- package/dist/esm/chunk-HK7RJPQ2.js.map +7 -0
- package/dist/esm/{chunk-IXNJFV4O.js → chunk-HVXXJZC2.js} +2 -2
- package/dist/esm/{chunk-GYB7PAGB.js → chunk-IND2NZIN.js} +2 -2
- package/dist/esm/{chunk-UZQO4APP.js → chunk-JDMJC76O.js} +2 -2
- package/dist/esm/{chunk-PUQXBW2K.js → chunk-JH55M4I2.js} +2 -2
- package/dist/esm/{chunk-N77QJUTO.js → chunk-JOB6FH3D.js} +2 -2
- package/dist/esm/chunk-JOB6FH3D.js.map +7 -0
- package/dist/esm/{chunk-GIIMBBVM.js → chunk-MLXFZDFU.js} +2 -2
- package/dist/esm/{chunk-GYNRAVCL.js → chunk-NEK7F746.js} +2 -2
- package/dist/esm/chunk-NTGRWJEG.js +2 -0
- package/dist/esm/{chunk-EVTNB4TB.js.map → chunk-NTGRWJEG.js.map} +2 -2
- package/dist/esm/{chunk-KDKL3HXD.js → chunk-O7IPBLC7.js} +2 -2
- package/dist/esm/{chunk-K6Y2SM5N.js → chunk-OLSTITVY.js} +2 -2
- package/dist/esm/{chunk-X3D3JR64.js → chunk-Q6GUADLO.js} +2 -2
- package/dist/esm/{chunk-YVHRWMSZ.js → chunk-QETAAJJV.js} +2 -2
- package/dist/esm/chunk-QEYOXQK5.js +2 -0
- package/dist/esm/{chunk-PDBVZAUJ.js.map → chunk-QEYOXQK5.js.map} +2 -2
- package/dist/esm/chunk-R372ULQC.js +2 -0
- package/dist/esm/chunk-R372ULQC.js.map +7 -0
- package/dist/esm/chunk-RDS3AJWW.js +2 -0
- package/dist/esm/chunk-RDS3AJWW.js.map +7 -0
- package/dist/esm/{chunk-6XNQ5XD3.js → chunk-SKOF4A27.js} +2 -2
- package/dist/esm/{chunk-BINUV3ME.js → chunk-TBWKDBUF.js} +2 -2
- package/dist/esm/{chunk-MAI7FEU7.js → chunk-TLZMLJTI.js} +2 -2
- package/dist/esm/{chunk-MAI7FEU7.js.map → chunk-TLZMLJTI.js.map} +2 -2
- package/dist/esm/{chunk-CR2BSCFM.js → chunk-UNH3FGU4.js} +2 -2
- package/dist/esm/{chunk-L2IIIELE.js → chunk-WBGKTN35.js} +2 -2
- package/dist/esm/chunk-WSKA5MZZ.js +2 -0
- package/dist/esm/chunk-WSKA5MZZ.js.map +7 -0
- package/dist/esm/chunk-XDAQXNBQ.js +2 -0
- package/dist/esm/chunk-XDAQXNBQ.js.map +7 -0
- package/dist/esm/{chunk-63ASTOS2.js → chunk-XDV2SDJ3.js} +2 -2
- package/dist/esm/{chunk-G6PO4QKW.js → chunk-XPT5ELKO.js} +2 -2
- package/dist/esm/{chunk-2XQECQF2.js → chunk-XXHIMGBY.js} +2 -2
- package/dist/esm/{chunk-JRIBL4WJ.js → chunk-ZRHXFYAE.js} +2 -2
- package/dist/esm/components/_internal/base-menu.props.d.ts +2 -2
- package/dist/esm/components/_internal/base-menu.props.js +1 -1
- package/dist/esm/components/_internal/base-menu.utils.d.ts.map +1 -1
- package/dist/esm/components/_internal/base-menu.utils.js +1 -1
- package/dist/esm/components/_internal/menu-context.d.ts +5 -2
- package/dist/esm/components/_internal/menu-context.d.ts.map +1 -1
- package/dist/esm/components/_internal/menu-context.js +1 -1
- package/dist/esm/components/alert-dialog.js +1 -1
- package/dist/esm/components/badge.js +1 -1
- package/dist/esm/components/blockquote.js +1 -1
- package/dist/esm/components/blockquote.props.d.ts +2 -2
- package/dist/esm/components/blockquote.props.js +1 -1
- package/dist/esm/components/button.js +1 -1
- package/dist/esm/components/chatbar.js +1 -1
- package/dist/esm/components/checkbox-group.js +1 -1
- package/dist/esm/components/code.js +1 -1
- package/dist/esm/components/code.props.d.ts +2 -2
- package/dist/esm/components/code.props.js +1 -1
- package/dist/esm/components/combobox.js +1 -1
- package/dist/esm/components/combobox.props.d.ts +1 -1
- package/dist/esm/components/combobox.props.js +1 -1
- package/dist/esm/components/context-menu.js +1 -1
- package/dist/esm/components/context-menu.props.js +1 -1
- package/dist/esm/components/data-list.js +1 -1
- package/dist/esm/components/dialog.js +1 -1
- package/dist/esm/components/dropdown-menu.js +1 -1
- package/dist/esm/components/dropdown-menu.props.js +1 -1
- package/dist/esm/components/heading.js +1 -1
- package/dist/esm/components/heading.props.d.ts +2 -2
- package/dist/esm/components/heading.props.js +1 -1
- package/dist/esm/components/icon-button.js +1 -1
- package/dist/esm/components/index.js +1 -1
- package/dist/esm/components/kbd.js +1 -1
- package/dist/esm/components/kbd.props.d.ts +1 -1
- package/dist/esm/components/kbd.props.js +1 -1
- package/dist/esm/components/link.js +1 -1
- package/dist/esm/components/link.props.d.ts +2 -2
- package/dist/esm/components/link.props.js +1 -1
- package/dist/esm/components/message-scroller.js +1 -1
- package/dist/esm/components/notice.js +1 -1
- package/dist/esm/components/radio-group.js +1 -1
- package/dist/esm/components/sheet.js +1 -1
- package/dist/esm/components/sidebar.d.ts.map +1 -1
- package/dist/esm/components/sidebar.js +1 -1
- package/dist/esm/components/text.js +1 -1
- package/dist/esm/components/text.props.d.ts +2 -2
- package/dist/esm/components/text.props.js +1 -1
- package/dist/esm/components/theme-panel.js +1 -1
- package/dist/esm/components/toggle-button.js +1 -1
- package/dist/esm/components/toggle-icon-button.js +1 -1
- package/dist/esm/components/toolbar.js +1 -1
- package/dist/esm/components/tooltip.js +1 -1
- package/dist/esm/components/virtual-menu.d.ts +2 -1
- package/dist/esm/components/virtual-menu.d.ts.map +1 -1
- package/dist/esm/components/virtual-menu.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/props/index.js +1 -1
- package/dist/esm/props/weight.prop.d.ts +1 -1
- package/dist/esm/props/weight.prop.d.ts.map +1 -1
- package/dist/esm/props/weight.prop.js +1 -1
- package/package.json +1 -1
- package/src/components/_internal/base-menu.css +120 -114
- package/src/components/_internal/base-menu.props.ts +1 -1
- package/src/components/_internal/base-menu.utils.tsx +2 -1
- package/src/components/_internal/base-sidebar-menu.css +8 -38
- package/src/components/_internal/menu-context.tsx +9 -4
- package/src/components/avatar.css +3 -3
- package/src/components/badge.css +3 -3
- package/src/components/blockquote.props.tsx +1 -1
- package/src/components/code.css +10 -32
- package/src/components/code.props.tsx +1 -1
- package/src/components/combobox.css +0 -9
- package/src/components/combobox.props.tsx +1 -1
- package/src/components/heading.css +9 -29
- package/src/components/heading.props.tsx +1 -1
- package/src/components/kbd.css +1 -29
- package/src/components/kbd.props.tsx +1 -1
- package/src/components/link.props.tsx +1 -1
- package/src/components/notice.css +10 -13
- package/src/components/select.css +19 -134
- package/src/components/sidebar.css +82 -123
- package/src/components/sidebar.tsx +1 -3
- package/src/components/slider.css +2 -2
- package/src/components/table.css +24 -11
- package/src/components/text.css +0 -20
- package/src/components/text.props.tsx +1 -1
- package/src/components/virtual-menu.tsx +3 -1
- package/src/props/weight.prop.ts +2 -1
- package/src/styles/tokens/radius.css +12 -0
- package/src/styles/tokens/typography.css +21 -49
- package/src/styles/utilities/font-weight.css +0 -20
- package/styles.css +1034 -2503
- package/tokens/base.css +23 -45
- package/tokens.css +23 -45
- package/utilities.css +0 -90
- package/dist/esm/chunk-5AHQJB6H.js +0 -2
- package/dist/esm/chunk-ABQHBDM4.js +0 -2
- package/dist/esm/chunk-ABQHBDM4.js.map +0 -7
- package/dist/esm/chunk-B72RMGWZ.js +0 -2
- package/dist/esm/chunk-B72RMGWZ.js.map +0 -7
- package/dist/esm/chunk-EUSKAXHP.js +0 -2
- package/dist/esm/chunk-EUSKAXHP.js.map +0 -7
- package/dist/esm/chunk-EVTNB4TB.js +0 -2
- package/dist/esm/chunk-FD2TR343.js +0 -2
- package/dist/esm/chunk-FD2TR343.js.map +0 -7
- package/dist/esm/chunk-FTGD2SZ6.js +0 -2
- package/dist/esm/chunk-FTGD2SZ6.js.map +0 -7
- package/dist/esm/chunk-G3U6OHVA.js +0 -2
- package/dist/esm/chunk-G3U6OHVA.js.map +0 -7
- package/dist/esm/chunk-N77QJUTO.js.map +0 -7
- package/dist/esm/chunk-PDBVZAUJ.js +0 -2
- package/dist/esm/chunk-UUV5UNYL.js +0 -2
- package/dist/esm/chunk-ZMFZYXLB.js +0 -2
- package/dist/esm/chunk-ZMFZYXLB.js.map +0 -7
- /package/dist/esm/{chunk-JZSXHYUU.js.map → chunk-33IRPFDK.js.map} +0 -0
- /package/dist/esm/{chunk-32ATKZAP.js.map → chunk-3E6ADI2F.js.map} +0 -0
- /package/dist/esm/{chunk-JBC6DT2X.js.map → chunk-74SNS4VY.js.map} +0 -0
- /package/dist/esm/{chunk-DIR22XIX.js.map → chunk-CNMFVJNC.js.map} +0 -0
- /package/dist/esm/{chunk-UUHTK35B.js.map → chunk-EUHAZKWY.js.map} +0 -0
- /package/dist/esm/{chunk-MZR6YBE7.js.map → chunk-GDACOD53.js.map} +0 -0
- /package/dist/esm/{chunk-BUBV3C6C.js.map → chunk-HJ6ACBXW.js.map} +0 -0
- /package/dist/esm/{chunk-XTE22CXV.js.map → chunk-HJZNHNLX.js.map} +0 -0
- /package/dist/esm/{chunk-IXNJFV4O.js.map → chunk-HVXXJZC2.js.map} +0 -0
- /package/dist/esm/{chunk-GYB7PAGB.js.map → chunk-IND2NZIN.js.map} +0 -0
- /package/dist/esm/{chunk-UZQO4APP.js.map → chunk-JDMJC76O.js.map} +0 -0
- /package/dist/esm/{chunk-PUQXBW2K.js.map → chunk-JH55M4I2.js.map} +0 -0
- /package/dist/esm/{chunk-GIIMBBVM.js.map → chunk-MLXFZDFU.js.map} +0 -0
- /package/dist/esm/{chunk-GYNRAVCL.js.map → chunk-NEK7F746.js.map} +0 -0
- /package/dist/esm/{chunk-KDKL3HXD.js.map → chunk-O7IPBLC7.js.map} +0 -0
- /package/dist/esm/{chunk-K6Y2SM5N.js.map → chunk-OLSTITVY.js.map} +0 -0
- /package/dist/esm/{chunk-X3D3JR64.js.map → chunk-Q6GUADLO.js.map} +0 -0
- /package/dist/esm/{chunk-YVHRWMSZ.js.map → chunk-QETAAJJV.js.map} +0 -0
- /package/dist/esm/{chunk-6XNQ5XD3.js.map → chunk-SKOF4A27.js.map} +0 -0
- /package/dist/esm/{chunk-BINUV3ME.js.map → chunk-TBWKDBUF.js.map} +0 -0
- /package/dist/esm/{chunk-CR2BSCFM.js.map → chunk-UNH3FGU4.js.map} +0 -0
- /package/dist/esm/{chunk-L2IIIELE.js.map → chunk-WBGKTN35.js.map} +0 -0
- /package/dist/esm/{chunk-63ASTOS2.js.map → chunk-XDV2SDJ3.js.map} +0 -0
- /package/dist/esm/{chunk-G6PO4QKW.js.map → chunk-XPT5ELKO.js.map} +0 -0
- /package/dist/esm/{chunk-2XQECQF2.js.map → chunk-XXHIMGBY.js.map} +0 -0
- /package/dist/esm/{chunk-JRIBL4WJ.js.map → chunk-ZRHXFYAE.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/virtual-menu.tsx", "../../../src/components/_internal/menu-context.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client';\n\nimport * as React from 'react';\nimport classNames from 'classnames';\nimport { useVirtualizer } from '@tanstack/react-virtual';\nimport { useMenuContext, getMenuItemHeight } from './_internal/menu-context.js';\n\n/**\n * VirtualMenu - A virtualized menu component for rendering large lists efficiently.\n *\n * Uses TanStack Virtual to render only visible items.\n * Works inside any container (DropdownMenu.Content, Popover.Content, etc.)\n *\n * @example\n * // Simple usage with itemLabel\n * <VirtualMenu\n * items={items}\n * itemLabel={(item) => item.name}\n * onSelect={handleSelect}\n * />\n *\n * @example\n * // Custom rendering with renderItem\n * const UserItem = React.memo(({ item, ...props }) => (\n * <VirtualMenu.Item {...props}>\n * <Avatar src={item.avatar} />\n * {item.name}\n * </VirtualMenu.Item>\n * ));\n *\n * <VirtualMenu items={users} renderItem={UserItem} onSelect={handleSelect} />\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Props passed to custom renderItem components */\ninterface VirtualMenuRenderItemProps<T> {\n /** The item data */\n item: T;\n /** Index in the items array */\n index: number;\n /** Whether this item is currently highlighted */\n isHighlighted: boolean;\n /** Unique ID for accessibility */\n id: string;\n /** Positioning styles - must be applied */\n style: React.CSSProperties;\n /** Tab index for focus management */\n tabIndex: number;\n /** Data attribute for CSS styling */\n 'data-highlighted': true | undefined;\n /** Data attribute for event delegation */\n 'data-index': number;\n /** Mouse enter handler */\n onMouseEnter: (e: React.MouseEvent<HTMLElement>) => void;\n /** Mouse leave handler */\n onMouseLeave: () => void;\n /** Click handler */\n onClick: (e: React.MouseEvent<HTMLElement>) => void;\n /** Keyboard handler for Enter/Space activation */\n onKeyDown: (e: React.KeyboardEvent<HTMLElement>) => void;\n}\n\ninterface VirtualMenuProps<T> {\n /** Array of items to render */\n items: T[];\n /**\n * Simple label accessor for basic text items.\n * Can be a property key or a function.\n * @example\n * itemLabel=\"name\"\n * itemLabel={(item) => item.name}\n */\n itemLabel?: keyof T | ((item: T) => React.ReactNode);\n /**\n * Custom component for rendering items.\n * Must be memoized (React.memo) for optimal performance.\n * @example\n * const MyItem = React.memo(({ item, ...props }) => (\n * <VirtualMenu.Item {...props}>{item.name}</VirtualMenu.Item>\n * ));\n * <VirtualMenu items={items} renderItem={MyItem} />\n */\n renderItem?: React.ComponentType<VirtualMenuRenderItemProps<T>>;\n /**\n * Menu size - controls item height.\n * Automatically inherited from parent DropdownMenu.Content/ContextMenu.Content.\n * Only set manually when using VirtualMenu outside of a menu context.\n * @default '2' (or inherited from context)\n */\n size?: '1' | '2';\n /**\n * Estimated height of each item in pixels.\n * Can be a number (same for all) or a function (per-item).\n * Usually not needed - height is automatically derived from size prop/context.\n * Use this only for custom item heights (e.g., variable height items).\n */\n estimatedItemSize?: number | ((index: number) => number);\n /** Number of items to render outside visible area */\n overscan?: number;\n /** Callback when an item is selected */\n onSelect?: (item: T, index: number) => void;\n /** Additional class name */\n className?: string;\n /** Additional styles */\n style?: React.CSSProperties;\n /** Accessible label for the menu */\n 'aria-label'?: string;\n}\n\n// ============================================================================\n// Internal Memoized Item Component\n// ============================================================================\n\ninterface SimpleItemProps {\n label: React.ReactNode;\n isHighlighted: boolean;\n id: string;\n style: React.CSSProperties;\n tabIndex: number;\n 'data-highlighted': true | undefined;\n 'data-index': number;\n onMouseEnter: (e: React.MouseEvent<HTMLElement>) => void;\n onMouseLeave: () => void;\n onClick: (e: React.MouseEvent<HTMLElement>) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLElement>) => void;\n}\n\nconst SimpleItem = React.memo(\n function SimpleItem({\n label,\n isHighlighted: _isHighlighted,\n id,\n style,\n tabIndex,\n 'data-highlighted': dataHighlighted,\n 'data-index': dataIndex,\n onMouseEnter,\n onMouseLeave,\n onClick,\n onKeyDown,\n }: SimpleItemProps) {\n return (\n <div\n id={id}\n role=\"menuitem\"\n className={classNames('rt-reset', 'rt-BaseMenuItem', 'rt-VirtualMenuItem')}\n style={style}\n tabIndex={tabIndex}\n data-highlighted={dataHighlighted}\n data-index={dataIndex}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onClick={onClick}\n onKeyDown={onKeyDown}\n >\n {label}\n </div>\n );\n },\n (prev, next) => {\n // Custom comparison - only re-render if these change\n if (prev.label !== next.label) return false;\n if (prev['data-highlighted'] !== next['data-highlighted']) return false;\n if (prev.style.height !== next.style.height) return false;\n if (prev.style.transform !== next.style.transform) return false;\n if (prev.tabIndex !== next.tabIndex) return false;\n if (prev.id !== next.id) return false;\n // Event handlers are stable, skip comparison\n return true;\n },\n);\n\n// ============================================================================\n// VirtualMenu Component\n// ============================================================================\n\nfunction VirtualMenuRoot<T>({\n items,\n itemLabel,\n renderItem: RenderItem,\n size: sizeProp,\n estimatedItemSize: estimatedItemSizeProp,\n overscan = 5,\n onSelect,\n className,\n style,\n 'aria-label': ariaLabel,\n}: VirtualMenuProps<T>) {\n const menuId = React.useId();\n const parentRef = React.useRef<HTMLDivElement>(null);\n const [highlightedIndex, setHighlightedIndex] = React.useState<number>(-1);\n const { isInsideMenu, size: contextSize, itemHeight: contextItemHeight } = useMenuContext();\n\n // Resolve item height: explicit prop > own size > parent menu > default size '2'.\n // Heights follow the theme scaling, like the --base-menu-item-height token.\n const estimatedItemSize =\n estimatedItemSizeProp ??\n (sizeProp\n ? getMenuItemHeight(sizeProp)\n : (contextItemHeight ?? getMenuItemHeight(contextSize ?? '2')));\n\n // Validate props\n if (!itemLabel && !RenderItem) {\n throw new Error('VirtualMenu requires either itemLabel or renderItem prop');\n }\n\n // Normalize itemLabel to a function\n const getLabel = React.useMemo(() => {\n if (!itemLabel) return null;\n if (typeof itemLabel === 'function') return itemLabel;\n return (item: T) => item[itemLabel] as React.ReactNode;\n }, [itemLabel]);\n\n // Derive safe highlighted index\n const safeHighlightedIndex = React.useMemo(() => {\n if (items.length === 0) return -1;\n if (highlightedIndex < 0) return -1;\n return Math.min(highlightedIndex, items.length - 1);\n }, [highlightedIndex, items.length]);\n\n // Normalize estimatedItemSize to a function\n const getItemSize = React.useMemo(\n () =>\n typeof estimatedItemSize === 'function'\n ? estimatedItemSize\n : () => estimatedItemSize,\n [estimatedItemSize],\n );\n\n const virtualizer = useVirtualizer({\n count: items.length,\n getScrollElement: () => parentRef.current,\n estimateSize: getItemSize,\n overscan,\n });\n\n const virtualItems = virtualizer.getVirtualItems();\n\n // Refs for stable handler references\n const itemsRef = React.useRef(items);\n const onSelectRef = React.useRef(onSelect);\n itemsRef.current = items;\n onSelectRef.current = onSelect;\n\n const scrollToIndexRef = React.useRef(virtualizer.scrollToIndex);\n scrollToIndexRef.current = virtualizer.scrollToIndex;\n\n const highlightedIndexRef = React.useRef(safeHighlightedIndex);\n highlightedIndexRef.current = safeHighlightedIndex;\n\n // Stable event handlers\n const handleItemMouseEnter = React.useCallback((e: React.MouseEvent<HTMLElement>) => {\n const index = e.currentTarget.dataset.index;\n if (index != null) {\n setHighlightedIndex(Number(index));\n }\n }, []);\n\n const handleItemClick = React.useCallback((e: React.MouseEvent<HTMLElement>) => {\n const index = e.currentTarget.dataset.index;\n if (index != null) {\n const idx = Number(index);\n const currentItems = itemsRef.current;\n if (idx >= 0 && idx < currentItems.length) {\n onSelectRef.current?.(currentItems[idx], idx);\n }\n }\n }, []);\n\n const noop = React.useCallback(() => {}, []);\n\n // Item-level keyboard handler for Enter/Space activation (satisfies a11y lint rule)\n const handleItemKeyDown = React.useCallback((e: React.KeyboardEvent<HTMLElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n const index = e.currentTarget.dataset.index;\n if (index != null) {\n const idx = Number(index);\n const currentItems = itemsRef.current;\n if (idx >= 0 && idx < currentItems.length) {\n onSelectRef.current?.(currentItems[idx], idx);\n }\n }\n }\n }, []);\n\n // Keyboard navigation\n const handleKeyDown = React.useCallback((e: React.KeyboardEvent) => {\n const currentItems = itemsRef.current;\n const currentHighlightedIndex = highlightedIndexRef.current;\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex =\n currentHighlightedIndex < currentItems.length - 1 ? currentHighlightedIndex + 1 : 0;\n setHighlightedIndex(nextIndex);\n scrollToIndexRef.current(nextIndex, { align: 'auto' });\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex =\n currentHighlightedIndex > 0 ? currentHighlightedIndex - 1 : currentItems.length - 1;\n setHighlightedIndex(prevIndex);\n scrollToIndexRef.current(prevIndex, { align: 'auto' });\n break;\n }\n case 'Home': {\n e.preventDefault();\n setHighlightedIndex(0);\n scrollToIndexRef.current(0, { align: 'start' });\n break;\n }\n case 'End': {\n e.preventDefault();\n const lastIndex = currentItems.length - 1;\n setHighlightedIndex(lastIndex);\n scrollToIndexRef.current(lastIndex, { align: 'end' });\n break;\n }\n case 'Enter':\n case ' ': {\n e.preventDefault();\n if (currentHighlightedIndex >= 0 && currentHighlightedIndex < currentItems.length) {\n onSelectRef.current?.(currentItems[currentHighlightedIndex], currentHighlightedIndex);\n }\n break;\n }\n case 'Tab': {\n e.preventDefault();\n break;\n }\n case 'Escape': {\n (e.currentTarget as HTMLElement).blur();\n break;\n }\n }\n }, []);\n\n // Item ID generator\n const getItemId = React.useCallback(\n (index: number) => `${menuId}-item-${index}`,\n [menuId],\n );\n\n // Memoize styles\n const rootStyle = React.useMemo(\n () => ({\n overflow: 'auto' as const,\n position: 'relative' as const,\n ...style,\n }),\n [style],\n );\n\n const totalSize = virtualizer.getTotalSize();\n const viewportStyle = React.useMemo(\n () => ({\n height: `${totalSize}px`,\n width: '100%' as const,\n position: 'relative' as const,\n }),\n [totalSize],\n );\n\n return (\n <div\n ref={parentRef}\n role={isInsideMenu ? 'group' : 'menu'}\n aria-label={ariaLabel}\n aria-activedescendant={safeHighlightedIndex >= 0 ? getItemId(safeHighlightedIndex) : undefined}\n tabIndex={0}\n onKeyDown={handleKeyDown}\n className={classNames('rt-VirtualMenuRoot', className)}\n style={rootStyle}\n >\n <div className=\"rt-VirtualMenuViewport\" style={viewportStyle}>\n {virtualItems.map((virtualRow) => {\n const item = items[virtualRow.index];\n const index = virtualRow.index;\n const isHighlighted = safeHighlightedIndex === index;\n\n const itemStyle: React.CSSProperties = {\n height: virtualRow.size,\n transform: `translateY(${virtualRow.start}px)`,\n };\n\n const commonProps = {\n id: getItemId(index),\n isHighlighted,\n style: itemStyle,\n tabIndex: isHighlighted ? 0 : -1,\n 'data-highlighted': isHighlighted ? true as const : undefined,\n 'data-index': index,\n onMouseEnter: handleItemMouseEnter,\n onMouseLeave: noop,\n onClick: handleItemClick,\n onKeyDown: handleItemKeyDown,\n };\n\n // Use renderItem if provided, otherwise use SimpleItem with itemLabel\n if (RenderItem) {\n return (\n <RenderItem\n key={virtualRow.key}\n item={item}\n index={index}\n {...commonProps}\n />\n );\n }\n\n return (\n <SimpleItem\n key={virtualRow.key}\n label={getLabel!(item)}\n {...commonProps}\n />\n );\n })}\n </div>\n </div>\n );\n}\n\nVirtualMenuRoot.displayName = 'VirtualMenu';\n\n// ============================================================================\n// VirtualMenu.Item Component (for custom renderItem usage)\n// ============================================================================\n\ninterface VirtualMenuItemProps extends React.ComponentPropsWithoutRef<'div'> {\n children: React.ReactNode;\n /** Data attribute for highlight styling */\n 'data-highlighted'?: true | undefined;\n /** Data attribute for event delegation */\n 'data-index'?: number;\n}\n\nconst VirtualMenuItemInner = React.forwardRef<HTMLDivElement, VirtualMenuItemProps>(\n ({ className, children, ...props }, forwardedRef) => {\n return (\n <div\n ref={forwardedRef}\n role=\"menuitem\"\n className={classNames('rt-reset', 'rt-BaseMenuItem', 'rt-VirtualMenuItem', className)}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\n\nVirtualMenuItemInner.displayName = 'VirtualMenu.Item';\n\n// Memoized with custom comparison\nconst VirtualMenuItem = React.memo(VirtualMenuItemInner, (prevProps, nextProps) => {\n const prevStyle = prevProps.style as React.CSSProperties | undefined;\n const nextStyle = nextProps.style as React.CSSProperties | undefined;\n if (prevStyle?.height !== nextStyle?.height) return false;\n if (prevStyle?.transform !== nextStyle?.transform) return false;\n if (prevProps['data-highlighted'] !== nextProps['data-highlighted']) return false;\n if (prevProps.tabIndex !== nextProps.tabIndex) return false;\n if (prevProps.id !== nextProps.id) return false;\n if (prevProps.className !== nextProps.className) return false;\n if (prevProps.children !== nextProps.children) return false;\n return true;\n});\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nconst VirtualMenu = Object.assign(VirtualMenuRoot, {\n Item: VirtualMenuItem,\n});\n\nexport { VirtualMenu };\nexport type { VirtualMenuProps, VirtualMenuItemProps, VirtualMenuRenderItemProps };\n", "'use client';\n\nimport * as React from 'react';\n\nimport { useResolvedResponsiveValue } from './base-menu.utils.js';\n\nimport type { Responsive } from '../../props/prop-def.js';\n\n/**\n * Context to detect if a component is rendered inside a menu (DropdownMenu, ContextMenu, etc.)\n * Used by VirtualMenu to adjust its behavior:\n * - Skip role=\"menu\" when inside a parent menu (parent owns the role)\n * - Delegate certain keyboard handling to parent\n * - Use the correct item height based on menu size\n */\n\nexport type MenuSize = '1' | '2';\n\ninterface MenuContextValue {\n /** Whether we're inside a menu that owns the menu role */\n isInsideMenu: boolean;\n /** Menu size for the current breakpoint */\n size?: MenuSize;\n /** Item height in px for the current size and theme scaling */\n itemHeight?: number;\n}\n\nconst MenuContext = React.createContext<MenuContextValue>({ isInsideMenu: false });\n\ninterface MenuProviderProps {\n children: React.ReactNode;\n /** Menu size passed from parent (DropdownMenu.Content, ContextMenu.Content, etc.) */\n size?: Responsive<MenuSize>;\n}\n\n/** Menu item height in pixels per size: the control height ladder (--control-height-N). */\nexport const menuSizeToItemHeight: Record<MenuSize, number> = {\n '1': 28,\n '2': 32,\n};\n\nexport function getMenuItemHeight(size: MenuSize): number {\n return menuSizeToItemHeight[size];\n}\n\nexport function MenuProvider({ children, size }: MenuProviderProps) {\n const resolvedSize = useResolvedResponsiveValue<MenuSize | undefined>(size, undefined);\n const itemHeight = resolvedSize ? getMenuItemHeight(resolvedSize) : undefined;\n const value = React.useMemo(\n () => ({ isInsideMenu: true, size: resolvedSize, itemHeight }),\n [resolvedSize, itemHeight],\n );\n return <MenuContext.Provider value={value}>{children}</MenuContext.Provider>;\n}\n\nexport function useMenuContext() {\n return React.useContext(MenuContext);\n}\n"],
|
|
5
|
-
"mappings": "ilBAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,iBAAAE,KAAA,eAAAC,GAAAH,IAEA,IAAAI,EAAuB,oBACvBC,EAAuB,yBACvBC,EAA+B,mCCF/B,IAAAC,EAAuB,oBAyBvB,IAAMC,GAAoB,gBAAgC,CAAE,aAAc,EAAM,CAAC,
|
|
4
|
+
"sourcesContent": ["'use client';\n\nimport * as React from 'react';\nimport classNames from 'classnames';\nimport { useVirtualizer } from '@tanstack/react-virtual';\nimport { useMenuContext, getMenuItemHeight } from './_internal/menu-context.js';\n\nimport type { MenuSize } from './_internal/menu-context.js';\n\n/**\n * VirtualMenu - A virtualized menu component for rendering large lists efficiently.\n *\n * Uses TanStack Virtual to render only visible items.\n * Works inside any container (DropdownMenu.Content, Popover.Content, etc.)\n *\n * @example\n * // Simple usage with itemLabel\n * <VirtualMenu\n * items={items}\n * itemLabel={(item) => item.name}\n * onSelect={handleSelect}\n * />\n *\n * @example\n * // Custom rendering with renderItem\n * const UserItem = React.memo(({ item, ...props }) => (\n * <VirtualMenu.Item {...props}>\n * <Avatar src={item.avatar} />\n * {item.name}\n * </VirtualMenu.Item>\n * ));\n *\n * <VirtualMenu items={users} renderItem={UserItem} onSelect={handleSelect} />\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Props passed to custom renderItem components */\ninterface VirtualMenuRenderItemProps<T> {\n /** The item data */\n item: T;\n /** Index in the items array */\n index: number;\n /** Whether this item is currently highlighted */\n isHighlighted: boolean;\n /** Unique ID for accessibility */\n id: string;\n /** Positioning styles - must be applied */\n style: React.CSSProperties;\n /** Tab index for focus management */\n tabIndex: number;\n /** Data attribute for CSS styling */\n 'data-highlighted': true | undefined;\n /** Data attribute for event delegation */\n 'data-index': number;\n /** Mouse enter handler */\n onMouseEnter: (e: React.MouseEvent<HTMLElement>) => void;\n /** Mouse leave handler */\n onMouseLeave: () => void;\n /** Click handler */\n onClick: (e: React.MouseEvent<HTMLElement>) => void;\n /** Keyboard handler for Enter/Space activation */\n onKeyDown: (e: React.KeyboardEvent<HTMLElement>) => void;\n}\n\ninterface VirtualMenuProps<T> {\n /** Array of items to render */\n items: T[];\n /**\n * Simple label accessor for basic text items.\n * Can be a property key or a function.\n * @example\n * itemLabel=\"name\"\n * itemLabel={(item) => item.name}\n */\n itemLabel?: keyof T | ((item: T) => React.ReactNode);\n /**\n * Custom component for rendering items.\n * Must be memoized (React.memo) for optimal performance.\n * @example\n * const MyItem = React.memo(({ item, ...props }) => (\n * <VirtualMenu.Item {...props}>{item.name}</VirtualMenu.Item>\n * ));\n * <VirtualMenu items={items} renderItem={MyItem} />\n */\n renderItem?: React.ComponentType<VirtualMenuRenderItemProps<T>>;\n /**\n * Menu size - controls item height.\n * Automatically inherited from parent DropdownMenu.Content/ContextMenu.Content.\n * Only set manually when using VirtualMenu outside of a menu context.\n * @default '2' (or inherited from context)\n */\n size?: MenuSize;\n /**\n * Estimated height of each item in pixels.\n * Can be a number (same for all) or a function (per-item).\n * Usually not needed - height is automatically derived from size prop/context.\n * Use this only for custom item heights (e.g., variable height items).\n */\n estimatedItemSize?: number | ((index: number) => number);\n /** Number of items to render outside visible area */\n overscan?: number;\n /** Callback when an item is selected */\n onSelect?: (item: T, index: number) => void;\n /** Additional class name */\n className?: string;\n /** Additional styles */\n style?: React.CSSProperties;\n /** Accessible label for the menu */\n 'aria-label'?: string;\n}\n\n// ============================================================================\n// Internal Memoized Item Component\n// ============================================================================\n\ninterface SimpleItemProps {\n label: React.ReactNode;\n isHighlighted: boolean;\n id: string;\n style: React.CSSProperties;\n tabIndex: number;\n 'data-highlighted': true | undefined;\n 'data-index': number;\n onMouseEnter: (e: React.MouseEvent<HTMLElement>) => void;\n onMouseLeave: () => void;\n onClick: (e: React.MouseEvent<HTMLElement>) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLElement>) => void;\n}\n\nconst SimpleItem = React.memo(\n function SimpleItem({\n label,\n isHighlighted: _isHighlighted,\n id,\n style,\n tabIndex,\n 'data-highlighted': dataHighlighted,\n 'data-index': dataIndex,\n onMouseEnter,\n onMouseLeave,\n onClick,\n onKeyDown,\n }: SimpleItemProps) {\n return (\n <div\n id={id}\n role=\"menuitem\"\n className={classNames('rt-reset', 'rt-BaseMenuItem', 'rt-VirtualMenuItem')}\n style={style}\n tabIndex={tabIndex}\n data-highlighted={dataHighlighted}\n data-index={dataIndex}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onClick={onClick}\n onKeyDown={onKeyDown}\n >\n {label}\n </div>\n );\n },\n (prev, next) => {\n // Custom comparison - only re-render if these change\n if (prev.label !== next.label) return false;\n if (prev['data-highlighted'] !== next['data-highlighted']) return false;\n if (prev.style.height !== next.style.height) return false;\n if (prev.style.transform !== next.style.transform) return false;\n if (prev.tabIndex !== next.tabIndex) return false;\n if (prev.id !== next.id) return false;\n // Event handlers are stable, skip comparison\n return true;\n },\n);\n\n// ============================================================================\n// VirtualMenu Component\n// ============================================================================\n\nfunction VirtualMenuRoot<T>({\n items,\n itemLabel,\n renderItem: RenderItem,\n size: sizeProp,\n estimatedItemSize: estimatedItemSizeProp,\n overscan = 5,\n onSelect,\n className,\n style,\n 'aria-label': ariaLabel,\n}: VirtualMenuProps<T>) {\n const menuId = React.useId();\n const parentRef = React.useRef<HTMLDivElement>(null);\n const [highlightedIndex, setHighlightedIndex] = React.useState<number>(-1);\n const { isInsideMenu, size: contextSize, itemHeight: contextItemHeight } = useMenuContext();\n\n // Resolve item height: explicit prop > own size > parent menu > default size '2'.\n // Heights follow the theme scaling, like the --base-menu-item-height token.\n const estimatedItemSize =\n estimatedItemSizeProp ??\n (sizeProp\n ? getMenuItemHeight(sizeProp)\n : (contextItemHeight ?? getMenuItemHeight(contextSize ?? '2')));\n\n // Validate props\n if (!itemLabel && !RenderItem) {\n throw new Error('VirtualMenu requires either itemLabel or renderItem prop');\n }\n\n // Normalize itemLabel to a function\n const getLabel = React.useMemo(() => {\n if (!itemLabel) return null;\n if (typeof itemLabel === 'function') return itemLabel;\n return (item: T) => item[itemLabel] as React.ReactNode;\n }, [itemLabel]);\n\n // Derive safe highlighted index\n const safeHighlightedIndex = React.useMemo(() => {\n if (items.length === 0) return -1;\n if (highlightedIndex < 0) return -1;\n return Math.min(highlightedIndex, items.length - 1);\n }, [highlightedIndex, items.length]);\n\n // Normalize estimatedItemSize to a function\n const getItemSize = React.useMemo(\n () =>\n typeof estimatedItemSize === 'function'\n ? estimatedItemSize\n : () => estimatedItemSize,\n [estimatedItemSize],\n );\n\n const virtualizer = useVirtualizer({\n count: items.length,\n getScrollElement: () => parentRef.current,\n estimateSize: getItemSize,\n overscan,\n });\n\n const virtualItems = virtualizer.getVirtualItems();\n\n // Refs for stable handler references\n const itemsRef = React.useRef(items);\n const onSelectRef = React.useRef(onSelect);\n itemsRef.current = items;\n onSelectRef.current = onSelect;\n\n const scrollToIndexRef = React.useRef(virtualizer.scrollToIndex);\n scrollToIndexRef.current = virtualizer.scrollToIndex;\n\n const highlightedIndexRef = React.useRef(safeHighlightedIndex);\n highlightedIndexRef.current = safeHighlightedIndex;\n\n // Stable event handlers\n const handleItemMouseEnter = React.useCallback((e: React.MouseEvent<HTMLElement>) => {\n const index = e.currentTarget.dataset.index;\n if (index != null) {\n setHighlightedIndex(Number(index));\n }\n }, []);\n\n const handleItemClick = React.useCallback((e: React.MouseEvent<HTMLElement>) => {\n const index = e.currentTarget.dataset.index;\n if (index != null) {\n const idx = Number(index);\n const currentItems = itemsRef.current;\n if (idx >= 0 && idx < currentItems.length) {\n onSelectRef.current?.(currentItems[idx], idx);\n }\n }\n }, []);\n\n const noop = React.useCallback(() => {}, []);\n\n // Item-level keyboard handler for Enter/Space activation (satisfies a11y lint rule)\n const handleItemKeyDown = React.useCallback((e: React.KeyboardEvent<HTMLElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n const index = e.currentTarget.dataset.index;\n if (index != null) {\n const idx = Number(index);\n const currentItems = itemsRef.current;\n if (idx >= 0 && idx < currentItems.length) {\n onSelectRef.current?.(currentItems[idx], idx);\n }\n }\n }\n }, []);\n\n // Keyboard navigation\n const handleKeyDown = React.useCallback((e: React.KeyboardEvent) => {\n const currentItems = itemsRef.current;\n const currentHighlightedIndex = highlightedIndexRef.current;\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex =\n currentHighlightedIndex < currentItems.length - 1 ? currentHighlightedIndex + 1 : 0;\n setHighlightedIndex(nextIndex);\n scrollToIndexRef.current(nextIndex, { align: 'auto' });\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex =\n currentHighlightedIndex > 0 ? currentHighlightedIndex - 1 : currentItems.length - 1;\n setHighlightedIndex(prevIndex);\n scrollToIndexRef.current(prevIndex, { align: 'auto' });\n break;\n }\n case 'Home': {\n e.preventDefault();\n setHighlightedIndex(0);\n scrollToIndexRef.current(0, { align: 'start' });\n break;\n }\n case 'End': {\n e.preventDefault();\n const lastIndex = currentItems.length - 1;\n setHighlightedIndex(lastIndex);\n scrollToIndexRef.current(lastIndex, { align: 'end' });\n break;\n }\n case 'Enter':\n case ' ': {\n e.preventDefault();\n if (currentHighlightedIndex >= 0 && currentHighlightedIndex < currentItems.length) {\n onSelectRef.current?.(currentItems[currentHighlightedIndex], currentHighlightedIndex);\n }\n break;\n }\n case 'Tab': {\n e.preventDefault();\n break;\n }\n case 'Escape': {\n (e.currentTarget as HTMLElement).blur();\n break;\n }\n }\n }, []);\n\n // Item ID generator\n const getItemId = React.useCallback(\n (index: number) => `${menuId}-item-${index}`,\n [menuId],\n );\n\n // Memoize styles\n const rootStyle = React.useMemo(\n () => ({\n overflow: 'auto' as const,\n position: 'relative' as const,\n ...style,\n }),\n [style],\n );\n\n const totalSize = virtualizer.getTotalSize();\n const viewportStyle = React.useMemo(\n () => ({\n height: `${totalSize}px`,\n width: '100%' as const,\n position: 'relative' as const,\n }),\n [totalSize],\n );\n\n return (\n <div\n ref={parentRef}\n role={isInsideMenu ? 'group' : 'menu'}\n aria-label={ariaLabel}\n aria-activedescendant={safeHighlightedIndex >= 0 ? getItemId(safeHighlightedIndex) : undefined}\n tabIndex={0}\n onKeyDown={handleKeyDown}\n className={classNames('rt-VirtualMenuRoot', className)}\n style={rootStyle}\n >\n <div className=\"rt-VirtualMenuViewport\" style={viewportStyle}>\n {virtualItems.map((virtualRow) => {\n const item = items[virtualRow.index];\n const index = virtualRow.index;\n const isHighlighted = safeHighlightedIndex === index;\n\n const itemStyle: React.CSSProperties = {\n height: virtualRow.size,\n transform: `translateY(${virtualRow.start}px)`,\n };\n\n const commonProps = {\n id: getItemId(index),\n isHighlighted,\n style: itemStyle,\n tabIndex: isHighlighted ? 0 : -1,\n 'data-highlighted': isHighlighted ? true as const : undefined,\n 'data-index': index,\n onMouseEnter: handleItemMouseEnter,\n onMouseLeave: noop,\n onClick: handleItemClick,\n onKeyDown: handleItemKeyDown,\n };\n\n // Use renderItem if provided, otherwise use SimpleItem with itemLabel\n if (RenderItem) {\n return (\n <RenderItem\n key={virtualRow.key}\n item={item}\n index={index}\n {...commonProps}\n />\n );\n }\n\n return (\n <SimpleItem\n key={virtualRow.key}\n label={getLabel!(item)}\n {...commonProps}\n />\n );\n })}\n </div>\n </div>\n );\n}\n\nVirtualMenuRoot.displayName = 'VirtualMenu';\n\n// ============================================================================\n// VirtualMenu.Item Component (for custom renderItem usage)\n// ============================================================================\n\ninterface VirtualMenuItemProps extends React.ComponentPropsWithoutRef<'div'> {\n children: React.ReactNode;\n /** Data attribute for highlight styling */\n 'data-highlighted'?: true | undefined;\n /** Data attribute for event delegation */\n 'data-index'?: number;\n}\n\nconst VirtualMenuItemInner = React.forwardRef<HTMLDivElement, VirtualMenuItemProps>(\n ({ className, children, ...props }, forwardedRef) => {\n return (\n <div\n ref={forwardedRef}\n role=\"menuitem\"\n className={classNames('rt-reset', 'rt-BaseMenuItem', 'rt-VirtualMenuItem', className)}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\n\nVirtualMenuItemInner.displayName = 'VirtualMenu.Item';\n\n// Memoized with custom comparison\nconst VirtualMenuItem = React.memo(VirtualMenuItemInner, (prevProps, nextProps) => {\n const prevStyle = prevProps.style as React.CSSProperties | undefined;\n const nextStyle = nextProps.style as React.CSSProperties | undefined;\n if (prevStyle?.height !== nextStyle?.height) return false;\n if (prevStyle?.transform !== nextStyle?.transform) return false;\n if (prevProps['data-highlighted'] !== nextProps['data-highlighted']) return false;\n if (prevProps.tabIndex !== nextProps.tabIndex) return false;\n if (prevProps.id !== nextProps.id) return false;\n if (prevProps.className !== nextProps.className) return false;\n if (prevProps.children !== nextProps.children) return false;\n return true;\n});\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nconst VirtualMenu = Object.assign(VirtualMenuRoot, {\n Item: VirtualMenuItem,\n});\n\nexport { VirtualMenu };\nexport type { VirtualMenuProps, VirtualMenuItemProps, VirtualMenuRenderItemProps };\n", "'use client';\n\nimport * as React from 'react';\n\nimport { useResolvedResponsiveValue } from './base-menu.utils.js';\n\nimport type { Responsive } from '../../props/prop-def.js';\n\n/**\n * Context to detect if a component is rendered inside a menu (DropdownMenu, ContextMenu, etc.)\n * Used by VirtualMenu to adjust its behavior:\n * - Skip role=\"menu\" when inside a parent menu (parent owns the role)\n * - Delegate certain keyboard handling to parent\n * - Use the correct item height based on menu size\n */\n\nexport type MenuSize = '1' | '2' | '3' | '4';\n\ninterface MenuContextValue {\n /** Whether we're inside a menu that owns the menu role */\n isInsideMenu: boolean;\n /** Menu size for the current breakpoint */\n size?: MenuSize;\n /** Item height in px for the current size and theme scaling */\n itemHeight?: number;\n}\n\nconst MenuContext = React.createContext<MenuContextValue>({ isInsideMenu: false });\n\ninterface MenuProviderProps {\n children: React.ReactNode;\n /** Menu size passed from parent (DropdownMenu.Content, ContextMenu.Content, etc.) */\n size?: Responsive<MenuSize>;\n}\n\n/**\n * Menu row height in pixels per size: the line height plus --row-inset-N above and below\n * (base-menu.css), never under the 24px target floor.\n */\nexport const menuSizeToItemHeight: Record<MenuSize, number> = {\n '1': 24,\n '2': 30,\n '3': 34,\n '4': 38,\n};\n\nexport function getMenuItemHeight(size: MenuSize): number {\n return menuSizeToItemHeight[size];\n}\n\nexport function MenuProvider({ children, size }: MenuProviderProps) {\n const resolvedSize = useResolvedResponsiveValue<MenuSize | undefined>(size, undefined);\n const itemHeight = resolvedSize ? getMenuItemHeight(resolvedSize) : undefined;\n const value = React.useMemo(\n () => ({ isInsideMenu: true, size: resolvedSize, itemHeight }),\n [resolvedSize, itemHeight],\n );\n return <MenuContext.Provider value={value}>{children}</MenuContext.Provider>;\n}\n\nexport function useMenuContext() {\n return React.useContext(MenuContext);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["virtual_menu_exports", "__export", "VirtualMenu", "__toCommonJS", "React", "import_classnames", "import_react_virtual", "React", "MenuContext", "menuSizeToItemHeight", "getMenuItemHeight", "size", "useMenuContext", "MenuContext", "SimpleItem", "label", "_isHighlighted", "id", "style", "tabIndex", "dataHighlighted", "dataIndex", "onMouseEnter", "onMouseLeave", "onClick", "onKeyDown", "classNames", "prev", "next", "VirtualMenuRoot", "items", "itemLabel", "RenderItem", "sizeProp", "estimatedItemSizeProp", "overscan", "onSelect", "className", "ariaLabel", "menuId", "parentRef", "highlightedIndex", "setHighlightedIndex", "isInsideMenu", "contextSize", "contextItemHeight", "useMenuContext", "estimatedItemSize", "getMenuItemHeight", "getLabel", "item", "safeHighlightedIndex", "getItemSize", "virtualizer", "virtualItems", "itemsRef", "onSelectRef", "scrollToIndexRef", "highlightedIndexRef", "handleItemMouseEnter", "e", "index", "handleItemClick", "idx", "currentItems", "noop", "handleItemKeyDown", "handleKeyDown", "currentHighlightedIndex", "nextIndex", "prevIndex", "lastIndex", "getItemId", "rootStyle", "totalSize", "viewportStyle", "virtualRow", "isHighlighted", "itemStyle", "commonProps", "VirtualMenuItemInner", "children", "props", "forwardedRef", "VirtualMenuItem", "prevProps", "nextProps", "prevStyle", "nextStyle", "VirtualMenu"]
|
|
7
7
|
}
|