@aloudata/aloudata-design 3.0.27 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AProgress/index.js +10 -0
- package/dist/AProgress/index.js.map +1 -1
- package/dist/Alert/index.js +3 -1
- package/dist/Alert/index.js.map +1 -1
- package/dist/Badge/index.js +37 -11
- package/dist/Badge/index.js.map +1 -1
- package/dist/Breadcrumb/index.js +12 -2
- package/dist/Breadcrumb/index.js.map +1 -1
- package/dist/Button/index.d.ts +1 -1
- package/dist/Button/index.js +29 -9
- package/dist/Button/index.js.map +1 -1
- package/dist/Card/index.js +1 -1
- package/dist/Card/index.js.map +1 -1
- package/dist/Carousel/index.js +9 -1
- package/dist/Carousel/index.js.map +1 -1
- package/dist/Checkbox/index.js +25 -4
- package/dist/Checkbox/index.js.map +1 -1
- package/dist/Checkbox/type.d.ts +10 -2
- package/dist/Collapse/index.js +68 -22
- package/dist/Collapse/index.js.map +1 -1
- package/dist/ColorPicker/index.js +112 -46
- package/dist/ColorPicker/index.js.map +1 -1
- package/dist/DataPreviewTable/components/Body/Cell.d.ts +2 -0
- package/dist/DataPreviewTable/components/Body/Cell.js +9 -1
- package/dist/DataPreviewTable/components/Body/Cell.js.map +1 -1
- package/dist/DataPreviewTable/components/Body/index.d.ts +1 -0
- package/dist/DataPreviewTable/components/Body/index.js +35 -23
- package/dist/DataPreviewTable/components/Body/index.js.map +1 -1
- package/dist/DataPreviewTable/components/Header/index.d.ts +1 -0
- package/dist/DataPreviewTable/components/Header/index.js +36 -28
- package/dist/DataPreviewTable/components/Header/index.js.map +1 -1
- package/dist/DataPreviewTable/index.js +19 -2
- package/dist/DataPreviewTable/index.js.map +1 -1
- package/dist/Drawer/index.d.ts +4 -0
- package/dist/Drawer/index.js +91 -78
- package/dist/Drawer/index.js.map +1 -1
- package/dist/Dropdown/index.d.ts +1 -1
- package/dist/Dropdown/index.js +116 -98
- package/dist/Dropdown/index.js.map +1 -1
- package/dist/Form/FormItemContext.d.ts +1 -1
- package/dist/Form/FormItemContext.js.map +1 -1
- package/dist/Form/index.js +50 -7
- package/dist/Form/index.js.map +1 -1
- package/dist/IconButton/index.d.ts +2 -2
- package/dist/IconButton/index.js +9 -3
- package/dist/IconButton/index.js.map +1 -1
- package/dist/Input/components/Input/index.js +23 -7
- package/dist/Input/components/Input/index.js.map +1 -1
- package/dist/Input/components/TextArea/index.js +20 -2
- package/dist/Input/components/TextArea/index.js.map +1 -1
- package/dist/Input/privateSemanticOwner.d.ts +2 -0
- package/dist/Input/privateSemanticOwner.js +1 -0
- package/dist/InputNumber/index.js +19 -5
- package/dist/InputNumber/index.js.map +1 -1
- package/dist/InputNumber/type.d.ts +2 -2
- package/dist/LogicTree/components/LogicItem/index.d.ts +2 -1
- package/dist/LogicTree/components/LogicItem/index.js +13 -2
- package/dist/LogicTree/components/LogicItem/index.js.map +1 -1
- package/dist/LogicTree/index.js +2 -0
- package/dist/LogicTree/index.js.map +1 -1
- package/dist/MemberPicker/components/MemberSelection.d.ts +1 -0
- package/dist/MemberPicker/components/MemberSelection.js +83 -94
- package/dist/MemberPicker/components/MemberSelection.js.map +1 -1
- package/dist/MemberPicker/components/MultipleOption.js +12 -0
- package/dist/MemberPicker/components/MultipleOption.js.map +1 -1
- package/dist/MemberPicker/components/Panel.d.ts +1 -0
- package/dist/MemberPicker/components/Panel.js +4 -1
- package/dist/MemberPicker/components/Panel.js.map +1 -1
- package/dist/MemberPicker/components/SelectedMemberTags.js +14 -6
- package/dist/MemberPicker/components/SelectedMemberTags.js.map +1 -1
- package/dist/MemberPicker/components/SingleOption.js +12 -0
- package/dist/MemberPicker/components/SingleOption.js.map +1 -1
- package/dist/MemberPicker/components/UserGroupSelection.d.ts +2 -1
- package/dist/MemberPicker/components/UserGroupSelection.js +61 -48
- package/dist/MemberPicker/components/UserGroupSelection.js.map +1 -1
- package/dist/MemberPicker/index.js +134 -108
- package/dist/MemberPicker/index.js.map +1 -1
- package/dist/Menu/index.d.ts +8 -0
- package/dist/Menu/index.js +33 -3
- package/dist/Menu/index.js.map +1 -1
- package/dist/Modal/index.d.ts +4 -0
- package/dist/Modal/index.js +55 -66
- package/dist/Modal/index.js.map +1 -1
- package/dist/OverflowCount/index.js +10 -0
- package/dist/OverflowCount/index.js.map +1 -1
- package/dist/Pagination/PageSizeChanger.d.ts +1 -0
- package/dist/Pagination/PageSizeChanger.js +3 -2
- package/dist/Pagination/PageSizeChanger.js.map +1 -1
- package/dist/Pagination/index.js +34 -19
- package/dist/Pagination/index.js.map +1 -1
- package/dist/Pagination/types.d.ts +3 -0
- package/dist/Popconfirm/index.js +9 -1
- package/dist/Popconfirm/index.js.map +1 -1
- package/dist/Popover/index.js +52 -1
- package/dist/Popover/index.js.map +1 -1
- package/dist/Progress/index.js +4 -0
- package/dist/Progress/index.js.map +1 -1
- package/dist/Radio/components/Group/index.d.ts +5 -1
- package/dist/Radio/components/Group/index.js +7 -2
- package/dist/Radio/components/Group/index.js.map +1 -1
- package/dist/Radio/components/Radio/index.js +27 -1
- package/dist/Radio/components/Radio/index.js.map +1 -1
- package/dist/Radio/interface/radio.d.ts +7 -0
- package/dist/Radio/interface/radioGroup.d.ts +2 -0
- package/dist/RenameInput/index.js +11 -0
- package/dist/RenameInput/index.js.map +1 -1
- package/dist/Select/BaseSelect.d.ts +3 -0
- package/dist/Select/BaseSelect.js +235 -38
- package/dist/Select/BaseSelect.js.map +1 -1
- package/dist/Select/SelectTrigger.d.ts +2 -0
- package/dist/Select/SelectTrigger.js +13 -5
- package/dist/Select/SelectTrigger.js.map +1 -1
- package/dist/Select/Selector/FixedOverflow.d.ts +1 -0
- package/dist/Select/Selector/FixedOverflow.js +3 -3
- package/dist/Select/Selector/FixedOverflow.js.map +1 -1
- package/dist/Select/Selector/MultipleSelector.js +1 -0
- package/dist/Select/Selector/MultipleSelector.js.map +1 -1
- package/dist/Select/components/OptionCollection.d.ts +41 -0
- package/dist/Select/components/OptionCollection.js +124 -0
- package/dist/Select/components/OptionCollection.js.map +1 -0
- package/dist/Select/index.js +45 -3
- package/dist/Select/index.js.map +1 -1
- package/dist/Select/interface.d.ts +1 -1
- package/dist/Skeleton/index.js +1 -1
- package/dist/Skeleton/index.js.map +1 -1
- package/dist/Spin/index.d.ts +1 -1
- package/dist/Spin/index.js +22 -7
- package/dist/Spin/index.js.map +1 -1
- package/dist/Steps/index.js +66 -14
- package/dist/Steps/index.js.map +1 -1
- package/dist/Switch/index.d.ts +5 -0
- package/dist/Switch/index.js +22 -5
- package/dist/Switch/index.js.map +1 -1
- package/dist/Table/components/Cell.js +8 -3
- package/dist/Table/components/Cell.js.map +1 -1
- package/dist/Table/components/ExpandCell.js +6 -2
- package/dist/Table/components/ExpandCell.js.map +1 -1
- package/dist/Table/components/Footer/index.js +2 -1
- package/dist/Table/components/Footer/index.js.map +1 -1
- package/dist/Table/components/Header.js +25 -18
- package/dist/Table/components/Header.js.map +1 -1
- package/dist/Table/hooks/useRowSelection.js +14 -7
- package/dist/Table/hooks/useRowSelection.js.map +1 -1
- package/dist/Table/index.js +50 -29
- package/dist/Table/index.js.map +1 -1
- package/dist/Tabs/index.d.ts +1 -1
- package/dist/Tabs/index.js +92 -11
- package/dist/Tabs/index.js.map +1 -1
- package/dist/Tag/index.js +20 -1
- package/dist/Tag/index.js.map +1 -1
- package/dist/Tooltip/index.js +34 -5
- package/dist/Tooltip/index.js.map +1 -1
- package/dist/Tour/index.js +13 -1
- package/dist/Tour/index.js.map +1 -1
- package/dist/Tree/Tree2.js +2 -0
- package/dist/Tree/Tree2.js.map +1 -1
- package/dist/_utils/dialogAccessibility.d.ts +17 -0
- package/dist/_utils/dialogAccessibility.js +110 -0
- package/dist/_utils/dialogAccessibility.js.map +1 -0
- package/dist/_utils/formControlSemanticOwner.d.ts +3 -0
- package/dist/_utils/formControlSemanticOwner.js +17 -0
- package/dist/_utils/formControlSemanticOwner.js.map +1 -0
- package/dist/_utils/overlayCoordinator.js +1 -11
- package/dist/_utils/overlayCoordinator.js.map +1 -1
- package/dist/aloudata-design.css +1 -1
- package/dist/locale/default.d.ts +6 -0
- package/dist/locale/en_US.d.ts +6 -0
- package/dist/locale/en_US.js +6 -0
- package/dist/locale/en_US.js.map +1 -1
- package/dist/locale/zh_CN.d.ts +6 -0
- package/dist/locale/zh_CN.js +6 -0
- package/dist/locale/zh_CN.js.map +1 -1
- package/dist/theme/contract/baselineResolvedTokenValueManifest.d.ts +1 -1
- package/dist/theme/contract/controlStateColorArtifact.d.ts +73 -0
- package/dist/theme/contract/controlStateColorArtifact.js +2 -0
- package/dist/theme/contract/darkResolvedTokenValueManifest.d.ts +1 -1
- package/dist/theme/contract/focusRingArtifact.d.ts +51 -0
- package/dist/theme/contract/focusRingArtifact.js +2 -0
- package/dist/theme/contract/tokenOutputContract.d.ts +1 -1
- package/dist/theme/contract/tokenOutputContract.js +4 -0
- package/dist/theme/contract/tokenOutputContract.js.map +1 -1
- package/dist/theme/generator/acceptedColorValues.d.ts +2 -1
- package/dist/theme/generator/baselineTokenValueDelivery.d.ts +9 -1
- package/dist/theme/generator/minimalAcceptedColorValues.d.ts +2 -2
- package/dist/theme/generator/neutralSourceResolver.d.ts +28 -0
- package/dist/theme/generator/neutralSourceResolver.js +2 -0
- package/dist/theme/generator/neutralSourceValues.d.ts +27 -0
- package/dist/theme/generator/neutralSourceValues.js +2 -0
- package/dist/theme/index.d.ts +2 -0
- package/dist/theme/index.js +1 -0
- package/dist/theme/neutralSourceContract.d.ts +3 -0
- package/dist/theme/neutralSourceContract.js +11 -0
- package/dist/theme/neutralSourceContract.js.map +1 -0
- package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.d.ts +1 -1
- package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js +47 -44
- package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js.map +1 -1
- package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.d.ts +3 -0
- package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.js +2 -0
- package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.d.ts +3 -0
- package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.js +2 -0
- package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.d.ts +3 -0
- package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.js +2 -0
- package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.d.ts +3 -0
- package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.js +2 -0
- package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.d.ts +1 -1
- package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js +43 -40
- package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js.map +1 -1
- package/dist/theme/runtime/colorValueMode/index.js +2 -12
- package/dist/theme/runtime/colorValueMode/index.js.map +1 -1
- package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.d.ts +2 -0
- package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js +48 -0
- package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js.map +1 -0
- package/dist/theme/runtime/colorValueMode/registry.d.ts +1 -1
- package/dist/theme/runtime/colorValueMode/registry.js +2 -1
- package/dist/theme/runtime/colorValueMode/registry.js.map +1 -1
- package/dist/theme/runtime/initAldTheme.js +1 -3
- package/dist/theme/runtime/initAldTheme.js.map +1 -1
- package/dist/theme/runtime/neutralSource/index.d.ts +6 -0
- package/dist/theme/runtime/neutralSource/index.js +11 -0
- package/dist/theme/runtime/neutralSource/index.js.map +1 -0
- package/dist/theme/runtime/neutralSource.d.ts +2 -0
- package/dist/theme/runtime/themeToCssVars.js +3 -0
- package/dist/theme/runtime/themeToCssVars.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseSelect.js","names":[],"sources":["../../src/Select/BaseSelect.tsx"],"sourcesContent":["import './ald-select.css';\nimport * as React from 'react';\nimport useMergedState from 'rc-util/es/hooks/useMergedState';\nimport { cn } from '../lib/utils';\nimport prefixCls from '../_utils/prefixCls';\n\n/** Align config type (locally defined to avoid rc-trigger dependency) */\nexport interface AlignType {\n points?: string[];\n offset?: (number | string)[];\n targetOffset?: (number | string)[];\n overflow?: { adjustX?: boolean; adjustY?: boolean };\n _experimental?: Record<string, any>;\n}\nimport SelectTrigger, { RefTriggerProps } from './SelectTrigger';\nimport Selector from './Selector';\nimport _ from 'lodash';\nimport { useContext, useRef, useState } from 'react';\nimport { FormItemInputContext } from '../Form/FormItemContext';\nimport getWidthStyle from './utils/getWidthStyle';\nimport Suffix from './components/Suffix';\nimport { PlacementType } from '../Dropdown';\nimport {\n BaseSelectRef,\n DisplayValueType,\n ISelectProps,\n LabelInValueType,\n SelectMenuProps,\n} from './interface';\nimport SizeContext from '../ConfigProvider/sizeContext';\nimport { ConfigContext } from '../ConfigProvider';\nimport { useCompactItemContext } from '../Space/CompactContext';\nimport { MenuInfo } from '../Menu';\nimport { toString } from './utils/commonUtil';\n\nexport type RenderNode = React.ReactNode | ((props: any) => React.ReactNode);\n\nexport type RenderDOMFunc = (props: any) => HTMLElement;\n\nexport type Mode =\n | 'multiple'\n | {\n type: 'multiple';\n responsive?: boolean;\n maxRows?: number;\n showSelectedSection?: boolean;\n };\n\nexport type RawValueType = string | number;\n\nexport type CustomTagProps = {\n label: React.ReactNode;\n value: any;\n disabled: boolean;\n onClose: (event?: React.MouseEvent<HTMLElement, MouseEvent>) => void;\n closable: boolean;\n};\nexport interface BaseSelectPrivateProps {\n // >>> MISC\n omitDomProps?: string[];\n\n // >>> Value\n displayValues: LabelInValueType[];\n onDisplayValuesChange: (\n values: LabelInValueType[],\n info: {\n type: 'add' | 'remove' | 'clear';\n values: LabelInValueType[];\n },\n ) => void;\n\n // >>> Active\n /** Current dropdown list active item string value */\n activeValue?: string;\n /** Link search input with target element */\n activeDescendantId?: string;\n onActiveValueChange?: (value: string | null) => void;\n}\n\nexport type BaseSelectPropsWithoutPrivate = Omit<\n BaseSelectProps,\n keyof BaseSelectPrivateProps\n>;\n\nexport interface BaseSelectProps\n extends BaseSelectPrivateProps,\n ISelectProps,\n React.AriaAttributes {\n className?: string;\n style?: React.CSSProperties;\n notFoundContent?: React.ReactNode;\n onClear?: () => void;\n innerSearchValue?: string;\n setInnerSearchValue?: (value: string) => void;\n displayMenu?: SelectMenuProps;\n // >>> Open\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n onOptionSelect?: (val: RawValueType) => void;\n\n // >>> Icons\n allowClear?: boolean;\n showArrow?: boolean;\n suffixIcon?: React.ReactNode;\n\n // >>> Dropdown\n dropdownAlign?: AlignType;\n placement?: PlacementType;\n getPopupContainer?: () => HTMLElement;\n\n // >>> Focus\n onBlur?: React.FocusEventHandler<HTMLElement>;\n onFocus?: React.FocusEventHandler<HTMLElement>;\n\n // >>> Rest Events\n onKeyUp?: React.KeyboardEventHandler<HTMLDivElement>;\n onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;\n onMouseDown?: React.MouseEventHandler<HTMLDivElement>;\n onPopupScroll?: React.UIEventHandler<HTMLDivElement>;\n onInputKeyDown?: React.KeyboardEventHandler<\n HTMLInputElement | HTMLTextAreaElement\n >;\n onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;\n onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;\n onClick?: React.MouseEventHandler<HTMLDivElement>;\n}\n\nexport function isMultiple(mode?: Mode) {\n return !!mode;\n}\nexport function isResponsive(mode?: Mode) {\n return mode === 'multiple' || (typeof mode === 'object' && mode?.responsive);\n}\nexport function isShowSelectedSection(mode?: Mode) {\n if (!mode || mode === 'multiple') {\n return false;\n }\n\n return (\n typeof mode === 'object' && mode.showSelectedSection && mode.responsive\n );\n}\nconst BaseSelect = React.forwardRef(\n (props: BaseSelectProps, ref: React.Ref<BaseSelectRef>) => {\n const {\n id,\n className,\n // Value\n displayValues,\n onDisplayValuesChange,\n displayMenu,\n notFoundContent,\n onClear,\n width,\n mode,\n status: customStatus,\n onOptionSelect,\n onClick,\n size: customSize,\n borderLess = false,\n // Status\n disabled,\n placeholder,\n loading = false,\n\n // Open\n open,\n defaultOpen,\n onOpenChange,\n showSearch,\n innerSearchValue,\n setInnerSearchValue,\n // Icons\n allowClear,\n showArrow = true,\n prefix,\n suffixIcon,\n dropdownRender,\n overlayStyle,\n dropdownStyle,\n popupMatchSelectWidth = true,\n placement,\n popupClassName,\n allowOverlap,\n style,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n ...restProps\n // Rest Props\n } = props;\n const setClassNames = prefixCls('select');\n const selectRef = useRef<HTMLDivElement>(null);\n const widthStyle = getWidthStyle(width);\n const dropdownRef = useRef<RefTriggerProps>(null);\n const [matchedPopupWidth, setMatchedPopupWidth] = useState<\n number | undefined\n >();\n const isResponsiveMode = isResponsive(mode);\n const isMultipleMode = isMultiple(mode);\n /** Used for component focused management */\n const contentSize = useContext(SizeContext);\n const { direction } = React.useContext(ConfigContext);\n // ===================== Compact Item =====================\n const { compactSize, compactItemClassnames } = useCompactItemContext(\n 'ald-select',\n direction,\n );\n const size = compactSize || customSize || contentSize || 'middle';\n const {\n status: contextStatus,\n // hasFeedback,\n // isFormItemInput,\n // feedbackIcon,\n } = useContext(FormItemInputContext);\n\n const mergedStatus =\n customStatus === null ? undefined : customStatus || contextStatus;\n\n // =========================== Imperative ===========================\n React.useImperativeHandle(ref, () => ({\n focus: () => setFocus(true),\n blur: () => setFocus(false),\n open: () => onToggleOpen(true),\n close: () => {\n console.log('ref close');\n onToggleOpen(false);\n },\n }));\n const [focus, setFocus] = useState(false);\n const [isHover, setIsHover] = useState(false);\n // ============================== Open ==============================\n const [innerOpen, setInnerOpen] = useMergedState<boolean>(false, {\n defaultValue: defaultOpen,\n value: open,\n });\n const mergedOpen = innerOpen;\n const shouldMatchPopupWidth =\n !!popupMatchSelectWidth && typeof popupMatchSelectWidth !== 'number';\n const updateMatchedPopupWidth = React.useCallback(() => {\n if (!shouldMatchPopupWidth) {\n return;\n }\n\n const nextWidth = selectRef.current?.getBoundingClientRect().width;\n if (nextWidth !== undefined) {\n setMatchedPopupWidth((currentWidth) =>\n currentWidth === nextWidth ? currentWidth : nextWidth,\n );\n }\n }, [shouldMatchPopupWidth]);\n const onToggleOpen = React.useCallback(\n (newOpen?: boolean) => {\n const nextOpen = newOpen !== undefined ? newOpen : !mergedOpen;\n if (nextOpen) {\n updateMatchedPopupWidth();\n }\n if (!nextOpen) {\n setShowResponsiveSelectedSection(false);\n setFocus(false);\n }\n if (mergedOpen !== nextOpen && !disabled) {\n setInnerOpen(nextOpen);\n onOpenChange?.(nextOpen);\n }\n },\n [\n mergedOpen,\n disabled,\n setInnerOpen,\n onOpenChange,\n updateMatchedPopupWidth,\n ],\n );\n React.useLayoutEffect(() => {\n if (!mergedOpen || !shouldMatchPopupWidth) {\n return;\n }\n\n const element = selectRef.current;\n if (!element) {\n return;\n }\n\n const updateMatchedWidth = () => {\n const nextWidth = element.getBoundingClientRect().width;\n setMatchedPopupWidth((currentWidth) =>\n currentWidth === nextWidth ? currentWidth : nextWidth,\n );\n };\n\n updateMatchedWidth();\n\n if (typeof ResizeObserver === 'undefined') {\n window.addEventListener('resize', updateMatchedWidth);\n return () => {\n window.removeEventListener('resize', updateMatchedWidth);\n };\n }\n\n let resizeAnimationFrame: number | undefined;\n const scheduleMatchedWidthUpdate = () => {\n if (resizeAnimationFrame !== undefined) {\n cancelAnimationFrame(resizeAnimationFrame);\n }\n resizeAnimationFrame = requestAnimationFrame(updateMatchedWidth);\n };\n\n const observer = new ResizeObserver(scheduleMatchedWidthUpdate);\n observer.observe(element);\n\n return () => {\n if (resizeAnimationFrame !== undefined) {\n cancelAnimationFrame(resizeAnimationFrame);\n }\n observer.disconnect();\n };\n }, [mergedOpen, shouldMatchPopupWidth]);\n const [showResponsiveSelectedSection, setShowResponsiveSelectedSection] =\n useState(false);\n // 多选 responsive 进入 -1 收纳态(仅\"首 tag + +N\")时为 true,\n // width:auto 下据此给根节点加 overflow-collapsed 钳住 min-width 链,\n // 抵抗父 flex 行因 intrinsic 低估造成的假压缩(详见 ald-select.css 对应段)\n const [overflowCollapsed, setOverflowCollapsed] = useState(false);\n\n // ============================ Selector ============================\n const onSelectorRemove = (val: DisplayValueType) => {\n const newValues = displayValues.filter(\n (item) => toString(item.value) !== toString(val.value),\n );\n\n onDisplayValuesChange(newValues, {\n type: 'remove',\n values: [\n {\n label: val.label,\n value: val.value as RawValueType,\n },\n ],\n });\n };\n\n const mergedClassName = cn(\n setClassNames('beta-ald-select', size, {\n active: mergedOpen || focus,\n borderless: borderLess,\n disabled: disabled,\n loading: loading,\n [`${mergedStatus}`]: !!mergedStatus,\n 'multiple-responsive': isResponsiveMode,\n 'multiple-default': isMultipleMode && !isResponsiveMode,\n // 仅 width:auto 生效:固定宽度下 -1 收纳态的收缩省略是预期行为,\n // 钳 min-width 反而会把固定宽撑破\n 'overflow-collapsed':\n overflowCollapsed && width === 'auto' && !_.isEmpty(displayValues),\n }),\n 'tw-text-typography-body-dense',\n className,\n compactItemClassnames,\n );\n const showMenu = React.useMemo(() => {\n if (!displayMenu) {\n return undefined;\n }\n\n return {\n ...displayMenu,\n onClick: (info: MenuInfo) => {\n displayMenu?.onClick?.(info);\n if (isMultipleMode) {\n // 多选默认选中后不收起下拉:Dropdown 在 menu.onClick 之后读\n // info.keepOpen 决定是否 onChangeOpen(false),不设则每次点击都被\n // 当成关闭信号。用 ?? 保留用户在自己的 onClick 里显式设 false 的能力\n info.keepOpen = info.keepOpen ?? true;\n } else if (displayMenu) {\n onToggleOpen(false);\n setFocus(false);\n }\n setIsHover(false);\n onOptionSelect?.(info.key);\n },\n };\n }, [displayMenu, isMultipleMode, onToggleOpen, onOptionSelect]);\n const onSelectClick = React.useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) {\n return;\n }\n onClick?.(e);\n },\n [disabled, onClick],\n );\n React.useEffect(() => {\n const element = selectRef.current;\n if (element) {\n const handleMouseOver = () => setIsHover(true);\n const handleMouseOut = () => setIsHover(false);\n\n element.addEventListener('mouseover', handleMouseOver);\n element.addEventListener('mouseout', handleMouseOut);\n\n return () => {\n element.removeEventListener('mouseover', handleMouseOver);\n element.removeEventListener('mouseout', handleMouseOut);\n };\n }\n }, []);\n const mergedPopupMatchSelectWidth =\n shouldMatchPopupWidth && matchedPopupWidth !== undefined\n ? matchedPopupWidth\n : popupMatchSelectWidth;\n return (\n <div\n className={mergedClassName}\n style={{\n ...widthStyle,\n // width:auto 且无选中值时锁 shrink:Chromium 对该子树给父 flex 行的\n // intrinsic 宽度贡献恒少约 14px,父行按低估值布局后回头压缩根节点,\n // placeholder 右侧会被裁;有选中值时必须保持可压缩,rc-overflow\n // 才能在父行变窄时把放不下的 tag 收纳成 \"+N\"\n ...(width === 'auto' && _.isEmpty(displayValues)\n ? { flexShrink: 0 }\n : {}),\n ...style,\n }}\n ref={selectRef}\n id={id}\n onClick={onSelectClick}\n data-testid={dataTestid}\n aria-label={ariaLabel}\n >\n <SelectTrigger\n {...restProps}\n open={!!mergedOpen}\n notFoundContent={notFoundContent}\n menu={showMenu}\n ref={dropdownRef}\n showSearch={showSearch}\n searchValue={innerSearchValue}\n setInnerSearchValue={setInnerSearchValue}\n popupMatchSelectWidth={mergedPopupMatchSelectWidth}\n overlayClassName={popupClassName}\n // @ts-ignore\n dropdownRender={dropdownRender}\n overlayStyle={overlayStyle || dropdownStyle}\n placement={placement}\n allowOverlap={allowOverlap}\n onOpenChange={(open) => {\n if (isResponsiveMode) {\n if (\n !mergedOpen &&\n !showResponsiveSelectedSection &&\n displayValues.length > 0 &&\n isShowSelectedSection(mode)\n ) {\n setShowResponsiveSelectedSection(true);\n } else {\n onToggleOpen(open);\n }\n } else {\n onToggleOpen(open);\n }\n }}\n >\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <div className={cn(setClassNames('trigger'), 'ant-select-selector')}>\n {prefix && <div className={setClassNames('prefix')}>{prefix}</div>}\n {_.isEmpty(displayValues) && (\n <div\n className={cn(\n setClassNames('placeholder'),\n 'ant-select-selection-placeholder',\n )}\n >\n {placeholder}\n </div>\n )}\n {!_.isEmpty(displayValues) && (\n <Selector\n {...restProps}\n suffixIcon={suffixIcon}\n size={size}\n disabled={disabled}\n mode={mode}\n dropdownRef={dropdownRef}\n displayValues={displayValues}\n onToggleOpen={onToggleOpen}\n onRemove={onSelectorRemove}\n showResponsiveSelectedSection={showResponsiveSelectedSection}\n onOverflowCollapsedChange={setOverflowCollapsed}\n ></Selector>\n )}\n </div>\n </SelectTrigger>\n <Suffix\n showArrow={showArrow}\n allowClear={allowClear}\n disabled={disabled}\n loading={loading}\n isHover={isHover}\n onClear={() => {\n onToggleOpen(false);\n\n onDisplayValuesChange([], {\n type: 'clear',\n values: displayValues,\n });\n onClear?.();\n }}\n isActive={innerOpen}\n icon={suffixIcon}\n displayValues={displayValues}\n ></Suffix>\n </div>\n );\n },\n);\n\nexport default BaseSelect;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAgIA,SAAgB,WAAW,MAAa;AACtC,QAAO,CAAC,CAAC;;AAEX,SAAgB,aAAa,MAAa;AACxC,QAAO,SAAS,cAAe,OAAO,SAAS,YAAY,MAAM;;AAEnE,SAAgB,sBAAsB,MAAa;AACjD,KAAI,CAAC,QAAQ,SAAS,WACpB,QAAO;AAGT,QACE,OAAO,SAAS,YAAY,KAAK,uBAAuB,KAAK;;AAGjE,IAAM,aAAa,QAAM,YACtB,OAAwB,QAAkC;CACzD,MAAM,EACJ,IACA,WAEA,eACA,uBACA,aACA,iBACA,SACA,OACA,MACA,QAAQ,cACR,gBACA,SACA,MAAM,YACN,aAAa,OAEb,UACA,aACA,UAAU,OAGV,MACA,aACA,cACA,YACA,kBACA,qBAEA,YACA,YAAY,MACZ,QACA,YACA,gBACA,cACA,eACA,wBAAwB,MACxB,WACA,gBACA,cACA,OACA,eAAe,YACf,cAAc,WACd,GAAG,cAED;CACJ,MAAM,gBAAgB,UAAU,SAAS;CACzC,MAAM,YAAY,OAAuB,KAAK;CAC9C,MAAM,aAAa,cAAc,MAAM;CACvC,MAAM,cAAc,OAAwB,KAAK;CACjD,MAAM,CAAC,mBAAmB,wBAAwB,UAE/C;CACH,MAAM,mBAAmB,aAAa,KAAK;CAC3C,MAAM,iBAAiB,WAAW,KAAK;;CAEvC,MAAM,cAAc,WAAW,YAAY;CAC3C,MAAM,EAAE,cAAc,QAAM,WAAW,cAAc;CAErD,MAAM,EAAE,aAAa,0BAA0B,sBAC7C,cACA,UACD;CACD,MAAM,OAAO,eAAe,cAAc,eAAe;CACzD,MAAM,EACJ,QAAQ,kBAIN,WAAW,qBAAqB;CAEpC,MAAM,eACJ,iBAAiB,OAAO,SAAY,gBAAgB;AAGtD,SAAM,oBAAoB,YAAY;EACpC,aAAa,SAAS,KAAK;EAC3B,YAAY,SAAS,MAAM;EAC3B,YAAY,aAAa,KAAK;EAC9B,aAAa;AACX,WAAQ,IAAI,YAAY;AACxB,gBAAa,MAAM;;EAEtB,EAAE;CACH,MAAM,CAAC,OAAO,YAAY,SAAS,MAAM;CACzC,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAE7C,MAAM,CAAC,WAAW,gBAAgB,eAAwB,OAAO;EAC/D,cAAc;EACd,OAAO;EACR,CAAC;CACF,MAAM,aAAa;CACnB,MAAM,wBACJ,CAAC,CAAC,yBAAyB,OAAO,0BAA0B;CAC9D,MAAM,0BAA0B,QAAM,kBAAkB;AACtD,MAAI,CAAC,sBACH;EAGF,MAAM,YAAY,UAAU,SAAS,uBAAuB,CAAC;AAC7D,MAAI,cAAc,OAChB,uBAAsB,iBACpB,iBAAiB,YAAY,eAAe,UAC7C;IAEF,CAAC,sBAAsB,CAAC;CAC3B,MAAM,eAAe,QAAM,aACxB,YAAsB;EACrB,MAAM,WAAW,YAAY,SAAY,UAAU,CAAC;AACpD,MAAI,SACF,0BAAyB;AAE3B,MAAI,CAAC,UAAU;AACb,oCAAiC,MAAM;AACvC,YAAS,MAAM;;AAEjB,MAAI,eAAe,YAAY,CAAC,UAAU;AACxC,gBAAa,SAAS;AACtB,kBAAe,SAAS;;IAG5B;EACE;EACA;EACA;EACA;EACA;EACD,CACF;AACD,SAAM,sBAAsB;AAC1B,MAAI,CAAC,cAAc,CAAC,sBAClB;EAGF,MAAM,UAAU,UAAU;AAC1B,MAAI,CAAC,QACH;EAGF,MAAM,2BAA2B;GAC/B,MAAM,YAAY,QAAQ,uBAAuB,CAAC;AAClD,yBAAsB,iBACpB,iBAAiB,YAAY,eAAe,UAC7C;;AAGH,sBAAoB;AAEpB,MAAI,OAAO,mBAAmB,aAAa;AACzC,UAAO,iBAAiB,UAAU,mBAAmB;AACrD,gBAAa;AACX,WAAO,oBAAoB,UAAU,mBAAmB;;;EAI5D,IAAI;EACJ,MAAM,mCAAmC;AACvC,OAAI,yBAAyB,OAC3B,sBAAqB,qBAAqB;AAE5C,0BAAuB,sBAAsB,mBAAmB;;EAGlE,MAAM,WAAW,IAAI,eAAe,2BAA2B;AAC/D,WAAS,QAAQ,QAAQ;AAEzB,eAAa;AACX,OAAI,yBAAyB,OAC3B,sBAAqB,qBAAqB;AAE5C,YAAS,YAAY;;IAEtB,CAAC,YAAY,sBAAsB,CAAC;CACvC,MAAM,CAAC,+BAA+B,oCACpC,SAAS,MAAM;CAIjB,MAAM,CAAC,mBAAmB,wBAAwB,SAAS,MAAM;CAGjE,MAAM,oBAAoB,QAA0B;AAKlD,wBAJkB,cAAc,QAC7B,SAAS,SAAS,KAAK,MAAM,KAAK,SAAS,IAAI,MAAM,CACvD,EAEgC;GAC/B,MAAM;GACN,QAAQ,CACN;IACE,OAAO,IAAI;IACX,OAAO,IAAI;IACZ,CACF;GACF,CAAC;;CAGJ,MAAM,kBAAkB,GACtB,cAAc,mBAAmB,MAAM;EACrC,QAAQ,cAAc;EACtB,YAAY;EACF;EACD;GACR,GAAG,iBAAiB,CAAC,CAAC;EACvB,uBAAuB;EACvB,oBAAoB,kBAAkB,CAAC;EAGvC,sBACE,qBAAqB,UAAU,UAAU,CAAC,EAAE,QAAQ,cAAc;EACrE,CAAC,EACF,iCACA,WACA,sBACD;CACD,MAAM,WAAW,QAAM,cAAc;AACnC,MAAI,CAAC,YACH;AAGF,SAAO;GACL,GAAG;GACH,UAAU,SAAmB;AAC3B,iBAAa,UAAU,KAAK;AAC5B,QAAI,eAIF,MAAK,WAAW,KAAK,YAAY;aACxB,aAAa;AACtB,kBAAa,MAAM;AACnB,cAAS,MAAM;;AAEjB,eAAW,MAAM;AACjB,qBAAiB,KAAK,IAAI;;GAE7B;IACA;EAAC;EAAa;EAAgB;EAAc;EAAe,CAAC;CAC/D,MAAM,gBAAgB,QAAM,aACzB,MAAwC;AACvC,MAAI,SACF;AAEF,YAAU,EAAE;IAEd,CAAC,UAAU,QAAQ,CACpB;AACD,SAAM,gBAAgB;EACpB,MAAM,UAAU,UAAU;AAC1B,MAAI,SAAS;GACX,MAAM,wBAAwB,WAAW,KAAK;GAC9C,MAAM,uBAAuB,WAAW,MAAM;AAE9C,WAAQ,iBAAiB,aAAa,gBAAgB;AACtD,WAAQ,iBAAiB,YAAY,eAAe;AAEpD,gBAAa;AACX,YAAQ,oBAAoB,aAAa,gBAAgB;AACzD,YAAQ,oBAAoB,YAAY,eAAe;;;IAG1D,EAAE,CAAC;CACN,MAAM,8BACJ,yBAAyB,sBAAsB,SAC3C,oBACA;AACN,QACE,qBAAC,OAAD;EACE,WAAW;EACX,OAAO;GACL,GAAG;GAKH,GAAI,UAAU,UAAU,EAAE,QAAQ,cAAc,GAC5C,EAAE,YAAY,GAAG,GACjB,EAAE;GACN,GAAG;GACJ;EACD,KAAK;EACD;EACJ,SAAS;EACT,eAAa;EACb,cAAY;YAjBd,CAmBE,oBAAC,kBAAD;GACE,GAAI;GACJ,MAAM,CAAC,CAAC;GACS;GACjB,MAAM;GACN,KAAK;GACO;GACZ,aAAa;GACQ;GACrB,uBAAuB;GACvB,kBAAkB;GAEF;GAChB,cAAc,gBAAgB;GACnB;GACG;GACd,eAAe,SAAS;AACtB,QAAI,iBACF,KACE,CAAC,cACD,CAAC,iCACD,cAAc,SAAS,KACvB,sBAAsB,KAAK,CAE3B,kCAAiC,KAAK;QAEtC,cAAa,KAAK;QAGpB,cAAa,KAAK;;aAKtB,qBAAC,OAAD;IAAK,WAAW,GAAG,cAAc,UAAU,EAAE,sBAAsB;cAAnE;KACG,UAAU,oBAAC,OAAD;MAAK,WAAW,cAAc,SAAS;gBAAG;MAAa,CAAA;KACjE,EAAE,QAAQ,cAAc,IACvB,oBAAC,OAAD;MACE,WAAW,GACT,cAAc,cAAc,EAC5B,mCACD;gBAEA;MACG,CAAA;KAEP,CAAC,EAAE,QAAQ,cAAc,IACxB,oBAAC,UAAD;MACE,GAAI;MACQ;MACN;MACI;MACJ;MACO;MACE;MACD;MACd,UAAU;MACqB;MAC/B,2BAA2B;MACjB,CAAA;KAEV;;GACQ,CAAA,EAChB,oBAAC,QAAD;GACa;GACC;GACF;GACD;GACA;GACT,eAAe;AACb,iBAAa,MAAM;AAEnB,0BAAsB,EAAE,EAAE;KACxB,MAAM;KACN,QAAQ;KACT,CAAC;AACF,eAAW;;GAEb,UAAU;GACV,MAAM;GACS;GACP,CAAA,CACN;;EAGX"}
|
|
1
|
+
{"version":3,"file":"BaseSelect.js","names":[],"sources":["../../src/Select/BaseSelect.tsx"],"sourcesContent":["import './ald-select.css';\nimport * as React from 'react';\nimport useMergedState from 'rc-util/es/hooks/useMergedState';\nimport { cn } from '../lib/utils';\nimport prefixCls from '../_utils/prefixCls';\n\n/** Align config type (locally defined to avoid rc-trigger dependency) */\nexport interface AlignType {\n points?: string[];\n offset?: (number | string)[];\n targetOffset?: (number | string)[];\n overflow?: { adjustX?: boolean; adjustY?: boolean };\n _experimental?: Record<string, any>;\n}\nimport SelectTrigger, { RefTriggerProps } from './SelectTrigger';\nimport Selector from './Selector';\nimport _ from 'lodash';\nimport { useContext, useRef, useState } from 'react';\nimport { FormItemInputContext } from '../Form/FormItemContext';\nimport getWidthStyle from './utils/getWidthStyle';\nimport Suffix from './components/Suffix';\nimport { PlacementType } from '../Dropdown';\nimport {\n BaseSelectRef,\n DisplayValueType,\n ISelectProps,\n LabelInValueType,\n SelectMenuProps,\n} from './interface';\nimport SizeContext from '../ConfigProvider/sizeContext';\nimport { ConfigContext } from '../ConfigProvider';\nimport { useCompactItemContext } from '../Space/CompactContext';\nimport { MenuInfo } from '../Menu';\nimport { toString } from './utils/commonUtil';\nimport OptionCollection, {\n SelectOptionCollection,\n} from './components/OptionCollection';\n\nexport type RenderNode = React.ReactNode | ((props: any) => React.ReactNode);\n\nexport type RenderDOMFunc = (props: any) => HTMLElement;\n\nexport type Mode =\n | 'multiple'\n | {\n type: 'multiple';\n responsive?: boolean;\n maxRows?: number;\n showSelectedSection?: boolean;\n };\n\nexport type RawValueType = string | number;\n\nfunction splitAriaProps(props: Record<string, any>) {\n return Object.keys(props).reduce<{\n ariaProps: Record<string, any>;\n restProps: Record<string, any>;\n }>(\n (result, key) => {\n if (key.startsWith('aria-')) {\n result.ariaProps[key] = props[key];\n } else {\n result.restProps[key] = props[key];\n }\n return result;\n },\n { ariaProps: {}, restProps: {} },\n );\n}\n\nexport type CustomTagProps = {\n label: React.ReactNode;\n value: any;\n disabled: boolean;\n onClose: (event?: React.MouseEvent<HTMLElement, MouseEvent>) => void;\n closable: boolean;\n};\nexport interface BaseSelectPrivateProps {\n // >>> MISC\n omitDomProps?: string[];\n\n // >>> Value\n displayValues: LabelInValueType[];\n onDisplayValuesChange: (\n values: LabelInValueType[],\n info: {\n type: 'add' | 'remove' | 'clear';\n values: LabelInValueType[];\n },\n ) => void;\n\n // >>> Active\n /** Current dropdown list active item string value */\n activeValue?: string;\n /** Link search input with target element */\n activeDescendantId?: string;\n onActiveValueChange?: (value: string | null) => void;\n}\n\nexport type BaseSelectPropsWithoutPrivate = Omit<\n BaseSelectProps,\n keyof BaseSelectPrivateProps\n>;\n\nexport interface BaseSelectProps\n extends BaseSelectPrivateProps,\n ISelectProps,\n React.AriaAttributes {\n className?: string;\n style?: React.CSSProperties;\n notFoundContent?: React.ReactNode;\n onClear?: () => void;\n innerSearchValue?: string;\n setInnerSearchValue?: (value: string) => void;\n displayMenu?: SelectMenuProps;\n optionCollection?: SelectOptionCollection;\n // >>> Open\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n onOptionSelect?: (val: RawValueType) => void;\n onCollectionOptionSelect?: (val: RawValueType) => void;\n\n // >>> Icons\n allowClear?: boolean;\n showArrow?: boolean;\n suffixIcon?: React.ReactNode;\n\n // >>> Dropdown\n dropdownAlign?: AlignType;\n placement?: PlacementType;\n getPopupContainer?: () => HTMLElement;\n\n // >>> Focus\n onBlur?: React.FocusEventHandler<HTMLElement>;\n onFocus?: React.FocusEventHandler<HTMLElement>;\n\n // >>> Rest Events\n onKeyUp?: React.KeyboardEventHandler<HTMLDivElement>;\n onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;\n onMouseDown?: React.MouseEventHandler<HTMLDivElement>;\n onPopupScroll?: React.UIEventHandler<HTMLDivElement>;\n onInputKeyDown?: React.KeyboardEventHandler<\n HTMLInputElement | HTMLTextAreaElement\n >;\n onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;\n onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;\n onClick?: React.MouseEventHandler<HTMLDivElement>;\n}\n\nexport function isMultiple(mode?: Mode) {\n return !!mode;\n}\nexport function isResponsive(mode?: Mode) {\n return mode === 'multiple' || (typeof mode === 'object' && mode?.responsive);\n}\nexport function isShowSelectedSection(mode?: Mode) {\n if (!mode || mode === 'multiple') {\n return false;\n }\n\n return (\n typeof mode === 'object' && mode.showSelectedSection && mode.responsive\n );\n}\nconst BaseSelect = React.forwardRef(\n (props: BaseSelectProps, ref: React.Ref<BaseSelectRef>) => {\n const {\n id,\n className,\n // Value\n displayValues,\n onDisplayValuesChange,\n displayMenu,\n optionCollection,\n notFoundContent,\n onClear,\n width,\n mode,\n status: customStatus,\n onOptionSelect,\n onCollectionOptionSelect,\n onClick,\n size: customSize,\n borderLess = false,\n // Status\n disabled,\n placeholder,\n loading = false,\n\n // Open\n open,\n defaultOpen,\n onOpenChange,\n showSearch,\n innerSearchValue,\n setInnerSearchValue,\n onInputKeyDown,\n // Icons\n allowClear,\n showArrow = true,\n prefix,\n suffixIcon,\n dropdownRender,\n overlayStyle,\n dropdownStyle,\n popupMatchSelectWidth = true,\n placement,\n popupClassName,\n allowOverlap,\n style,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n ...restProps\n // Rest Props\n } = props;\n const { ariaProps, restProps: passthroughProps } = React.useMemo(\n () => splitAriaProps(restProps),\n [restProps],\n );\n const triggerAriaProps = React.useMemo<React.AriaAttributes>(\n () => ({\n ...ariaProps,\n 'aria-label': ariaLabel,\n }),\n [ariaLabel, ariaProps],\n );\n const setClassNames = prefixCls('select');\n const selectRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const widthStyle = getWidthStyle(width);\n const dropdownRef = useRef<RefTriggerProps>(null);\n const [matchedPopupWidth, setMatchedPopupWidth] = useState<\n number | undefined\n >();\n const isResponsiveMode = isResponsive(mode);\n const isMultipleMode = isMultiple(mode);\n /** Used for component focused management */\n const contentSize = useContext(SizeContext);\n const { direction } = React.useContext(ConfigContext);\n // ===================== Compact Item =====================\n const { compactSize, compactItemClassnames } = useCompactItemContext(\n 'ald-select',\n direction,\n );\n const size = compactSize || customSize || contentSize || 'middle';\n const {\n status: contextStatus,\n // hasFeedback,\n // isFormItemInput,\n // feedbackIcon,\n } = useContext(FormItemInputContext);\n\n const mergedStatus =\n customStatus === null ? undefined : customStatus || contextStatus;\n\n // =========================== Imperative ===========================\n React.useImperativeHandle(ref, () => ({\n // The trigger is the Select focus owner. Keeping this as a real DOM\n // focus target makes keyboard focus, the Focus State Layer, and the\n // public imperative API describe the same element.\n focus: () => {\n if (showSearch && optionCollection) {\n searchInputRef.current?.focus();\n } else {\n triggerRef.current?.focus();\n }\n },\n blur: () => {\n if (showSearch && optionCollection) {\n searchInputRef.current?.blur();\n } else {\n triggerRef.current?.blur();\n }\n },\n open: () => onToggleOpen(true),\n close: () => {\n console.log('ref close');\n onToggleOpen(false);\n },\n }));\n const [isHover, setIsHover] = useState(false);\n const [activeOptionKey, setActiveOptionKey] = useState<string>();\n const [composingSearchValue, setComposingSearchValue] = useState<\n string | undefined\n >();\n const isComposingSearchRef = useRef(false);\n const isSearchableCollection = !!optionCollection && !!showSearch;\n const ownerAriaProps = React.useMemo(\n () => ({\n ...triggerAriaProps,\n 'aria-busy': loading || triggerAriaProps['aria-busy'] || undefined,\n 'aria-invalid':\n triggerAriaProps['aria-invalid'] ??\n (mergedStatus === 'error' ? true : undefined),\n }),\n [loading, mergedStatus, triggerAriaProps],\n );\n // ============================== Open ==============================\n const [innerOpen, setInnerOpen] = useMergedState<boolean>(false, {\n defaultValue: defaultOpen,\n value: open,\n });\n const mergedOpen = innerOpen;\n const shouldMatchPopupWidth =\n !!popupMatchSelectWidth && typeof popupMatchSelectWidth !== 'number';\n const updateMatchedPopupWidth = React.useCallback(() => {\n if (!shouldMatchPopupWidth) {\n return;\n }\n\n const nextWidth = selectRef.current?.getBoundingClientRect().width;\n if (nextWidth !== undefined) {\n setMatchedPopupWidth((currentWidth) =>\n currentWidth === nextWidth ? currentWidth : nextWidth,\n );\n }\n }, [shouldMatchPopupWidth]);\n const onToggleOpen = React.useCallback(\n (newOpen?: boolean) => {\n const nextOpen = newOpen !== undefined ? newOpen : !mergedOpen;\n if (nextOpen) {\n updateMatchedPopupWidth();\n }\n if (!nextOpen) {\n setShowResponsiveSelectedSection(false);\n }\n if (mergedOpen !== nextOpen && !disabled) {\n setInnerOpen(nextOpen);\n onOpenChange?.(nextOpen);\n }\n },\n [\n mergedOpen,\n disabled,\n setInnerOpen,\n onOpenChange,\n updateMatchedPopupWidth,\n ],\n );\n const getInitialActiveOptionKey = React.useCallback(\n (position: 'first' | 'last') => {\n if (!optionCollection) {\n return undefined;\n }\n\n if (position === 'last') {\n return optionCollection.enabledOptions[\n optionCollection.enabledOptions.length - 1\n ]?.key;\n }\n\n const selected = optionCollection.options.find(\n (option) =>\n !option.disabled &&\n displayValues.some(\n (value) => toString(value.value) === toString(option.value),\n ),\n );\n return selected?.key ?? optionCollection.enabledOptions[0]?.key;\n },\n [displayValues, optionCollection],\n );\n React.useEffect(() => {\n if (!optionCollection || !mergedOpen) {\n setActiveOptionKey(undefined);\n return;\n }\n\n setActiveOptionKey((current) =>\n optionCollection.enabledOptions.some((option) => option.key === current)\n ? current\n : getInitialActiveOptionKey('first'),\n );\n }, [getInitialActiveOptionKey, mergedOpen, optionCollection]);\n React.useLayoutEffect(() => {\n if (!mergedOpen || !shouldMatchPopupWidth) {\n return;\n }\n\n const element = selectRef.current;\n if (!element) {\n return;\n }\n\n const updateMatchedWidth = () => {\n const nextWidth = element.getBoundingClientRect().width;\n setMatchedPopupWidth((currentWidth) =>\n currentWidth === nextWidth ? currentWidth : nextWidth,\n );\n };\n\n updateMatchedWidth();\n\n if (typeof ResizeObserver === 'undefined') {\n window.addEventListener('resize', updateMatchedWidth);\n return () => {\n window.removeEventListener('resize', updateMatchedWidth);\n };\n }\n\n let resizeAnimationFrame: number | undefined;\n const scheduleMatchedWidthUpdate = () => {\n if (resizeAnimationFrame !== undefined) {\n cancelAnimationFrame(resizeAnimationFrame);\n }\n resizeAnimationFrame = requestAnimationFrame(updateMatchedWidth);\n };\n\n const observer = new ResizeObserver(scheduleMatchedWidthUpdate);\n observer.observe(element);\n\n return () => {\n if (resizeAnimationFrame !== undefined) {\n cancelAnimationFrame(resizeAnimationFrame);\n }\n observer.disconnect();\n };\n }, [mergedOpen, shouldMatchPopupWidth]);\n const [showResponsiveSelectedSection, setShowResponsiveSelectedSection] =\n useState(false);\n // 多选 responsive 进入 -1 收纳态(仅\"首 tag + +N\")时为 true,\n // width:auto 下据此给根节点加 overflow-collapsed 钳住 min-width 链,\n // 抵抗父 flex 行因 intrinsic 低估造成的假压缩(详见 ald-select.css 对应段)\n const [overflowCollapsed, setOverflowCollapsed] = useState(false);\n\n // ============================ Selector ============================\n const onSelectorRemove = (val: DisplayValueType) => {\n const newValues = displayValues.filter(\n (item) => toString(item.value) !== toString(val.value),\n );\n\n onDisplayValuesChange(newValues, {\n type: 'remove',\n values: [\n {\n label: val.label,\n value: val.value as RawValueType,\n },\n ],\n });\n };\n\n const mergedClassName = cn(\n setClassNames('beta-ald-select', size, {\n // Popup visibility is not focus. The trigger's :focus-visible state\n // owns the Focus State Layer in ald-select.css.\n open: mergedOpen,\n // Retain the legacy hook for consumers that style the open state.\n // It no longer represents trigger focus.\n active: mergedOpen,\n borderless: borderLess,\n disabled: disabled,\n loading: loading,\n [`${mergedStatus}`]: !!mergedStatus,\n 'multiple-responsive': isResponsiveMode,\n 'multiple-default': isMultipleMode && !isResponsiveMode,\n // 仅 width:auto 生效:固定宽度下 -1 收纳态的收缩省略是预期行为,\n // 钳 min-width 反而会把固定宽撑破\n 'overflow-collapsed':\n overflowCollapsed && width === 'auto' && !_.isEmpty(displayValues),\n }),\n 'tw-text-typography-body-dense',\n className,\n compactItemClassnames,\n );\n const showMenu = React.useMemo(() => {\n if (!displayMenu) {\n return undefined;\n }\n\n return {\n ...displayMenu,\n onClick: (info: MenuInfo) => {\n displayMenu?.onClick?.(info);\n if (isMultipleMode) {\n // 多选默认选中后不收起下拉:Dropdown 在 menu.onClick 之后读\n // info.keepOpen 决定是否 onChangeOpen(false),不设则每次点击都被\n // 当成关闭信号。用 ?? 保留用户在自己的 onClick 里显式设 false 的能力\n info.keepOpen = info.keepOpen ?? true;\n } else if (displayMenu) {\n onToggleOpen(false);\n }\n setIsHover(false);\n onOptionSelect?.(info.key);\n },\n };\n }, [displayMenu, isMultipleMode, onToggleOpen, onOptionSelect]);\n const onSelectClick = React.useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) {\n return;\n }\n onClick?.(e);\n },\n [disabled, onClick],\n );\n React.useEffect(() => {\n const element = selectRef.current;\n if (element) {\n const handleMouseOver = () => setIsHover(true);\n const handleMouseOut = () => setIsHover(false);\n\n element.addEventListener('mouseover', handleMouseOver);\n element.addEventListener('mouseout', handleMouseOut);\n\n return () => {\n element.removeEventListener('mouseover', handleMouseOver);\n element.removeEventListener('mouseout', handleMouseOut);\n };\n }\n }, []);\n const mergedPopupMatchSelectWidth =\n shouldMatchPopupWidth && matchedPopupWidth !== undefined\n ? matchedPopupWidth\n : popupMatchSelectWidth;\n const activeOptionId = optionCollection?.options.find(\n (option) => option.key === activeOptionKey,\n )?.id;\n const moveActiveOption = React.useCallback(\n (direction: 1 | -1) => {\n if (!optionCollection || optionCollection.enabledOptions.length === 0) {\n return;\n }\n\n const currentIndex = optionCollection.enabledOptions.findIndex(\n (option) => option.key === activeOptionKey,\n );\n const nextIndex =\n currentIndex === -1\n ? direction === 1\n ? 0\n : optionCollection.enabledOptions.length - 1\n : (currentIndex +\n direction +\n optionCollection.enabledOptions.length) %\n optionCollection.enabledOptions.length;\n setActiveOptionKey(optionCollection.enabledOptions[nextIndex].key);\n },\n [activeOptionKey, optionCollection],\n );\n const typeaheadRef = useRef({ value: '', timestamp: 0 });\n const onCollectionKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLElement>) => {\n if (!optionCollection || disabled) {\n return;\n }\n\n const openCollection = (position: 'first' | 'last') => {\n event.preventDefault();\n setActiveOptionKey(getInitialActiveOptionKey(position));\n onToggleOpen(true);\n };\n\n if (!mergedOpen) {\n if (event.key === 'ArrowDown') {\n openCollection('first');\n } else if (event.key === 'ArrowUp') {\n openCollection('last');\n } else if (event.key === 'Enter' || event.key === ' ') {\n openCollection('first');\n }\n return;\n }\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n moveActiveOption(1);\n return;\n }\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n moveActiveOption(-1);\n return;\n }\n if (event.key === 'Home') {\n event.preventDefault();\n setActiveOptionKey(optionCollection.enabledOptions[0]?.key);\n return;\n }\n if (event.key === 'End') {\n event.preventDefault();\n setActiveOptionKey(\n optionCollection.enabledOptions[\n optionCollection.enabledOptions.length - 1\n ]?.key,\n );\n return;\n }\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n const activeOption = optionCollection.options.find(\n (option) => option.key === activeOptionKey,\n );\n if (activeOption && !activeOption.disabled) {\n if (!isMultipleMode) {\n onToggleOpen(false);\n }\n onCollectionOptionSelect?.(activeOption.value);\n }\n return;\n }\n if (event.key === 'Escape') {\n event.preventDefault();\n onToggleOpen(false);\n if (isSearchableCollection) {\n searchInputRef.current?.focus();\n } else {\n triggerRef.current?.focus();\n }\n return;\n }\n if (event.key === 'Tab') {\n onToggleOpen(false);\n return;\n }\n if (\n event.key.length === 1 &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey\n ) {\n const now = Date.now();\n const query =\n now - typeaheadRef.current.timestamp > 500\n ? event.key\n : `${typeaheadRef.current.value}${event.key}`;\n typeaheadRef.current = { value: query, timestamp: now };\n const normalizedQuery = query.toLocaleLowerCase();\n const activeIndex = optionCollection.enabledOptions.findIndex(\n (option) => option.key === activeOptionKey,\n );\n const orderedOptions = [\n ...optionCollection.enabledOptions.slice(activeIndex + 1),\n ...optionCollection.enabledOptions.slice(0, activeIndex + 1),\n ];\n const match = orderedOptions.find((option) =>\n String(option.label ?? option.value)\n .toLocaleLowerCase()\n .startsWith(normalizedQuery),\n );\n if (match) {\n event.preventDefault();\n setActiveOptionKey(match.key);\n }\n }\n },\n [\n activeOptionKey,\n disabled,\n getInitialActiveOptionKey,\n mergedOpen,\n moveActiveOption,\n onCollectionOptionSelect,\n onToggleOpen,\n optionCollection,\n isSearchableCollection,\n ],\n );\n const onSearchInputKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLInputElement>) => {\n onInputKeyDown?.(event);\n if (event.defaultPrevented) {\n return;\n }\n\n if (\n event.key === ' ' ||\n (event.key.length === 1 &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey)\n ) {\n return;\n }\n\n onCollectionKeyDown(event);\n },\n [onCollectionKeyDown, onInputKeyDown],\n );\n const onSearchInputChange = React.useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const nextValue = event.target.value;\n if (isComposingSearchRef.current) {\n setComposingSearchValue(nextValue);\n return;\n }\n setInnerSearchValue?.(nextValue);\n },\n [setInnerSearchValue],\n );\n const searchInputValue = composingSearchValue ?? innerSearchValue ?? '';\n const collectionContent = optionCollection ? (\n <OptionCollection\n collection={optionCollection}\n selectedValues={displayValues.map((item) => item.value as RawValueType)}\n activeOptionKey={activeOptionKey}\n multiple={isMultipleMode}\n loading={loading}\n listHeight={props.listHeight ?? 256}\n notFoundContent={notFoundContent}\n onSelect={(value) => {\n if (!isMultipleMode) {\n onToggleOpen(false);\n }\n onCollectionOptionSelect?.(value);\n }}\n />\n ) : undefined;\n return (\n <div\n className={mergedClassName}\n style={{\n ...widthStyle,\n // width:auto 且无选中值时锁 shrink:Chromium 对该子树给父 flex 行的\n // intrinsic 宽度贡献恒少约 14px,父行按低估值布局后回头压缩根节点,\n // placeholder 右侧会被裁;有选中值时必须保持可压缩,rc-overflow\n // 才能在父行变窄时把放不下的 tag 收纳成 \"+N\"\n ...(width === 'auto' && _.isEmpty(displayValues)\n ? { flexShrink: 0 }\n : {}),\n ...style,\n }}\n ref={selectRef}\n id={id}\n onClick={onSelectClick}\n data-testid={dataTestid}\n aria-label={ariaLabel}\n >\n <SelectTrigger\n {...passthroughProps}\n open={!!mergedOpen}\n notFoundContent={notFoundContent}\n menu={showMenu}\n collection={collectionContent}\n ref={dropdownRef}\n showSearch={showSearch}\n searchValue={innerSearchValue}\n setInnerSearchValue={setInnerSearchValue}\n popupMatchSelectWidth={mergedPopupMatchSelectWidth}\n overlayClassName={popupClassName}\n // @ts-ignore\n dropdownRender={dropdownRender}\n overlayStyle={overlayStyle || dropdownStyle}\n placement={placement}\n allowOverlap={allowOverlap}\n onOpenChange={(open) => {\n if (isResponsiveMode) {\n if (\n !mergedOpen &&\n !showResponsiveSelectedSection &&\n displayValues.length > 0 &&\n isShowSelectedSection(mode)\n ) {\n setShowResponsiveSelectedSection(true);\n } else {\n onToggleOpen(open);\n }\n } else {\n onToggleOpen(open);\n }\n }}\n >\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <div\n {...(!isSearchableCollection ? ownerAriaProps : {})}\n ref={triggerRef}\n tabIndex={isSearchableCollection || disabled ? undefined : 0}\n role={isSearchableCollection ? undefined : 'combobox'}\n aria-disabled={\n isSearchableCollection ? undefined : disabled || undefined\n }\n aria-expanded={isSearchableCollection ? undefined : mergedOpen}\n aria-haspopup={\n isSearchableCollection\n ? undefined\n : optionCollection\n ? 'listbox'\n : undefined\n }\n aria-controls={\n isSearchableCollection\n ? undefined\n : mergedOpen && optionCollection\n ? optionCollection.listboxId\n : undefined\n }\n aria-activedescendant={\n isSearchableCollection\n ? undefined\n : mergedOpen && optionCollection\n ? activeOptionId\n : undefined\n }\n onKeyDown={\n isSearchableCollection\n ? undefined\n : optionCollection\n ? onCollectionKeyDown\n : undefined\n }\n className={cn(setClassNames('trigger'), 'ant-select-selector')}\n >\n {prefix && <div className={setClassNames('prefix')}>{prefix}</div>}\n {isSearchableCollection ? (\n <input\n {...ownerAriaProps}\n ref={searchInputRef}\n type=\"text\"\n role=\"combobox\"\n className={setClassNames('search-input')}\n value={searchInputValue}\n disabled={disabled}\n placeholder={\n typeof placeholder === 'string' ? placeholder : undefined\n }\n aria-disabled={disabled || undefined}\n aria-expanded={mergedOpen}\n aria-haspopup=\"listbox\"\n aria-controls={\n mergedOpen ? optionCollection?.listboxId : undefined\n }\n aria-activedescendant={mergedOpen ? activeOptionId : undefined}\n onFocus={() => onToggleOpen(true)}\n onChange={onSearchInputChange}\n onCompositionStart={() => {\n isComposingSearchRef.current = true;\n }}\n onCompositionEnd={(event) => {\n isComposingSearchRef.current = false;\n setComposingSearchValue(undefined);\n setInnerSearchValue?.(event.currentTarget.value);\n }}\n onKeyDown={onSearchInputKeyDown}\n />\n ) : (\n <>\n {_.isEmpty(displayValues) && (\n <div\n className={cn(\n setClassNames('placeholder'),\n 'ant-select-selection-placeholder',\n )}\n >\n {placeholder}\n </div>\n )}\n {!_.isEmpty(displayValues) && (\n <Selector\n {...passthroughProps}\n suffixIcon={suffixIcon}\n size={size}\n disabled={disabled}\n mode={mode}\n dropdownRef={dropdownRef}\n displayValues={displayValues}\n onToggleOpen={onToggleOpen}\n onRemove={onSelectorRemove}\n showResponsiveSelectedSection={\n showResponsiveSelectedSection\n }\n onOverflowCollapsedChange={setOverflowCollapsed}\n ></Selector>\n )}\n </>\n )}\n </div>\n </SelectTrigger>\n <Suffix\n showArrow={showArrow}\n allowClear={allowClear}\n disabled={disabled}\n loading={loading}\n isHover={isHover}\n onClear={() => {\n onToggleOpen(false);\n\n onDisplayValuesChange([], {\n type: 'clear',\n values: displayValues,\n });\n onClear?.();\n }}\n isActive={innerOpen}\n icon={suffixIcon}\n displayValues={displayValues}\n ></Suffix>\n </div>\n );\n },\n);\n\nexport default BaseSelect;\n"],"mappings":"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"}
|
|
@@ -18,6 +18,8 @@ export interface SelectTriggerProps extends IDropdownProps {
|
|
|
18
18
|
searchValue?: string;
|
|
19
19
|
setInnerSearchValue?: (value: string) => void;
|
|
20
20
|
filterOption?: (inputValue: string, option: SelectOptionType) => boolean;
|
|
21
|
+
/** Private Select-owned popup collection for the flat standard path. */
|
|
22
|
+
collection?: React.ReactNode;
|
|
21
23
|
}
|
|
22
24
|
declare const RefSelectTrigger: React.ForwardRefExoticComponent<SelectTriggerProps & React.RefAttributes<RefTriggerProps>>;
|
|
23
25
|
export default RefSelectTrigger;
|
|
@@ -7,20 +7,20 @@ import React, { useCallback } from "react";
|
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
//#region src/Select/SelectTrigger.tsx
|
|
9
9
|
var RefSelectTrigger = React.forwardRef((props, ref) => {
|
|
10
|
-
const { overlayStyle, disabled, open, children, dropdownRender, getPopupContainer, onOpenChange, showSearch, searchValue, setInnerSearchValue, menu: menuProps, overlayClassName, placement = "bottom-start", popupMatchSelectWidth, notFoundContent = /* @__PURE__ */ jsx(Empty, { size: "small" }), ...restProps } = props;
|
|
10
|
+
const { overlayStyle, disabled, open, children, dropdownRender, getPopupContainer, onOpenChange, showSearch, searchValue, setInnerSearchValue, menu: menuProps, collection, overlayClassName, placement = "bottom-start", popupMatchSelectWidth, notFoundContent = /* @__PURE__ */ jsx(Empty, { size: "small" }), ...restProps } = props;
|
|
11
11
|
const popupRef = React.useRef(null);
|
|
12
12
|
React.useImperativeHandle(ref, () => ({ getPopupElement: () => popupRef.current }));
|
|
13
13
|
const customDropdownRender = useCallback((menu) => {
|
|
14
14
|
return /* @__PURE__ */ jsxs("div", {
|
|
15
15
|
className: "beta-ald-select-popup",
|
|
16
16
|
ref: popupRef,
|
|
17
|
-
children: [/* @__PURE__ */ jsx(SearchBox_default, {
|
|
17
|
+
children: [!collection && /* @__PURE__ */ jsx(SearchBox_default, {
|
|
18
18
|
showSearch,
|
|
19
19
|
value: searchValue,
|
|
20
20
|
onChange: (value) => {
|
|
21
21
|
setInnerSearchValue?.(value);
|
|
22
22
|
}
|
|
23
|
-
}), /* @__PURE__ */ jsx(PopupContent, {
|
|
23
|
+
}), collection || /* @__PURE__ */ jsx(PopupContent, {
|
|
24
24
|
content: menu,
|
|
25
25
|
notFoundContent,
|
|
26
26
|
dropdownRender,
|
|
@@ -29,6 +29,7 @@ var RefSelectTrigger = React.forwardRef((props, ref) => {
|
|
|
29
29
|
});
|
|
30
30
|
}, [
|
|
31
31
|
dropdownRender,
|
|
32
|
+
collection,
|
|
32
33
|
menuProps,
|
|
33
34
|
notFoundContent,
|
|
34
35
|
searchValue,
|
|
@@ -39,7 +40,7 @@ var RefSelectTrigger = React.forwardRef((props, ref) => {
|
|
|
39
40
|
...restProps,
|
|
40
41
|
disabled,
|
|
41
42
|
open,
|
|
42
|
-
menu: menuProps,
|
|
43
|
+
menu: collection ? void 0 : menuProps,
|
|
43
44
|
placement,
|
|
44
45
|
popupMatchTriggerWidth: popupMatchSelectWidth,
|
|
45
46
|
overlayStyle,
|
|
@@ -50,7 +51,14 @@ var RefSelectTrigger = React.forwardRef((props, ref) => {
|
|
|
50
51
|
onOpenChange: (o) => {
|
|
51
52
|
onOpenChange?.(o);
|
|
52
53
|
},
|
|
53
|
-
children
|
|
54
|
+
children: collection ? /* @__PURE__ */ jsx("span", {
|
|
55
|
+
style: {
|
|
56
|
+
display: "flex",
|
|
57
|
+
flex: "1 1 auto",
|
|
58
|
+
minWidth: 0
|
|
59
|
+
},
|
|
60
|
+
children
|
|
61
|
+
}) : children
|
|
54
62
|
});
|
|
55
63
|
});
|
|
56
64
|
RefSelectTrigger.displayName = "SelectTrigger";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectTrigger.js","names":[],"sources":["../../src/Select/SelectTrigger.tsx"],"sourcesContent":["import React, { useCallback } from 'react';\nimport type { ScrollTo } from 'rc-virtual-list/es/List';\nimport Dropdown from '../Dropdown';\nimport { cn } from '../lib/utils';\nimport { IDropdownProps } from '../Dropdown';\nimport { DefaultOptionType as SelectOptionType } from './interface';\nimport SearchBox from './components/SearchBox';\nimport PopupContent from './components/PopupContent';\nimport Empty from '../Empty';\n\nexport interface RefTriggerProps {\n getPopupElement: () => HTMLDivElement | null;\n}\nexport interface RefSelectorProps {\n focus: (options?: FocusOptions) => void;\n blur: () => void;\n scrollTo?: ScrollTo;\n}\nexport interface SelectTriggerProps extends IDropdownProps {\n open: boolean;\n notFoundContent?: React.ReactNode;\n popupMatchSelectWidth?: boolean | number;\n showSearch?: boolean;\n searchValue?: string;\n setInnerSearchValue?: (value: string) => void;\n filterOption?: (inputValue: string, option: SelectOptionType) => boolean;\n}\n\nconst RefSelectTrigger = React.forwardRef<RefTriggerProps, SelectTriggerProps>(\n (props, ref) => {\n const {\n // prefixCls,\n overlayStyle,\n disabled,\n open,\n children,\n dropdownRender,\n getPopupContainer,\n onOpenChange,\n showSearch,\n searchValue,\n setInnerSearchValue,\n menu: menuProps,\n overlayClassName,\n placement = 'bottom-start',\n popupMatchSelectWidth,\n notFoundContent = <Empty size=\"small\" />,\n ...restProps\n } = props;\n\n // ======================= Ref =======================\n const popupRef = React.useRef<HTMLDivElement>(null);\n React.useImperativeHandle(ref, () => ({\n getPopupElement: () => popupRef.current,\n }));\n\n const customDropdownRender = useCallback(\n (menu: React.ReactNode) => {\n return (\n <div className=\"beta-ald-select-popup\" ref={popupRef}>\n <SearchBox\n
|
|
1
|
+
{"version":3,"file":"SelectTrigger.js","names":[],"sources":["../../src/Select/SelectTrigger.tsx"],"sourcesContent":["import React, { useCallback } from 'react';\nimport type { ScrollTo } from 'rc-virtual-list/es/List';\nimport Dropdown from '../Dropdown';\nimport { cn } from '../lib/utils';\nimport { IDropdownProps } from '../Dropdown';\nimport { DefaultOptionType as SelectOptionType } from './interface';\nimport SearchBox from './components/SearchBox';\nimport PopupContent from './components/PopupContent';\nimport Empty from '../Empty';\n\nexport interface RefTriggerProps {\n getPopupElement: () => HTMLDivElement | null;\n}\nexport interface RefSelectorProps {\n focus: (options?: FocusOptions) => void;\n blur: () => void;\n scrollTo?: ScrollTo;\n}\nexport interface SelectTriggerProps extends IDropdownProps {\n open: boolean;\n notFoundContent?: React.ReactNode;\n popupMatchSelectWidth?: boolean | number;\n showSearch?: boolean;\n searchValue?: string;\n setInnerSearchValue?: (value: string) => void;\n filterOption?: (inputValue: string, option: SelectOptionType) => boolean;\n /** Private Select-owned popup collection for the flat standard path. */\n collection?: React.ReactNode;\n}\n\nconst RefSelectTrigger = React.forwardRef<RefTriggerProps, SelectTriggerProps>(\n (props, ref) => {\n const {\n // prefixCls,\n overlayStyle,\n disabled,\n open,\n children,\n dropdownRender,\n getPopupContainer,\n onOpenChange,\n showSearch,\n searchValue,\n setInnerSearchValue,\n menu: menuProps,\n collection,\n overlayClassName,\n placement = 'bottom-start',\n popupMatchSelectWidth,\n notFoundContent = <Empty size=\"small\" />,\n ...restProps\n } = props;\n\n // ======================= Ref =======================\n const popupRef = React.useRef<HTMLDivElement>(null);\n React.useImperativeHandle(ref, () => ({\n getPopupElement: () => popupRef.current,\n }));\n\n const customDropdownRender = useCallback(\n (menu: React.ReactNode) => {\n return (\n <div className=\"beta-ald-select-popup\" ref={popupRef}>\n {!collection && (\n <SearchBox\n showSearch={showSearch}\n value={searchValue}\n onChange={(value) => {\n setInnerSearchValue?.(value);\n }}\n />\n )}\n {collection || (\n <PopupContent\n content={menu}\n notFoundContent={notFoundContent}\n dropdownRender={dropdownRender}\n menuProps={menuProps}\n />\n )}\n </div>\n );\n },\n [\n dropdownRender,\n collection,\n menuProps,\n notFoundContent,\n searchValue,\n setInnerSearchValue,\n showSearch,\n ],\n );\n\n return (\n <Dropdown\n {...restProps}\n disabled={disabled}\n open={open}\n // Dropdown still receives the existing menu input to preserve its\n // trigger lifecycle. For the private collection path, its rendered\n // Menu node is ignored by customDropdownRender above.\n menu={collection ? undefined : menuProps}\n placement={placement}\n popupMatchTriggerWidth={popupMatchSelectWidth}\n overlayStyle={overlayStyle}\n overlayClassName={cn(\n 'beta-ald-select-popup-container',\n overlayClassName,\n )}\n autoUpdatePos\n dropdownRender={customDropdownRender}\n getPopupContainer={getPopupContainer}\n onOpenChange={(o) => {\n onOpenChange?.(o);\n }}\n >\n {collection ? (\n <span style={{ display: 'flex', flex: '1 1 auto', minWidth: 0 }}>\n {children}\n </span>\n ) : (\n children\n )}\n </Dropdown>\n );\n },\n);\n\nRefSelectTrigger.displayName = 'SelectTrigger';\n\nexport default RefSelectTrigger;\n"],"mappings":";;;;;;;;AA8BA,IAAM,mBAAmB,MAAM,YAC5B,OAAO,QAAQ;CACd,MAAM,EAEJ,cACA,UACA,MACA,UACA,gBACA,mBACA,cACA,YACA,aACA,qBACA,MAAM,WACN,YACA,kBACA,YAAY,gBACZ,uBACA,kBAAkB,oBAAC,OAAD,EAAO,MAAK,SAAU,CAAA,EACxC,GAAG,cACD;CAGJ,MAAM,WAAW,MAAM,OAAuB,KAAK;AACnD,OAAM,oBAAoB,YAAY,EACpC,uBAAuB,SAAS,SACjC,EAAE;CAEH,MAAM,uBAAuB,aAC1B,SAA0B;AACzB,SACE,qBAAC,OAAD;GAAK,WAAU;GAAwB,KAAK;aAA5C,CACG,CAAC,cACA,oBAAC,mBAAD;IACc;IACZ,OAAO;IACP,WAAW,UAAU;AACnB,2BAAsB,MAAM;;IAE9B,CAAA,EAEH,cACC,oBAAC,cAAD;IACE,SAAS;IACQ;IACD;IACL;IACX,CAAA,CAEA;;IAGV;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;AAED,QACE,oBAAC,UAAD;EACE,GAAI;EACM;EACJ;EAIN,MAAM,aAAa,SAAY;EACpB;EACX,wBAAwB;EACV;EACd,kBAAkB,GAChB,mCACA,iBACD;EACD,eAAA;EACA,gBAAgB;EACG;EACnB,eAAe,MAAM;AACnB,kBAAe,EAAE;;YAGlB,aACC,oBAAC,QAAD;GAAM,OAAO;IAAE,SAAS;IAAQ,MAAM;IAAY,UAAU;IAAG;GAC5D;GACI,CAAA,GAEP;EAEO,CAAA;EAGhB;AAED,iBAAiB,cAAc"}
|
|
@@ -35,7 +35,7 @@ function InternalItem(props) {
|
|
|
35
35
|
var ITEM_WIDTH = 10;
|
|
36
36
|
var REST_KEY = "__OVERFLOW_REST__";
|
|
37
37
|
function OverflowInner(props, ref) {
|
|
38
|
-
const { prefixCls = "rc-overflow", data, renderItem, itemKey, renderRest, className, onVisibleChange } = props;
|
|
38
|
+
const { prefixCls = "rc-overflow", data, renderItem, itemKey, renderRest, gap = 0, className, onVisibleChange } = props;
|
|
39
39
|
const [containerWidth, setContainerWidth] = useState(null);
|
|
40
40
|
const mergedContainerWidth = containerWidth || 0;
|
|
41
41
|
const [itemWidths, setItemWidths] = useState(() => /* @__PURE__ */ new Map());
|
|
@@ -97,11 +97,11 @@ function OverflowInner(props, ref) {
|
|
|
97
97
|
return;
|
|
98
98
|
}
|
|
99
99
|
totalWidth += currentItemWidth;
|
|
100
|
-
if (lastIndex === 0 && totalWidth <= mergedContainerWidth || i === lastIndex - 1 && totalWidth + (getItemWidth(lastIndex) ?? 0) <= mergedContainerWidth) {
|
|
100
|
+
if (lastIndex === 0 && totalWidth <= mergedContainerWidth || i === lastIndex - 1 && totalWidth + (getItemWidth(lastIndex) ?? 0) + lastIndex * gap <= mergedContainerWidth) {
|
|
101
101
|
updateDisplayCount(lastIndex);
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
|
-
if (totalWidth + mergedRestWidth > mergedContainerWidth) {
|
|
104
|
+
if (totalWidth + mergedRestWidth + (i + 1) * gap > mergedContainerWidth) {
|
|
105
105
|
updateDisplayCount(i - 1);
|
|
106
106
|
return;
|
|
107
107
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FixedOverflow.js","names":[],"sources":["../../../src/Select/Selector/FixedOverflow.tsx"],"sourcesContent":["// 修复 rc-overflow 的 restReady 卡 false bug。\n//\n// 根因(rc-overflow@1.5 es/Overflow.js updateDisplayCount):\n// if (displayCount === count && ...) return; // <-- 这一行\n// setDisplayCount(count);\n// if (!notReady) { setRestReady(count < data.length - 1); onVisibleChange?.(count); }\n//\n// 触发条件:modal 首开等首屏渲染时,半测量阶段(部分 itemWidth 还没注册)\n// 会先以 notReady=true 把 displayCount 推到「最终值 N」(比如 9 个 tag 都已\n// 测过,第 10 个还没到时调用 updateDisplayCount(9, undefined, true),\n// 而最终稳定态恰好也是 displayCount=9)。后续 ready 路径 displayCount===count\n// 早返回,setRestReady 永远没被调用 → restReady 始终是 false →\n// rest 节点 opacity:0, position:absolute, height:0 不可见。\n//\n// 修复:把 setRestReady 和 onVisibleChange 移到 early-return 之前。只要本次\n// 是 ready 路径,无论 displayCount 是否变化,都把 rest 状态推到位。\n//\n// 其它逻辑 1:1 复刻 rc-overflow 的 responsive 分支(ald 只用 maxCount='responsive'\n// 一种模式,prefix/suffix/raw render 等都没用),删掉用不到的代码以降复杂度。\n// 用 React 18 自动批处理,不再重写 channelUpdate / unstable_batchedUpdates。\n\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport ResizeObserver from 'rc-resize-observer';\nimport useLayoutEffect from 'rc-util/es/hooks/useLayoutEffect';\nimport cn from 'classnames';\n\ninterface ResizeInfo {\n width: number;\n height: number;\n offsetWidth: number;\n offsetHeight: number;\n}\n\ninterface InternalItemProps {\n prefixCls: string;\n display: boolean;\n order: number;\n itemKey: React.Key;\n registerSize: (key: React.Key, width: number | null) => void;\n className?: string;\n children?: React.ReactNode;\n}\n\nfunction InternalItem(props: InternalItemProps) {\n const {\n prefixCls,\n display,\n order,\n itemKey,\n registerSize,\n className,\n children,\n } = props;\n const mergedHidden = !display;\n // 卸载时把本 item 的 width 从 Map 里删掉。registerSize/itemKey 用 ref 抓最新,\n // 这样 effect 自身依赖只有 [],不需要 eslint-disable。\n const registerSizeRef = useRef(registerSize);\n const itemKeyRef = useRef(itemKey);\n registerSizeRef.current = registerSize;\n itemKeyRef.current = itemKey;\n useEffect(\n () => () => {\n registerSizeRef.current(itemKeyRef.current, null);\n },\n [],\n );\n const overflowStyle: React.CSSProperties = {\n opacity: mergedHidden ? 0 : 1,\n height: mergedHidden ? 0 : undefined,\n overflowY: mergedHidden ? 'hidden' : undefined,\n order,\n pointerEvents: mergedHidden ? 'none' : undefined,\n position: mergedHidden ? 'absolute' : undefined,\n };\n return (\n <ResizeObserver\n onResize={({ offsetWidth }: ResizeInfo) =>\n registerSize(itemKey, offsetWidth)\n }\n >\n <div\n className={cn(prefixCls, className)}\n style={overflowStyle}\n aria-hidden={mergedHidden || undefined}\n >\n {children}\n </div>\n </ResizeObserver>\n );\n}\n\nexport interface FixedOverflowProps<T> {\n prefixCls?: string;\n data: T[];\n renderItem: (item: T, info: { index: number }) => React.ReactNode;\n itemKey: (item: T) => React.Key;\n renderRest: (omittedItems: T[]) => React.ReactNode;\n className?: string;\n onVisibleChange?: (count: number) => void;\n}\n\nconst ITEM_WIDTH = 10;\n// rest 节点的固定 React key。假设调用方传入的 itemKey 不会返回此常量\n// (ald 内部 Select 的 itemKey 取 value/key 字段,不会等于这个字符串)。\nconst REST_KEY: React.Key = '__OVERFLOW_REST__';\n\nfunction OverflowInner<T>(\n props: FixedOverflowProps<T>,\n ref: React.ForwardedRef<HTMLDivElement>,\n) {\n const {\n prefixCls = 'rc-overflow',\n data,\n renderItem,\n itemKey,\n renderRest,\n className,\n onVisibleChange,\n } = props;\n\n const [containerWidth, setContainerWidth] = useState<number | null>(null);\n const mergedContainerWidth = containerWidth || 0;\n const [itemWidths, setItemWidths] = useState<Map<React.Key, number>>(\n () => new Map(),\n );\n const [prevRestWidth, setPrevRestWidth] = useState(0);\n const [restWidth, setRestWidth] = useState(0);\n const [displayCount, setDisplayCount] = useState<number | null>(null);\n const [restReady, setRestReady] = useState(false);\n\n const mergedDisplayCount = displayCount || 0;\n const itemPrefixCls = `${prefixCls}-item`;\n const mergedRestWidth = Math.max(prevRestWidth, restWidth);\n\n const getKey = useCallback(\n (item: T, index: number): React.Key => {\n if (item == null) return index;\n return itemKey(item) ?? index;\n },\n [itemKey],\n );\n\n const mergedData = useMemo(() => {\n if (!data.length) return data;\n return data.slice(\n 0,\n Math.min(data.length, mergedContainerWidth / ITEM_WIDTH),\n );\n }, [data, mergedContainerWidth]);\n\n const omittedItems = useMemo(\n () => data.slice(mergedDisplayCount + 1),\n [data, mergedDisplayCount],\n );\n\n const updateDisplayCount = (count: number, notReady?: boolean) => {\n // === BUG FIX ===\n // 不论 displayCount 是否变化,只要本次是 ready 路径,立即把 restReady /\n // onVisibleChange 推到位。原版在 displayCount===count 时早返回,会跳过\n // 这两步,造成 restReady 卡死在 false。\n if (!notReady) {\n setRestReady(count < data.length - 1);\n onVisibleChange?.(count);\n }\n if (displayCount !== count) {\n setDisplayCount(count);\n }\n };\n\n const registerSize = useCallback((key: React.Key, width: number | null) => {\n setItemWidths((origin) => {\n const clone = new Map(origin);\n if (width === null) clone.delete(key);\n else clone.set(key, width);\n return clone;\n });\n }, []);\n\n const registerRestSize = useCallback(\n (_key: React.Key, width: number | null) => {\n if (width === null) return;\n setRestWidth((prev) => {\n setPrevRestWidth(prev);\n return width;\n });\n },\n [],\n );\n\n const onOverflowResize = (_: ResizeInfo, element: HTMLElement) => {\n setContainerWidth(element.clientWidth);\n };\n\n // 故意不加依赖数组:测量回路依赖每次渲染都重跑——itemWidths 变 → 重算 displayCount\n // → 触发再渲染 → 再测量。加 deps 会破坏 rc-overflow 原版的测量-更新循环。\n useLayoutEffect(() => {\n if (!mergedContainerWidth || !mergedData) return;\n const len = mergedData.length;\n const lastIndex = len - 1;\n if (!len) {\n updateDisplayCount(0);\n return;\n }\n let totalWidth = 0;\n const getItemWidth = (index: number): number | undefined =>\n itemWidths.get(getKey(mergedData[index], index));\n for (let i = 0; i < len; i += 1) {\n const currentItemWidth = getItemWidth(i);\n if (currentItemWidth === undefined) {\n // 半测量:先把 displayCount 推到 i-1,但不动 restReady(notReady=true)。\n updateDisplayCount(i - 1, true);\n return;\n }\n totalWidth += currentItemWidth;\n if (\n (lastIndex === 0 && totalWidth <= mergedContainerWidth) ||\n (i === lastIndex - 1 &&\n totalWidth + (getItemWidth(lastIndex) ?? 0) <= mergedContainerWidth)\n ) {\n // 全部塞得下\n updateDisplayCount(lastIndex);\n return;\n }\n if (totalWidth + mergedRestWidth > mergedContainerWidth) {\n // 当前这个塞不下了,需要展示 \"+N\"\n updateDisplayCount(i - 1);\n return;\n }\n }\n });\n\n const displayRest = restReady && !!omittedItems.length;\n\n return (\n <ResizeObserver onResize={onOverflowResize} disabled={!data.length}>\n <div className={cn(prefixCls, className)} ref={ref}>\n {mergedData.map((item, index) => {\n const key = getKey(item, index);\n return (\n <InternalItem\n key={key}\n prefixCls={itemPrefixCls}\n display={index <= mergedDisplayCount}\n order={index}\n itemKey={key}\n registerSize={registerSize}\n >\n {renderItem(item, { index })}\n </InternalItem>\n );\n })}\n <InternalItem\n prefixCls={itemPrefixCls}\n display={displayRest}\n order={displayRest ? mergedDisplayCount : Number.MAX_SAFE_INTEGER}\n itemKey={REST_KEY}\n registerSize={registerRestSize}\n className={`${itemPrefixCls}-rest`}\n >\n {renderRest(omittedItems)}\n </InternalItem>\n </div>\n </ResizeObserver>\n );\n}\n\nconst FixedOverflow = forwardRef(OverflowInner) as <T>(\n props: FixedOverflowProps<T> & { ref?: React.Ref<HTMLDivElement> },\n) => React.ReactElement;\n\nexport default FixedOverflow;\n"],"mappings":";;;;;;AAkDA,SAAS,aAAa,OAA0B;CAC9C,MAAM,EACJ,WACA,SACA,OACA,SACA,cACA,WACA,aACE;CACJ,MAAM,eAAe,CAAC;CAGtB,MAAM,kBAAkB,OAAO,aAAa;CAC5C,MAAM,aAAa,OAAO,QAAQ;AAClC,iBAAgB,UAAU;AAC1B,YAAW,UAAU;AACrB,uBACc;AACV,kBAAgB,QAAQ,WAAW,SAAS,KAAK;IAEnD,EAAE,CACH;CACD,MAAM,gBAAqC;EACzC,SAAS,eAAe,IAAI;EAC5B,QAAQ,eAAe,IAAI;EAC3B,WAAW,eAAe,WAAW;EACrC;EACA,eAAe,eAAe,SAAS;EACvC,UAAU,eAAe,aAAa;EACvC;AACD,QACE,oBAAC,gBAAD;EACE,WAAW,EAAE,kBACX,aAAa,SAAS,YAAY;YAGpC,oBAAC,OAAD;GACE,WAAW,GAAG,WAAW,UAAU;GACnC,OAAO;GACP,eAAa,gBAAgB;GAE5B;GACG,CAAA;EACS,CAAA;;AAcrB,IAAM,aAAa;AAGnB,IAAM,WAAsB;AAE5B,SAAS,cACP,OACA,KACA;CACA,MAAM,EACJ,YAAY,eACZ,MACA,YACA,SACA,YACA,WACA,oBACE;CAEJ,MAAM,CAAC,gBAAgB,qBAAqB,SAAwB,KAAK;CACzE,MAAM,uBAAuB,kBAAkB;CAC/C,MAAM,CAAC,YAAY,iBAAiB,+BAC5B,IAAI,KAAK,CAChB;CACD,MAAM,CAAC,eAAe,oBAAoB,SAAS,EAAE;CACrD,MAAM,CAAC,WAAW,gBAAgB,SAAS,EAAE;CAC7C,MAAM,CAAC,cAAc,mBAAmB,SAAwB,KAAK;CACrE,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CAEjD,MAAM,qBAAqB,gBAAgB;CAC3C,MAAM,gBAAgB,GAAG,UAAU;CACnC,MAAM,kBAAkB,KAAK,IAAI,eAAe,UAAU;CAE1D,MAAM,SAAS,aACZ,MAAS,UAA6B;AACrC,MAAI,QAAQ,KAAM,QAAO;AACzB,SAAO,QAAQ,KAAK,IAAI;IAE1B,CAAC,QAAQ,CACV;CAED,MAAM,aAAa,cAAc;AAC/B,MAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,SAAO,KAAK,MACV,GACA,KAAK,IAAI,KAAK,QAAQ,uBAAuB,WAAW,CACzD;IACA,CAAC,MAAM,qBAAqB,CAAC;CAEhC,MAAM,eAAe,cACb,KAAK,MAAM,qBAAqB,EAAE,EACxC,CAAC,MAAM,mBAAmB,CAC3B;CAED,MAAM,sBAAsB,OAAe,aAAuB;AAKhE,MAAI,CAAC,UAAU;AACb,gBAAa,QAAQ,KAAK,SAAS,EAAE;AACrC,qBAAkB,MAAM;;AAE1B,MAAI,iBAAiB,MACnB,iBAAgB,MAAM;;CAI1B,MAAM,eAAe,aAAa,KAAgB,UAAyB;AACzE,iBAAe,WAAW;GACxB,MAAM,QAAQ,IAAI,IAAI,OAAO;AAC7B,OAAI,UAAU,KAAM,OAAM,OAAO,IAAI;OAChC,OAAM,IAAI,KAAK,MAAM;AAC1B,UAAO;IACP;IACD,EAAE,CAAC;CAEN,MAAM,mBAAmB,aACtB,MAAiB,UAAyB;AACzC,MAAI,UAAU,KAAM;AACpB,gBAAc,SAAS;AACrB,oBAAiB,KAAK;AACtB,UAAO;IACP;IAEJ,EAAE,CACH;CAED,MAAM,oBAAoB,GAAe,YAAyB;AAChE,oBAAkB,QAAQ,YAAY;;AAKxC,yBAAsB;AACpB,MAAI,CAAC,wBAAwB,CAAC,WAAY;EAC1C,MAAM,MAAM,WAAW;EACvB,MAAM,YAAY,MAAM;AACxB,MAAI,CAAC,KAAK;AACR,sBAAmB,EAAE;AACrB;;EAEF,IAAI,aAAa;EACjB,MAAM,gBAAgB,UACpB,WAAW,IAAI,OAAO,WAAW,QAAQ,MAAM,CAAC;AAClD,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK,GAAG;GAC/B,MAAM,mBAAmB,aAAa,EAAE;AACxC,OAAI,qBAAqB,QAAW;AAElC,uBAAmB,IAAI,GAAG,KAAK;AAC/B;;AAEF,iBAAc;AACd,OACG,cAAc,KAAK,cAAc,wBACjC,MAAM,YAAY,KACjB,cAAc,aAAa,UAAU,IAAI,MAAM,sBACjD;AAEA,uBAAmB,UAAU;AAC7B;;AAEF,OAAI,aAAa,kBAAkB,sBAAsB;AAEvD,uBAAmB,IAAI,EAAE;AACzB;;;GAGJ;CAEF,MAAM,cAAc,aAAa,CAAC,CAAC,aAAa;AAEhD,QACE,oBAAC,gBAAD;EAAgB,UAAU;EAAkB,UAAU,CAAC,KAAK;YAC1D,qBAAC,OAAD;GAAK,WAAW,GAAG,WAAW,UAAU;GAAO;aAA/C,CACG,WAAW,KAAK,MAAM,UAAU;IAC/B,MAAM,MAAM,OAAO,MAAM,MAAM;AAC/B,WACE,oBAAC,cAAD;KAEE,WAAW;KACX,SAAS,SAAS;KAClB,OAAO;KACP,SAAS;KACK;eAEb,WAAW,MAAM,EAAE,OAAO,CAAC;KACf,EARR,IAQQ;KAEjB,EACF,oBAAC,cAAD;IACE,WAAW;IACX,SAAS;IACT,OAAO,cAAc,qBAAqB,OAAO;IACjD,SAAS;IACT,cAAc;IACd,WAAW,GAAG,cAAc;cAE3B,WAAW,aAAa;IACZ,CAAA,CACX;;EACS,CAAA;;AAIrB,IAAM,gBAAgB,WAAW,cAAc"}
|
|
1
|
+
{"version":3,"file":"FixedOverflow.js","names":[],"sources":["../../../src/Select/Selector/FixedOverflow.tsx"],"sourcesContent":["// 修复 rc-overflow 的 restReady 卡 false bug。\n//\n// 根因(rc-overflow@1.5 es/Overflow.js updateDisplayCount):\n// if (displayCount === count && ...) return; // <-- 这一行\n// setDisplayCount(count);\n// if (!notReady) { setRestReady(count < data.length - 1); onVisibleChange?.(count); }\n//\n// 触发条件:modal 首开等首屏渲染时,半测量阶段(部分 itemWidth 还没注册)\n// 会先以 notReady=true 把 displayCount 推到「最终值 N」(比如 9 个 tag 都已\n// 测过,第 10 个还没到时调用 updateDisplayCount(9, undefined, true),\n// 而最终稳定态恰好也是 displayCount=9)。后续 ready 路径 displayCount===count\n// 早返回,setRestReady 永远没被调用 → restReady 始终是 false →\n// rest 节点 opacity:0, position:absolute, height:0 不可见。\n//\n// 修复:把 setRestReady 和 onVisibleChange 移到 early-return 之前。只要本次\n// 是 ready 路径,无论 displayCount 是否变化,都把 rest 状态推到位。\n//\n// 其它逻辑 1:1 复刻 rc-overflow 的 responsive 分支(ald 只用 maxCount='responsive'\n// 一种模式,prefix/suffix/raw render 等都没用),删掉用不到的代码以降复杂度。\n// 用 React 18 自动批处理,不再重写 channelUpdate / unstable_batchedUpdates。\n\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport ResizeObserver from 'rc-resize-observer';\nimport useLayoutEffect from 'rc-util/es/hooks/useLayoutEffect';\nimport cn from 'classnames';\n\ninterface ResizeInfo {\n width: number;\n height: number;\n offsetWidth: number;\n offsetHeight: number;\n}\n\ninterface InternalItemProps {\n prefixCls: string;\n display: boolean;\n order: number;\n itemKey: React.Key;\n registerSize: (key: React.Key, width: number | null) => void;\n className?: string;\n children?: React.ReactNode;\n}\n\nfunction InternalItem(props: InternalItemProps) {\n const {\n prefixCls,\n display,\n order,\n itemKey,\n registerSize,\n className,\n children,\n } = props;\n const mergedHidden = !display;\n // 卸载时把本 item 的 width 从 Map 里删掉。registerSize/itemKey 用 ref 抓最新,\n // 这样 effect 自身依赖只有 [],不需要 eslint-disable。\n const registerSizeRef = useRef(registerSize);\n const itemKeyRef = useRef(itemKey);\n registerSizeRef.current = registerSize;\n itemKeyRef.current = itemKey;\n useEffect(\n () => () => {\n registerSizeRef.current(itemKeyRef.current, null);\n },\n [],\n );\n const overflowStyle: React.CSSProperties = {\n opacity: mergedHidden ? 0 : 1,\n height: mergedHidden ? 0 : undefined,\n overflowY: mergedHidden ? 'hidden' : undefined,\n order,\n pointerEvents: mergedHidden ? 'none' : undefined,\n position: mergedHidden ? 'absolute' : undefined,\n };\n return (\n <ResizeObserver\n onResize={({ offsetWidth }: ResizeInfo) =>\n registerSize(itemKey, offsetWidth)\n }\n >\n <div\n className={cn(prefixCls, className)}\n style={overflowStyle}\n aria-hidden={mergedHidden || undefined}\n >\n {children}\n </div>\n </ResizeObserver>\n );\n}\n\nexport interface FixedOverflowProps<T> {\n prefixCls?: string;\n data: T[];\n renderItem: (item: T, info: { index: number }) => React.ReactNode;\n itemKey: (item: T) => React.Key;\n renderRest: (omittedItems: T[]) => React.ReactNode;\n gap?: number;\n className?: string;\n onVisibleChange?: (count: number) => void;\n}\n\nconst ITEM_WIDTH = 10;\n// rest 节点的固定 React key。假设调用方传入的 itemKey 不会返回此常量\n// (ald 内部 Select 的 itemKey 取 value/key 字段,不会等于这个字符串)。\nconst REST_KEY: React.Key = '__OVERFLOW_REST__';\n\nfunction OverflowInner<T>(\n props: FixedOverflowProps<T>,\n ref: React.ForwardedRef<HTMLDivElement>,\n) {\n const {\n prefixCls = 'rc-overflow',\n data,\n renderItem,\n itemKey,\n renderRest,\n gap = 0,\n className,\n onVisibleChange,\n } = props;\n\n const [containerWidth, setContainerWidth] = useState<number | null>(null);\n const mergedContainerWidth = containerWidth || 0;\n const [itemWidths, setItemWidths] = useState<Map<React.Key, number>>(\n () => new Map(),\n );\n const [prevRestWidth, setPrevRestWidth] = useState(0);\n const [restWidth, setRestWidth] = useState(0);\n const [displayCount, setDisplayCount] = useState<number | null>(null);\n const [restReady, setRestReady] = useState(false);\n\n const mergedDisplayCount = displayCount || 0;\n const itemPrefixCls = `${prefixCls}-item`;\n const mergedRestWidth = Math.max(prevRestWidth, restWidth);\n\n const getKey = useCallback(\n (item: T, index: number): React.Key => {\n if (item == null) return index;\n return itemKey(item) ?? index;\n },\n [itemKey],\n );\n\n const mergedData = useMemo(() => {\n if (!data.length) return data;\n return data.slice(\n 0,\n Math.min(data.length, mergedContainerWidth / ITEM_WIDTH),\n );\n }, [data, mergedContainerWidth]);\n\n const omittedItems = useMemo(\n () => data.slice(mergedDisplayCount + 1),\n [data, mergedDisplayCount],\n );\n\n const updateDisplayCount = (count: number, notReady?: boolean) => {\n // === BUG FIX ===\n // 不论 displayCount 是否变化,只要本次是 ready 路径,立即把 restReady /\n // onVisibleChange 推到位。原版在 displayCount===count 时早返回,会跳过\n // 这两步,造成 restReady 卡死在 false。\n if (!notReady) {\n setRestReady(count < data.length - 1);\n onVisibleChange?.(count);\n }\n if (displayCount !== count) {\n setDisplayCount(count);\n }\n };\n\n const registerSize = useCallback((key: React.Key, width: number | null) => {\n setItemWidths((origin) => {\n const clone = new Map(origin);\n if (width === null) clone.delete(key);\n else clone.set(key, width);\n return clone;\n });\n }, []);\n\n const registerRestSize = useCallback(\n (_key: React.Key, width: number | null) => {\n if (width === null) return;\n setRestWidth((prev) => {\n setPrevRestWidth(prev);\n return width;\n });\n },\n [],\n );\n\n const onOverflowResize = (_: ResizeInfo, element: HTMLElement) => {\n setContainerWidth(element.clientWidth);\n };\n\n // 故意不加依赖数组:测量回路依赖每次渲染都重跑——itemWidths 变 → 重算 displayCount\n // → 触发再渲染 → 再测量。加 deps 会破坏 rc-overflow 原版的测量-更新循环。\n useLayoutEffect(() => {\n if (!mergedContainerWidth || !mergedData) return;\n const len = mergedData.length;\n const lastIndex = len - 1;\n if (!len) {\n updateDisplayCount(0);\n return;\n }\n let totalWidth = 0;\n const getItemWidth = (index: number): number | undefined =>\n itemWidths.get(getKey(mergedData[index], index));\n for (let i = 0; i < len; i += 1) {\n const currentItemWidth = getItemWidth(i);\n if (currentItemWidth === undefined) {\n // 半测量:先把 displayCount 推到 i-1,但不动 restReady(notReady=true)。\n updateDisplayCount(i - 1, true);\n return;\n }\n totalWidth += currentItemWidth;\n if (\n (lastIndex === 0 && totalWidth <= mergedContainerWidth) ||\n (i === lastIndex - 1 &&\n totalWidth + (getItemWidth(lastIndex) ?? 0) + lastIndex * gap <=\n mergedContainerWidth)\n ) {\n // 全部塞得下\n updateDisplayCount(lastIndex);\n return;\n }\n if (totalWidth + mergedRestWidth + (i + 1) * gap > mergedContainerWidth) {\n // 当前这个塞不下了,需要展示 \"+N\"\n updateDisplayCount(i - 1);\n return;\n }\n }\n });\n\n const displayRest = restReady && !!omittedItems.length;\n\n return (\n <ResizeObserver onResize={onOverflowResize} disabled={!data.length}>\n <div className={cn(prefixCls, className)} ref={ref}>\n {mergedData.map((item, index) => {\n const key = getKey(item, index);\n return (\n <InternalItem\n key={key}\n prefixCls={itemPrefixCls}\n display={index <= mergedDisplayCount}\n order={index}\n itemKey={key}\n registerSize={registerSize}\n >\n {renderItem(item, { index })}\n </InternalItem>\n );\n })}\n <InternalItem\n prefixCls={itemPrefixCls}\n display={displayRest}\n order={displayRest ? mergedDisplayCount : Number.MAX_SAFE_INTEGER}\n itemKey={REST_KEY}\n registerSize={registerRestSize}\n className={`${itemPrefixCls}-rest`}\n >\n {renderRest(omittedItems)}\n </InternalItem>\n </div>\n </ResizeObserver>\n );\n}\n\nconst FixedOverflow = forwardRef(OverflowInner) as <T>(\n props: FixedOverflowProps<T> & { ref?: React.Ref<HTMLDivElement> },\n) => React.ReactElement;\n\nexport default FixedOverflow;\n"],"mappings":"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"}
|
|
@@ -102,6 +102,7 @@ function MultipleSelector(props) {
|
|
|
102
102
|
className: cn({ "beta-ald-select-selector-overflow-hidden": showItemIndex === -1 && displayValues.length === 1 }),
|
|
103
103
|
renderRest,
|
|
104
104
|
itemKey,
|
|
105
|
+
gap,
|
|
105
106
|
onVisibleChange
|
|
106
107
|
}),
|
|
107
108
|
showResponsiveSelectedSection && /* @__PURE__ */ jsx(MultipleResponsiveSelectedSection, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultipleSelector.js","names":[],"sources":["../../../src/Select/Selector/MultipleSelector.tsx"],"sourcesContent":["import React, { RefObject, useEffect, useMemo, useState } from 'react';\nimport { SelectorProps } from './index';\nimport Tag from '../../Tag';\nimport { DisplayValueType, RawValueType } from '../interface';\nimport {\n CustomTagProps,\n isMultiple,\n isResponsive,\n isShowSelectedSection,\n} from '../BaseSelect';\nimport ScrollArea from '../../ScrollArea';\nimport { cn } from '../../lib/utils';\nimport _ from 'lodash';\n// 用 ald 内部 fork 的 FixedOverflow 替代 rc-overflow。\n// 原因:rc-overflow 1.5 的 updateDisplayCount 在 displayCount===count 时早返回,\n// 会跳过 setRestReady,导致 modal 首开等场景下半测量阶段把 displayCount 提前\n// 推到「最终值 N」后,restReady 卡在 false → \"+N\" 节点 opacity:0 不可见。\n// FixedOverflow 把 setRestReady/onVisibleChange 上移到 early-return 之前,\n// 其它逻辑 1:1 复刻 rc-overflow 的 responsive 分支。\nimport Overflow from './FixedOverflow';\nimport MultipleResponsiveSelectedSection from './MultipleResponsiveSelectedSection';\nimport { RefTriggerProps } from '../SelectTrigger';\nconst overflowPrefixCls = 'beta-ald-select-selector-overflow';\nconst tagHeight = 20;\nconst gap = 4;\ninterface MultipleSelectorProps extends SelectorProps {\n // Event\n onRemove: (value: DisplayValueType) => void;\n onToggleOpen: (open?: boolean) => void;\n tagRender?: (props: CustomTagProps, isPreview?: boolean) => React.ReactNode;\n maxTagPlaceholder?:\n | React.ReactNode\n | ((omittedValues: DisplayValueType[]) => React.ReactNode);\n dropdownRef: RefObject<RefTriggerProps>;\n}\nconst onPreventMouseDown = (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n};\n\nfunction itemKey(value: DisplayValueType): React.Key {\n return (value.key ?? value.value) || '';\n}\n\nexport default function MultipleSelector(props: MultipleSelectorProps) {\n const {\n displayValues,\n tagRender,\n onRemove,\n onToggleOpen,\n mode,\n disabled,\n maxTagPlaceholder,\n showResponsiveSelectedSection,\n dropdownRef,\n suffixIcon,\n onOverflowCollapsedChange,\n } = props;\n const innerMaxTagPlaceholder = (omittedValues: DisplayValueType[]) => {\n return `+ ${\n omittedValues.length === displayValues.length\n ? omittedValues.length - 1\n : omittedValues.length\n }`;\n };\n const [showItemIndex, setShowItemIndex] = useState(0);\n const isCollapsed = showItemIndex === -1 && displayValues.length > 0;\n useEffect(() => {\n onOverflowCollapsedChange?.(isCollapsed);\n }, [isCollapsed, onOverflowCollapsedChange]);\n const customizeRenderSelector = (\n value: RawValueType | undefined,\n content: React.ReactNode,\n itemDisabled: boolean,\n closable?: boolean,\n onClose?: (event?: React.MouseEvent) => void,\n isPreview?: boolean,\n uniqueKey?: React.Key,\n ) => {\n const onMouseDown = (e: React.MouseEvent) => {\n onPreventMouseDown(e);\n };\n\n return (\n <span\n className=\"beta-ald-select-custom-tag-render-wrapper\"\n onMouseDown={onMouseDown}\n key={uniqueKey ?? value}\n >\n {tagRender?.(\n {\n label: content,\n value,\n disabled: itemDisabled,\n closable: isPreview ? false : closable ?? false,\n onClose: onClose ?? (() => {}),\n },\n isPreview,\n )}\n </span>\n );\n };\n const defaultRenderSelector = (\n item: DisplayValueType | undefined,\n content: React.ReactNode,\n itemDisabled: boolean,\n closable?: boolean,\n onClose?: React.MouseEventHandler,\n isPreview?: boolean,\n uniqueKey?: React.Key,\n ) => (\n <Tag\n disabled={itemDisabled}\n key={uniqueKey ?? item?.value}\n size=\"small\"\n closable={isPreview ? false : closable}\n onClose={(e) => {\n onPreventMouseDown(e);\n onClose?.(e);\n }}\n >\n {content}\n </Tag>\n );\n const isResponsiveMode = isResponsive(mode);\n const showSelectedSection = isShowSelectedSection(mode);\n const renderItem = (valueItem: DisplayValueType, index?: number) => {\n const { disabled: itemDisabled, label, value } = valueItem;\n const closable = !disabled && !itemDisabled;\n let isPreview = !showResponsiveSelectedSection;\n if (!isResponsiveMode) {\n isPreview = false;\n }\n if (!showSelectedSection) {\n isPreview = false;\n }\n if (disabled) {\n isPreview = true;\n }\n const displayLabel: React.ReactNode = label;\n\n const onClose = (event?: React.MouseEvent) => {\n if (event) {\n event.stopPropagation();\n }\n onRemove(valueItem);\n };\n if (_.isNil(value)) {\n return null;\n }\n\n // 生成唯一的 key,如果 value 可能重复,使用 value + index 组合\n const uniqueKey =\n valueItem.key ??\n (value !== undefined && value !== null\n ? `${value}-${index ?? ''}`\n : `item-${index ?? ''}`);\n\n return typeof tagRender === 'function'\n ? customizeRenderSelector(\n value,\n displayLabel,\n !!itemDisabled,\n closable,\n onClose,\n isPreview,\n uniqueKey,\n )\n : defaultRenderSelector(\n valueItem,\n displayLabel,\n !!itemDisabled,\n closable,\n onClose,\n isPreview,\n uniqueKey,\n );\n };\n\n const renderRest = (omittedValues: DisplayValueType[]) => {\n if (displayValues.length === 1) {\n return null;\n }\n\n const content =\n typeof maxTagPlaceholder === 'function'\n ? maxTagPlaceholder(\n omittedValues.length === displayValues.length\n ? omittedValues.slice(1, omittedValues.length)\n : omittedValues,\n )\n : innerMaxTagPlaceholder(\n omittedValues.length === displayValues.length\n ? omittedValues.slice(1, omittedValues.length)\n : omittedValues,\n );\n\n return typeof maxTagPlaceholder === 'function'\n ? content\n : defaultRenderSelector({ title: content }, content, false);\n };\n const onVisibleChange = (visibleCount: number) => {\n setShowItemIndex(visibleCount);\n };\n const maxHeight = useMemo(() => {\n if (isMultiple(mode)) {\n let maxRows: number | undefined;\n if (typeof mode === 'object') {\n maxRows = mode.maxRows;\n }\n if (!maxRows) {\n // 2.5行高+2行间距\n return 2.5 * tagHeight + 2 * gap;\n } else {\n // 总行高+总行间距\n return maxRows * tagHeight + (maxRows - 1) * gap;\n }\n }\n\n return undefined;\n }, [mode]);\n if (isResponsiveMode) {\n return (\n <div className=\"beta-ald-select-selector beta-ald-select-selector-multiple-responsive\">\n {showItemIndex === -1 && displayValues.length > 0 && (\n <div className=\"beta-ald-select-selector-overflow-item-first\">\n {renderItem(displayValues[0], 0)}\n </div>\n )}\n <Overflow\n prefixCls={overflowPrefixCls}\n data={displayValues}\n renderItem={(item, info) => renderItem(item, info?.index)}\n className={cn({\n 'beta-ald-select-selector-overflow-hidden':\n showItemIndex === -1 && displayValues.length === 1,\n })}\n renderRest={renderRest}\n itemKey={itemKey}\n onVisibleChange={onVisibleChange}\n />\n {showResponsiveSelectedSection && (\n <MultipleResponsiveSelectedSection\n displayValues={displayValues}\n renderItem={renderItem}\n maxHeight={maxHeight}\n suffixIcon={suffixIcon}\n onToggleOpen={onToggleOpen}\n dropdownRef={dropdownRef}\n />\n )}\n </div>\n );\n }\n\n return (\n <ScrollArea\n innerClassName=\"beta-ald-select-selector-multiple-default-inner\"\n className=\"beta-ald-select-selector beta-ald-select-selector-multiple-default\"\n innerStyle={{\n maxHeight: maxHeight,\n }}\n >\n <div className=\"beta-ald-select-selector-multiple-default-tags\">\n {displayValues.map((item, index) => renderItem(item, index))}\n </div>\n </ScrollArea>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MultipleSelector.js","names":[],"sources":["../../../src/Select/Selector/MultipleSelector.tsx"],"sourcesContent":["import React, { RefObject, useEffect, useMemo, useState } from 'react';\nimport { SelectorProps } from './index';\nimport Tag from '../../Tag';\nimport { DisplayValueType, RawValueType } from '../interface';\nimport {\n CustomTagProps,\n isMultiple,\n isResponsive,\n isShowSelectedSection,\n} from '../BaseSelect';\nimport ScrollArea from '../../ScrollArea';\nimport { cn } from '../../lib/utils';\nimport _ from 'lodash';\n// 用 ald 内部 fork 的 FixedOverflow 替代 rc-overflow。\n// 原因:rc-overflow 1.5 的 updateDisplayCount 在 displayCount===count 时早返回,\n// 会跳过 setRestReady,导致 modal 首开等场景下半测量阶段把 displayCount 提前\n// 推到「最终值 N」后,restReady 卡在 false → \"+N\" 节点 opacity:0 不可见。\n// FixedOverflow 把 setRestReady/onVisibleChange 上移到 early-return 之前,\n// 其它逻辑 1:1 复刻 rc-overflow 的 responsive 分支。\nimport Overflow from './FixedOverflow';\nimport MultipleResponsiveSelectedSection from './MultipleResponsiveSelectedSection';\nimport { RefTriggerProps } from '../SelectTrigger';\nconst overflowPrefixCls = 'beta-ald-select-selector-overflow';\nconst tagHeight = 20;\nconst gap = 4;\ninterface MultipleSelectorProps extends SelectorProps {\n // Event\n onRemove: (value: DisplayValueType) => void;\n onToggleOpen: (open?: boolean) => void;\n tagRender?: (props: CustomTagProps, isPreview?: boolean) => React.ReactNode;\n maxTagPlaceholder?:\n | React.ReactNode\n | ((omittedValues: DisplayValueType[]) => React.ReactNode);\n dropdownRef: RefObject<RefTriggerProps>;\n}\nconst onPreventMouseDown = (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n};\n\nfunction itemKey(value: DisplayValueType): React.Key {\n return (value.key ?? value.value) || '';\n}\n\nexport default function MultipleSelector(props: MultipleSelectorProps) {\n const {\n displayValues,\n tagRender,\n onRemove,\n onToggleOpen,\n mode,\n disabled,\n maxTagPlaceholder,\n showResponsiveSelectedSection,\n dropdownRef,\n suffixIcon,\n onOverflowCollapsedChange,\n } = props;\n const innerMaxTagPlaceholder = (omittedValues: DisplayValueType[]) => {\n return `+ ${\n omittedValues.length === displayValues.length\n ? omittedValues.length - 1\n : omittedValues.length\n }`;\n };\n const [showItemIndex, setShowItemIndex] = useState(0);\n const isCollapsed = showItemIndex === -1 && displayValues.length > 0;\n useEffect(() => {\n onOverflowCollapsedChange?.(isCollapsed);\n }, [isCollapsed, onOverflowCollapsedChange]);\n const customizeRenderSelector = (\n value: RawValueType | undefined,\n content: React.ReactNode,\n itemDisabled: boolean,\n closable?: boolean,\n onClose?: (event?: React.MouseEvent) => void,\n isPreview?: boolean,\n uniqueKey?: React.Key,\n ) => {\n const onMouseDown = (e: React.MouseEvent) => {\n onPreventMouseDown(e);\n };\n\n return (\n <span\n className=\"beta-ald-select-custom-tag-render-wrapper\"\n onMouseDown={onMouseDown}\n key={uniqueKey ?? value}\n >\n {tagRender?.(\n {\n label: content,\n value,\n disabled: itemDisabled,\n closable: isPreview ? false : closable ?? false,\n onClose: onClose ?? (() => {}),\n },\n isPreview,\n )}\n </span>\n );\n };\n const defaultRenderSelector = (\n item: DisplayValueType | undefined,\n content: React.ReactNode,\n itemDisabled: boolean,\n closable?: boolean,\n onClose?: React.MouseEventHandler,\n isPreview?: boolean,\n uniqueKey?: React.Key,\n ) => (\n <Tag\n disabled={itemDisabled}\n key={uniqueKey ?? item?.value}\n size=\"small\"\n closable={isPreview ? false : closable}\n onClose={(e) => {\n onPreventMouseDown(e);\n onClose?.(e);\n }}\n >\n {content}\n </Tag>\n );\n const isResponsiveMode = isResponsive(mode);\n const showSelectedSection = isShowSelectedSection(mode);\n const renderItem = (valueItem: DisplayValueType, index?: number) => {\n const { disabled: itemDisabled, label, value } = valueItem;\n const closable = !disabled && !itemDisabled;\n let isPreview = !showResponsiveSelectedSection;\n if (!isResponsiveMode) {\n isPreview = false;\n }\n if (!showSelectedSection) {\n isPreview = false;\n }\n if (disabled) {\n isPreview = true;\n }\n const displayLabel: React.ReactNode = label;\n\n const onClose = (event?: React.MouseEvent) => {\n if (event) {\n event.stopPropagation();\n }\n onRemove(valueItem);\n };\n if (_.isNil(value)) {\n return null;\n }\n\n // 生成唯一的 key,如果 value 可能重复,使用 value + index 组合\n const uniqueKey =\n valueItem.key ??\n (value !== undefined && value !== null\n ? `${value}-${index ?? ''}`\n : `item-${index ?? ''}`);\n\n return typeof tagRender === 'function'\n ? customizeRenderSelector(\n value,\n displayLabel,\n !!itemDisabled,\n closable,\n onClose,\n isPreview,\n uniqueKey,\n )\n : defaultRenderSelector(\n valueItem,\n displayLabel,\n !!itemDisabled,\n closable,\n onClose,\n isPreview,\n uniqueKey,\n );\n };\n\n const renderRest = (omittedValues: DisplayValueType[]) => {\n if (displayValues.length === 1) {\n return null;\n }\n\n const content =\n typeof maxTagPlaceholder === 'function'\n ? maxTagPlaceholder(\n omittedValues.length === displayValues.length\n ? omittedValues.slice(1, omittedValues.length)\n : omittedValues,\n )\n : innerMaxTagPlaceholder(\n omittedValues.length === displayValues.length\n ? omittedValues.slice(1, omittedValues.length)\n : omittedValues,\n );\n\n return typeof maxTagPlaceholder === 'function'\n ? content\n : defaultRenderSelector({ title: content }, content, false);\n };\n const onVisibleChange = (visibleCount: number) => {\n setShowItemIndex(visibleCount);\n };\n const maxHeight = useMemo(() => {\n if (isMultiple(mode)) {\n let maxRows: number | undefined;\n if (typeof mode === 'object') {\n maxRows = mode.maxRows;\n }\n if (!maxRows) {\n // 2.5行高+2行间距\n return 2.5 * tagHeight + 2 * gap;\n } else {\n // 总行高+总行间距\n return maxRows * tagHeight + (maxRows - 1) * gap;\n }\n }\n\n return undefined;\n }, [mode]);\n if (isResponsiveMode) {\n return (\n <div className=\"beta-ald-select-selector beta-ald-select-selector-multiple-responsive\">\n {showItemIndex === -1 && displayValues.length > 0 && (\n <div className=\"beta-ald-select-selector-overflow-item-first\">\n {renderItem(displayValues[0], 0)}\n </div>\n )}\n <Overflow\n prefixCls={overflowPrefixCls}\n data={displayValues}\n renderItem={(item, info) => renderItem(item, info?.index)}\n className={cn({\n 'beta-ald-select-selector-overflow-hidden':\n showItemIndex === -1 && displayValues.length === 1,\n })}\n renderRest={renderRest}\n itemKey={itemKey}\n gap={gap}\n onVisibleChange={onVisibleChange}\n />\n {showResponsiveSelectedSection && (\n <MultipleResponsiveSelectedSection\n displayValues={displayValues}\n renderItem={renderItem}\n maxHeight={maxHeight}\n suffixIcon={suffixIcon}\n onToggleOpen={onToggleOpen}\n dropdownRef={dropdownRef}\n />\n )}\n </div>\n );\n }\n\n return (\n <ScrollArea\n innerClassName=\"beta-ald-select-selector-multiple-default-inner\"\n className=\"beta-ald-select-selector beta-ald-select-selector-multiple-default\"\n innerStyle={{\n maxHeight: maxHeight,\n }}\n >\n <div className=\"beta-ald-select-selector-multiple-default-tags\">\n {displayValues.map((item, index) => renderItem(item, index))}\n </div>\n </ScrollArea>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { RawValueType, SelectItemType } from '../interface';
|
|
3
|
+
export interface SelectOptionCollectionItem {
|
|
4
|
+
id: string;
|
|
5
|
+
key: string;
|
|
6
|
+
value: RawValueType;
|
|
7
|
+
label: React.ReactNode;
|
|
8
|
+
disabled: boolean;
|
|
9
|
+
option: SelectItemType;
|
|
10
|
+
}
|
|
11
|
+
export interface SelectOptionCollection {
|
|
12
|
+
listboxId: string;
|
|
13
|
+
options: SelectOptionCollectionItem[];
|
|
14
|
+
enabledOptions: SelectOptionCollectionItem[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Private Select collection seam for normalized, flat option data.
|
|
18
|
+
*
|
|
19
|
+
* It intentionally consumes the existing useOptions result instead of adding
|
|
20
|
+
* another public normalization path. Menu-shaped and hierarchical inputs stay
|
|
21
|
+
* on the legacy compatibility path until their Select contract is migrated.
|
|
22
|
+
*/
|
|
23
|
+
export declare function createSelectOptionCollection(listboxId: string, keyMenuItems: Map<string, SelectItemType>): SelectOptionCollection;
|
|
24
|
+
interface OptionCollectionProps {
|
|
25
|
+
collection: SelectOptionCollection;
|
|
26
|
+
selectedValues: RawValueType[];
|
|
27
|
+
activeOptionKey?: string;
|
|
28
|
+
multiple?: boolean;
|
|
29
|
+
loading?: boolean;
|
|
30
|
+
listHeight: number;
|
|
31
|
+
notFoundContent: React.ReactNode;
|
|
32
|
+
onSelect: (value: RawValueType) => void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Visual collection renderer for the standard flat single-select popup.
|
|
36
|
+
*
|
|
37
|
+
* The legacy Menu class hooks are retained only to preserve existing Select
|
|
38
|
+
* geometry and option presentation while ownership moves to Select.
|
|
39
|
+
*/
|
|
40
|
+
export default function OptionCollection({ collection, selectedValues, activeOptionKey, multiple, loading, listHeight, notFoundContent, onSelect, }: OptionCollectionProps): import("react/jsx-runtime").JSX.Element;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { cn } from "../../lib/utils.js";
|
|
2
|
+
import Memo from "../../Icon/components/CheckLightLine.js";
|
|
3
|
+
import { toString } from "../utils/commonUtil.js";
|
|
4
|
+
import "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/Select/components/OptionCollection.tsx
|
|
7
|
+
/**
|
|
8
|
+
* Private Select collection seam for normalized, flat option data.
|
|
9
|
+
*
|
|
10
|
+
* It intentionally consumes the existing useOptions result instead of adding
|
|
11
|
+
* another public normalization path. Menu-shaped and hierarchical inputs stay
|
|
12
|
+
* on the legacy compatibility path until their Select contract is migrated.
|
|
13
|
+
*/
|
|
14
|
+
function createSelectOptionCollection(listboxId, keyMenuItems) {
|
|
15
|
+
const options = Array.from(keyMenuItems.entries()).map(([key, option]) => ({
|
|
16
|
+
id: `${listboxId}-option-${key}`,
|
|
17
|
+
key,
|
|
18
|
+
value: option.value ?? key,
|
|
19
|
+
label: option.label,
|
|
20
|
+
disabled: !!option.disabled,
|
|
21
|
+
option
|
|
22
|
+
}));
|
|
23
|
+
return {
|
|
24
|
+
listboxId,
|
|
25
|
+
options,
|
|
26
|
+
enabledOptions: options.filter((option) => !option.disabled)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Visual collection renderer for the standard flat single-select popup.
|
|
31
|
+
*
|
|
32
|
+
* The legacy Menu class hooks are retained only to preserve existing Select
|
|
33
|
+
* geometry and option presentation while ownership moves to Select.
|
|
34
|
+
*/
|
|
35
|
+
function OptionCollection({ collection, selectedValues, activeOptionKey, multiple = false, loading = false, listHeight, notFoundContent, onSelect }) {
|
|
36
|
+
if (collection.options.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
37
|
+
className: "ald-menu",
|
|
38
|
+
"data-select-option-collection": collection.listboxId,
|
|
39
|
+
style: {
|
|
40
|
+
height: listHeight,
|
|
41
|
+
overflow: "auto"
|
|
42
|
+
},
|
|
43
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
44
|
+
className: "szh-menu",
|
|
45
|
+
id: collection.listboxId,
|
|
46
|
+
role: "listbox",
|
|
47
|
+
"aria-multiselectable": multiple || void 0,
|
|
48
|
+
"aria-busy": loading || void 0,
|
|
49
|
+
style: {
|
|
50
|
+
height: listHeight,
|
|
51
|
+
overflow: "auto"
|
|
52
|
+
},
|
|
53
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
54
|
+
role: "status",
|
|
55
|
+
"aria-live": "polite",
|
|
56
|
+
"aria-atomic": "true",
|
|
57
|
+
children: notFoundContent
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
});
|
|
61
|
+
return /* @__PURE__ */ jsx("div", {
|
|
62
|
+
className: "ald-menu",
|
|
63
|
+
"data-select-option-collection": collection.listboxId,
|
|
64
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
65
|
+
className: "szh-menu",
|
|
66
|
+
id: collection.listboxId,
|
|
67
|
+
role: "listbox",
|
|
68
|
+
"aria-multiselectable": multiple || void 0,
|
|
69
|
+
"aria-busy": loading || void 0,
|
|
70
|
+
style: {
|
|
71
|
+
width: "100%",
|
|
72
|
+
minWidth: 0,
|
|
73
|
+
maxWidth: "none",
|
|
74
|
+
maxHeight: listHeight,
|
|
75
|
+
overflowY: "auto"
|
|
76
|
+
},
|
|
77
|
+
children: collection.options.map((item) => {
|
|
78
|
+
const selected = selectedValues.some((value) => toString(value) === toString(item.value));
|
|
79
|
+
return /* @__PURE__ */ jsx("div", {
|
|
80
|
+
id: item.id,
|
|
81
|
+
role: "option",
|
|
82
|
+
"aria-selected": selected,
|
|
83
|
+
"aria-disabled": item.disabled || void 0,
|
|
84
|
+
className: cn("szh-menu__item", "ald-menu-item", {
|
|
85
|
+
"szh-menu__item--disabled": item.disabled,
|
|
86
|
+
"ald-menu-item-selected": selected,
|
|
87
|
+
"szh-menu__item--hover": activeOptionKey === item.key
|
|
88
|
+
}),
|
|
89
|
+
"data-select-option-id": item.id,
|
|
90
|
+
onClick: () => {
|
|
91
|
+
if (!item.disabled) onSelect(item.value);
|
|
92
|
+
},
|
|
93
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
94
|
+
className: "ald-menu-item-label",
|
|
95
|
+
children: [
|
|
96
|
+
item.option.icon && /* @__PURE__ */ jsx("div", {
|
|
97
|
+
className: "ald-menu-item-label-icon",
|
|
98
|
+
children: item.option.icon
|
|
99
|
+
}),
|
|
100
|
+
/* @__PURE__ */ jsx("div", {
|
|
101
|
+
className: "ald-menu-item-label-text tw-text-typography-body-dense",
|
|
102
|
+
children: item.label
|
|
103
|
+
}),
|
|
104
|
+
(item.option.extra || selectedValues.length > 0) && /* @__PURE__ */ jsxs("div", {
|
|
105
|
+
className: "ald-menu-item-right",
|
|
106
|
+
children: [item.option.extra && /* @__PURE__ */ jsx("span", {
|
|
107
|
+
className: "ald-menu-item-extra",
|
|
108
|
+
children: item.option.extra
|
|
109
|
+
}), selectedValues.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
110
|
+
className: cn("ald-menu-item-selection-slot", { "ald-menu-item-selection-slot-selected ald-menu-item-selected-icon": selected }),
|
|
111
|
+
children: selected ? /* @__PURE__ */ jsx(Memo, {}) : null
|
|
112
|
+
})]
|
|
113
|
+
})
|
|
114
|
+
]
|
|
115
|
+
})
|
|
116
|
+
}, item.key);
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { createSelectOptionCollection, OptionCollection as default };
|
|
123
|
+
|
|
124
|
+
//# sourceMappingURL=OptionCollection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OptionCollection.js","names":[],"sources":["../../../src/Select/components/OptionCollection.tsx"],"sourcesContent":["import React from 'react';\nimport { CheckLightLine } from '../../Icon';\nimport { cn } from '../../lib/utils';\nimport { RawValueType, SelectItemType } from '../interface';\nimport { toString } from '../utils/commonUtil';\n\nexport interface SelectOptionCollectionItem {\n id: string;\n key: string;\n value: RawValueType;\n label: React.ReactNode;\n disabled: boolean;\n option: SelectItemType;\n}\n\nexport interface SelectOptionCollection {\n listboxId: string;\n options: SelectOptionCollectionItem[];\n enabledOptions: SelectOptionCollectionItem[];\n}\n\n/**\n * Private Select collection seam for normalized, flat option data.\n *\n * It intentionally consumes the existing useOptions result instead of adding\n * another public normalization path. Menu-shaped and hierarchical inputs stay\n * on the legacy compatibility path until their Select contract is migrated.\n */\nexport function createSelectOptionCollection(\n listboxId: string,\n keyMenuItems: Map<string, SelectItemType>,\n): SelectOptionCollection {\n const options = Array.from(keyMenuItems.entries()).map(([key, option]) => ({\n id: `${listboxId}-option-${key}`,\n key,\n value: (option.value ?? key) as RawValueType,\n label: option.label,\n disabled: !!option.disabled,\n option,\n }));\n\n return {\n listboxId,\n options,\n enabledOptions: options.filter((option) => !option.disabled),\n };\n}\n\ninterface OptionCollectionProps {\n collection: SelectOptionCollection;\n selectedValues: RawValueType[];\n activeOptionKey?: string;\n multiple?: boolean;\n loading?: boolean;\n listHeight: number;\n notFoundContent: React.ReactNode;\n onSelect: (value: RawValueType) => void;\n}\n\n/**\n * Visual collection renderer for the standard flat single-select popup.\n *\n * The legacy Menu class hooks are retained only to preserve existing Select\n * geometry and option presentation while ownership moves to Select.\n */\nexport default function OptionCollection({\n collection,\n selectedValues,\n activeOptionKey,\n multiple = false,\n loading = false,\n listHeight,\n notFoundContent,\n onSelect,\n}: OptionCollectionProps) {\n if (collection.options.length === 0) {\n return (\n <div\n className=\"ald-menu\"\n data-select-option-collection={collection.listboxId}\n style={{ height: listHeight, overflow: 'auto' }}\n >\n <div\n className=\"szh-menu\"\n id={collection.listboxId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n aria-busy={loading || undefined}\n style={{ height: listHeight, overflow: 'auto' }}\n >\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {notFoundContent}\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className=\"ald-menu\"\n data-select-option-collection={collection.listboxId}\n >\n <div\n className=\"szh-menu\"\n id={collection.listboxId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n aria-busy={loading || undefined}\n style={{\n width: '100%',\n minWidth: 0,\n maxWidth: 'none',\n maxHeight: listHeight,\n overflowY: 'auto',\n }}\n >\n {collection.options.map((item) => {\n const selected = selectedValues.some(\n (value) => toString(value) === toString(item.value),\n );\n\n return (\n <div\n key={item.key}\n id={item.id}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={item.disabled || undefined}\n className={cn('szh-menu__item', 'ald-menu-item', {\n 'szh-menu__item--disabled': item.disabled,\n 'ald-menu-item-selected': selected,\n 'szh-menu__item--hover': activeOptionKey === item.key,\n })}\n data-select-option-id={item.id}\n onClick={() => {\n if (!item.disabled) {\n onSelect(item.value);\n }\n }}\n >\n <div className=\"ald-menu-item-label\">\n {item.option.icon && (\n <div className=\"ald-menu-item-label-icon\">\n {item.option.icon}\n </div>\n )}\n <div className=\"ald-menu-item-label-text tw-text-typography-body-dense\">\n {item.label}\n </div>\n {(item.option.extra || selectedValues.length > 0) && (\n <div className=\"ald-menu-item-right\">\n {item.option.extra && (\n <span className=\"ald-menu-item-extra\">\n {item.option.extra}\n </span>\n )}\n {selectedValues.length > 0 && (\n <div\n className={cn('ald-menu-item-selection-slot', {\n 'ald-menu-item-selection-slot-selected ald-menu-item-selected-icon':\n selected,\n })}\n >\n {selected ? <CheckLightLine /> : null}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AA4BA,SAAgB,6BACd,WACA,cACwB;CACxB,MAAM,UAAU,MAAM,KAAK,aAAa,SAAS,CAAC,CAAC,KAAK,CAAC,KAAK,aAAa;EACzE,IAAI,GAAG,UAAU,UAAU;EAC3B;EACA,OAAQ,OAAO,SAAS;EACxB,OAAO,OAAO;EACd,UAAU,CAAC,CAAC,OAAO;EACnB;EACD,EAAE;AAEH,QAAO;EACL;EACA;EACA,gBAAgB,QAAQ,QAAQ,WAAW,CAAC,OAAO,SAAS;EAC7D;;;;;;;;AAoBH,SAAwB,iBAAiB,EACvC,YACA,gBACA,iBACA,WAAW,OACX,UAAU,OACV,YACA,iBACA,YACwB;AACxB,KAAI,WAAW,QAAQ,WAAW,EAChC,QACE,oBAAC,OAAD;EACE,WAAU;EACV,iCAA+B,WAAW;EAC1C,OAAO;GAAE,QAAQ;GAAY,UAAU;GAAQ;YAE/C,oBAAC,OAAD;GACE,WAAU;GACV,IAAI,WAAW;GACf,MAAK;GACL,wBAAsB,YAAY;GAClC,aAAW,WAAW;GACtB,OAAO;IAAE,QAAQ;IAAY,UAAU;IAAQ;aAE/C,oBAAC,OAAD;IAAK,MAAK;IAAS,aAAU;IAAS,eAAY;cAC/C;IACG,CAAA;GACF,CAAA;EACF,CAAA;AAIV,QACE,oBAAC,OAAD;EACE,WAAU;EACV,iCAA+B,WAAW;YAE1C,oBAAC,OAAD;GACE,WAAU;GACV,IAAI,WAAW;GACf,MAAK;GACL,wBAAsB,YAAY;GAClC,aAAW,WAAW;GACtB,OAAO;IACL,OAAO;IACP,UAAU;IACV,UAAU;IACV,WAAW;IACX,WAAW;IACZ;aAEA,WAAW,QAAQ,KAAK,SAAS;IAChC,MAAM,WAAW,eAAe,MAC7B,UAAU,SAAS,MAAM,KAAK,SAAS,KAAK,MAAM,CACpD;AAED,WACE,oBAAC,OAAD;KAEE,IAAI,KAAK;KACT,MAAK;KACL,iBAAe;KACf,iBAAe,KAAK,YAAY;KAChC,WAAW,GAAG,kBAAkB,iBAAiB;MAC/C,4BAA4B,KAAK;MACjC,0BAA0B;MAC1B,yBAAyB,oBAAoB,KAAK;MACnD,CAAC;KACF,yBAAuB,KAAK;KAC5B,eAAe;AACb,UAAI,CAAC,KAAK,SACR,UAAS,KAAK,MAAM;;eAIxB,qBAAC,OAAD;MAAK,WAAU;gBAAf;OACG,KAAK,OAAO,QACX,oBAAC,OAAD;QAAK,WAAU;kBACZ,KAAK,OAAO;QACT,CAAA;OAER,oBAAC,OAAD;QAAK,WAAU;kBACZ,KAAK;QACF,CAAA;QACJ,KAAK,OAAO,SAAS,eAAe,SAAS,MAC7C,qBAAC,OAAD;QAAK,WAAU;kBAAf,CACG,KAAK,OAAO,SACX,oBAAC,QAAD;SAAM,WAAU;mBACb,KAAK,OAAO;SACR,CAAA,EAER,eAAe,SAAS,KACvB,oBAAC,OAAD;SACE,WAAW,GAAG,gCAAgC,EAC5C,qEACE,UACH,CAAC;mBAED,WAAW,oBAAC,MAAD,EAAkB,CAAA,GAAG;SAC7B,CAAA,CAEJ;;OAEJ;;KACF,EA9CC,KAAK,IA8CN;KAER;GACE,CAAA;EACF,CAAA"}
|