@aloudata/aloudata-design 3.0.13 → 3.0.14
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/App/index.js +6 -1
- package/dist/App/index.js.map +1 -1
- package/dist/Checkbox/index.js +1 -1
- package/dist/Checkbox/index.js.map +1 -1
- package/dist/Dropdown/index.js +11 -2
- package/dist/Dropdown/index.js.map +1 -1
- package/dist/Pagination/PageSizeChanger.js +3 -1
- package/dist/Pagination/PageSizeChanger.js.map +1 -1
- package/dist/Skeleton/index.js +18 -3
- package/dist/Skeleton/index.js.map +1 -1
- package/dist/Tabs/index.js +4 -4
- package/dist/Tabs/index.js.map +1 -1
- package/package.json +1 -1
package/dist/App/index.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { cn } from "../lib/utils.js";
|
|
2
2
|
import "react";
|
|
3
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { createPortal } from "react-dom";
|
|
4
5
|
import { ToastContainer } from "react-toastify";
|
|
5
6
|
//#region src/App/index.tsx
|
|
7
|
+
var BodyPortal = ({ children }) => {
|
|
8
|
+
if (typeof document === "undefined") return null;
|
|
9
|
+
return createPortal(children, document.body);
|
|
10
|
+
};
|
|
6
11
|
var AldApp = ({ children, className, ...restProps }) => {
|
|
7
12
|
return /* @__PURE__ */ jsxs("div", {
|
|
8
13
|
className: cn("ald-app", className),
|
|
@@ -12,7 +17,7 @@ var AldApp = ({ children, className, ...restProps }) => {
|
|
|
12
17
|
containerId: "message-container",
|
|
13
18
|
limit: 1
|
|
14
19
|
}),
|
|
15
|
-
/* @__PURE__ */ jsx(ToastContainer, { containerId: "notification-container" }),
|
|
20
|
+
/* @__PURE__ */ jsx(BodyPortal, { children: /* @__PURE__ */ jsx(ToastContainer, { containerId: "notification-container" }) }),
|
|
16
21
|
children
|
|
17
22
|
]
|
|
18
23
|
});
|
package/dist/App/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/App/index.tsx"],"sourcesContent":["import React from 'react';\nimport { ToastContainer } from 'react-toastify';\nimport { cn } from '../lib/utils';\n\ninterface AppProps {\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst AldApp: React.FC<AppProps> = ({ children, className, ...restProps }) => {\n return (\n <div className={cn('ald-app', className)} {...restProps}>\n <ToastContainer containerId={'message-container'} limit={1} />\n <ToastContainer containerId={'notification-container'} />\n {children}\n </div>\n );\n};\n\nexport default AldApp;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/App/index.tsx"],"sourcesContent":["import React from 'react';\nimport { createPortal } from 'react-dom';\nimport { ToastContainer } from 'react-toastify';\nimport { cn } from '../lib/utils';\n\ninterface AppProps {\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst BodyPortal: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n if (typeof document === 'undefined') return null;\n return createPortal(children, document.body);\n};\n\nconst AldApp: React.FC<AppProps> = ({ children, className, ...restProps }) => {\n return (\n <div className={cn('ald-app', className)} {...restProps}>\n <ToastContainer containerId={'message-container'} limit={1} />\n <BodyPortal>\n <ToastContainer containerId={'notification-container'} />\n </BodyPortal>\n {children}\n </div>\n );\n};\n\nexport default AldApp;\n"],"mappings":";;;;;;AAWA,IAAM,cAAuD,EAAE,eAAe;AAC5E,KAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,QAAO,aAAa,UAAU,SAAS,KAAK;;AAG9C,IAAM,UAA8B,EAAE,UAAU,WAAW,GAAG,gBAAgB;AAC5E,QACE,qBAAC,OAAD;EAAK,WAAW,GAAG,WAAW,UAAU;EAAE,GAAI;YAA9C;GACE,oBAAC,gBAAD;IAAgB,aAAa;IAAqB,OAAO;IAAK,CAAA;GAC9D,oBAAC,YAAD,EAAA,UACE,oBAAC,gBAAD,EAAgB,aAAa,0BAA4B,CAAA,EAC9C,CAAA;GACZ;GACG"}
|
package/dist/Checkbox/index.js
CHANGED
|
@@ -41,7 +41,7 @@ function Checkbox(props) {
|
|
|
41
41
|
className: cn("ald-checkbox-wrapper ald-checkbox tw-inline-flex tw-cursor-pointer tw-items-center tw-gap-2 tw-leading-5", mergedDisabled && "tw-cursor-default", size === "small" && "ald-checkbox-small", !mergedDisabled && "[&:hover_.ald-checkbox-inner]:tw-border-2 [&:hover_.ald-checkbox-inner]:tw-border-[var(--interaction-border-hover)]", !mergedDisabled && checked && "[&:hover_.ald-checkbox-inner]:tw-border-transparent [&:hover_.ald-checkbox-inner]:tw-bg-[var(--interaction-default-hover)]", className),
|
|
42
42
|
style,
|
|
43
43
|
children: [/* @__PURE__ */ jsxs("span", {
|
|
44
|
-
className: cn("ald-checkbox-inner tw-relative tw-box-border tw-flex tw-size-4 tw-min-h-4 tw-min-w-4 tw-items-center tw-justify-center tw-rounded-r-50 tw-border-2 tw-border-solid tw-transition-all tw-duration-200", checked && "ald-checkbox-checked tw-border-transparent tw-bg-[var(--interaction-default-normal)]", mergedDisabled && "tw-opacity-50", !checked && !indeterminate && !alert && "tw-border-[var(--interaction-border-neutral-normal)] tw-bg-[var(--interaction-background-form-field)]", !checked && !indeterminate && alert && "tw-border-[var(--interaction-border-alert)] tw-bg-[var(--interaction-background-form-field)]", indeterminate && !checked && "ald-checkbox-indeterminate tw-border-transparent tw-bg-[var(--interaction-default-normal)]"),
|
|
44
|
+
className: cn("ald-checkbox-inner tw-relative tw-box-border tw-flex tw-size-4 tw-min-h-4 tw-min-w-4 tw-items-center tw-justify-center tw-rounded-r-50 tw-border-2 tw-border-solid tw-transition-all tw-duration-200", checked && "ald-checkbox-checked tw-border-transparent tw-bg-[var(--interaction-default-normal)]", mergedDisabled && !checked && !indeterminate && "tw-opacity-50", !checked && !indeterminate && !alert && "tw-border-[var(--interaction-border-neutral-normal)] tw-bg-[var(--interaction-background-form-field)]", !checked && !indeterminate && alert && "tw-border-[var(--interaction-border-alert)] tw-bg-[var(--interaction-background-form-field)]", indeterminate && !checked && "ald-checkbox-indeterminate tw-border-transparent tw-bg-[var(--interaction-default-normal)]"),
|
|
45
45
|
children: [/* @__PURE__ */ jsx("input", {
|
|
46
46
|
ref: inputRef,
|
|
47
47
|
type: "checkbox",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/Checkbox/index.tsx"],"sourcesContent":["import React, { useContext, useEffect, useRef, useState } from 'react';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport { cn } from '../lib/utils';\nimport {\n CheckboxChangeEvent,\n CheckboxValueType,\n ICheckboxGroupProps,\n ICheckboxProps,\n} from './type';\n\nexport type { CheckboxChangeEvent, CheckboxValueType };\nexport type { CheckboxOptionType } from './type';\nexport type { ICheckboxProps, ICheckboxGroupProps };\n\nfunction Checkbox(props: ICheckboxProps) {\n const {\n className,\n disabled: customDisabled,\n alert,\n bold,\n size,\n checked: controlledChecked,\n defaultChecked,\n indeterminate,\n onChange,\n onClick,\n autoFocus,\n children,\n value,\n name,\n style,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n } = props;\n\n const disabled = useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n\n const isControlled = 'checked' in props;\n const [innerChecked, setInnerChecked] = useState(defaultChecked ?? false);\n const checked = isControlled ? controlledChecked : innerChecked;\n\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.indeterminate = !!indeterminate;\n }\n }, [indeterminate]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (mergedDisabled) return;\n const newChecked = e.target.checked;\n if (!isControlled) {\n setInnerChecked(newChecked);\n }\n onChange?.({\n target: { checked: newChecked, value },\n nativeEvent: e.nativeEvent,\n });\n };\n\n const handleLabelClick = (e: React.MouseEvent) => {\n if (mergedDisabled) return;\n if (onClick) {\n // Table row selection uses onClick — prevent label from also toggling input\n e.preventDefault();\n e.stopPropagation();\n onClick(e);\n }\n };\n\n return (\n <label\n onClick={handleLabelClick}\n data-testid={dataTestid}\n aria-label={ariaLabel}\n className={cn(\n 'ald-checkbox-wrapper ald-checkbox tw-inline-flex tw-cursor-pointer tw-items-center tw-gap-2 tw-leading-5',\n mergedDisabled && 'tw-cursor-default',\n size === 'small' && 'ald-checkbox-small',\n !mergedDisabled &&\n '[&:hover_.ald-checkbox-inner]:tw-border-2 [&:hover_.ald-checkbox-inner]:tw-border-[var(--interaction-border-hover)]',\n !mergedDisabled &&\n checked &&\n '[&:hover_.ald-checkbox-inner]:tw-border-transparent [&:hover_.ald-checkbox-inner]:tw-bg-[var(--interaction-default-hover)]',\n className,\n )}\n style={style}\n >\n <span\n className={cn(\n 'ald-checkbox-inner tw-relative tw-box-border tw-flex tw-size-4 tw-min-h-4 tw-min-w-4 tw-items-center tw-justify-center tw-rounded-r-50 tw-border-2 tw-border-solid tw-transition-all tw-duration-200',\n checked &&\n 'ald-checkbox-checked tw-border-transparent tw-bg-[var(--interaction-default-normal)]',\n mergedDisabled && 'tw-opacity-50',\n !checked &&\n !indeterminate &&\n !alert &&\n 'tw-border-[var(--interaction-border-neutral-normal)] tw-bg-[var(--interaction-background-form-field)]',\n !checked &&\n !indeterminate &&\n alert &&\n 'tw-border-[var(--interaction-border-alert)] tw-bg-[var(--interaction-background-form-field)]',\n indeterminate &&\n !checked &&\n 'ald-checkbox-indeterminate tw-border-transparent tw-bg-[var(--interaction-default-normal)]',\n )}\n >\n <input\n ref={inputRef}\n type=\"checkbox\"\n className=\"tw-absolute tw-inset-0 tw-m-0 tw-cursor-pointer tw-opacity-0 disabled:tw-cursor-default\"\n checked={!!checked}\n disabled={mergedDisabled}\n onChange={handleChange}\n autoFocus={autoFocus}\n name={name}\n value={value as string}\n />\n {(checked || (indeterminate && !checked)) && (\n <span\n className=\"tw-absolute tw-inset-0 tw-bg-center tw-bg-no-repeat\"\n style={{\n backgroundImage:\n indeterminate && !checked\n ? 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMiIgdmlld0JveD0iMCAwIDEwIDIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGlkPSJWZWN0b3IgMSAoU3Ryb2tlKSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjc1IDFDMC43NSAwLjU4NTc4NiAxLjA4NTc5IDAuMjUgMS41IDAuMjVIOC41QzguOTE0MjEgMC4yNSA5LjI1IDAuNTg1Nzg2IDkuMjUgMUM5LjI1IDEuNDE0MjEgOC45MTQyMSAxLjc1IDguNSAxLjc1SDEuNUMxLjA4NTc5IDEuNzUgMC43NSAxLjQxNDIxIDAuNzUgMVoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=\")'\n : 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDEwIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGlkPSJJY29uIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTkuNTMwMzMgMC45Njk2N0M5LjgyMzIyIDEuMjYyNTYgOS44MjMyMiAxLjczNzQ0IDkuNTMwMzMgMi4wMzAzM0w0LjUzMDMzIDcuMDMwMzNDNC4yMzc0NCA3LjMyMzIyIDMuNzYyNTYgNy4zMjMyMiAzLjQ2OTY3IDcuMDMwMzNMMC45Njk2NyA0LjUzMDMzQzAuNjc2Nzc3IDQuMjM3NDQgMC42NzY3NzcgMy43NjI1NiAwLjk2OTY3IDMuNDY5NjdDMS4yNjI1NiAzLjE3Njc4IDEuNzM3NDQgMy4xNzY3OCAyLjAzMDMzIDMuNDY5NjdMNCA1LjQzOTM0TDguNDY5NjcgMC45Njk2N0M4Ljc2MjU2IDAuNjc2Nzc3IDkuMjM3NDQgMC42NzY3NzcgOS41MzAzMyAwLjk2OTY3WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==\")',\n backgroundSize:\n indeterminate && !checked ? '10px 2px' : '10px 8px',\n }}\n />\n )}\n </span>\n {children && (\n <span\n className={cn(\n 'ald-checkbox-label tw-inline-flex tw-select-none tw-items-center tw-gap-1 tw-text-[var(--alias-colors-text-default)] [&_svg]:tw-inline-block [&_svg]:tw-shrink-0',\n size === 'small' ? 'tw-text-xs' : 'tw-text-sm',\n bold && 'tw-font-medium',\n mergedDisabled && 'tw-cursor-default',\n )}\n >\n {children}\n </span>\n )}\n </label>\n );\n}\n\nfunction CheckboxGroup(props: ICheckboxGroupProps) {\n const {\n className,\n disabled: customDisabled,\n size,\n options,\n value: controlledValue,\n defaultValue,\n onChange,\n direction,\n name,\n children,\n style,\n } = props;\n\n const disabled = useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n\n const isControlled = 'value' in props;\n const [innerValue, setInnerValue] = useState<CheckboxValueType[]>(\n defaultValue ?? [],\n );\n const value = isControlled ? controlledValue ?? [] : innerValue;\n\n const handleGroupChange = (\n itemValue: CheckboxValueType,\n itemChecked: boolean,\n ) => {\n const newValue = itemChecked\n ? [...value, itemValue]\n : value.filter((v) => v !== itemValue);\n if (!isControlled) {\n setInnerValue(newValue);\n }\n onChange?.(newValue);\n };\n\n const renderOptions = () => {\n if (!options) return children;\n return options.map((opt) => {\n const optObj =\n typeof opt === 'object' ? opt : { label: String(opt), value: opt };\n return (\n <Checkbox\n key={String(optObj.value)}\n value={optObj.value}\n disabled={mergedDisabled || optObj.disabled}\n checked={value.includes(optObj.value)}\n size={size}\n name={name}\n onChange={(e) => handleGroupChange(optObj.value, e.target.checked)}\n >\n {optObj.label}\n </Checkbox>\n );\n });\n };\n\n return (\n <div\n className={cn(\n 'ald-checkbox-group tw-flex tw-flex-wrap tw-gap-3',\n direction === 'vertical' && 'ald-checkbox-group-vertical tw-flex-col',\n size === 'small' && 'ald-checkbox-group-small',\n className,\n )}\n style={style}\n >\n {renderOptions()}\n </div>\n );\n}\n\nCheckbox.Group = CheckboxGroup;\n\nexport default Checkbox;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/Checkbox/index.tsx"],"sourcesContent":["import React, { useContext, useEffect, useRef, useState } from 'react';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport { cn } from '../lib/utils';\nimport {\n CheckboxChangeEvent,\n CheckboxValueType,\n ICheckboxGroupProps,\n ICheckboxProps,\n} from './type';\n\nexport type { CheckboxChangeEvent, CheckboxValueType };\nexport type { CheckboxOptionType } from './type';\nexport type { ICheckboxProps, ICheckboxGroupProps };\n\nfunction Checkbox(props: ICheckboxProps) {\n const {\n className,\n disabled: customDisabled,\n alert,\n bold,\n size,\n checked: controlledChecked,\n defaultChecked,\n indeterminate,\n onChange,\n onClick,\n autoFocus,\n children,\n value,\n name,\n style,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n } = props;\n\n const disabled = useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n\n const isControlled = 'checked' in props;\n const [innerChecked, setInnerChecked] = useState(defaultChecked ?? false);\n const checked = isControlled ? controlledChecked : innerChecked;\n\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.indeterminate = !!indeterminate;\n }\n }, [indeterminate]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (mergedDisabled) return;\n const newChecked = e.target.checked;\n if (!isControlled) {\n setInnerChecked(newChecked);\n }\n onChange?.({\n target: { checked: newChecked, value },\n nativeEvent: e.nativeEvent,\n });\n };\n\n const handleLabelClick = (e: React.MouseEvent) => {\n if (mergedDisabled) return;\n if (onClick) {\n // Table row selection uses onClick — prevent label from also toggling input\n e.preventDefault();\n e.stopPropagation();\n onClick(e);\n }\n };\n\n return (\n <label\n onClick={handleLabelClick}\n data-testid={dataTestid}\n aria-label={ariaLabel}\n className={cn(\n 'ald-checkbox-wrapper ald-checkbox tw-inline-flex tw-cursor-pointer tw-items-center tw-gap-2 tw-leading-5',\n mergedDisabled && 'tw-cursor-default',\n size === 'small' && 'ald-checkbox-small',\n !mergedDisabled &&\n '[&:hover_.ald-checkbox-inner]:tw-border-2 [&:hover_.ald-checkbox-inner]:tw-border-[var(--interaction-border-hover)]',\n !mergedDisabled &&\n checked &&\n '[&:hover_.ald-checkbox-inner]:tw-border-transparent [&:hover_.ald-checkbox-inner]:tw-bg-[var(--interaction-default-hover)]',\n className,\n )}\n style={style}\n >\n <span\n className={cn(\n 'ald-checkbox-inner tw-relative tw-box-border tw-flex tw-size-4 tw-min-h-4 tw-min-w-4 tw-items-center tw-justify-center tw-rounded-r-50 tw-border-2 tw-border-solid tw-transition-all tw-duration-200',\n checked &&\n 'ald-checkbox-checked tw-border-transparent tw-bg-[var(--interaction-default-normal)]',\n mergedDisabled && !checked && !indeterminate && 'tw-opacity-50',\n !checked &&\n !indeterminate &&\n !alert &&\n 'tw-border-[var(--interaction-border-neutral-normal)] tw-bg-[var(--interaction-background-form-field)]',\n !checked &&\n !indeterminate &&\n alert &&\n 'tw-border-[var(--interaction-border-alert)] tw-bg-[var(--interaction-background-form-field)]',\n indeterminate &&\n !checked &&\n 'ald-checkbox-indeterminate tw-border-transparent tw-bg-[var(--interaction-default-normal)]',\n )}\n >\n <input\n ref={inputRef}\n type=\"checkbox\"\n className=\"tw-absolute tw-inset-0 tw-m-0 tw-cursor-pointer tw-opacity-0 disabled:tw-cursor-default\"\n checked={!!checked}\n disabled={mergedDisabled}\n onChange={handleChange}\n autoFocus={autoFocus}\n name={name}\n value={value as string}\n />\n {(checked || (indeterminate && !checked)) && (\n <span\n className=\"tw-absolute tw-inset-0 tw-bg-center tw-bg-no-repeat\"\n style={{\n backgroundImage:\n indeterminate && !checked\n ? 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMiIgdmlld0JveD0iMCAwIDEwIDIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGlkPSJWZWN0b3IgMSAoU3Ryb2tlKSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjc1IDFDMC43NSAwLjU4NTc4NiAxLjA4NTc5IDAuMjUgMS41IDAuMjVIOC41QzguOTE0MjEgMC4yNSA5LjI1IDAuNTg1Nzg2IDkuMjUgMUM5LjI1IDEuNDE0MjEgOC45MTQyMSAxLjc1IDguNSAxLjc1SDEuNUMxLjA4NTc5IDEuNzUgMC43NSAxLjQxNDIxIDAuNzUgMVoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=\")'\n : 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDEwIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGlkPSJJY29uIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTkuNTMwMzMgMC45Njk2N0M5LjgyMzIyIDEuMjYyNTYgOS44MjMyMiAxLjczNzQ0IDkuNTMwMzMgMi4wMzAzM0w0LjUzMDMzIDcuMDMwMzNDNC4yMzc0NCA3LjMyMzIyIDMuNzYyNTYgNy4zMjMyMiAzLjQ2OTY3IDcuMDMwMzNMMC45Njk2NyA0LjUzMDMzQzAuNjc2Nzc3IDQuMjM3NDQgMC42NzY3NzcgMy43NjI1NiAwLjk2OTY3IDMuNDY5NjdDMS4yNjI1NiAzLjE3Njc4IDEuNzM3NDQgMy4xNzY3OCAyLjAzMDMzIDMuNDY5NjdMNCA1LjQzOTM0TDguNDY5NjcgMC45Njk2N0M4Ljc2MjU2IDAuNjc2Nzc3IDkuMjM3NDQgMC42NzY3NzcgOS41MzAzMyAwLjk2OTY3WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==\")',\n backgroundSize:\n indeterminate && !checked ? '10px 2px' : '10px 8px',\n }}\n />\n )}\n </span>\n {children && (\n <span\n className={cn(\n 'ald-checkbox-label tw-inline-flex tw-select-none tw-items-center tw-gap-1 tw-text-[var(--alias-colors-text-default)] [&_svg]:tw-inline-block [&_svg]:tw-shrink-0',\n size === 'small' ? 'tw-text-xs' : 'tw-text-sm',\n bold && 'tw-font-medium',\n mergedDisabled && 'tw-cursor-default',\n )}\n >\n {children}\n </span>\n )}\n </label>\n );\n}\n\nfunction CheckboxGroup(props: ICheckboxGroupProps) {\n const {\n className,\n disabled: customDisabled,\n size,\n options,\n value: controlledValue,\n defaultValue,\n onChange,\n direction,\n name,\n children,\n style,\n } = props;\n\n const disabled = useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n\n const isControlled = 'value' in props;\n const [innerValue, setInnerValue] = useState<CheckboxValueType[]>(\n defaultValue ?? [],\n );\n const value = isControlled ? controlledValue ?? [] : innerValue;\n\n const handleGroupChange = (\n itemValue: CheckboxValueType,\n itemChecked: boolean,\n ) => {\n const newValue = itemChecked\n ? [...value, itemValue]\n : value.filter((v) => v !== itemValue);\n if (!isControlled) {\n setInnerValue(newValue);\n }\n onChange?.(newValue);\n };\n\n const renderOptions = () => {\n if (!options) return children;\n return options.map((opt) => {\n const optObj =\n typeof opt === 'object' ? opt : { label: String(opt), value: opt };\n return (\n <Checkbox\n key={String(optObj.value)}\n value={optObj.value}\n disabled={mergedDisabled || optObj.disabled}\n checked={value.includes(optObj.value)}\n size={size}\n name={name}\n onChange={(e) => handleGroupChange(optObj.value, e.target.checked)}\n >\n {optObj.label}\n </Checkbox>\n );\n });\n };\n\n return (\n <div\n className={cn(\n 'ald-checkbox-group tw-flex tw-flex-wrap tw-gap-3',\n direction === 'vertical' && 'ald-checkbox-group-vertical tw-flex-col',\n size === 'small' && 'ald-checkbox-group-small',\n className,\n )}\n style={style}\n >\n {renderOptions()}\n </div>\n );\n}\n\nCheckbox.Group = CheckboxGroup;\n\nexport default Checkbox;\n"],"mappings":"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"}
|
package/dist/Dropdown/index.js
CHANGED
|
@@ -4,9 +4,9 @@ import Menu from "../Menu/index.js";
|
|
|
4
4
|
import { useFloatingPopupZIndex } from "../_utils/floatingLayer.js";
|
|
5
5
|
import { cloneElement, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import ReactDOM from "react-dom";
|
|
7
8
|
import { FloatingFocusManager, FloatingNode, FloatingTree, autoUpdate, flip, offset, safePolygon, shift, size, useClick, useDismiss, useFloating, useFloatingNodeId, useFloatingParentNodeId, useHover, useId as useId$1, useInteractions, useRole } from "@floating-ui/react";
|
|
8
9
|
import { useMemoizedFn } from "ahooks";
|
|
9
|
-
import ReactDOM from "react-dom";
|
|
10
10
|
//#region src/Dropdown/index.tsx
|
|
11
11
|
var OVERLAY_EXIT_ANIMATION_MS = 200;
|
|
12
12
|
function resolvePlacementSide(currentPlacement) {
|
|
@@ -225,6 +225,14 @@ function Dropdown(props) {
|
|
|
225
225
|
return /* @__PURE__ */ jsx(Menu, {
|
|
226
226
|
...menu,
|
|
227
227
|
items: menu?.items || [],
|
|
228
|
+
menuStyle: {
|
|
229
|
+
...popupMatchTriggerWidth ? {
|
|
230
|
+
width: "100%",
|
|
231
|
+
minWidth: 0,
|
|
232
|
+
maxWidth: "none"
|
|
233
|
+
} : void 0,
|
|
234
|
+
...menu?.menuStyle
|
|
235
|
+
},
|
|
228
236
|
onBeforeLeafItemClick: markRootClosing,
|
|
229
237
|
rootClosing: isAnimatingOut,
|
|
230
238
|
onClick: onMenuItemClick,
|
|
@@ -235,7 +243,8 @@ function Dropdown(props) {
|
|
|
235
243
|
isAnimatingOut,
|
|
236
244
|
markRootClosing,
|
|
237
245
|
menu,
|
|
238
|
-
onMenuItemClick
|
|
246
|
+
onMenuItemClick,
|
|
247
|
+
popupMatchTriggerWidth
|
|
239
248
|
]);
|
|
240
249
|
const popupElement = useMemo(() => {
|
|
241
250
|
return typeof dropdownRender === "function" ? dropdownRender(menuInstance) : menuInstance;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/Dropdown/index.tsx"],"sourcesContent":["import './dropdown.css';\nimport {\n FloatingFocusManager,\n FloatingFocusManagerProps,\n FloatingNode,\n FloatingTree,\n OffsetOptions,\n UseHoverProps,\n autoUpdate,\n flip,\n offset,\n safePolygon,\n shift,\n size,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useHover,\n useId,\n useInteractions,\n useRole,\n} from '@floating-ui/react';\nimport { useMemoizedFn } from 'ahooks';\nimport { cn } from '../lib/utils';\nimport React, {\n cloneElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport ReactDOM from 'react-dom';\nimport Menu, { MenuInfo, MenuProps } from '../Menu';\nimport { useFloatingPopupZIndex } from '../_utils/floatingLayer';\n\nconst OVERLAY_EXIT_ANIMATION_MS = 200;\n\nfunction resolvePlacementSide(\n currentPlacement: string,\n): 'top' | 'bottom' | 'left' | 'right' {\n const [side] = currentPlacement.split('-');\n if (\n side === 'top' ||\n side === 'bottom' ||\n side === 'left' ||\n side === 'right'\n ) {\n return side;\n }\n if (currentPlacement.startsWith('top')) {\n return 'top';\n }\n if (currentPlacement.startsWith('bottom')) {\n return 'bottom';\n }\n if (currentPlacement.startsWith('left')) {\n return 'left';\n }\n if (currentPlacement.startsWith('right')) {\n return 'right';\n }\n return 'bottom';\n}\n\nfunction parsePopupMatchWidth(value: unknown): number | undefined {\n if (typeof value === 'number') {\n return value;\n }\n\n if (typeof value === 'string' && value.trim() !== '') {\n const parsedValue = Number(value);\n return Number.isNaN(parsedValue) ? undefined : parsedValue;\n }\n\n return undefined;\n}\n\nexport type ActionType = 'hover' | 'click';\nexport type PlacementType =\n | 'top'\n | 'bottom'\n | 'left'\n | 'right'\n | 'top-start'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-end'\n | 'left-start'\n | 'left-end'\n | 'right-start'\n | 'right-end'\n // Legacy antd-style placement names\n | 'topLeft'\n | 'topRight'\n | 'bottomLeft'\n | 'bottomRight';\nexport interface IDropdownProps {\n children: React.ReactNode;\n /**\n * @description 菜单弹出位置的偏移量\n */\n offset?: OffsetOptions;\n /**\n * @description 关闭后是否销毁 Dropdown\n * @default false\n */\n destroyPopupOnHide?: boolean;\n /**\n * @description 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位\n * @default () => document.body\n */\n getPopupContainer?: () => HTMLElement;\n /**\n * @description 菜单\n * @type Menu | () => Menu\n * @default -\n */\n menu?: MenuProps;\n // /**\n // * @description 菜单\n // * @type Menu | () => Menu\n // * @default -\n // */\n // menu?: ReactElement | (() => ReactElement);\n /**\n * @description 下拉根元素的类名称\n * @default -\n */\n overlayClassName?: string;\n /**\n * @description 菜单弹出位置\n * @default bottomLeft\n */\n placement?: PlacementType;\n /**\n * @description 触发下拉的行为\n * @type ActionType, 其中 ActionType 为 'hover' | 'click' | 'contextMenu';\n * @default click\n */\n trigger?: ActionType | ActionType[];\n /**\n * @description 菜单是否显示\n * @default -\n */\n open?: boolean;\n /**\n * @description 菜单显示状态改变时调用,参数为 open,点击菜单按钮导致的消失不会触发\n * @default -\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * @description 下拉框外层 overlay 的内联样式(与定位 transform 合并)\n * @default -\n */\n overlayStyle?: React.CSSProperties;\n /**\n * @description 下拉框内层 surface 的内联样式。\n * 用于覆盖 surface 默认约束(默认 min-width:160px、max-width:320px);\n * 自定义 dropdownRender 内容若需大于 320px 宽,传 `{ width: 400, maxWidth: 'none' }` 即可。\n * @default -\n */\n overlayInnerStyle?: React.CSSProperties;\n\n /**\n * @description 自定义下拉框内容\n * @default -\n */\n dropdownRender?: (menus: React.ReactNode) => React.ReactNode;\n /**\n * @description 是否禁用\n * @default false\n */\n // 透传给子元素,antd的dropdown用cloneElement生成dropdown的子元素,劫持了disabled属性,因此如果Dropdown上没有disabled属性,子元素不能获得该属性\n disabled?: boolean;\n /**\n * @description 鼠标移入后延迟显示下拉框的时间,单位为毫秒\n * @default 0\n */\n delay?: UseHoverProps['delay'];\n /**\n * @description 是否在下拉框变化的时候自动更新位置\n * @default false\n */\n autoUpdatePos?: boolean;\n /**\n * @description 初始化焦点,参照:https://floating-ui.com/docs/floatingfocusmanager#initialfocus\n */\n initialFocus?: FloatingFocusManagerProps['initialFocus'];\n\n /**\n * @description 菜单是否跟随触发元素宽度\n * @default false\n */\n popupMatchTriggerWidth?: boolean | number;\n /**\n * @description 空间不足时自动计算菜单最大高度并启用滚动,启用后 offset 固定为 0\n * @default false\n */\n allowOverlap?: boolean;\n}\n\nfunction hasTrigger(\n trigger: ActionType | ActionType[],\n action: ActionType,\n): boolean {\n return Array.isArray(trigger) ? trigger.includes(action) : trigger === action;\n}\n\nexport default function Dropdown(props: IDropdownProps) {\n const {\n children,\n destroyPopupOnHide = true,\n getPopupContainer,\n menu,\n overlayClassName,\n placement = 'bottom-start',\n trigger = 'click',\n open,\n onOpenChange = () => {},\n overlayStyle,\n overlayInnerStyle,\n dropdownRender,\n disabled,\n offset: offsetProps = 4,\n delay = 0,\n autoUpdatePos = false,\n // 默认不自动 focus\n initialFocus = -1,\n popupMatchTriggerWidth = false,\n allowOverlap = false,\n } = props;\n const [isOpen, setIsOpen] = useState<boolean>(open || false);\n const [isAnimatingOut, setIsAnimatingOut] = useState(false);\n const closeAnimationTimerRef = useRef<ReturnType<typeof setTimeout> | null>(\n null,\n );\n const lastResolvedFloatingStylesRef = useRef<React.CSSProperties | null>(\n null,\n );\n const lastResolvedSideRef = useRef<'top' | 'bottom' | 'left' | 'right'>(\n resolvePlacementSide(placement),\n );\n const currentFloatingStylesRef = useRef<React.CSSProperties | null>(null);\n const currentFloatingSideRef = useRef<'top' | 'bottom' | 'left' | 'right'>(\n resolvePlacementSide(placement),\n );\n const [targetElement, setTargetElement] = useState<HTMLElement | null>(null);\n const popupMatchTriggerWidthNumber = parsePopupMatchWidth(\n popupMatchTriggerWidth,\n );\n const [matchedTriggerWidth, setMatchedTriggerWidth] = useState<\n number | undefined\n >(popupMatchTriggerWidthNumber);\n const popupZIndex = useFloatingPopupZIndex();\n\n const onOpenChangeFn = useMemoizedFn(onOpenChange);\n const isOpenControlled = open !== undefined;\n\n const clearCloseAnimationTimer = useCallback(() => {\n if (closeAnimationTimerRef.current) {\n clearTimeout(closeAnimationTimerRef.current);\n closeAnimationTimerRef.current = null;\n }\n }, []);\n\n const stopCloseAnimation = useCallback(() => {\n clearCloseAnimationTimer();\n document.body.classList.remove('ald-dropdown-root-closing');\n setIsAnimatingOut(false);\n }, [clearCloseAnimationTimer]);\n\n const markRootClosing = useCallback(() => {\n document.body.classList.add('ald-dropdown-root-closing');\n lastResolvedFloatingStylesRef.current =\n currentFloatingStylesRef.current ?? lastResolvedFloatingStylesRef.current;\n lastResolvedSideRef.current =\n currentFloatingSideRef.current ?? lastResolvedSideRef.current;\n }, []);\n\n const startCloseAnimation = useCallback(() => {\n clearCloseAnimationTimer();\n markRootClosing();\n setIsAnimatingOut(true);\n closeAnimationTimerRef.current = setTimeout(() => {\n document.body.classList.remove('ald-dropdown-root-closing');\n setIsAnimatingOut(false);\n closeAnimationTimerRef.current = null;\n }, OVERLAY_EXIT_ANIMATION_MS);\n }, [clearCloseAnimationTimer, markRootClosing]);\n\n useLayoutEffect(() => {\n if (!isOpenControlled) {\n return;\n }\n\n if (open) {\n stopCloseAnimation();\n setIsOpen(true);\n return;\n }\n\n if (isOpen) {\n startCloseAnimation();\n }\n setIsOpen(false);\n }, [isOpen, isOpenControlled, open, startCloseAnimation, stopCloseAnimation]);\n\n useEffect(() => {\n return () => {\n clearCloseAnimationTimer();\n };\n }, [clearCloseAnimationTimer]);\n\n useEffect(() => {\n return () => {\n document.body.classList.remove('ald-dropdown-root-closing');\n };\n }, []);\n\n const onChangeOpen = useCallback(\n (newOpen: boolean) => {\n if (newOpen) {\n stopCloseAnimation();\n } else {\n startCloseAnimation();\n }\n\n if (!isOpenControlled) {\n setIsOpen(newOpen);\n }\n onOpenChangeFn(newOpen);\n },\n [isOpenControlled, onOpenChangeFn, startCloseAnimation, stopCloseAnimation],\n );\n\n const nodeId = useFloatingNodeId();\n const {\n refs,\n floatingStyles,\n context,\n placement: floatingPlacement,\n x,\n y,\n } = useFloating({\n nodeId,\n placement: placement as any,\n open: isOpen,\n onOpenChange: onChangeOpen,\n middleware: [\n offset(allowOverlap ? 0 : offsetProps),\n flip({\n fallbackAxisSideDirection: 'end',\n ...(allowOverlap && { fallbackStrategy: 'bestFit' }),\n }),\n shift(allowOverlap ? { mainAxis: true } : undefined),\n size({\n ...(allowOverlap && { padding: 8 }),\n apply({ availableHeight, elements }) {\n if (!allowOverlap) {\n return;\n }\n\n Object.assign(elements.floating.style, {\n maxHeight: `${Math.max(100, availableHeight)}px`,\n overflowY: 'auto',\n });\n },\n }),\n ],\n whileElementsMounted: autoUpdatePos ? autoUpdate : undefined,\n });\n\n const click = useClick(context, {\n enabled: hasTrigger(trigger, 'click'),\n });\n const hover = useHover(context, {\n enabled: hasTrigger(trigger, 'hover'),\n handleClose: safePolygon({}),\n delay: delay,\n });\n const dismiss = useDismiss(context, {});\n const role = useRole(context);\n\n const propsList = useMemo(() => {\n const res = [dismiss, role];\n\n if (hasTrigger(trigger, 'hover')) {\n res.unshift(hover);\n }\n if (hasTrigger(trigger, 'click')) {\n res.unshift(click);\n }\n return res;\n }, [trigger, click, dismiss, role, hover]);\n\n const { getReferenceProps, getFloatingProps } = useInteractions(propsList);\n\n const headingId = useId();\n\n useLayoutEffect(() => {\n if (!popupMatchTriggerWidth || !isOpen) {\n setMatchedTriggerWidth(undefined);\n return;\n }\n\n if (popupMatchTriggerWidthNumber !== undefined) {\n setMatchedTriggerWidth(popupMatchTriggerWidthNumber);\n return;\n }\n\n const referenceElement = targetElement;\n if (!referenceElement) {\n return;\n }\n\n const updateMatchedWidth = () => {\n const nextWidth = referenceElement.getBoundingClientRect().width;\n setMatchedTriggerWidth((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(referenceElement);\n\n return () => {\n if (resizeAnimationFrame !== undefined) {\n cancelAnimationFrame(resizeAnimationFrame);\n }\n observer.disconnect();\n };\n }, [\n isOpen,\n popupMatchTriggerWidth,\n popupMatchTriggerWidthNumber,\n targetElement,\n ]);\n\n const child = children as React.ReactElement;\n const childProps = child.props || {};\n const referenceProps = getReferenceProps();\n const updateMatchedWidthFromElement = useCallback(\n (element: HTMLElement) => {\n if (!popupMatchTriggerWidth) {\n return;\n }\n\n setMatchedTriggerWidth((currentWidth) => {\n const nextWidth =\n popupMatchTriggerWidthNumber !== undefined\n ? popupMatchTriggerWidthNumber\n : element.getBoundingClientRect().width;\n return currentWidth === nextWidth ? currentWidth : nextWidth;\n });\n },\n [popupMatchTriggerWidth, popupMatchTriggerWidthNumber],\n );\n const modifiedChild = cloneElement(child, {\n ...childProps,\n disabled,\n // ref: (node: HTMLDivElement) => refs.setReference(node),\n ...referenceProps,\n onClick: (event: React.MouseEvent<HTMLElement>) => {\n updateMatchedWidthFromElement(event.currentTarget);\n childProps.onClick?.(event);\n const { onClick: referenceOnClick } = referenceProps;\n if (typeof referenceOnClick === 'function') {\n referenceOnClick(event);\n }\n },\n });\n\n const onMenuItemClick = useCallback(\n (info: MenuInfo) => {\n if (menu?.onClick) {\n menu.onClick(info);\n }\n if (info.keepOpen) {\n document.body.classList.remove('ald-dropdown-root-closing');\n return;\n }\n onChangeOpen(false);\n },\n [menu, onChangeOpen],\n );\n\n const menuInstance = useMemo(() => {\n const menuProps = {\n ...menu,\n items: menu?.items || [],\n onBeforeLeafItemClick: markRootClosing,\n rootClosing: isAnimatingOut,\n };\n return (\n <Menu\n {...menuProps}\n onClick={onMenuItemClick}\n externalOverflow={allowOverlap}\n />\n );\n }, [allowOverlap, isAnimatingOut, markRootClosing, menu, onMenuItemClick]);\n\n const popupElement = useMemo(() => {\n return typeof dropdownRender === 'function'\n ? dropdownRender(menuInstance)\n : menuInstance;\n }, [dropdownRender, menuInstance]);\n\n const mergedMatchedTriggerWidth =\n popupMatchTriggerWidthNumber ?? matchedTriggerWidth;\n const matchedOverlayStyle =\n popupMatchTriggerWidth && mergedMatchedTriggerWidth !== undefined\n ? ({\n width: `${mergedMatchedTriggerWidth}px`,\n minWidth: 0,\n } satisfies React.CSSProperties)\n : undefined;\n\n const matchedSurfaceStyle = popupMatchTriggerWidth\n ? ({\n width: '100%',\n minWidth: 0,\n maxWidth: 'none',\n } satisfies React.CSSProperties)\n : undefined;\n\n const floatingSide = resolvePlacementSide(String(floatingPlacement));\n const shouldKeepMounted = !destroyPopupOnHide || isOpen || isAnimatingOut;\n const isPositionReady = x !== null && y !== null;\n const overlayHidden =\n (!isOpen && !isAnimatingOut) || (isOpen && !isPositionReady);\n const resolvedFloatingStyles = isAnimatingOut\n ? lastResolvedFloatingStylesRef.current ?? floatingStyles\n : floatingStyles;\n const resolvedFloatingSide = isAnimatingOut\n ? lastResolvedSideRef.current\n : floatingSide;\n\n if (isOpen && isPositionReady) {\n currentFloatingStylesRef.current = { ...floatingStyles };\n currentFloatingSideRef.current = floatingSide;\n lastResolvedFloatingStylesRef.current = { ...floatingStyles };\n lastResolvedSideRef.current = floatingSide;\n }\n\n // 渲染浮动内容到自定义容器\n const renderFloatingContent = useCallback(() => {\n const surface = (\n <div\n {...(isAnimatingOut ? {} : getFloatingProps())}\n className={cn(\n 'ald-dropdown-overlay',\n // tw-outline-none:FloatingFocusManager 打开时会聚焦浮层容器,不抑制 outline 会渲染出蓝色焦点框\n 'tw-pointer-events-auto tw-z-[1001] tw-max-w-none tw-outline-none',\n overlayClassName,\n { 'ald-dropdown-overlay-hidden': overlayHidden },\n )}\n ref={refs.setFloating}\n style={{\n zIndex: popupZIndex,\n ...resolvedFloatingStyles,\n ...matchedOverlayStyle,\n ...overlayStyle,\n }}\n aria-labelledby={headingId}\n >\n <div\n className={cn(\n 'ald-dropdown-surface',\n 'tw-flex tw-flex-col tw-items-start tw-text-sm',\n )}\n style={{\n ...matchedSurfaceStyle,\n ...overlayInnerStyle,\n }}\n data-state={isOpen ? 'open' : 'closed'}\n data-side={resolvedFloatingSide}\n >\n {popupElement}\n </div>\n </div>\n );\n\n const popupElem =\n isAnimatingOut && !isOpen ? (\n surface\n ) : (\n <FloatingFocusManager\n context={context}\n modal={false}\n initialFocus={initialFocus}\n >\n {surface}\n </FloatingFocusManager>\n );\n\n const popupContainer =\n typeof getPopupContainer === 'function'\n ? getPopupContainer()\n : document.body;\n return ReactDOM.createPortal(popupElem, popupContainer);\n }, [\n context,\n getFloatingProps,\n getPopupContainer,\n headingId,\n popupElement,\n refs.setFloating,\n overlayClassName,\n overlayStyle,\n overlayInnerStyle,\n matchedOverlayStyle,\n matchedSurfaceStyle,\n popupZIndex,\n overlayHidden,\n isAnimatingOut,\n isOpen,\n initialFocus,\n resolvedFloatingSide,\n resolvedFloatingStyles,\n ]);\n\n const popup = shouldKeepMounted ? renderFloatingContent() : null;\n const { setReference } = refs;\n\n const setTargetRef = useCallback(\n (node: HTMLElement | null) => {\n if (node) {\n // display: contents 元素没有 box model,getBoundingClientRect() 返回零值\n // 需要获取实际的第一个子元素作为 floating-ui 的参考元素\n const target =\n node.style.display === 'contents'\n ? (node.firstElementChild as HTMLElement) || node\n : node;\n setTargetElement((currentTarget) =>\n currentTarget === target ? currentTarget : target,\n );\n setReference(target);\n } else {\n setTargetElement(null);\n setReference(null);\n }\n },\n [setReference],\n );\n\n const content = (\n <>\n <span ref={setTargetRef} style={{ display: 'contents' }}>\n {modifiedChild}\n </span>\n <FloatingNode id={nodeId}>{popup}</FloatingNode>\n </>\n );\n\n const parentId = useFloatingParentNodeId();\n if (!parentId) {\n return <FloatingTree>{content}</FloatingTree>;\n }\n\n return content;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/Dropdown/index.tsx"],"sourcesContent":["import './dropdown.css';\nimport {\n FloatingFocusManager,\n FloatingFocusManagerProps,\n FloatingNode,\n FloatingTree,\n OffsetOptions,\n UseHoverProps,\n autoUpdate,\n flip,\n offset,\n safePolygon,\n shift,\n size,\n useClick,\n useDismiss,\n useFloating,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useHover,\n useId,\n useInteractions,\n useRole,\n} from '@floating-ui/react';\nimport { useMemoizedFn } from 'ahooks';\nimport { cn } from '../lib/utils';\nimport React, {\n cloneElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport ReactDOM from 'react-dom';\nimport Menu, { MenuInfo, MenuProps } from '../Menu';\nimport { useFloatingPopupZIndex } from '../_utils/floatingLayer';\n\nconst OVERLAY_EXIT_ANIMATION_MS = 200;\n\nfunction resolvePlacementSide(\n currentPlacement: string,\n): 'top' | 'bottom' | 'left' | 'right' {\n const [side] = currentPlacement.split('-');\n if (\n side === 'top' ||\n side === 'bottom' ||\n side === 'left' ||\n side === 'right'\n ) {\n return side;\n }\n if (currentPlacement.startsWith('top')) {\n return 'top';\n }\n if (currentPlacement.startsWith('bottom')) {\n return 'bottom';\n }\n if (currentPlacement.startsWith('left')) {\n return 'left';\n }\n if (currentPlacement.startsWith('right')) {\n return 'right';\n }\n return 'bottom';\n}\n\nfunction parsePopupMatchWidth(value: unknown): number | undefined {\n if (typeof value === 'number') {\n return value;\n }\n\n if (typeof value === 'string' && value.trim() !== '') {\n const parsedValue = Number(value);\n return Number.isNaN(parsedValue) ? undefined : parsedValue;\n }\n\n return undefined;\n}\n\nexport type ActionType = 'hover' | 'click';\nexport type PlacementType =\n | 'top'\n | 'bottom'\n | 'left'\n | 'right'\n | 'top-start'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-end'\n | 'left-start'\n | 'left-end'\n | 'right-start'\n | 'right-end'\n // Legacy antd-style placement names\n | 'topLeft'\n | 'topRight'\n | 'bottomLeft'\n | 'bottomRight';\nexport interface IDropdownProps {\n children: React.ReactNode;\n /**\n * @description 菜单弹出位置的偏移量\n */\n offset?: OffsetOptions;\n /**\n * @description 关闭后是否销毁 Dropdown\n * @default false\n */\n destroyPopupOnHide?: boolean;\n /**\n * @description 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位\n * @default () => document.body\n */\n getPopupContainer?: () => HTMLElement;\n /**\n * @description 菜单\n * @type Menu | () => Menu\n * @default -\n */\n menu?: MenuProps;\n // /**\n // * @description 菜单\n // * @type Menu | () => Menu\n // * @default -\n // */\n // menu?: ReactElement | (() => ReactElement);\n /**\n * @description 下拉根元素的类名称\n * @default -\n */\n overlayClassName?: string;\n /**\n * @description 菜单弹出位置\n * @default bottomLeft\n */\n placement?: PlacementType;\n /**\n * @description 触发下拉的行为\n * @type ActionType, 其中 ActionType 为 'hover' | 'click' | 'contextMenu';\n * @default click\n */\n trigger?: ActionType | ActionType[];\n /**\n * @description 菜单是否显示\n * @default -\n */\n open?: boolean;\n /**\n * @description 菜单显示状态改变时调用,参数为 open,点击菜单按钮导致的消失不会触发\n * @default -\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * @description 下拉框外层 overlay 的内联样式(与定位 transform 合并)\n * @default -\n */\n overlayStyle?: React.CSSProperties;\n /**\n * @description 下拉框内层 surface 的内联样式。\n * 用于覆盖 surface 默认约束(默认 min-width:160px、max-width:320px);\n * 自定义 dropdownRender 内容若需大于 320px 宽,传 `{ width: 400, maxWidth: 'none' }` 即可。\n * @default -\n */\n overlayInnerStyle?: React.CSSProperties;\n\n /**\n * @description 自定义下拉框内容\n * @default -\n */\n dropdownRender?: (menus: React.ReactNode) => React.ReactNode;\n /**\n * @description 是否禁用\n * @default false\n */\n // 透传给子元素,antd的dropdown用cloneElement生成dropdown的子元素,劫持了disabled属性,因此如果Dropdown上没有disabled属性,子元素不能获得该属性\n disabled?: boolean;\n /**\n * @description 鼠标移入后延迟显示下拉框的时间,单位为毫秒\n * @default 0\n */\n delay?: UseHoverProps['delay'];\n /**\n * @description 是否在下拉框变化的时候自动更新位置\n * @default false\n */\n autoUpdatePos?: boolean;\n /**\n * @description 初始化焦点,参照:https://floating-ui.com/docs/floatingfocusmanager#initialfocus\n */\n initialFocus?: FloatingFocusManagerProps['initialFocus'];\n\n /**\n * @description 菜单是否跟随触发元素宽度\n * @default false\n */\n popupMatchTriggerWidth?: boolean | number;\n /**\n * @description 空间不足时自动计算菜单最大高度并启用滚动,启用后 offset 固定为 0\n * @default false\n */\n allowOverlap?: boolean;\n}\n\nfunction hasTrigger(\n trigger: ActionType | ActionType[],\n action: ActionType,\n): boolean {\n return Array.isArray(trigger) ? trigger.includes(action) : trigger === action;\n}\n\nexport default function Dropdown(props: IDropdownProps) {\n const {\n children,\n destroyPopupOnHide = true,\n getPopupContainer,\n menu,\n overlayClassName,\n placement = 'bottom-start',\n trigger = 'click',\n open,\n onOpenChange = () => {},\n overlayStyle,\n overlayInnerStyle,\n dropdownRender,\n disabled,\n offset: offsetProps = 4,\n delay = 0,\n autoUpdatePos = false,\n // 默认不自动 focus\n initialFocus = -1,\n popupMatchTriggerWidth = false,\n allowOverlap = false,\n } = props;\n const [isOpen, setIsOpen] = useState<boolean>(open || false);\n const [isAnimatingOut, setIsAnimatingOut] = useState(false);\n const closeAnimationTimerRef = useRef<ReturnType<typeof setTimeout> | null>(\n null,\n );\n const lastResolvedFloatingStylesRef = useRef<React.CSSProperties | null>(\n null,\n );\n const lastResolvedSideRef = useRef<'top' | 'bottom' | 'left' | 'right'>(\n resolvePlacementSide(placement),\n );\n const currentFloatingStylesRef = useRef<React.CSSProperties | null>(null);\n const currentFloatingSideRef = useRef<'top' | 'bottom' | 'left' | 'right'>(\n resolvePlacementSide(placement),\n );\n const [targetElement, setTargetElement] = useState<HTMLElement | null>(null);\n const popupMatchTriggerWidthNumber = parsePopupMatchWidth(\n popupMatchTriggerWidth,\n );\n const [matchedTriggerWidth, setMatchedTriggerWidth] = useState<\n number | undefined\n >(popupMatchTriggerWidthNumber);\n const popupZIndex = useFloatingPopupZIndex();\n\n const onOpenChangeFn = useMemoizedFn(onOpenChange);\n const isOpenControlled = open !== undefined;\n\n const clearCloseAnimationTimer = useCallback(() => {\n if (closeAnimationTimerRef.current) {\n clearTimeout(closeAnimationTimerRef.current);\n closeAnimationTimerRef.current = null;\n }\n }, []);\n\n const stopCloseAnimation = useCallback(() => {\n clearCloseAnimationTimer();\n document.body.classList.remove('ald-dropdown-root-closing');\n setIsAnimatingOut(false);\n }, [clearCloseAnimationTimer]);\n\n const markRootClosing = useCallback(() => {\n document.body.classList.add('ald-dropdown-root-closing');\n lastResolvedFloatingStylesRef.current =\n currentFloatingStylesRef.current ?? lastResolvedFloatingStylesRef.current;\n lastResolvedSideRef.current =\n currentFloatingSideRef.current ?? lastResolvedSideRef.current;\n }, []);\n\n const startCloseAnimation = useCallback(() => {\n clearCloseAnimationTimer();\n markRootClosing();\n setIsAnimatingOut(true);\n closeAnimationTimerRef.current = setTimeout(() => {\n document.body.classList.remove('ald-dropdown-root-closing');\n setIsAnimatingOut(false);\n closeAnimationTimerRef.current = null;\n }, OVERLAY_EXIT_ANIMATION_MS);\n }, [clearCloseAnimationTimer, markRootClosing]);\n\n useLayoutEffect(() => {\n if (!isOpenControlled) {\n return;\n }\n\n if (open) {\n stopCloseAnimation();\n setIsOpen(true);\n return;\n }\n\n if (isOpen) {\n startCloseAnimation();\n }\n setIsOpen(false);\n }, [isOpen, isOpenControlled, open, startCloseAnimation, stopCloseAnimation]);\n\n useEffect(() => {\n return () => {\n clearCloseAnimationTimer();\n };\n }, [clearCloseAnimationTimer]);\n\n useEffect(() => {\n return () => {\n document.body.classList.remove('ald-dropdown-root-closing');\n };\n }, []);\n\n const onChangeOpen = useCallback(\n (newOpen: boolean) => {\n if (newOpen) {\n stopCloseAnimation();\n } else {\n startCloseAnimation();\n }\n\n if (!isOpenControlled) {\n setIsOpen(newOpen);\n }\n onOpenChangeFn(newOpen);\n },\n [isOpenControlled, onOpenChangeFn, startCloseAnimation, stopCloseAnimation],\n );\n\n const nodeId = useFloatingNodeId();\n const {\n refs,\n floatingStyles,\n context,\n placement: floatingPlacement,\n x,\n y,\n } = useFloating({\n nodeId,\n placement: placement as any,\n open: isOpen,\n onOpenChange: onChangeOpen,\n middleware: [\n offset(allowOverlap ? 0 : offsetProps),\n flip({\n fallbackAxisSideDirection: 'end',\n ...(allowOverlap && { fallbackStrategy: 'bestFit' }),\n }),\n shift(allowOverlap ? { mainAxis: true } : undefined),\n size({\n ...(allowOverlap && { padding: 8 }),\n apply({ availableHeight, elements }) {\n if (!allowOverlap) {\n return;\n }\n\n Object.assign(elements.floating.style, {\n maxHeight: `${Math.max(100, availableHeight)}px`,\n overflowY: 'auto',\n });\n },\n }),\n ],\n whileElementsMounted: autoUpdatePos ? autoUpdate : undefined,\n });\n\n const click = useClick(context, {\n enabled: hasTrigger(trigger, 'click'),\n });\n const hover = useHover(context, {\n enabled: hasTrigger(trigger, 'hover'),\n handleClose: safePolygon({}),\n delay: delay,\n });\n const dismiss = useDismiss(context, {});\n const role = useRole(context);\n\n const propsList = useMemo(() => {\n const res = [dismiss, role];\n\n if (hasTrigger(trigger, 'hover')) {\n res.unshift(hover);\n }\n if (hasTrigger(trigger, 'click')) {\n res.unshift(click);\n }\n return res;\n }, [trigger, click, dismiss, role, hover]);\n\n const { getReferenceProps, getFloatingProps } = useInteractions(propsList);\n\n const headingId = useId();\n\n useLayoutEffect(() => {\n if (!popupMatchTriggerWidth || !isOpen) {\n setMatchedTriggerWidth(undefined);\n return;\n }\n\n if (popupMatchTriggerWidthNumber !== undefined) {\n setMatchedTriggerWidth(popupMatchTriggerWidthNumber);\n return;\n }\n\n const referenceElement = targetElement;\n if (!referenceElement) {\n return;\n }\n\n const updateMatchedWidth = () => {\n const nextWidth = referenceElement.getBoundingClientRect().width;\n setMatchedTriggerWidth((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(referenceElement);\n\n return () => {\n if (resizeAnimationFrame !== undefined) {\n cancelAnimationFrame(resizeAnimationFrame);\n }\n observer.disconnect();\n };\n }, [\n isOpen,\n popupMatchTriggerWidth,\n popupMatchTriggerWidthNumber,\n targetElement,\n ]);\n\n const child = children as React.ReactElement;\n const childProps = child.props || {};\n const referenceProps = getReferenceProps();\n const updateMatchedWidthFromElement = useCallback(\n (element: HTMLElement) => {\n if (!popupMatchTriggerWidth) {\n return;\n }\n\n setMatchedTriggerWidth((currentWidth) => {\n const nextWidth =\n popupMatchTriggerWidthNumber !== undefined\n ? popupMatchTriggerWidthNumber\n : element.getBoundingClientRect().width;\n return currentWidth === nextWidth ? currentWidth : nextWidth;\n });\n },\n [popupMatchTriggerWidth, popupMatchTriggerWidthNumber],\n );\n const modifiedChild = cloneElement(child, {\n ...childProps,\n disabled,\n // ref: (node: HTMLDivElement) => refs.setReference(node),\n ...referenceProps,\n onClick: (event: React.MouseEvent<HTMLElement>) => {\n updateMatchedWidthFromElement(event.currentTarget);\n childProps.onClick?.(event);\n const { onClick: referenceOnClick } = referenceProps;\n if (typeof referenceOnClick === 'function') {\n referenceOnClick(event);\n }\n },\n });\n\n const onMenuItemClick = useCallback(\n (info: MenuInfo) => {\n if (menu?.onClick) {\n menu.onClick(info);\n }\n if (info.keepOpen) {\n document.body.classList.remove('ald-dropdown-root-closing');\n return;\n }\n onChangeOpen(false);\n },\n [menu, onChangeOpen],\n );\n\n const menuInstance = useMemo(() => {\n const menuProps = {\n ...menu,\n items: menu?.items || [],\n menuStyle: {\n ...(popupMatchTriggerWidth\n ? {\n width: '100%',\n minWidth: 0,\n maxWidth: 'none',\n }\n : undefined),\n ...menu?.menuStyle,\n },\n onBeforeLeafItemClick: markRootClosing,\n rootClosing: isAnimatingOut,\n };\n return (\n <Menu\n {...menuProps}\n onClick={onMenuItemClick}\n externalOverflow={allowOverlap}\n />\n );\n }, [\n allowOverlap,\n isAnimatingOut,\n markRootClosing,\n menu,\n onMenuItemClick,\n popupMatchTriggerWidth,\n ]);\n\n const popupElement = useMemo(() => {\n return typeof dropdownRender === 'function'\n ? dropdownRender(menuInstance)\n : menuInstance;\n }, [dropdownRender, menuInstance]);\n\n const mergedMatchedTriggerWidth =\n popupMatchTriggerWidthNumber ?? matchedTriggerWidth;\n const matchedOverlayStyle =\n popupMatchTriggerWidth && mergedMatchedTriggerWidth !== undefined\n ? ({\n width: `${mergedMatchedTriggerWidth}px`,\n minWidth: 0,\n } satisfies React.CSSProperties)\n : undefined;\n\n const matchedSurfaceStyle = popupMatchTriggerWidth\n ? ({\n width: '100%',\n minWidth: 0,\n maxWidth: 'none',\n } satisfies React.CSSProperties)\n : undefined;\n\n const floatingSide = resolvePlacementSide(String(floatingPlacement));\n const shouldKeepMounted = !destroyPopupOnHide || isOpen || isAnimatingOut;\n const isPositionReady = x !== null && y !== null;\n const overlayHidden =\n (!isOpen && !isAnimatingOut) || (isOpen && !isPositionReady);\n const resolvedFloatingStyles = isAnimatingOut\n ? lastResolvedFloatingStylesRef.current ?? floatingStyles\n : floatingStyles;\n const resolvedFloatingSide = isAnimatingOut\n ? lastResolvedSideRef.current\n : floatingSide;\n\n if (isOpen && isPositionReady) {\n currentFloatingStylesRef.current = { ...floatingStyles };\n currentFloatingSideRef.current = floatingSide;\n lastResolvedFloatingStylesRef.current = { ...floatingStyles };\n lastResolvedSideRef.current = floatingSide;\n }\n\n // 渲染浮动内容到自定义容器\n const renderFloatingContent = useCallback(() => {\n const surface = (\n <div\n {...(isAnimatingOut ? {} : getFloatingProps())}\n className={cn(\n 'ald-dropdown-overlay',\n // tw-outline-none:FloatingFocusManager 打开时会聚焦浮层容器,不抑制 outline 会渲染出蓝色焦点框\n 'tw-pointer-events-auto tw-z-[1001] tw-max-w-none tw-outline-none',\n overlayClassName,\n { 'ald-dropdown-overlay-hidden': overlayHidden },\n )}\n ref={refs.setFloating}\n style={{\n zIndex: popupZIndex,\n ...resolvedFloatingStyles,\n ...matchedOverlayStyle,\n ...overlayStyle,\n }}\n aria-labelledby={headingId}\n >\n <div\n className={cn(\n 'ald-dropdown-surface',\n 'tw-flex tw-flex-col tw-items-start tw-text-sm',\n )}\n style={{\n ...matchedSurfaceStyle,\n ...overlayInnerStyle,\n }}\n data-state={isOpen ? 'open' : 'closed'}\n data-side={resolvedFloatingSide}\n >\n {popupElement}\n </div>\n </div>\n );\n\n const popupElem =\n isAnimatingOut && !isOpen ? (\n surface\n ) : (\n <FloatingFocusManager\n context={context}\n modal={false}\n initialFocus={initialFocus}\n >\n {surface}\n </FloatingFocusManager>\n );\n\n const popupContainer =\n typeof getPopupContainer === 'function'\n ? getPopupContainer()\n : document.body;\n return ReactDOM.createPortal(popupElem, popupContainer);\n }, [\n context,\n getFloatingProps,\n getPopupContainer,\n headingId,\n popupElement,\n refs.setFloating,\n overlayClassName,\n overlayStyle,\n overlayInnerStyle,\n matchedOverlayStyle,\n matchedSurfaceStyle,\n popupZIndex,\n overlayHidden,\n isAnimatingOut,\n isOpen,\n initialFocus,\n resolvedFloatingSide,\n resolvedFloatingStyles,\n ]);\n\n const popup = shouldKeepMounted ? renderFloatingContent() : null;\n const { setReference } = refs;\n\n const setTargetRef = useCallback(\n (node: HTMLElement | null) => {\n if (node) {\n // display: contents 元素没有 box model,getBoundingClientRect() 返回零值\n // 需要获取实际的第一个子元素作为 floating-ui 的参考元素\n const target =\n node.style.display === 'contents'\n ? (node.firstElementChild as HTMLElement) || node\n : node;\n setTargetElement((currentTarget) =>\n currentTarget === target ? currentTarget : target,\n );\n setReference(target);\n } else {\n setTargetElement(null);\n setReference(null);\n }\n },\n [setReference],\n );\n\n const content = (\n <>\n <span ref={setTargetRef} style={{ display: 'contents' }}>\n {modifiedChild}\n </span>\n <FloatingNode id={nodeId}>{popup}</FloatingNode>\n </>\n );\n\n const parentId = useFloatingParentNodeId();\n if (!parentId) {\n return <FloatingTree>{content}</FloatingTree>;\n }\n\n return content;\n}\n"],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import Select_default from "../Select/index.js";
|
|
|
3
3
|
import { useContext } from "react";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
//#region src/Pagination/PageSizeChanger.tsx
|
|
6
|
+
var PAGE_SIZE_CHANGER_POPUP_WIDTH = 128;
|
|
6
7
|
var PageSizeChanger = ({ pageSize, pageSizeOptions, onChange, className, disabled = false }) => {
|
|
7
8
|
const { locale } = useContext(LocaleContext);
|
|
8
9
|
const t = getTranslator(locale);
|
|
@@ -22,7 +23,8 @@ var PageSizeChanger = ({ pageSize, pageSizeOptions, onChange, className, disable
|
|
|
22
23
|
width: 112,
|
|
23
24
|
disabled,
|
|
24
25
|
className: `ald-pagination-page-size-changer ${className || ""}`.trim(),
|
|
25
|
-
placeholder: t.Pagination.selectPageSize
|
|
26
|
+
placeholder: t.Pagination.selectPageSize,
|
|
27
|
+
popupMatchSelectWidth: PAGE_SIZE_CHANGER_POPUP_WIDTH
|
|
26
28
|
});
|
|
27
29
|
};
|
|
28
30
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageSizeChanger.js","names":[],"sources":["../../src/Pagination/PageSizeChanger.tsx"],"sourcesContent":["import React, { useContext } from 'react';\nimport Select from '../Select';\nimport { ISelectProps } from '../Select/interface';\nimport { LocaleContext, getTranslator } from '../locale/default';\n\ninterface IPageSizeChangerProps {\n // 当前 pageSize\n pageSize: number;\n // pageSize 选项\n pageSizeOptions: (string | number)[];\n // pageSize 变化的回调\n onChange: (size: number) => void;\n // 自定义样式类名\n className?: string;\n // 是否禁用\n disabled?: boolean;\n}\n\nconst PageSizeChanger: React.FC<IPageSizeChangerProps> = ({\n pageSize,\n pageSizeOptions,\n onChange,\n className,\n disabled = false,\n}) => {\n const { locale } = useContext(LocaleContext);\n const t = getTranslator(locale);\n\n // 将 pageSizeOptions 转换为 Select 可用的选项格式\n // 确保当前 pageSize 值在选项中存在\n const optionSet = new Set([...pageSizeOptions, pageSize]);\n const allOptions = Array.from(optionSet).sort(\n (a, b) => Number(a) - Number(b),\n );\n const selectOptions = allOptions.map((option) => ({\n label: `${option} ${t.Pagination.itemsPerPage}`,\n value: String(option),\n }));\n\n const handleChange = (value: string) => {\n const newSize = parseInt(value, 10);\n if (!isNaN(newSize) && newSize !== pageSize) {\n onChange(newSize);\n }\n };\n\n const selectProps: ISelectProps = {\n value: String(pageSize),\n onChange: handleChange,\n options: selectOptions,\n width: 112,\n disabled,\n className: `ald-pagination-page-size-changer ${className || ''}`.trim(),\n placeholder: t.Pagination.selectPageSize,\n };\n\n return <Select {...selectProps} />;\n};\n\nexport default PageSizeChanger;\n"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"PageSizeChanger.js","names":[],"sources":["../../src/Pagination/PageSizeChanger.tsx"],"sourcesContent":["import React, { useContext } from 'react';\nimport Select from '../Select';\nimport { ISelectProps } from '../Select/interface';\nimport { LocaleContext, getTranslator } from '../locale/default';\n\nconst PAGE_SIZE_CHANGER_POPUP_WIDTH = 128;\n\ninterface IPageSizeChangerProps {\n // 当前 pageSize\n pageSize: number;\n // pageSize 选项\n pageSizeOptions: (string | number)[];\n // pageSize 变化的回调\n onChange: (size: number) => void;\n // 自定义样式类名\n className?: string;\n // 是否禁用\n disabled?: boolean;\n}\n\nconst PageSizeChanger: React.FC<IPageSizeChangerProps> = ({\n pageSize,\n pageSizeOptions,\n onChange,\n className,\n disabled = false,\n}) => {\n const { locale } = useContext(LocaleContext);\n const t = getTranslator(locale);\n\n // 将 pageSizeOptions 转换为 Select 可用的选项格式\n // 确保当前 pageSize 值在选项中存在\n const optionSet = new Set([...pageSizeOptions, pageSize]);\n const allOptions = Array.from(optionSet).sort(\n (a, b) => Number(a) - Number(b),\n );\n const selectOptions = allOptions.map((option) => ({\n label: `${option} ${t.Pagination.itemsPerPage}`,\n value: String(option),\n }));\n\n const handleChange = (value: string) => {\n const newSize = parseInt(value, 10);\n if (!isNaN(newSize) && newSize !== pageSize) {\n onChange(newSize);\n }\n };\n\n const selectProps: ISelectProps = {\n value: String(pageSize),\n onChange: handleChange,\n options: selectOptions,\n width: 112,\n disabled,\n className: `ald-pagination-page-size-changer ${className || ''}`.trim(),\n placeholder: t.Pagination.selectPageSize,\n popupMatchSelectWidth: PAGE_SIZE_CHANGER_POPUP_WIDTH,\n };\n\n return <Select {...selectProps} />;\n};\n\nexport default PageSizeChanger;\n"],"mappings":";;;;;AAKA,IAAM,gCAAgC;AAetC,IAAM,mBAAoD,EACxD,UACA,iBACA,UACA,WACA,WAAW,YACP;CACJ,MAAM,EAAE,WAAW,WAAW,cAAc;CAC5C,MAAM,IAAI,cAAc,OAAO;CAI/B,MAAM,YAAY,IAAI,IAAI,CAAC,GAAG,iBAAiB,SAAS,CAAC;CAIzD,MAAM,gBAHa,MAAM,KAAK,UAAU,CAAC,MACtC,GAAG,MAAM,OAAO,EAAE,GAAG,OAAO,EAAE,CAChC,CACgC,KAAK,YAAY;EAChD,OAAO,GAAG,OAAO,GAAG,EAAE,WAAW;EACjC,OAAO,OAAO,OAAO;EACtB,EAAE;CAEH,MAAM,gBAAgB,UAAkB;EACtC,MAAM,UAAU,SAAS,OAAO,GAAG;AACnC,MAAI,CAAC,MAAM,QAAQ,IAAI,YAAY,SACjC,UAAS,QAAQ;;AAerB,QAAO,oBAAC,gBAAD;EAVL,OAAO,OAAO,SAAS;EACvB,UAAU;EACV,SAAS;EACT,OAAO;EACP;EACA,WAAW,oCAAoC,aAAa,KAAK,MAAM;EACvE,aAAa,EAAE,WAAW;EAC1B,uBAAuB;EAGS,CAAA"}
|
package/dist/Skeleton/index.js
CHANGED
|
@@ -26,6 +26,7 @@ var INPUT_SIZE_MAP = {
|
|
|
26
26
|
default: 32,
|
|
27
27
|
large: 40
|
|
28
28
|
};
|
|
29
|
+
var SKELETON_BACKGROUND_COLOR = "var(--alias-colors-bg-skeleton-subtle, var(--background-neutral-subtle, #e5e7eb))";
|
|
29
30
|
var SkeletonButton = ({ active, size = "default", shape = "square", block, className, style }) => {
|
|
30
31
|
const animClass = active ? "tw-animate-pulse" : "";
|
|
31
32
|
const dims = BUTTON_SIZE_MAP[size];
|
|
@@ -33,6 +34,7 @@ var SkeletonButton = ({ active, size = "default", shape = "square", block, class
|
|
|
33
34
|
return /* @__PURE__ */ jsx("span", {
|
|
34
35
|
className: cn("ald-skeleton-button tw-inline-block tw-bg-[var(--background-neutral-subtle)]", animClass, block && "tw-block tw-w-full", className),
|
|
35
36
|
style: {
|
|
37
|
+
backgroundColor: SKELETON_BACKGROUND_COLOR,
|
|
36
38
|
width: shape === "circle" ? dims.height : block ? void 0 : dims.width,
|
|
37
39
|
height: dims.height,
|
|
38
40
|
borderRadius,
|
|
@@ -46,6 +48,7 @@ var SkeletonAvatar = ({ active, size = "default", shape = "circle", className, s
|
|
|
46
48
|
return /* @__PURE__ */ jsx("span", {
|
|
47
49
|
className: cn("ald-skeleton-avatar tw-inline-block tw-bg-[var(--background-neutral-subtle)]", animClass, className),
|
|
48
50
|
style: {
|
|
51
|
+
backgroundColor: SKELETON_BACKGROUND_COLOR,
|
|
49
52
|
width: dim,
|
|
50
53
|
height: dim,
|
|
51
54
|
borderRadius: shape === "circle" ? "50%" : "4px",
|
|
@@ -59,6 +62,7 @@ var SkeletonInput = ({ active, size = "default", block, className, style }) => {
|
|
|
59
62
|
return /* @__PURE__ */ jsx("span", {
|
|
60
63
|
className: cn("ald-skeleton-input tw-inline-block tw-bg-[var(--background-neutral-subtle)]", animClass, block && "tw-block tw-w-full", className),
|
|
61
64
|
style: {
|
|
65
|
+
backgroundColor: SKELETON_BACKGROUND_COLOR,
|
|
62
66
|
width: block ? void 0 : 200,
|
|
63
67
|
height,
|
|
64
68
|
borderRadius: 4,
|
|
@@ -70,6 +74,7 @@ var SkeletonImage = ({ active, className, style }) => {
|
|
|
70
74
|
return /* @__PURE__ */ jsx("span", {
|
|
71
75
|
className: cn("ald-skeleton-image tw-flex tw-items-center tw-justify-center tw-bg-[var(--background-neutral-subtle)]", active ? "tw-animate-pulse" : "", className),
|
|
72
76
|
style: {
|
|
77
|
+
backgroundColor: SKELETON_BACKGROUND_COLOR,
|
|
73
78
|
width: 96,
|
|
74
79
|
height: 96,
|
|
75
80
|
borderRadius: 4,
|
|
@@ -97,6 +102,7 @@ function Skeleton(props) {
|
|
|
97
102
|
children: [avatar && /* @__PURE__ */ jsx("div", {
|
|
98
103
|
className: cn("ald-skeleton-avatar tw-shrink-0 tw-rounded-full tw-bg-[var(--background-neutral-subtle)]", animClass, typeof avatar === "object" && avatar.shape === "square" ? "tw-rounded-r-50" : "tw-rounded-full"),
|
|
99
104
|
style: {
|
|
105
|
+
backgroundColor: SKELETON_BACKGROUND_COLOR,
|
|
100
106
|
width: 40,
|
|
101
107
|
height: 40
|
|
102
108
|
}
|
|
@@ -104,10 +110,16 @@ function Skeleton(props) {
|
|
|
104
110
|
className: "ald-skeleton-content tw-flex-1",
|
|
105
111
|
children: [title && /* @__PURE__ */ jsx("div", {
|
|
106
112
|
className: cn("ald-skeleton-title tw-mb-4 tw-h-4 tw-bg-[var(--background-neutral-subtle)]", animClass, round ? "tw-rounded-full" : "tw-rounded-r-25"),
|
|
107
|
-
style: {
|
|
113
|
+
style: {
|
|
114
|
+
backgroundColor: SKELETON_BACKGROUND_COLOR,
|
|
115
|
+
width: typeof title === "object" ? title.width : "38%"
|
|
116
|
+
}
|
|
108
117
|
}), paragraph && Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsx("div", {
|
|
109
118
|
className: cn("ald-skeleton-paragraph tw-mb-3 tw-h-4 tw-bg-[var(--background-neutral-subtle)]", animClass, round ? "tw-rounded-full" : "tw-rounded-r-25"),
|
|
110
|
-
style: {
|
|
119
|
+
style: {
|
|
120
|
+
backgroundColor: SKELETON_BACKGROUND_COLOR,
|
|
121
|
+
width: i === rows - 1 ? "61%" : "100%"
|
|
122
|
+
}
|
|
111
123
|
}, i))]
|
|
112
124
|
})]
|
|
113
125
|
});
|
|
@@ -115,7 +127,10 @@ function Skeleton(props) {
|
|
|
115
127
|
function SkeletonNode({ active, className, style, children }) {
|
|
116
128
|
return /* @__PURE__ */ jsx("div", {
|
|
117
129
|
className: cn("ald-skeleton-node tw-inline-flex tw-items-center tw-justify-center tw-rounded-r-25 tw-bg-[var(--background-neutral-subtle)]", active && "tw-animate-pulse", className),
|
|
118
|
-
style
|
|
130
|
+
style: {
|
|
131
|
+
backgroundColor: SKELETON_BACKGROUND_COLOR,
|
|
132
|
+
...style
|
|
133
|
+
},
|
|
119
134
|
children
|
|
120
135
|
});
|
|
121
136
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/Skeleton/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface SkeletonProps {\n active?: boolean;\n loading?: boolean;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n avatar?:\n | boolean\n | {\n size?: number | 'small' | 'default' | 'large';\n shape?: 'circle' | 'square';\n };\n title?: boolean | { width?: number | string };\n paragraph?:\n | boolean\n | { rows?: number; width?: number | string | (number | string)[] };\n round?: boolean;\n}\n\n// --- Shared types for sub-components ---\n\ntype SkeletonElementSize = 'small' | 'default' | 'large';\n\ninterface SkeletonElementBaseProps {\n active?: boolean;\n size?: SkeletonElementSize;\n className?: string;\n style?: React.CSSProperties;\n}\n\ninterface SkeletonButtonProps extends SkeletonElementBaseProps {\n shape?: 'circle' | 'round' | 'square';\n block?: boolean;\n}\n\ninterface SkeletonAvatarProps extends SkeletonElementBaseProps {\n shape?: 'circle' | 'square';\n}\n\ninterface SkeletonInputProps extends SkeletonElementBaseProps {\n block?: boolean;\n}\n\ninterface SkeletonImageProps {\n active?: boolean;\n className?: string;\n style?: React.CSSProperties;\n}\n\n// --- Size maps ---\n\nconst BUTTON_SIZE_MAP: Record<\n SkeletonElementSize,\n { width: number; height: number }\n> = {\n small: { width: 64, height: 24 },\n default: { width: 80, height: 32 },\n large: { width: 96, height: 40 },\n};\n\nconst AVATAR_SIZE_MAP: Record<SkeletonElementSize, number> = {\n small: 24,\n default: 32,\n large: 40,\n};\n\nconst INPUT_SIZE_MAP: Record<SkeletonElementSize, number> = {\n small: 24,\n default: 32,\n large: 40,\n};\n\n// --- Sub-components ---\n\nconst SkeletonButton: React.FC<SkeletonButtonProps> = ({\n active,\n size = 'default',\n shape = 'square',\n block,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const dims = BUTTON_SIZE_MAP[size];\n\n const borderRadius =\n shape === 'circle'\n ? '50%'\n : shape === 'round'\n ? `${dims.height / 2}px`\n : '4px';\n\n return (\n <span\n className={cn(\n 'ald-skeleton-button tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n block && 'tw-block tw-w-full',\n className,\n )}\n style={{\n width:\n shape === 'circle' ? dims.height : block ? undefined : dims.width,\n height: dims.height,\n borderRadius,\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonAvatar: React.FC<SkeletonAvatarProps> = ({\n active,\n size = 'default',\n shape = 'circle',\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const dim = typeof size === 'number' ? size : AVATAR_SIZE_MAP[size];\n\n return (\n <span\n className={cn(\n 'ald-skeleton-avatar tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n className,\n )}\n style={{\n width: dim,\n height: dim,\n borderRadius: shape === 'circle' ? '50%' : '4px',\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonInput: React.FC<SkeletonInputProps> = ({\n active,\n size = 'default',\n block,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const height = INPUT_SIZE_MAP[size];\n\n return (\n <span\n className={cn(\n 'ald-skeleton-input tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n block && 'tw-block tw-w-full',\n className,\n )}\n style={{\n width: block ? undefined : 200,\n height,\n borderRadius: 4,\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonImage: React.FC<SkeletonImageProps> = ({\n active,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n\n return (\n <span\n className={cn(\n 'ald-skeleton-image tw-flex tw-items-center tw-justify-center tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n className,\n )}\n style={{\n width: 96,\n height: 96,\n borderRadius: 4,\n ...style,\n }}\n >\n <svg\n viewBox=\"0 0 1098 1024\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"48\"\n height=\"48\"\n fill=\"currentColor\"\n style={{ opacity: 0.2 }}\n >\n <path d=\"M365.714 329.143q0 45.714-32.036 77.75t-77.75 32.036-77.75-32.036-32.036-77.75 32.036-77.75 77.75-32.036 77.75 32.036 32.036 77.75zM950.857 548.571v256H146.286V694.857l182.857-182.857 91.429 91.429 292.571-292.571zM1005.714 146.286H91.429q-7.46 0-12.873 5.413T73.143 164.571v694.857q0 7.46 5.413 12.873t12.873 5.413h914.286q7.46 0 12.873-5.413t5.413-12.873V164.571q0-7.46-5.413-12.873t-12.873-5.413zm91.429 18.286v694.857q0 37.714-26.857 64.571t-64.571 26.857H91.429q-37.714 0-64.571-26.857T0 859.429V164.571q0-37.714 26.857-64.571T91.429 73.143h914.286q37.714 0 64.571 26.857t26.857 64.571z\" />\n </svg>\n </span>\n );\n};\n\n// --- Main Skeleton component ---\n\nfunction Skeleton(props: SkeletonProps) {\n const {\n active = false,\n loading = true,\n className,\n style,\n children,\n avatar,\n title = true,\n paragraph = true,\n round,\n } = props;\n\n if (!loading) {\n return <>{children}</>;\n }\n\n const animClass = active ? 'tw-animate-pulse' : '';\n const rows =\n typeof paragraph === 'object' ? paragraph.rows || 3 : paragraph ? 3 : 0;\n\n return (\n <div\n className={cn('ald-skeleton tw-flex tw-gap-4', className)}\n style={style}\n >\n {avatar && (\n <div\n className={cn(\n 'ald-skeleton-avatar tw-shrink-0 tw-rounded-full tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n typeof avatar === 'object' && avatar.shape === 'square'\n ? 'tw-rounded-r-50'\n : 'tw-rounded-full',\n )}\n style={{ width: 40, height: 40 }}\n />\n )}\n <div className=\"ald-skeleton-content tw-flex-1\">\n {title && (\n <div\n className={cn(\n 'ald-skeleton-title tw-mb-4 tw-h-4 tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n round ? 'tw-rounded-full' : 'tw-rounded-r-25',\n )}\n style={{\n width: typeof title === 'object' ? title.width : '38%',\n }}\n />\n )}\n {paragraph &&\n Array.from({ length: rows }).map((_, i) => (\n <div\n key={i}\n className={cn(\n 'ald-skeleton-paragraph tw-mb-3 tw-h-4 tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n round ? 'tw-rounded-full' : 'tw-rounded-r-25',\n )}\n style={{\n width: i === rows - 1 ? '61%' : '100%',\n }}\n />\n ))}\n </div>\n </div>\n );\n}\n\nfunction SkeletonNode({\n active,\n className,\n style,\n children,\n}: {\n active?: boolean;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n}) {\n return (\n <div\n className={cn(\n 'ald-skeleton-node tw-inline-flex tw-items-center tw-justify-center tw-rounded-r-25 tw-bg-[var(--background-neutral-subtle)]',\n active && 'tw-animate-pulse',\n className,\n )}\n style={style}\n >\n {children}\n </div>\n );\n}\n\n// Attach sub-components\nSkeleton.Button = SkeletonButton;\nSkeleton.Avatar = SkeletonAvatar;\nSkeleton.Input = SkeletonInput;\nSkeleton.Image = SkeletonImage;\nSkeleton.Node = SkeletonNode;\n\nexport default Skeleton;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/Skeleton/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface SkeletonProps {\n active?: boolean;\n loading?: boolean;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n avatar?:\n | boolean\n | {\n size?: number | 'small' | 'default' | 'large';\n shape?: 'circle' | 'square';\n };\n title?: boolean | { width?: number | string };\n paragraph?:\n | boolean\n | { rows?: number; width?: number | string | (number | string)[] };\n round?: boolean;\n}\n\n// --- Shared types for sub-components ---\n\ntype SkeletonElementSize = 'small' | 'default' | 'large';\n\ninterface SkeletonElementBaseProps {\n active?: boolean;\n size?: SkeletonElementSize;\n className?: string;\n style?: React.CSSProperties;\n}\n\ninterface SkeletonButtonProps extends SkeletonElementBaseProps {\n shape?: 'circle' | 'round' | 'square';\n block?: boolean;\n}\n\ninterface SkeletonAvatarProps extends SkeletonElementBaseProps {\n shape?: 'circle' | 'square';\n}\n\ninterface SkeletonInputProps extends SkeletonElementBaseProps {\n block?: boolean;\n}\n\ninterface SkeletonImageProps {\n active?: boolean;\n className?: string;\n style?: React.CSSProperties;\n}\n\n// --- Size maps ---\n\nconst BUTTON_SIZE_MAP: Record<\n SkeletonElementSize,\n { width: number; height: number }\n> = {\n small: { width: 64, height: 24 },\n default: { width: 80, height: 32 },\n large: { width: 96, height: 40 },\n};\n\nconst AVATAR_SIZE_MAP: Record<SkeletonElementSize, number> = {\n small: 24,\n default: 32,\n large: 40,\n};\n\nconst INPUT_SIZE_MAP: Record<SkeletonElementSize, number> = {\n small: 24,\n default: 32,\n large: 40,\n};\n\nconst SKELETON_BACKGROUND_COLOR =\n 'var(--alias-colors-bg-skeleton-subtle, var(--background-neutral-subtle, #e5e7eb))';\n\n// --- Sub-components ---\n\nconst SkeletonButton: React.FC<SkeletonButtonProps> = ({\n active,\n size = 'default',\n shape = 'square',\n block,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const dims = BUTTON_SIZE_MAP[size];\n\n const borderRadius =\n shape === 'circle'\n ? '50%'\n : shape === 'round'\n ? `${dims.height / 2}px`\n : '4px';\n\n return (\n <span\n className={cn(\n 'ald-skeleton-button tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n block && 'tw-block tw-w-full',\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width:\n shape === 'circle' ? dims.height : block ? undefined : dims.width,\n height: dims.height,\n borderRadius,\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonAvatar: React.FC<SkeletonAvatarProps> = ({\n active,\n size = 'default',\n shape = 'circle',\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const dim = typeof size === 'number' ? size : AVATAR_SIZE_MAP[size];\n\n return (\n <span\n className={cn(\n 'ald-skeleton-avatar tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: dim,\n height: dim,\n borderRadius: shape === 'circle' ? '50%' : '4px',\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonInput: React.FC<SkeletonInputProps> = ({\n active,\n size = 'default',\n block,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const height = INPUT_SIZE_MAP[size];\n\n return (\n <span\n className={cn(\n 'ald-skeleton-input tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n block && 'tw-block tw-w-full',\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: block ? undefined : 200,\n height,\n borderRadius: 4,\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonImage: React.FC<SkeletonImageProps> = ({\n active,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n\n return (\n <span\n className={cn(\n 'ald-skeleton-image tw-flex tw-items-center tw-justify-center tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: 96,\n height: 96,\n borderRadius: 4,\n ...style,\n }}\n >\n <svg\n viewBox=\"0 0 1098 1024\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"48\"\n height=\"48\"\n fill=\"currentColor\"\n style={{ opacity: 0.2 }}\n >\n <path d=\"M365.714 329.143q0 45.714-32.036 77.75t-77.75 32.036-77.75-32.036-32.036-77.75 32.036-77.75 77.75-32.036 77.75 32.036 32.036 77.75zM950.857 548.571v256H146.286V694.857l182.857-182.857 91.429 91.429 292.571-292.571zM1005.714 146.286H91.429q-7.46 0-12.873 5.413T73.143 164.571v694.857q0 7.46 5.413 12.873t12.873 5.413h914.286q7.46 0 12.873-5.413t5.413-12.873V164.571q0-7.46-5.413-12.873t-12.873-5.413zm91.429 18.286v694.857q0 37.714-26.857 64.571t-64.571 26.857H91.429q-37.714 0-64.571-26.857T0 859.429V164.571q0-37.714 26.857-64.571T91.429 73.143h914.286q37.714 0 64.571 26.857t26.857 64.571z\" />\n </svg>\n </span>\n );\n};\n\n// --- Main Skeleton component ---\n\nfunction Skeleton(props: SkeletonProps) {\n const {\n active = false,\n loading = true,\n className,\n style,\n children,\n avatar,\n title = true,\n paragraph = true,\n round,\n } = props;\n\n if (!loading) {\n return <>{children}</>;\n }\n\n const animClass = active ? 'tw-animate-pulse' : '';\n const rows =\n typeof paragraph === 'object' ? paragraph.rows || 3 : paragraph ? 3 : 0;\n\n return (\n <div\n className={cn('ald-skeleton tw-flex tw-gap-4', className)}\n style={style}\n >\n {avatar && (\n <div\n className={cn(\n 'ald-skeleton-avatar tw-shrink-0 tw-rounded-full tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n typeof avatar === 'object' && avatar.shape === 'square'\n ? 'tw-rounded-r-50'\n : 'tw-rounded-full',\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: 40,\n height: 40,\n }}\n />\n )}\n <div className=\"ald-skeleton-content tw-flex-1\">\n {title && (\n <div\n className={cn(\n 'ald-skeleton-title tw-mb-4 tw-h-4 tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n round ? 'tw-rounded-full' : 'tw-rounded-r-25',\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: typeof title === 'object' ? title.width : '38%',\n }}\n />\n )}\n {paragraph &&\n Array.from({ length: rows }).map((_, i) => (\n <div\n key={i}\n className={cn(\n 'ald-skeleton-paragraph tw-mb-3 tw-h-4 tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n round ? 'tw-rounded-full' : 'tw-rounded-r-25',\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: i === rows - 1 ? '61%' : '100%',\n }}\n />\n ))}\n </div>\n </div>\n );\n}\n\nfunction SkeletonNode({\n active,\n className,\n style,\n children,\n}: {\n active?: boolean;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n}) {\n return (\n <div\n className={cn(\n 'ald-skeleton-node tw-inline-flex tw-items-center tw-justify-center tw-rounded-r-25 tw-bg-[var(--background-neutral-subtle)]',\n active && 'tw-animate-pulse',\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n ...style,\n }}\n >\n {children}\n </div>\n );\n}\n\n// Attach sub-components\nSkeleton.Button = SkeletonButton;\nSkeleton.Avatar = SkeletonAvatar;\nSkeleton.Input = SkeletonInput;\nSkeleton.Image = SkeletonImage;\nSkeleton.Node = SkeletonNode;\n\nexport default Skeleton;\n"],"mappings":"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"}
|
package/dist/Tabs/index.js
CHANGED
|
@@ -99,7 +99,7 @@ function Tabs(props) {
|
|
|
99
99
|
"--tabs-padding": `${paddingVal}px`
|
|
100
100
|
},
|
|
101
101
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
102
|
-
className: cn("ald-tabs-nav ant-tabs-nav tw-flex tw-items-center", isTop && "tw-mb-5", isBottom && "tw-mt-5", isTop && hasDividing && "tw-border-0 tw-border-b tw-border-solid tw-border-b-[var(--global-cool-grey-100)]", isBottom && hasDividing && "tw-border-0 tw-border-t tw-border-solid tw-border-t-[var(--global-cool-grey-100)]", isTop && compact && "!tw-mb-0", isBottom && compact && "!tw-mt-0", isLeft && "tw-flex-col tw-border-0 tw-border-r tw-border-solid tw-border-r-[var(--global-cool-grey-100)]", isRight && "tw-flex-col tw-border-0 tw-border-l tw-border-solid tw-border-l-[var(--global-cool-grey-100)]"),
|
|
102
|
+
className: cn("ald-tabs-nav ant-tabs-nav tw-flex tw-items-center", isVertical && "tw-shrink-0", isTop && "tw-mb-5", isBottom && "tw-mt-5", isTop && hasDividing && "tw-border-0 tw-border-b tw-border-solid tw-border-b-[var(--global-cool-grey-100)]", isBottom && hasDividing && "tw-border-0 tw-border-t tw-border-solid tw-border-t-[var(--global-cool-grey-100)]", isTop && compact && "!tw-mb-0", isBottom && compact && "!tw-mt-0", isLeft && "tw-flex-col tw-border-0 tw-border-r tw-border-solid tw-border-r-[var(--global-cool-grey-100)]", isRight && "tw-flex-col tw-border-0 tw-border-l tw-border-solid tw-border-l-[var(--global-cool-grey-100)]"),
|
|
103
103
|
style: headerBackgroundColor || tabBarStyle ? {
|
|
104
104
|
...tabBarStyle,
|
|
105
105
|
...headerBackgroundColor ? { backgroundColor: headerBackgroundColor } : {}
|
|
@@ -114,11 +114,11 @@ function Tabs(props) {
|
|
|
114
114
|
children: /* @__PURE__ */ jsx(Memo, { size: 16 })
|
|
115
115
|
}),
|
|
116
116
|
/* @__PURE__ */ jsx("div", {
|
|
117
|
-
className: "ald-tabs-nav-wrap ant-tabs-nav-wrap tw-min-w-0 tw-flex-1",
|
|
117
|
+
className: cn("ald-tabs-nav-wrap ant-tabs-nav-wrap", isVertical ? "tw-w-full tw-shrink-0" : "tw-min-w-0 tw-flex-1"),
|
|
118
118
|
style: paddingVal ? { margin: `0 ${paddingVal}px` } : void 0,
|
|
119
119
|
children: /* @__PURE__ */ jsx("div", {
|
|
120
120
|
ref: navListRef,
|
|
121
|
-
className: cn("ald-tabs-nav-list ant-tabs-nav-list tw-flex tw-overflow-hidden", isVertical && "tw-flex-col", centered && !isVertical && "tw-justify-center", monospace && "[&>*]:tw-flex-1", isCard ? "tw-gap-1" : !monospace && "tw-gap-8"),
|
|
121
|
+
className: cn("ald-tabs-nav-list ant-tabs-nav-list tw-flex tw-overflow-hidden", isVertical && "tw-w-full tw-shrink-0 tw-flex-col", centered && !isVertical && "tw-justify-center", monospace && "[&>*]:tw-flex-1", isCard ? "tw-gap-1" : !monospace && "tw-gap-8"),
|
|
122
122
|
style: !isVertical ? {
|
|
123
123
|
scrollbarWidth: "none",
|
|
124
124
|
msOverflowStyle: "none"
|
|
@@ -127,7 +127,7 @@ function Tabs(props) {
|
|
|
127
127
|
const isActive = activeKey === item.key;
|
|
128
128
|
const showClose = isEditable && item.closable !== false;
|
|
129
129
|
return /* @__PURE__ */ jsxs("div", {
|
|
130
|
-
className: cn("ald-tabs-tab ant-tabs-tab tw-relative tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-gap-2 tw-whitespace-nowrap tw-transition-colors", isCard ? cn("tw-h-10 tw-rounded-t-[6px] tw-border tw-border-b-0 tw-border-solid tw-px-4 tw-text-sm tw-leading-5", "tw-gap-sp-75", isActive ? "tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--background-default)] tw-font-medium tw-text-[var(--alias-colors-text-selected)]" : "tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--alias-colors-bg-skeleton-subtler)] tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit") : cn(size === "small" ? "tw-py-2 tw-text-xs tw-leading-4" : "tw-py-2.5 tw-text-sm tw-leading-5", monospace && "tw-justify-center", isActive ? "tw-font-medium tw-text-[var(--alias-colors-text-selected)]" : "tw-font-medium tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit"), item.disabled && "tw-pointer-events-none tw-cursor-default tw-opacity-50"),
|
|
130
|
+
className: cn("ald-tabs-tab ant-tabs-tab tw-relative tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-gap-2 tw-whitespace-nowrap tw-transition-colors", isVertical && "tw-w-full", isCard ? cn("tw-h-10 tw-rounded-t-[6px] tw-border tw-border-b-0 tw-border-solid tw-px-4 tw-text-sm tw-leading-5", "tw-gap-sp-75", isActive ? "tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--background-default)] tw-font-medium tw-text-[var(--alias-colors-text-selected)]" : "tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--alias-colors-bg-skeleton-subtler)] tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit") : cn(size === "small" ? "tw-py-2 tw-text-xs tw-leading-4" : "tw-py-2.5 tw-text-sm tw-leading-5", monospace && "tw-justify-center", isActive ? "tw-font-medium tw-text-[var(--alias-colors-text-selected)]" : "tw-font-medium tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit"), item.disabled && "tw-pointer-events-none tw-cursor-default tw-opacity-50"),
|
|
131
131
|
onClick: item.disabled ? void 0 : (e) => handleTabClick(item.key, e),
|
|
132
132
|
children: [
|
|
133
133
|
item.icon,
|
package/dist/Tabs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/Tabs/index.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { cn } from '../lib/utils';\nimport { ChevronLeftLine, ChevronRightLine, CloseLightLine } from '../Icon';\nimport TabPane from './TabPane';\n\nexport type TabsSize = 'default' | 'small';\n\ninterface TabItem {\n key: string;\n label: React.ReactNode;\n children?: React.ReactNode;\n disabled?: boolean;\n closable?: boolean;\n icon?: React.ReactNode;\n forceRender?: boolean;\n className?: string;\n}\n\nexport interface ITabsProps {\n size?: TabsSize;\n activeKey?: string;\n defaultActiveKey?: string;\n onChange?: (activeKey: string) => void;\n onTabClick?: (activeKey: string, e: React.MouseEvent) => void;\n destroyInactiveTabPane?: boolean;\n centered?: boolean;\n adaptHeight?: boolean;\n tabPosition?: 'left' | 'right' | 'top' | 'bottom';\n className?: string;\n children?: React.ReactNode;\n headerBackgroundColor?: string;\n monospace?: boolean;\n padding?: boolean | number;\n compact?: boolean;\n hasDividing?: boolean;\n items?: TabItem[];\n type?: 'line' | 'card' | 'editable-card';\n tabBarExtraContent?:\n | React.ReactNode\n | { left?: React.ReactNode; right?: React.ReactNode };\n onEdit?: (\n targetKey: string | React.MouseEvent | React.KeyboardEvent,\n action: 'add' | 'remove',\n ) => void;\n hideAdd?: boolean;\n style?: React.CSSProperties;\n tabBarStyle?: React.CSSProperties;\n popupClassName?: string;\n tabBarGutter?: number;\n moreIcon?: React.ReactNode;\n /** 透传到 Tabs 根容器的 data-testid,用于自动化测试定位 */\n 'data-testid'?: string;\n /** 透传到 Tabs 根容器的 aria-label,用于可访问性与自动化测试定位 */\n 'aria-label'?: string;\n}\n\nexport default function Tabs(props: ITabsProps) {\n const {\n size,\n className,\n adaptHeight,\n style = {},\n monospace: propsMonospace,\n tabPosition = 'top',\n padding: propsPadding = false,\n compact,\n hasDividing = true,\n items,\n activeKey: controlledActiveKey,\n defaultActiveKey,\n onChange,\n onTabClick,\n destroyInactiveTabPane,\n centered,\n tabBarExtraContent,\n headerBackgroundColor,\n children,\n type,\n onEdit,\n hideAdd,\n tabBarStyle,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n } = props;\n\n const isEditable = type === 'editable-card';\n const isCard = type === 'card' || type === 'editable-card';\n\n // Derive items from children if not provided\n const resolvedItems: TabItem[] = useMemo(() => {\n if (items) return items;\n return React.Children.toArray(children)\n .filter(React.isValidElement)\n .map((child: any) => ({\n key: child.key || child.props.key || '',\n label: child.props.tab,\n children: child.props.children,\n disabled: child.props.disabled,\n closable: child.props.closable,\n forceRender: child.props.forceRender,\n }));\n }, [items, children]);\n\n const firstKey = resolvedItems[0]?.key || '';\n const [innerActiveKey, setInnerActiveKey] = useState(\n defaultActiveKey || firstKey,\n );\n const mergedActiveKey =\n controlledActiveKey !== undefined ? controlledActiveKey : innerActiveKey;\n const activeKey = resolvedItems.some((item) => item.key === mergedActiveKey)\n ? mergedActiveKey\n : firstKey;\n\n const handleTabClick = (key: string, e: React.MouseEvent) => {\n if (controlledActiveKey === undefined) {\n setInnerActiveKey(key);\n }\n onChange?.(key);\n onTabClick?.(key, e);\n };\n\n const handleRemove = (key: string, e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(key, 'remove');\n };\n\n const handleAdd = (e: React.MouseEvent) => {\n onEdit?.(e, 'add');\n };\n\n const monospace = tabPosition !== 'top' ? false : propsMonospace;\n const paddingVal = useMemo(() => {\n if (tabPosition !== 'top') return 0;\n if (typeof propsPadding === 'number') return propsPadding;\n if (typeof propsPadding === 'boolean' && propsPadding) return 20;\n return 0;\n }, [propsPadding, tabPosition]);\n\n const isTop = tabPosition === 'top';\n const isBottom = tabPosition === 'bottom';\n const isLeft = tabPosition === 'left';\n const isRight = tabPosition === 'right';\n const isVertical = tabPosition === 'left' || tabPosition === 'right';\n const rootDirectionClass = isRight\n ? 'tw-flex-row-reverse'\n : isLeft\n ? 'tw-flex-row'\n : isBottom\n ? 'tw-flex-col-reverse'\n : 'tw-flex-col';\n\n const extraLeft =\n tabBarExtraContent &&\n typeof tabBarExtraContent === 'object' &&\n 'left' in tabBarExtraContent\n ? tabBarExtraContent.left\n : null;\n const extraRight = tabBarExtraContent\n ? typeof tabBarExtraContent === 'object' && 'right' in tabBarExtraContent\n ? tabBarExtraContent.right\n : React.isValidElement(tabBarExtraContent)\n ? tabBarExtraContent\n : null\n : null;\n\n // Scroll state for overflow\n const navListRef = useRef<HTMLDivElement>(null);\n const [canScrollLeft, setCanScrollLeft] = useState(false);\n const [canScrollRight, setCanScrollRight] = useState(false);\n\n const checkScroll = useCallback(() => {\n const el = navListRef.current;\n if (!el || isVertical) {\n setCanScrollLeft(false);\n setCanScrollRight(false);\n return;\n }\n const { scrollLeft, scrollWidth, clientWidth } = el;\n setCanScrollLeft(scrollLeft > 1);\n setCanScrollRight(scrollLeft + clientWidth < scrollWidth - 1);\n }, [isVertical]);\n\n useEffect(() => {\n checkScroll();\n const el = navListRef.current;\n if (!el) return;\n // Use ResizeObserver to detect size changes\n let ro: ResizeObserver | undefined;\n if (typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(() => checkScroll());\n ro.observe(el);\n }\n el.addEventListener('scroll', checkScroll, { passive: true });\n return () => {\n el.removeEventListener('scroll', checkScroll);\n ro?.disconnect();\n };\n }, [checkScroll, resolvedItems.length]);\n\n const scrollBy = (delta: number) => {\n const el = navListRef.current;\n if (el) {\n el.scrollBy({ left: delta, behavior: 'smooth' });\n }\n };\n\n const showScrollButtons = canScrollLeft || canScrollRight;\n\n return (\n <div\n data-testid={dataTestId}\n aria-label={ariaLabel}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs ant-tabs tw-flex',\n rootDirectionClass,\n adaptHeight && 'ald-adapt-height tw-h-full',\n size !== 'small' && 'ald-tabs-default',\n monospace && 'ald-tabs-monospace',\n compact && 'ald-tabs-compact',\n !hasDividing && 'ald-tabs-no-dividing',\n className,\n )}\n style={\n {\n ...style,\n '--header-bg-color': headerBackgroundColor,\n '--tabs-padding': `${paddingVal}px`,\n } as React.CSSProperties\n }\n >\n {/* Tab nav */}\n <div\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav ant-tabs-nav tw-flex tw-items-center',\n isTop && 'tw-mb-5',\n isBottom && 'tw-mt-5',\n isTop &&\n hasDividing &&\n 'tw-border-0 tw-border-b tw-border-solid tw-border-b-[var(--global-cool-grey-100)]',\n isBottom &&\n hasDividing &&\n 'tw-border-0 tw-border-t tw-border-solid tw-border-t-[var(--global-cool-grey-100)]',\n isTop && compact && '!tw-mb-0',\n isBottom && compact && '!tw-mt-0',\n isLeft &&\n 'tw-flex-col tw-border-0 tw-border-r tw-border-solid tw-border-r-[var(--global-cool-grey-100)]',\n isRight &&\n 'tw-flex-col tw-border-0 tw-border-l tw-border-solid tw-border-l-[var(--global-cool-grey-100)]',\n )}\n style={\n headerBackgroundColor || tabBarStyle\n ? {\n ...tabBarStyle,\n ...(headerBackgroundColor\n ? { backgroundColor: headerBackgroundColor }\n : {}),\n }\n : undefined\n }\n >\n {extraLeft}\n\n {/* Scroll left button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-transparent tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollLeft && 'tw-invisible',\n )}\n onClick={() => scrollBy(-200)}\n aria-label=\"Scroll tabs left\"\n >\n <ChevronLeftLine size={16} />\n </button>\n )}\n\n <div\n className=\"ald-tabs-nav-wrap ant-tabs-nav-wrap tw-min-w-0 tw-flex-1\"\n style={paddingVal ? { margin: `0 ${paddingVal}px` } : undefined}\n >\n <div\n ref={navListRef}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav-list ant-tabs-nav-list tw-flex tw-overflow-hidden',\n isVertical && 'tw-flex-col',\n centered && !isVertical && 'tw-justify-center',\n monospace && '[&>*]:tw-flex-1',\n isCard ? 'tw-gap-1' : !monospace && 'tw-gap-8',\n )}\n style={\n !isVertical\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = activeKey === item.key;\n // For editable-card, closable defaults to true unless explicitly set to false\n const showClose = isEditable && item.closable !== false;\n\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tab ant-tabs-tab tw-relative tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-gap-2 tw-whitespace-nowrap tw-transition-colors',\n // Card / editable-card styling\n isCard\n ? cn(\n 'tw-h-10 tw-rounded-t-[6px] tw-border tw-border-b-0 tw-border-solid tw-px-4 tw-text-sm tw-leading-5',\n 'tw-gap-sp-75',\n isActive\n ? 'tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--background-default)] tw-font-medium tw-text-[var(--alias-colors-text-selected)]'\n : 'tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--alias-colors-bg-skeleton-subtler)] tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit',\n )\n : cn(\n size === 'small'\n ? 'tw-py-2 tw-text-xs tw-leading-4'\n : 'tw-py-2.5 tw-text-sm tw-leading-5',\n monospace && 'tw-justify-center',\n isActive\n ? 'tw-font-medium tw-text-[var(--alias-colors-text-selected)]'\n : 'tw-font-medium tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit',\n ),\n item.disabled &&\n 'tw-pointer-events-none tw-cursor-default tw-opacity-50',\n )}\n onClick={\n item.disabled\n ? undefined\n : (e) => handleTabClick(item.key, e)\n }\n >\n {item.icon}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <span className=\"ant-tabs-tab-btn\">{item.label}</span>\n {/* Close button for editable-card */}\n {showClose && (\n <span\n className=\"ald-tabs-tab-remove tw-m-0 tw-grid tw-size-4 tw-cursor-pointer tw-place-items-center tw-p-0 tw-text-[var(--alias-colors-icon-subtle)] tw-transition-colors hover:tw-text-[var(--alias-colors-text-default)]\"\n onClick={(e) => handleRemove(item.key, e)}\n aria-label={`Remove ${item.label}`}\n >\n <CloseLightLine size={12} />\n </span>\n )}\n {/* Active indicator for non-card line tabs */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n {!isCard && isActive && isTop && (\n <div className=\"ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--bottom-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n {!isCard && isActive && isBottom && (\n <div className=\"ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--top-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n {!isCard && isActive && isLeft && (\n <div className=\"tw-absolute tw-inset-y-0 tw--right-px tw-w-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n {!isCard && isActive && isRight && (\n <div className=\"tw-absolute tw-inset-y-0 tw--left-px tw-w-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n </div>\n );\n })}\n </div>\n </div>\n\n {/* Scroll right button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-transparent tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollRight && 'tw-invisible',\n )}\n onClick={() => scrollBy(200)}\n aria-label=\"Scroll tabs right\"\n >\n <ChevronRightLine size={16} />\n </button>\n )}\n\n {/* Add button for editable-card */}\n {isEditable && !hideAdd && (\n <button\n type=\"button\"\n className=\"ald-tabs-nav-add tw-ml-1 tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-justify-center tw-rounded tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-px-2 tw-py-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]\"\n onClick={handleAdd}\n aria-label=\"Add tab\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n </button>\n )}\n\n {extraRight}\n </div>\n\n {/* Tab content */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <div\n className={cn(\n 'ald-tabs-content ant-tabs-content ant-tabs-content-holder tw-min-h-0 tw-flex-1',\n adaptHeight && 'tw-h-full',\n )}\n style={\n paddingVal\n ? { padding: `0 ${paddingVal}px ${paddingVal}px` }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = item.key === activeKey;\n if (!isActive && destroyInactiveTabPane && !item.forceRender) {\n return null;\n }\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tabpane ant-tabs-tabpane',\n // v2 行为:adaptHeight 时 tabpane 撑满内容区,子元素的百分比高度才能解析\n adaptHeight && 'tw-h-full tw-overflow-y-auto',\n isActive ? 'ant-tabs-tabpane-active tw-block' : 'tw-hidden',\n )}\n role=\"tabpanel\"\n >\n {item.children}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nTabs.TabPane = TabPane;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/Tabs/index.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { cn } from '../lib/utils';\nimport { ChevronLeftLine, ChevronRightLine, CloseLightLine } from '../Icon';\nimport TabPane from './TabPane';\n\nexport type TabsSize = 'default' | 'small';\n\ninterface TabItem {\n key: string;\n label: React.ReactNode;\n children?: React.ReactNode;\n disabled?: boolean;\n closable?: boolean;\n icon?: React.ReactNode;\n forceRender?: boolean;\n className?: string;\n}\n\nexport interface ITabsProps {\n size?: TabsSize;\n activeKey?: string;\n defaultActiveKey?: string;\n onChange?: (activeKey: string) => void;\n onTabClick?: (activeKey: string, e: React.MouseEvent) => void;\n destroyInactiveTabPane?: boolean;\n centered?: boolean;\n adaptHeight?: boolean;\n tabPosition?: 'left' | 'right' | 'top' | 'bottom';\n className?: string;\n children?: React.ReactNode;\n headerBackgroundColor?: string;\n monospace?: boolean;\n padding?: boolean | number;\n compact?: boolean;\n hasDividing?: boolean;\n items?: TabItem[];\n type?: 'line' | 'card' | 'editable-card';\n tabBarExtraContent?:\n | React.ReactNode\n | { left?: React.ReactNode; right?: React.ReactNode };\n onEdit?: (\n targetKey: string | React.MouseEvent | React.KeyboardEvent,\n action: 'add' | 'remove',\n ) => void;\n hideAdd?: boolean;\n style?: React.CSSProperties;\n tabBarStyle?: React.CSSProperties;\n popupClassName?: string;\n tabBarGutter?: number;\n moreIcon?: React.ReactNode;\n /** 透传到 Tabs 根容器的 data-testid,用于自动化测试定位 */\n 'data-testid'?: string;\n /** 透传到 Tabs 根容器的 aria-label,用于可访问性与自动化测试定位 */\n 'aria-label'?: string;\n}\n\nexport default function Tabs(props: ITabsProps) {\n const {\n size,\n className,\n adaptHeight,\n style = {},\n monospace: propsMonospace,\n tabPosition = 'top',\n padding: propsPadding = false,\n compact,\n hasDividing = true,\n items,\n activeKey: controlledActiveKey,\n defaultActiveKey,\n onChange,\n onTabClick,\n destroyInactiveTabPane,\n centered,\n tabBarExtraContent,\n headerBackgroundColor,\n children,\n type,\n onEdit,\n hideAdd,\n tabBarStyle,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n } = props;\n\n const isEditable = type === 'editable-card';\n const isCard = type === 'card' || type === 'editable-card';\n\n // Derive items from children if not provided\n const resolvedItems: TabItem[] = useMemo(() => {\n if (items) return items;\n return React.Children.toArray(children)\n .filter(React.isValidElement)\n .map((child: any) => ({\n key: child.key || child.props.key || '',\n label: child.props.tab,\n children: child.props.children,\n disabled: child.props.disabled,\n closable: child.props.closable,\n forceRender: child.props.forceRender,\n }));\n }, [items, children]);\n\n const firstKey = resolvedItems[0]?.key || '';\n const [innerActiveKey, setInnerActiveKey] = useState(\n defaultActiveKey || firstKey,\n );\n const mergedActiveKey =\n controlledActiveKey !== undefined ? controlledActiveKey : innerActiveKey;\n const activeKey = resolvedItems.some((item) => item.key === mergedActiveKey)\n ? mergedActiveKey\n : firstKey;\n\n const handleTabClick = (key: string, e: React.MouseEvent) => {\n if (controlledActiveKey === undefined) {\n setInnerActiveKey(key);\n }\n onChange?.(key);\n onTabClick?.(key, e);\n };\n\n const handleRemove = (key: string, e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(key, 'remove');\n };\n\n const handleAdd = (e: React.MouseEvent) => {\n onEdit?.(e, 'add');\n };\n\n const monospace = tabPosition !== 'top' ? false : propsMonospace;\n const paddingVal = useMemo(() => {\n if (tabPosition !== 'top') return 0;\n if (typeof propsPadding === 'number') return propsPadding;\n if (typeof propsPadding === 'boolean' && propsPadding) return 20;\n return 0;\n }, [propsPadding, tabPosition]);\n\n const isTop = tabPosition === 'top';\n const isBottom = tabPosition === 'bottom';\n const isLeft = tabPosition === 'left';\n const isRight = tabPosition === 'right';\n const isVertical = tabPosition === 'left' || tabPosition === 'right';\n const rootDirectionClass = isRight\n ? 'tw-flex-row-reverse'\n : isLeft\n ? 'tw-flex-row'\n : isBottom\n ? 'tw-flex-col-reverse'\n : 'tw-flex-col';\n\n const extraLeft =\n tabBarExtraContent &&\n typeof tabBarExtraContent === 'object' &&\n 'left' in tabBarExtraContent\n ? tabBarExtraContent.left\n : null;\n const extraRight = tabBarExtraContent\n ? typeof tabBarExtraContent === 'object' && 'right' in tabBarExtraContent\n ? tabBarExtraContent.right\n : React.isValidElement(tabBarExtraContent)\n ? tabBarExtraContent\n : null\n : null;\n\n // Scroll state for overflow\n const navListRef = useRef<HTMLDivElement>(null);\n const [canScrollLeft, setCanScrollLeft] = useState(false);\n const [canScrollRight, setCanScrollRight] = useState(false);\n\n const checkScroll = useCallback(() => {\n const el = navListRef.current;\n if (!el || isVertical) {\n setCanScrollLeft(false);\n setCanScrollRight(false);\n return;\n }\n const { scrollLeft, scrollWidth, clientWidth } = el;\n setCanScrollLeft(scrollLeft > 1);\n setCanScrollRight(scrollLeft + clientWidth < scrollWidth - 1);\n }, [isVertical]);\n\n useEffect(() => {\n checkScroll();\n const el = navListRef.current;\n if (!el) return;\n // Use ResizeObserver to detect size changes\n let ro: ResizeObserver | undefined;\n if (typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(() => checkScroll());\n ro.observe(el);\n }\n el.addEventListener('scroll', checkScroll, { passive: true });\n return () => {\n el.removeEventListener('scroll', checkScroll);\n ro?.disconnect();\n };\n }, [checkScroll, resolvedItems.length]);\n\n const scrollBy = (delta: number) => {\n const el = navListRef.current;\n if (el) {\n el.scrollBy({ left: delta, behavior: 'smooth' });\n }\n };\n\n const showScrollButtons = canScrollLeft || canScrollRight;\n\n return (\n <div\n data-testid={dataTestId}\n aria-label={ariaLabel}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs ant-tabs tw-flex',\n rootDirectionClass,\n adaptHeight && 'ald-adapt-height tw-h-full',\n size !== 'small' && 'ald-tabs-default',\n monospace && 'ald-tabs-monospace',\n compact && 'ald-tabs-compact',\n !hasDividing && 'ald-tabs-no-dividing',\n className,\n )}\n style={\n {\n ...style,\n '--header-bg-color': headerBackgroundColor,\n '--tabs-padding': `${paddingVal}px`,\n } as React.CSSProperties\n }\n >\n {/* Tab nav */}\n <div\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav ant-tabs-nav tw-flex tw-items-center',\n isVertical && 'tw-shrink-0',\n isTop && 'tw-mb-5',\n isBottom && 'tw-mt-5',\n isTop &&\n hasDividing &&\n 'tw-border-0 tw-border-b tw-border-solid tw-border-b-[var(--global-cool-grey-100)]',\n isBottom &&\n hasDividing &&\n 'tw-border-0 tw-border-t tw-border-solid tw-border-t-[var(--global-cool-grey-100)]',\n isTop && compact && '!tw-mb-0',\n isBottom && compact && '!tw-mt-0',\n isLeft &&\n 'tw-flex-col tw-border-0 tw-border-r tw-border-solid tw-border-r-[var(--global-cool-grey-100)]',\n isRight &&\n 'tw-flex-col tw-border-0 tw-border-l tw-border-solid tw-border-l-[var(--global-cool-grey-100)]',\n )}\n style={\n headerBackgroundColor || tabBarStyle\n ? {\n ...tabBarStyle,\n ...(headerBackgroundColor\n ? { backgroundColor: headerBackgroundColor }\n : {}),\n }\n : undefined\n }\n >\n {extraLeft}\n\n {/* Scroll left button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-transparent tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollLeft && 'tw-invisible',\n )}\n onClick={() => scrollBy(-200)}\n aria-label=\"Scroll tabs left\"\n >\n <ChevronLeftLine size={16} />\n </button>\n )}\n\n <div\n className={cn(\n 'ald-tabs-nav-wrap ant-tabs-nav-wrap',\n isVertical ? 'tw-w-full tw-shrink-0' : 'tw-min-w-0 tw-flex-1',\n )}\n style={paddingVal ? { margin: `0 ${paddingVal}px` } : undefined}\n >\n <div\n ref={navListRef}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav-list ant-tabs-nav-list tw-flex tw-overflow-hidden',\n isVertical && 'tw-w-full tw-shrink-0 tw-flex-col',\n centered && !isVertical && 'tw-justify-center',\n monospace && '[&>*]:tw-flex-1',\n isCard ? 'tw-gap-1' : !monospace && 'tw-gap-8',\n )}\n style={\n !isVertical\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = activeKey === item.key;\n // For editable-card, closable defaults to true unless explicitly set to false\n const showClose = isEditable && item.closable !== false;\n\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tab ant-tabs-tab tw-relative tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-gap-2 tw-whitespace-nowrap tw-transition-colors',\n isVertical && 'tw-w-full',\n // Card / editable-card styling\n isCard\n ? cn(\n 'tw-h-10 tw-rounded-t-[6px] tw-border tw-border-b-0 tw-border-solid tw-px-4 tw-text-sm tw-leading-5',\n 'tw-gap-sp-75',\n isActive\n ? 'tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--background-default)] tw-font-medium tw-text-[var(--alias-colors-text-selected)]'\n : 'tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--alias-colors-bg-skeleton-subtler)] tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit',\n )\n : cn(\n size === 'small'\n ? 'tw-py-2 tw-text-xs tw-leading-4'\n : 'tw-py-2.5 tw-text-sm tw-leading-5',\n monospace && 'tw-justify-center',\n isActive\n ? 'tw-font-medium tw-text-[var(--alias-colors-text-selected)]'\n : 'tw-font-medium tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit',\n ),\n item.disabled &&\n 'tw-pointer-events-none tw-cursor-default tw-opacity-50',\n )}\n onClick={\n item.disabled\n ? undefined\n : (e) => handleTabClick(item.key, e)\n }\n >\n {item.icon}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <span className=\"ant-tabs-tab-btn\">{item.label}</span>\n {/* Close button for editable-card */}\n {showClose && (\n <span\n className=\"ald-tabs-tab-remove tw-m-0 tw-grid tw-size-4 tw-cursor-pointer tw-place-items-center tw-p-0 tw-text-[var(--alias-colors-icon-subtle)] tw-transition-colors hover:tw-text-[var(--alias-colors-text-default)]\"\n onClick={(e) => handleRemove(item.key, e)}\n aria-label={`Remove ${item.label}`}\n >\n <CloseLightLine size={12} />\n </span>\n )}\n {/* Active indicator for non-card line tabs */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n {!isCard && isActive && isTop && (\n <div className=\"ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--bottom-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n {!isCard && isActive && isBottom && (\n <div className=\"ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--top-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n {!isCard && isActive && isLeft && (\n <div className=\"tw-absolute tw-inset-y-0 tw--right-px tw-w-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n {!isCard && isActive && isRight && (\n <div className=\"tw-absolute tw-inset-y-0 tw--left-px tw-w-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n </div>\n );\n })}\n </div>\n </div>\n\n {/* Scroll right button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-transparent tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollRight && 'tw-invisible',\n )}\n onClick={() => scrollBy(200)}\n aria-label=\"Scroll tabs right\"\n >\n <ChevronRightLine size={16} />\n </button>\n )}\n\n {/* Add button for editable-card */}\n {isEditable && !hideAdd && (\n <button\n type=\"button\"\n className=\"ald-tabs-nav-add tw-ml-1 tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-justify-center tw-rounded tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-px-2 tw-py-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]\"\n onClick={handleAdd}\n aria-label=\"Add tab\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n </button>\n )}\n\n {extraRight}\n </div>\n\n {/* Tab content */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <div\n className={cn(\n 'ald-tabs-content ant-tabs-content ant-tabs-content-holder tw-min-h-0 tw-flex-1',\n adaptHeight && 'tw-h-full',\n )}\n style={\n paddingVal\n ? { padding: `0 ${paddingVal}px ${paddingVal}px` }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = item.key === activeKey;\n if (!isActive && destroyInactiveTabPane && !item.forceRender) {\n return null;\n }\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tabpane ant-tabs-tabpane',\n // v2 行为:adaptHeight 时 tabpane 撑满内容区,子元素的百分比高度才能解析\n adaptHeight && 'tw-h-full tw-overflow-y-auto',\n isActive ? 'ant-tabs-tabpane-active tw-block' : 'tw-hidden',\n )}\n role=\"tabpanel\"\n >\n {item.children}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nTabs.TabPane = TabPane;\n"],"mappings":"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"}
|