@aloudata/aloudata-design 3.0.11 → 3.0.13
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/Checkbox/index.js +2 -1
- package/dist/Checkbox/index.js.map +1 -1
- package/dist/Checkbox/type.d.ts +1 -0
- package/dist/DataPreviewTable/index.js +51 -47
- package/dist/DataPreviewTable/index.js.map +1 -1
- package/dist/Drawer/index.d.ts +1 -0
- package/dist/Drawer/index.js +2 -2
- package/dist/Drawer/index.js.map +1 -1
- package/dist/Dropdown/index.js +86 -12
- package/dist/Dropdown/index.js.map +1 -1
- package/dist/Form/index.d.ts +12 -21
- package/dist/Form/index.js +2 -1
- package/dist/Form/index.js.map +1 -1
- package/dist/Input/components/Input/index.d.ts +1 -1
- package/dist/Input/components/Input/index.js +3 -2
- package/dist/Input/components/Input/index.js.map +1 -1
- package/dist/Input/components/Password/index.d.ts +3 -2
- package/dist/Input/components/Password/index.js +2 -2
- package/dist/Input/components/Password/index.js.map +1 -1
- package/dist/Input/components/TextArea/index.d.ts +1 -1
- package/dist/Input/components/TextArea/index.js +5 -1
- package/dist/Input/components/TextArea/index.js.map +1 -1
- package/dist/Popconfirm/index.d.ts +2 -0
- package/dist/Popconfirm/index.js +61 -36
- package/dist/Popconfirm/index.js.map +1 -1
- package/dist/Popover/index.d.ts +6 -0
- package/dist/Popover/index.js +33 -3
- package/dist/Popover/index.js.map +1 -1
- package/dist/Select/BaseSelect.js +40 -3
- package/dist/Select/BaseSelect.js.map +1 -1
- package/dist/Select/interface.d.ts +1 -1
- package/dist/Tabs/index.d.ts +1 -0
- package/dist/Tabs/index.js +16 -6
- package/dist/Tabs/index.js.map +1 -1
- package/dist/Tree/Tree2.js +17 -5
- package/dist/Tree/Tree2.js.map +1 -1
- package/dist/Typography/index.d.ts +10 -7
- package/dist/Typography/index.js +38 -15
- package/dist/Typography/index.js.map +1 -1
- package/dist/Upload/index.d.ts +1 -1
- package/dist/Upload/index.js.map +1 -1
- package/dist/aloudata-design.css +1 -1
- package/package.json +1 -1
package/dist/Form/index.d.ts
CHANGED
|
@@ -8,6 +8,13 @@ import { ValidateStatus } from './FormItemContext.js';
|
|
|
8
8
|
* We override to keep backward compatibility.
|
|
9
9
|
*/
|
|
10
10
|
type LooseNamePath = string | number | (string | number)[];
|
|
11
|
+
type ColConfig = {
|
|
12
|
+
flex?: string | number;
|
|
13
|
+
span?: number;
|
|
14
|
+
offset?: number;
|
|
15
|
+
style?: React.CSSProperties;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
};
|
|
11
18
|
/**
|
|
12
19
|
* FormInstance — extends rc-field-form FormInstance with loose-typed overloads
|
|
13
20
|
* to maintain antd v4 backward compatibility. Uses intersection so that both
|
|
@@ -33,9 +40,7 @@ export type FormInstance<Values = any> = RcFormInstance<Values> & {
|
|
|
33
40
|
resetFields(fields?: LooseNamePath[]): void;
|
|
34
41
|
validateFields(nameList?: LooseNamePath[]): Promise<Values>;
|
|
35
42
|
/** Scroll to field position (antd-compatible extension) */
|
|
36
|
-
scrollToField?(name: LooseNamePath, options?:
|
|
37
|
-
behavior?: 'smooth' | 'auto';
|
|
38
|
-
}): void;
|
|
43
|
+
scrollToField?(name: LooseNamePath, options?: ScrollIntoViewOptions): void;
|
|
39
44
|
};
|
|
40
45
|
export interface FormProps<Values = any> extends Omit<RcFormProps, 'form'> {
|
|
41
46
|
form?: FormInstance<Values>;
|
|
@@ -43,14 +48,8 @@ export interface FormProps<Values = any> extends Omit<RcFormProps, 'form'> {
|
|
|
43
48
|
size?: 'small' | 'middle' | 'large';
|
|
44
49
|
colon?: boolean;
|
|
45
50
|
disabled?: boolean;
|
|
46
|
-
labelCol?:
|
|
47
|
-
|
|
48
|
-
offset?: number;
|
|
49
|
-
};
|
|
50
|
-
wrapperCol?: {
|
|
51
|
-
span?: number;
|
|
52
|
-
offset?: number;
|
|
53
|
-
};
|
|
51
|
+
labelCol?: ColConfig;
|
|
52
|
+
wrapperCol?: ColConfig;
|
|
54
53
|
className?: string;
|
|
55
54
|
style?: React.CSSProperties;
|
|
56
55
|
requiredMark?: boolean | 'optional';
|
|
@@ -80,16 +79,8 @@ export interface FormItemProps {
|
|
|
80
79
|
title?: React.ReactNode;
|
|
81
80
|
icon?: React.ReactNode;
|
|
82
81
|
};
|
|
83
|
-
labelCol?:
|
|
84
|
-
|
|
85
|
-
offset?: number;
|
|
86
|
-
[key: string]: any;
|
|
87
|
-
};
|
|
88
|
-
wrapperCol?: {
|
|
89
|
-
span?: number;
|
|
90
|
-
offset?: number;
|
|
91
|
-
[key: string]: any;
|
|
92
|
-
};
|
|
82
|
+
labelCol?: ColConfig;
|
|
83
|
+
wrapperCol?: ColConfig;
|
|
93
84
|
validateStatus?: ValidateStatus;
|
|
94
85
|
colon?: boolean;
|
|
95
86
|
trigger?: string;
|
package/dist/Form/index.js
CHANGED
|
@@ -10,7 +10,8 @@ import FieldContext from "rc-field-form/es/FieldContext";
|
|
|
10
10
|
/** Convert a 24-column span/offset to Tailwind-compatible inline styles */
|
|
11
11
|
function colStyle(col) {
|
|
12
12
|
if (!col) return void 0;
|
|
13
|
-
const s = {};
|
|
13
|
+
const s = { ...col.style };
|
|
14
|
+
if (col.flex !== null && col.flex !== void 0) s.flex = col.flex;
|
|
14
15
|
if (col.span !== null && col.span !== void 0) {
|
|
15
16
|
s.width = `${col.span / 24 * 100}%`;
|
|
16
17
|
s.flex = `0 0 ${col.span / 24 * 100}%`;
|
package/dist/Form/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/Form/index.tsx"],"sourcesContent":["import RcForm, {\n Field,\n FormInstance as RcFormInstance,\n FormProvider,\n List,\n useForm as rcUseForm,\n useWatch,\n} from 'rc-field-form';\nimport type { FormProps as RcFormProps } from 'rc-field-form';\nimport FieldContext from 'rc-field-form/es/FieldContext';\nimport type { Rule, RuleObject, RuleRender } from 'rc-field-form/es/interface';\nimport type { Meta, NamePath } from 'rc-field-form/es/interface';\nimport React, { forwardRef, useContext, useMemo } from 'react';\nimport SizeContext, {\n SizeContextProvider,\n} from '../ConfigProvider/sizeContext';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport { cn } from '../lib/utils';\nimport {\n FormContext,\n FormItemInputContext,\n type ValidateStatus,\n} from './FormItemContext';\n\n/**\n * Loose NamePath: accepts string, number, or array of them.\n * antd v4 uses loose paths; rc-field-form v2 uses strict DeepNamePath.\n * We override to keep backward compatibility.\n */\ntype LooseNamePath = string | number | (string | number)[];\n\n/**\n * FormInstance — extends rc-field-form FormInstance with loose-typed overloads\n * to maintain antd v4 backward compatibility. Uses intersection so that both\n * strict DeepNamePath and loose LooseNamePath signatures are accepted.\n */\nexport type FormInstance<Values = any> = RcFormInstance<Values> & {\n getFieldValue(name: LooseNamePath): any;\n setFieldValue(name: LooseNamePath, value: any): void;\n setFieldsValue(values: Record<string, any>): void;\n getFieldsValue(): Values;\n getFieldsValue(\n nameList: LooseNamePath[] | true,\n filterFunc?: (meta: Meta) => boolean,\n ): any;\n getFieldError(name: LooseNamePath): string[];\n getFieldsError(\n nameList?: LooseNamePath[],\n ): { name: (string | number)[]; errors: string[] }[];\n getFieldWarning(name: LooseNamePath): string[];\n isFieldTouched(name: LooseNamePath): boolean;\n isFieldsTouched(\n nameList?: LooseNamePath[],\n allFieldsTouched?: boolean,\n ): boolean;\n isFieldValidating(name: LooseNamePath): boolean;\n isFieldsValidating(nameList?: LooseNamePath[]): boolean;\n setFields(fields: FieldData[]): void;\n resetFields(fields?: LooseNamePath[]): void;\n validateFields(nameList?: LooseNamePath[]): Promise<Values>;\n /** Scroll to field position (antd-compatible extension) */\n scrollToField?(\n name: LooseNamePath,\n options?: { behavior?: 'smooth' | 'auto' },\n ): void;\n};\n\n// FormProps compatible with antd\nexport interface FormProps<Values = any> extends Omit<RcFormProps, 'form'> {\n form?: FormInstance<Values>;\n layout?: 'horizontal' | 'vertical' | 'inline';\n size?: 'small' | 'middle' | 'large';\n colon?: boolean;\n disabled?: boolean;\n labelCol?: { span?: number; offset?: number };\n wrapperCol?: { span?: number; offset?: number };\n className?: string;\n style?: React.CSSProperties;\n requiredMark?: boolean | 'optional';\n labelWidth?: number;\n labelAlign?: 'left' | 'right';\n}\n\n// FormItemProps\nexport interface FormItemProps {\n name?: NamePath;\n label?: React.ReactNode;\n rules?: Rule[];\n children?: React.ReactNode | ((form: RcFormInstance) => React.ReactNode);\n className?: string;\n style?: React.CSSProperties;\n required?: boolean;\n hidden?: boolean;\n initialValue?: any;\n dependencies?: NamePath[];\n shouldUpdate?: boolean | ((prevValues: any, curValues: any) => boolean);\n help?: React.ReactNode;\n extra?: React.ReactNode;\n validateTrigger?: string | string[];\n valuePropName?: string;\n getValueFromEvent?: (...args: any[]) => any;\n noStyle?: boolean;\n labelWidth?: number;\n tooltip?:\n | React.ReactNode\n | { title?: React.ReactNode; icon?: React.ReactNode };\n labelCol?: { span?: number; offset?: number; [key: string]: any };\n wrapperCol?: { span?: number; offset?: number; [key: string]: any };\n validateStatus?: ValidateStatus;\n colon?: boolean;\n trigger?: string;\n normalize?: (value: any, prevValue: any, allValues: any) => any;\n getValueProps?: (value: any) => Record<string, any>;\n}\n\n/** antd v4 compat: FormLabelAlign */\nexport type FormLabelAlign = 'left' | 'right';\n\n/** antd v4 compat: FieldData */\nexport type FieldData = {\n name: NamePath;\n value?: any;\n touched?: boolean;\n validating?: boolean;\n errors?: string[];\n};\n\nexport interface ErrorListProps {\n errors?: React.ReactNode[];\n help?: React.ReactNode;\n className?: string;\n}\n\nexport type FormListFieldData = {\n name: number;\n key: number;\n isListField: boolean;\n};\n\nexport type FormListOperation = {\n add: (defaultValue?: any, insertIndex?: number) => void;\n remove: (index: number | number[]) => void;\n move: (from: number, to: number) => void;\n};\n\nexport type FormListProps = {\n name: NamePath;\n rules?: Rule[];\n children: (\n fields: FormListFieldData[],\n operation: FormListOperation,\n meta: { errors: React.ReactNode[] },\n ) => React.ReactNode;\n initialValue?: any[];\n};\n\n// ============== Helpers ==============\n\n/** Convert a 24-column span/offset to Tailwind-compatible inline styles */\nfunction colStyle(col?: {\n span?: number;\n offset?: number;\n}): React.CSSProperties | undefined {\n if (!col) return undefined;\n const s: React.CSSProperties = {};\n if (col.span !== null && col.span !== undefined) {\n // 24-column grid: width = span / 24 * 100%\n s.width = `${(col.span / 24) * 100}%`;\n s.flex = `0 0 ${(col.span / 24) * 100}%`;\n }\n if (col.offset !== null && col.offset !== undefined && col.offset > 0) {\n s.marginLeft = `${(col.offset / 24) * 100}%`;\n }\n return s;\n}\n\nfunction mergeControlProps(\n childProps: Record<string, any>,\n control: Record<string, any>,\n) {\n const mergedControl = { ...control };\n\n Object.keys(control).forEach((key) => {\n const controlHandler = control[key];\n const childHandler = childProps[key];\n\n if (\n typeof controlHandler === 'function' &&\n typeof childHandler === 'function'\n ) {\n mergedControl[key] = (...args: any[]) => {\n controlHandler(...args);\n childHandler(...args);\n };\n }\n });\n\n return mergedControl;\n}\n\n// ============== Form ==============\n\nconst AldForm = forwardRef((props: any, ref: any) => {\n const contextSize = useContext(SizeContext);\n const {\n children,\n size = contextSize,\n labelWidth,\n style = {},\n className,\n layout = 'horizontal',\n disabled,\n labelCol,\n wrapperCol,\n colon = false,\n requiredMark,\n labelAlign,\n ...restProps\n } = props;\n const customStyle = {\n ...style,\n ...(labelWidth ? { '--label-width': `${labelWidth}px` } : {}),\n ...(labelAlign ? { '--label-align': labelAlign } : {}),\n };\n\n const formContextValue = useMemo(\n () => ({\n layout,\n labelCol,\n wrapperCol,\n colon,\n requiredMark,\n labelWidth,\n labelAlign,\n }),\n [layout, labelCol, wrapperCol, colon, requiredMark, labelWidth, labelAlign],\n );\n\n return (\n <FormContext.Provider value={formContextValue}>\n <DisabledContext.Provider value={disabled}>\n <SizeContextProvider size={size}>\n <RcForm\n style={customStyle}\n className={cn(\n 'ald-form ant-form',\n `ald-form-${layout}`,\n `ant-form-${layout}`,\n className,\n )}\n {...restProps}\n ref={ref}\n >\n {children}\n </RcForm>\n </SizeContextProvider>\n </DisabledContext.Provider>\n </FormContext.Provider>\n );\n}) as <Values = any>(\n props: React.PropsWithChildren<FormProps<Values>> & {\n ref?: React.Ref<FormInstance<Values>>;\n labelWidth?: number;\n },\n) => React.ReactElement;\n\n// ============== Form.Item ==============\n\ninterface IFormItemProps extends FormItemProps {\n labelWidth?: number;\n labelAlign?: 'left' | 'right';\n}\n\n/** Derive status from meta or manual validateStatus */\nfunction deriveStatus(\n meta?: Meta,\n validateStatus?: ValidateStatus,\n): ValidateStatus {\n if (validateStatus) return validateStatus;\n if (!meta) return '';\n if (meta.validating) return 'validating';\n if (meta.errors && meta.errors.length > 0) return 'error';\n if (meta.warnings && meta.warnings.length > 0) return 'warning';\n if (meta.touched) return 'success';\n return '';\n}\n\n/** Status-based border class for the control wrapper */\nfunction statusClassName(status: ValidateStatus): string {\n switch (status) {\n case 'error':\n return 'ald-form-item-has-error';\n case 'warning':\n return 'ald-form-item-has-warning';\n case 'success':\n return 'ald-form-item-has-success';\n case 'validating':\n return 'ald-form-item-is-validating';\n default:\n return '';\n }\n}\n\n/** Render the inner label + control layout, receiving meta from Field */\nfunction FormItemLayout({\n label,\n children,\n meta,\n help,\n extra,\n required,\n rules,\n hidden,\n className,\n customStyle,\n noStyle,\n labelCol: itemLabelCol,\n wrapperCol: itemWrapperCol,\n validateStatus: manualStatus,\n colon: itemColon,\n formContext,\n}: {\n label?: React.ReactNode;\n children: React.ReactNode;\n meta?: Meta;\n help?: React.ReactNode;\n extra?: React.ReactNode;\n required?: boolean;\n rules?: Rule[];\n hidden?: boolean;\n className?: string;\n customStyle?: React.CSSProperties;\n noStyle?: boolean;\n labelCol?: { span?: number; offset?: number };\n wrapperCol?: { span?: number; offset?: number };\n validateStatus?: ValidateStatus;\n colon?: boolean;\n formContext: {\n layout?: string;\n labelCol?: { span?: number; offset?: number };\n wrapperCol?: { span?: number; offset?: number };\n colon?: boolean;\n requiredMark?: boolean | 'optional';\n labelWidth?: number;\n };\n}) {\n const status = deriveStatus(meta, manualStatus);\n const errors = useMemo(() => meta?.errors ?? [], [meta?.errors]);\n const warnings = useMemo(() => meta?.warnings ?? [], [meta?.warnings]);\n\n // Provide status context to child controls\n const itemInputContextValue = useMemo(\n () => ({\n status,\n isFormItemInput: true,\n errors,\n warnings,\n }),\n [status, errors, warnings],\n );\n\n if (noStyle) {\n return <>{children}</>;\n }\n\n // Determine if we should show required mark\n const { requiredMark } = formContext;\n const rulesRequired =\n rules && rules.some((r: any) => typeof r === 'object' && r && r.required);\n const isRequired =\n required || rulesRequired || (meta && (meta as any).required);\n const showRequired = requiredMark !== false && isRequired;\n const showOptional = requiredMark === 'optional' && !isRequired;\n\n // Resolve cols: item-level overrides form-level\n const resolvedLabelCol = itemLabelCol ?? formContext.labelCol;\n const resolvedWrapperCol = itemWrapperCol ?? formContext.wrapperCol;\n const layout = formContext.layout || 'horizontal';\n const showColon =\n (itemColon ?? formContext.colon) !== false && layout === 'horizontal';\n\n // Decide whether to use grid-style layout\n const useGridLayout =\n layout === 'horizontal' && (resolvedLabelCol || resolvedWrapperCol);\n\n // Determine display errors: if help is provided, show help instead of validation errors\n const displayMessages = help !== null && help !== undefined ? [help] : errors;\n const hasError = status === 'error' || (errors.length > 0 && help === null);\n const hasWarning =\n status === 'warning' || (warnings.length > 0 && help === null);\n const hasLabel = label !== null && label !== undefined && label !== '';\n\n const labelNode = hasLabel ? (\n <div\n className={cn(\n 'ald-form-item-label ant-form-item-label',\n // tw-block 不能省:label 容器同时挂了 ant-form-item-label 兼容 class,\n // 消费方残留的 antd 样式会把它设为 inline-block,导致 vertical 布局下\n // label 缩成内容宽而非整行铺在控件上方\n layout === 'vertical' && 'tw-mb-1 tw-block',\n layout === 'horizontal' && 'tw-mr-3 tw-shrink-0',\n )}\n style={useGridLayout ? colStyle(resolvedLabelCol) : undefined}\n >\n <label\n className={cn(\n 'tw-text-sm tw-font-medium tw-text-[var(--alias-colors-text-subtle,var(--content-secondary))]',\n !showColon && 'ant-form-item-no-colon',\n )}\n >\n {showRequired && (\n <span className=\"tw-mr-1 tw-text-[var(--content-negative-primary)]\">\n *\n </span>\n )}\n {label}\n {showOptional && (\n <span className=\"tw-ml-1 tw-text-xs tw-font-normal tw-text-[var(--content-secondary)]\">\n (optional)\n </span>\n )}\n {showColon && label ? ':' : null}\n </label>\n </div>\n ) : null;\n\n const controlNode = (\n <div\n className={cn(\n 'ald-form-item-control ant-form-item-control',\n // tw-min-w-0 必须同时加:flex item 默认 min-width:auto = min-content,\n // 子元素 intrinsic min-content(如多选 Select 的 tag 集合)会反向把 control 撑超出父\n // form-item 分配的宽度,再让 rc-overflow 误判\"全部能塞下\"导致不折叠 +N。\n // 实测:指标定义\"更多筛选\"浮窗里 8 个特性 tag 横向溢出浮窗边界即此因\n // (release-2.3_test 复现);这里钳住 min-width 后 Overflow 测量恢复正确。\n layout === 'horizontal' && 'tw-min-w-0 tw-flex-1',\n )}\n style={useGridLayout ? colStyle(resolvedWrapperCol) : undefined}\n >\n <FormItemInputContext.Provider value={itemInputContextValue}>\n <div className=\"ald-form-item-control-input\">\n <div className=\"ald-form-item-control-input-content\">{children}</div>\n </div>\n </FormItemInputContext.Provider>\n {/* 始终渲染错误容器,避免 DOM 增删触发 Radix FocusScope MutationObserver 劫持焦点 */}\n <div\n className={cn(\n 'ald-form-item-explain ant-form-item-explain tw-text-xs tw-transition-all tw-duration-200',\n displayMessages.length > 0 && 'tw-mt-1',\n hasError && 'tw-text-[var(--content-negative-secondary)]',\n hasWarning &&\n !hasError &&\n 'tw-text-[color:var(--content-warning-primary,#faad14)]',\n !hasError &&\n !hasWarning &&\n help !== null &&\n help !== undefined &&\n 'tw-text-[var(--content-secondary)]',\n )}\n style={displayMessages.length === 0 ? { display: 'none' } : undefined}\n >\n {displayMessages.map((msg, i) => (\n <div key={i}>{msg}</div>\n ))}\n </div>\n {extra && (\n <div className=\"ald-form-item-extra tw-mt-1 tw-text-xs tw-text-[var(--content-secondary)]\">\n {extra}\n </div>\n )}\n </div>\n );\n\n return (\n <div\n className={cn(\n 'ald-form-item ant-form-item ant-row tw-mb-6',\n hidden && 'tw-hidden',\n showRequired && 'ald-form-item-required',\n statusClassName(status),\n layout === 'horizontal' && 'tw-flex tw-flex-row tw-items-start',\n layout === 'inline' &&\n 'tw-mr-4 tw-inline-flex tw-flex-row tw-items-start',\n className,\n )}\n style={customStyle as React.CSSProperties}\n >\n {labelNode}\n {controlNode}\n </div>\n );\n}\n\nconst AldFormItem = function (props: IFormItemProps) {\n const {\n labelWidth,\n style = {},\n label,\n name,\n rules,\n children,\n className,\n required,\n hidden,\n initialValue,\n dependencies,\n shouldUpdate,\n help,\n extra,\n validateTrigger,\n valuePropName,\n getValueFromEvent,\n normalize,\n getValueProps,\n noStyle,\n labelCol,\n wrapperCol,\n validateStatus,\n colon,\n trigger,\n } = props;\n\n const formContext = useContext(FormContext);\n\n const customStyle = {\n ...style,\n ...(labelWidth ? { '--label-width': `${labelWidth}px` } : {}),\n ...(props.labelAlign ? { '--label-align': props.labelAlign } : {}),\n };\n\n // If no name is provided (e.g. a submit button wrapper), we don't need Field\n // Also when shouldUpdate or dependencies are used without name, Field is still needed for re-render\n const needField =\n (name !== null && name !== undefined) ||\n (shouldUpdate !== null && shouldUpdate !== undefined) ||\n (dependencies !== null && dependencies !== undefined);\n\n if (!needField) {\n return (\n <FormItemLayout\n label={label}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n noStyle={noStyle}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {children as React.ReactNode}\n </FormItemLayout>\n );\n }\n\n return (\n <Field\n name={name}\n rules={rules}\n initialValue={initialValue}\n dependencies={dependencies}\n shouldUpdate={shouldUpdate}\n validateTrigger={validateTrigger}\n trigger={trigger}\n valuePropName={valuePropName}\n getValueFromEvent={getValueFromEvent}\n normalize={normalize}\n getValueProps={getValueProps}\n >\n {(control, meta, form) => {\n // If children is a render function (shouldUpdate / dependencies pattern),\n // call it with the form instance and wrap in layout\n if (typeof children === 'function') {\n const childContent = (\n children as (form: RcFormInstance) => React.ReactNode\n )(form);\n if (noStyle) {\n return childContent;\n }\n return (\n <FormItemLayout\n label={label}\n meta={meta}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n noStyle={noStyle}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {childContent}\n </FormItemLayout>\n );\n }\n\n // For noStyle, just clone with control props\n if (noStyle) {\n if (React.isValidElement(children)) {\n return React.cloneElement(\n children as React.ReactElement<any>,\n mergeControlProps(\n (children as React.ReactElement<any>).props,\n control,\n ),\n );\n }\n return children;\n }\n\n // Clone control props onto the single child element\n let childNode: React.ReactNode = children;\n if (React.isValidElement(children)) {\n childNode = React.cloneElement(\n children as React.ReactElement<any>,\n mergeControlProps(\n (children as React.ReactElement<any>).props,\n control,\n ),\n );\n }\n\n return (\n <FormItemLayout\n label={label}\n meta={meta}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {childNode}\n </FormItemLayout>\n );\n }}\n </Field>\n );\n};\n\nfunction useFormItemStatus() {\n const ctx = useContext(FormItemInputContext);\n return {\n status: ctx.status,\n errors: ctx.errors ?? [],\n warnings: ctx.warnings ?? [],\n };\n}\n\nAldFormItem.useStatus = useFormItemStatus;\n\n// ============== ErrorList ==============\n\nfunction ErrorListComponent(props: ErrorListProps) {\n const { errors, className } = props;\n if (!errors || errors.length === 0) return null;\n return (\n <div className={cn('ald-form-error-list', className)}>\n {errors.map((err, i) => (\n <div\n key={i}\n className=\"tw-text-xs tw-text-[var(--content-negative-secondary)]\"\n >\n {err}\n </div>\n ))}\n </div>\n );\n}\n\n// ============== useFormInstance ==============\n\nfunction useFormInstance<T = any>(): FormInstance<T> {\n const form = useContext(FieldContext);\n return form as unknown as FormInstance<T>;\n}\n\n// ============== Compound component ==============\n\ntype InternalFormType = typeof AldForm;\ntype CompoundedComponent = InternalFormType & {\n useForm: <T = any>(...args: any[]) => [FormInstance<T>];\n useFormInstance: typeof useFormInstance;\n /** Loose-typed useWatch for antd v4 compat */\n useWatch: <T = any>(name: LooseNamePath, form?: FormInstance) => T;\n Item: typeof AldFormItem;\n List: typeof List;\n ErrorList: typeof ErrorListComponent;\n Provider: typeof FormProvider;\n create: () => void;\n};\n\nconst Form = AldForm as CompoundedComponent;\n\nForm.Item = AldFormItem;\nForm.List = List;\nForm.ErrorList = ErrorListComponent;\nForm.useForm = rcUseForm as CompoundedComponent['useForm'];\nForm.useFormInstance = useFormInstance;\nForm.useWatch = useWatch;\nForm.Provider = FormProvider;\nForm.create = () => {\n console.warn('Form.create is deprecated. Please use Form.useForm() instead.');\n};\n\nexport type { Rule, RuleObject, RuleRender };\nexport default Form;\n"],"mappings":";;;;;;;;;;AA+JA,SAAS,SAAS,KAGkB;AAClC,KAAI,CAAC,IAAK,QAAO;CACjB,MAAM,IAAyB,EAAE;AACjC,KAAI,IAAI,SAAS,QAAQ,IAAI,SAAS,QAAW;AAE/C,IAAE,QAAQ,GAAI,IAAI,OAAO,KAAM,IAAI;AACnC,IAAE,OAAO,OAAQ,IAAI,OAAO,KAAM,IAAI;;AAExC,KAAI,IAAI,WAAW,QAAQ,IAAI,WAAW,UAAa,IAAI,SAAS,EAClE,GAAE,aAAa,GAAI,IAAI,SAAS,KAAM,IAAI;AAE5C,QAAO;;AAGT,SAAS,kBACP,YACA,SACA;CACA,MAAM,gBAAgB,EAAE,GAAG,SAAS;AAEpC,QAAO,KAAK,QAAQ,CAAC,SAAS,QAAQ;EACpC,MAAM,iBAAiB,QAAQ;EAC/B,MAAM,eAAe,WAAW;AAEhC,MACE,OAAO,mBAAmB,cAC1B,OAAO,iBAAiB,WAExB,eAAc,QAAQ,GAAG,SAAgB;AACvC,kBAAe,GAAG,KAAK;AACvB,gBAAa,GAAG,KAAK;;GAGzB;AAEF,QAAO;;AAKT,IAAM,UAAU,YAAY,OAAY,QAAa;CACnD,MAAM,cAAc,WAAW,YAAY;CAC3C,MAAM,EACJ,UACA,OAAO,aACP,YACA,QAAQ,EAAE,EACV,WACA,SAAS,cACT,UACA,UACA,YACA,QAAQ,OACR,cACA,YACA,GAAG,cACD;CACJ,MAAM,cAAc;EAClB,GAAG;EACH,GAAI,aAAa,EAAE,iBAAiB,GAAG,WAAW,KAAK,GAAG,EAAE;EAC5D,GAAI,aAAa,EAAE,iBAAiB,YAAY,GAAG,EAAE;EACtD;CAED,MAAM,mBAAmB,eAChB;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACD,GACD;EAAC;EAAQ;EAAU;EAAY;EAAO;EAAc;EAAY;EAAW,CAC5E;AAED,QACE,oBAAC,YAAY,UAAb;EAAsB,OAAO;YAC3B,oBAAC,gBAAgB,UAAjB;GAA0B,OAAO;aAC/B,oBAAC,qBAAD;IAA2B;cACzB,oBAAC,QAAD;KACE,OAAO;KACP,WAAW,GACT,qBACA,YAAY,UACZ,YAAY,UACZ,UACD;KACD,GAAI;KACC;KAEJ;KACM,CAAA;IACW,CAAA;GACG,CAAA;EACN,CAAA;EAEzB;;AAeF,SAAS,aACP,MACA,gBACgB;AAChB,KAAI,eAAgB,QAAO;AAC3B,KAAI,CAAC,KAAM,QAAO;AAClB,KAAI,KAAK,WAAY,QAAO;AAC5B,KAAI,KAAK,UAAU,KAAK,OAAO,SAAS,EAAG,QAAO;AAClD,KAAI,KAAK,YAAY,KAAK,SAAS,SAAS,EAAG,QAAO;AACtD,KAAI,KAAK,QAAS,QAAO;AACzB,QAAO;;;AAIT,SAAS,gBAAgB,QAAgC;AACvD,SAAQ,QAAR;EACE,KAAK,QACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK,aACH,QAAO;EACT,QACE,QAAO;;;;AAKb,SAAS,eAAe,EACtB,OACA,UACA,MACA,MACA,OACA,UACA,OACA,QACA,WACA,aACA,SACA,UAAU,cACV,YAAY,gBACZ,gBAAgB,cAChB,OAAO,WACP,eAyBC;CACD,MAAM,SAAS,aAAa,MAAM,aAAa;CAC/C,MAAM,SAAS,cAAc,MAAM,UAAU,EAAE,EAAE,CAAC,MAAM,OAAO,CAAC;CAChE,MAAM,WAAW,cAAc,MAAM,YAAY,EAAE,EAAE,CAAC,MAAM,SAAS,CAAC;CAGtE,MAAM,wBAAwB,eACrB;EACL;EACA,iBAAiB;EACjB;EACA;EACD,GACD;EAAC;EAAQ;EAAQ;EAAS,CAC3B;AAED,KAAI,QACF,QAAO,oBAAA,UAAA,EAAG,UAAY,CAAA;CAIxB,MAAM,EAAE,iBAAiB;CACzB,MAAM,gBACJ,SAAS,MAAM,MAAM,MAAW,OAAO,MAAM,YAAY,KAAK,EAAE,SAAS;CAC3E,MAAM,aACJ,YAAY,iBAAkB,QAAS,KAAa;CACtD,MAAM,eAAe,iBAAiB,SAAS;CAC/C,MAAM,eAAe,iBAAiB,cAAc,CAAC;CAGrD,MAAM,mBAAmB,gBAAgB,YAAY;CACrD,MAAM,qBAAqB,kBAAkB,YAAY;CACzD,MAAM,SAAS,YAAY,UAAU;CACrC,MAAM,aACH,aAAa,YAAY,WAAW,SAAS,WAAW;CAG3D,MAAM,gBACJ,WAAW,iBAAiB,oBAAoB;CAGlD,MAAM,kBAAkB,SAAS,QAAQ,SAAS,SAAY,CAAC,KAAK,GAAG;CACvE,MAAM,WAAW,WAAW,WAAY,OAAO,SAAS,KAAK,SAAS;CACtE,MAAM,aACJ,WAAW,aAAc,SAAS,SAAS,KAAK,SAAS;CAG3D,MAAM,YAFW,UAAU,QAAQ,UAAU,UAAa,UAAU,KAGlE,oBAAC,OAAD;EACE,WAAW,GACT,2CAIA,WAAW,cAAc,oBACzB,WAAW,gBAAgB,sBAC5B;EACD,OAAO,gBAAgB,SAAS,iBAAiB,GAAG;YAEpD,qBAAC,SAAD;GACE,WAAW,GACT,gGACA,CAAC,aAAa,yBACf;aAJH;IAMG,gBACC,oBAAC,QAAD;KAAM,WAAU;eAAoD;KAE7D,CAAA;IAER;IACA,gBACC,oBAAC,QAAD;KAAM,WAAU;eAAuE;KAEhF,CAAA;IAER,aAAa,QAAQ,MAAM;IACtB;;EACJ,CAAA,GACJ;CAEJ,MAAM,cACJ,qBAAC,OAAD;EACE,WAAW,GACT,+CAMA,WAAW,gBAAgB,uBAC5B;EACD,OAAO,gBAAgB,SAAS,mBAAmB,GAAG;YAVxD;GAYE,oBAAC,qBAAqB,UAAtB;IAA+B,OAAO;cACpC,oBAAC,OAAD;KAAK,WAAU;eACb,oBAAC,OAAD;MAAK,WAAU;MAAuC;MAAe,CAAA;KACjE,CAAA;IACwB,CAAA;GAEhC,oBAAC,OAAD;IACE,WAAW,GACT,4FACA,gBAAgB,SAAS,KAAK,WAC9B,YAAY,+CACZ,cACE,CAAC,YACD,0DACF,CAAC,YACC,CAAC,cACD,SAAS,QACT,SAAS,UACT,qCACH;IACD,OAAO,gBAAgB,WAAW,IAAI,EAAE,SAAS,QAAQ,GAAG;cAE3D,gBAAgB,KAAK,KAAK,MACzB,oBAAC,OAAD,EAAA,UAAc,KAAU,EAAd,EAAc,CACxB;IACE,CAAA;GACL,SACC,oBAAC,OAAD;IAAK,WAAU;cACZ;IACG,CAAA;GAEJ;;AAGR,QACE,qBAAC,OAAD;EACE,WAAW,GACT,+CACA,UAAU,aACV,gBAAgB,0BAChB,gBAAgB,OAAO,EACvB,WAAW,gBAAgB,sCAC3B,WAAW,YACT,qDACF,UACD;EACD,OAAO;YAXT,CAaG,WACA,YACG;;;AAIV,IAAM,cAAc,SAAU,OAAuB;CACnD,MAAM,EACJ,YACA,QAAQ,EAAE,EACV,OACA,MACA,OACA,UACA,WACA,UACA,QACA,cACA,cACA,cACA,MACA,OACA,iBACA,eACA,mBACA,WACA,eACA,SACA,UACA,YACA,gBACA,OACA,YACE;CAEJ,MAAM,cAAc,WAAW,YAAY;CAE3C,MAAM,cAAc;EAClB,GAAG;EACH,GAAI,aAAa,EAAE,iBAAiB,GAAG,WAAW,KAAK,GAAG,EAAE;EAC5D,GAAI,MAAM,aAAa,EAAE,iBAAiB,MAAM,YAAY,GAAG,EAAE;EAClE;AASD,KAAI,EAJD,SAAS,QAAQ,SAAS,UAC1B,iBAAiB,QAAQ,iBAAiB,UAC1C,iBAAiB,QAAQ,iBAAiB,QAG3C,QACE,oBAAC,gBAAD;EACS;EACD;EACC;EACG;EACH;EACC;EACG;EACE;EACJ;EACC;EACE;EACI;EACT;EACM;EAEZ;EACc,CAAA;AAIrB,QACE,oBAAC,OAAD;EACQ;EACC;EACO;EACA;EACA;EACG;EACR;EACM;EACI;EACR;EACI;aAEb,SAAS,MAAM,SAAS;AAGxB,OAAI,OAAO,aAAa,YAAY;IAClC,MAAM,eACJ,SACA,KAAK;AACP,QAAI,QACF,QAAO;AAET,WACE,oBAAC,gBAAD;KACS;KACD;KACA;KACC;KACG;KACH;KACC;KACG;KACE;KACJ;KACC;KACE;KACI;KACT;KACM;eAEZ;KACc,CAAA;;AAKrB,OAAI,SAAS;AACX,QAAI,MAAM,eAAe,SAAS,CAChC,QAAO,MAAM,aACX,UACA,kBACG,SAAqC,OACtC,QACD,CACF;AAEH,WAAO;;GAIT,IAAI,YAA6B;AACjC,OAAI,MAAM,eAAe,SAAS,CAChC,aAAY,MAAM,aAChB,UACA,kBACG,SAAqC,OACtC,QACD,CACF;AAGH,UACE,oBAAC,gBAAD;IACS;IACD;IACA;IACC;IACG;IACH;IACC;IACG;IACE;IACH;IACE;IACI;IACT;IACM;cAEZ;IACc,CAAA;;EAGf,CAAA;;AAIZ,SAAS,oBAAoB;CAC3B,MAAM,MAAM,WAAW,qBAAqB;AAC5C,QAAO;EACL,QAAQ,IAAI;EACZ,QAAQ,IAAI,UAAU,EAAE;EACxB,UAAU,IAAI,YAAY,EAAE;EAC7B;;AAGH,YAAY,YAAY;AAIxB,SAAS,mBAAmB,OAAuB;CACjD,MAAM,EAAE,QAAQ,cAAc;AAC9B,KAAI,CAAC,UAAU,OAAO,WAAW,EAAG,QAAO;AAC3C,QACE,oBAAC,OAAD;EAAK,WAAW,GAAG,uBAAuB,UAAU;YACjD,OAAO,KAAK,KAAK,MAChB,oBAAC,OAAD;GAEE,WAAU;aAET;GACG,EAJC,EAID,CACN;EACE,CAAA;;AAMV,SAAS,kBAA4C;AAEnD,QADa,WAAW,aAAa;;AAmBvC,IAAM,OAAO;AAEb,KAAK,OAAO;AACZ,KAAK,OAAO;AACZ,KAAK,YAAY;AACjB,KAAK,UAAU;AACf,KAAK,kBAAkB;AACvB,KAAK,WAAW;AAChB,KAAK,WAAW;AAChB,KAAK,eAAe;AAClB,SAAQ,KAAK,gEAAgE"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/Form/index.tsx"],"sourcesContent":["import RcForm, {\n Field,\n FormInstance as RcFormInstance,\n FormProvider,\n List,\n useForm as rcUseForm,\n useWatch,\n} from 'rc-field-form';\nimport type { FormProps as RcFormProps } from 'rc-field-form';\nimport FieldContext from 'rc-field-form/es/FieldContext';\nimport type { Rule, RuleObject, RuleRender } from 'rc-field-form/es/interface';\nimport type { Meta, NamePath } from 'rc-field-form/es/interface';\nimport React, { forwardRef, useContext, useMemo } from 'react';\nimport SizeContext, {\n SizeContextProvider,\n} from '../ConfigProvider/sizeContext';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport { cn } from '../lib/utils';\nimport {\n FormContext,\n FormItemInputContext,\n type ValidateStatus,\n} from './FormItemContext';\n\n/**\n * Loose NamePath: accepts string, number, or array of them.\n * antd v4 uses loose paths; rc-field-form v2 uses strict DeepNamePath.\n * We override to keep backward compatibility.\n */\ntype LooseNamePath = string | number | (string | number)[];\n\ntype ColConfig = {\n flex?: string | number;\n span?: number;\n offset?: number;\n style?: React.CSSProperties;\n [key: string]: any;\n};\n\n/**\n * FormInstance — extends rc-field-form FormInstance with loose-typed overloads\n * to maintain antd v4 backward compatibility. Uses intersection so that both\n * strict DeepNamePath and loose LooseNamePath signatures are accepted.\n */\nexport type FormInstance<Values = any> = RcFormInstance<Values> & {\n getFieldValue(name: LooseNamePath): any;\n setFieldValue(name: LooseNamePath, value: any): void;\n setFieldsValue(values: Record<string, any>): void;\n getFieldsValue(): Values;\n getFieldsValue(\n nameList: LooseNamePath[] | true,\n filterFunc?: (meta: Meta) => boolean,\n ): any;\n getFieldError(name: LooseNamePath): string[];\n getFieldsError(\n nameList?: LooseNamePath[],\n ): { name: (string | number)[]; errors: string[] }[];\n getFieldWarning(name: LooseNamePath): string[];\n isFieldTouched(name: LooseNamePath): boolean;\n isFieldsTouched(\n nameList?: LooseNamePath[],\n allFieldsTouched?: boolean,\n ): boolean;\n isFieldValidating(name: LooseNamePath): boolean;\n isFieldsValidating(nameList?: LooseNamePath[]): boolean;\n setFields(fields: FieldData[]): void;\n resetFields(fields?: LooseNamePath[]): void;\n validateFields(nameList?: LooseNamePath[]): Promise<Values>;\n /** Scroll to field position (antd-compatible extension) */\n scrollToField?(name: LooseNamePath, options?: ScrollIntoViewOptions): void;\n};\n\n// FormProps compatible with antd\nexport interface FormProps<Values = any> extends Omit<RcFormProps, 'form'> {\n form?: FormInstance<Values>;\n layout?: 'horizontal' | 'vertical' | 'inline';\n size?: 'small' | 'middle' | 'large';\n colon?: boolean;\n disabled?: boolean;\n labelCol?: ColConfig;\n wrapperCol?: ColConfig;\n className?: string;\n style?: React.CSSProperties;\n requiredMark?: boolean | 'optional';\n labelWidth?: number;\n labelAlign?: 'left' | 'right';\n}\n\n// FormItemProps\nexport interface FormItemProps {\n name?: NamePath;\n label?: React.ReactNode;\n rules?: Rule[];\n children?: React.ReactNode | ((form: RcFormInstance) => React.ReactNode);\n className?: string;\n style?: React.CSSProperties;\n required?: boolean;\n hidden?: boolean;\n initialValue?: any;\n dependencies?: NamePath[];\n shouldUpdate?: boolean | ((prevValues: any, curValues: any) => boolean);\n help?: React.ReactNode;\n extra?: React.ReactNode;\n validateTrigger?: string | string[];\n valuePropName?: string;\n getValueFromEvent?: (...args: any[]) => any;\n noStyle?: boolean;\n labelWidth?: number;\n tooltip?:\n | React.ReactNode\n | { title?: React.ReactNode; icon?: React.ReactNode };\n labelCol?: ColConfig;\n wrapperCol?: ColConfig;\n validateStatus?: ValidateStatus;\n colon?: boolean;\n trigger?: string;\n normalize?: (value: any, prevValue: any, allValues: any) => any;\n getValueProps?: (value: any) => Record<string, any>;\n}\n\n/** antd v4 compat: FormLabelAlign */\nexport type FormLabelAlign = 'left' | 'right';\n\n/** antd v4 compat: FieldData */\nexport type FieldData = {\n name: NamePath;\n value?: any;\n touched?: boolean;\n validating?: boolean;\n errors?: string[];\n};\n\nexport interface ErrorListProps {\n errors?: React.ReactNode[];\n help?: React.ReactNode;\n className?: string;\n}\n\nexport type FormListFieldData = {\n name: number;\n key: number;\n isListField: boolean;\n};\n\nexport type FormListOperation = {\n add: (defaultValue?: any, insertIndex?: number) => void;\n remove: (index: number | number[]) => void;\n move: (from: number, to: number) => void;\n};\n\nexport type FormListProps = {\n name: NamePath;\n rules?: Rule[];\n children: (\n fields: FormListFieldData[],\n operation: FormListOperation,\n meta: { errors: React.ReactNode[] },\n ) => React.ReactNode;\n initialValue?: any[];\n};\n\n// ============== Helpers ==============\n\n/** Convert a 24-column span/offset to Tailwind-compatible inline styles */\nfunction colStyle(col?: ColConfig): React.CSSProperties | undefined {\n if (!col) return undefined;\n const s: React.CSSProperties = { ...col.style };\n if (col.flex !== null && col.flex !== undefined) {\n s.flex = col.flex;\n }\n if (col.span !== null && col.span !== undefined) {\n // 24-column grid: width = span / 24 * 100%\n s.width = `${(col.span / 24) * 100}%`;\n s.flex = `0 0 ${(col.span / 24) * 100}%`;\n }\n if (col.offset !== null && col.offset !== undefined && col.offset > 0) {\n s.marginLeft = `${(col.offset / 24) * 100}%`;\n }\n return s;\n}\n\nfunction mergeControlProps(\n childProps: Record<string, any>,\n control: Record<string, any>,\n) {\n const mergedControl = { ...control };\n\n Object.keys(control).forEach((key) => {\n const controlHandler = control[key];\n const childHandler = childProps[key];\n\n if (\n typeof controlHandler === 'function' &&\n typeof childHandler === 'function'\n ) {\n mergedControl[key] = (...args: any[]) => {\n controlHandler(...args);\n childHandler(...args);\n };\n }\n });\n\n return mergedControl;\n}\n\n// ============== Form ==============\n\nconst AldForm = forwardRef((props: any, ref: any) => {\n const contextSize = useContext(SizeContext);\n const {\n children,\n size = contextSize,\n labelWidth,\n style = {},\n className,\n layout = 'horizontal',\n disabled,\n labelCol,\n wrapperCol,\n colon = false,\n requiredMark,\n labelAlign,\n ...restProps\n } = props;\n const customStyle = {\n ...style,\n ...(labelWidth ? { '--label-width': `${labelWidth}px` } : {}),\n ...(labelAlign ? { '--label-align': labelAlign } : {}),\n };\n\n const formContextValue = useMemo(\n () => ({\n layout,\n labelCol,\n wrapperCol,\n colon,\n requiredMark,\n labelWidth,\n labelAlign,\n }),\n [layout, labelCol, wrapperCol, colon, requiredMark, labelWidth, labelAlign],\n );\n\n return (\n <FormContext.Provider value={formContextValue}>\n <DisabledContext.Provider value={disabled}>\n <SizeContextProvider size={size}>\n <RcForm\n style={customStyle}\n className={cn(\n 'ald-form ant-form',\n `ald-form-${layout}`,\n `ant-form-${layout}`,\n className,\n )}\n {...restProps}\n ref={ref}\n >\n {children}\n </RcForm>\n </SizeContextProvider>\n </DisabledContext.Provider>\n </FormContext.Provider>\n );\n}) as <Values = any>(\n props: React.PropsWithChildren<FormProps<Values>> & {\n ref?: React.Ref<FormInstance<Values>>;\n labelWidth?: number;\n },\n) => React.ReactElement;\n\n// ============== Form.Item ==============\n\ninterface IFormItemProps extends FormItemProps {\n labelWidth?: number;\n labelAlign?: 'left' | 'right';\n}\n\n/** Derive status from meta or manual validateStatus */\nfunction deriveStatus(\n meta?: Meta,\n validateStatus?: ValidateStatus,\n): ValidateStatus {\n if (validateStatus) return validateStatus;\n if (!meta) return '';\n if (meta.validating) return 'validating';\n if (meta.errors && meta.errors.length > 0) return 'error';\n if (meta.warnings && meta.warnings.length > 0) return 'warning';\n if (meta.touched) return 'success';\n return '';\n}\n\n/** Status-based border class for the control wrapper */\nfunction statusClassName(status: ValidateStatus): string {\n switch (status) {\n case 'error':\n return 'ald-form-item-has-error';\n case 'warning':\n return 'ald-form-item-has-warning';\n case 'success':\n return 'ald-form-item-has-success';\n case 'validating':\n return 'ald-form-item-is-validating';\n default:\n return '';\n }\n}\n\n/** Render the inner label + control layout, receiving meta from Field */\nfunction FormItemLayout({\n label,\n children,\n meta,\n help,\n extra,\n required,\n rules,\n hidden,\n className,\n customStyle,\n noStyle,\n labelCol: itemLabelCol,\n wrapperCol: itemWrapperCol,\n validateStatus: manualStatus,\n colon: itemColon,\n formContext,\n}: {\n label?: React.ReactNode;\n children: React.ReactNode;\n meta?: Meta;\n help?: React.ReactNode;\n extra?: React.ReactNode;\n required?: boolean;\n rules?: Rule[];\n hidden?: boolean;\n className?: string;\n customStyle?: React.CSSProperties;\n noStyle?: boolean;\n labelCol?: ColConfig;\n wrapperCol?: ColConfig;\n validateStatus?: ValidateStatus;\n colon?: boolean;\n formContext: {\n layout?: string;\n labelCol?: ColConfig;\n wrapperCol?: ColConfig;\n colon?: boolean;\n requiredMark?: boolean | 'optional';\n labelWidth?: number;\n };\n}) {\n const status = deriveStatus(meta, manualStatus);\n const errors = useMemo(() => meta?.errors ?? [], [meta?.errors]);\n const warnings = useMemo(() => meta?.warnings ?? [], [meta?.warnings]);\n\n // Provide status context to child controls\n const itemInputContextValue = useMemo(\n () => ({\n status,\n isFormItemInput: true,\n errors,\n warnings,\n }),\n [status, errors, warnings],\n );\n\n if (noStyle) {\n return <>{children}</>;\n }\n\n // Determine if we should show required mark\n const { requiredMark } = formContext;\n const rulesRequired =\n rules && rules.some((r: any) => typeof r === 'object' && r && r.required);\n const isRequired =\n required || rulesRequired || (meta && (meta as any).required);\n const showRequired = requiredMark !== false && isRequired;\n const showOptional = requiredMark === 'optional' && !isRequired;\n\n // Resolve cols: item-level overrides form-level\n const resolvedLabelCol = itemLabelCol ?? formContext.labelCol;\n const resolvedWrapperCol = itemWrapperCol ?? formContext.wrapperCol;\n const layout = formContext.layout || 'horizontal';\n const showColon =\n (itemColon ?? formContext.colon) !== false && layout === 'horizontal';\n\n // Decide whether to use grid-style layout\n const useGridLayout =\n layout === 'horizontal' && (resolvedLabelCol || resolvedWrapperCol);\n\n // Determine display errors: if help is provided, show help instead of validation errors\n const displayMessages = help !== null && help !== undefined ? [help] : errors;\n const hasError = status === 'error' || (errors.length > 0 && help === null);\n const hasWarning =\n status === 'warning' || (warnings.length > 0 && help === null);\n const hasLabel = label !== null && label !== undefined && label !== '';\n\n const labelNode = hasLabel ? (\n <div\n className={cn(\n 'ald-form-item-label ant-form-item-label',\n // tw-block 不能省:label 容器同时挂了 ant-form-item-label 兼容 class,\n // 消费方残留的 antd 样式会把它设为 inline-block,导致 vertical 布局下\n // label 缩成内容宽而非整行铺在控件上方\n layout === 'vertical' && 'tw-mb-1 tw-block',\n layout === 'horizontal' && 'tw-mr-3 tw-shrink-0',\n )}\n style={useGridLayout ? colStyle(resolvedLabelCol) : undefined}\n >\n <label\n className={cn(\n 'tw-text-sm tw-font-medium tw-text-[var(--alias-colors-text-subtle,var(--content-secondary))]',\n !showColon && 'ant-form-item-no-colon',\n )}\n >\n {showRequired && (\n <span className=\"tw-mr-1 tw-text-[var(--content-negative-primary)]\">\n *\n </span>\n )}\n {label}\n {showOptional && (\n <span className=\"tw-ml-1 tw-text-xs tw-font-normal tw-text-[var(--content-secondary)]\">\n (optional)\n </span>\n )}\n {showColon && label ? ':' : null}\n </label>\n </div>\n ) : null;\n\n const controlNode = (\n <div\n className={cn(\n 'ald-form-item-control ant-form-item-control',\n // tw-min-w-0 必须同时加:flex item 默认 min-width:auto = min-content,\n // 子元素 intrinsic min-content(如多选 Select 的 tag 集合)会反向把 control 撑超出父\n // form-item 分配的宽度,再让 rc-overflow 误判\"全部能塞下\"导致不折叠 +N。\n // 实测:指标定义\"更多筛选\"浮窗里 8 个特性 tag 横向溢出浮窗边界即此因\n // (release-2.3_test 复现);这里钳住 min-width 后 Overflow 测量恢复正确。\n layout === 'horizontal' && 'tw-min-w-0 tw-flex-1',\n )}\n style={useGridLayout ? colStyle(resolvedWrapperCol) : undefined}\n >\n <FormItemInputContext.Provider value={itemInputContextValue}>\n <div className=\"ald-form-item-control-input\">\n <div className=\"ald-form-item-control-input-content\">{children}</div>\n </div>\n </FormItemInputContext.Provider>\n {/* 始终渲染错误容器,避免 DOM 增删触发 Radix FocusScope MutationObserver 劫持焦点 */}\n <div\n className={cn(\n 'ald-form-item-explain ant-form-item-explain tw-text-xs tw-transition-all tw-duration-200',\n displayMessages.length > 0 && 'tw-mt-1',\n hasError && 'tw-text-[var(--content-negative-secondary)]',\n hasWarning &&\n !hasError &&\n 'tw-text-[color:var(--content-warning-primary,#faad14)]',\n !hasError &&\n !hasWarning &&\n help !== null &&\n help !== undefined &&\n 'tw-text-[var(--content-secondary)]',\n )}\n style={displayMessages.length === 0 ? { display: 'none' } : undefined}\n >\n {displayMessages.map((msg, i) => (\n <div key={i}>{msg}</div>\n ))}\n </div>\n {extra && (\n <div className=\"ald-form-item-extra tw-mt-1 tw-text-xs tw-text-[var(--content-secondary)]\">\n {extra}\n </div>\n )}\n </div>\n );\n\n return (\n <div\n className={cn(\n 'ald-form-item ant-form-item ant-row tw-mb-6',\n hidden && 'tw-hidden',\n showRequired && 'ald-form-item-required',\n statusClassName(status),\n layout === 'horizontal' && 'tw-flex tw-flex-row tw-items-start',\n layout === 'inline' &&\n 'tw-mr-4 tw-inline-flex tw-flex-row tw-items-start',\n className,\n )}\n style={customStyle as React.CSSProperties}\n >\n {labelNode}\n {controlNode}\n </div>\n );\n}\n\nconst AldFormItem = function (props: IFormItemProps) {\n const {\n labelWidth,\n style = {},\n label,\n name,\n rules,\n children,\n className,\n required,\n hidden,\n initialValue,\n dependencies,\n shouldUpdate,\n help,\n extra,\n validateTrigger,\n valuePropName,\n getValueFromEvent,\n normalize,\n getValueProps,\n noStyle,\n labelCol,\n wrapperCol,\n validateStatus,\n colon,\n trigger,\n } = props;\n\n const formContext = useContext(FormContext);\n\n const customStyle = {\n ...style,\n ...(labelWidth ? { '--label-width': `${labelWidth}px` } : {}),\n ...(props.labelAlign ? { '--label-align': props.labelAlign } : {}),\n };\n\n // If no name is provided (e.g. a submit button wrapper), we don't need Field\n // Also when shouldUpdate or dependencies are used without name, Field is still needed for re-render\n const needField =\n (name !== null && name !== undefined) ||\n (shouldUpdate !== null && shouldUpdate !== undefined) ||\n (dependencies !== null && dependencies !== undefined);\n\n if (!needField) {\n return (\n <FormItemLayout\n label={label}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n noStyle={noStyle}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {children as React.ReactNode}\n </FormItemLayout>\n );\n }\n\n return (\n <Field\n name={name}\n rules={rules}\n initialValue={initialValue}\n dependencies={dependencies}\n shouldUpdate={shouldUpdate}\n validateTrigger={validateTrigger}\n trigger={trigger}\n valuePropName={valuePropName}\n getValueFromEvent={getValueFromEvent}\n normalize={normalize}\n getValueProps={getValueProps}\n >\n {(control, meta, form) => {\n // If children is a render function (shouldUpdate / dependencies pattern),\n // call it with the form instance and wrap in layout\n if (typeof children === 'function') {\n const childContent = (\n children as (form: RcFormInstance) => React.ReactNode\n )(form);\n if (noStyle) {\n return childContent;\n }\n return (\n <FormItemLayout\n label={label}\n meta={meta}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n noStyle={noStyle}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {childContent}\n </FormItemLayout>\n );\n }\n\n // For noStyle, just clone with control props\n if (noStyle) {\n if (React.isValidElement(children)) {\n return React.cloneElement(\n children as React.ReactElement<any>,\n mergeControlProps(\n (children as React.ReactElement<any>).props,\n control,\n ),\n );\n }\n return children;\n }\n\n // Clone control props onto the single child element\n let childNode: React.ReactNode = children;\n if (React.isValidElement(children)) {\n childNode = React.cloneElement(\n children as React.ReactElement<any>,\n mergeControlProps(\n (children as React.ReactElement<any>).props,\n control,\n ),\n );\n }\n\n return (\n <FormItemLayout\n label={label}\n meta={meta}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {childNode}\n </FormItemLayout>\n );\n }}\n </Field>\n );\n};\n\nfunction useFormItemStatus() {\n const ctx = useContext(FormItemInputContext);\n return {\n status: ctx.status,\n errors: ctx.errors ?? [],\n warnings: ctx.warnings ?? [],\n };\n}\n\nAldFormItem.useStatus = useFormItemStatus;\n\n// ============== ErrorList ==============\n\nfunction ErrorListComponent(props: ErrorListProps) {\n const { errors, className } = props;\n if (!errors || errors.length === 0) return null;\n return (\n <div className={cn('ald-form-error-list', className)}>\n {errors.map((err, i) => (\n <div\n key={i}\n className=\"tw-text-xs tw-text-[var(--content-negative-secondary)]\"\n >\n {err}\n </div>\n ))}\n </div>\n );\n}\n\n// ============== useFormInstance ==============\n\nfunction useFormInstance<T = any>(): FormInstance<T> {\n const form = useContext(FieldContext);\n return form as unknown as FormInstance<T>;\n}\n\n// ============== Compound component ==============\n\ntype InternalFormType = typeof AldForm;\ntype CompoundedComponent = InternalFormType & {\n useForm: <T = any>(...args: any[]) => [FormInstance<T>];\n useFormInstance: typeof useFormInstance;\n /** Loose-typed useWatch for antd v4 compat */\n useWatch: <T = any>(name: LooseNamePath, form?: FormInstance) => T;\n Item: typeof AldFormItem;\n List: typeof List;\n ErrorList: typeof ErrorListComponent;\n Provider: typeof FormProvider;\n create: () => void;\n};\n\nconst Form = AldForm as CompoundedComponent;\n\nForm.Item = AldFormItem;\nForm.List = List;\nForm.ErrorList = ErrorListComponent;\nForm.useForm = rcUseForm as CompoundedComponent['useForm'];\nForm.useFormInstance = useFormInstance;\nForm.useWatch = useWatch;\nForm.Provider = FormProvider;\nForm.create = () => {\n console.warn('Form.create is deprecated. Please use Form.useForm() instead.');\n};\n\nexport type { Rule, RuleObject, RuleRender };\nexport default Form;\n"],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ export type InputRef = HTMLInputElement & {
|
|
|
12
12
|
input?: HTMLInputElement | null;
|
|
13
13
|
};
|
|
14
14
|
type ChangeEventHandler = (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
15
|
-
export interface IInputProps {
|
|
15
|
+
export interface IInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix' | 'value' | 'defaultValue' | 'onChange' | 'disabled' | 'type' | 'max'> {
|
|
16
16
|
addonAfter?: ReactNode;
|
|
17
17
|
addonBefore?: ReactNode;
|
|
18
18
|
size?: TSize;
|
|
@@ -15,7 +15,7 @@ function getSizeType(sizeType) {
|
|
|
15
15
|
return "middle";
|
|
16
16
|
}
|
|
17
17
|
var Input = forwardRef((props, ref) => {
|
|
18
|
-
const { size: customSize, className, bordered = true, status, disabled, allowClear, prefix, suffix, addonBefore, addonAfter, showCount, maxLength, minLength, value: controlledValue, defaultValue, onChange, onPressEnter, onBlur, onFocus, onKeyDown, onCompositionStart, onCompositionEnd, placeholder, type, id, autoComplete = "off", autoFocus, readOnly, width, style, "data-testid": dataTestid, "aria-label": ariaLabel } = props;
|
|
18
|
+
const { size: customSize, className, bordered = true, status, disabled, allowClear, prefix, suffix, addonBefore, addonAfter, showCount, maxLength, minLength, value: controlledValue, defaultValue, onChange, onPressEnter, onBlur, onFocus, onKeyDown, onCompositionStart, onCompositionEnd, placeholder, type, id, autoComplete = "off", autoFocus, readOnly, width, style, "data-testid": dataTestid, "aria-label": ariaLabel, ...restInputProps } = props;
|
|
19
19
|
const contextDisabled = useContext(DisabledContext);
|
|
20
20
|
const mergedDisabled = disabled ?? contextDisabled;
|
|
21
21
|
const contentSize = useContext(SizeContext);
|
|
@@ -104,7 +104,8 @@ var Input = forwardRef((props, ref) => {
|
|
|
104
104
|
readOnly,
|
|
105
105
|
spellCheck: false,
|
|
106
106
|
"data-testid": dataTestid,
|
|
107
|
-
"aria-label": ariaLabel
|
|
107
|
+
"aria-label": ariaLabel,
|
|
108
|
+
...restInputProps
|
|
108
109
|
}),
|
|
109
110
|
showClearIcon && /* @__PURE__ */ jsx("span", {
|
|
110
111
|
className: "ald-input-clear ant-input-clear-icon tw-flex tw-cursor-pointer tw-items-center tw-pr-1",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/Input/components/Input/index.tsx"],"sourcesContent":["import React, {\n ReactNode,\n forwardRef,\n useContext,\n useRef,\n useState,\n} from 'react';\nimport DisabledContext from '../../../ConfigProvider/DisabledContext';\nimport SizeContext, { SizeType } from '../../../ConfigProvider/sizeContext';\nimport { CloseCircleFill } from '../../../Icon';\nimport { cn } from '../../../lib/utils';\nimport { useCompactItemContext } from '../../../Space/CompactContext';\n\ninterface IShowCountProps {\n formatter: (args: { count: number; maxLength?: number }) => string;\n}\nexport type TSize = SizeType;\nexport type InputRef = HTMLInputElement & {\n /** antd v4 compat — points to the underlying <input> element */\n input?: HTMLInputElement | null;\n};\n\ntype ChangeEventHandler = (e: React.ChangeEvent<HTMLInputElement>) => void;\n\nexport interface IInputProps {\n addonAfter?: ReactNode;\n addonBefore?: ReactNode;\n size?: TSize;\n id?: string;\n prefix?: ReactNode;\n suffix?: ReactNode;\n allowClear?: boolean;\n disabled?: boolean;\n showCount?: boolean | IShowCountProps;\n maxLength?: number;\n minLength?: number;\n max?: number;\n value?: string;\n defaultValue?: string;\n onPressEnter?: React.KeyboardEventHandler<HTMLInputElement>;\n onChange?: ChangeEventHandler;\n className?: string;\n style?: React.CSSProperties;\n placeholder?: string;\n type?: string;\n bordered?: boolean;\n status?: 'error' | 'warning' | '';\n autoComplete?: string;\n autoFocus?: boolean;\n readOnly?: boolean;\n width?: number | string;\n onBlur?: React.FocusEventHandler<HTMLInputElement>;\n onFocus?: React.FocusEventHandler<HTMLInputElement>;\n onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;\n onCompositionStart?: React.CompositionEventHandler<HTMLInputElement>;\n onCompositionEnd?: React.CompositionEventHandler<HTMLInputElement>;\n /** 透传到内部 input 元素的 data-testid,用于自动化测试定位 */\n 'data-testid'?: string;\n /** 透传到内部 input 元素的 aria-label,用于可访问性与自动化测试定位 */\n 'aria-label'?: string;\n}\n\nexport function getSizeType(sizeType: TSize): TSize {\n if (['small', 'middle', 'large'].includes(sizeType || '')) {\n return sizeType;\n }\n return 'middle';\n}\n\nconst Input = forwardRef<InputRef, IInputProps>((props, ref) => {\n const {\n size: customSize,\n className,\n bordered = true,\n status,\n disabled,\n allowClear,\n prefix,\n suffix,\n addonBefore,\n addonAfter,\n showCount,\n maxLength,\n minLength,\n value: controlledValue,\n defaultValue,\n onChange,\n onPressEnter,\n onBlur,\n onFocus,\n onKeyDown,\n onCompositionStart,\n onCompositionEnd,\n placeholder,\n type,\n id,\n autoComplete = 'off',\n autoFocus,\n readOnly,\n width,\n style,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n } = props;\n\n const contextDisabled = useContext(DisabledContext);\n const mergedDisabled = disabled ?? contextDisabled;\n\n const contentSize = useContext(SizeContext);\n const { compactSize, compactItemClassnames } =\n useCompactItemContext('ald-input');\n const size = customSize || compactSize || contentSize || 'middle';\n\n const isControlled = 'value' in props;\n const [innerValue, setInnerValue] = useState(defaultValue ?? '');\n const currentValue = isControlled ? controlledValue ?? '' : innerValue;\n const [focused, setFocused] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n\n React.useImperativeHandle(ref, () => {\n const el = inputRef.current!;\n // Expose .input for antd v4 compat (ref.current.input.focus())\n (el as InputRef).input = el;\n return el as InputRef;\n });\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setInnerValue(e.target.value);\n onChange?.(e);\n };\n\n const handleClear = () => {\n const nativeEvent = new Event('input', { bubbles: true });\n if (inputRef.current) {\n const nativeSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n 'value',\n )?.set;\n nativeSetter?.call(inputRef.current, '');\n inputRef.current.dispatchEvent(nativeEvent);\n }\n if (!isControlled) setInnerValue('');\n onChange?.({\n target: { value: '' },\n } as React.ChangeEvent<HTMLInputElement>);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') onPressEnter?.(e);\n onKeyDown?.(e);\n };\n\n const showClearIcon = allowClear && currentValue && !mergedDisabled;\n\n const countInfo =\n showCount && typeof showCount === 'object'\n ? showCount.formatter({\n count: currentValue.length,\n maxLength,\n })\n : showCount\n ? `${currentValue.length}${maxLength ? `/${maxLength}` : ''}`\n : null;\n\n // Build compact-mode border-radius and margin overrides\n const compactClasses = compactItemClassnames\n ? cn(\n !compactItemClassnames['ald-input-compact-first-item'] &&\n '!tw-rounded-l-none',\n !compactItemClassnames['ald-input-compact-last-item'] &&\n '!tw-rounded-r-none',\n !compactItemClassnames['ald-input-compact-first-item'] && '-tw-ml-px',\n )\n : undefined;\n\n return (\n <span\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-input ant-input-affix-wrapper tw-inline-flex tw-w-full tw-items-center tw-bg-[var(--interaction-background-form-field)]',\n bordered &&\n 'tw-rounded-r-75 tw-border tw-border-solid tw-border-[var(--interaction-border-neutral-normal)]',\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n // focus 仅变 border-color,不加额外 box-shadow/outline。\n // 消费方通过 CSS 将 border 设为 0 后 focus 高亮自然消失,和 antd 行为一致。\n focused &&\n 'ant-input-affix-wrapper-focused tw-border-[var(--interaction-focus-default)]',\n !mergedDisabled &&\n !focused &&\n 'hover:tw-border-[var(--interaction-border-hover)]',\n `ald-input-${getSizeType(size)}`,\n size === 'small' && 'tw-h-7 tw-text-xs',\n size === 'large' && 'tw-h-9 tw-text-sm',\n (size === 'middle' || !size) && 'tw-h-8 tw-text-sm',\n status === 'error' &&\n `ald-input-error tw-border-[var(--border-negative-strong)]`,\n status === 'warning' &&\n `ald-input-warning tw-border-[var(--border-warning-subtle)]`,\n mergedDisabled &&\n 'ald-input-disabled tw-cursor-not-allowed tw-bg-[var(--global-cool-gray-alpha-50)] tw-text-[var(--content-secondary)]',\n compactClasses,\n className,\n )}\n style={{\n ...style,\n width,\n }}\n onMouseDown={(e) => {\n // 点击 wrapper 非 input 区域时:\n // 如果 input 已聚焦 → preventDefault 防止点击 wrapper 导致丢焦\n // 如果 input 未聚焦 → 不阻止默认行为,让浏览器正常处理 blur 上一个元素\n if (e.target !== inputRef.current) {\n if (document.activeElement === inputRef.current) {\n e.preventDefault();\n }\n }\n }}\n onMouseUp={(e) => {\n // 在 mouseUp 时将焦点转发给内部 input(兼容 prefix/suffix/padding 区域的点击)\n if (e.target !== inputRef.current && inputRef.current) {\n inputRef.current.focus();\n }\n }}\n >\n {addonBefore && (\n <span className=\"ald-input-addon tw-flex tw-shrink-0 tw-items-center tw-self-stretch tw-border-r tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-neutral-subtle)] tw-px-3 tw-text-[var(--content-secondary)]\">\n {addonBefore}\n </span>\n )}\n {/* antd 兼容:保留 ant-input-prefix class,消费方 CSS 可能依赖该选择器 */}\n {prefix && (\n <span className=\"ald-input-prefix ant-input-prefix tw-flex tw-items-center tw-pl-2 tw-text-[var(--content-secondary)]\">\n {prefix}\n </span>\n )}\n <input\n ref={inputRef}\n id={id}\n type={type || 'text'}\n className=\"tw-min-w-0 tw-flex-1 tw-self-stretch tw-border-0 tw-bg-transparent tw-px-2 tw-text-[var(--content-primary)] tw-text-inherit tw-outline-none\"\n value={currentValue}\n onChange={handleChange}\n onBlur={(e) => {\n setFocused(false);\n onBlur?.(e);\n }}\n onFocus={(e) => {\n setFocused(true);\n onFocus?.(e);\n }}\n onKeyDown={handleKeyDown}\n onCompositionStart={onCompositionStart}\n onCompositionEnd={onCompositionEnd}\n disabled={mergedDisabled}\n placeholder={placeholder}\n maxLength={maxLength}\n minLength={minLength}\n autoComplete={autoComplete}\n autoFocus={autoFocus}\n readOnly={readOnly}\n spellCheck={false}\n data-testid={dataTestid}\n aria-label={ariaLabel}\n />\n {showClearIcon && (\n <span\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n className=\"ald-input-clear ant-input-clear-icon tw-flex tw-cursor-pointer tw-items-center tw-pr-1\"\n onClick={handleClear}\n >\n <CloseCircleFill size={16} color=\"var(--alias-colors-icon-subtle)\" />\n </span>\n )}\n {/* antd 兼容:保留 ant-input-suffix class,消费方 CSS 可能依赖该选择器 */}\n {suffix && (\n <span className=\"ald-input-suffix ant-input-suffix tw-flex tw-items-center tw-pr-2 tw-text-[var(--content-secondary)]\">\n {suffix}\n </span>\n )}\n {countInfo && (\n <span className=\"ald-input-count tw-pr-2 tw-text-xs tw-text-[var(--content-tertiary)]\">\n {countInfo}\n </span>\n )}\n {addonAfter && (\n <span className=\"ald-input-addon tw-border-l tw-border-solid tw-border-[var(--border-default)] tw-px-2 tw-text-[var(--content-secondary)]\">\n {addonAfter}\n </span>\n )}\n </span>\n );\n});\n\nexport default Input;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/Input/components/Input/index.tsx"],"sourcesContent":["import React, {\n ReactNode,\n forwardRef,\n useContext,\n useRef,\n useState,\n} from 'react';\nimport DisabledContext from '../../../ConfigProvider/DisabledContext';\nimport SizeContext, { SizeType } from '../../../ConfigProvider/sizeContext';\nimport { CloseCircleFill } from '../../../Icon';\nimport { cn } from '../../../lib/utils';\nimport { useCompactItemContext } from '../../../Space/CompactContext';\n\ninterface IShowCountProps {\n formatter: (args: { count: number; maxLength?: number }) => string;\n}\nexport type TSize = SizeType;\nexport type InputRef = HTMLInputElement & {\n /** antd v4 compat — points to the underlying <input> element */\n input?: HTMLInputElement | null;\n};\n\ntype ChangeEventHandler = (e: React.ChangeEvent<HTMLInputElement>) => void;\n\nexport interface IInputProps\n extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n | 'size'\n | 'prefix'\n | 'value'\n | 'defaultValue'\n | 'onChange'\n | 'disabled'\n | 'type'\n | 'max'\n > {\n addonAfter?: ReactNode;\n addonBefore?: ReactNode;\n size?: TSize;\n id?: string;\n prefix?: ReactNode;\n suffix?: ReactNode;\n allowClear?: boolean;\n disabled?: boolean;\n showCount?: boolean | IShowCountProps;\n maxLength?: number;\n minLength?: number;\n max?: number;\n value?: string;\n defaultValue?: string;\n onPressEnter?: React.KeyboardEventHandler<HTMLInputElement>;\n onChange?: ChangeEventHandler;\n className?: string;\n style?: React.CSSProperties;\n placeholder?: string;\n type?: string;\n bordered?: boolean;\n status?: 'error' | 'warning' | '';\n autoComplete?: string;\n autoFocus?: boolean;\n readOnly?: boolean;\n width?: number | string;\n onBlur?: React.FocusEventHandler<HTMLInputElement>;\n onFocus?: React.FocusEventHandler<HTMLInputElement>;\n onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;\n onCompositionStart?: React.CompositionEventHandler<HTMLInputElement>;\n onCompositionEnd?: React.CompositionEventHandler<HTMLInputElement>;\n /** 透传到内部 input 元素的 data-testid,用于自动化测试定位 */\n 'data-testid'?: string;\n /** 透传到内部 input 元素的 aria-label,用于可访问性与自动化测试定位 */\n 'aria-label'?: string;\n}\n\nexport function getSizeType(sizeType: TSize): TSize {\n if (['small', 'middle', 'large'].includes(sizeType || '')) {\n return sizeType;\n }\n return 'middle';\n}\n\nconst Input = forwardRef<InputRef, IInputProps>((props, ref) => {\n const {\n size: customSize,\n className,\n bordered = true,\n status,\n disabled,\n allowClear,\n prefix,\n suffix,\n addonBefore,\n addonAfter,\n showCount,\n maxLength,\n minLength,\n value: controlledValue,\n defaultValue,\n onChange,\n onPressEnter,\n onBlur,\n onFocus,\n onKeyDown,\n onCompositionStart,\n onCompositionEnd,\n placeholder,\n type,\n id,\n autoComplete = 'off',\n autoFocus,\n readOnly,\n width,\n style,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n ...restInputProps\n } = props;\n\n const contextDisabled = useContext(DisabledContext);\n const mergedDisabled = disabled ?? contextDisabled;\n\n const contentSize = useContext(SizeContext);\n const { compactSize, compactItemClassnames } =\n useCompactItemContext('ald-input');\n const size = customSize || compactSize || contentSize || 'middle';\n\n const isControlled = 'value' in props;\n const [innerValue, setInnerValue] = useState(defaultValue ?? '');\n const currentValue = isControlled ? controlledValue ?? '' : innerValue;\n const [focused, setFocused] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n\n React.useImperativeHandle(ref, () => {\n const el = inputRef.current!;\n // Expose .input for antd v4 compat (ref.current.input.focus())\n (el as InputRef).input = el;\n return el as InputRef;\n });\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setInnerValue(e.target.value);\n onChange?.(e);\n };\n\n const handleClear = () => {\n const nativeEvent = new Event('input', { bubbles: true });\n if (inputRef.current) {\n const nativeSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n 'value',\n )?.set;\n nativeSetter?.call(inputRef.current, '');\n inputRef.current.dispatchEvent(nativeEvent);\n }\n if (!isControlled) setInnerValue('');\n onChange?.({\n target: { value: '' },\n } as React.ChangeEvent<HTMLInputElement>);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') onPressEnter?.(e);\n onKeyDown?.(e);\n };\n\n const showClearIcon = allowClear && currentValue && !mergedDisabled;\n\n const countInfo =\n showCount && typeof showCount === 'object'\n ? showCount.formatter({\n count: currentValue.length,\n maxLength,\n })\n : showCount\n ? `${currentValue.length}${maxLength ? `/${maxLength}` : ''}`\n : null;\n\n // Build compact-mode border-radius and margin overrides\n const compactClasses = compactItemClassnames\n ? cn(\n !compactItemClassnames['ald-input-compact-first-item'] &&\n '!tw-rounded-l-none',\n !compactItemClassnames['ald-input-compact-last-item'] &&\n '!tw-rounded-r-none',\n !compactItemClassnames['ald-input-compact-first-item'] && '-tw-ml-px',\n )\n : undefined;\n\n return (\n <span\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-input ant-input-affix-wrapper tw-inline-flex tw-w-full tw-items-center tw-bg-[var(--interaction-background-form-field)]',\n bordered &&\n 'tw-rounded-r-75 tw-border tw-border-solid tw-border-[var(--interaction-border-neutral-normal)]',\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n // focus 仅变 border-color,不加额外 box-shadow/outline。\n // 消费方通过 CSS 将 border 设为 0 后 focus 高亮自然消失,和 antd 行为一致。\n focused &&\n 'ant-input-affix-wrapper-focused tw-border-[var(--interaction-focus-default)]',\n !mergedDisabled &&\n !focused &&\n 'hover:tw-border-[var(--interaction-border-hover)]',\n `ald-input-${getSizeType(size)}`,\n size === 'small' && 'tw-h-7 tw-text-xs',\n size === 'large' && 'tw-h-9 tw-text-sm',\n (size === 'middle' || !size) && 'tw-h-8 tw-text-sm',\n status === 'error' &&\n `ald-input-error tw-border-[var(--border-negative-strong)]`,\n status === 'warning' &&\n `ald-input-warning tw-border-[var(--border-warning-subtle)]`,\n mergedDisabled &&\n 'ald-input-disabled tw-cursor-not-allowed tw-bg-[var(--global-cool-gray-alpha-50)] tw-text-[var(--content-secondary)]',\n compactClasses,\n className,\n )}\n style={{\n ...style,\n width,\n }}\n onMouseDown={(e) => {\n // 点击 wrapper 非 input 区域时:\n // 如果 input 已聚焦 → preventDefault 防止点击 wrapper 导致丢焦\n // 如果 input 未聚焦 → 不阻止默认行为,让浏览器正常处理 blur 上一个元素\n if (e.target !== inputRef.current) {\n if (document.activeElement === inputRef.current) {\n e.preventDefault();\n }\n }\n }}\n onMouseUp={(e) => {\n // 在 mouseUp 时将焦点转发给内部 input(兼容 prefix/suffix/padding 区域的点击)\n if (e.target !== inputRef.current && inputRef.current) {\n inputRef.current.focus();\n }\n }}\n >\n {addonBefore && (\n <span className=\"ald-input-addon tw-flex tw-shrink-0 tw-items-center tw-self-stretch tw-border-r tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-neutral-subtle)] tw-px-3 tw-text-[var(--content-secondary)]\">\n {addonBefore}\n </span>\n )}\n {/* antd 兼容:保留 ant-input-prefix class,消费方 CSS 可能依赖该选择器 */}\n {prefix && (\n <span className=\"ald-input-prefix ant-input-prefix tw-flex tw-items-center tw-pl-2 tw-text-[var(--content-secondary)]\">\n {prefix}\n </span>\n )}\n <input\n ref={inputRef}\n id={id}\n type={type || 'text'}\n className=\"tw-min-w-0 tw-flex-1 tw-self-stretch tw-border-0 tw-bg-transparent tw-px-2 tw-text-[var(--content-primary)] tw-text-inherit tw-outline-none\"\n value={currentValue}\n onChange={handleChange}\n onBlur={(e) => {\n setFocused(false);\n onBlur?.(e);\n }}\n onFocus={(e) => {\n setFocused(true);\n onFocus?.(e);\n }}\n onKeyDown={handleKeyDown}\n onCompositionStart={onCompositionStart}\n onCompositionEnd={onCompositionEnd}\n disabled={mergedDisabled}\n placeholder={placeholder}\n maxLength={maxLength}\n minLength={minLength}\n autoComplete={autoComplete}\n autoFocus={autoFocus}\n readOnly={readOnly}\n spellCheck={false}\n data-testid={dataTestid}\n aria-label={ariaLabel}\n {...restInputProps}\n />\n {showClearIcon && (\n <span\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n className=\"ald-input-clear ant-input-clear-icon tw-flex tw-cursor-pointer tw-items-center tw-pr-1\"\n onClick={handleClear}\n >\n <CloseCircleFill size={16} color=\"var(--alias-colors-icon-subtle)\" />\n </span>\n )}\n {/* antd 兼容:保留 ant-input-suffix class,消费方 CSS 可能依赖该选择器 */}\n {suffix && (\n <span className=\"ald-input-suffix ant-input-suffix tw-flex tw-items-center tw-pr-2 tw-text-[var(--content-secondary)]\">\n {suffix}\n </span>\n )}\n {countInfo && (\n <span className=\"ald-input-count tw-pr-2 tw-text-xs tw-text-[var(--content-tertiary)]\">\n {countInfo}\n </span>\n )}\n {addonAfter && (\n <span className=\"ald-input-addon tw-border-l tw-border-solid tw-border-[var(--border-default)] tw-px-2 tw-text-[var(--content-secondary)]\">\n {addonAfter}\n </span>\n )}\n </span>\n );\n});\n\nexport default Input;\n"],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
import { IInputProps, TSize } from '../Input';
|
|
2
|
+
import { IInputProps, InputRef, TSize } from '../Input';
|
|
3
3
|
export interface IPasswordProps extends Omit<IInputProps, 'type'> {
|
|
4
4
|
visibilityToggle?: boolean;
|
|
5
5
|
size?: TSize;
|
|
6
|
+
iconRender?: (visible: boolean) => React.ReactNode;
|
|
6
7
|
}
|
|
7
|
-
declare const _default: React.ForwardRefExoticComponent<IPasswordProps & React.RefAttributes<
|
|
8
|
+
declare const _default: React.ForwardRefExoticComponent<IPasswordProps & React.RefAttributes<InputRef>>;
|
|
8
9
|
export default _default;
|
|
@@ -9,7 +9,7 @@ import { forwardRef, useContext, useState } from "react";
|
|
|
9
9
|
import { jsx } from "react/jsx-runtime";
|
|
10
10
|
//#region src/Input/components/Password/index.tsx
|
|
11
11
|
var Password_default = forwardRef((props, ref) => {
|
|
12
|
-
const { size: customSize, className, disabled, visibilityToggle = true, ...restProps } = props;
|
|
12
|
+
const { size: customSize, className, disabled, visibilityToggle = true, iconRender, ...restProps } = props;
|
|
13
13
|
const contextDisabled = useContext(DisabledContext);
|
|
14
14
|
const mergedDisabled = disabled ?? contextDisabled;
|
|
15
15
|
const contentSize = useContext(SizeContext);
|
|
@@ -23,7 +23,7 @@ var Password_default = forwardRef((props, ref) => {
|
|
|
23
23
|
className: cn("ald-input-password", `ald-input-${getSizeType(size)}`, mergedDisabled && "ald-input-disabled", className),
|
|
24
24
|
suffix: visibilityToggle ? /* @__PURE__ */ jsx(IconButton, {
|
|
25
25
|
size: "small",
|
|
26
|
-
icon: visible ? /* @__PURE__ */ jsx(Memo$1, {}) : /* @__PURE__ */ jsx(Memo, {}),
|
|
26
|
+
icon: iconRender?.(visible) || (visible ? /* @__PURE__ */ jsx(Memo$1, {}) : /* @__PURE__ */ jsx(Memo, {})),
|
|
27
27
|
onClick: () => setVisible(!visible)
|
|
28
28
|
}) : void 0
|
|
29
29
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/Input/components/Password/index.tsx"],"sourcesContent":["import React, { forwardRef, useContext, useState } from 'react';\nimport DisabledContext from '../../../ConfigProvider/DisabledContext';\nimport SizeContext from '../../../ConfigProvider/sizeContext';\nimport { EyeOffLine, EyeOnLine } from '../../../Icon';\nimport IconButton from '../../../IconButton';\nimport { cn } from '../../../lib/utils';\nimport Input, { IInputProps, TSize, getSizeType } from '../Input';\n\nexport interface IPasswordProps extends Omit<IInputProps, 'type'> {\n visibilityToggle?: boolean;\n size?: TSize;\n}\n\nexport default forwardRef<
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/Input/components/Password/index.tsx"],"sourcesContent":["import React, { forwardRef, useContext, useState } from 'react';\nimport DisabledContext from '../../../ConfigProvider/DisabledContext';\nimport SizeContext from '../../../ConfigProvider/sizeContext';\nimport { EyeOffLine, EyeOnLine } from '../../../Icon';\nimport IconButton from '../../../IconButton';\nimport { cn } from '../../../lib/utils';\nimport Input, { IInputProps, InputRef, TSize, getSizeType } from '../Input';\n\nexport interface IPasswordProps extends Omit<IInputProps, 'type'> {\n visibilityToggle?: boolean;\n size?: TSize;\n iconRender?: (visible: boolean) => React.ReactNode;\n}\n\nexport default forwardRef<InputRef, IPasswordProps>((props, ref) => {\n const {\n size: customSize,\n className,\n disabled,\n visibilityToggle = true,\n iconRender,\n ...restProps\n } = props;\n const contextDisabled = useContext(DisabledContext);\n const mergedDisabled = disabled ?? contextDisabled;\n\n const contentSize = useContext(SizeContext);\n const size = customSize || contentSize || 'middle';\n const [visible, setVisible] = useState(false);\n\n return (\n <Input\n {...restProps}\n ref={ref}\n disabled={mergedDisabled}\n type={visible ? 'text' : 'password'}\n className={cn(\n 'ald-input-password',\n `ald-input-${getSizeType(size)}`,\n mergedDisabled && 'ald-input-disabled',\n className,\n )}\n suffix={\n visibilityToggle ? (\n <IconButton\n size=\"small\"\n icon={\n iconRender?.(visible) ||\n (visible ? <EyeOnLine /> : <EyeOffLine />)\n }\n onClick={() => setVisible(!visible)}\n />\n ) : undefined\n }\n />\n );\n});\n"],"mappings":";;;;;;;;;;AAcA,IAAA,mBAAe,YAAsC,OAAO,QAAQ;CAClE,MAAM,EACJ,MAAM,YACN,WACA,UACA,mBAAmB,MACnB,YACA,GAAG,cACD;CACJ,MAAM,kBAAkB,WAAW,gBAAgB;CACnD,MAAM,iBAAiB,YAAY;CAEnC,MAAM,cAAc,WAAW,YAAY;CAC3C,MAAM,OAAO,cAAc,eAAe;CAC1C,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;AAE7C,QACE,oBAAC,OAAD;EACE,GAAI;EACC;EACL,UAAU;EACV,MAAM,UAAU,SAAS;EACzB,WAAW,GACT,sBACA,aAAa,YAAY,KAAK,IAC9B,kBAAkB,sBAClB,UACD;EACD,QACE,mBACE,oBAAC,YAAD;GACE,MAAK;GACL,MACE,aAAa,QAAQ,KACpB,UAAU,oBAAC,QAAD,EAAa,CAAA,GAAG,oBAAC,MAAD,EAAc,CAAA;GAE3C,eAAe,WAAW,CAAC,QAAQ;GACnC,CAAA,GACA;EAEN,CAAA;EAEJ"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { TSize } from '../Input';
|
|
3
3
|
export type TextAreaRef = HTMLTextAreaElement;
|
|
4
|
-
export interface ITextAreaProps {
|
|
4
|
+
export interface ITextAreaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'size' | 'value' | 'defaultValue' | 'onChange' | 'disabled' | 'rows'> {
|
|
5
5
|
autoFocus?: boolean;
|
|
6
6
|
allowClear?: boolean;
|
|
7
7
|
autoSize?: boolean | {
|
|
@@ -7,7 +7,7 @@ import React, { forwardRef, useContext, useRef, useState } from "react";
|
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
//#region src/Input/components/TextArea/index.tsx
|
|
9
9
|
var TextArea_default = forwardRef((props, ref) => {
|
|
10
|
-
const { bordered, border, size: customSize, disabled, className = "", allowClear = false, value: controlledValue, defaultValue, onChange, onPressEnter, maxLength, showCount, autoSize, placeholder, rows, onBlur, onFocus, style } = props;
|
|
10
|
+
const { bordered, border, size: customSize, disabled, className = "", allowClear = false, value: controlledValue, defaultValue, onChange, onPressEnter, maxLength, showCount, autoSize, placeholder, rows, onBlur, onFocus, onKeyDown, onCompositionStart, onCompositionEnd, style, ...restTextAreaProps } = props;
|
|
11
11
|
const isBordered = bordered ?? border ?? true;
|
|
12
12
|
const contextDisabled = useContext(DisabledContext);
|
|
13
13
|
const mergedDisabled = disabled ?? contextDisabled;
|
|
@@ -28,6 +28,7 @@ var TextArea_default = forwardRef((props, ref) => {
|
|
|
28
28
|
};
|
|
29
29
|
const handleKeyDown = (e) => {
|
|
30
30
|
if (e.key === "Enter") onPressEnter?.(e);
|
|
31
|
+
onKeyDown?.(e);
|
|
31
32
|
};
|
|
32
33
|
const minRows = typeof autoSize === "object" ? autoSize.minRows : void 0;
|
|
33
34
|
const maxRows = typeof autoSize === "object" ? autoSize.maxRows : void 0;
|
|
@@ -43,12 +44,15 @@ var TextArea_default = forwardRef((props, ref) => {
|
|
|
43
44
|
onBlur,
|
|
44
45
|
onFocus,
|
|
45
46
|
onKeyDown: handleKeyDown,
|
|
47
|
+
onCompositionStart,
|
|
48
|
+
onCompositionEnd,
|
|
46
49
|
disabled: mergedDisabled,
|
|
47
50
|
placeholder,
|
|
48
51
|
maxLength,
|
|
49
52
|
rows: rows || (minRows ?? 3),
|
|
50
53
|
spellCheck: false,
|
|
51
54
|
autoComplete: "off",
|
|
55
|
+
...restTextAreaProps,
|
|
52
56
|
style: {
|
|
53
57
|
minHeight: minRows ? `${minRows * 22}px` : void 0,
|
|
54
58
|
maxHeight: maxRows ? `${maxRows * 22}px` : void 0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/Input/components/TextArea/index.tsx"],"sourcesContent":["import React, { forwardRef, useContext, useRef, useState } from 'react';\nimport DisabledContext from '../../../ConfigProvider/DisabledContext';\nimport SizeContext from '../../../ConfigProvider/sizeContext';\nimport { CloseCircleFill } from '../../../Icon';\nimport { cn } from '../../../lib/utils';\nimport { TSize, getSizeType } from '../Input';\n\nexport type TextAreaRef = HTMLTextAreaElement;\n\nexport interface ITextAreaProps {\n autoFocus?: boolean;\n allowClear?: boolean;\n autoSize?: boolean | { minRows?: number; maxRows?: number };\n defaultValue?: string;\n maxLength?: number;\n showCount?:\n | boolean\n | { formatter: (args: { count: number; maxLength?: number }) => string };\n value?: string;\n onPressEnter?: React.KeyboardEventHandler<HTMLTextAreaElement>;\n onResize?: (size: { width: number; height: number }) => void;\n border?: boolean;\n bordered?: boolean;\n className?: string;\n size?: TSize;\n disabled?: boolean;\n placeholder?: string;\n rows?: number;\n onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n onBlur?: React.FocusEventHandler<HTMLTextAreaElement>;\n onFocus?: React.FocusEventHandler<HTMLTextAreaElement>;\n onKeyDown?: React.KeyboardEventHandler<HTMLTextAreaElement>;\n onCompositionStart?: React.CompositionEventHandler<HTMLTextAreaElement>;\n onCompositionEnd?: React.CompositionEventHandler<HTMLTextAreaElement>;\n style?: React.CSSProperties;\n}\n\nexport default forwardRef<TextAreaRef, ITextAreaProps>((props, ref) => {\n const {\n bordered,\n border,\n size: customSize,\n disabled,\n className = '',\n allowClear = false,\n value: controlledValue,\n defaultValue,\n onChange,\n onPressEnter,\n maxLength,\n showCount,\n autoSize,\n placeholder,\n rows,\n onBlur,\n onFocus,\n style,\n } = props;\n\n const isBordered = bordered ?? border ?? true;\n\n const contextDisabled = useContext(DisabledContext);\n const mergedDisabled = disabled ?? contextDisabled;\n\n const contentSize = useContext(SizeContext);\n const size = customSize || contentSize || 'middle';\n const isControlled = 'value' in props;\n const [innerValue, setInnerValue] = useState(defaultValue ?? '');\n const currentValue = isControlled ? controlledValue ?? '' : innerValue;\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(ref, () => textareaRef.current!);\n\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setInnerValue(e.target.value);\n onChange?.(e);\n };\n\n const handleClear = () => {\n if (!isControlled) setInnerValue('');\n onChange?.({\n target: { value: '' },\n } as React.ChangeEvent<HTMLTextAreaElement>);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter') onPressEnter?.(e);\n };\n\n const minRows = typeof autoSize === 'object' ? autoSize.minRows : undefined;\n const maxRows = typeof autoSize === 'object' ? autoSize.maxRows : undefined;\n\n return (\n <div\n className={cn(\n 'ald-input ald-input-textarea tw-relative',\n `ald-input-textarea-${getSizeType(size)}`,\n isBordered &&\n 'tw-rounded-r-75 tw-border tw-border-solid tw-border-[var(--border-default)]',\n mergedDisabled && 'ald-input-disabled tw-opacity-50',\n className,\n )}\n style={style}\n >\n <textarea\n ref={textareaRef}\n className=\"tw-w-full tw-resize-y tw-border-0 tw-bg-transparent tw-px-3 tw-py-2 tw-text-sm tw-text-[var(--content-primary)] tw-outline-none\"\n value={currentValue}\n onChange={handleChange}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={handleKeyDown}\n disabled={mergedDisabled}\n placeholder={placeholder}\n maxLength={maxLength}\n rows={rows || (minRows ?? 3)}\n spellCheck={false}\n autoComplete=\"off\"\n style={{\n minHeight: minRows ? `${minRows * 22}px` : undefined,\n maxHeight: maxRows ? `${maxRows * 22}px` : undefined,\n }}\n />\n {allowClear && currentValue && !mergedDisabled && (\n <span\n className=\"tw-absolute tw-right-2 tw-top-2 tw-cursor-pointer\"\n onClick={handleClear}\n >\n <CloseCircleFill size={16} color=\"var(--alias-colors-icon-subtle)\" />\n </span>\n )}\n {showCount && (\n <div className=\"tw-px-2 tw-pb-1 tw-text-right tw-text-xs tw-text-[var(--content-tertiary)]\">\n {typeof showCount === 'object'\n ? showCount.formatter({ count: currentValue.length, maxLength })\n : `${currentValue.length}${maxLength ? `/${maxLength}` : ''}`}\n </div>\n )}\n </div>\n );\n});\n"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/Input/components/TextArea/index.tsx"],"sourcesContent":["import React, { forwardRef, useContext, useRef, useState } from 'react';\nimport DisabledContext from '../../../ConfigProvider/DisabledContext';\nimport SizeContext from '../../../ConfigProvider/sizeContext';\nimport { CloseCircleFill } from '../../../Icon';\nimport { cn } from '../../../lib/utils';\nimport { TSize, getSizeType } from '../Input';\n\nexport type TextAreaRef = HTMLTextAreaElement;\n\nexport interface ITextAreaProps\n extends Omit<\n React.TextareaHTMLAttributes<HTMLTextAreaElement>,\n 'size' | 'value' | 'defaultValue' | 'onChange' | 'disabled' | 'rows'\n > {\n autoFocus?: boolean;\n allowClear?: boolean;\n autoSize?: boolean | { minRows?: number; maxRows?: number };\n defaultValue?: string;\n maxLength?: number;\n showCount?:\n | boolean\n | { formatter: (args: { count: number; maxLength?: number }) => string };\n value?: string;\n onPressEnter?: React.KeyboardEventHandler<HTMLTextAreaElement>;\n onResize?: (size: { width: number; height: number }) => void;\n border?: boolean;\n bordered?: boolean;\n className?: string;\n size?: TSize;\n disabled?: boolean;\n placeholder?: string;\n rows?: number;\n onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n onBlur?: React.FocusEventHandler<HTMLTextAreaElement>;\n onFocus?: React.FocusEventHandler<HTMLTextAreaElement>;\n onKeyDown?: React.KeyboardEventHandler<HTMLTextAreaElement>;\n onCompositionStart?: React.CompositionEventHandler<HTMLTextAreaElement>;\n onCompositionEnd?: React.CompositionEventHandler<HTMLTextAreaElement>;\n style?: React.CSSProperties;\n}\n\nexport default forwardRef<TextAreaRef, ITextAreaProps>((props, ref) => {\n const {\n bordered,\n border,\n size: customSize,\n disabled,\n className = '',\n allowClear = false,\n value: controlledValue,\n defaultValue,\n onChange,\n onPressEnter,\n maxLength,\n showCount,\n autoSize,\n placeholder,\n rows,\n onBlur,\n onFocus,\n onKeyDown,\n onCompositionStart,\n onCompositionEnd,\n style,\n ...restTextAreaProps\n } = props;\n\n const isBordered = bordered ?? border ?? true;\n\n const contextDisabled = useContext(DisabledContext);\n const mergedDisabled = disabled ?? contextDisabled;\n\n const contentSize = useContext(SizeContext);\n const size = customSize || contentSize || 'middle';\n const isControlled = 'value' in props;\n const [innerValue, setInnerValue] = useState(defaultValue ?? '');\n const currentValue = isControlled ? controlledValue ?? '' : innerValue;\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(ref, () => textareaRef.current!);\n\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setInnerValue(e.target.value);\n onChange?.(e);\n };\n\n const handleClear = () => {\n if (!isControlled) setInnerValue('');\n onChange?.({\n target: { value: '' },\n } as React.ChangeEvent<HTMLTextAreaElement>);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter') onPressEnter?.(e);\n onKeyDown?.(e);\n };\n\n const minRows = typeof autoSize === 'object' ? autoSize.minRows : undefined;\n const maxRows = typeof autoSize === 'object' ? autoSize.maxRows : undefined;\n\n return (\n <div\n className={cn(\n 'ald-input ald-input-textarea tw-relative',\n `ald-input-textarea-${getSizeType(size)}`,\n isBordered &&\n 'tw-rounded-r-75 tw-border tw-border-solid tw-border-[var(--border-default)]',\n mergedDisabled && 'ald-input-disabled tw-opacity-50',\n className,\n )}\n style={style}\n >\n <textarea\n ref={textareaRef}\n className=\"tw-w-full tw-resize-y tw-border-0 tw-bg-transparent tw-px-3 tw-py-2 tw-text-sm tw-text-[var(--content-primary)] tw-outline-none\"\n value={currentValue}\n onChange={handleChange}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyDown={handleKeyDown}\n onCompositionStart={onCompositionStart}\n onCompositionEnd={onCompositionEnd}\n disabled={mergedDisabled}\n placeholder={placeholder}\n maxLength={maxLength}\n rows={rows || (minRows ?? 3)}\n spellCheck={false}\n autoComplete=\"off\"\n {...restTextAreaProps}\n style={{\n minHeight: minRows ? `${minRows * 22}px` : undefined,\n maxHeight: maxRows ? `${maxRows * 22}px` : undefined,\n }}\n />\n {allowClear && currentValue && !mergedDisabled && (\n <span\n className=\"tw-absolute tw-right-2 tw-top-2 tw-cursor-pointer\"\n onClick={handleClear}\n >\n <CloseCircleFill size={16} color=\"var(--alias-colors-icon-subtle)\" />\n </span>\n )}\n {showCount && (\n <div className=\"tw-px-2 tw-pb-1 tw-text-right tw-text-xs tw-text-[var(--content-tertiary)]\">\n {typeof showCount === 'object'\n ? showCount.formatter({ count: currentValue.length, maxLength })\n : `${currentValue.length}${maxLength ? `/${maxLength}` : ''}`}\n </div>\n )}\n </div>\n );\n});\n"],"mappings":";;;;;;;;AAyCA,IAAA,mBAAe,YAAyC,OAAO,QAAQ;CACrE,MAAM,EACJ,UACA,QACA,MAAM,YACN,UACA,YAAY,IACZ,aAAa,OACb,OAAO,iBACP,cACA,UACA,cACA,WACA,WACA,UACA,aACA,MACA,QACA,SACA,WACA,oBACA,kBACA,OACA,GAAG,sBACD;CAEJ,MAAM,aAAa,YAAY,UAAU;CAEzC,MAAM,kBAAkB,WAAW,gBAAgB;CACnD,MAAM,iBAAiB,YAAY;CAEnC,MAAM,cAAc,WAAW,YAAY;CAC3C,MAAM,OAAO,cAAc,eAAe;CAC1C,MAAM,eAAe,WAAW;CAChC,MAAM,CAAC,YAAY,iBAAiB,SAAS,gBAAgB,GAAG;CAChE,MAAM,eAAe,eAAe,mBAAmB,KAAK;CAC5D,MAAM,cAAc,OAA4B,KAAK;AAErD,OAAM,oBAAoB,WAAW,YAAY,QAAS;CAE1D,MAAM,gBAAgB,MAA8C;AAClE,MAAI,CAAC,aAAc,eAAc,EAAE,OAAO,MAAM;AAChD,aAAW,EAAE;;CAGf,MAAM,oBAAoB;AACxB,MAAI,CAAC,aAAc,eAAc,GAAG;AACpC,aAAW,EACT,QAAQ,EAAE,OAAO,IAAI,EACtB,CAA2C;;CAG9C,MAAM,iBAAiB,MAAgD;AACrE,MAAI,EAAE,QAAQ,QAAS,gBAAe,EAAE;AACxC,cAAY,EAAE;;CAGhB,MAAM,UAAU,OAAO,aAAa,WAAW,SAAS,UAAU;CAClE,MAAM,UAAU,OAAO,aAAa,WAAW,SAAS,UAAU;AAElE,QACE,qBAAC,OAAD;EACE,WAAW,GACT,4CACA,sBAAsB,YAAY,KAAK,IACvC,cACE,+EACF,kBAAkB,oCAClB,UACD;EACM;YATT;GAWE,oBAAC,YAAD;IACE,KAAK;IACL,WAAU;IACV,OAAO;IACP,UAAU;IACF;IACC;IACT,WAAW;IACS;IACF;IAClB,UAAU;IACG;IACF;IACX,MAAM,SAAS,WAAW;IAC1B,YAAY;IACZ,cAAa;IACb,GAAI;IACJ,OAAO;KACL,WAAW,UAAU,GAAG,UAAU,GAAG,MAAM;KAC3C,WAAW,UAAU,GAAG,UAAU,GAAG,MAAM;KAC5C;IACD,CAAA;GACD,cAAc,gBAAgB,CAAC,kBAC9B,oBAAC,QAAD;IACE,WAAU;IACV,SAAS;cAET,oBAAC,MAAD;KAAiB,MAAM;KAAI,OAAM;KAAoC,CAAA;IAChE,CAAA;GAER,aACC,oBAAC,OAAD;IAAK,WAAU;cACZ,OAAO,cAAc,WAClB,UAAU,UAAU;KAAE,OAAO,aAAa;KAAQ;KAAW,CAAC,GAC9D,GAAG,aAAa,SAAS,YAAY,IAAI,cAAc;IACvD,CAAA;GAEJ;;EAER"}
|
|
@@ -15,6 +15,8 @@ export interface PopconfirmProps {
|
|
|
15
15
|
placement?: 'top' | 'bottom' | 'left' | 'right' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom';
|
|
16
16
|
rootClassName?: string;
|
|
17
17
|
className?: string;
|
|
18
|
+
overlayClassName?: string;
|
|
19
|
+
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
|
|
18
20
|
children?: React.ReactNode;
|
|
19
21
|
disabled?: boolean;
|
|
20
22
|
}
|
package/dist/Popconfirm/index.js
CHANGED
|
@@ -35,10 +35,30 @@ function Popconfirm(props) {
|
|
|
35
35
|
size: 16,
|
|
36
36
|
color: "var(--action-destructive-normal)",
|
|
37
37
|
fill: "var(--action-inverted-normal)"
|
|
38
|
-
}), open: controlledOpen, onOpenChange, placement = "top", rootClassName, children, disabled } = props;
|
|
38
|
+
}), open: controlledOpen, onOpenChange, placement = "top", rootClassName, overlayClassName, getPopupContainer, children, disabled } = props;
|
|
39
39
|
const [innerOpen, setInnerOpen] = useState(false);
|
|
40
|
+
const triggerRef = React.useRef(null);
|
|
41
|
+
const getPopupContainerRef = React.useRef(getPopupContainer);
|
|
42
|
+
const lastGetPopupContainerRef = React.useRef(getPopupContainer);
|
|
43
|
+
const [popupContainer, setPopupContainer] = useState();
|
|
44
|
+
getPopupContainerRef.current = getPopupContainer;
|
|
40
45
|
const isControlled = controlledOpen !== void 0;
|
|
41
46
|
const mergedOpen = disabled ? false : isControlled ? controlledOpen : innerOpen;
|
|
47
|
+
const updatePopupContainer = React.useCallback((node) => {
|
|
48
|
+
const nextContainer = node && getPopupContainerRef.current ? getPopupContainerRef.current(node) : void 0;
|
|
49
|
+
setPopupContainer((prevContainer) => prevContainer === nextContainer ? prevContainer : nextContainer);
|
|
50
|
+
}, []);
|
|
51
|
+
const setTriggerNode = React.useCallback((node) => {
|
|
52
|
+
if (!node) return;
|
|
53
|
+
if (triggerRef.current === node) return;
|
|
54
|
+
triggerRef.current = node;
|
|
55
|
+
updatePopupContainer(node);
|
|
56
|
+
}, [updatePopupContainer]);
|
|
57
|
+
React.useEffect(() => {
|
|
58
|
+
if (lastGetPopupContainerRef.current === getPopupContainer) return;
|
|
59
|
+
lastGetPopupContainerRef.current = getPopupContainer;
|
|
60
|
+
updatePopupContainer(triggerRef.current);
|
|
61
|
+
}, [getPopupContainer, updatePopupContainer]);
|
|
42
62
|
const handleOpenChange = (val) => {
|
|
43
63
|
if (disabled) return;
|
|
44
64
|
if (!isControlled) setInnerOpen(val);
|
|
@@ -55,50 +75,55 @@ function Popconfirm(props) {
|
|
|
55
75
|
const side = sideMap[placement] || "top";
|
|
56
76
|
const align = alignMap[placement] || "center";
|
|
57
77
|
const popupZIndex = useFloatingPopupZIndex();
|
|
78
|
+
const triggerChild = React.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
|
|
58
79
|
return /* @__PURE__ */ jsxs(PopoverPrimitive.Root, {
|
|
59
80
|
open: mergedOpen,
|
|
60
81
|
onOpenChange: handleOpenChange,
|
|
61
82
|
children: [/* @__PURE__ */ jsx(PopoverPrimitive.Trigger, {
|
|
62
83
|
asChild: true,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
className: "tw-mb-2 tw-break-all tw-text-xs tw-leading-4 tw-text-[var(--alias-colors-text-default)]",
|
|
82
|
-
children: title
|
|
84
|
+
ref: setTriggerNode,
|
|
85
|
+
children: triggerChild
|
|
86
|
+
}), /* @__PURE__ */ jsx(PopoverPrimitive.Portal, {
|
|
87
|
+
container: popupContainer,
|
|
88
|
+
children: /* @__PURE__ */ jsx(PopoverPrimitive.Content, {
|
|
89
|
+
side,
|
|
90
|
+
align,
|
|
91
|
+
sideOffset: 4,
|
|
92
|
+
className: cn("ald-pop-confirm tw-z-50 tw-w-[240px] tw-rounded-[6px] tw-border tw-border-solid tw-border-[var(--border-default-alpha)] tw-bg-[var(--background-default)] tw-p-3 tw-outline-none", rootClassName, overlayClassName),
|
|
93
|
+
style: {
|
|
94
|
+
zIndex: popupZIndex,
|
|
95
|
+
boxShadow: "var(--elevation-bottom-bottom-md)"
|
|
96
|
+
},
|
|
97
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
98
|
+
className: "tw-flex tw-gap-2",
|
|
99
|
+
children: [icon && /* @__PURE__ */ jsx("span", {
|
|
100
|
+
className: "tw-mt-0.5 tw-shrink-0",
|
|
101
|
+
children: icon
|
|
83
102
|
}), /* @__PURE__ */ jsxs("div", {
|
|
84
|
-
className: "tw-flex
|
|
85
|
-
children: [/* @__PURE__ */ jsx(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
children:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
103
|
+
className: "tw-flex-1",
|
|
104
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
105
|
+
className: "tw-mb-2 tw-break-all tw-text-xs tw-leading-4 tw-text-[var(--alias-colors-text-default)]",
|
|
106
|
+
children: title
|
|
107
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
108
|
+
className: "tw-flex tw-justify-end tw-gap-2",
|
|
109
|
+
children: [/* @__PURE__ */ jsx(Button_default, {
|
|
110
|
+
type: "secondary",
|
|
111
|
+
size: "small",
|
|
112
|
+
...cancelButtonProps,
|
|
113
|
+
onClick: handleCancel,
|
|
114
|
+
children: cancelText
|
|
115
|
+
}), /* @__PURE__ */ jsx(Button_default, {
|
|
116
|
+
type: okType,
|
|
117
|
+
size: "small",
|
|
118
|
+
...okButtonProps,
|
|
119
|
+
onClick: handleConfirm,
|
|
120
|
+
children: okText
|
|
121
|
+
})]
|
|
97
122
|
})]
|
|
98
123
|
})]
|
|
99
|
-
})
|
|
124
|
+
})
|
|
100
125
|
})
|
|
101
|
-
})
|
|
126
|
+
})]
|
|
102
127
|
});
|
|
103
128
|
}
|
|
104
129
|
//#endregion
|