@aloudata/aloudata-design 3.0.27 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AProgress/index.js +10 -0
- package/dist/AProgress/index.js.map +1 -1
- package/dist/Alert/index.js +3 -1
- package/dist/Alert/index.js.map +1 -1
- package/dist/Badge/index.js +37 -11
- package/dist/Badge/index.js.map +1 -1
- package/dist/Breadcrumb/index.js +12 -2
- package/dist/Breadcrumb/index.js.map +1 -1
- package/dist/Button/index.d.ts +1 -1
- package/dist/Button/index.js +29 -9
- package/dist/Button/index.js.map +1 -1
- package/dist/Card/index.js +1 -1
- package/dist/Card/index.js.map +1 -1
- package/dist/Carousel/index.js +9 -1
- package/dist/Carousel/index.js.map +1 -1
- package/dist/Checkbox/index.js +25 -4
- package/dist/Checkbox/index.js.map +1 -1
- package/dist/Checkbox/type.d.ts +10 -2
- package/dist/Collapse/index.js +68 -22
- package/dist/Collapse/index.js.map +1 -1
- package/dist/ColorPicker/index.js +112 -46
- package/dist/ColorPicker/index.js.map +1 -1
- package/dist/DataPreviewTable/components/Body/Cell.d.ts +2 -0
- package/dist/DataPreviewTable/components/Body/Cell.js +9 -1
- package/dist/DataPreviewTable/components/Body/Cell.js.map +1 -1
- package/dist/DataPreviewTable/components/Body/index.d.ts +1 -0
- package/dist/DataPreviewTable/components/Body/index.js +35 -23
- package/dist/DataPreviewTable/components/Body/index.js.map +1 -1
- package/dist/DataPreviewTable/components/Header/index.d.ts +1 -0
- package/dist/DataPreviewTable/components/Header/index.js +36 -28
- package/dist/DataPreviewTable/components/Header/index.js.map +1 -1
- package/dist/DataPreviewTable/index.js +19 -2
- package/dist/DataPreviewTable/index.js.map +1 -1
- package/dist/Drawer/index.d.ts +4 -0
- package/dist/Drawer/index.js +91 -78
- package/dist/Drawer/index.js.map +1 -1
- package/dist/Dropdown/index.d.ts +1 -1
- package/dist/Dropdown/index.js +116 -98
- package/dist/Dropdown/index.js.map +1 -1
- package/dist/Form/FormItemContext.d.ts +1 -1
- package/dist/Form/FormItemContext.js.map +1 -1
- package/dist/Form/index.js +50 -7
- package/dist/Form/index.js.map +1 -1
- package/dist/IconButton/index.d.ts +2 -2
- package/dist/IconButton/index.js +9 -3
- package/dist/IconButton/index.js.map +1 -1
- package/dist/Input/components/Input/index.js +23 -7
- package/dist/Input/components/Input/index.js.map +1 -1
- package/dist/Input/components/TextArea/index.js +20 -2
- package/dist/Input/components/TextArea/index.js.map +1 -1
- package/dist/Input/privateSemanticOwner.d.ts +2 -0
- package/dist/Input/privateSemanticOwner.js +1 -0
- package/dist/InputNumber/index.js +19 -5
- package/dist/InputNumber/index.js.map +1 -1
- package/dist/InputNumber/type.d.ts +2 -2
- package/dist/LogicTree/components/LogicItem/index.d.ts +2 -1
- package/dist/LogicTree/components/LogicItem/index.js +13 -2
- package/dist/LogicTree/components/LogicItem/index.js.map +1 -1
- package/dist/LogicTree/index.js +2 -0
- package/dist/LogicTree/index.js.map +1 -1
- package/dist/MemberPicker/components/MemberSelection.d.ts +1 -0
- package/dist/MemberPicker/components/MemberSelection.js +83 -94
- package/dist/MemberPicker/components/MemberSelection.js.map +1 -1
- package/dist/MemberPicker/components/MultipleOption.js +12 -0
- package/dist/MemberPicker/components/MultipleOption.js.map +1 -1
- package/dist/MemberPicker/components/Panel.d.ts +1 -0
- package/dist/MemberPicker/components/Panel.js +4 -1
- package/dist/MemberPicker/components/Panel.js.map +1 -1
- package/dist/MemberPicker/components/SelectedMemberTags.js +14 -6
- package/dist/MemberPicker/components/SelectedMemberTags.js.map +1 -1
- package/dist/MemberPicker/components/SingleOption.js +12 -0
- package/dist/MemberPicker/components/SingleOption.js.map +1 -1
- package/dist/MemberPicker/components/UserGroupSelection.d.ts +2 -1
- package/dist/MemberPicker/components/UserGroupSelection.js +61 -48
- package/dist/MemberPicker/components/UserGroupSelection.js.map +1 -1
- package/dist/MemberPicker/index.js +134 -108
- package/dist/MemberPicker/index.js.map +1 -1
- package/dist/Menu/index.d.ts +8 -0
- package/dist/Menu/index.js +33 -3
- package/dist/Menu/index.js.map +1 -1
- package/dist/Modal/index.d.ts +4 -0
- package/dist/Modal/index.js +55 -66
- package/dist/Modal/index.js.map +1 -1
- package/dist/OverflowCount/index.js +10 -0
- package/dist/OverflowCount/index.js.map +1 -1
- package/dist/Pagination/PageSizeChanger.d.ts +1 -0
- package/dist/Pagination/PageSizeChanger.js +3 -2
- package/dist/Pagination/PageSizeChanger.js.map +1 -1
- package/dist/Pagination/index.js +34 -19
- package/dist/Pagination/index.js.map +1 -1
- package/dist/Pagination/types.d.ts +3 -0
- package/dist/Popconfirm/index.js +9 -1
- package/dist/Popconfirm/index.js.map +1 -1
- package/dist/Popover/index.js +52 -1
- package/dist/Popover/index.js.map +1 -1
- package/dist/Progress/index.js +4 -0
- package/dist/Progress/index.js.map +1 -1
- package/dist/Radio/components/Group/index.d.ts +5 -1
- package/dist/Radio/components/Group/index.js +7 -2
- package/dist/Radio/components/Group/index.js.map +1 -1
- package/dist/Radio/components/Radio/index.js +27 -1
- package/dist/Radio/components/Radio/index.js.map +1 -1
- package/dist/Radio/interface/radio.d.ts +7 -0
- package/dist/Radio/interface/radioGroup.d.ts +2 -0
- package/dist/RenameInput/index.js +11 -0
- package/dist/RenameInput/index.js.map +1 -1
- package/dist/Select/BaseSelect.d.ts +3 -0
- package/dist/Select/BaseSelect.js +235 -38
- package/dist/Select/BaseSelect.js.map +1 -1
- package/dist/Select/SelectTrigger.d.ts +2 -0
- package/dist/Select/SelectTrigger.js +13 -5
- package/dist/Select/SelectTrigger.js.map +1 -1
- package/dist/Select/Selector/FixedOverflow.d.ts +1 -0
- package/dist/Select/Selector/FixedOverflow.js +3 -3
- package/dist/Select/Selector/FixedOverflow.js.map +1 -1
- package/dist/Select/Selector/MultipleSelector.js +1 -0
- package/dist/Select/Selector/MultipleSelector.js.map +1 -1
- package/dist/Select/components/OptionCollection.d.ts +41 -0
- package/dist/Select/components/OptionCollection.js +124 -0
- package/dist/Select/components/OptionCollection.js.map +1 -0
- package/dist/Select/index.js +45 -3
- package/dist/Select/index.js.map +1 -1
- package/dist/Select/interface.d.ts +1 -1
- package/dist/Skeleton/index.js +1 -1
- package/dist/Skeleton/index.js.map +1 -1
- package/dist/Spin/index.d.ts +1 -1
- package/dist/Spin/index.js +22 -7
- package/dist/Spin/index.js.map +1 -1
- package/dist/Steps/index.js +66 -14
- package/dist/Steps/index.js.map +1 -1
- package/dist/Switch/index.d.ts +5 -0
- package/dist/Switch/index.js +22 -5
- package/dist/Switch/index.js.map +1 -1
- package/dist/Table/components/Cell.js +8 -3
- package/dist/Table/components/Cell.js.map +1 -1
- package/dist/Table/components/ExpandCell.js +6 -2
- package/dist/Table/components/ExpandCell.js.map +1 -1
- package/dist/Table/components/Footer/index.js +2 -1
- package/dist/Table/components/Footer/index.js.map +1 -1
- package/dist/Table/components/Header.js +25 -18
- package/dist/Table/components/Header.js.map +1 -1
- package/dist/Table/hooks/useRowSelection.js +14 -7
- package/dist/Table/hooks/useRowSelection.js.map +1 -1
- package/dist/Table/index.js +50 -29
- package/dist/Table/index.js.map +1 -1
- package/dist/Tabs/index.d.ts +1 -1
- package/dist/Tabs/index.js +92 -11
- package/dist/Tabs/index.js.map +1 -1
- package/dist/Tag/index.js +20 -1
- package/dist/Tag/index.js.map +1 -1
- package/dist/Tooltip/index.js +34 -5
- package/dist/Tooltip/index.js.map +1 -1
- package/dist/Tour/index.js +13 -1
- package/dist/Tour/index.js.map +1 -1
- package/dist/Tree/Tree2.js +2 -0
- package/dist/Tree/Tree2.js.map +1 -1
- package/dist/_utils/dialogAccessibility.d.ts +17 -0
- package/dist/_utils/dialogAccessibility.js +110 -0
- package/dist/_utils/dialogAccessibility.js.map +1 -0
- package/dist/_utils/formControlSemanticOwner.d.ts +3 -0
- package/dist/_utils/formControlSemanticOwner.js +17 -0
- package/dist/_utils/formControlSemanticOwner.js.map +1 -0
- package/dist/_utils/overlayCoordinator.js +1 -11
- package/dist/_utils/overlayCoordinator.js.map +1 -1
- package/dist/aloudata-design.css +1 -1
- package/dist/locale/default.d.ts +6 -0
- package/dist/locale/en_US.d.ts +6 -0
- package/dist/locale/en_US.js +6 -0
- package/dist/locale/en_US.js.map +1 -1
- package/dist/locale/zh_CN.d.ts +6 -0
- package/dist/locale/zh_CN.js +6 -0
- package/dist/locale/zh_CN.js.map +1 -1
- package/dist/theme/contract/baselineResolvedTokenValueManifest.d.ts +1 -1
- package/dist/theme/contract/controlStateColorArtifact.d.ts +73 -0
- package/dist/theme/contract/controlStateColorArtifact.js +2 -0
- package/dist/theme/contract/darkResolvedTokenValueManifest.d.ts +1 -1
- package/dist/theme/contract/focusRingArtifact.d.ts +51 -0
- package/dist/theme/contract/focusRingArtifact.js +2 -0
- package/dist/theme/contract/tokenOutputContract.d.ts +1 -1
- package/dist/theme/contract/tokenOutputContract.js +4 -0
- package/dist/theme/contract/tokenOutputContract.js.map +1 -1
- package/dist/theme/generator/acceptedColorValues.d.ts +2 -1
- package/dist/theme/generator/baselineTokenValueDelivery.d.ts +9 -1
- package/dist/theme/generator/minimalAcceptedColorValues.d.ts +2 -2
- package/dist/theme/generator/neutralSourceResolver.d.ts +28 -0
- package/dist/theme/generator/neutralSourceResolver.js +2 -0
- package/dist/theme/generator/neutralSourceValues.d.ts +27 -0
- package/dist/theme/generator/neutralSourceValues.js +2 -0
- package/dist/theme/index.d.ts +2 -0
- package/dist/theme/index.js +1 -0
- package/dist/theme/neutralSourceContract.d.ts +3 -0
- package/dist/theme/neutralSourceContract.js +11 -0
- package/dist/theme/neutralSourceContract.js.map +1 -0
- package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.d.ts +1 -1
- package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js +47 -44
- package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js.map +1 -1
- package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.d.ts +3 -0
- package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.js +2 -0
- package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.d.ts +3 -0
- package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.js +2 -0
- package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.d.ts +3 -0
- package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.js +2 -0
- package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.d.ts +3 -0
- package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.js +2 -0
- package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.d.ts +1 -1
- package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js +43 -40
- package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js.map +1 -1
- package/dist/theme/runtime/colorValueMode/index.js +2 -12
- package/dist/theme/runtime/colorValueMode/index.js.map +1 -1
- package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.d.ts +2 -0
- package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js +48 -0
- package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js.map +1 -0
- package/dist/theme/runtime/colorValueMode/registry.d.ts +1 -1
- package/dist/theme/runtime/colorValueMode/registry.js +2 -1
- package/dist/theme/runtime/colorValueMode/registry.js.map +1 -1
- package/dist/theme/runtime/initAldTheme.js +1 -3
- package/dist/theme/runtime/initAldTheme.js.map +1 -1
- package/dist/theme/runtime/neutralSource/index.d.ts +6 -0
- package/dist/theme/runtime/neutralSource/index.js +11 -0
- package/dist/theme/runtime/neutralSource/index.js.map +1 -0
- package/dist/theme/runtime/neutralSource.d.ts +2 -0
- package/dist/theme/runtime/themeToCssVars.js +3 -0
- package/dist/theme/runtime/themeToCssVars.js.map +1 -1
- package/package.json +1 -1
package/dist/Checkbox/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { cn } from "../lib/utils.js";
|
|
2
2
|
import DisabledContext from "../ConfigProvider/DisabledContext.js";
|
|
3
|
+
import { getSemanticOwnerAriaProps } from "../_utils/formControlSemanticOwner.js";
|
|
3
4
|
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
//#region src/Checkbox/index.tsx
|
|
6
7
|
var CheckboxGroupContext = createContext(null);
|
|
7
8
|
function Checkbox(props) {
|
|
8
|
-
const { className, disabled: customDisabled, alert, bold, size, checked: controlledChecked, defaultChecked, indeterminate, onChange, onClick, autoFocus, children, value, name, style, "data-testid": dataTestid, "aria-label": ariaLabel } = props;
|
|
9
|
+
const { className, disabled: customDisabled, alert, bold, size, checked: controlledChecked, defaultChecked, indeterminate, onChange, onClick, autoFocus, children, value, name, required, style, "data-testid": dataTestid, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, "aria-required": ariaRequired, "aria-disabled": ariaDisabled } = props;
|
|
9
10
|
const disabled = useContext(DisabledContext);
|
|
10
11
|
const group = useContext(CheckboxGroupContext);
|
|
11
12
|
const isGroupCheckbox = group !== null && value !== void 0;
|
|
@@ -45,13 +46,29 @@ function Checkbox(props) {
|
|
|
45
46
|
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(--border-brand-strong)]", !mergedDisabled && checked && "[&:hover_.ald-checkbox-inner]:tw-border-[var(--action-ghost-normal)] [&:hover_.ald-checkbox-inner]:tw-bg-[var(--action-primary-hover)]", className),
|
|
46
47
|
style,
|
|
47
48
|
children: [/* @__PURE__ */ jsxs("span", {
|
|
48
|
-
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-
|
|
49
|
+
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-colors tw-duration-200", !mergedDisabled && [
|
|
50
|
+
"has-[input:focus-visible]:tw-shadow-[0_0_0_2px_var(--focus-ring)]",
|
|
51
|
+
"forced-colors:has-[input:focus-visible]:tw-outline",
|
|
52
|
+
"forced-colors:has-[input:focus-visible]:tw-outline-2",
|
|
53
|
+
"forced-colors:has-[input:focus-visible]:tw-outline-offset-2",
|
|
54
|
+
"forced-colors:has-[input:focus-visible]:tw-outline-[Highlight]"
|
|
55
|
+
], checked && "ald-checkbox-checked", checked && !mergedDisabled && "tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]", checked && mergedDisabled && "tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]", !checked && !indeterminate && mergedDisabled && "tw-border-[var(--content-disabled)] tw-bg-[var(--background-neutral-on-subtle)]", !checked && !indeterminate && !mergedDisabled && !alert && "tw-border-[var(--border-neutral-subtle)] tw-bg-[var(--background-default)]", !checked && !indeterminate && !mergedDisabled && alert && "tw-border-[var(--border-negative-strong)] tw-bg-[var(--background-default)]", indeterminate && !checked && "ald-checkbox-indeterminate", indeterminate && !checked && !mergedDisabled && "tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]", indeterminate && !checked && mergedDisabled && "tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]"),
|
|
49
56
|
children: [/* @__PURE__ */ jsx("input", {
|
|
50
57
|
ref: inputRef,
|
|
51
58
|
type: "checkbox",
|
|
52
59
|
className: "tw-absolute tw-inset-0 tw-m-0 tw-cursor-pointer tw-opacity-0 disabled:tw-cursor-default",
|
|
53
60
|
checked: !!checked,
|
|
54
61
|
disabled: mergedDisabled,
|
|
62
|
+
required,
|
|
63
|
+
"aria-checked": indeterminate ? "mixed" : void 0,
|
|
64
|
+
...getSemanticOwnerAriaProps({
|
|
65
|
+
"aria-label": ariaLabel,
|
|
66
|
+
"aria-labelledby": ariaLabelledBy,
|
|
67
|
+
"aria-describedby": ariaDescribedBy,
|
|
68
|
+
"aria-invalid": ariaInvalid,
|
|
69
|
+
"aria-required": ariaRequired,
|
|
70
|
+
"aria-disabled": ariaDisabled
|
|
71
|
+
}),
|
|
55
72
|
onChange: handleChange,
|
|
56
73
|
autoFocus,
|
|
57
74
|
name: group?.name ?? name,
|
|
@@ -64,13 +81,13 @@ function Checkbox(props) {
|
|
|
64
81
|
}
|
|
65
82
|
})]
|
|
66
83
|
}), children && /* @__PURE__ */ jsx("span", {
|
|
67
|
-
className: cn("ald-checkbox-label tw-inline-flex tw-select-none tw-items-center tw-gap-1 tw-text-[var(--content-primary)] [&_svg]:tw-inline-block [&_svg]:tw-shrink-0",
|
|
84
|
+
className: cn("ald-checkbox-label tw-inline-flex tw-select-none tw-items-center tw-gap-1 tw-text-[var(--content-primary)] [&_svg]:tw-inline-block [&_svg]:tw-shrink-0", "tw-text-typography-label", bold && "tw-font-medium", mergedDisabled && "tw-cursor-default tw-text-[var(--content-disabled)]"),
|
|
68
85
|
children
|
|
69
86
|
})]
|
|
70
87
|
});
|
|
71
88
|
}
|
|
72
89
|
function CheckboxGroup(props) {
|
|
73
|
-
const { className, disabled: customDisabled, size, options, value: controlledValue, defaultValue, onChange, direction, name, children, style } = props;
|
|
90
|
+
const { className, disabled: customDisabled, size, options, value: controlledValue, defaultValue, onChange, direction, name, children, style, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy } = props;
|
|
74
91
|
const disabled = useContext(DisabledContext);
|
|
75
92
|
const mergedDisabled = customDisabled ?? disabled;
|
|
76
93
|
const isControlled = "value" in props;
|
|
@@ -100,6 +117,10 @@ function CheckboxGroup(props) {
|
|
|
100
117
|
return /* @__PURE__ */ jsx("div", {
|
|
101
118
|
className: cn("ald-checkbox-group tw-flex tw-flex-wrap tw-gap-3", direction === "vertical" && "ald-checkbox-group-vertical tw-flex-col", size === "small" && "ald-checkbox-group-small", className),
|
|
102
119
|
style,
|
|
120
|
+
role: "group",
|
|
121
|
+
"aria-label": ariaLabel,
|
|
122
|
+
"aria-labelledby": ariaLabelledBy,
|
|
123
|
+
"aria-describedby": ariaDescribedBy,
|
|
103
124
|
children: /* @__PURE__ */ jsx(CheckboxGroupContext.Provider, {
|
|
104
125
|
value: {
|
|
105
126
|
value,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/Checkbox/index.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useEffect,\n useRef,\n useState,\n} 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\ninterface CheckboxGroupContextValue {\n value: CheckboxValueType[];\n disabled?: boolean;\n name?: string;\n toggleOption: (value: CheckboxValueType, checked: boolean) => void;\n}\n\nconst CheckboxGroupContext = createContext<CheckboxGroupContextValue | null>(\n null,\n);\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 group = useContext(CheckboxGroupContext);\n const isGroupCheckbox = group !== null && value !== undefined;\n const mergedDisabled = group?.disabled || customDisabled || disabled;\n\n const isControlled = isGroupCheckbox || 'checked' in props;\n const [innerChecked, setInnerChecked] = useState(defaultChecked ?? false);\n const checked = isGroupCheckbox\n ? group.value.includes(value)\n : isControlled\n ? controlledChecked\n : 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 (isGroupCheckbox) {\n group.toggleOption(value, newChecked);\n } else 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(--border-brand-strong)]',\n !mergedDisabled &&\n checked &&\n '[&:hover_.ald-checkbox-inner]:tw-border-[var(--action-ghost-normal)] [&:hover_.ald-checkbox-inner]:tw-bg-[var(--action-primary-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 && 'ald-checkbox-checked',\n checked &&\n !mergedDisabled &&\n 'tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]',\n checked &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]',\n !checked &&\n !indeterminate &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--background-neutral-on-subtle)]',\n !checked &&\n !indeterminate &&\n !mergedDisabled &&\n !alert &&\n 'tw-border-[var(--border-neutral-subtle)] tw-bg-[var(--background-default)]',\n !checked &&\n !indeterminate &&\n !mergedDisabled &&\n alert &&\n 'tw-border-[var(--border-negative-strong)] tw-bg-[var(--background-default)]',\n indeterminate && !checked && 'ald-checkbox-indeterminate',\n indeterminate &&\n !checked &&\n !mergedDisabled &&\n 'tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]',\n indeterminate &&\n !checked &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]',\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={group?.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(--content-primary)] [&_svg]:tw-inline-block [&_svg]:tw-shrink-0',\n size === 'small' ? 'tw-text-xs' : 'tw-text-sm',\n bold && 'tw-font-medium',\n mergedDisabled &&\n 'tw-cursor-default tw-text-[var(--content-disabled)]',\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={optObj.disabled}\n size={size}\n onChange={optObj.onChange}\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 <CheckboxGroupContext.Provider\n value={{\n value,\n disabled: mergedDisabled,\n name,\n toggleOption: handleGroupChange,\n }}\n >\n {renderOptions()}\n </CheckboxGroupContext.Provider>\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, {\n createContext,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport { getSemanticOwnerAriaProps } from '../_utils/formControlSemanticOwner';\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\ninterface CheckboxGroupContextValue {\n value: CheckboxValueType[];\n disabled?: boolean;\n name?: string;\n toggleOption: (value: CheckboxValueType, checked: boolean) => void;\n}\n\nconst CheckboxGroupContext = createContext<CheckboxGroupContextValue | null>(\n null,\n);\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 required,\n style,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-disabled': ariaDisabled,\n } = props;\n\n const disabled = useContext(DisabledContext);\n const group = useContext(CheckboxGroupContext);\n const isGroupCheckbox = group !== null && value !== undefined;\n const mergedDisabled = group?.disabled || customDisabled || disabled;\n\n const isControlled = isGroupCheckbox || 'checked' in props;\n const [innerChecked, setInnerChecked] = useState(defaultChecked ?? false);\n const checked = isGroupCheckbox\n ? group.value.includes(value)\n : isControlled\n ? controlledChecked\n : 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 (isGroupCheckbox) {\n group.toggleOption(value, newChecked);\n } else 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(--border-brand-strong)]',\n !mergedDisabled &&\n checked &&\n '[&:hover_.ald-checkbox-inner]:tw-border-[var(--action-ghost-normal)] [&:hover_.ald-checkbox-inner]:tw-bg-[var(--action-primary-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-colors tw-duration-200',\n // The native input owns focus and its visual control owns the\n // Focus State Layer. Checked, indeterminate, and alert styling\n // remain independent control states.\n !mergedDisabled && [\n 'has-[input:focus-visible]:tw-shadow-[0_0_0_2px_var(--focus-ring)]',\n 'forced-colors:has-[input:focus-visible]:tw-outline',\n 'forced-colors:has-[input:focus-visible]:tw-outline-2',\n 'forced-colors:has-[input:focus-visible]:tw-outline-offset-2',\n 'forced-colors:has-[input:focus-visible]:tw-outline-[Highlight]',\n ],\n checked && 'ald-checkbox-checked',\n checked &&\n !mergedDisabled &&\n 'tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]',\n checked &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]',\n !checked &&\n !indeterminate &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--background-neutral-on-subtle)]',\n !checked &&\n !indeterminate &&\n !mergedDisabled &&\n !alert &&\n 'tw-border-[var(--border-neutral-subtle)] tw-bg-[var(--background-default)]',\n !checked &&\n !indeterminate &&\n !mergedDisabled &&\n alert &&\n 'tw-border-[var(--border-negative-strong)] tw-bg-[var(--background-default)]',\n indeterminate && !checked && 'ald-checkbox-indeterminate',\n indeterminate &&\n !checked &&\n !mergedDisabled &&\n 'tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]',\n indeterminate &&\n !checked &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]',\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 required={required}\n aria-checked={indeterminate ? 'mixed' : undefined}\n {...getSemanticOwnerAriaProps({\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-disabled': ariaDisabled,\n })}\n onChange={handleChange}\n autoFocus={autoFocus}\n name={group?.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(--content-primary)] [&_svg]:tw-inline-block [&_svg]:tw-shrink-0',\n 'tw-text-typography-label',\n bold && 'tw-font-medium',\n mergedDisabled &&\n 'tw-cursor-default tw-text-[var(--content-disabled)]',\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 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\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={optObj.disabled}\n size={size}\n onChange={optObj.onChange}\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 role=\"group\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n >\n <CheckboxGroupContext.Provider\n value={{\n value,\n disabled: mergedDisabled,\n name,\n toggleOption: handleGroupChange,\n }}\n >\n {renderOptions()}\n </CheckboxGroupContext.Provider>\n </div>\n );\n}\n\nCheckbox.Group = CheckboxGroup;\n\nexport default Checkbox;\n"],"mappings":"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"}
|
package/dist/Checkbox/type.d.ts
CHANGED
|
@@ -35,10 +35,15 @@ export interface ICheckboxProps {
|
|
|
35
35
|
children?: React.ReactNode;
|
|
36
36
|
value?: CheckboxValueType;
|
|
37
37
|
name?: string;
|
|
38
|
+
required?: boolean;
|
|
39
|
+
'aria-label'?: string;
|
|
40
|
+
'aria-labelledby'?: string;
|
|
41
|
+
'aria-describedby'?: string;
|
|
42
|
+
'aria-invalid'?: React.AriaAttributes['aria-invalid'];
|
|
43
|
+
'aria-required'?: React.AriaAttributes['aria-required'];
|
|
44
|
+
'aria-disabled'?: React.AriaAttributes['aria-disabled'];
|
|
38
45
|
/** 透传到根 label 元素的 data-testid,用于自动化测试定位 */
|
|
39
46
|
'data-testid'?: string;
|
|
40
|
-
/** 透传到根 label 元素的 aria-label,用于可访问性与自动化测试定位 */
|
|
41
|
-
'aria-label'?: string;
|
|
42
47
|
}
|
|
43
48
|
export interface ICheckboxGroupProps {
|
|
44
49
|
defaultValue?: Array<CheckboxValueType>;
|
|
@@ -52,4 +57,7 @@ export interface ICheckboxGroupProps {
|
|
|
52
57
|
style?: React.CSSProperties;
|
|
53
58
|
size?: TSize;
|
|
54
59
|
children?: React.ReactNode;
|
|
60
|
+
'aria-label'?: string;
|
|
61
|
+
'aria-labelledby'?: string;
|
|
62
|
+
'aria-describedby'?: string;
|
|
55
63
|
}
|
package/dist/Collapse/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { cn } from "../lib/utils.js";
|
|
2
2
|
import Memo from "../Icon/components/ArrowRightLightLine.js";
|
|
3
|
-
import React, { useContext, useRef, useState } from "react";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React, { useContext, useEffect, useId, useRef, useState } from "react";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region src/Collapse/index.tsx
|
|
6
6
|
var CollapseContext = React.createContext(null);
|
|
7
7
|
var normalizeKeys = (keys) => {
|
|
@@ -110,8 +110,13 @@ Panel.__COLLAPSE_PANEL = true;
|
|
|
110
110
|
var CollapsePanelView = React.forwardRef((props, ref) => {
|
|
111
111
|
const { header, isActive, onToggle, disabled, extra, className, style, children, forceRender, expandIcon, expandIconPosition = "start", bordered, size = "middle", collapsible = "header" } = props;
|
|
112
112
|
const contentRef = useRef(null);
|
|
113
|
+
const triggerId = useId();
|
|
114
|
+
const headerId = useId();
|
|
115
|
+
const contentId = useId();
|
|
113
116
|
const [rendered, setRendered] = useState(isActive || !!forceRender);
|
|
114
|
-
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (isActive || forceRender) setRendered(true);
|
|
119
|
+
}, [forceRender, isActive]);
|
|
115
120
|
const handleTransitionEnd = () => {
|
|
116
121
|
if (!isActive && !forceRender) setRendered(false);
|
|
117
122
|
};
|
|
@@ -121,37 +126,78 @@ var CollapsePanelView = React.forwardRef((props, ref) => {
|
|
|
121
126
|
});
|
|
122
127
|
const iconElement = /* @__PURE__ */ jsx("span", {
|
|
123
128
|
className: "ald-collapse-expand-icon ant-collapse-expand-icon tw-flex tw-items-center",
|
|
129
|
+
"aria-hidden": "true",
|
|
124
130
|
style: {
|
|
125
131
|
transform: isActive ? "rotate(90deg)" : "rotate(0deg)",
|
|
126
132
|
transition: "transform 200ms"
|
|
127
133
|
},
|
|
128
|
-
onClick: disabled || collapsible !== "icon" ? void 0 : (e) => {
|
|
129
|
-
e.stopPropagation();
|
|
130
|
-
onToggle();
|
|
131
|
-
},
|
|
132
134
|
children: iconNode
|
|
133
135
|
});
|
|
136
|
+
const triggerProps = {
|
|
137
|
+
type: "button",
|
|
138
|
+
id: triggerId,
|
|
139
|
+
"aria-expanded": isActive,
|
|
140
|
+
"aria-controls": contentId,
|
|
141
|
+
disabled,
|
|
142
|
+
onClick: onToggle
|
|
143
|
+
};
|
|
144
|
+
const headerText = /* @__PURE__ */ jsx("span", {
|
|
145
|
+
className: "ald-collapse-header-text ant-collapse-header-text tw-flex-1 tw-text-sm tw-font-medium tw-leading-5 tw-text-[var(--content-primary)]",
|
|
146
|
+
children: header
|
|
147
|
+
});
|
|
148
|
+
const headerTrigger = collapsible === "disabled" ? /* @__PURE__ */ jsxs("div", {
|
|
149
|
+
id: triggerId,
|
|
150
|
+
className: "tw-flex tw-flex-1 tw-items-center tw-gap-2",
|
|
151
|
+
"aria-disabled": "true",
|
|
152
|
+
children: [
|
|
153
|
+
expandIconPosition === "start" && iconElement,
|
|
154
|
+
headerText,
|
|
155
|
+
expandIconPosition === "end" && iconElement
|
|
156
|
+
]
|
|
157
|
+
}) : collapsible === "icon" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
158
|
+
expandIconPosition === "start" && /* @__PURE__ */ jsx("button", {
|
|
159
|
+
...triggerProps,
|
|
160
|
+
className: "tw-flex tw-cursor-pointer tw-items-center tw-border-0 tw-bg-transparent tw-p-0",
|
|
161
|
+
"aria-labelledby": headerId,
|
|
162
|
+
children: iconElement
|
|
163
|
+
}),
|
|
164
|
+
/* @__PURE__ */ jsx("span", {
|
|
165
|
+
id: headerId,
|
|
166
|
+
className: "ald-collapse-header-text ant-collapse-header-text tw-flex-1 tw-text-sm tw-font-medium tw-leading-5 tw-text-[var(--content-primary)]",
|
|
167
|
+
children: header
|
|
168
|
+
}),
|
|
169
|
+
expandIconPosition === "end" && /* @__PURE__ */ jsx("button", {
|
|
170
|
+
...triggerProps,
|
|
171
|
+
className: "tw-flex tw-cursor-pointer tw-items-center tw-border-0 tw-bg-transparent tw-p-0",
|
|
172
|
+
"aria-labelledby": headerId,
|
|
173
|
+
children: iconElement
|
|
174
|
+
})
|
|
175
|
+
] }) : /* @__PURE__ */ jsxs("button", {
|
|
176
|
+
...triggerProps,
|
|
177
|
+
className: "tw-flex tw-flex-1 tw-items-center tw-gap-2 tw-border-0 tw-bg-transparent tw-p-0 tw-text-left",
|
|
178
|
+
children: [
|
|
179
|
+
expandIconPosition === "start" && iconElement,
|
|
180
|
+
headerText,
|
|
181
|
+
expandIconPosition === "end" && iconElement
|
|
182
|
+
]
|
|
183
|
+
});
|
|
134
184
|
return /* @__PURE__ */ jsxs("div", {
|
|
135
185
|
ref,
|
|
136
186
|
className: cn("ald-collapse-item ant-collapse-item tw-w-full", isActive && "ald-collapse-item-active", disabled && "tw-pointer-events-none tw-opacity-50", `ald-collapse-item-${size}`, className),
|
|
137
187
|
style,
|
|
188
|
+
"aria-disabled": disabled || collapsible === "disabled" || void 0,
|
|
138
189
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
139
|
-
className: cn("ald-collapse-header ant-collapse-header tw-flex tw-items-center tw-gap-2 tw-p-3", !disabled && collapsible !== "icon" && "tw-cursor-pointer"),
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
children: header
|
|
146
|
-
}),
|
|
147
|
-
extra && /* @__PURE__ */ jsx("span", {
|
|
148
|
-
className: "ald-collapse-extra ant-collapse-extra",
|
|
149
|
-
onClick: (e) => e.stopPropagation(),
|
|
150
|
-
children: extra
|
|
151
|
-
}),
|
|
152
|
-
expandIconPosition === "end" && iconElement
|
|
153
|
-
]
|
|
190
|
+
className: cn("ald-collapse-header ant-collapse-header tw-flex tw-items-center tw-gap-2 tw-p-3", !disabled && collapsible !== "icon" && collapsible !== "disabled" && "tw-cursor-pointer"),
|
|
191
|
+
children: [headerTrigger, extra && /* @__PURE__ */ jsx("span", {
|
|
192
|
+
className: "ald-collapse-extra ant-collapse-extra",
|
|
193
|
+
onClick: (e) => e.stopPropagation(),
|
|
194
|
+
children: extra
|
|
195
|
+
})]
|
|
154
196
|
}), /* @__PURE__ */ jsx("div", {
|
|
197
|
+
id: contentId,
|
|
198
|
+
role: "region",
|
|
199
|
+
"aria-labelledby": triggerId,
|
|
200
|
+
"aria-hidden": !isActive,
|
|
155
201
|
className: "tw-grid tw-transition-[grid-template-rows] tw-duration-200",
|
|
156
202
|
style: { gridTemplateRows: isActive ? "1fr" : "0fr" },
|
|
157
203
|
onTransitionEnd: handleTransitionEnd,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/Collapse/index.tsx"],"sourcesContent":["import React, { useContext, useRef, useState } from 'react';\nimport { ArrowRightLightLine } from '../Icon';\nimport { cn } from '../lib/utils';\n\n/**\n * Compound Components 模式:Collapse 通过 Context 注入受控状态 + 视觉配置,\n * Panel 始终自渲染(header + 折叠交互),靠 `panelKey` 与父协调 activeKey /\n * accordion。设计对齐 Radix / Mantine:Item 自渲染,靠声明式 value 与 Root 通信。\n *\n * 这里不再做\"扫描 children 提 Panel props 再替换渲染\"的 hack——后者无法穿透\n * forwardRef / 业务包装组件边界,是 ald v3 升级回归\"包装 Panel 丢 header\"的根因。\n */\ninterface CollapseContextValue {\n // 视觉配置\n expandIcon?: (props: { isActive: boolean }) => React.ReactNode;\n expandIconPosition: 'start' | 'end';\n bordered: boolean;\n size: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\n // 受控状态协调\n activeKeys: string[];\n toggleKey: (key: string) => void;\n}\n\nconst CollapseContext = React.createContext<CollapseContextValue | null>(null);\n\nexport interface CollapsePanelProps {\n /**\n * 与父 Collapse 协调 activeKey / accordion 的 key。\n * 不提供时 Panel 走内部 state(视觉一致但不参与父协调)。\n * Radix Accordion 等同 prop 名是 `value`;这里沿用 `panelKey` 与已有\n * `Collapse items[].key` 命名一致,迁移成本最低。\n */\n panelKey?: string;\n header?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n disabled?: boolean;\n extra?: React.ReactNode;\n forceRender?: boolean;\n collapsible?: 'header' | 'icon' | 'disabled';\n showArrow?: boolean;\n}\n\nexport interface CollapseProps {\n activeKey?: string | string[];\n defaultActiveKey?: string | string[];\n accordion?: boolean;\n onChange?: (key: string | string[]) => void;\n className?: string;\n style?: React.CSSProperties;\n bordered?: boolean;\n expandIconPosition?: 'start' | 'end' | 'left' | 'right';\n expandIcon?: (props: { isActive: boolean }) => React.ReactNode;\n ghost?: boolean;\n size?: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\n children?: React.ReactNode;\n items?: Array<{\n key: string;\n label: React.ReactNode;\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n extra?: React.ReactNode;\n disabled?: boolean;\n collapsible?: 'header' | 'icon' | 'disabled';\n forceRender?: boolean;\n }>;\n}\n\nconst normalizeKeys = (keys: string | string[] | undefined): string[] => {\n if (!keys) return [];\n return Array.isArray(keys) ? keys : [keys];\n};\n\nconst Collapse = (props: CollapseProps) => {\n const {\n defaultActiveKey = [],\n activeKey: controlledActiveKey,\n accordion,\n onChange,\n className,\n style,\n bordered = true,\n ghost,\n size = 'middle',\n collapsible,\n expandIconPosition,\n expandIcon,\n items: itemsProp,\n children,\n } = props;\n\n const resolvedPosition =\n expandIconPosition === 'left'\n ? 'start'\n : expandIconPosition === 'right'\n ? 'end'\n : expandIconPosition ?? 'start';\n\n const [internalActiveKey, setInternalActiveKey] = useState<string[]>(\n normalizeKeys(defaultActiveKey),\n );\n\n const activeKeys =\n controlledActiveKey !== undefined\n ? normalizeKeys(controlledActiveKey)\n : internalActiveKey;\n\n const toggleKey = (key: string) => {\n let newKeys: string[];\n if (accordion) {\n newKeys = activeKeys.includes(key) ? [] : [key];\n } else {\n newKeys = activeKeys.includes(key)\n ? activeKeys.filter((k) => k !== key)\n : [...activeKeys, key];\n }\n if (controlledActiveKey === undefined) {\n setInternalActiveKey(newKeys);\n }\n onChange?.(accordion ? newKeys[0] || '' : newKeys);\n };\n\n const contextValue: CollapseContextValue = {\n expandIcon,\n expandIconPosition: resolvedPosition,\n bordered: bordered && !ghost,\n size,\n collapsible,\n activeKeys,\n toggleKey,\n };\n\n /**\n * children 路径:向后兼容老用法 `<Collapse><Collapse.Panel key=\"1\" ...>`\n * ——React `key` 是保留字不会进 Panel props,所以把它读出来 cloneElement\n * 注入到 `panelKey` 上(只对直接子元素生效;包装组件需要业务侧自己透传)。\n */\n const enhancedChildren = React.Children.map(children, (child) => {\n if (!React.isValidElement<CollapsePanelProps>(child)) return child;\n if ((child.type as any)?.__COLLAPSE_PANEL !== true) return child;\n if (child.props.panelKey !== undefined) return child;\n if (child.key === null || child.key === undefined) return child;\n return React.cloneElement(child, { panelKey: String(child.key) });\n });\n\n return (\n <CollapseContext.Provider value={contextValue}>\n <div\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n // 相邻 .ald-collapse-item 用 CSS 兄弟选择器画分隔线,避免在 React 树里\n // 注入 <div .ald-collapse-divider /> 节点——后者在\"业务包装 Panel\"场景\n // 需要 Collapse 知道子元素拓扑,与 Compound Components 解耦原则冲突。\n 'ald-collapse ant-collapse tw-flex tw-flex-col tw-items-stretch tw-overflow-hidden tw-rounded-r-75 [&>.ald-collapse-item+.ald-collapse-item]:tw-border-0 [&>.ald-collapse-item+.ald-collapse-item]:tw-border-t [&>.ald-collapse-item+.ald-collapse-item]:tw-border-solid [&>.ald-collapse-item+.ald-collapse-item]:tw-border-[var(--border-default)]',\n !ghost && !bordered && 'tw-bg-[var(--background-neutral-subtle)]',\n !ghost &&\n bordered &&\n 'tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-neutral-subtle)]',\n `ald-collapse-${size}`,\n className,\n )}\n style={style}\n >\n {itemsProp && itemsProp.length > 0\n ? itemsProp.map((item) => (\n <Panel\n key={item.key}\n panelKey={item.key}\n header={item.label}\n disabled={item.disabled}\n collapsible={item.collapsible ?? collapsible}\n extra={item.extra}\n className={item.className}\n style={item.style}\n forceRender={item.forceRender}\n >\n {item.children}\n </Panel>\n ))\n : enhancedChildren}\n </div>\n </CollapseContext.Provider>\n );\n};\n\n/**\n * Panel —— 始终自渲染。\n *\n * - 在 `<Collapse>` 内(ctx 存在)+ 提供 `panelKey`:受控渲染(参与父 activeKey\n * / accordion 协调),点击调 `ctx.toggleKey`,`isActive` 来自 `ctx.activeKeys`。\n * - 在 `<Collapse>` 内(ctx 存在)+ 未提供 `panelKey`:自渲染 + 独立 state,视觉\n * 配置仍来自 ctx,但与父受控状态隔离(业务包装组件没透传 panelKey 时的退化)。\n * - `<Collapse>` 外使用(ctx 不存在):完全自给自足,视觉配置走默认值。\n *\n * 用 forwardRef 转发 ref 到 `.ald-collapse-item` root div——业务侧包装组件常\n * 需要拿到 panel 容器引用做滚动定位等,向后兼容旧版本 Panel 暴露的 ref API。\n */\nconst Panel = React.forwardRef<HTMLDivElement, CollapsePanelProps>(\n (props, ref) => {\n const ctx = useContext(CollapseContext);\n const {\n panelKey,\n header,\n children,\n className,\n style,\n extra,\n disabled,\n collapsible,\n forceRender,\n } = props;\n\n const isControlled = ctx !== null && panelKey !== undefined;\n\n const [internalActive, setInternalActive] = useState(false);\n\n const isActive = isControlled\n ? ctx!.activeKeys.includes(panelKey!)\n : internalActive;\n\n const onToggle = () => {\n if (isControlled) {\n ctx!.toggleKey(panelKey!);\n } else {\n setInternalActive((v) => !v);\n }\n };\n\n const expandIcon = ctx?.expandIcon;\n const expandIconPosition = ctx?.expandIconPosition ?? 'start';\n const bordered = ctx?.bordered ?? true;\n const size = ctx?.size ?? 'middle';\n const mergedCollapsible = collapsible ?? ctx?.collapsible;\n\n return (\n <CollapsePanelView\n ref={ref}\n header={header}\n isActive={isActive}\n onToggle={onToggle}\n disabled={disabled || mergedCollapsible === 'disabled'}\n extra={extra}\n className={className}\n style={style}\n forceRender={forceRender}\n expandIcon={expandIcon}\n expandIconPosition={expandIconPosition}\n bordered={bordered}\n size={size}\n collapsible={mergedCollapsible}\n >\n {children}\n </CollapsePanelView>\n );\n },\n);\n\n(Panel as any).__COLLAPSE_PANEL = true;\n\ninterface CollapsePanelViewProps {\n header: React.ReactNode;\n isActive: boolean;\n onToggle: () => void;\n disabled?: boolean;\n extra?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n forceRender?: boolean;\n expandIcon?: (props: { isActive: boolean }) => React.ReactNode;\n expandIconPosition?: 'start' | 'end';\n bordered?: boolean;\n size?: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\n}\n\n/** 哑视图组件,承担 DOM 结构 + 折叠动画;不持有受控状态,ref 转发到 root div。 */\nconst CollapsePanelView = React.forwardRef<\n HTMLDivElement,\n CollapsePanelViewProps\n>((props, ref) => {\n const {\n header,\n isActive,\n onToggle,\n disabled,\n extra,\n className,\n style,\n children,\n forceRender,\n expandIcon,\n expandIconPosition = 'start',\n bordered,\n size = 'middle',\n collapsible = 'header',\n } = props;\n\n const contentRef = useRef<HTMLDivElement>(null);\n const [rendered, setRendered] = useState(isActive || !!forceRender);\n\n if (isActive && !rendered) {\n setRendered(true);\n }\n\n const handleTransitionEnd = () => {\n if (!isActive && !forceRender) {\n setRendered(false);\n }\n };\n\n const iconNode = expandIcon ? (\n expandIcon({ isActive })\n ) : (\n <ArrowRightLightLine size={20} color=\"var(--content-secondary)\" />\n );\n\n const iconElement = (\n <span\n className=\"ald-collapse-expand-icon ant-collapse-expand-icon tw-flex tw-items-center\"\n style={{\n transform: isActive ? 'rotate(90deg)' : 'rotate(0deg)',\n transition: 'transform 200ms',\n }}\n onClick={\n disabled || collapsible !== 'icon'\n ? undefined\n : (e) => {\n e.stopPropagation();\n onToggle();\n }\n }\n >\n {iconNode}\n </span>\n );\n\n return (\n <div\n ref={ref}\n className={cn(\n 'ald-collapse-item ant-collapse-item tw-w-full',\n isActive && 'ald-collapse-item-active',\n disabled && 'tw-pointer-events-none tw-opacity-50',\n `ald-collapse-item-${size}`,\n className,\n )}\n style={style}\n >\n <div\n className={cn(\n 'ald-collapse-header ant-collapse-header tw-flex tw-items-center tw-gap-2 tw-p-3',\n !disabled && collapsible !== 'icon' && 'tw-cursor-pointer',\n )}\n onClick={disabled || collapsible === 'icon' ? undefined : onToggle}\n >\n {expandIconPosition === 'start' && iconElement}\n <span className=\"ald-collapse-header-text ant-collapse-header-text tw-flex-1 tw-text-sm tw-font-medium tw-leading-5 tw-text-[var(--content-primary)]\">\n {header}\n </span>\n {extra && (\n // extra 区域里常放 Switch / Button 等交互控件,点击不该冒泡触发 panel\n // 切展开/收起。antd Collapse 也是同样行为;不强制消费方在每个 extra\n // 控件上自己写 stopPropagation。\n <span\n className=\"ald-collapse-extra ant-collapse-extra\"\n onClick={(e) => e.stopPropagation()}\n >\n {extra}\n </span>\n )}\n {expandIconPosition === 'end' && iconElement}\n </div>\n <div\n className=\"tw-grid tw-transition-[grid-template-rows] tw-duration-200\"\n style={{ gridTemplateRows: isActive ? '1fr' : '0fr' }}\n onTransitionEnd={handleTransitionEnd}\n >\n <div className=\"tw-overflow-hidden\">\n {rendered && (\n <div\n ref={contentRef}\n className={cn(\n 'ald-collapse-content ant-collapse-content tw-flex tw-flex-col tw-items-stretch tw-gap-2.5 tw-self-stretch',\n bordered\n ? 'tw-bg-[var(--background-default)] tw-p-4'\n : 'tw-px-4 tw-pb-4 tw-pt-0',\n )}\n >\n {children}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n});\n\nCollapse.Panel = Panel;\n\nexport default Collapse;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/Collapse/index.tsx"],"sourcesContent":["import React, { useContext, useEffect, useId, useRef, useState } from 'react';\nimport { ArrowRightLightLine } from '../Icon';\nimport { cn } from '../lib/utils';\n\n/**\n * Compound Components 模式:Collapse 通过 Context 注入受控状态 + 视觉配置,\n * Panel 始终自渲染(header + 折叠交互),靠 `panelKey` 与父协调 activeKey /\n * accordion。设计对齐 Radix / Mantine:Item 自渲染,靠声明式 value 与 Root 通信。\n *\n * 这里不再做\"扫描 children 提 Panel props 再替换渲染\"的 hack——后者无法穿透\n * forwardRef / 业务包装组件边界,是 ald v3 升级回归\"包装 Panel 丢 header\"的根因。\n */\ninterface CollapseContextValue {\n // 视觉配置\n expandIcon?: (props: { isActive: boolean }) => React.ReactNode;\n expandIconPosition: 'start' | 'end';\n bordered: boolean;\n size: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\n // 受控状态协调\n activeKeys: string[];\n toggleKey: (key: string) => void;\n}\n\nconst CollapseContext = React.createContext<CollapseContextValue | null>(null);\n\nexport interface CollapsePanelProps {\n /**\n * 与父 Collapse 协调 activeKey / accordion 的 key。\n * 不提供时 Panel 走内部 state(视觉一致但不参与父协调)。\n * Radix Accordion 等同 prop 名是 `value`;这里沿用 `panelKey` 与已有\n * `Collapse items[].key` 命名一致,迁移成本最低。\n */\n panelKey?: string;\n header?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n disabled?: boolean;\n extra?: React.ReactNode;\n forceRender?: boolean;\n collapsible?: 'header' | 'icon' | 'disabled';\n showArrow?: boolean;\n}\n\nexport interface CollapseProps {\n activeKey?: string | string[];\n defaultActiveKey?: string | string[];\n accordion?: boolean;\n onChange?: (key: string | string[]) => void;\n className?: string;\n style?: React.CSSProperties;\n bordered?: boolean;\n expandIconPosition?: 'start' | 'end' | 'left' | 'right';\n expandIcon?: (props: { isActive: boolean }) => React.ReactNode;\n ghost?: boolean;\n size?: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\n children?: React.ReactNode;\n items?: Array<{\n key: string;\n label: React.ReactNode;\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n extra?: React.ReactNode;\n disabled?: boolean;\n collapsible?: 'header' | 'icon' | 'disabled';\n forceRender?: boolean;\n }>;\n}\n\nconst normalizeKeys = (keys: string | string[] | undefined): string[] => {\n if (!keys) return [];\n return Array.isArray(keys) ? keys : [keys];\n};\n\nconst Collapse = (props: CollapseProps) => {\n const {\n defaultActiveKey = [],\n activeKey: controlledActiveKey,\n accordion,\n onChange,\n className,\n style,\n bordered = true,\n ghost,\n size = 'middle',\n collapsible,\n expandIconPosition,\n expandIcon,\n items: itemsProp,\n children,\n } = props;\n\n const resolvedPosition =\n expandIconPosition === 'left'\n ? 'start'\n : expandIconPosition === 'right'\n ? 'end'\n : expandIconPosition ?? 'start';\n\n const [internalActiveKey, setInternalActiveKey] = useState<string[]>(\n normalizeKeys(defaultActiveKey),\n );\n\n const activeKeys =\n controlledActiveKey !== undefined\n ? normalizeKeys(controlledActiveKey)\n : internalActiveKey;\n\n const toggleKey = (key: string) => {\n let newKeys: string[];\n if (accordion) {\n newKeys = activeKeys.includes(key) ? [] : [key];\n } else {\n newKeys = activeKeys.includes(key)\n ? activeKeys.filter((k) => k !== key)\n : [...activeKeys, key];\n }\n if (controlledActiveKey === undefined) {\n setInternalActiveKey(newKeys);\n }\n onChange?.(accordion ? newKeys[0] || '' : newKeys);\n };\n\n const contextValue: CollapseContextValue = {\n expandIcon,\n expandIconPosition: resolvedPosition,\n bordered: bordered && !ghost,\n size,\n collapsible,\n activeKeys,\n toggleKey,\n };\n\n /**\n * children 路径:向后兼容老用法 `<Collapse><Collapse.Panel key=\"1\" ...>`\n * ——React `key` 是保留字不会进 Panel props,所以把它读出来 cloneElement\n * 注入到 `panelKey` 上(只对直接子元素生效;包装组件需要业务侧自己透传)。\n */\n const enhancedChildren = React.Children.map(children, (child) => {\n if (!React.isValidElement<CollapsePanelProps>(child)) return child;\n if ((child.type as any)?.__COLLAPSE_PANEL !== true) return child;\n if (child.props.panelKey !== undefined) return child;\n if (child.key === null || child.key === undefined) return child;\n return React.cloneElement(child, { panelKey: String(child.key) });\n });\n\n return (\n <CollapseContext.Provider value={contextValue}>\n <div\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n // 相邻 .ald-collapse-item 用 CSS 兄弟选择器画分隔线,避免在 React 树里\n // 注入 <div .ald-collapse-divider /> 节点——后者在\"业务包装 Panel\"场景\n // 需要 Collapse 知道子元素拓扑,与 Compound Components 解耦原则冲突。\n 'ald-collapse ant-collapse tw-flex tw-flex-col tw-items-stretch tw-overflow-hidden tw-rounded-r-75 [&>.ald-collapse-item+.ald-collapse-item]:tw-border-0 [&>.ald-collapse-item+.ald-collapse-item]:tw-border-t [&>.ald-collapse-item+.ald-collapse-item]:tw-border-solid [&>.ald-collapse-item+.ald-collapse-item]:tw-border-[var(--border-default)]',\n !ghost && !bordered && 'tw-bg-[var(--background-neutral-subtle)]',\n !ghost &&\n bordered &&\n 'tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-neutral-subtle)]',\n `ald-collapse-${size}`,\n className,\n )}\n style={style}\n >\n {itemsProp && itemsProp.length > 0\n ? itemsProp.map((item) => (\n <Panel\n key={item.key}\n panelKey={item.key}\n header={item.label}\n disabled={item.disabled}\n collapsible={item.collapsible ?? collapsible}\n extra={item.extra}\n className={item.className}\n style={item.style}\n forceRender={item.forceRender}\n >\n {item.children}\n </Panel>\n ))\n : enhancedChildren}\n </div>\n </CollapseContext.Provider>\n );\n};\n\n/**\n * Panel —— 始终自渲染。\n *\n * - 在 `<Collapse>` 内(ctx 存在)+ 提供 `panelKey`:受控渲染(参与父 activeKey\n * / accordion 协调),点击调 `ctx.toggleKey`,`isActive` 来自 `ctx.activeKeys`。\n * - 在 `<Collapse>` 内(ctx 存在)+ 未提供 `panelKey`:自渲染 + 独立 state,视觉\n * 配置仍来自 ctx,但与父受控状态隔离(业务包装组件没透传 panelKey 时的退化)。\n * - `<Collapse>` 外使用(ctx 不存在):完全自给自足,视觉配置走默认值。\n *\n * 用 forwardRef 转发 ref 到 `.ald-collapse-item` root div——业务侧包装组件常\n * 需要拿到 panel 容器引用做滚动定位等,向后兼容旧版本 Panel 暴露的 ref API。\n */\nconst Panel = React.forwardRef<HTMLDivElement, CollapsePanelProps>(\n (props, ref) => {\n const ctx = useContext(CollapseContext);\n const {\n panelKey,\n header,\n children,\n className,\n style,\n extra,\n disabled,\n collapsible,\n forceRender,\n } = props;\n\n const isControlled = ctx !== null && panelKey !== undefined;\n\n const [internalActive, setInternalActive] = useState(false);\n\n const isActive = isControlled\n ? ctx!.activeKeys.includes(panelKey!)\n : internalActive;\n\n const onToggle = () => {\n if (isControlled) {\n ctx!.toggleKey(panelKey!);\n } else {\n setInternalActive((v) => !v);\n }\n };\n\n const expandIcon = ctx?.expandIcon;\n const expandIconPosition = ctx?.expandIconPosition ?? 'start';\n const bordered = ctx?.bordered ?? true;\n const size = ctx?.size ?? 'middle';\n const mergedCollapsible = collapsible ?? ctx?.collapsible;\n\n return (\n <CollapsePanelView\n ref={ref}\n header={header}\n isActive={isActive}\n onToggle={onToggle}\n disabled={disabled || mergedCollapsible === 'disabled'}\n extra={extra}\n className={className}\n style={style}\n forceRender={forceRender}\n expandIcon={expandIcon}\n expandIconPosition={expandIconPosition}\n bordered={bordered}\n size={size}\n collapsible={mergedCollapsible}\n >\n {children}\n </CollapsePanelView>\n );\n },\n);\n\n(Panel as any).__COLLAPSE_PANEL = true;\n\ninterface CollapsePanelViewProps {\n header: React.ReactNode;\n isActive: boolean;\n onToggle: () => void;\n disabled?: boolean;\n extra?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n forceRender?: boolean;\n expandIcon?: (props: { isActive: boolean }) => React.ReactNode;\n expandIconPosition?: 'start' | 'end';\n bordered?: boolean;\n size?: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\n}\n\n/** 哑视图组件,承担 DOM 结构 + 折叠动画;不持有受控状态,ref 转发到 root div。 */\nconst CollapsePanelView = React.forwardRef<\n HTMLDivElement,\n CollapsePanelViewProps\n>((props, ref) => {\n const {\n header,\n isActive,\n onToggle,\n disabled,\n extra,\n className,\n style,\n children,\n forceRender,\n expandIcon,\n expandIconPosition = 'start',\n bordered,\n size = 'middle',\n collapsible = 'header',\n } = props;\n\n const contentRef = useRef<HTMLDivElement>(null);\n const triggerId = useId();\n const headerId = useId();\n const contentId = useId();\n const [rendered, setRendered] = useState(isActive || !!forceRender);\n\n useEffect(() => {\n if (isActive || forceRender) {\n setRendered(true);\n }\n }, [forceRender, isActive]);\n\n const handleTransitionEnd = () => {\n if (!isActive && !forceRender) {\n setRendered(false);\n }\n };\n\n const iconNode = expandIcon ? (\n expandIcon({ isActive })\n ) : (\n <ArrowRightLightLine size={20} color=\"var(--content-secondary)\" />\n );\n\n const iconElement = (\n <span\n className=\"ald-collapse-expand-icon ant-collapse-expand-icon tw-flex tw-items-center\"\n aria-hidden=\"true\"\n style={{\n transform: isActive ? 'rotate(90deg)' : 'rotate(0deg)',\n transition: 'transform 200ms',\n }}\n >\n {iconNode}\n </span>\n );\n\n const triggerProps = {\n type: 'button' as const,\n id: triggerId,\n 'aria-expanded': isActive,\n 'aria-controls': contentId,\n disabled,\n onClick: onToggle,\n };\n\n const headerText = (\n <span className=\"ald-collapse-header-text ant-collapse-header-text tw-flex-1 tw-text-sm tw-font-medium tw-leading-5 tw-text-[var(--content-primary)]\">\n {header}\n </span>\n );\n\n const headerTrigger =\n collapsible === 'disabled' ? (\n <div\n id={triggerId}\n className=\"tw-flex tw-flex-1 tw-items-center tw-gap-2\"\n aria-disabled=\"true\"\n >\n {expandIconPosition === 'start' && iconElement}\n {headerText}\n {expandIconPosition === 'end' && iconElement}\n </div>\n ) : collapsible === 'icon' ? (\n <>\n {expandIconPosition === 'start' && (\n <button\n {...triggerProps}\n className=\"tw-flex tw-cursor-pointer tw-items-center tw-border-0 tw-bg-transparent tw-p-0\"\n aria-labelledby={headerId}\n >\n {iconElement}\n </button>\n )}\n <span\n id={headerId}\n className=\"ald-collapse-header-text ant-collapse-header-text tw-flex-1 tw-text-sm tw-font-medium tw-leading-5 tw-text-[var(--content-primary)]\"\n >\n {header}\n </span>\n {expandIconPosition === 'end' && (\n <button\n {...triggerProps}\n className=\"tw-flex tw-cursor-pointer tw-items-center tw-border-0 tw-bg-transparent tw-p-0\"\n aria-labelledby={headerId}\n >\n {iconElement}\n </button>\n )}\n </>\n ) : (\n <button\n {...triggerProps}\n className=\"tw-flex tw-flex-1 tw-items-center tw-gap-2 tw-border-0 tw-bg-transparent tw-p-0 tw-text-left\"\n >\n {expandIconPosition === 'start' && iconElement}\n {headerText}\n {expandIconPosition === 'end' && iconElement}\n </button>\n );\n\n return (\n <div\n ref={ref}\n className={cn(\n 'ald-collapse-item ant-collapse-item tw-w-full',\n isActive && 'ald-collapse-item-active',\n disabled && 'tw-pointer-events-none tw-opacity-50',\n `ald-collapse-item-${size}`,\n className,\n )}\n style={style}\n aria-disabled={disabled || collapsible === 'disabled' || undefined}\n >\n <div\n className={cn(\n 'ald-collapse-header ant-collapse-header tw-flex tw-items-center tw-gap-2 tw-p-3',\n !disabled &&\n collapsible !== 'icon' &&\n collapsible !== 'disabled' &&\n 'tw-cursor-pointer',\n )}\n >\n {headerTrigger}\n {extra && (\n // extra 区域里常放 Switch / Button 等交互控件,点击不该冒泡触发 panel\n // 切展开/收起。antd Collapse 也是同样行为;不强制消费方在每个 extra\n // 控件上自己写 stopPropagation。\n <span\n className=\"ald-collapse-extra ant-collapse-extra\"\n onClick={(e) => e.stopPropagation()}\n >\n {extra}\n </span>\n )}\n </div>\n <div\n id={contentId}\n role=\"region\"\n aria-labelledby={triggerId}\n aria-hidden={!isActive}\n className=\"tw-grid tw-transition-[grid-template-rows] tw-duration-200\"\n style={{ gridTemplateRows: isActive ? '1fr' : '0fr' }}\n onTransitionEnd={handleTransitionEnd}\n >\n <div className=\"tw-overflow-hidden\">\n {rendered && (\n <div\n ref={contentRef}\n className={cn(\n 'ald-collapse-content ant-collapse-content tw-flex tw-flex-col tw-items-stretch tw-gap-2.5 tw-self-stretch',\n bordered\n ? 'tw-bg-[var(--background-default)] tw-p-4'\n : 'tw-px-4 tw-pb-4 tw-pt-0',\n )}\n >\n {children}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n});\n\nCollapse.Panel = Panel;\n\nexport default Collapse;\n"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { LocaleContext, getTranslator } from "../locale/default.js";
|
|
|
5
5
|
import { colors, specialColors } from "./constant.js";
|
|
6
6
|
/* empty css */
|
|
7
7
|
import ColorPicker$1 from "./ComplexColorPicker/index.js";
|
|
8
|
-
import { useContext, useEffect, useRef, useState } from "react";
|
|
8
|
+
import { useContext, useEffect, useId, useRef, useState } from "react";
|
|
9
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
//#region src/ColorPicker/index.tsx
|
|
11
11
|
function getLocalRecentColors(localStorageKey) {
|
|
@@ -26,6 +26,15 @@ function ColorPicker({ className, value, icon, onChange, defaultColor = colors[0
|
|
|
26
26
|
const [recentColors, setRecentColors] = useState([]);
|
|
27
27
|
const overlayRef = useRef(null);
|
|
28
28
|
const wrapRef = useRef(null);
|
|
29
|
+
const triggerRef = useRef(null);
|
|
30
|
+
const swatchRefs = useRef({});
|
|
31
|
+
const triggerId = `ald-color-picker-trigger-${useId().replace(/:/g, "")}`;
|
|
32
|
+
const popupId = `ald-color-picker-popup-${useId().replace(/:/g, "")}`;
|
|
33
|
+
const swatchOrder = Array.from(new Set([
|
|
34
|
+
defaultColor,
|
|
35
|
+
...colors,
|
|
36
|
+
...recentColors
|
|
37
|
+
]));
|
|
29
38
|
useEffect(() => {
|
|
30
39
|
setRecentColors(getLocalRecentColors(localStorageKey));
|
|
31
40
|
}, [localStorageKey]);
|
|
@@ -36,76 +45,115 @@ function ColorPicker({ className, value, icon, onChange, defaultColor = colors[0
|
|
|
36
45
|
setLocalRecentColors(localStorageKey, newRecentColors);
|
|
37
46
|
onChange?.(color);
|
|
38
47
|
setOpen(false);
|
|
48
|
+
window.setTimeout(() => triggerRef.current?.focus(), 0);
|
|
39
49
|
};
|
|
40
50
|
useEffect(() => {
|
|
41
51
|
const handleClick = (e) => {
|
|
42
|
-
if (wrapRef.current?.contains(e.target)) return setOpen(
|
|
43
|
-
if (!overlayRef.current?.contains(e.target)) return setOpen(false);
|
|
52
|
+
if (!wrapRef.current?.contains(e.target) && !overlayRef.current?.contains(e.target)) return setOpen(false);
|
|
44
53
|
};
|
|
45
54
|
document.addEventListener("click", handleClick);
|
|
46
55
|
return () => {
|
|
47
56
|
document.removeEventListener("click", handleClick);
|
|
48
57
|
};
|
|
49
|
-
}, [
|
|
58
|
+
}, []);
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (!open) return;
|
|
61
|
+
const selectedIndex = Math.max(0, swatchOrder.indexOf(value ?? defaultColor));
|
|
62
|
+
window.setTimeout(() => {
|
|
63
|
+
swatchRefs.current[swatchOrder[selectedIndex]]?.focus();
|
|
64
|
+
}, 0);
|
|
65
|
+
}, [
|
|
66
|
+
defaultColor,
|
|
67
|
+
open,
|
|
68
|
+
swatchOrder,
|
|
69
|
+
value
|
|
70
|
+
]);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
triggerRef.current?.setAttribute("aria-expanded", String(open));
|
|
73
|
+
triggerRef.current?.setAttribute("aria-controls", popupId);
|
|
74
|
+
}, [open, popupId]);
|
|
75
|
+
const renderSwatch = (color, label) => {
|
|
76
|
+
const selected = color === value;
|
|
77
|
+
const index = swatchOrder.indexOf(color);
|
|
78
|
+
const selectedIndex = Math.max(0, swatchOrder.indexOf(value ?? defaultColor));
|
|
79
|
+
return /* @__PURE__ */ jsx("button", {
|
|
80
|
+
type: "button",
|
|
81
|
+
id: `${popupId}-swatch-${encodeURIComponent(color)}`,
|
|
82
|
+
ref: (node) => {
|
|
83
|
+
swatchRefs.current[color] = node;
|
|
84
|
+
},
|
|
85
|
+
role: "radio",
|
|
86
|
+
"aria-label": label,
|
|
87
|
+
"aria-checked": selected,
|
|
88
|
+
tabIndex: index === selectedIndex ? 0 : -1,
|
|
89
|
+
disabled,
|
|
90
|
+
className: cn("tw-box-border tw-h-[21px] tw-w-[21px] tw-cursor-pointer tw-border tw-border-solid tw-border-[var(--background-default)] tw-bg-transparent tw-p-0", { "tw-border-[var(--border-neutral-strong)]": selected }),
|
|
91
|
+
onClick: () => {
|
|
92
|
+
if (!selected) onColorSelect(color);
|
|
93
|
+
},
|
|
94
|
+
onKeyDown: (event) => {
|
|
95
|
+
if (event.key === "Escape") {
|
|
96
|
+
event.preventDefault();
|
|
97
|
+
setOpen(false);
|
|
98
|
+
triggerRef.current?.focus();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (event.key === "ArrowRight" || event.key === "ArrowDown") {
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
swatchRefs.current[swatchOrder[(index + 1) % swatchOrder.length]]?.focus();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
swatchRefs.current[swatchOrder[(index - 1 + swatchOrder.length) % swatchOrder.length]]?.focus();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (event.key === "Home" || event.key === "End") {
|
|
112
|
+
event.preventDefault();
|
|
113
|
+
swatchRefs.current[swatchOrder[event.key === "Home" ? 0 : swatchOrder.length - 1]]?.focus();
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
style: { borderColor: selected ? "var(--border-neutral-strong)" : specialColors.includes(color) ? "var(--border-neutral-subtle)" : color },
|
|
117
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
118
|
+
"aria-hidden": "true",
|
|
119
|
+
className: cn("tw-block tw-h-full tw-w-full", { "tw-m-px tw-h-[17px] tw-w-[17px]": selected }),
|
|
120
|
+
style: { backgroundColor: color }
|
|
121
|
+
})
|
|
122
|
+
}, `${label}-${color}`);
|
|
123
|
+
};
|
|
50
124
|
const overlay = /* @__PURE__ */ jsxs("div", {
|
|
125
|
+
id: popupId,
|
|
126
|
+
role: "radiogroup",
|
|
127
|
+
"aria-label": t.ColorPicker.standardColor,
|
|
51
128
|
className: "tw-relative tw-box-border tw-w-[253px] tw-rounded-sm tw-bg-[var(--background-default)] tw-p-[8px_7px]",
|
|
52
129
|
ref: overlayRef,
|
|
130
|
+
onKeyDown: (event) => {
|
|
131
|
+
if (event.key === "Escape") {
|
|
132
|
+
event.preventDefault();
|
|
133
|
+
setOpen(false);
|
|
134
|
+
triggerRef.current?.focus();
|
|
135
|
+
}
|
|
136
|
+
},
|
|
53
137
|
children: [
|
|
54
138
|
/* @__PURE__ */ jsxs("div", {
|
|
55
139
|
className: "tw-flex tw-items-center tw-text-xs",
|
|
56
140
|
children: [/* @__PURE__ */ jsx("div", {
|
|
57
|
-
className:
|
|
58
|
-
|
|
59
|
-
if (disabled) return;
|
|
60
|
-
if (defaultColor === value) return;
|
|
61
|
-
onColorSelect(defaultColor);
|
|
62
|
-
},
|
|
63
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
64
|
-
className: "tw-size-full",
|
|
65
|
-
style: { backgroundColor: defaultColor }
|
|
66
|
-
})
|
|
141
|
+
className: "tw-mr-2",
|
|
142
|
+
children: renderSwatch(defaultColor, t.ColorPicker.default)
|
|
67
143
|
}), t.ColorPicker.default]
|
|
68
144
|
}),
|
|
69
145
|
/* @__PURE__ */ jsxs("div", {
|
|
70
146
|
className: "tw-mt-1.5 tw-text-xs",
|
|
71
147
|
children: [/* @__PURE__ */ jsx("p", { children: t.ColorPicker.standardColor }), /* @__PURE__ */ jsx("div", {
|
|
72
148
|
className: "tw-mt-0.5 tw-flex tw-flex-wrap tw-justify-evenly tw-gap-[4px_2px] tw-text-[0px]",
|
|
73
|
-
children: colors.map((color) =>
|
|
74
|
-
const isSelected = color === value;
|
|
75
|
-
return /* @__PURE__ */ jsx("div", {
|
|
76
|
-
className: cn("tw-box-border tw-h-[21px] tw-w-[21px] tw-cursor-pointer tw-border tw-border-solid tw-border-[var(--background-default)]", { "tw-border-[var(--border-neutral-strong)]": isSelected }),
|
|
77
|
-
onClick: () => {
|
|
78
|
-
if (color === value) return;
|
|
79
|
-
onColorSelect(color);
|
|
80
|
-
},
|
|
81
|
-
style: { borderColor: isSelected ? "var(--border-neutral-strong)" : specialColors.includes(color) ? "var(--border-neutral-subtle)" : color },
|
|
82
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
83
|
-
className: cn("tw-h-full tw-w-full", { "tw-m-px tw-h-[17px] tw-w-[17px]": isSelected }),
|
|
84
|
-
style: { backgroundColor: color }
|
|
85
|
-
})
|
|
86
|
-
}, color);
|
|
87
|
-
})
|
|
149
|
+
children: colors.map((color) => renderSwatch(color, color))
|
|
88
150
|
})]
|
|
89
151
|
}),
|
|
90
152
|
/* @__PURE__ */ jsxs("div", {
|
|
91
153
|
className: "tw-mt-1.5 tw-text-xs",
|
|
92
154
|
children: [/* @__PURE__ */ jsx("p", { children: t.ColorPicker.recentlyUsed }), /* @__PURE__ */ jsx("div", {
|
|
93
155
|
className: "tw-mt-0.5 tw-flex tw-flex-wrap tw-justify-start tw-gap-[4px_2px] tw-text-[0px]",
|
|
94
|
-
children: recentColors.map((color) =>
|
|
95
|
-
const isSelected = color === value;
|
|
96
|
-
return /* @__PURE__ */ jsx("div", {
|
|
97
|
-
className: cn("tw-box-border tw-h-[21px] tw-w-[21px] tw-cursor-pointer tw-border tw-border-solid tw-border-[var(--background-default)]", { "tw-border-[var(--border-neutral-strong)]": isSelected }),
|
|
98
|
-
onClick: () => {
|
|
99
|
-
if (color === value) return;
|
|
100
|
-
onColorSelect(color);
|
|
101
|
-
},
|
|
102
|
-
style: { borderColor: isSelected ? "var(--border-neutral-strong)" : specialColors.includes(color) ? "var(--border-neutral-subtle)" : color },
|
|
103
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
104
|
-
className: cn("tw-h-full tw-w-full", { "tw-m-px tw-h-[17px] tw-w-[17px]": isSelected }),
|
|
105
|
-
style: { backgroundColor: color }
|
|
106
|
-
})
|
|
107
|
-
}, color);
|
|
108
|
-
})
|
|
156
|
+
children: recentColors.map((color) => renderSwatch(color, color))
|
|
109
157
|
})]
|
|
110
158
|
})
|
|
111
159
|
]
|
|
@@ -116,13 +164,20 @@ function ColorPicker({ className, value, icon, onChange, defaultColor = colors[0
|
|
|
116
164
|
children: /* @__PURE__ */ jsx(Dropdown, {
|
|
117
165
|
trigger: "click",
|
|
118
166
|
open,
|
|
167
|
+
onOpenChange: setOpen,
|
|
119
168
|
disabled,
|
|
120
169
|
placement: "bottom-start",
|
|
121
170
|
overlayClassName: "ald-color-picker-overlay-wrapper",
|
|
122
171
|
dropdownRender: () => {
|
|
123
172
|
return overlay;
|
|
124
173
|
},
|
|
125
|
-
children: /* @__PURE__ */ jsxs("
|
|
174
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
175
|
+
type: "button",
|
|
176
|
+
id: triggerId,
|
|
177
|
+
ref: triggerRef,
|
|
178
|
+
"aria-label": t.ColorPicker.default,
|
|
179
|
+
"aria-controls": popupId,
|
|
180
|
+
"aria-expanded": open,
|
|
126
181
|
className: cn("ald-color-picker-wrapper", "tw-flex tw-flex-row tw-items-center tw-justify-between tw-gap-1 tw-h-7 tw-px-2.5 tw-py-1.5 tw-bg-[var(--background-default)] tw-border tw-border-solid tw-border-[var(--border-neutral-subtle)] tw-box-border tw-cursor-pointer tw-rounded tw-text-[var(--content-primary)] tw-transition-[border] tw-duration-500 tw-ease-in-out", {
|
|
127
182
|
"tw-border-[var(--border-brand-subtle)]": open && bordered !== false,
|
|
128
183
|
"tw-border-[var(--border-neutral-subtle)] tw-bg-[var(--background-neutral-on-subtle)]": disabled,
|
|
@@ -131,7 +186,18 @@ function ColorPicker({ className, value, icon, onChange, defaultColor = colors[0
|
|
|
131
186
|
"hover:tw-border-[var(--action-ghost-normal)]": bordered === false
|
|
132
187
|
}),
|
|
133
188
|
onClick: (e) => {
|
|
134
|
-
if (disabled)
|
|
189
|
+
if (disabled) {
|
|
190
|
+
e.stopPropagation();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
setOpen((current) => !current);
|
|
194
|
+
},
|
|
195
|
+
onKeyDown: (event) => {
|
|
196
|
+
if (disabled) return;
|
|
197
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Enter" || event.key === " ") {
|
|
198
|
+
event.preventDefault();
|
|
199
|
+
setOpen(true);
|
|
200
|
+
}
|
|
135
201
|
},
|
|
136
202
|
children: [icon ? /* @__PURE__ */ jsxs("div", {
|
|
137
203
|
className: "tw-relative -tw-top-px",
|