@tiny-design/react 1.0.10 → 1.1.0

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/es/index.d.ts CHANGED
@@ -31,6 +31,7 @@ import { DefaultForm } from "./form/index.js";
31
31
  import { Image } from "./image/image.js";
32
32
  import { DefaultInput } from "./input/index.js";
33
33
  import { InputNumber } from "./input-number/input-number.js";
34
+ import { InputOTP } from "./input-otp/input-otp.js";
34
35
  import { InputPassword } from "./input-password/input-password.js";
35
36
  import { IntlProvider } from "./intl-provider/intl-provider.js";
36
37
  import { Keyboard } from "./keyboard/keyboard.js";
@@ -85,4 +86,4 @@ import { en_US } from "./locale/en_US.js";
85
86
  import { zh_CN } from "./locale/zh_CN.js";
86
87
  import { useLocale } from "./_utils/use-locale.js";
87
88
  import { ThemeMode, useTheme } from "./_utils/use-theme.js";
88
- export { Alert, DefaultAnchor as Anchor, AspectRatio, AutoComplete, DefaultAvatar as Avatar, BackTop, Badge, DefaultBreadcrumb as Breadcrumb, DefaultButton as Button, Calendar, DefaultCard as Card, DefaultCarousel as Carousel, Cascader, DefaultCheckbox as Checkbox, Col, DefaultCollapse as Collapse, ColorPicker, ConfigProvider, CopyToClipboard, Countdown, DatePicker, DefaultDesc as Descriptions, Divider, Drawer, Dropdown, Empty, Flex, DefaultFlip as Flip, DefaultForm as Form, Image, DefaultInput as Input, InputNumber, InputPassword, IntlProvider, Keyboard, DefaultLayout as Layout, Link, DefaultList as List, Loader, _default as LoadingBar, type Locale, DefaultMenu as Menu, messageContainer as Message, ModalWithContext as Modal, DefaultSelect as NativeSelect, notificationContainer as Notification, Overlay, Pagination, PopConfirm, Popover, Progress, DefaultRadio as Radio, Rate, Result, Row, ScrollIndicator, Segmented, DefaultSelect$1 as Select, Skeleton, Slider, Space, DefaultSpeedDial as SpeedDial, Split, SplitButton, Statistic, DefaultSteps as Steps, Sticky, StrengthIndicator, Switch, Table, DefaultTabs as Tabs, DefaultTag as Tag, Textarea, type ThemeMode, TimePicker, DefaultTimeline as Timeline, Tooltip, Transfer, Transition, Tree, DefaultTypo as Typography, Upload, en_US, useLocale, useTheme, withLocale, withSpin, zh_CN };
89
+ export { Alert, DefaultAnchor as Anchor, AspectRatio, AutoComplete, DefaultAvatar as Avatar, BackTop, Badge, DefaultBreadcrumb as Breadcrumb, DefaultButton as Button, Calendar, DefaultCard as Card, DefaultCarousel as Carousel, Cascader, DefaultCheckbox as Checkbox, Col, DefaultCollapse as Collapse, ColorPicker, ConfigProvider, CopyToClipboard, Countdown, DatePicker, DefaultDesc as Descriptions, Divider, Drawer, Dropdown, Empty, Flex, DefaultFlip as Flip, DefaultForm as Form, Image, DefaultInput as Input, InputNumber, InputOTP, InputPassword, IntlProvider, Keyboard, DefaultLayout as Layout, Link, DefaultList as List, Loader, _default as LoadingBar, type Locale, DefaultMenu as Menu, messageContainer as Message, ModalWithContext as Modal, DefaultSelect as NativeSelect, notificationContainer as Notification, Overlay, Pagination, PopConfirm, Popover, Progress, DefaultRadio as Radio, Rate, Result, Row, ScrollIndicator, Segmented, DefaultSelect$1 as Select, Skeleton, Slider, Space, DefaultSpeedDial as SpeedDial, Split, SplitButton, Statistic, DefaultSteps as Steps, Sticky, StrengthIndicator, Switch, Table, DefaultTabs as Tabs, DefaultTag as Tag, Textarea, type ThemeMode, TimePicker, DefaultTimeline as Timeline, Tooltip, Transfer, Transition, Tree, DefaultTypo as Typography, Upload, en_US, useLocale, useTheme, withLocale, withSpin, zh_CN };
package/es/index.js CHANGED
@@ -37,6 +37,7 @@ import DefaultForm from "./form/index.js";
37
37
  import image_default from "./image/index.js";
38
38
  import DefaultInput from "./input/index.js";
39
39
  import input_number_default from "./input-number/index.js";
40
+ import input_otp_default from "./input-otp/index.js";
40
41
  import input_password_default from "./input-password/index.js";
41
42
  import keyboard_default from "./keyboard/index.js";
42
43
  import DefaultLayout from "./layout/index.js";
@@ -85,4 +86,4 @@ import { withLocale } from "./intl-provider/with-locale.js";
85
86
  import { withSpin } from "./with-spin/with-spin.js";
86
87
  import zh_CN from "./locale/zh_CN.js";
87
88
  import { useTheme } from "./_utils/use-theme.js";
88
- export { alert_default as Alert, DefaultAnchor as Anchor, aspect_ratio_default as AspectRatio, AutoComplete, DefaultAvatar as Avatar, back_top_default as BackTop, badge_default as Badge, DefaultBreadcrumb as Breadcrumb, DefaultButton as Button, calendar_default as Calendar, DefaultCard as Card, DefaultCarousel as Carousel, cascader_default as Cascader, DefaultCheckbox as Checkbox, col_default as Col, DefaultCollapse as Collapse, color_picker_default as ColorPicker, config_provider_default as ConfigProvider, copy_to_clipboard_default as CopyToClipboard, countdown_default as Countdown, date_picker_default as DatePicker, DefaultDesc as Descriptions, divider_default as Divider, drawer_default as Drawer, dropdown_default as Dropdown, empty_default as Empty, flex_default as Flex, DefaultFlip as Flip, DefaultForm as Form, image_default as Image, DefaultInput as Input, input_number_default as InputNumber, input_password_default as InputPassword, intl_provider_default as IntlProvider, keyboard_default as Keyboard, DefaultLayout as Layout, link_default as Link, DefaultList as List, loader_default as Loader, loading_bar_default as LoadingBar, DefaultMenu as Menu, message_default as Message, ModalWithContext as Modal, DefaultSelect as NativeSelect, notification_default as Notification, overlay_default as Overlay, pagination_default as Pagination, pop_confirm_default as PopConfirm, popover_default as Popover, Progress, DefaultRadio as Radio, rate_default as Rate, result_default as Result, row_default as Row, scroll_indicator_default as ScrollIndicator, segmented_default as Segmented, DefaultSelect$1 as Select, skeleton_default as Skeleton, slider_default as Slider, space_default as Space, DefaultSpeedDial as SpeedDial, split_default as Split, split_button_default as SplitButton, statistic_default as Statistic, DefaultSteps as Steps, sticky_default as Sticky, strength_indicator_default as StrengthIndicator, switch_default as Switch, table_default as Table, DefaultTabs as Tabs, DefaultTag as Tag, textarea_default as Textarea, time_picker_default as TimePicker, DefaultTimeline as Timeline, tooltip_default as Tooltip, transfer_default as Transfer, transition_default as Transition, tree_default as Tree, DefaultTypo as Typography, upload_default as Upload, en_US, useLocale, useTheme, withLocale, withSpin, zh_CN };
89
+ export { alert_default as Alert, DefaultAnchor as Anchor, aspect_ratio_default as AspectRatio, AutoComplete, DefaultAvatar as Avatar, back_top_default as BackTop, badge_default as Badge, DefaultBreadcrumb as Breadcrumb, DefaultButton as Button, calendar_default as Calendar, DefaultCard as Card, DefaultCarousel as Carousel, cascader_default as Cascader, DefaultCheckbox as Checkbox, col_default as Col, DefaultCollapse as Collapse, color_picker_default as ColorPicker, config_provider_default as ConfigProvider, copy_to_clipboard_default as CopyToClipboard, countdown_default as Countdown, date_picker_default as DatePicker, DefaultDesc as Descriptions, divider_default as Divider, drawer_default as Drawer, dropdown_default as Dropdown, empty_default as Empty, flex_default as Flex, DefaultFlip as Flip, DefaultForm as Form, image_default as Image, DefaultInput as Input, input_number_default as InputNumber, input_otp_default as InputOTP, input_password_default as InputPassword, intl_provider_default as IntlProvider, keyboard_default as Keyboard, DefaultLayout as Layout, link_default as Link, DefaultList as List, loader_default as Loader, loading_bar_default as LoadingBar, DefaultMenu as Menu, message_default as Message, ModalWithContext as Modal, DefaultSelect as NativeSelect, notification_default as Notification, overlay_default as Overlay, pagination_default as Pagination, pop_confirm_default as PopConfirm, popover_default as Popover, Progress, DefaultRadio as Radio, rate_default as Rate, result_default as Result, row_default as Row, scroll_indicator_default as ScrollIndicator, segmented_default as Segmented, DefaultSelect$1 as Select, skeleton_default as Skeleton, slider_default as Slider, space_default as Space, DefaultSpeedDial as SpeedDial, split_default as Split, split_button_default as SplitButton, statistic_default as Statistic, DefaultSteps as Steps, sticky_default as Sticky, strength_indicator_default as StrengthIndicator, switch_default as Switch, table_default as Table, DefaultTabs as Tabs, DefaultTag as Tag, textarea_default as Textarea, time_picker_default as TimePicker, DefaultTimeline as Timeline, tooltip_default as Tooltip, transfer_default as Transfer, transition_default as Transition, tree_default as Tree, DefaultTypo as Typography, upload_default as Upload, en_US, useLocale, useTheme, withLocale, withSpin, zh_CN };
@@ -14,11 +14,15 @@ const InputGroupAddon = (props) => {
14
14
  className: cls,
15
15
  style,
16
16
  children: React.Children.map(children, (child) => {
17
- const childProps = {
18
- disabled,
19
- size: inputSize
20
- };
21
- return React.cloneElement(child, childProps);
17
+ const displayName = child.type?.displayName;
18
+ if (displayName === "Input" || displayName === "Button" || displayName === "Select") {
19
+ const childProps = {
20
+ disabled,
21
+ size: inputSize
22
+ };
23
+ return React.cloneElement(child, childProps);
24
+ }
25
+ return child;
22
26
  })
23
27
  });
24
28
  return /* @__PURE__ */ jsx("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"input-group-addon.js","names":[],"sources":["../../src/input/input-group-addon.tsx"],"sourcesContent":["import React, { useContext } from 'react';\nimport classNames from 'classnames';\nimport { ConfigContext } from '../config-provider/config-context';\nimport { getPrefixCls } from '../_utils/general';\nimport { InputGroupAddonProps, InputProps } from './types';\nimport { SizeType } from '../_utils/props';\n\nconst InputGroupAddon = (props: InputGroupAddonProps): React.ReactElement => {\n const {\n disabled = false,\n size = 'md',\n noBorder,\n className,\n style,\n children,\n prefixCls: customisedCls,\n ...otherProps\n } = props;\n const configContext = useContext(ConfigContext);\n const prefixCls = getPrefixCls('input-group-addon', configContext.prefixCls, customisedCls);\n const inputSize = props.size || configContext.componentSize || size;\n const cls = classNames(prefixCls, className, `${prefixCls}_${inputSize}`, {\n [`${prefixCls}_no-border`]: noBorder,\n });\n\n if (React.isValidElement(children)) {\n return (\n <div className={cls} style={style}>\n {React.Children.map(children, (child: React.ReactElement) => {\n const childProps: Partial<InputProps> = {\n disabled,\n size: inputSize as SizeType,\n };\n return React.cloneElement(child, childProps);\n })}\n </div>\n );\n }\n return (\n <div {...otherProps} className={cls} style={style}>\n {children}\n </div>\n );\n};\n\nInputGroupAddon.displayName = 'InputGroupAddon';\n\nexport default InputGroupAddon;\n"],"mappings":";;;;;;AAOA,MAAM,mBAAmB,UAAoD;CAC3E,MAAM,EACJ,WAAW,OACX,OAAO,MACP,UACA,WACA,OACA,UACA,WAAW,eACX,GAAG,eACD;CACJ,MAAM,gBAAgB,WAAW,cAAc;CAC/C,MAAM,YAAY,aAAa,qBAAqB,cAAc,WAAW,cAAc;CAC3F,MAAM,YAAY,MAAM,QAAQ,cAAc,iBAAiB;CAC/D,MAAM,MAAM,WAAW,WAAW,WAAW,GAAG,UAAU,GAAG,aAAa,GACvE,GAAG,UAAU,cAAc,UAC7B,CAAC;AAEF,KAAI,MAAM,eAAe,SAAS,CAChC,QACE,oBAAC,OAAD;EAAK,WAAW;EAAY;YACzB,MAAM,SAAS,IAAI,WAAW,UAA8B;GAC3D,MAAM,aAAkC;IACtC;IACA,MAAM;IACP;AACD,UAAO,MAAM,aAAa,OAAO,WAAW;IAC5C;EACE,CAAA;AAGV,QACE,oBAAC,OAAD;EAAK,GAAI;EAAY,WAAW;EAAY;EACzC;EACG,CAAA;;AAIV,gBAAgB,cAAc"}
1
+ {"version":3,"file":"input-group-addon.js","names":[],"sources":["../../src/input/input-group-addon.tsx"],"sourcesContent":["import React, { useContext } from 'react';\nimport classNames from 'classnames';\nimport { ConfigContext } from '../config-provider/config-context';\nimport { getPrefixCls } from '../_utils/general';\nimport { InputGroupAddonProps, InputProps } from './types';\nimport { SizeType } from '../_utils/props';\n\nconst InputGroupAddon = (props: InputGroupAddonProps): React.ReactElement => {\n const {\n disabled = false,\n size = 'md',\n noBorder,\n className,\n style,\n children,\n prefixCls: customisedCls,\n ...otherProps\n } = props;\n const configContext = useContext(ConfigContext);\n const prefixCls = getPrefixCls('input-group-addon', configContext.prefixCls, customisedCls);\n const inputSize = props.size || configContext.componentSize || size;\n const cls = classNames(prefixCls, className, `${prefixCls}_${inputSize}`, {\n [`${prefixCls}_no-border`]: noBorder,\n });\n\n if (React.isValidElement(children)) {\n return (\n <div className={cls} style={style}>\n {React.Children.map(children, (child: React.ReactElement) => {\n const displayName = (child.type as any)?.displayName;\n if (displayName === 'Input' || displayName === 'Button' || displayName === 'Select') {\n const childProps: Partial<InputProps> = {\n disabled,\n size: inputSize as SizeType,\n };\n return React.cloneElement(child, childProps);\n }\n return child;\n })}\n </div>\n );\n }\n return (\n <div {...otherProps} className={cls} style={style}>\n {children}\n </div>\n );\n};\n\nInputGroupAddon.displayName = 'InputGroupAddon';\n\nexport default InputGroupAddon;\n"],"mappings":";;;;;;AAOA,MAAM,mBAAmB,UAAoD;CAC3E,MAAM,EACJ,WAAW,OACX,OAAO,MACP,UACA,WACA,OACA,UACA,WAAW,eACX,GAAG,eACD;CACJ,MAAM,gBAAgB,WAAW,cAAc;CAC/C,MAAM,YAAY,aAAa,qBAAqB,cAAc,WAAW,cAAc;CAC3F,MAAM,YAAY,MAAM,QAAQ,cAAc,iBAAiB;CAC/D,MAAM,MAAM,WAAW,WAAW,WAAW,GAAG,UAAU,GAAG,aAAa,GACvE,GAAG,UAAU,cAAc,UAC7B,CAAC;AAEF,KAAI,MAAM,eAAe,SAAS,CAChC,QACE,oBAAC,OAAD;EAAK,WAAW;EAAY;YACzB,MAAM,SAAS,IAAI,WAAW,UAA8B;GAC3D,MAAM,cAAe,MAAM,MAAc;AACzC,OAAI,gBAAgB,WAAW,gBAAgB,YAAY,gBAAgB,UAAU;IACnF,MAAM,aAAkC;KACtC;KACA,MAAM;KACP;AACD,WAAO,MAAM,aAAa,OAAO,WAAW;;AAE9C,UAAO;IACP;EACE,CAAA;AAGV,QACE,oBAAC,OAAD;EAAK,GAAI;EAAY,WAAW;EAAY;EACzC;EACG,CAAA;;AAIV,gBAAgB,cAAc"}
@@ -0,0 +1 @@
1
+ import { InputOTP } from "./input-otp.js";
@@ -0,0 +1,9 @@
1
+ import '../style/base.css';
2
+ import './style/index.css';
3
+ import InputOTP from "./input-otp.js";
4
+ //#region src/input-otp/index.tsx
5
+ var input_otp_default = InputOTP;
6
+ //#endregion
7
+ export { input_otp_default as default };
8
+
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/input-otp/index.tsx"],"sourcesContent":["import InputOTP from './input-otp';\n\nexport default InputOTP;\n"],"mappings":";;AAEA,IAAA,oBAAe"}
@@ -0,0 +1,13 @@
1
+ import { InputOTPProps } from "./types.js";
2
+ import React from "react";
3
+
4
+ //#region src/input-otp/input-otp.d.ts
5
+ interface InputOTPRef {
6
+ focus: () => void;
7
+ blur: () => void;
8
+ nativeElement: HTMLDivElement | null;
9
+ }
10
+ declare const InputOTP: React.ForwardRefExoticComponent<InputOTPProps & React.RefAttributes<InputOTPRef>>;
11
+ //#endregion
12
+ export { InputOTP };
13
+ //# sourceMappingURL=input-otp.d.ts.map
@@ -0,0 +1,128 @@
1
+ import { ConfigContext } from "../config-provider/config-context.js";
2
+ import { getPrefixCls } from "../_utils/general.js";
3
+ import OTPInput from "./otp-input.js";
4
+ import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
5
+ import classNames from "classnames";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/input-otp/input-otp.tsx
8
+ function strToArr(str) {
9
+ return (str || "").split("");
10
+ }
11
+ const InputOTP = React.forwardRef((props, ref) => {
12
+ const { length = 6, size = "md", defaultValue, value, onChange, formatter, separator, disabled = false, mask, autoFocus, autoComplete, className, style, prefixCls: customisedCls, onFocus, ...otherProps } = props;
13
+ const configContext = useContext(ConfigContext);
14
+ const prefixCls = getPrefixCls("input-otp", configContext.prefixCls, customisedCls);
15
+ const inputSize = size || configContext.componentSize || "md";
16
+ const containerRef = useRef(null);
17
+ const inputsRef = useRef({});
18
+ const internalFormatter = useCallback((txt) => formatter ? formatter(txt) : txt, [formatter]);
19
+ const [valueCells, setValueCells] = useState(() => strToArr(internalFormatter(defaultValue || "")));
20
+ useEffect(() => {
21
+ if (value !== void 0) setValueCells(strToArr(value));
22
+ }, [value]);
23
+ React.useImperativeHandle(ref, () => ({
24
+ focus: () => {
25
+ let nextIndex = 0;
26
+ for (let i = 0; i < length; i += 1) {
27
+ if (!inputsRef.current[i]?.value) {
28
+ nextIndex = i;
29
+ break;
30
+ }
31
+ nextIndex = i;
32
+ }
33
+ inputsRef.current[nextIndex]?.focus();
34
+ },
35
+ blur: () => {
36
+ for (let i = 0; i < length; i += 1) inputsRef.current[i]?.blur();
37
+ },
38
+ nativeElement: containerRef.current
39
+ }));
40
+ const triggerValueCellsChange = useCallback((nextValueCells) => {
41
+ setValueCells((prev) => {
42
+ const prevValue = prev.join("");
43
+ const nextValue = nextValueCells.join("");
44
+ if (onChange && prevValue !== nextValue) onChange(nextValue);
45
+ return nextValueCells;
46
+ });
47
+ }, [onChange]);
48
+ const patchValue = useCallback((index, txt) => {
49
+ let nextCells = [...valueCells];
50
+ for (let i = 0; i < index; i += 1) if (!nextCells[i]) nextCells[i] = "";
51
+ if (txt.length <= 1) nextCells[index] = txt;
52
+ else nextCells = nextCells.slice(0, index).concat(strToArr(txt));
53
+ nextCells = nextCells.slice(0, length);
54
+ for (let i = nextCells.length - 1; i >= 0; i -= 1) {
55
+ if (nextCells[i]) break;
56
+ nextCells.pop();
57
+ }
58
+ nextCells = strToArr(internalFormatter(nextCells.map((c) => c || " ").join(""))).map((c, i) => {
59
+ if (c === " " && !nextCells[i]) return nextCells[i];
60
+ return c;
61
+ });
62
+ return nextCells;
63
+ }, [
64
+ valueCells,
65
+ length,
66
+ internalFormatter
67
+ ]);
68
+ const onInputChange = useCallback((index, txt) => {
69
+ const nextCells = patchValue(index, txt);
70
+ const nextIndex = Math.min(index + txt.length, length - 1);
71
+ if (nextIndex !== index && nextCells[index] !== void 0) inputsRef.current[nextIndex]?.focus();
72
+ triggerValueCellsChange(nextCells);
73
+ }, [
74
+ patchValue,
75
+ length,
76
+ triggerValueCellsChange
77
+ ]);
78
+ const onInputActiveChange = useCallback((nextIndex) => {
79
+ const clampedIndex = Math.max(0, Math.min(nextIndex, length - 1));
80
+ inputsRef.current[clampedIndex]?.focus();
81
+ }, [length]);
82
+ const onInputFocus = useCallback((event, index) => {
83
+ if (onFocus) onFocus(event);
84
+ }, [onFocus]);
85
+ const renderSeparator = useMemo(() => {
86
+ if (!separator) return null;
87
+ return (index) => {
88
+ const separatorNode = typeof separator === "function" ? separator(index) : separator;
89
+ if (!separatorNode) return null;
90
+ return /* @__PURE__ */ jsx("span", {
91
+ className: `${prefixCls}__separator`,
92
+ children: separatorNode
93
+ });
94
+ };
95
+ }, [separator, prefixCls]);
96
+ const cls = classNames(prefixCls, className, `${prefixCls}_${inputSize}`, { [`${prefixCls}_disabled`]: disabled });
97
+ return /* @__PURE__ */ jsx("div", {
98
+ ...otherProps,
99
+ ref: containerRef,
100
+ className: cls,
101
+ style,
102
+ role: "group",
103
+ children: Array.from({ length }).map((_, index) => {
104
+ const singleValue = valueCells[index] || "";
105
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [/* @__PURE__ */ jsx(OTPInput, {
106
+ ref: (el) => {
107
+ inputsRef.current[index] = el;
108
+ },
109
+ index,
110
+ size: inputSize,
111
+ prefixCls,
112
+ value: singleValue,
113
+ disabled,
114
+ mask,
115
+ autoFocus: index === 0 && autoFocus,
116
+ autoComplete,
117
+ onChange: onInputChange,
118
+ onActiveChange: onInputActiveChange,
119
+ onFocus: (e) => onInputFocus(e, index)
120
+ }), index < length - 1 && renderSeparator?.(index)] }, `otp-${index}`);
121
+ })
122
+ });
123
+ });
124
+ InputOTP.displayName = "InputOTP";
125
+ //#endregion
126
+ export { InputOTP as default };
127
+
128
+ //# sourceMappingURL=input-otp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-otp.js","names":[],"sources":["../../src/input-otp/input-otp.tsx"],"sourcesContent":["import React, { useRef, useState, useEffect, useContext, useCallback, useMemo } from 'react';\nimport classNames from 'classnames';\nimport { ConfigContext } from '../config-provider/config-context';\nimport { getPrefixCls } from '../_utils/general';\nimport { InputOTPProps } from './types';\nimport OTPInput from './otp-input';\n\nfunction strToArr(str: string): string[] {\n return (str || '').split('');\n}\n\nexport interface InputOTPRef {\n focus: () => void;\n blur: () => void;\n nativeElement: HTMLDivElement | null;\n}\n\nconst InputOTP = React.forwardRef<InputOTPRef, InputOTPProps>(\n (props, ref) => {\n const {\n length = 6,\n size = 'md',\n defaultValue,\n value,\n onChange,\n formatter,\n separator,\n disabled = false,\n mask,\n autoFocus,\n autoComplete,\n className,\n style,\n prefixCls: customisedCls,\n onFocus,\n ...otherProps\n } = props;\n\n const configContext = useContext(ConfigContext);\n const prefixCls = getPrefixCls('input-otp', configContext.prefixCls, customisedCls);\n const inputSize = size || configContext.componentSize || 'md';\n\n const containerRef = useRef<HTMLDivElement>(null);\n const inputsRef = useRef<Record<number, HTMLInputElement | null>>({});\n\n // Formatter helper\n const internalFormatter = useCallback(\n (txt: string) => (formatter ? formatter(txt) : txt),\n [formatter]\n );\n\n // Value state\n const [valueCells, setValueCells] = useState<string[]>(() =>\n strToArr(internalFormatter(defaultValue || ''))\n );\n\n useEffect(() => {\n if (value !== undefined) {\n setValueCells(strToArr(value));\n }\n }, [value]);\n\n // Imperative handle\n React.useImperativeHandle(ref, () => ({\n focus: () => {\n // Focus first empty cell (or last cell if all filled)\n let nextIndex = 0;\n for (let i = 0; i < length; i += 1) {\n if (!inputsRef.current[i]?.value) {\n nextIndex = i;\n break;\n }\n nextIndex = i;\n }\n inputsRef.current[nextIndex]?.focus();\n },\n blur: () => {\n for (let i = 0; i < length; i += 1) {\n inputsRef.current[i]?.blur();\n }\n },\n nativeElement: containerRef.current,\n }));\n\n // Trigger onChange when value cells change\n const triggerValueCellsChange = useCallback(\n (nextValueCells: string[]) => {\n setValueCells((prev) => {\n const prevValue = prev.join('');\n const nextValue = nextValueCells.join('');\n if (onChange && prevValue !== nextValue) {\n onChange(nextValue);\n }\n return nextValueCells;\n });\n },\n [onChange]\n );\n\n // Patch value at given index\n const patchValue = useCallback(\n (index: number, txt: string) => {\n let nextCells = [...valueCells];\n\n // Fill cells till index\n for (let i = 0; i < index; i += 1) {\n if (!nextCells[i]) {\n nextCells[i] = '';\n }\n }\n\n if (txt.length <= 1) {\n nextCells[index] = txt;\n } else {\n nextCells = nextCells.slice(0, index).concat(strToArr(txt));\n }\n nextCells = nextCells.slice(0, length);\n\n // Clean trailing empty cells\n for (let i = nextCells.length - 1; i >= 0; i -= 1) {\n if (nextCells[i]) {\n break;\n }\n nextCells.pop();\n }\n\n // Format if needed\n const formattedValue = internalFormatter(\n nextCells.map((c) => c || ' ').join('')\n );\n nextCells = strToArr(formattedValue).map((c, i) => {\n if (c === ' ' && !nextCells[i]) {\n return nextCells[i];\n }\n return c;\n });\n\n return nextCells;\n },\n [valueCells, length, internalFormatter]\n );\n\n // Handle input change\n const onInputChange = useCallback(\n (index: number, txt: string) => {\n const nextCells = patchValue(index, txt);\n const nextIndex = Math.min(index + txt.length, length - 1);\n if (nextIndex !== index && nextCells[index] !== undefined) {\n inputsRef.current[nextIndex]?.focus();\n }\n triggerValueCellsChange(nextCells);\n },\n [patchValue, length, triggerValueCellsChange]\n );\n\n // Handle active change (arrow keys, backspace)\n const onInputActiveChange = useCallback(\n (nextIndex: number) => {\n const clampedIndex = Math.max(0, Math.min(nextIndex, length - 1));\n inputsRef.current[clampedIndex]?.focus();\n },\n [length]\n );\n\n // Handle focus — keep focus on the interacted cell\n const onInputFocus = useCallback(\n (event: React.FocusEvent<HTMLInputElement>, index: number) => {\n if (onFocus) {\n (onFocus as React.FocusEventHandler<HTMLDivElement>)(event as unknown as React.FocusEvent<HTMLDivElement>);\n }\n },\n [onFocus]\n );\n\n // Render separator\n const renderSeparator = useMemo(() => {\n if (!separator) return null;\n return (index: number) => {\n const separatorNode =\n typeof separator === 'function' ? separator(index) : separator;\n if (!separatorNode) return null;\n return (\n <span className={`${prefixCls}__separator`}>\n {separatorNode}\n </span>\n );\n };\n }, [separator, prefixCls]);\n\n const cls = classNames(prefixCls, className, `${prefixCls}_${inputSize}`, {\n [`${prefixCls}_disabled`]: disabled,\n });\n\n return (\n <div\n {...otherProps}\n ref={containerRef}\n className={cls}\n style={style}\n role=\"group\"\n >\n {Array.from({ length }).map((_, index) => {\n const singleValue = valueCells[index] || '';\n return (\n <React.Fragment key={`otp-${index}`}>\n <OTPInput\n ref={(el) => {\n inputsRef.current[index] = el;\n }}\n index={index}\n size={inputSize}\n prefixCls={prefixCls}\n value={singleValue}\n disabled={disabled}\n mask={mask}\n autoFocus={index === 0 && autoFocus}\n autoComplete={autoComplete}\n onChange={onInputChange}\n onActiveChange={onInputActiveChange}\n onFocus={(e) => onInputFocus(e, index)}\n />\n {index < length - 1 && renderSeparator?.(index)}\n </React.Fragment>\n );\n })}\n </div>\n );\n }\n);\n\nInputOTP.displayName = 'InputOTP';\n\nexport default InputOTP;\n"],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import React, { useCallback, useRef } from "react";
2
+ import classNames from "classnames";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/input-otp/otp-input.tsx
5
+ const OTPInput = React.forwardRef((props, ref) => {
6
+ const { index, value, disabled, mask, size = "md", autoFocus, autoComplete, prefixCls, onChange, onActiveChange, onFocus } = props;
7
+ const inputRef = useRef(null);
8
+ const setRef = useCallback((el) => {
9
+ inputRef.current = el;
10
+ if (typeof ref === "function") ref(el);
11
+ else if (ref) ref.current = el;
12
+ }, [ref]);
13
+ const syncSelection = useCallback(() => {
14
+ requestAnimationFrame(() => {
15
+ const inputEle = inputRef.current;
16
+ if (document.activeElement === inputEle && inputEle) inputEle.select();
17
+ });
18
+ }, []);
19
+ const onInternalInput = (e) => {
20
+ onChange(index, e.target.value);
21
+ };
22
+ const onInternalFocus = (e) => {
23
+ onFocus?.(e);
24
+ syncSelection();
25
+ };
26
+ const onInternalKeyDown = (event) => {
27
+ const { key, ctrlKey, metaKey } = event;
28
+ if (key === "ArrowLeft") onActiveChange(index - 1);
29
+ else if (key === "ArrowRight") onActiveChange(index + 1);
30
+ else if (key === "z" && (ctrlKey || metaKey)) event.preventDefault();
31
+ else if (key === "Backspace" && !value) onActiveChange(index - 1);
32
+ syncSelection();
33
+ };
34
+ const displayValue = mask && typeof mask === "string" && value ? mask : value;
35
+ const inputType = mask === true ? "password" : "text";
36
+ return /* @__PURE__ */ jsx("input", {
37
+ ref: setRef,
38
+ "aria-label": `OTP Input ${index + 1}`,
39
+ type: inputType,
40
+ inputMode: "numeric",
41
+ autoComplete: autoComplete || "one-time-code",
42
+ className: classNames(`${prefixCls}__cell`, `${prefixCls}__cell_${size}`, {
43
+ [`${prefixCls}__cell_disabled`]: disabled,
44
+ [`${prefixCls}__cell_mask`]: mask
45
+ }),
46
+ value: displayValue,
47
+ disabled,
48
+ autoFocus,
49
+ onInput: onInternalInput,
50
+ onFocus: onInternalFocus,
51
+ onKeyDown: onInternalKeyDown,
52
+ onMouseDown: syncSelection,
53
+ onMouseUp: syncSelection
54
+ });
55
+ });
56
+ OTPInput.displayName = "OTPInput";
57
+ //#endregion
58
+ export { OTPInput as default };
59
+
60
+ //# sourceMappingURL=otp-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otp-input.js","names":[],"sources":["../../src/input-otp/otp-input.tsx"],"sourcesContent":["import React, { useRef, useCallback } from 'react';\nimport classNames from 'classnames';\nimport { OTPInputCellProps } from './types';\n\nconst OTPInput = React.forwardRef<HTMLInputElement, OTPInputCellProps>(\n (props, ref) => {\n const {\n index,\n value,\n disabled,\n mask,\n size = 'md',\n autoFocus,\n autoComplete,\n prefixCls,\n onChange,\n onActiveChange,\n onFocus,\n } = props;\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Merge refs\n const setRef = useCallback(\n (el: HTMLInputElement | null) => {\n inputRef.current = el;\n if (typeof ref === 'function') {\n ref(el);\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLInputElement | null>).current = el;\n }\n },\n [ref]\n );\n\n const syncSelection = useCallback(() => {\n requestAnimationFrame(() => {\n const inputEle = inputRef.current;\n if (document.activeElement === inputEle && inputEle) {\n inputEle.select();\n }\n });\n }, []);\n\n const onInternalInput = (e: React.FormEvent<HTMLInputElement>): void => {\n onChange(index, (e.target as HTMLInputElement).value);\n };\n\n const onInternalFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {\n onFocus?.(e);\n syncSelection();\n };\n\n const onInternalKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {\n const { key, ctrlKey, metaKey } = event;\n\n if (key === 'ArrowLeft') {\n onActiveChange(index - 1);\n } else if (key === 'ArrowRight') {\n onActiveChange(index + 1);\n } else if (key === 'z' && (ctrlKey || metaKey)) {\n event.preventDefault();\n } else if (key === 'Backspace' && !value) {\n onActiveChange(index - 1);\n }\n\n syncSelection();\n };\n\n const displayValue = mask && typeof mask === 'string' && value ? mask : value;\n const inputType = mask === true ? 'password' : 'text';\n\n return (\n <input\n ref={setRef}\n aria-label={`OTP Input ${index + 1}`}\n type={inputType}\n inputMode=\"numeric\"\n autoComplete={autoComplete || 'one-time-code'}\n className={classNames(`${prefixCls}__cell`, `${prefixCls}__cell_${size}`, {\n [`${prefixCls}__cell_disabled`]: disabled,\n [`${prefixCls}__cell_mask`]: mask,\n })}\n value={displayValue}\n disabled={disabled}\n autoFocus={autoFocus}\n onInput={onInternalInput}\n onFocus={onInternalFocus}\n onKeyDown={onInternalKeyDown}\n onMouseDown={syncSelection}\n onMouseUp={syncSelection}\n />\n );\n }\n);\n\nOTPInput.displayName = 'OTPInput';\n\nexport default OTPInput;\n"],"mappings":";;;;AAIA,MAAM,WAAW,MAAM,YACpB,OAAO,QAAQ;CACd,MAAM,EACJ,OACA,OACA,UACA,MACA,OAAO,MACP,WACA,cACA,WACA,UACA,gBACA,YACE;CAEJ,MAAM,WAAW,OAAgC,KAAK;CAGtD,MAAM,SAAS,aACZ,OAAgC;AAC/B,WAAS,UAAU;AACnB,MAAI,OAAO,QAAQ,WACjB,KAAI,GAAG;WACE,IACR,KAAwD,UAAU;IAGvE,CAAC,IAAI,CACN;CAED,MAAM,gBAAgB,kBAAkB;AACtC,8BAA4B;GAC1B,MAAM,WAAW,SAAS;AAC1B,OAAI,SAAS,kBAAkB,YAAY,SACzC,UAAS,QAAQ;IAEnB;IACD,EAAE,CAAC;CAEN,MAAM,mBAAmB,MAA+C;AACtE,WAAS,OAAQ,EAAE,OAA4B,MAAM;;CAGvD,MAAM,mBAA8D,MAAM;AACxE,YAAU,EAAE;AACZ,iBAAe;;CAGjB,MAAM,qBAAmE,UAAU;EACjF,MAAM,EAAE,KAAK,SAAS,YAAY;AAElC,MAAI,QAAQ,YACV,gBAAe,QAAQ,EAAE;WAChB,QAAQ,aACjB,gBAAe,QAAQ,EAAE;WAChB,QAAQ,QAAQ,WAAW,SACpC,OAAM,gBAAgB;WACb,QAAQ,eAAe,CAAC,MACjC,gBAAe,QAAQ,EAAE;AAG3B,iBAAe;;CAGjB,MAAM,eAAe,QAAQ,OAAO,SAAS,YAAY,QAAQ,OAAO;CACxE,MAAM,YAAY,SAAS,OAAO,aAAa;AAE/C,QACE,oBAAC,SAAD;EACE,KAAK;EACL,cAAY,aAAa,QAAQ;EACjC,MAAM;EACN,WAAU;EACV,cAAc,gBAAgB;EAC9B,WAAW,WAAW,GAAG,UAAU,SAAS,GAAG,UAAU,SAAS,QAAQ;IACvE,GAAG,UAAU,mBAAmB;IAChC,GAAG,UAAU,eAAe;GAC9B,CAAC;EACF,OAAO;EACG;EACC;EACX,SAAS;EACT,SAAS;EACT,WAAW;EACX,aAAa;EACb,WAAW;EACX,CAAA;EAGP;AAED,SAAS,cAAc"}
@@ -0,0 +1,53 @@
1
+ @use '../../style/variables' as *;
2
+ @use '../../input/style/mixin' as *;
3
+
4
+ .#{$prefix}-input-otp {
5
+ display: inline-flex;
6
+ align-items: center;
7
+ gap: 8px;
8
+
9
+ &__cell {
10
+ @include input-default;
11
+
12
+ width: 36px;
13
+ height: 36px;
14
+ text-align: center;
15
+ padding: 0;
16
+ font-size: $input-md-font-size;
17
+ border-radius: $input-border-radius;
18
+ caret-color: currentcolor;
19
+
20
+ &_sm {
21
+ width: 28px;
22
+ height: 28px;
23
+ font-size: $input-sm-font-size;
24
+ }
25
+
26
+ &_md {
27
+ width: 36px;
28
+ height: 36px;
29
+ font-size: $input-md-font-size;
30
+ }
31
+
32
+ &_lg {
33
+ width: 44px;
34
+ height: 44px;
35
+ font-size: $input-lg-font-size;
36
+ }
37
+
38
+ &_disabled {
39
+ @include input-default-disabled;
40
+ }
41
+ }
42
+
43
+ &__separator {
44
+ display: inline-flex;
45
+ align-items: center;
46
+ color: var(--ty-color-text-secondary);
47
+ font-size: $font-size-base;
48
+ }
49
+
50
+ &_disabled {
51
+ cursor: not-allowed;
52
+ }
53
+ }
@@ -0,0 +1,71 @@
1
+ .ty-input-otp {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: 8px;
5
+ }
6
+ .ty-input-otp__cell {
7
+ box-sizing: border-box;
8
+ width: 100%;
9
+ margin: 0;
10
+ color: var(--ty-color-text);
11
+ border: 1px solid var(--ty-input-border);
12
+ transition: all 0.3s;
13
+ outline: 0;
14
+ border-radius: 2px;
15
+ font-size: 1rem;
16
+ background-color: var(--ty-input-bg);
17
+ }
18
+ .ty-input-otp__cell:hover {
19
+ border-color: var(--ty-color-primary);
20
+ }
21
+ .ty-input-otp__cell:focus {
22
+ border-color: var(--ty-input-focus-border);
23
+ box-shadow: var(--ty-input-focus-shadow);
24
+ }
25
+ .ty-input-otp__cell::-moz-placeholder {
26
+ color: var(--ty-color-text-placeholder);
27
+ }
28
+ .ty-input-otp__cell::placeholder {
29
+ color: var(--ty-color-text-placeholder);
30
+ }
31
+ .ty-input-otp__cell {
32
+ width: 36px;
33
+ height: 36px;
34
+ text-align: center;
35
+ padding: 0;
36
+ font-size: 1rem;
37
+ border-radius: 2px;
38
+ caret-color: currentcolor;
39
+ }
40
+ .ty-input-otp__cell_sm {
41
+ width: 28px;
42
+ height: 28px;
43
+ font-size: 0.875rem;
44
+ }
45
+ .ty-input-otp__cell_md {
46
+ width: 36px;
47
+ height: 36px;
48
+ font-size: 1rem;
49
+ }
50
+ .ty-input-otp__cell_lg {
51
+ width: 44px;
52
+ height: 44px;
53
+ font-size: 1.25rem;
54
+ }
55
+ .ty-input-otp__cell_disabled {
56
+ cursor: not-allowed;
57
+ background-color: var(--ty-input-disabled-bg);
58
+ color: var(--ty-input-disabled-color);
59
+ }
60
+ .ty-input-otp__cell_disabled:hover {
61
+ border-color: var(--ty-input-border);
62
+ }
63
+ .ty-input-otp__separator {
64
+ display: inline-flex;
65
+ align-items: center;
66
+ color: var(--ty-color-text-secondary);
67
+ font-size: 1rem;
68
+ }
69
+ .ty-input-otp_disabled {
70
+ cursor: not-allowed;
71
+ }
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ import "./index.css";
@@ -0,0 +1,31 @@
1
+ import { BaseProps, SizeType } from "../_utils/props.js";
2
+ import React from "react";
3
+
4
+ //#region src/input-otp/types.d.ts
5
+ interface InputOTPProps extends BaseProps, Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'onInput'> {
6
+ /** Number of OTP input cells */
7
+ length?: number;
8
+ /** Size of the input */
9
+ size?: SizeType;
10
+ /** Default value of the OTP input */
11
+ defaultValue?: string;
12
+ /** Controlled value of the OTP input */
13
+ value?: string;
14
+ /** Callback when all cells are filled */
15
+ onChange?: (value: string) => void;
16
+ /** Custom formatter to restrict/modify input */
17
+ formatter?: (value: string) => string;
18
+ /** Separator element between cells */
19
+ separator?: ((index: number) => React.ReactNode) | React.ReactNode;
20
+ /** Whether the input is disabled */
21
+ disabled?: boolean;
22
+ /** Whether to mask the values, or a custom mask character */
23
+ mask?: boolean | string;
24
+ /** Auto focus the first cell on mount */
25
+ autoFocus?: boolean;
26
+ /** Autocomplete attribute */
27
+ autoComplete?: string;
28
+ }
29
+ //#endregion
30
+ export { InputOTPProps };
31
+ //# sourceMappingURL=types.d.ts.map
@@ -28,6 +28,7 @@
28
28
  @use "../image/style/index" as *;
29
29
  @use "../input/style/index" as *;
30
30
  @use "../input-number/style/index" as *;
31
+ @use "../input-otp/style/index" as *;
31
32
  @use "../input-password/style/index" as *;
32
33
  @use "../layout/style/index" as *;
33
34
  @use "../link/style/index" as *;
@@ -75,4 +76,4 @@
75
76
  @use "../tree/style/index" as *;
76
77
  @use "../typography/style/index" as *;
77
78
  @use "../upload/style/index" as *;
78
- @use "../with-spin/style/index" as *;
79
+ @use "../with-spin/style/index" as *;
package/lib/index.d.ts CHANGED
@@ -31,6 +31,7 @@ import { DefaultForm } from "./form/index.js";
31
31
  import { Image } from "./image/image.js";
32
32
  import { DefaultInput } from "./input/index.js";
33
33
  import { InputNumber } from "./input-number/input-number.js";
34
+ import { InputOTP } from "./input-otp/input-otp.js";
34
35
  import { InputPassword } from "./input-password/input-password.js";
35
36
  import { IntlProvider } from "./intl-provider/intl-provider.js";
36
37
  import { Keyboard } from "./keyboard/keyboard.js";
@@ -85,4 +86,4 @@ import { en_US } from "./locale/en_US.js";
85
86
  import { zh_CN } from "./locale/zh_CN.js";
86
87
  import { useLocale } from "./_utils/use-locale.js";
87
88
  import { ThemeMode, useTheme } from "./_utils/use-theme.js";
88
- export { Alert, DefaultAnchor as Anchor, AspectRatio, AutoComplete, DefaultAvatar as Avatar, BackTop, Badge, DefaultBreadcrumb as Breadcrumb, DefaultButton as Button, Calendar, DefaultCard as Card, DefaultCarousel as Carousel, Cascader, DefaultCheckbox as Checkbox, Col, DefaultCollapse as Collapse, ColorPicker, ConfigProvider, CopyToClipboard, Countdown, DatePicker, DefaultDesc as Descriptions, Divider, Drawer, Dropdown, Empty, Flex, DefaultFlip as Flip, DefaultForm as Form, Image, DefaultInput as Input, InputNumber, InputPassword, IntlProvider, Keyboard, DefaultLayout as Layout, Link, DefaultList as List, Loader, _default as LoadingBar, type Locale, DefaultMenu as Menu, messageContainer as Message, ModalWithContext as Modal, DefaultSelect as NativeSelect, notificationContainer as Notification, Overlay, Pagination, PopConfirm, Popover, Progress, DefaultRadio as Radio, Rate, Result, Row, ScrollIndicator, Segmented, DefaultSelect$1 as Select, Skeleton, Slider, Space, DefaultSpeedDial as SpeedDial, Split, SplitButton, Statistic, DefaultSteps as Steps, Sticky, StrengthIndicator, Switch, Table, DefaultTabs as Tabs, DefaultTag as Tag, Textarea, type ThemeMode, TimePicker, DefaultTimeline as Timeline, Tooltip, Transfer, Transition, Tree, DefaultTypo as Typography, Upload, en_US, useLocale, useTheme, withLocale, withSpin, zh_CN };
89
+ export { Alert, DefaultAnchor as Anchor, AspectRatio, AutoComplete, DefaultAvatar as Avatar, BackTop, Badge, DefaultBreadcrumb as Breadcrumb, DefaultButton as Button, Calendar, DefaultCard as Card, DefaultCarousel as Carousel, Cascader, DefaultCheckbox as Checkbox, Col, DefaultCollapse as Collapse, ColorPicker, ConfigProvider, CopyToClipboard, Countdown, DatePicker, DefaultDesc as Descriptions, Divider, Drawer, Dropdown, Empty, Flex, DefaultFlip as Flip, DefaultForm as Form, Image, DefaultInput as Input, InputNumber, InputOTP, InputPassword, IntlProvider, Keyboard, DefaultLayout as Layout, Link, DefaultList as List, Loader, _default as LoadingBar, type Locale, DefaultMenu as Menu, messageContainer as Message, ModalWithContext as Modal, DefaultSelect as NativeSelect, notificationContainer as Notification, Overlay, Pagination, PopConfirm, Popover, Progress, DefaultRadio as Radio, Rate, Result, Row, ScrollIndicator, Segmented, DefaultSelect$1 as Select, Skeleton, Slider, Space, DefaultSpeedDial as SpeedDial, Split, SplitButton, Statistic, DefaultSteps as Steps, Sticky, StrengthIndicator, Switch, Table, DefaultTabs as Tabs, DefaultTag as Tag, Textarea, type ThemeMode, TimePicker, DefaultTimeline as Timeline, Tooltip, Transfer, Transition, Tree, DefaultTypo as Typography, Upload, en_US, useLocale, useTheme, withLocale, withSpin, zh_CN };
package/lib/index.js CHANGED
@@ -38,50 +38,51 @@ const require_index$31 = require("./form/index.js");
38
38
  const require_index$32 = require("./image/index.js");
39
39
  const require_index$33 = require("./input/index.js");
40
40
  const require_index$34 = require("./input-number/index.js");
41
- const require_index$35 = require("./input-password/index.js");
42
- const require_index$36 = require("./keyboard/index.js");
43
- const require_index$37 = require("./layout/index.js");
44
- const require_index$38 = require("./link/index.js");
45
- const require_index$39 = require("./pagination/index.js");
46
- const require_index$40 = require("./list/index.js");
47
- const require_index$41 = require("./loader/index.js");
48
- const require_index$42 = require("./loading-bar/index.js");
49
- const require_index$43 = require("./menu/index.js");
50
- const require_index$44 = require("./message/index.js");
51
- const require_index$45 = require("./native-select/index.js");
52
- const require_index$46 = require("./row/index.js");
53
- const require_index$47 = require("./modal/index.js");
54
- const require_index$48 = require("./notification/index.js");
55
- const require_index$49 = require("./popover/index.js");
56
- const require_index$50 = require("./pop-confirm/index.js");
57
- const require_index$51 = require("./progress/index.js");
58
- const require_index$52 = require("./radio/index.js");
59
- const require_index$53 = require("./rate/index.js");
60
- const require_index$54 = require("./result/index.js");
61
- const require_index$55 = require("./scroll-indicator/index.js");
62
- const require_index$56 = require("./segmented/index.js");
63
- const require_index$57 = require("./select/index.js");
64
- const require_index$58 = require("./skeleton/index.js");
65
- const require_index$59 = require("./tooltip/index.js");
66
- const require_index$60 = require("./slider/index.js");
67
- const require_index$61 = require("./split/index.js");
68
- const require_index$62 = require("./split-button/index.js");
69
- const require_index$63 = require("./space/index.js");
70
- const require_index$64 = require("./speed-dial/index.js");
71
- const require_index$65 = require("./steps/index.js");
72
- const require_index$66 = require("./statistic/index.js");
73
- const require_index$67 = require("./strength-indicator/index.js");
74
- const require_index$68 = require("./switch/index.js");
75
- const require_index$69 = require("./table/index.js");
76
- const require_index$70 = require("./tabs/index.js");
77
- const require_index$71 = require("./tag/index.js");
78
- const require_index$72 = require("./textarea/index.js");
79
- const require_index$73 = require("./timeline/index.js");
80
- const require_index$74 = require("./time-picker/index.js");
81
- const require_index$75 = require("./transfer/index.js");
82
- const require_index$76 = require("./tree/index.js");
83
- const require_index$77 = require("./typography/index.js");
84
- const require_index$78 = require("./upload/index.js");
41
+ const require_index$35 = require("./input-otp/index.js");
42
+ const require_index$36 = require("./input-password/index.js");
43
+ const require_index$37 = require("./keyboard/index.js");
44
+ const require_index$38 = require("./layout/index.js");
45
+ const require_index$39 = require("./link/index.js");
46
+ const require_index$40 = require("./pagination/index.js");
47
+ const require_index$41 = require("./list/index.js");
48
+ const require_index$42 = require("./loader/index.js");
49
+ const require_index$43 = require("./loading-bar/index.js");
50
+ const require_index$44 = require("./menu/index.js");
51
+ const require_index$45 = require("./message/index.js");
52
+ const require_index$46 = require("./native-select/index.js");
53
+ const require_index$47 = require("./row/index.js");
54
+ const require_index$48 = require("./modal/index.js");
55
+ const require_index$49 = require("./notification/index.js");
56
+ const require_index$50 = require("./popover/index.js");
57
+ const require_index$51 = require("./pop-confirm/index.js");
58
+ const require_index$52 = require("./progress/index.js");
59
+ const require_index$53 = require("./radio/index.js");
60
+ const require_index$54 = require("./rate/index.js");
61
+ const require_index$55 = require("./result/index.js");
62
+ const require_index$56 = require("./scroll-indicator/index.js");
63
+ const require_index$57 = require("./segmented/index.js");
64
+ const require_index$58 = require("./select/index.js");
65
+ const require_index$59 = require("./skeleton/index.js");
66
+ const require_index$60 = require("./tooltip/index.js");
67
+ const require_index$61 = require("./slider/index.js");
68
+ const require_index$62 = require("./split/index.js");
69
+ const require_index$63 = require("./split-button/index.js");
70
+ const require_index$64 = require("./space/index.js");
71
+ const require_index$65 = require("./speed-dial/index.js");
72
+ const require_index$66 = require("./steps/index.js");
73
+ const require_index$67 = require("./statistic/index.js");
74
+ const require_index$68 = require("./strength-indicator/index.js");
75
+ const require_index$69 = require("./switch/index.js");
76
+ const require_index$70 = require("./table/index.js");
77
+ const require_index$71 = require("./tabs/index.js");
78
+ const require_index$72 = require("./tag/index.js");
79
+ const require_index$73 = require("./textarea/index.js");
80
+ const require_index$74 = require("./timeline/index.js");
81
+ const require_index$75 = require("./time-picker/index.js");
82
+ const require_index$76 = require("./transfer/index.js");
83
+ const require_index$77 = require("./tree/index.js");
84
+ const require_index$78 = require("./typography/index.js");
85
+ const require_index$79 = require("./upload/index.js");
85
86
  const require_with_locale = require("./intl-provider/with-locale.js");
86
87
  const require_with_spin = require("./with-spin/with-spin.js");
87
88
  const require_zh_CN = require("./locale/zh_CN.js");
@@ -118,54 +119,55 @@ exports.Form = require_index$31;
118
119
  exports.Image = require_index$32;
119
120
  exports.Input = require_index$33;
120
121
  exports.InputNumber = require_index$34;
121
- exports.InputPassword = require_index$35;
122
+ exports.InputOTP = require_index$35;
123
+ exports.InputPassword = require_index$36;
122
124
  exports.IntlProvider = require_index$15;
123
- exports.Keyboard = require_index$36;
124
- exports.Layout = require_index$37;
125
- exports.Link = require_index$38;
126
- exports.List = require_index$40;
127
- exports.Loader = require_index$41;
128
- exports.LoadingBar = require_index$42;
129
- exports.Menu = require_index$43;
130
- exports.Message = require_index$44;
131
- exports.Modal = require_index$47;
132
- exports.NativeSelect = require_index$45;
133
- exports.Notification = require_index$48;
125
+ exports.Keyboard = require_index$37;
126
+ exports.Layout = require_index$38;
127
+ exports.Link = require_index$39;
128
+ exports.List = require_index$41;
129
+ exports.Loader = require_index$42;
130
+ exports.LoadingBar = require_index$43;
131
+ exports.Menu = require_index$44;
132
+ exports.Message = require_index$45;
133
+ exports.Modal = require_index$48;
134
+ exports.NativeSelect = require_index$46;
135
+ exports.Notification = require_index$49;
134
136
  exports.Overlay = require_index$26;
135
- exports.Pagination = require_index$39;
136
- exports.PopConfirm = require_index$50;
137
- exports.Popover = require_index$49;
138
- exports.Progress = require_index$51;
139
- exports.Radio = require_index$52;
140
- exports.Rate = require_index$53;
141
- exports.Result = require_index$54;
142
- exports.Row = require_index$46;
143
- exports.ScrollIndicator = require_index$55;
144
- exports.Segmented = require_index$56;
145
- exports.Select = require_index$57;
146
- exports.Skeleton = require_index$58;
147
- exports.Slider = require_index$60;
148
- exports.Space = require_index$63;
149
- exports.SpeedDial = require_index$64;
150
- exports.Split = require_index$61;
151
- exports.SplitButton = require_index$62;
152
- exports.Statistic = require_index$66;
153
- exports.Steps = require_index$65;
137
+ exports.Pagination = require_index$40;
138
+ exports.PopConfirm = require_index$51;
139
+ exports.Popover = require_index$50;
140
+ exports.Progress = require_index$52;
141
+ exports.Radio = require_index$53;
142
+ exports.Rate = require_index$54;
143
+ exports.Result = require_index$55;
144
+ exports.Row = require_index$47;
145
+ exports.ScrollIndicator = require_index$56;
146
+ exports.Segmented = require_index$57;
147
+ exports.Select = require_index$58;
148
+ exports.Skeleton = require_index$59;
149
+ exports.Slider = require_index$61;
150
+ exports.Space = require_index$64;
151
+ exports.SpeedDial = require_index$65;
152
+ exports.Split = require_index$62;
153
+ exports.SplitButton = require_index$63;
154
+ exports.Statistic = require_index$67;
155
+ exports.Steps = require_index$66;
154
156
  exports.Sticky = require_index$2;
155
- exports.StrengthIndicator = require_index$67;
156
- exports.Switch = require_index$68;
157
- exports.Table = require_index$69;
158
- exports.Tabs = require_index$70;
159
- exports.Tag = require_index$71;
160
- exports.Textarea = require_index$72;
161
- exports.TimePicker = require_index$74;
162
- exports.Timeline = require_index$73;
163
- exports.Tooltip = require_index$59;
164
- exports.Transfer = require_index$75;
157
+ exports.StrengthIndicator = require_index$68;
158
+ exports.Switch = require_index$69;
159
+ exports.Table = require_index$70;
160
+ exports.Tabs = require_index$71;
161
+ exports.Tag = require_index$72;
162
+ exports.Textarea = require_index$73;
163
+ exports.TimePicker = require_index$75;
164
+ exports.Timeline = require_index$74;
165
+ exports.Tooltip = require_index$60;
166
+ exports.Transfer = require_index$76;
165
167
  exports.Transition = require_index;
166
- exports.Tree = require_index$76;
167
- exports.Typography = require_index$77;
168
- exports.Upload = require_index$78;
168
+ exports.Tree = require_index$77;
169
+ exports.Typography = require_index$78;
170
+ exports.Upload = require_index$79;
169
171
  exports.en_US = require_en_US;
170
172
  exports.useLocale = require_use_locale.useLocale;
171
173
  exports.useTheme = require_use_theme.useTheme;
@@ -17,11 +17,15 @@ const InputGroupAddon = (props) => {
17
17
  className: cls,
18
18
  style,
19
19
  children: react.default.Children.map(children, (child) => {
20
- const childProps = {
21
- disabled,
22
- size: inputSize
23
- };
24
- return react.default.cloneElement(child, childProps);
20
+ const displayName = child.type?.displayName;
21
+ if (displayName === "Input" || displayName === "Button" || displayName === "Select") {
22
+ const childProps = {
23
+ disabled,
24
+ size: inputSize
25
+ };
26
+ return react.default.cloneElement(child, childProps);
27
+ }
28
+ return child;
25
29
  })
26
30
  });
27
31
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"input-group-addon.js","names":["ConfigContext","getPrefixCls","React"],"sources":["../../src/input/input-group-addon.tsx"],"sourcesContent":["import React, { useContext } from 'react';\nimport classNames from 'classnames';\nimport { ConfigContext } from '../config-provider/config-context';\nimport { getPrefixCls } from '../_utils/general';\nimport { InputGroupAddonProps, InputProps } from './types';\nimport { SizeType } from '../_utils/props';\n\nconst InputGroupAddon = (props: InputGroupAddonProps): React.ReactElement => {\n const {\n disabled = false,\n size = 'md',\n noBorder,\n className,\n style,\n children,\n prefixCls: customisedCls,\n ...otherProps\n } = props;\n const configContext = useContext(ConfigContext);\n const prefixCls = getPrefixCls('input-group-addon', configContext.prefixCls, customisedCls);\n const inputSize = props.size || configContext.componentSize || size;\n const cls = classNames(prefixCls, className, `${prefixCls}_${inputSize}`, {\n [`${prefixCls}_no-border`]: noBorder,\n });\n\n if (React.isValidElement(children)) {\n return (\n <div className={cls} style={style}>\n {React.Children.map(children, (child: React.ReactElement) => {\n const childProps: Partial<InputProps> = {\n disabled,\n size: inputSize as SizeType,\n };\n return React.cloneElement(child, childProps);\n })}\n </div>\n );\n }\n return (\n <div {...otherProps} className={cls} style={style}>\n {children}\n </div>\n );\n};\n\nInputGroupAddon.displayName = 'InputGroupAddon';\n\nexport default InputGroupAddon;\n"],"mappings":";;;;;;;;;AAOA,MAAM,mBAAmB,UAAoD;CAC3E,MAAM,EACJ,WAAW,OACX,OAAO,MACP,UACA,WACA,OACA,UACA,WAAW,eACX,GAAG,eACD;CACJ,MAAM,iBAAA,GAAA,MAAA,YAA2BA,uBAAAA,cAAc;CAC/C,MAAM,YAAYC,gBAAAA,aAAa,qBAAqB,cAAc,WAAW,cAAc;CAC3F,MAAM,YAAY,MAAM,QAAQ,cAAc,iBAAiB;CAC/D,MAAM,OAAA,GAAA,WAAA,SAAiB,WAAW,WAAW,GAAG,UAAU,GAAG,aAAa,GACvE,GAAG,UAAU,cAAc,UAC7B,CAAC;AAEF,KAAIC,MAAAA,QAAM,eAAe,SAAS,CAChC,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,WAAW;EAAY;YACzBA,MAAAA,QAAM,SAAS,IAAI,WAAW,UAA8B;GAC3D,MAAM,aAAkC;IACtC;IACA,MAAM;IACP;AACD,UAAOA,MAAAA,QAAM,aAAa,OAAO,WAAW;IAC5C;EACE,CAAA;AAGV,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,GAAI;EAAY,WAAW;EAAY;EACzC;EACG,CAAA;;AAIV,gBAAgB,cAAc"}
1
+ {"version":3,"file":"input-group-addon.js","names":["ConfigContext","getPrefixCls","React"],"sources":["../../src/input/input-group-addon.tsx"],"sourcesContent":["import React, { useContext } from 'react';\nimport classNames from 'classnames';\nimport { ConfigContext } from '../config-provider/config-context';\nimport { getPrefixCls } from '../_utils/general';\nimport { InputGroupAddonProps, InputProps } from './types';\nimport { SizeType } from '../_utils/props';\n\nconst InputGroupAddon = (props: InputGroupAddonProps): React.ReactElement => {\n const {\n disabled = false,\n size = 'md',\n noBorder,\n className,\n style,\n children,\n prefixCls: customisedCls,\n ...otherProps\n } = props;\n const configContext = useContext(ConfigContext);\n const prefixCls = getPrefixCls('input-group-addon', configContext.prefixCls, customisedCls);\n const inputSize = props.size || configContext.componentSize || size;\n const cls = classNames(prefixCls, className, `${prefixCls}_${inputSize}`, {\n [`${prefixCls}_no-border`]: noBorder,\n });\n\n if (React.isValidElement(children)) {\n return (\n <div className={cls} style={style}>\n {React.Children.map(children, (child: React.ReactElement) => {\n const displayName = (child.type as any)?.displayName;\n if (displayName === 'Input' || displayName === 'Button' || displayName === 'Select') {\n const childProps: Partial<InputProps> = {\n disabled,\n size: inputSize as SizeType,\n };\n return React.cloneElement(child, childProps);\n }\n return child;\n })}\n </div>\n );\n }\n return (\n <div {...otherProps} className={cls} style={style}>\n {children}\n </div>\n );\n};\n\nInputGroupAddon.displayName = 'InputGroupAddon';\n\nexport default InputGroupAddon;\n"],"mappings":";;;;;;;;;AAOA,MAAM,mBAAmB,UAAoD;CAC3E,MAAM,EACJ,WAAW,OACX,OAAO,MACP,UACA,WACA,OACA,UACA,WAAW,eACX,GAAG,eACD;CACJ,MAAM,iBAAA,GAAA,MAAA,YAA2BA,uBAAAA,cAAc;CAC/C,MAAM,YAAYC,gBAAAA,aAAa,qBAAqB,cAAc,WAAW,cAAc;CAC3F,MAAM,YAAY,MAAM,QAAQ,cAAc,iBAAiB;CAC/D,MAAM,OAAA,GAAA,WAAA,SAAiB,WAAW,WAAW,GAAG,UAAU,GAAG,aAAa,GACvE,GAAG,UAAU,cAAc,UAC7B,CAAC;AAEF,KAAIC,MAAAA,QAAM,eAAe,SAAS,CAChC,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,WAAW;EAAY;YACzBA,MAAAA,QAAM,SAAS,IAAI,WAAW,UAA8B;GAC3D,MAAM,cAAe,MAAM,MAAc;AACzC,OAAI,gBAAgB,WAAW,gBAAgB,YAAY,gBAAgB,UAAU;IACnF,MAAM,aAAkC;KACtC;KACA,MAAM;KACP;AACD,WAAOA,MAAAA,QAAM,aAAa,OAAO,WAAW;;AAE9C,UAAO;IACP;EACE,CAAA;AAGV,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,GAAI;EAAY,WAAW;EAAY;EACzC;EACG,CAAA;;AAIV,gBAAgB,cAAc"}
@@ -0,0 +1,8 @@
1
+ require('../style/base.css');
2
+ require('./style/index.css');
3
+ //#region src/input-otp/index.tsx
4
+ var input_otp_default = require("./input-otp.js").default;
5
+ //#endregion
6
+ exports.default = input_otp_default;
7
+
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["InputOTP"],"sources":["../../src/input-otp/index.tsx"],"sourcesContent":["import InputOTP from './input-otp';\n\nexport default InputOTP;\n"],"mappings":";AAEA,IAAA,8CAAeA"}
@@ -0,0 +1,13 @@
1
+ import { InputOTPProps } from "./types.js";
2
+ import React from "react";
3
+
4
+ //#region src/input-otp/input-otp.d.ts
5
+ interface InputOTPRef {
6
+ focus: () => void;
7
+ blur: () => void;
8
+ nativeElement: HTMLDivElement | null;
9
+ }
10
+ declare const InputOTP: React.ForwardRefExoticComponent<InputOTPProps & React.RefAttributes<InputOTPRef>>;
11
+ //#endregion
12
+ export { InputOTP };
13
+ //# sourceMappingURL=input-otp.d.ts.map
@@ -0,0 +1,131 @@
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.js");
2
+ const require_config_context = require("../config-provider/config-context.js");
3
+ const require_general = require("../_utils/general.js");
4
+ const require_otp_input = require("./otp-input.js");
5
+ let react = require("react");
6
+ react = require_runtime.__toESM(react);
7
+ let classnames = require("classnames");
8
+ classnames = require_runtime.__toESM(classnames);
9
+ let react_jsx_runtime = require("react/jsx-runtime");
10
+ //#region src/input-otp/input-otp.tsx
11
+ function strToArr(str) {
12
+ return (str || "").split("");
13
+ }
14
+ const InputOTP = react.default.forwardRef((props, ref) => {
15
+ const { length = 6, size = "md", defaultValue, value, onChange, formatter, separator, disabled = false, mask, autoFocus, autoComplete, className, style, prefixCls: customisedCls, onFocus, ...otherProps } = props;
16
+ const configContext = (0, react.useContext)(require_config_context.ConfigContext);
17
+ const prefixCls = require_general.getPrefixCls("input-otp", configContext.prefixCls, customisedCls);
18
+ const inputSize = size || configContext.componentSize || "md";
19
+ const containerRef = (0, react.useRef)(null);
20
+ const inputsRef = (0, react.useRef)({});
21
+ const internalFormatter = (0, react.useCallback)((txt) => formatter ? formatter(txt) : txt, [formatter]);
22
+ const [valueCells, setValueCells] = (0, react.useState)(() => strToArr(internalFormatter(defaultValue || "")));
23
+ (0, react.useEffect)(() => {
24
+ if (value !== void 0) setValueCells(strToArr(value));
25
+ }, [value]);
26
+ react.default.useImperativeHandle(ref, () => ({
27
+ focus: () => {
28
+ let nextIndex = 0;
29
+ for (let i = 0; i < length; i += 1) {
30
+ if (!inputsRef.current[i]?.value) {
31
+ nextIndex = i;
32
+ break;
33
+ }
34
+ nextIndex = i;
35
+ }
36
+ inputsRef.current[nextIndex]?.focus();
37
+ },
38
+ blur: () => {
39
+ for (let i = 0; i < length; i += 1) inputsRef.current[i]?.blur();
40
+ },
41
+ nativeElement: containerRef.current
42
+ }));
43
+ const triggerValueCellsChange = (0, react.useCallback)((nextValueCells) => {
44
+ setValueCells((prev) => {
45
+ const prevValue = prev.join("");
46
+ const nextValue = nextValueCells.join("");
47
+ if (onChange && prevValue !== nextValue) onChange(nextValue);
48
+ return nextValueCells;
49
+ });
50
+ }, [onChange]);
51
+ const patchValue = (0, react.useCallback)((index, txt) => {
52
+ let nextCells = [...valueCells];
53
+ for (let i = 0; i < index; i += 1) if (!nextCells[i]) nextCells[i] = "";
54
+ if (txt.length <= 1) nextCells[index] = txt;
55
+ else nextCells = nextCells.slice(0, index).concat(strToArr(txt));
56
+ nextCells = nextCells.slice(0, length);
57
+ for (let i = nextCells.length - 1; i >= 0; i -= 1) {
58
+ if (nextCells[i]) break;
59
+ nextCells.pop();
60
+ }
61
+ nextCells = strToArr(internalFormatter(nextCells.map((c) => c || " ").join(""))).map((c, i) => {
62
+ if (c === " " && !nextCells[i]) return nextCells[i];
63
+ return c;
64
+ });
65
+ return nextCells;
66
+ }, [
67
+ valueCells,
68
+ length,
69
+ internalFormatter
70
+ ]);
71
+ const onInputChange = (0, react.useCallback)((index, txt) => {
72
+ const nextCells = patchValue(index, txt);
73
+ const nextIndex = Math.min(index + txt.length, length - 1);
74
+ if (nextIndex !== index && nextCells[index] !== void 0) inputsRef.current[nextIndex]?.focus();
75
+ triggerValueCellsChange(nextCells);
76
+ }, [
77
+ patchValue,
78
+ length,
79
+ triggerValueCellsChange
80
+ ]);
81
+ const onInputActiveChange = (0, react.useCallback)((nextIndex) => {
82
+ const clampedIndex = Math.max(0, Math.min(nextIndex, length - 1));
83
+ inputsRef.current[clampedIndex]?.focus();
84
+ }, [length]);
85
+ const onInputFocus = (0, react.useCallback)((event, index) => {
86
+ if (onFocus) onFocus(event);
87
+ }, [onFocus]);
88
+ const renderSeparator = (0, react.useMemo)(() => {
89
+ if (!separator) return null;
90
+ return (index) => {
91
+ const separatorNode = typeof separator === "function" ? separator(index) : separator;
92
+ if (!separatorNode) return null;
93
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
94
+ className: `${prefixCls}__separator`,
95
+ children: separatorNode
96
+ });
97
+ };
98
+ }, [separator, prefixCls]);
99
+ const cls = (0, classnames.default)(prefixCls, className, `${prefixCls}_${inputSize}`, { [`${prefixCls}_disabled`]: disabled });
100
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
101
+ ...otherProps,
102
+ ref: containerRef,
103
+ className: cls,
104
+ style,
105
+ role: "group",
106
+ children: Array.from({ length }).map((_, index) => {
107
+ const singleValue = valueCells[index] || "";
108
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.default.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_otp_input.default, {
109
+ ref: (el) => {
110
+ inputsRef.current[index] = el;
111
+ },
112
+ index,
113
+ size: inputSize,
114
+ prefixCls,
115
+ value: singleValue,
116
+ disabled,
117
+ mask,
118
+ autoFocus: index === 0 && autoFocus,
119
+ autoComplete,
120
+ onChange: onInputChange,
121
+ onActiveChange: onInputActiveChange,
122
+ onFocus: (e) => onInputFocus(e, index)
123
+ }), index < length - 1 && renderSeparator?.(index)] }, `otp-${index}`);
124
+ })
125
+ });
126
+ });
127
+ InputOTP.displayName = "InputOTP";
128
+ //#endregion
129
+ exports.default = InputOTP;
130
+
131
+ //# sourceMappingURL=input-otp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-otp.js","names":["React","ConfigContext","getPrefixCls","OTPInput"],"sources":["../../src/input-otp/input-otp.tsx"],"sourcesContent":["import React, { useRef, useState, useEffect, useContext, useCallback, useMemo } from 'react';\nimport classNames from 'classnames';\nimport { ConfigContext } from '../config-provider/config-context';\nimport { getPrefixCls } from '../_utils/general';\nimport { InputOTPProps } from './types';\nimport OTPInput from './otp-input';\n\nfunction strToArr(str: string): string[] {\n return (str || '').split('');\n}\n\nexport interface InputOTPRef {\n focus: () => void;\n blur: () => void;\n nativeElement: HTMLDivElement | null;\n}\n\nconst InputOTP = React.forwardRef<InputOTPRef, InputOTPProps>(\n (props, ref) => {\n const {\n length = 6,\n size = 'md',\n defaultValue,\n value,\n onChange,\n formatter,\n separator,\n disabled = false,\n mask,\n autoFocus,\n autoComplete,\n className,\n style,\n prefixCls: customisedCls,\n onFocus,\n ...otherProps\n } = props;\n\n const configContext = useContext(ConfigContext);\n const prefixCls = getPrefixCls('input-otp', configContext.prefixCls, customisedCls);\n const inputSize = size || configContext.componentSize || 'md';\n\n const containerRef = useRef<HTMLDivElement>(null);\n const inputsRef = useRef<Record<number, HTMLInputElement | null>>({});\n\n // Formatter helper\n const internalFormatter = useCallback(\n (txt: string) => (formatter ? formatter(txt) : txt),\n [formatter]\n );\n\n // Value state\n const [valueCells, setValueCells] = useState<string[]>(() =>\n strToArr(internalFormatter(defaultValue || ''))\n );\n\n useEffect(() => {\n if (value !== undefined) {\n setValueCells(strToArr(value));\n }\n }, [value]);\n\n // Imperative handle\n React.useImperativeHandle(ref, () => ({\n focus: () => {\n // Focus first empty cell (or last cell if all filled)\n let nextIndex = 0;\n for (let i = 0; i < length; i += 1) {\n if (!inputsRef.current[i]?.value) {\n nextIndex = i;\n break;\n }\n nextIndex = i;\n }\n inputsRef.current[nextIndex]?.focus();\n },\n blur: () => {\n for (let i = 0; i < length; i += 1) {\n inputsRef.current[i]?.blur();\n }\n },\n nativeElement: containerRef.current,\n }));\n\n // Trigger onChange when value cells change\n const triggerValueCellsChange = useCallback(\n (nextValueCells: string[]) => {\n setValueCells((prev) => {\n const prevValue = prev.join('');\n const nextValue = nextValueCells.join('');\n if (onChange && prevValue !== nextValue) {\n onChange(nextValue);\n }\n return nextValueCells;\n });\n },\n [onChange]\n );\n\n // Patch value at given index\n const patchValue = useCallback(\n (index: number, txt: string) => {\n let nextCells = [...valueCells];\n\n // Fill cells till index\n for (let i = 0; i < index; i += 1) {\n if (!nextCells[i]) {\n nextCells[i] = '';\n }\n }\n\n if (txt.length <= 1) {\n nextCells[index] = txt;\n } else {\n nextCells = nextCells.slice(0, index).concat(strToArr(txt));\n }\n nextCells = nextCells.slice(0, length);\n\n // Clean trailing empty cells\n for (let i = nextCells.length - 1; i >= 0; i -= 1) {\n if (nextCells[i]) {\n break;\n }\n nextCells.pop();\n }\n\n // Format if needed\n const formattedValue = internalFormatter(\n nextCells.map((c) => c || ' ').join('')\n );\n nextCells = strToArr(formattedValue).map((c, i) => {\n if (c === ' ' && !nextCells[i]) {\n return nextCells[i];\n }\n return c;\n });\n\n return nextCells;\n },\n [valueCells, length, internalFormatter]\n );\n\n // Handle input change\n const onInputChange = useCallback(\n (index: number, txt: string) => {\n const nextCells = patchValue(index, txt);\n const nextIndex = Math.min(index + txt.length, length - 1);\n if (nextIndex !== index && nextCells[index] !== undefined) {\n inputsRef.current[nextIndex]?.focus();\n }\n triggerValueCellsChange(nextCells);\n },\n [patchValue, length, triggerValueCellsChange]\n );\n\n // Handle active change (arrow keys, backspace)\n const onInputActiveChange = useCallback(\n (nextIndex: number) => {\n const clampedIndex = Math.max(0, Math.min(nextIndex, length - 1));\n inputsRef.current[clampedIndex]?.focus();\n },\n [length]\n );\n\n // Handle focus — keep focus on the interacted cell\n const onInputFocus = useCallback(\n (event: React.FocusEvent<HTMLInputElement>, index: number) => {\n if (onFocus) {\n (onFocus as React.FocusEventHandler<HTMLDivElement>)(event as unknown as React.FocusEvent<HTMLDivElement>);\n }\n },\n [onFocus]\n );\n\n // Render separator\n const renderSeparator = useMemo(() => {\n if (!separator) return null;\n return (index: number) => {\n const separatorNode =\n typeof separator === 'function' ? separator(index) : separator;\n if (!separatorNode) return null;\n return (\n <span className={`${prefixCls}__separator`}>\n {separatorNode}\n </span>\n );\n };\n }, [separator, prefixCls]);\n\n const cls = classNames(prefixCls, className, `${prefixCls}_${inputSize}`, {\n [`${prefixCls}_disabled`]: disabled,\n });\n\n return (\n <div\n {...otherProps}\n ref={containerRef}\n className={cls}\n style={style}\n role=\"group\"\n >\n {Array.from({ length }).map((_, index) => {\n const singleValue = valueCells[index] || '';\n return (\n <React.Fragment key={`otp-${index}`}>\n <OTPInput\n ref={(el) => {\n inputsRef.current[index] = el;\n }}\n index={index}\n size={inputSize}\n prefixCls={prefixCls}\n value={singleValue}\n disabled={disabled}\n mask={mask}\n autoFocus={index === 0 && autoFocus}\n autoComplete={autoComplete}\n onChange={onInputChange}\n onActiveChange={onInputActiveChange}\n onFocus={(e) => onInputFocus(e, index)}\n />\n {index < length - 1 && renderSeparator?.(index)}\n </React.Fragment>\n );\n })}\n </div>\n );\n }\n);\n\nInputOTP.displayName = 'InputOTP';\n\nexport default InputOTP;\n"],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.js");
2
+ let react = require("react");
3
+ react = require_runtime.__toESM(react);
4
+ let classnames = require("classnames");
5
+ classnames = require_runtime.__toESM(classnames);
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+ //#region src/input-otp/otp-input.tsx
8
+ const OTPInput = react.default.forwardRef((props, ref) => {
9
+ const { index, value, disabled, mask, size = "md", autoFocus, autoComplete, prefixCls, onChange, onActiveChange, onFocus } = props;
10
+ const inputRef = (0, react.useRef)(null);
11
+ const setRef = (0, react.useCallback)((el) => {
12
+ inputRef.current = el;
13
+ if (typeof ref === "function") ref(el);
14
+ else if (ref) ref.current = el;
15
+ }, [ref]);
16
+ const syncSelection = (0, react.useCallback)(() => {
17
+ requestAnimationFrame(() => {
18
+ const inputEle = inputRef.current;
19
+ if (document.activeElement === inputEle && inputEle) inputEle.select();
20
+ });
21
+ }, []);
22
+ const onInternalInput = (e) => {
23
+ onChange(index, e.target.value);
24
+ };
25
+ const onInternalFocus = (e) => {
26
+ onFocus?.(e);
27
+ syncSelection();
28
+ };
29
+ const onInternalKeyDown = (event) => {
30
+ const { key, ctrlKey, metaKey } = event;
31
+ if (key === "ArrowLeft") onActiveChange(index - 1);
32
+ else if (key === "ArrowRight") onActiveChange(index + 1);
33
+ else if (key === "z" && (ctrlKey || metaKey)) event.preventDefault();
34
+ else if (key === "Backspace" && !value) onActiveChange(index - 1);
35
+ syncSelection();
36
+ };
37
+ const displayValue = mask && typeof mask === "string" && value ? mask : value;
38
+ const inputType = mask === true ? "password" : "text";
39
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
40
+ ref: setRef,
41
+ "aria-label": `OTP Input ${index + 1}`,
42
+ type: inputType,
43
+ inputMode: "numeric",
44
+ autoComplete: autoComplete || "one-time-code",
45
+ className: (0, classnames.default)(`${prefixCls}__cell`, `${prefixCls}__cell_${size}`, {
46
+ [`${prefixCls}__cell_disabled`]: disabled,
47
+ [`${prefixCls}__cell_mask`]: mask
48
+ }),
49
+ value: displayValue,
50
+ disabled,
51
+ autoFocus,
52
+ onInput: onInternalInput,
53
+ onFocus: onInternalFocus,
54
+ onKeyDown: onInternalKeyDown,
55
+ onMouseDown: syncSelection,
56
+ onMouseUp: syncSelection
57
+ });
58
+ });
59
+ OTPInput.displayName = "OTPInput";
60
+ //#endregion
61
+ exports.default = OTPInput;
62
+
63
+ //# sourceMappingURL=otp-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otp-input.js","names":["React"],"sources":["../../src/input-otp/otp-input.tsx"],"sourcesContent":["import React, { useRef, useCallback } from 'react';\nimport classNames from 'classnames';\nimport { OTPInputCellProps } from './types';\n\nconst OTPInput = React.forwardRef<HTMLInputElement, OTPInputCellProps>(\n (props, ref) => {\n const {\n index,\n value,\n disabled,\n mask,\n size = 'md',\n autoFocus,\n autoComplete,\n prefixCls,\n onChange,\n onActiveChange,\n onFocus,\n } = props;\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Merge refs\n const setRef = useCallback(\n (el: HTMLInputElement | null) => {\n inputRef.current = el;\n if (typeof ref === 'function') {\n ref(el);\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLInputElement | null>).current = el;\n }\n },\n [ref]\n );\n\n const syncSelection = useCallback(() => {\n requestAnimationFrame(() => {\n const inputEle = inputRef.current;\n if (document.activeElement === inputEle && inputEle) {\n inputEle.select();\n }\n });\n }, []);\n\n const onInternalInput = (e: React.FormEvent<HTMLInputElement>): void => {\n onChange(index, (e.target as HTMLInputElement).value);\n };\n\n const onInternalFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {\n onFocus?.(e);\n syncSelection();\n };\n\n const onInternalKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {\n const { key, ctrlKey, metaKey } = event;\n\n if (key === 'ArrowLeft') {\n onActiveChange(index - 1);\n } else if (key === 'ArrowRight') {\n onActiveChange(index + 1);\n } else if (key === 'z' && (ctrlKey || metaKey)) {\n event.preventDefault();\n } else if (key === 'Backspace' && !value) {\n onActiveChange(index - 1);\n }\n\n syncSelection();\n };\n\n const displayValue = mask && typeof mask === 'string' && value ? mask : value;\n const inputType = mask === true ? 'password' : 'text';\n\n return (\n <input\n ref={setRef}\n aria-label={`OTP Input ${index + 1}`}\n type={inputType}\n inputMode=\"numeric\"\n autoComplete={autoComplete || 'one-time-code'}\n className={classNames(`${prefixCls}__cell`, `${prefixCls}__cell_${size}`, {\n [`${prefixCls}__cell_disabled`]: disabled,\n [`${prefixCls}__cell_mask`]: mask,\n })}\n value={displayValue}\n disabled={disabled}\n autoFocus={autoFocus}\n onInput={onInternalInput}\n onFocus={onInternalFocus}\n onKeyDown={onInternalKeyDown}\n onMouseDown={syncSelection}\n onMouseUp={syncSelection}\n />\n );\n }\n);\n\nOTPInput.displayName = 'OTPInput';\n\nexport default OTPInput;\n"],"mappings":";;;;;;;AAIA,MAAM,WAAWA,MAAAA,QAAM,YACpB,OAAO,QAAQ;CACd,MAAM,EACJ,OACA,OACA,UACA,MACA,OAAO,MACP,WACA,cACA,WACA,UACA,gBACA,YACE;CAEJ,MAAM,YAAA,GAAA,MAAA,QAA2C,KAAK;CAGtD,MAAM,UAAA,GAAA,MAAA,cACH,OAAgC;AAC/B,WAAS,UAAU;AACnB,MAAI,OAAO,QAAQ,WACjB,KAAI,GAAG;WACE,IACR,KAAwD,UAAU;IAGvE,CAAC,IAAI,CACN;CAED,MAAM,iBAAA,GAAA,MAAA,mBAAkC;AACtC,8BAA4B;GAC1B,MAAM,WAAW,SAAS;AAC1B,OAAI,SAAS,kBAAkB,YAAY,SACzC,UAAS,QAAQ;IAEnB;IACD,EAAE,CAAC;CAEN,MAAM,mBAAmB,MAA+C;AACtE,WAAS,OAAQ,EAAE,OAA4B,MAAM;;CAGvD,MAAM,mBAA8D,MAAM;AACxE,YAAU,EAAE;AACZ,iBAAe;;CAGjB,MAAM,qBAAmE,UAAU;EACjF,MAAM,EAAE,KAAK,SAAS,YAAY;AAElC,MAAI,QAAQ,YACV,gBAAe,QAAQ,EAAE;WAChB,QAAQ,aACjB,gBAAe,QAAQ,EAAE;WAChB,QAAQ,QAAQ,WAAW,SACpC,OAAM,gBAAgB;WACb,QAAQ,eAAe,CAAC,MACjC,gBAAe,QAAQ,EAAE;AAG3B,iBAAe;;CAGjB,MAAM,eAAe,QAAQ,OAAO,SAAS,YAAY,QAAQ,OAAO;CACxE,MAAM,YAAY,SAAS,OAAO,aAAa;AAE/C,QACE,iBAAA,GAAA,kBAAA,KAAC,SAAD;EACE,KAAK;EACL,cAAY,aAAa,QAAQ;EACjC,MAAM;EACN,WAAU;EACV,cAAc,gBAAgB;EAC9B,YAAA,GAAA,WAAA,SAAsB,GAAG,UAAU,SAAS,GAAG,UAAU,SAAS,QAAQ;IACvE,GAAG,UAAU,mBAAmB;IAChC,GAAG,UAAU,eAAe;GAC9B,CAAC;EACF,OAAO;EACG;EACC;EACX,SAAS;EACT,SAAS;EACT,WAAW;EACX,aAAa;EACb,WAAW;EACX,CAAA;EAGP;AAED,SAAS,cAAc"}
@@ -0,0 +1,53 @@
1
+ @use '../../style/variables' as *;
2
+ @use '../../input/style/mixin' as *;
3
+
4
+ .#{$prefix}-input-otp {
5
+ display: inline-flex;
6
+ align-items: center;
7
+ gap: 8px;
8
+
9
+ &__cell {
10
+ @include input-default;
11
+
12
+ width: 36px;
13
+ height: 36px;
14
+ text-align: center;
15
+ padding: 0;
16
+ font-size: $input-md-font-size;
17
+ border-radius: $input-border-radius;
18
+ caret-color: currentcolor;
19
+
20
+ &_sm {
21
+ width: 28px;
22
+ height: 28px;
23
+ font-size: $input-sm-font-size;
24
+ }
25
+
26
+ &_md {
27
+ width: 36px;
28
+ height: 36px;
29
+ font-size: $input-md-font-size;
30
+ }
31
+
32
+ &_lg {
33
+ width: 44px;
34
+ height: 44px;
35
+ font-size: $input-lg-font-size;
36
+ }
37
+
38
+ &_disabled {
39
+ @include input-default-disabled;
40
+ }
41
+ }
42
+
43
+ &__separator {
44
+ display: inline-flex;
45
+ align-items: center;
46
+ color: var(--ty-color-text-secondary);
47
+ font-size: $font-size-base;
48
+ }
49
+
50
+ &_disabled {
51
+ cursor: not-allowed;
52
+ }
53
+ }
@@ -0,0 +1,71 @@
1
+ .ty-input-otp {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: 8px;
5
+ }
6
+ .ty-input-otp__cell {
7
+ box-sizing: border-box;
8
+ width: 100%;
9
+ margin: 0;
10
+ color: var(--ty-color-text);
11
+ border: 1px solid var(--ty-input-border);
12
+ transition: all 0.3s;
13
+ outline: 0;
14
+ border-radius: 2px;
15
+ font-size: 1rem;
16
+ background-color: var(--ty-input-bg);
17
+ }
18
+ .ty-input-otp__cell:hover {
19
+ border-color: var(--ty-color-primary);
20
+ }
21
+ .ty-input-otp__cell:focus {
22
+ border-color: var(--ty-input-focus-border);
23
+ box-shadow: var(--ty-input-focus-shadow);
24
+ }
25
+ .ty-input-otp__cell::-moz-placeholder {
26
+ color: var(--ty-color-text-placeholder);
27
+ }
28
+ .ty-input-otp__cell::placeholder {
29
+ color: var(--ty-color-text-placeholder);
30
+ }
31
+ .ty-input-otp__cell {
32
+ width: 36px;
33
+ height: 36px;
34
+ text-align: center;
35
+ padding: 0;
36
+ font-size: 1rem;
37
+ border-radius: 2px;
38
+ caret-color: currentcolor;
39
+ }
40
+ .ty-input-otp__cell_sm {
41
+ width: 28px;
42
+ height: 28px;
43
+ font-size: 0.875rem;
44
+ }
45
+ .ty-input-otp__cell_md {
46
+ width: 36px;
47
+ height: 36px;
48
+ font-size: 1rem;
49
+ }
50
+ .ty-input-otp__cell_lg {
51
+ width: 44px;
52
+ height: 44px;
53
+ font-size: 1.25rem;
54
+ }
55
+ .ty-input-otp__cell_disabled {
56
+ cursor: not-allowed;
57
+ background-color: var(--ty-input-disabled-bg);
58
+ color: var(--ty-input-disabled-color);
59
+ }
60
+ .ty-input-otp__cell_disabled:hover {
61
+ border-color: var(--ty-input-border);
62
+ }
63
+ .ty-input-otp__separator {
64
+ display: inline-flex;
65
+ align-items: center;
66
+ color: var(--ty-color-text-secondary);
67
+ font-size: 1rem;
68
+ }
69
+ .ty-input-otp_disabled {
70
+ cursor: not-allowed;
71
+ }
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ require("./index.css");
@@ -0,0 +1,31 @@
1
+ import { BaseProps, SizeType } from "../_utils/props.js";
2
+ import React from "react";
3
+
4
+ //#region src/input-otp/types.d.ts
5
+ interface InputOTPProps extends BaseProps, Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'onInput'> {
6
+ /** Number of OTP input cells */
7
+ length?: number;
8
+ /** Size of the input */
9
+ size?: SizeType;
10
+ /** Default value of the OTP input */
11
+ defaultValue?: string;
12
+ /** Controlled value of the OTP input */
13
+ value?: string;
14
+ /** Callback when all cells are filled */
15
+ onChange?: (value: string) => void;
16
+ /** Custom formatter to restrict/modify input */
17
+ formatter?: (value: string) => string;
18
+ /** Separator element between cells */
19
+ separator?: ((index: number) => React.ReactNode) | React.ReactNode;
20
+ /** Whether the input is disabled */
21
+ disabled?: boolean;
22
+ /** Whether to mask the values, or a custom mask character */
23
+ mask?: boolean | string;
24
+ /** Auto focus the first cell on mount */
25
+ autoFocus?: boolean;
26
+ /** Autocomplete attribute */
27
+ autoComplete?: string;
28
+ }
29
+ //#endregion
30
+ export { InputOTPProps };
31
+ //# sourceMappingURL=types.d.ts.map
@@ -28,6 +28,7 @@
28
28
  @use "../image/style/index" as *;
29
29
  @use "../input/style/index" as *;
30
30
  @use "../input-number/style/index" as *;
31
+ @use "../input-otp/style/index" as *;
31
32
  @use "../input-password/style/index" as *;
32
33
  @use "../layout/style/index" as *;
33
34
  @use "../link/style/index" as *;
@@ -75,4 +76,4 @@
75
76
  @use "../tree/style/index" as *;
76
77
  @use "../typography/style/index" as *;
77
78
  @use "../upload/style/index" as *;
78
- @use "../with-spin/style/index" as *;
79
+ @use "../with-spin/style/index" as *;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiny-design/react",
3
- "version": "1.0.10",
3
+ "version": "1.1.0",
4
4
  "description": "A friendly UI component set for React",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -55,8 +55,8 @@
55
55
  "classnames": "^2.3.1",
56
56
  "react-transition-group": "^4.4.2",
57
57
  "tslib": "^2.3.1",
58
- "@tiny-design/icons": "1.0.10",
59
- "@tiny-design/tokens": "1.0.10"
58
+ "@tiny-design/icons": "1.1.0",
59
+ "@tiny-design/tokens": "1.1.0"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@testing-library/jest-dom": "^6.0.0",