@aloudata/aloudata-design 3.1.0 → 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 +20 -6
- 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 +17 -2
- package/dist/Checkbox/index.js.map +1 -1
- package/dist/Checkbox/type.d.ts +10 -2
- 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 +64 -13
- 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 +18 -8
- package/dist/Input/components/Input/index.js.map +1 -1
- package/dist/Input/components/TextArea/index.js +18 -7
- 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 +16 -9
- 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/index.js +1 -0
- package/dist/Pagination/index.js.map +1 -1
- 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 +26 -0
- 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 +229 -32
- 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/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/Switch/index.d.ts +5 -0
- package/dist/Switch/index.js +15 -5
- package/dist/Switch/index.js.map +1 -1
- package/dist/Table/components/Header.js +0 -1
- package/dist/Table/components/Header.js.map +1 -1
- package/dist/Table/index.js +42 -27
- package/dist/Table/index.js.map +1 -1
- package/dist/Tabs/index.js +1 -0
- 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/theme/contract/baselineResolvedTokenValueManifest.d.ts +1 -1
- package/dist/theme/contract/darkResolvedTokenValueManifest.d.ts +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 +45 -45
- 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 +41 -41
- 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/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/MemberPicker/index.tsx"],"sourcesContent":["import { usePrevious, useRequest } from 'ahooks';\nimport { cn } from '../lib/utils';\nimport _ from 'lodash';\nimport React, {\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport Avatar from '../Avatar';\nimport ConfigProvider from '../ConfigProvider';\nimport './member-picker.css';\nimport {\n EUserType,\n IUser,\n IUserGroup,\n TUser,\n} from '../ConfigProvider/getUserList';\nimport { LocaleContext, getTranslator } from '../locale/default';\nimport message from '../message';\nimport Panel from './components/Panel';\nimport MemberPanel from './components/PanelWrapper';\nimport {\n EMemberPicker,\n IMemberPickerProps,\n TUserGroupValue,\n TUserValue,\n} from './interface';\nimport { isUser, isUserGroup } from './utils/getUsersWithUserId';\nimport Select from '../Select';\nimport { Mode } from '../Select/BaseSelect';\n\nconst DEFAULT_MULTIPLE_DROPDOWN_WIDTH = 480;\n\nconst Component: React.FC<IMemberPickerProps> = (props) => {\n const { locale } = useContext(LocaleContext);\n const t = getTranslator(locale);\n\n const {\n value,\n type = EMemberPicker.USER,\n onChange,\n multiple,\n dropdownWidth,\n open,\n onOpenChange,\n placeholder = t.MemberPicker.select,\n className,\n allowClear,\n disabled,\n onClear,\n size,\n prefix: propPrefix,\n lockedIds = [],\n footer,\n onCancel,\n filterItem,\n mode: propsMode,\n renderItem,\n renderSelectedTag,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n ...restProps\n } = props;\n const allowOverlap = props.allowOverlap ?? false;\n const { getUsersByIds, getUsersByKeywords } = ConfigProvider.useGetUserList();\n const [selectedUserList, setSelectedUserList] = useState<TUser>([]);\n const prevValue = usePrevious(value);\n const [searchUserList, setSearchUserList] = useState<TUser>([]);\n const [searchString, setSearchString] = useState<string>('');\n const [dropdownContentWidth, setDropdownContentWidth] =\n useState(dropdownWidth);\n // 单选默认浮窗跟触发器等宽(true),调用方传 dropdownWidth 时用具体数字;\n // 多选默认 480,单条记录只有 头像+nickname 时触发器太窄装不下选中标签,故固定值。\n const panelWidth: number | boolean =\n dropdownWidth ?? (multiple ? DEFAULT_MULTIPLE_DROPDOWN_WIDTH : true);\n\n const triggerRef = useRef<HTMLDivElement>(null);\n const onSearchValueChange = useCallback((v: string) => {\n setSearchString(v);\n }, []);\n const [dropdownOpen, setDropdownOpen] = useState<boolean>(!!open);\n const queryByKeywords = useMemo(() => {\n if (getUsersByKeywords) {\n return getUsersByKeywords;\n }\n\n return (_params = {}) =>\n Promise.reject({\n message: t.MemberPicker.pleaseConfigGetUserByKeywordsMethod,\n });\n }, [getUsersByKeywords, t.MemberPicker.pleaseConfigGetUserByKeywordsMethod]);\n const queryByIds = useMemo(() => {\n if (getUsersByIds) {\n return getUsersByIds;\n }\n\n return (_params = {}) =>\n Promise.reject({\n message: t.MemberPicker.pleaseConfigGetUserByIdsMethod,\n });\n }, [getUsersByIds, t.MemberPicker.pleaseConfigGetUserByIdsMethod]);\n const { loading, run } = useRequest(() => queryByKeywords(searchString), {\n refreshDeps: [searchString],\n manual: true,\n cacheKey: 'member-selector',\n cacheTime: 1000 * 60 * 2, // 2分钟内不重复请求\n onSuccess: (result) => {\n setSearchUserList(result);\n },\n onError: (error) => {\n message.error(error.message);\n },\n });\n\n const totalUserList: TUser = useMemo(() => {\n const totalUsers = searchUserList.concat(\n selectedUserList.filter((item) => {\n const name =\n (item.type === EUserType.USER ? item.nickname : item.name) || '';\n\n return name.toUpperCase().includes(searchString.trim().toUpperCase());\n }),\n );\n\n return _.uniqBy(totalUsers, (data: IUser | IUserGroup) => {\n if (data.type === EUserType.USER) return data.userId;\n\n return data.groupId;\n }).filter((item) => {\n if (filterItem) {\n return filterItem(item);\n }\n\n return true;\n });\n }, [filterItem, searchString, searchUserList, selectedUserList]);\n\n useEffect(() => {\n if (!dropdownOpen) return;\n run();\n }, [dropdownOpen, run, searchString]);\n\n useEffect(() => {\n if (_.isEqual(value, prevValue)) {\n return;\n }\n if (Array.isArray(value) && (isUser(value[0]) || isUserGroup(value[0]))) {\n setSelectedUserList(value as TUser);\n } else if (isUser(value) || isUserGroup(value)) {\n setSelectedUserList([value]);\n } else {\n let param: Array<TUserValue | TUserGroupValue> = [];\n if (!value) return;\n if (Array.isArray(value) && value.length === 0) {\n setSelectedUserList([]);\n\n return;\n }\n if (!Array.isArray(value)) {\n param = [value];\n } else {\n param = value;\n }\n queryByIds(param).then((result) => {\n // 如果用户已被删除,则需要展示出id\n const valueNotInResult: TUser = param\n .filter((item) => {\n if (item.type === EUserType.USER) {\n return result\n .filter(isUser)\n .every((user) => user.userId !== item.userId);\n }\n\n return result\n .filter(isUserGroup)\n .every((user) => user.groupId !== item.groupId);\n })\n .map((item) => {\n if (item.type === EUserType.USER) {\n return {\n type: EUserType.USER,\n userId: item.userId,\n } as IUser;\n }\n\n return {\n type: EUserType.USER_GROUP,\n groupId: item.groupId,\n } as IUserGroup;\n });\n\n setSelectedUserList([...result, ...valueNotInResult]);\n });\n }\n }, [value, queryByIds, prevValue]);\n\n const onSelectedChange = useCallback(\n (users: TUser) => {\n if (multiple) {\n setSelectedUserList(users);\n onChange?.(users);\n } else {\n setSelectedUserList(users);\n onChange?.(users[0]);\n }\n setDropdownOpen(false);\n },\n [multiple, onChange, setDropdownOpen],\n );\n\n useEffect(() => {\n if (typeof open === 'boolean') {\n setDropdownOpen(open);\n }\n }, [open]);\n\n useEffect(() => {\n if (!dropdownContentWidth) {\n const resizeEle = triggerRef.current;\n if (!resizeEle) return;\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width } = entry.contentRect;\n setDropdownContentWidth(width);\n }\n });\n resizeObserver.observe(resizeEle);\n\n return () => {\n resizeObserver.unobserve(resizeEle);\n };\n }\n }, [triggerRef, dropdownContentWidth]);\n const onDropdownOpenChange = useCallback(\n (open: boolean) => {\n setDropdownOpen(open);\n onOpenChange?.(open);\n },\n [onOpenChange],\n );\n const panelKey = useMemo(() => {\n if (dropdownOpen) {\n return _.sampleSize('abcdefghijklmnopqrstuvwxyz0123456789', 8).join('');\n }\n }, [dropdownOpen]);\n const mode = useMemo(() => {\n if (multiple === true) {\n if (typeof propsMode === 'object')\n return {\n ...(propsMode || {}),\n type: 'multiple',\n responsive: _.isNil(propsMode.responsive)\n ? true\n : propsMode.responsive,\n } as Mode;\n return {\n type: 'multiple',\n responsive: true,\n } as Mode;\n }\n\n return multiple ? (multiple as Mode) : propsMode;\n }, [multiple, propsMode]);\n\n const selectOpen = typeof open === 'boolean' ? open : dropdownOpen;\n\n return (\n <Select\n prefix={propPrefix}\n {...restProps}\n data-testid={dataTestId}\n aria-label={ariaLabel}\n size={size}\n className={cn('ald-member-picker-select', className)}\n value={selectedUserList.map((item) => {\n if (item.type === EUserType.USER_GROUP) {\n return item.groupId;\n } else {\n return item.userId;\n }\n })}\n onChange={(value) => {\n if (_.isEmpty(value)) {\n setSelectedUserList([]);\n if (multiple) {\n onChange?.([]);\n } else {\n onChange?.();\n }\n } else {\n const valueList = Array.isArray(value) ? value : [value];\n if (multiple) {\n const users = valueList\n .map((item) => {\n const user = totalUserList.find((user) => {\n if (user.type === EUserType.USER) {\n return user.userId === item;\n }\n\n return user.groupId === item;\n });\n\n return user;\n })\n .filter(Boolean) as TUser;\n setSelectedUserList(users);\n onChange?.(users);\n } else {\n const user = totalUserList.find((user) => {\n if (user.type === EUserType.USER) {\n return user.userId === value;\n }\n\n return user.groupId === value;\n });\n if (user) {\n setSelectedUserList([user]);\n onChange?.(user);\n } else {\n setSelectedUserList([]);\n onChange?.();\n }\n }\n }\n }}\n disabled={disabled}\n allowClear={allowClear}\n onClear={() => {\n setSelectedUserList([]);\n if (multiple) {\n onChange?.([]);\n } else {\n onChange?.();\n }\n onClear?.();\n }}\n popupClassName={cn(\n 'ald-member-picker-popup',\n allowOverlap && 'ald-member-picker-popup-adaptive',\n props.popupClassName,\n )}\n mode={mode}\n options={selectedUserList.map((item) => {\n if (item.type === EUserType.USER_GROUP)\n return {\n label: item.name || item.groupId,\n value: item.groupId,\n tag: (\n <div className={'ald-member-picker-tag'}>\n <Avatar type=\"team\" size={20}>\n {item.name || item.groupId}\n </Avatar>\n {item.name || item.groupId}\n </div>\n ),\n };\n\n return {\n label: item.nickname || item.name || item.userId,\n value: item.userId,\n tag: (\n <div className={'ald-member-picker-tag'}>\n <Avatar\n size={20}\n src={item.photo}\n type={item.type === EUserType.USER ? 'user' : 'team'}\n >\n {item.nickname || item.name || item.userId}\n </Avatar>\n {item.nickname || item.name || item.userId}\n </div>\n ),\n };\n })}\n optionLabelProp={multiple ? 'label' : 'tag'}\n open={selectOpen}\n onOpenChange={onDropdownOpenChange}\n popupMatchSelectWidth={panelWidth}\n allowOverlap={allowOverlap}\n placeholder={placeholder}\n dropdownRender={() => {\n return (\n <div\n ref={triggerRef}\n className={cn({\n 'ald-member-picker-popup-body': allowOverlap,\n })}\n >\n <Panel\n type={type}\n footer={footer}\n value={selectedUserList}\n dataList={totalUserList}\n lockedIds={lockedIds}\n multiple={!!multiple}\n key={panelKey}\n loading={loading}\n dropdownWidth={dropdownContentWidth}\n onSearchValueChange={onSearchValueChange}\n onChange={onSelectedChange}\n onCancel={() => {\n onCancel?.();\n setDropdownOpen(false);\n }}\n renderItem={renderItem}\n renderSelectedTag={renderSelectedTag}\n ></Panel>\n </div>\n );\n }}\n ></Select>\n );\n};\n\nconst MemberSelector = Component as React.FC<IMemberPickerProps> & {\n MemberPanel: typeof MemberPanel;\n};\n\nMemberSelector.MemberPanel = MemberPanel;\nexport default MemberSelector;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/MemberPicker/index.tsx"],"sourcesContent":["import { usePrevious, useRequest } from 'ahooks';\nimport { cn } from '../lib/utils';\nimport _ from 'lodash';\nimport React, {\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport Avatar from '../Avatar';\nimport ConfigProvider from '../ConfigProvider';\nimport './member-picker.css';\nimport {\n EUserType,\n IUser,\n IUserGroup,\n TUser,\n} from '../ConfigProvider/getUserList';\nimport { LocaleContext, getTranslator } from '../locale/default';\nimport message from '../message';\nimport Panel from './components/Panel';\nimport MemberPanel from './components/PanelWrapper';\nimport {\n EMemberPicker,\n IMemberPickerProps,\n TUserGroupValue,\n TUserValue,\n} from './interface';\nimport { getId } from './utils';\nimport { isUser, isUserGroup } from './utils/getUsersWithUserId';\nimport Select from '../Select';\nimport { Mode } from '../Select/BaseSelect';\n\nconst DEFAULT_MULTIPLE_DROPDOWN_WIDTH = 480;\n\nconst Component: React.FC<IMemberPickerProps> = (props) => {\n const { locale } = useContext(LocaleContext);\n const t = getTranslator(locale);\n\n const {\n value,\n type = EMemberPicker.USER,\n onChange,\n multiple,\n dropdownWidth,\n open,\n onOpenChange,\n placeholder = t.MemberPicker.select,\n className,\n allowClear,\n disabled,\n onClear,\n size,\n prefix: propPrefix,\n lockedIds = [],\n footer,\n onCancel,\n filterItem,\n mode: propsMode,\n renderItem,\n renderSelectedTag,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n ...restProps\n } = props;\n const allowOverlap = props.allowOverlap ?? false;\n const { getUsersByIds, getUsersByKeywords } = ConfigProvider.useGetUserList();\n const [selectedUserList, setSelectedUserList] = useState<TUser>([]);\n const prevValue = usePrevious(value);\n const [searchUserList, setSearchUserList] = useState<TUser>([]);\n const [searchString, setSearchString] = useState<string>('');\n const [dropdownContentWidth, setDropdownContentWidth] =\n useState(dropdownWidth);\n const selectOwnerRef = useRef<HTMLDivElement>(null);\n // 单选默认浮窗跟触发器等宽(true),调用方传 dropdownWidth 时用具体数字;\n // 多选默认 480,单条记录只有 头像+nickname 时触发器太窄装不下选中标签,故固定值。\n const panelWidth: number | boolean =\n dropdownWidth ?? (multiple ? DEFAULT_MULTIPLE_DROPDOWN_WIDTH : true);\n\n const triggerRef = useRef<HTMLDivElement>(null);\n const onSearchValueChange = useCallback((v: string) => {\n setSearchString(v);\n }, []);\n const [dropdownOpen, setDropdownOpen] = useState<boolean>(!!open);\n const queryByKeywords = useMemo(() => {\n if (getUsersByKeywords) {\n return getUsersByKeywords;\n }\n\n return (_params = {}) =>\n Promise.reject({\n message: t.MemberPicker.pleaseConfigGetUserByKeywordsMethod,\n });\n }, [getUsersByKeywords, t.MemberPicker.pleaseConfigGetUserByKeywordsMethod]);\n const queryByIds = useMemo(() => {\n if (getUsersByIds) {\n return getUsersByIds;\n }\n\n return (_params = {}) =>\n Promise.reject({\n message: t.MemberPicker.pleaseConfigGetUserByIdsMethod,\n });\n }, [getUsersByIds, t.MemberPicker.pleaseConfigGetUserByIdsMethod]);\n const { loading, run } = useRequest(() => queryByKeywords(searchString), {\n refreshDeps: [searchString],\n manual: true,\n cacheKey: 'member-selector',\n cacheTime: 1000 * 60 * 2, // 2分钟内不重复请求\n onSuccess: (result) => {\n setSearchUserList(result);\n },\n onError: (error) => {\n message.error(error.message);\n },\n });\n\n const totalUserList: TUser = useMemo(() => {\n const totalUsers = searchUserList.concat(\n selectedUserList.filter((item) => {\n const name =\n (item.type === EUserType.USER ? item.nickname : item.name) || '';\n\n return name.toUpperCase().includes(searchString.trim().toUpperCase());\n }),\n );\n\n return _.uniqBy(totalUsers, (data: IUser | IUserGroup) => {\n if (data.type === EUserType.USER) return data.userId;\n\n return data.groupId;\n }).filter((item) => {\n if (filterItem) {\n return filterItem(item);\n }\n\n return true;\n });\n }, [filterItem, searchString, searchUserList, selectedUserList]);\n\n useEffect(() => {\n if (!dropdownOpen) return;\n run();\n }, [dropdownOpen, run, searchString]);\n\n useEffect(() => {\n if (_.isEqual(value, prevValue)) {\n return;\n }\n if (Array.isArray(value) && (isUser(value[0]) || isUserGroup(value[0]))) {\n setSelectedUserList(value as TUser);\n } else if (isUser(value) || isUserGroup(value)) {\n setSelectedUserList([value]);\n } else {\n let param: Array<TUserValue | TUserGroupValue> = [];\n if (!value) return;\n if (Array.isArray(value) && value.length === 0) {\n setSelectedUserList([]);\n\n return;\n }\n if (!Array.isArray(value)) {\n param = [value];\n } else {\n param = value;\n }\n queryByIds(param).then((result) => {\n // 如果用户已被删除,则需要展示出id\n const valueNotInResult: TUser = param\n .filter((item) => {\n if (item.type === EUserType.USER) {\n return result\n .filter(isUser)\n .every((user) => user.userId !== item.userId);\n }\n\n return result\n .filter(isUserGroup)\n .every((user) => user.groupId !== item.groupId);\n })\n .map((item) => {\n if (item.type === EUserType.USER) {\n return {\n type: EUserType.USER,\n userId: item.userId,\n } as IUser;\n }\n\n return {\n type: EUserType.USER_GROUP,\n groupId: item.groupId,\n } as IUserGroup;\n });\n\n setSelectedUserList([...result, ...valueNotInResult]);\n });\n }\n }, [value, queryByIds, prevValue]);\n\n const onSelectedChange = useCallback(\n (users: TUser) => {\n if (multiple) {\n setSelectedUserList(users);\n onChange?.(users);\n } else {\n setSelectedUserList(users);\n onChange?.(users[0]);\n }\n setDropdownOpen(false);\n },\n [multiple, onChange, setDropdownOpen],\n );\n\n useEffect(() => {\n if (typeof open === 'boolean') {\n setDropdownOpen(open);\n }\n }, [open]);\n\n useEffect(() => {\n if (!dropdownContentWidth) {\n const resizeEle = triggerRef.current;\n if (!resizeEle) return;\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width } = entry.contentRect;\n setDropdownContentWidth(width);\n }\n });\n resizeObserver.observe(resizeEle);\n\n return () => {\n resizeObserver.unobserve(resizeEle);\n };\n }\n }, [triggerRef, dropdownContentWidth]);\n const onDropdownOpenChange = useCallback(\n (open: boolean) => {\n setDropdownOpen(open);\n onOpenChange?.(open);\n },\n [onOpenChange],\n );\n const mode = useMemo(() => {\n if (multiple === true) {\n if (typeof propsMode === 'object')\n return {\n ...(propsMode || {}),\n type: 'multiple',\n responsive: _.isNil(propsMode.responsive)\n ? true\n : propsMode.responsive,\n } as Mode;\n return {\n type: 'multiple',\n responsive: true,\n } as Mode;\n }\n\n return multiple ? (multiple as Mode) : propsMode;\n }, [multiple, propsMode]);\n\n const selectOpen = typeof open === 'boolean' ? open : dropdownOpen;\n const listboxId = `ald-member-picker-listbox-${React.useId().replace(\n /:/g,\n '',\n )}`;\n const activeMember = totalUserList[0];\n const activeMemberId = activeMember\n ? `ald-member-picker-option-${getId(activeMember)}`\n : undefined;\n\n useEffect(() => {\n const owner = selectOwnerRef.current?.querySelector<HTMLElement>(\n '[role=\"combobox\"], input',\n );\n if (!owner) return;\n owner.setAttribute('aria-controls', listboxId);\n if (selectOpen && activeMemberId) {\n owner.setAttribute('aria-activedescendant', activeMemberId);\n } else {\n owner.removeAttribute('aria-activedescendant');\n }\n }, [activeMemberId, listboxId, selectOpen]);\n\n return (\n <div ref={selectOwnerRef} style={{ display: 'contents' }}>\n <Select\n prefix={propPrefix}\n {...restProps}\n data-testid={dataTestId}\n aria-label={ariaLabel}\n showSearch\n searchValue={searchString}\n onSearch={onSearchValueChange}\n aria-controls={listboxId}\n aria-activedescendant={selectOpen ? activeMemberId : undefined}\n size={size}\n className={cn('ald-member-picker-select', className)}\n value={selectedUserList.map((item) => {\n if (item.type === EUserType.USER_GROUP) {\n return item.groupId;\n } else {\n return item.userId;\n }\n })}\n onChange={(value) => {\n if (_.isEmpty(value)) {\n setSelectedUserList([]);\n if (multiple) {\n onChange?.([]);\n } else {\n onChange?.();\n }\n } else {\n const valueList = Array.isArray(value) ? value : [value];\n if (multiple) {\n const users = valueList\n .map((item) => {\n const user = totalUserList.find((user) => {\n if (user.type === EUserType.USER) {\n return user.userId === item;\n }\n\n return user.groupId === item;\n });\n\n return user;\n })\n .filter(Boolean) as TUser;\n setSelectedUserList(users);\n onChange?.(users);\n } else {\n const user = totalUserList.find((user) => {\n if (user.type === EUserType.USER) {\n return user.userId === value;\n }\n\n return user.groupId === value;\n });\n if (user) {\n setSelectedUserList([user]);\n onChange?.(user);\n } else {\n setSelectedUserList([]);\n onChange?.();\n }\n }\n }\n }}\n disabled={disabled}\n allowClear={allowClear}\n onClear={() => {\n setSelectedUserList([]);\n if (multiple) {\n onChange?.([]);\n } else {\n onChange?.();\n }\n onClear?.();\n }}\n popupClassName={cn(\n 'ald-member-picker-popup',\n allowOverlap && 'ald-member-picker-popup-adaptive',\n props.popupClassName,\n )}\n mode={mode}\n options={selectedUserList.map((item) => {\n if (item.type === EUserType.USER_GROUP)\n return {\n label: item.name || item.groupId,\n value: item.groupId,\n tag: (\n <div className={'ald-member-picker-tag'}>\n <Avatar type=\"team\" size={20}>\n {item.name || item.groupId}\n </Avatar>\n {item.name || item.groupId}\n </div>\n ),\n };\n\n return {\n label: item.nickname || item.name || item.userId,\n value: item.userId,\n tag: (\n <div className={'ald-member-picker-tag'}>\n <Avatar\n size={20}\n src={item.photo}\n type={item.type === EUserType.USER ? 'user' : 'team'}\n >\n {item.nickname || item.name || item.userId}\n </Avatar>\n {item.nickname || item.name || item.userId}\n </div>\n ),\n };\n })}\n optionLabelProp={multiple ? 'label' : 'tag'}\n open={selectOpen}\n onOpenChange={onDropdownOpenChange}\n popupMatchSelectWidth={panelWidth}\n allowOverlap={allowOverlap}\n placeholder={placeholder}\n dropdownRender={() => {\n return (\n <div\n ref={triggerRef}\n id={listboxId}\n role=\"group\"\n aria-label=\"Member selection results\"\n className={cn({\n 'ald-member-picker-popup-body': allowOverlap,\n })}\n >\n <Panel\n type={type}\n footer={footer}\n value={selectedUserList}\n dataList={totalUserList}\n lockedIds={lockedIds}\n multiple={!!multiple}\n loading={loading}\n dropdownWidth={dropdownContentWidth}\n onSearchValueChange={onSearchValueChange}\n onChange={onSelectedChange}\n onCancel={() => {\n onCancel?.();\n setDropdownOpen(false);\n }}\n renderItem={renderItem}\n renderSelectedTag={renderSelectedTag}\n searchValue={searchString}\n ></Panel>\n </div>\n );\n }}\n ></Select>\n </div>\n );\n};\n\nconst MemberSelector = Component as React.FC<IMemberPickerProps> & {\n MemberPanel: typeof MemberPanel;\n};\n\nMemberSelector.MemberPanel = MemberPanel;\nexport default MemberSelector;\n"],"mappings":"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"}
|
package/dist/Menu/index.d.ts
CHANGED
|
@@ -6,6 +6,12 @@ export interface MenuProps {
|
|
|
6
6
|
items: MenuItemType[];
|
|
7
7
|
selectedKeys?: string[];
|
|
8
8
|
menuStyle?: React.CSSProperties;
|
|
9
|
+
/** Accessible name for the command menu when its context is not otherwise clear. */
|
|
10
|
+
ariaLabel?: string;
|
|
11
|
+
/** @internal Requested initial keyboard position when the popup opens. */
|
|
12
|
+
initialFocus?: 'first' | 'last';
|
|
13
|
+
/** @internal Requests that the owning popup close, including on Escape. */
|
|
14
|
+
onRequestClose?: (reason: 'click' | 'cancel' | 'blur' | 'scroll') => void;
|
|
9
15
|
rootClosing?: boolean;
|
|
10
16
|
/** @internal 由 Dropdown 注入,禁用内部定位/overflow 计算。不支持含 SubMenu 的菜单 */
|
|
11
17
|
externalOverflow?: boolean;
|
|
@@ -24,6 +30,7 @@ export interface ItemType {
|
|
|
24
30
|
danger?: boolean;
|
|
25
31
|
disabled?: boolean;
|
|
26
32
|
className?: string;
|
|
33
|
+
ariaLabel?: string;
|
|
27
34
|
}
|
|
28
35
|
export interface MenuDividerType {
|
|
29
36
|
key?: string;
|
|
@@ -41,6 +48,7 @@ export interface SubMenuType {
|
|
|
41
48
|
icon?: React.ReactNode;
|
|
42
49
|
popupClassName?: string;
|
|
43
50
|
disabled?: boolean;
|
|
51
|
+
ariaLabel?: string;
|
|
44
52
|
}
|
|
45
53
|
export interface MenuInfo {
|
|
46
54
|
key: string;
|
package/dist/Menu/index.js
CHANGED
|
@@ -2,14 +2,38 @@ import { cn } from "../lib/utils.js";
|
|
|
2
2
|
import Memo from "../Icon/components/CheckLightLine.js";
|
|
3
3
|
import Memo$1 from "../Icon/components/ChevronRightLine.js";
|
|
4
4
|
/* empty css */
|
|
5
|
-
import { useRef } from "react";
|
|
5
|
+
import { useCallback, useMemo, useRef } from "react";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import _ from "lodash";
|
|
8
8
|
import { ControlledMenu, MenuDivider, MenuHeader, MenuItem, SubMenu } from "@szhsin/react-menu";
|
|
9
9
|
//#region src/Menu/index.tsx
|
|
10
10
|
function Menu(props) {
|
|
11
|
-
const { className, items, onClick: onMenuClick, onBeforeLeafItemClick, selectedKeys, menuStyle, rootClosing = false, externalOverflow } = props;
|
|
11
|
+
const { className, items, onClick: onMenuClick, onBeforeLeafItemClick, selectedKeys, menuStyle, ariaLabel, initialFocus = "first", onRequestClose, rootClosing = false, externalOverflow } = props;
|
|
12
12
|
const selectedKeySet = new Set(selectedKeys || []);
|
|
13
|
+
const typeaheadRef = useRef({
|
|
14
|
+
query: "",
|
|
15
|
+
timestamp: 0
|
|
16
|
+
});
|
|
17
|
+
const menuItemFocus = useMemo(() => ({ position: initialFocus }), [initialFocus]);
|
|
18
|
+
const onMenuKeyDown = useCallback((event) => {
|
|
19
|
+
if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || event.key.length !== 1) return;
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
const previous = typeaheadRef.current;
|
|
22
|
+
const query = `${now - previous.timestamp > 500 ? "" : previous.query}${event.key}`.toLocaleLowerCase();
|
|
23
|
+
typeaheadRef.current = {
|
|
24
|
+
query,
|
|
25
|
+
timestamp: now
|
|
26
|
+
};
|
|
27
|
+
const menuItems = Array.from(event.currentTarget.querySelectorAll("[role=\"menuitem\"]:not([aria-hidden=\"true\"]):not([aria-disabled=\"true\"])"));
|
|
28
|
+
const activeIndex = menuItems.indexOf(document.activeElement);
|
|
29
|
+
const match = [...menuItems.slice(activeIndex + 1), ...menuItems.slice(0, activeIndex + 1)].find((item) => {
|
|
30
|
+
return (item.getAttribute("aria-label") || item.textContent || "").trim().toLocaleLowerCase().startsWith(query);
|
|
31
|
+
});
|
|
32
|
+
if (match) {
|
|
33
|
+
event.preventDefault();
|
|
34
|
+
match.focus();
|
|
35
|
+
}
|
|
36
|
+
}, []);
|
|
13
37
|
const hasDirectSelectedItem = (items) => items.some((item) => {
|
|
14
38
|
if (isSubMenuItem(item)) return selectedKeySet.has(item.key);
|
|
15
39
|
if (isHeaderMenuItem(item) || isDivideMenuItem(item)) return false;
|
|
@@ -46,6 +70,7 @@ function Menu(props) {
|
|
|
46
70
|
]
|
|
47
71
|
}),
|
|
48
72
|
disabled: item.disabled,
|
|
73
|
+
"aria-label": item.ariaLabel || titleStr || void 0,
|
|
49
74
|
itemProps: { className: isLeafSubMenu ? "ald-menu-submenu-leaf-trigger" : void 0 },
|
|
50
75
|
align: "start",
|
|
51
76
|
direction: "right",
|
|
@@ -64,6 +89,7 @@ function Menu(props) {
|
|
|
64
89
|
"ald-menu-item-selected": isSelected
|
|
65
90
|
}),
|
|
66
91
|
disabled: item.disabled,
|
|
92
|
+
"aria-label": item.ariaLabel || titleStr || void 0,
|
|
67
93
|
onClick: ({ syntheticEvent }) => {
|
|
68
94
|
onBeforeLeafItemClick?.();
|
|
69
95
|
const menuInfo = {
|
|
@@ -117,7 +143,11 @@ function Menu(props) {
|
|
|
117
143
|
anchorRef: ref,
|
|
118
144
|
className: cn(className, "ald-menu", isLeafRootMenu && !externalOverflow && "ald-menu-leaf", !isLeafRootMenu && menuStyle?.maxHeight !== void 0 && !externalOverflow && "ald-menu-scrollable"),
|
|
119
145
|
position: externalOverflow ? "initial" : "auto",
|
|
120
|
-
|
|
146
|
+
"aria-label": ariaLabel,
|
|
147
|
+
captureFocus: true,
|
|
148
|
+
menuItemFocus,
|
|
149
|
+
onKeyDown: onMenuKeyDown,
|
|
150
|
+
onClose: ({ reason }) => onRequestClose?.(reason),
|
|
121
151
|
viewScroll: externalOverflow ? "initial" : "auto",
|
|
122
152
|
overflow: externalOverflow ? "visible" : menuOverflow,
|
|
123
153
|
children: getMenuItems(items || [])
|
package/dist/Menu/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/Menu/index.tsx"],"sourcesContent":["import {\n ControlledMenu,\n MenuDivider,\n MenuHeader,\n MenuItem,\n SubMenu,\n} from '@szhsin/react-menu';\nimport { cn } from '../lib/utils';\nimport _ from 'lodash';\nimport React, { useRef } from 'react';\nimport { CheckLightLine, ChevronRightLine } from '../Icon';\nimport './menu.css';\n\nexport interface MenuProps {\n onClick?: (info: MenuInfo) => void;\n onBeforeLeafItemClick?: () => void;\n className?: string;\n items: MenuItemType[];\n selectedKeys?: string[];\n menuStyle?: React.CSSProperties;\n rootClosing?: boolean;\n /** @internal 由 Dropdown 注入,禁用内部定位/overflow 计算。不支持含 SubMenu 的菜单 */\n externalOverflow?: boolean;\n}\n\nexport default function Menu(props: MenuProps) {\n const {\n className,\n items,\n onClick: onMenuClick,\n onBeforeLeafItemClick,\n selectedKeys,\n menuStyle,\n rootClosing = false,\n externalOverflow,\n } = props;\n const selectedKeySet = new Set(selectedKeys || []);\n\n const hasDirectSelectedItem = (items: MenuItemType[]): boolean =>\n items.some((item) => {\n if (isSubMenuItem(item)) {\n return selectedKeySet.has(item.key);\n }\n if (isHeaderMenuItem(item) || isDivideMenuItem(item)) {\n return false;\n }\n return selectedKeySet.has(item.key);\n });\n\n const getMenuItems = (items: MenuItemType[], parentPath: string[] = []) => {\n const isSelectableGroup = hasDirectSelectedItem(items);\n\n return items.map((item, index) => {\n if (isDivideMenuItem(item)) {\n return <MenuDivider key={`divider_${index}`} />;\n }\n if (isHeaderMenuItem(item)) {\n return <MenuHeader key={`header_${index}`}>{item.label}</MenuHeader>;\n }\n const currPath = [...parentPath, item.key];\n const titleStr = _.isString(item.label) ? item.label : '';\n const isSelected = selectedKeys?.includes(item.key);\n\n if (isSubMenuItem(item)) {\n const isLeafSubMenu = isLeafMenu(item.children);\n const subMenuOverflow =\n isLeafSubMenu || menuStyle?.maxHeight !== undefined\n ? 'auto'\n : undefined;\n const subMenuItemLabel = (\n <div className=\"ald-menu-item-label\" title={titleStr}>\n {item.icon ? (\n <div className=\"ald-menu-item-label-icon\">{item.icon}</div>\n ) : null}\n <div className=\"ald-menu-item-label-text tw-text-typography-body-dense\">\n {item.label}\n </div>\n <div className=\"ald-menu-item-right\">\n {isSelectableGroup ? (\n <div className=\"ald-menu-item-selection-slot\" />\n ) : null}\n <ChevronRightLine size={16} />\n </div>\n </div>\n );\n\n return (\n <SubMenu\n key={item.key}\n label={subMenuItemLabel}\n disabled={item.disabled}\n itemProps={{\n className: isLeafSubMenu\n ? 'ald-menu-submenu-leaf-trigger'\n : undefined,\n }}\n align=\"start\"\n direction=\"right\"\n gap={-8}\n position=\"anchor\"\n shift={0}\n menuStyle={{\n ...menuStyle,\n }}\n menuClassName={cn(\n 'ald-menu-submenu-popup',\n isLeafSubMenu && 'ald-menu-submenu-popup-leaf',\n !isLeafSubMenu &&\n menuStyle?.maxHeight !== undefined &&\n 'ald-menu-submenu-popup-scrollable',\n item.popupClassName,\n rootClosing && 'ald-menu-submenu-popup-root-closing',\n )}\n overflow={subMenuOverflow}\n >\n {getMenuItems(item.children, currPath)}\n </SubMenu>\n );\n }\n\n return (\n <MenuItem\n key={item.key}\n className={cn(item.className, {\n 'ald-menu-item-danger': item.danger,\n 'ald-menu-item-selected': isSelected,\n })}\n disabled={item.disabled}\n onClick={({ syntheticEvent }) => {\n onBeforeLeafItemClick?.();\n const menuInfo = {\n key: item.key,\n keyPath: currPath,\n domEvent: syntheticEvent,\n };\n if (item.onClick) {\n item.onClick(menuInfo);\n }\n if (onMenuClick) {\n onMenuClick(menuInfo);\n }\n }}\n >\n <div className=\"ald-menu-item-label\" title={titleStr}>\n {item.icon ? (\n <div className=\"ald-menu-item-label-icon\">{item.icon}</div>\n ) : null}\n <div className=\"ald-menu-item-label-text tw-text-typography-body-dense\">\n {item.label}\n </div>\n {isSelectableGroup ? (\n <div className=\"ald-menu-item-right\">\n <div\n className={cn(\n 'ald-menu-item-selection-slot',\n isSelected &&\n 'ald-menu-item-selection-slot-selected ald-menu-item-selected-icon',\n )}\n >\n {isSelected ? <CheckLightLine /> : null}\n </div>\n </div>\n ) : null}\n </div>\n </MenuItem>\n );\n });\n };\n\n const ref = useRef(null);\n\n const isLeafRootMenu = isLeafMenu(items);\n const menuOverflow =\n isLeafRootMenu || menuStyle?.maxHeight !== undefined ? 'auto' : undefined;\n\n return (\n <>\n <div style={{ display: 'none' }} ref={ref} />\n <ControlledMenu\n state=\"open\"\n transition={{ open: true, close: true }}\n transitionTimeout={200}\n submenuOpenDelay={0}\n submenuCloseDelay={0}\n menuStyle={{\n ...menuStyle,\n }}\n anchorRef={ref}\n className={cn(\n className,\n 'ald-menu',\n isLeafRootMenu && !externalOverflow && 'ald-menu-leaf',\n !isLeafRootMenu &&\n menuStyle?.maxHeight !== undefined &&\n !externalOverflow &&\n 'ald-menu-scrollable',\n )}\n position={externalOverflow ? 'initial' : 'auto'}\n captureFocus={false}\n viewScroll={externalOverflow ? 'initial' : 'auto'}\n overflow={externalOverflow ? 'visible' : menuOverflow}\n >\n {getMenuItems(items || [])}\n </ControlledMenu>\n </>\n );\n}\n\nexport function isHeaderMenuItem(\n menuItem: MenuItemType,\n): menuItem is MenuHeaderType {\n return 'type' in menuItem && menuItem.type === 'header';\n}\n\nexport function isDivideMenuItem(\n menuItem: MenuItemType,\n): menuItem is MenuDividerType {\n return 'type' in menuItem && menuItem.type === 'divider';\n}\n\nexport function isSubMenuItem(menuItem: MenuItemType): menuItem is SubMenuType {\n return 'children' in menuItem && !!menuItem.children;\n}\n\nexport function isLeafMenu(menuItems: MenuItemType[]) {\n return !_.some(menuItems, (item) => isSubMenuItem(item));\n}\n\nexport type MenuItemType =\n | ItemType\n | MenuDividerType\n | SubMenuType\n | MenuHeaderType;\n\nexport interface ItemType {\n key: string;\n label: React.ReactNode;\n icon?: React.ReactNode;\n onClick?: (info: MenuInfo) => void;\n danger?: boolean;\n disabled?: boolean;\n className?: string;\n}\n\nexport interface MenuDividerType {\n key?: string;\n type: 'divider';\n}\n\nexport interface MenuHeaderType {\n key?: string;\n type: 'header';\n label: string;\n}\n\nexport interface SubMenuType {\n children: MenuItemType[];\n key: string;\n label: React.ReactNode;\n icon?: React.ReactNode;\n popupClassName?: string;\n disabled?: boolean;\n}\n\nexport interface MenuInfo {\n key: string;\n keyPath: string[];\n domEvent: MouseEvent | KeyboardEvent;\n // 阻止菜单关闭\n keepOpen?: boolean;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/Menu/index.tsx"],"sourcesContent":["import {\n ControlledMenu,\n MenuDivider,\n MenuHeader,\n MenuItem,\n SubMenu,\n} from '@szhsin/react-menu';\nimport { cn } from '../lib/utils';\nimport _ from 'lodash';\nimport React, { useCallback, useMemo, useRef } from 'react';\nimport { CheckLightLine, ChevronRightLine } from '../Icon';\nimport './menu.css';\n\nexport interface MenuProps {\n onClick?: (info: MenuInfo) => void;\n onBeforeLeafItemClick?: () => void;\n className?: string;\n items: MenuItemType[];\n selectedKeys?: string[];\n menuStyle?: React.CSSProperties;\n /** Accessible name for the command menu when its context is not otherwise clear. */\n ariaLabel?: string;\n /** @internal Requested initial keyboard position when the popup opens. */\n initialFocus?: 'first' | 'last';\n /** @internal Requests that the owning popup close, including on Escape. */\n onRequestClose?: (reason: 'click' | 'cancel' | 'blur' | 'scroll') => void;\n rootClosing?: boolean;\n /** @internal 由 Dropdown 注入,禁用内部定位/overflow 计算。不支持含 SubMenu 的菜单 */\n externalOverflow?: boolean;\n}\n\nexport default function Menu(props: MenuProps) {\n const {\n className,\n items,\n onClick: onMenuClick,\n onBeforeLeafItemClick,\n selectedKeys,\n menuStyle,\n ariaLabel,\n initialFocus = 'first',\n onRequestClose,\n rootClosing = false,\n externalOverflow,\n } = props;\n const selectedKeySet = new Set(selectedKeys || []);\n const typeaheadRef = useRef({ query: '', timestamp: 0 });\n const menuItemFocus = useMemo(\n () => ({ position: initialFocus }),\n [initialFocus],\n );\n const onMenuKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLUListElement>) => {\n if (\n event.defaultPrevented ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n event.key.length !== 1\n ) {\n return;\n }\n\n const now = Date.now();\n const previous = typeaheadRef.current;\n const query = `${now - previous.timestamp > 500 ? '' : previous.query}${\n event.key\n }`.toLocaleLowerCase();\n typeaheadRef.current = { query, timestamp: now };\n\n const menuItems = Array.from(\n event.currentTarget.querySelectorAll<HTMLElement>(\n '[role=\"menuitem\"]:not([aria-hidden=\"true\"]):not([aria-disabled=\"true\"])',\n ),\n );\n const activeIndex = menuItems.indexOf(\n document.activeElement as HTMLElement,\n );\n const orderedItems = [\n ...menuItems.slice(activeIndex + 1),\n ...menuItems.slice(0, activeIndex + 1),\n ];\n const match = orderedItems.find((item) => {\n const accessibleName =\n item.getAttribute('aria-label') || item.textContent || '';\n return accessibleName.trim().toLocaleLowerCase().startsWith(query);\n });\n\n if (match) {\n event.preventDefault();\n match.focus();\n }\n },\n [],\n );\n\n const hasDirectSelectedItem = (items: MenuItemType[]): boolean =>\n items.some((item) => {\n if (isSubMenuItem(item)) {\n return selectedKeySet.has(item.key);\n }\n if (isHeaderMenuItem(item) || isDivideMenuItem(item)) {\n return false;\n }\n return selectedKeySet.has(item.key);\n });\n\n const getMenuItems = (items: MenuItemType[], parentPath: string[] = []) => {\n const isSelectableGroup = hasDirectSelectedItem(items);\n\n return items.map((item, index) => {\n if (isDivideMenuItem(item)) {\n return <MenuDivider key={`divider_${index}`} />;\n }\n if (isHeaderMenuItem(item)) {\n return <MenuHeader key={`header_${index}`}>{item.label}</MenuHeader>;\n }\n const currPath = [...parentPath, item.key];\n const titleStr = _.isString(item.label) ? item.label : '';\n const isSelected = selectedKeys?.includes(item.key);\n\n if (isSubMenuItem(item)) {\n const isLeafSubMenu = isLeafMenu(item.children);\n const subMenuOverflow =\n isLeafSubMenu || menuStyle?.maxHeight !== undefined\n ? 'auto'\n : undefined;\n const subMenuItemLabel = (\n <div className=\"ald-menu-item-label\" title={titleStr}>\n {item.icon ? (\n <div className=\"ald-menu-item-label-icon\">{item.icon}</div>\n ) : null}\n <div className=\"ald-menu-item-label-text tw-text-typography-body-dense\">\n {item.label}\n </div>\n <div className=\"ald-menu-item-right\">\n {isSelectableGroup ? (\n <div className=\"ald-menu-item-selection-slot\" />\n ) : null}\n <ChevronRightLine size={16} />\n </div>\n </div>\n );\n\n return (\n <SubMenu\n key={item.key}\n label={subMenuItemLabel}\n disabled={item.disabled}\n aria-label={item.ariaLabel || titleStr || undefined}\n itemProps={{\n className: isLeafSubMenu\n ? 'ald-menu-submenu-leaf-trigger'\n : undefined,\n }}\n align=\"start\"\n direction=\"right\"\n gap={-8}\n position=\"anchor\"\n shift={0}\n menuStyle={{\n ...menuStyle,\n }}\n menuClassName={cn(\n 'ald-menu-submenu-popup',\n isLeafSubMenu && 'ald-menu-submenu-popup-leaf',\n !isLeafSubMenu &&\n menuStyle?.maxHeight !== undefined &&\n 'ald-menu-submenu-popup-scrollable',\n item.popupClassName,\n rootClosing && 'ald-menu-submenu-popup-root-closing',\n )}\n overflow={subMenuOverflow}\n >\n {getMenuItems(item.children, currPath)}\n </SubMenu>\n );\n }\n\n return (\n <MenuItem\n key={item.key}\n className={cn(item.className, {\n 'ald-menu-item-danger': item.danger,\n 'ald-menu-item-selected': isSelected,\n })}\n disabled={item.disabled}\n aria-label={item.ariaLabel || titleStr || undefined}\n onClick={({ syntheticEvent }) => {\n onBeforeLeafItemClick?.();\n const menuInfo = {\n key: item.key,\n keyPath: currPath,\n domEvent: syntheticEvent,\n };\n if (item.onClick) {\n item.onClick(menuInfo);\n }\n if (onMenuClick) {\n onMenuClick(menuInfo);\n }\n }}\n >\n <div className=\"ald-menu-item-label\" title={titleStr}>\n {item.icon ? (\n <div className=\"ald-menu-item-label-icon\">{item.icon}</div>\n ) : null}\n <div className=\"ald-menu-item-label-text tw-text-typography-body-dense\">\n {item.label}\n </div>\n {isSelectableGroup ? (\n <div className=\"ald-menu-item-right\">\n <div\n className={cn(\n 'ald-menu-item-selection-slot',\n isSelected &&\n 'ald-menu-item-selection-slot-selected ald-menu-item-selected-icon',\n )}\n >\n {isSelected ? <CheckLightLine /> : null}\n </div>\n </div>\n ) : null}\n </div>\n </MenuItem>\n );\n });\n };\n\n const ref = useRef(null);\n\n const isLeafRootMenu = isLeafMenu(items);\n const menuOverflow =\n isLeafRootMenu || menuStyle?.maxHeight !== undefined ? 'auto' : undefined;\n\n return (\n <>\n <div style={{ display: 'none' }} ref={ref} />\n <ControlledMenu\n state=\"open\"\n transition={{ open: true, close: true }}\n transitionTimeout={200}\n submenuOpenDelay={0}\n submenuCloseDelay={0}\n menuStyle={{\n ...menuStyle,\n }}\n anchorRef={ref}\n className={cn(\n className,\n 'ald-menu',\n isLeafRootMenu && !externalOverflow && 'ald-menu-leaf',\n !isLeafRootMenu &&\n menuStyle?.maxHeight !== undefined &&\n !externalOverflow &&\n 'ald-menu-scrollable',\n )}\n position={externalOverflow ? 'initial' : 'auto'}\n aria-label={ariaLabel}\n captureFocus\n menuItemFocus={menuItemFocus}\n onKeyDown={onMenuKeyDown}\n onClose={({ reason }) => onRequestClose?.(reason)}\n viewScroll={externalOverflow ? 'initial' : 'auto'}\n overflow={externalOverflow ? 'visible' : menuOverflow}\n >\n {getMenuItems(items || [])}\n </ControlledMenu>\n </>\n );\n}\n\nexport function isHeaderMenuItem(\n menuItem: MenuItemType,\n): menuItem is MenuHeaderType {\n return 'type' in menuItem && menuItem.type === 'header';\n}\n\nexport function isDivideMenuItem(\n menuItem: MenuItemType,\n): menuItem is MenuDividerType {\n return 'type' in menuItem && menuItem.type === 'divider';\n}\n\nexport function isSubMenuItem(menuItem: MenuItemType): menuItem is SubMenuType {\n return 'children' in menuItem && !!menuItem.children;\n}\n\nexport function isLeafMenu(menuItems: MenuItemType[]) {\n return !_.some(menuItems, (item) => isSubMenuItem(item));\n}\n\nexport type MenuItemType =\n | ItemType\n | MenuDividerType\n | SubMenuType\n | MenuHeaderType;\n\nexport interface ItemType {\n key: string;\n label: React.ReactNode;\n icon?: React.ReactNode;\n onClick?: (info: MenuInfo) => void;\n danger?: boolean;\n disabled?: boolean;\n className?: string;\n ariaLabel?: string;\n}\n\nexport interface MenuDividerType {\n key?: string;\n type: 'divider';\n}\n\nexport interface MenuHeaderType {\n key?: string;\n type: 'header';\n label: string;\n}\n\nexport interface SubMenuType {\n children: MenuItemType[];\n key: string;\n label: React.ReactNode;\n icon?: React.ReactNode;\n popupClassName?: string;\n disabled?: boolean;\n ariaLabel?: string;\n}\n\nexport interface MenuInfo {\n key: string;\n keyPath: string[];\n domEvent: MouseEvent | KeyboardEvent;\n // 阻止菜单关闭\n keepOpen?: boolean;\n}\n"],"mappings":"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"}
|
package/dist/Modal/index.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export interface ModalProps {
|
|
|
27
27
|
'data-testid'?: string;
|
|
28
28
|
/** Pass through to the modal content root for accessibility and automated testing. */
|
|
29
29
|
'aria-label'?: string;
|
|
30
|
+
/** Dialog semantic role. Use alertdialog only for explicitly urgent confirmation flows. */
|
|
31
|
+
role?: 'dialog' | 'alertdialog';
|
|
30
32
|
/** Applied to the outer wrap layer (matches antd wrapClassName behavior) */
|
|
31
33
|
wrapClassName?: string;
|
|
32
34
|
style?: React.CSSProperties;
|
|
@@ -67,6 +69,8 @@ export interface ModalFuncProps {
|
|
|
67
69
|
type?: 'info' | 'success' | 'error' | 'warn' | 'warning' | 'confirm';
|
|
68
70
|
centered?: boolean;
|
|
69
71
|
maskClosable?: boolean;
|
|
72
|
+
/** Dialog semantic role. Use alertdialog only for explicitly urgent confirmation flows. */
|
|
73
|
+
role?: 'dialog' | 'alertdialog';
|
|
70
74
|
}
|
|
71
75
|
declare function OriginModal(props: OriginModalProps): import("react/jsx-runtime").JSX.Element;
|
|
72
76
|
type ModalFunc = (props: ModalFuncProps) => {
|
package/dist/Modal/index.js
CHANGED
|
@@ -7,9 +7,10 @@ import { FLOATING_LAYER_BASE_Z_INDEX, FloatingLayerProvider } from "../_utils/fl
|
|
|
7
7
|
import { ModalLayerProvider, useModalLayer } from "../_utils/overlayCoordinator.js";
|
|
8
8
|
import Button_default from "../Button/index.js";
|
|
9
9
|
import { LocaleContext, getTranslator } from "../locale/default.js";
|
|
10
|
-
|
|
10
|
+
/* empty css */
|
|
11
11
|
import ScrollArea_default from "../ScrollArea/index.js";
|
|
12
|
-
import {
|
|
12
|
+
import { focusInitialDialogTarget, markDialogEscapeEvent, restoreDialogFocus, useDialogAccessibility } from "../_utils/dialogAccessibility.js";
|
|
13
|
+
import React, { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
13
14
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
14
15
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
15
16
|
import { hideOthers } from "aria-hidden";
|
|
@@ -17,10 +18,6 @@ import { createRoot } from "react-dom/client";
|
|
|
17
18
|
//#region src/Modal/index.tsx
|
|
18
19
|
var destroyFns = [];
|
|
19
20
|
var DEFAULT_WIDTH = 552;
|
|
20
|
-
var modalEscapeEvents = /* @__PURE__ */ new WeakSet();
|
|
21
|
-
function shouldCancelTopModal(event) {
|
|
22
|
-
return !event.cancelBubble && (!event.defaultPrevented || modalEscapeEvents.has(event));
|
|
23
|
-
}
|
|
24
21
|
function ModalContentProviders({ layerId, floatingLevel, children }) {
|
|
25
22
|
return /* @__PURE__ */ jsx(ModalLayerProvider, {
|
|
26
23
|
id: layerId,
|
|
@@ -30,7 +27,7 @@ function ModalContentProviders({ layerId, floatingLevel, children }) {
|
|
|
30
27
|
})
|
|
31
28
|
});
|
|
32
29
|
}
|
|
33
|
-
var ModalTitle = ({ icon, title, subTitle }, type) => /* @__PURE__ */ jsxs("div", {
|
|
30
|
+
var ModalTitle = ({ icon, title, subTitle, titleId, descriptionId }, type) => /* @__PURE__ */ jsxs("div", {
|
|
34
31
|
className: "ald-modal-title-container tw-flex tw-items-center tw-gap-4",
|
|
35
32
|
children: [icon && /* @__PURE__ */ jsx("div", {
|
|
36
33
|
className: cn("ald-modal-icon-container tw-grid tw-size-10 tw-shrink-0 tw-place-items-center tw-rounded-[var(--global-grid-250)]", type === "info" && "ald-modal-cion-info-container tw-bg-[var(--background-informative-muted)]", type === "success" && "ald-modal-cion-success-container tw-bg-[var(--background-positive-muted)]", type === "warning" && "ald-modal-cion-warning-container tw-bg-[var(--background-warning-muted)]", type === "warn" && "ald-modal-cion-warning-container tw-bg-[var(--background-warning-muted)]", type === "error" && "ald-modal-cion-error-container tw-bg-[var(--background-negative-muted)]", type === "confirm" && "ald-modal-cion-confirm-container tw-bg-[var(--background-brand-muted)]"),
|
|
@@ -38,9 +35,11 @@ var ModalTitle = ({ icon, title, subTitle }, type) => /* @__PURE__ */ jsxs("div"
|
|
|
38
35
|
}), /* @__PURE__ */ jsxs("div", {
|
|
39
36
|
className: "ald-modal-text-container",
|
|
40
37
|
children: [title && /* @__PURE__ */ jsx("div", {
|
|
38
|
+
id: titleId,
|
|
41
39
|
className: cn("ald-modal-text-title tw-text-lg tw-font-semibold tw-leading-7 tw-text-[var(--content-primary)]", !subTitle && "ald-modal-text-title-only tw-text-xl"),
|
|
42
40
|
children: title
|
|
43
41
|
}), subTitle && /* @__PURE__ */ jsx("div", {
|
|
42
|
+
id: descriptionId,
|
|
44
43
|
className: "ald-modal-text-sub-title tw-mt-1 tw-text-xs tw-leading-4 tw-text-[var(--content-secondary)]",
|
|
45
44
|
children: subTitle
|
|
46
45
|
})]
|
|
@@ -69,12 +68,22 @@ function getIcon(type) {
|
|
|
69
68
|
function OriginModal(props) {
|
|
70
69
|
const { locale } = useContext(LocaleContext);
|
|
71
70
|
const t = getTranslator(locale);
|
|
72
|
-
const { className, "data-testid": dataTestId, "aria-label": ariaLabel, children, okType = "primary", width, closeIcon, subTitle, okButtonProps = {}, cancelButtonProps = {}, okText = t.Modal.sure, cancelText = t.Modal.cancel, icon, title, paddingLess, responsiveBounds, hideHeaderBottomBorder, virtualScrollBar, style, maskClosable = false, fullscreen, open = false, onOk, onCancel, footer, confirmLoading, closable = true, zIndex = 1e3, bodyStyle, keyboard = true, afterOpenChange, wrapClassName, _modalType, onTopChange } = props;
|
|
71
|
+
const { className, "data-testid": dataTestId, "aria-label": ariaLabel, role = "dialog", children, okType = "primary", width, closeIcon, subTitle, okButtonProps = {}, cancelButtonProps = {}, okText = t.Modal.sure, cancelText = t.Modal.cancel, icon, title, paddingLess, responsiveBounds, hideHeaderBottomBorder, virtualScrollBar, style, maskClosable = false, fullscreen, open = false, onOk, onCancel, footer, confirmLoading, closable = true, zIndex = 1e3, bodyStyle, keyboard = true, afterOpenChange, wrapClassName, _modalType, onTopChange } = props;
|
|
73
72
|
const prevOpenRef = useRef(open);
|
|
74
73
|
const contentRef = useRef(null);
|
|
75
74
|
const modalRef = useRef(null);
|
|
75
|
+
const generatedId = React.useId();
|
|
76
|
+
const titleId = `${generatedId}-title`;
|
|
77
|
+
const descriptionId = `${generatedId}-description`;
|
|
76
78
|
const { id: modalLayerId, maskZIndex, contentZIndex, isTop } = useModalLayer(open, zIndex);
|
|
77
79
|
const nextFloatingLevel = (maskZIndex - FLOATING_LAYER_BASE_Z_INDEX) / 10 + 1;
|
|
80
|
+
useDialogAccessibility({
|
|
81
|
+
open,
|
|
82
|
+
isTop,
|
|
83
|
+
keyboard,
|
|
84
|
+
containerRef: modalRef,
|
|
85
|
+
onEscape: () => onCancel?.({})
|
|
86
|
+
});
|
|
78
87
|
useLayoutEffect(() => {
|
|
79
88
|
onTopChange?.(isTop);
|
|
80
89
|
}, [isTop, onTopChange]);
|
|
@@ -88,44 +97,6 @@ function OriginModal(props) {
|
|
|
88
97
|
if (!open || !isTop || !contentRef.current) return;
|
|
89
98
|
return hideOthers(contentRef.current);
|
|
90
99
|
}, [isTop, open]);
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
if (!open || !isTop || !contentRef.current) return;
|
|
93
|
-
const container = contentRef.current;
|
|
94
|
-
const handleKeyDown = (e) => {
|
|
95
|
-
if (e.key !== "Tab") return;
|
|
96
|
-
const focusable = container.querySelectorAll("a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"]):not([disabled])");
|
|
97
|
-
if (focusable.length === 0) return;
|
|
98
|
-
const first = focusable[0];
|
|
99
|
-
const last = focusable[focusable.length - 1];
|
|
100
|
-
if (e.shiftKey) {
|
|
101
|
-
if (document.activeElement === first || !container.contains(document.activeElement)) {
|
|
102
|
-
e.preventDefault();
|
|
103
|
-
last.focus();
|
|
104
|
-
}
|
|
105
|
-
} else if (document.activeElement === last || !container.contains(document.activeElement)) {
|
|
106
|
-
e.preventDefault();
|
|
107
|
-
first.focus();
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
111
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
112
|
-
}, [isTop, open]);
|
|
113
|
-
useEffect(() => {
|
|
114
|
-
if (!open || !isTop || !keyboard) return;
|
|
115
|
-
const handleEscape = (event) => {
|
|
116
|
-
if (event.key !== "Escape") return;
|
|
117
|
-
queueMicrotask(() => {
|
|
118
|
-
if (shouldCancelTopModal(event)) onCancel?.({});
|
|
119
|
-
});
|
|
120
|
-
};
|
|
121
|
-
window.addEventListener("keydown", handleEscape, true);
|
|
122
|
-
return () => window.removeEventListener("keydown", handleEscape, true);
|
|
123
|
-
}, [
|
|
124
|
-
isTop,
|
|
125
|
-
keyboard,
|
|
126
|
-
onCancel,
|
|
127
|
-
open
|
|
128
|
-
]);
|
|
129
100
|
const responsiveBoundsStyle = useMemo(() => {
|
|
130
101
|
if (!responsiveBounds) return {};
|
|
131
102
|
return {
|
|
@@ -141,14 +112,16 @@ function OriginModal(props) {
|
|
|
141
112
|
loading: confirmLoading,
|
|
142
113
|
...okButtonProps
|
|
143
114
|
};
|
|
115
|
+
const headerBorderClassName = hideHeaderBottomBorder ? "!tw-border-0" : "tw-border-b tw-border-solid tw-border-[var(--border-default)] !tw-border-x-0 !tw-border-t-0";
|
|
144
116
|
const renderFooter = () => {
|
|
145
117
|
if (footer === null) return null;
|
|
118
|
+
const footerBorderClassName = "tw-border-t tw-border-solid tw-border-[var(--border-default)] !tw-border-x-0 !tw-border-b-0";
|
|
146
119
|
if (footer) return /* @__PURE__ */ jsx("div", {
|
|
147
|
-
className: "ald-modal-footer ant-modal-footer tw-flex tw-items-center tw-justify-end tw-gap-2 tw-
|
|
120
|
+
className: cn("ald-modal-footer ant-modal-footer tw-flex tw-items-center tw-justify-end tw-gap-2 tw-bg-[var(--background-default)] tw-px-6 tw-py-3 tw-text-right", footerBorderClassName),
|
|
148
121
|
children: footer
|
|
149
122
|
});
|
|
150
123
|
return /* @__PURE__ */ jsxs("div", {
|
|
151
|
-
className: "ald-modal-footer ant-modal-footer tw-flex tw-justify-end tw-gap-2 tw-
|
|
124
|
+
className: cn("ald-modal-footer ant-modal-footer tw-flex tw-justify-end tw-gap-2 tw-px-6 tw-py-4", footerBorderClassName),
|
|
152
125
|
children: [/* @__PURE__ */ jsx(Button_default, {
|
|
153
126
|
type: "secondary",
|
|
154
127
|
size: "middle",
|
|
@@ -182,9 +155,13 @@ function OriginModal(props) {
|
|
|
182
155
|
children: /* @__PURE__ */ jsx(DialogPrimitive.Content, {
|
|
183
156
|
ref: modalRef,
|
|
184
157
|
tabIndex: -1,
|
|
158
|
+
role,
|
|
185
159
|
"data-testid": dataTestId,
|
|
160
|
+
"aria-modal": isTop || void 0,
|
|
161
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
162
|
+
"aria-describedby": subTitle ? descriptionId : void 0,
|
|
186
163
|
"aria-label": ariaLabel,
|
|
187
|
-
className: cn("ald-modal ant-modal tw-pointer-events-auto tw-box-border tw-flex tw-flex-col tw-overflow-hidden tw-bg-[var(--background-default)] tw-shadow-
|
|
164
|
+
className: cn("ald-modal ant-modal tw-pointer-events-auto tw-box-border tw-flex tw-flex-col tw-overflow-hidden tw-border-0 tw-bg-[var(--background-default)] tw-shadow-none tw-outline-none", fullscreen ? "ald-modal-fullscreen tw-fixed tw-inset-0 tw-size-full tw-rounded-none" : "tw-rounded-r-75", paddingLess && "ald-modal-padding-less", virtualScrollBar && "ald-modal-virtual-scroll-bar", hideHeaderBottomBorder && "ald-modal-hide-header-bottom-border", responsiveBounds && "ald-modal-responsive-bounds", className),
|
|
188
165
|
style: {
|
|
189
166
|
...fullscreen ? {} : {
|
|
190
167
|
width: responsiveBounds ? responsiveBoundsStyle.width : width || DEFAULT_WIDTH,
|
|
@@ -196,14 +173,11 @@ function OriginModal(props) {
|
|
|
196
173
|
event.preventDefault();
|
|
197
174
|
requestAnimationFrame(() => {
|
|
198
175
|
const modal = modalRef.current;
|
|
199
|
-
|
|
200
|
-
const activeOverlay = activeElement instanceof HTMLElement ? activeElement.closest("[role=\"dialog\"], [role=\"menu\"], [role=\"listbox\"]") : null;
|
|
201
|
-
if (!modal || activeOverlay && !activeOverlay.classList.contains("ald-modal") && activeOverlay !== modal && !modal.contains(activeOverlay)) return;
|
|
202
|
-
modal.focus({ preventScroll: true });
|
|
176
|
+
if (modal) focusInitialDialogTarget(modal);
|
|
203
177
|
});
|
|
204
178
|
},
|
|
205
179
|
onEscapeKeyDown: (event) => {
|
|
206
|
-
if (!event.defaultPrevented)
|
|
180
|
+
if (!event.defaultPrevented) markDialogEscapeEvent(event);
|
|
207
181
|
event.preventDefault();
|
|
208
182
|
},
|
|
209
183
|
onPointerDownOutside: (e) => {
|
|
@@ -214,13 +188,13 @@ function OriginModal(props) {
|
|
|
214
188
|
if (!maskClosable) e.preventDefault();
|
|
215
189
|
},
|
|
216
190
|
children: /* @__PURE__ */ jsx("div", {
|
|
217
|
-
className: "ant-modal-content tw-flex tw-h-full tw-flex-col",
|
|
191
|
+
className: "ant-modal-content tw-flex tw-h-full tw-flex-col !tw-rounded-none !tw-border-0 !tw-bg-transparent !tw-p-0 !tw-shadow-none",
|
|
218
192
|
children: /* @__PURE__ */ jsxs(ModalContentProviders, {
|
|
219
193
|
layerId: modalLayerId,
|
|
220
194
|
floatingLevel: nextFloatingLevel,
|
|
221
195
|
children: [
|
|
222
196
|
!fullscreen && /* @__PURE__ */ jsxs("div", {
|
|
223
|
-
className: cn("ald-modal-header ant-modal-header tw-flex tw-items-start tw-justify-between tw-bg-[var(--background-default)] tw-px-6 tw-py-4",
|
|
197
|
+
className: cn("ald-modal-header ant-modal-header tw-flex tw-items-start tw-justify-between tw-bg-[var(--background-default)] tw-px-6 tw-py-4", headerBorderClassName),
|
|
224
198
|
children: [/* @__PURE__ */ jsx(DialogPrimitive.Title, {
|
|
225
199
|
asChild: true,
|
|
226
200
|
children: /* @__PURE__ */ jsx("div", {
|
|
@@ -228,24 +202,39 @@ function OriginModal(props) {
|
|
|
228
202
|
children: ModalTitle({
|
|
229
203
|
icon,
|
|
230
204
|
title,
|
|
231
|
-
subTitle
|
|
205
|
+
subTitle,
|
|
206
|
+
titleId,
|
|
207
|
+
descriptionId
|
|
232
208
|
}, _modalType)
|
|
233
209
|
})
|
|
234
210
|
}), closable && /* @__PURE__ */ jsx(DialogPrimitive.Close, {
|
|
235
211
|
asChild: true,
|
|
236
|
-
children: /* @__PURE__ */ jsx("
|
|
237
|
-
|
|
212
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
213
|
+
type: "button",
|
|
214
|
+
className: "ant-modal-close ald-icon-button ald-icon-button-middle focus-visible:tw-outline focus-visible:tw-outline-2 focus-visible:tw-outline-offset-2 focus-visible:tw-outline-[var(--focus-ring)] forced-colors:focus-visible:tw-outline-[Highlight]",
|
|
215
|
+
"aria-label": "Close",
|
|
216
|
+
"data-overlay-close": "true",
|
|
238
217
|
onClick: onCancel,
|
|
239
|
-
children:
|
|
240
|
-
|
|
241
|
-
size:
|
|
218
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
219
|
+
className: "ald-icon-button-wrap",
|
|
220
|
+
children: closeIcon || /* @__PURE__ */ jsx(Memo$2, { size: 20 })
|
|
242
221
|
})
|
|
243
222
|
})
|
|
244
223
|
})]
|
|
245
224
|
}),
|
|
246
225
|
fullscreen && /* @__PURE__ */ jsx(DialogPrimitive.Title, {
|
|
226
|
+
asChild: true,
|
|
227
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
228
|
+
className: "tw-sr-only",
|
|
229
|
+
children: title && /* @__PURE__ */ jsx("span", {
|
|
230
|
+
id: titleId,
|
|
231
|
+
children: title
|
|
232
|
+
})
|
|
233
|
+
})
|
|
234
|
+
}),
|
|
235
|
+
subTitle && /* @__PURE__ */ jsx(DialogPrimitive.Description, {
|
|
247
236
|
className: "tw-sr-only",
|
|
248
|
-
children:
|
|
237
|
+
children: subTitle
|
|
249
238
|
}),
|
|
250
239
|
/* @__PURE__ */ jsx("div", {
|
|
251
240
|
className: cn("ald-modal-body ant-modal-body tw-flex-1 tw-text-sm tw-leading-5", fullscreen ? "tw-h-full tw-overflow-auto tw-p-0" : "tw-min-h-[130px]", !fullscreen && (virtualScrollBar ? "tw-overflow-hidden tw-p-0" : "tw-overflow-auto"), !fullscreen && !responsiveBounds && !virtualScrollBar && "tw-max-h-[68vh]", !fullscreen && !paddingLess && !virtualScrollBar && "tw-p-6"),
|
|
@@ -280,9 +269,7 @@ function createStaticModal(type, props) {
|
|
|
280
269
|
container.remove();
|
|
281
270
|
const idx = destroyFns.indexOf(destroy);
|
|
282
271
|
if (idx >= 0) destroyFns.splice(idx, 1);
|
|
283
|
-
|
|
284
|
-
if (shouldRestoreFocus && focusTarget?.isConnected) focusTarget.focus();
|
|
285
|
-
});
|
|
272
|
+
if (shouldRestoreFocus) restoreDialogFocus(focusTarget);
|
|
286
273
|
};
|
|
287
274
|
const update = (newProps) => {
|
|
288
275
|
currentProps = {
|
|
@@ -317,6 +304,7 @@ function createStaticModal(type, props) {
|
|
|
317
304
|
className: cn("ald-modal", p.className),
|
|
318
305
|
closable: p.closable,
|
|
319
306
|
maskClosable: p.maskClosable,
|
|
307
|
+
role: p.role,
|
|
320
308
|
_modalType: type,
|
|
321
309
|
onTopChange: (nextIsTop) => {
|
|
322
310
|
isTop = nextIsTop;
|
|
@@ -408,6 +396,7 @@ function useModal() {
|
|
|
408
396
|
className: cn("ald-modal", m.props.className),
|
|
409
397
|
closable: m.props.closable,
|
|
410
398
|
maskClosable: m.props.maskClosable,
|
|
399
|
+
role: m.props.role,
|
|
411
400
|
_modalType: m.type,
|
|
412
401
|
footer: isConfirmType ? void 0 : /* @__PURE__ */ jsx(Button_default, {
|
|
413
402
|
type: "primary",
|