@tiny-design/react 1.2.0 → 1.4.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/button/style/_index.scss +16 -11
- package/es/button/style/index.css +26 -5
- package/es/drawer/drawer.js +3 -2
- package/es/drawer/drawer.js.map +1 -1
- package/es/message/message.js +3 -2
- package/es/message/message.js.map +1 -1
- package/es/modal/modal.js +3 -2
- package/es/modal/modal.js.map +1 -1
- package/es/overlay/overlay.js +2 -2
- package/es/overlay/overlay.js.map +1 -1
- package/es/pop-confirm/style/_index.scss +4 -0
- package/es/pop-confirm/style/index.css +4 -0
- package/es/slider/style/_index.scss +1 -9
- package/es/slider/style/index.css +1 -6
- package/es/speed-dial/style/_index.scss +6 -7
- package/es/speed-dial/style/index.css +5 -5
- package/es/style/base.css +24 -3
- package/es/tag/style/_index.scss +24 -0
- package/es/tag/style/index.css +20 -0
- package/es/tag/types.d.ts +2 -1
- package/es/tag/types.js +7 -2
- package/es/tag/types.js.map +1 -1
- package/es/time-picker/style/_index.scss +13 -0
- package/es/time-picker/style/index.css +10 -0
- package/es/time-picker/time-panel.js +28 -28
- package/es/time-picker/time-panel.js.map +1 -1
- package/es/time-picker/time-picker.js +50 -29
- package/es/time-picker/time-picker.js.map +1 -1
- package/es/transition/index.js +1 -0
- package/es/transition/index.js.map +1 -1
- package/es/transition/transition.d.ts +20 -5
- package/es/transition/transition.js +33 -8
- package/es/transition/transition.js.map +1 -1
- package/es/transition/use-transition.js +137 -0
- package/es/transition/use-transition.js.map +1 -0
- package/es/waterfall/waterfall.js +62 -39
- package/es/waterfall/waterfall.js.map +1 -1
- package/lib/button/style/_index.scss +16 -11
- package/lib/button/style/index.css +26 -5
- package/lib/drawer/drawer.js +5 -4
- package/lib/drawer/drawer.js.map +1 -1
- package/lib/message/message.js +3 -2
- package/lib/message/message.js.map +1 -1
- package/lib/modal/modal.js +5 -4
- package/lib/modal/modal.js.map +1 -1
- package/lib/overlay/overlay.js +3 -3
- package/lib/overlay/overlay.js.map +1 -1
- package/lib/pop-confirm/style/_index.scss +4 -0
- package/lib/pop-confirm/style/index.css +4 -0
- package/lib/slider/style/_index.scss +1 -9
- package/lib/slider/style/index.css +1 -6
- package/lib/speed-dial/style/_index.scss +6 -7
- package/lib/speed-dial/style/index.css +5 -5
- package/lib/style/base.css +24 -3
- package/lib/tag/style/_index.scss +24 -0
- package/lib/tag/style/index.css +20 -0
- package/lib/tag/types.d.ts +2 -1
- package/lib/tag/types.js +7 -2
- package/lib/tag/types.js.map +1 -1
- package/lib/time-picker/style/_index.scss +13 -0
- package/lib/time-picker/style/index.css +10 -0
- package/lib/time-picker/time-panel.js +28 -28
- package/lib/time-picker/time-panel.js.map +1 -1
- package/lib/time-picker/time-picker.js +50 -29
- package/lib/time-picker/time-picker.js.map +1 -1
- package/lib/transition/index.js +1 -0
- package/lib/transition/index.js.map +1 -1
- package/lib/transition/transition.d.ts +20 -5
- package/lib/transition/transition.js +32 -7
- package/lib/transition/transition.js.map +1 -1
- package/lib/transition/use-transition.js +138 -0
- package/lib/transition/use-transition.js.map +1 -0
- package/lib/waterfall/waterfall.js +61 -38
- package/lib/waterfall/waterfall.js.map +1 -1
- package/package.json +3 -5
package/es/tag/style/index.css
CHANGED
|
@@ -88,6 +88,26 @@
|
|
|
88
88
|
background: var(--ty-tag-purple-bg);
|
|
89
89
|
border-color: var(--ty-tag-purple-border);
|
|
90
90
|
}
|
|
91
|
+
.ty-tag_success {
|
|
92
|
+
color: var(--ty-color-success);
|
|
93
|
+
background: var(--ty-color-success-bg);
|
|
94
|
+
border-color: var(--ty-color-success-border);
|
|
95
|
+
}
|
|
96
|
+
.ty-tag_info {
|
|
97
|
+
color: var(--ty-color-info);
|
|
98
|
+
background: var(--ty-color-info-bg);
|
|
99
|
+
border-color: var(--ty-color-info-border);
|
|
100
|
+
}
|
|
101
|
+
.ty-tag_warning {
|
|
102
|
+
color: var(--ty-color-warning);
|
|
103
|
+
background: var(--ty-color-warning-bg);
|
|
104
|
+
border-color: var(--ty-color-warning-border);
|
|
105
|
+
}
|
|
106
|
+
.ty-tag_danger {
|
|
107
|
+
color: var(--ty-color-danger);
|
|
108
|
+
background: var(--ty-color-danger-bg);
|
|
109
|
+
border-color: var(--ty-color-danger-border);
|
|
110
|
+
}
|
|
91
111
|
|
|
92
112
|
.ty-checkable-tag {
|
|
93
113
|
background-color: var(--ty-tag-checkable-bg);
|
package/es/tag/types.d.ts
CHANGED
|
@@ -8,8 +8,9 @@ interface CheckableTagProps extends BaseProps {
|
|
|
8
8
|
onChange?: (checked: boolean, e: React.MouseEvent) => void;
|
|
9
9
|
children?: React.ReactNode;
|
|
10
10
|
}
|
|
11
|
+
type StatusColor = 'success' | 'warning' | 'info' | 'danger';
|
|
11
12
|
interface TagProps extends BaseProps, React.PropsWithoutRef<JSX.IntrinsicElements['div']> {
|
|
12
|
-
color?: string;
|
|
13
|
+
color?: string | StatusColor;
|
|
13
14
|
closable?: boolean;
|
|
14
15
|
onClose?: React.MouseEventHandler;
|
|
15
16
|
onClick?: React.MouseEventHandler;
|
package/es/tag/types.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//#region src/tag/types.ts
|
|
2
1
|
const PresetColors = [
|
|
3
2
|
"magenta",
|
|
4
3
|
"red",
|
|
@@ -10,7 +9,13 @@ const PresetColors = [
|
|
|
10
9
|
"cyan",
|
|
11
10
|
"blue",
|
|
12
11
|
"geekblue",
|
|
13
|
-
"purple"
|
|
12
|
+
"purple",
|
|
13
|
+
...[
|
|
14
|
+
"success",
|
|
15
|
+
"info",
|
|
16
|
+
"warning",
|
|
17
|
+
"danger"
|
|
18
|
+
]
|
|
14
19
|
];
|
|
15
20
|
//#endregion
|
|
16
21
|
export { PresetColors };
|
package/es/tag/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../src/tag/types.ts"],"sourcesContent":["import React from 'react';\nimport { BaseProps } from '../_utils/props';\n\nexport interface CheckableTagProps extends BaseProps {\n defaultChecked?: boolean;\n checked?: boolean;\n onChange?: (checked: boolean, e: React.MouseEvent) => void;\n children?: React.ReactNode;\n}\n\nexport const PresetColors = [\n 'magenta',\n 'red',\n 'volcano',\n 'orange',\n 'gold',\n 'lime',\n 'green',\n 'cyan',\n 'blue',\n 'geekblue',\n 'purple',\n];\n\nexport interface TagProps extends BaseProps, React.PropsWithoutRef<JSX.IntrinsicElements['div']> {\n color?: string;\n closable?: boolean;\n onClose?: React.MouseEventHandler;\n onClick?: React.MouseEventHandler;\n defaultVisible?: boolean;\n visible?: boolean;\n children?: React.ReactNode;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../src/tag/types.ts"],"sourcesContent":["import React from 'react';\nimport { BaseProps } from '../_utils/props';\n\nexport interface CheckableTagProps extends BaseProps {\n defaultChecked?: boolean;\n checked?: boolean;\n onChange?: (checked: boolean, e: React.MouseEvent) => void;\n children?: React.ReactNode;\n}\n\nexport type StatusColor = 'success' | 'warning' | 'info' | 'danger';\n\nexport const StatusColors: StatusColor[] = ['success', 'info', 'warning', 'danger'];\n\nexport const PresetColors = [\n 'magenta',\n 'red',\n 'volcano',\n 'orange',\n 'gold',\n 'lime',\n 'green',\n 'cyan',\n 'blue',\n 'geekblue',\n 'purple',\n ...StatusColors,\n];\n\nexport interface TagProps extends BaseProps, React.PropsWithoutRef<JSX.IntrinsicElements['div']> {\n color?: string | StatusColor;\n closable?: boolean;\n onClose?: React.MouseEventHandler;\n onClick?: React.MouseEventHandler;\n defaultVisible?: boolean;\n visible?: boolean;\n children?: React.ReactNode;\n}\n"],"mappings":"AAcA,MAAa,eAAe;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,GAdyC;EAAC;EAAW;EAAQ;EAAW;EAAS;CAelF"}
|
|
@@ -29,6 +29,10 @@ $tp: #{$prefix}-time-picker;
|
|
|
29
29
|
box-shadow: var(--ty-input-focus-shadow);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
&_pending &__input-field {
|
|
33
|
+
color: var(--ty-color-text-tertiary);
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
&__input-field {
|
|
33
37
|
flex: 1;
|
|
34
38
|
border: none;
|
|
@@ -191,6 +195,15 @@ $tp: #{$prefix}-time-picker;
|
|
|
191
195
|
}
|
|
192
196
|
}
|
|
193
197
|
|
|
198
|
+
&_pending {
|
|
199
|
+
background: var(--ty-color-primary-bg);
|
|
200
|
+
color: var(--ty-color-text-tertiary);
|
|
201
|
+
|
|
202
|
+
&:hover {
|
|
203
|
+
background: var(--ty-color-primary-bg-hover);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
194
207
|
&_disabled {
|
|
195
208
|
color: var(--ty-color-text-quaternary);
|
|
196
209
|
cursor: not-allowed;
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
border-color: var(--ty-color-primary);
|
|
22
22
|
box-shadow: var(--ty-input-focus-shadow);
|
|
23
23
|
}
|
|
24
|
+
.ty-time-picker_pending .ty-time-picker__input-field {
|
|
25
|
+
color: var(--ty-color-text-tertiary);
|
|
26
|
+
}
|
|
24
27
|
.ty-time-picker__input-field {
|
|
25
28
|
flex: 1;
|
|
26
29
|
border: none;
|
|
@@ -157,6 +160,13 @@
|
|
|
157
160
|
.ty-time-picker__cell_selected:hover {
|
|
158
161
|
background: var(--ty-color-primary-bg-hover);
|
|
159
162
|
}
|
|
163
|
+
.ty-time-picker__cell_pending {
|
|
164
|
+
background: var(--ty-color-primary-bg);
|
|
165
|
+
color: var(--ty-color-text-tertiary);
|
|
166
|
+
}
|
|
167
|
+
.ty-time-picker__cell_pending:hover {
|
|
168
|
+
background: var(--ty-color-primary-bg-hover);
|
|
169
|
+
}
|
|
160
170
|
.ty-time-picker__cell_disabled {
|
|
161
171
|
color: var(--ty-color-text-quaternary);
|
|
162
172
|
cursor: not-allowed;
|
|
@@ -4,14 +4,16 @@ import { jsx } from "react/jsx-runtime";
|
|
|
4
4
|
//#region src/time-picker/time-panel.tsx
|
|
5
5
|
const ITEM_HEIGHT = 28;
|
|
6
6
|
const TimePanel = (props) => {
|
|
7
|
-
const { prefixCls, value, items, disabledItems = [], loop = false, onChange } = props;
|
|
7
|
+
const { prefixCls, value, pendingValue, items, disabledItems = [], loop = false, onChange } = props;
|
|
8
8
|
const panelRef = useRef(null);
|
|
9
9
|
const itemRefs = useRef(/* @__PURE__ */ new Map());
|
|
10
10
|
const isResetting = useRef(false);
|
|
11
11
|
const clickedRef = useRef(false);
|
|
12
12
|
const scrollToItemRef = useRef(null);
|
|
13
13
|
const oneGroupHeight = items.length * ITEM_HEIGHT;
|
|
14
|
+
const displayValue = pendingValue ?? value;
|
|
14
15
|
scrollToItemRef.current = (val) => {
|
|
16
|
+
if (val === null) return;
|
|
15
17
|
const panel = panelRef.current;
|
|
16
18
|
if (!panel) return;
|
|
17
19
|
if (loop) {
|
|
@@ -39,8 +41,8 @@ const TimePanel = (props) => {
|
|
|
39
41
|
clickedRef.current = false;
|
|
40
42
|
return;
|
|
41
43
|
}
|
|
42
|
-
scrollToItemRef.current?.(
|
|
43
|
-
}, [
|
|
44
|
+
scrollToItemRef.current?.(displayValue);
|
|
45
|
+
}, [displayValue]);
|
|
44
46
|
const handleScroll = useCallback(() => {
|
|
45
47
|
if (!loop || isResetting.current) return;
|
|
46
48
|
const panel = panelRef.current;
|
|
@@ -62,6 +64,16 @@ const TimePanel = (props) => {
|
|
|
62
64
|
clickedRef.current = true;
|
|
63
65
|
onChange(num);
|
|
64
66
|
};
|
|
67
|
+
const isPending = pendingValue !== null;
|
|
68
|
+
const isCommitted = value !== null && pendingValue === null;
|
|
69
|
+
const cellCls = (num) => {
|
|
70
|
+
const isSelected = num === displayValue;
|
|
71
|
+
return classNames(`${prefixCls}__cell`, {
|
|
72
|
+
[`${prefixCls}__cell_selected`]: isSelected && isCommitted,
|
|
73
|
+
[`${prefixCls}__cell_pending`]: isSelected && isPending,
|
|
74
|
+
[`${prefixCls}__cell_disabled`]: disabledItems.includes(num)
|
|
75
|
+
});
|
|
76
|
+
};
|
|
65
77
|
if (loop) return /* @__PURE__ */ jsx("div", {
|
|
66
78
|
className: `${prefixCls}__column`,
|
|
67
79
|
ref: panelRef,
|
|
@@ -72,17 +84,11 @@ const TimePanel = (props) => {
|
|
|
72
84
|
0,
|
|
73
85
|
1,
|
|
74
86
|
2
|
|
75
|
-
].map((copyIdx) => items.map((num, i) => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
[`${prefixCls}__cell_disabled`]: isDisabled
|
|
81
|
-
}),
|
|
82
|
-
onClick: () => handleClick(num),
|
|
83
|
-
children: String(num).padStart(2, "0")
|
|
84
|
-
}, `c${copyIdx}-${i}`);
|
|
85
|
-
}))
|
|
87
|
+
].map((copyIdx) => items.map((num, i) => /* @__PURE__ */ jsx("li", {
|
|
88
|
+
className: cellCls(num),
|
|
89
|
+
onClick: () => handleClick(num),
|
|
90
|
+
children: String(num).padStart(2, "0")
|
|
91
|
+
}, `c${copyIdx}-${i}`)))
|
|
86
92
|
})
|
|
87
93
|
});
|
|
88
94
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -90,20 +96,14 @@ const TimePanel = (props) => {
|
|
|
90
96
|
ref: panelRef,
|
|
91
97
|
children: /* @__PURE__ */ jsx("ul", {
|
|
92
98
|
className: `${prefixCls}__column-list`,
|
|
93
|
-
children: items.map((num) => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
[`${prefixCls}__cell_disabled`]: isDisabled
|
|
102
|
-
}),
|
|
103
|
-
onClick: () => handleClick(num),
|
|
104
|
-
children: String(num).padStart(2, "0")
|
|
105
|
-
}, num);
|
|
106
|
-
})
|
|
99
|
+
children: items.map((num) => /* @__PURE__ */ jsx("li", {
|
|
100
|
+
ref: (el) => {
|
|
101
|
+
if (el) itemRefs.current.set(num, el);
|
|
102
|
+
},
|
|
103
|
+
className: cellCls(num),
|
|
104
|
+
onClick: () => handleClick(num),
|
|
105
|
+
children: String(num).padStart(2, "0")
|
|
106
|
+
}, num))
|
|
107
107
|
})
|
|
108
108
|
});
|
|
109
109
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-panel.js","names":[],"sources":["../../src/time-picker/time-panel.tsx"],"sourcesContent":["import { useRef, useEffect, useCallback } from 'react';\nimport classNames from 'classnames';\n\nexport interface TimePanelProps {\n value: number;\n items: number[];\n disabledItems?: number[];\n loop?: boolean;\n onChange: (num: number) => void;\n prefixCls: string;\n}\n\nconst ITEM_HEIGHT = 28; // 4px padding-top + 20px line-height + 4px padding-bottom\n\nconst TimePanel = (props: TimePanelProps): React.ReactElement => {\n const { prefixCls, value, items, disabledItems = [], loop = false, onChange } = props;\n const panelRef = useRef<HTMLDivElement>(null);\n const itemRefs = useRef<Map<number, HTMLLIElement>>(new Map());\n const isResetting = useRef(false);\n const clickedRef = useRef(false);\n const scrollToItemRef = useRef<((val: number) => void) | null>(null);\n\n const oneGroupHeight = items.length * ITEM_HEIGHT;\n\n scrollToItemRef.current = (val: number) => {\n const panel = panelRef.current;\n if (!panel) return;\n\n if (loop) {\n const idx = items.indexOf(val);\n if (idx === -1) return;\n const top = oneGroupHeight + idx * ITEM_HEIGHT;\n isResetting.current = true;\n panel.scrollTo({ top, behavior: 'auto' });\n requestAnimationFrame(() => { isResetting.current = false; });\n } else {\n const el = itemRefs.current.get(val);\n if (el) {\n panel.scrollTo({ top: el.offsetTop, behavior: 'auto' });\n }\n }\n };\n\n useEffect(() => {\n if (clickedRef.current) {\n clickedRef.current = false;\n return;\n }\n scrollToItemRef.current?.(
|
|
1
|
+
{"version":3,"file":"time-panel.js","names":[],"sources":["../../src/time-picker/time-panel.tsx"],"sourcesContent":["import { useRef, useEffect, useCallback } from 'react';\nimport classNames from 'classnames';\n\nexport interface TimePanelProps {\n value: number | null;\n pendingValue: number | null;\n items: number[];\n disabledItems?: number[];\n loop?: boolean;\n onChange: (num: number) => void;\n prefixCls: string;\n}\n\nconst ITEM_HEIGHT = 28; // 4px padding-top + 20px line-height + 4px padding-bottom\n\nconst TimePanel = (props: TimePanelProps): React.ReactElement => {\n const { prefixCls, value, pendingValue, items, disabledItems = [], loop = false, onChange } = props;\n const panelRef = useRef<HTMLDivElement>(null);\n const itemRefs = useRef<Map<number, HTMLLIElement>>(new Map());\n const isResetting = useRef(false);\n const clickedRef = useRef(false);\n const scrollToItemRef = useRef<((val: number | null) => void) | null>(null);\n\n const oneGroupHeight = items.length * ITEM_HEIGHT;\n\n // The displayed value: pending takes priority, then committed\n const displayValue = pendingValue ?? value;\n\n scrollToItemRef.current = (val: number | null) => {\n if (val === null) return;\n const panel = panelRef.current;\n if (!panel) return;\n\n if (loop) {\n const idx = items.indexOf(val);\n if (idx === -1) return;\n const top = oneGroupHeight + idx * ITEM_HEIGHT;\n isResetting.current = true;\n panel.scrollTo({ top, behavior: 'auto' });\n requestAnimationFrame(() => { isResetting.current = false; });\n } else {\n const el = itemRefs.current.get(val);\n if (el) {\n panel.scrollTo({ top: el.offsetTop, behavior: 'auto' });\n }\n }\n };\n\n useEffect(() => {\n if (clickedRef.current) {\n clickedRef.current = false;\n return;\n }\n scrollToItemRef.current?.(displayValue);\n }, [displayValue]);\n\n // Scroll reset for loop mode\n const handleScroll = useCallback(() => {\n if (!loop || isResetting.current) return;\n const panel = panelRef.current;\n if (!panel) return;\n\n const st = panel.scrollTop;\n if (st < oneGroupHeight || st >= 2 * oneGroupHeight) {\n isResetting.current = true;\n panel.scrollTo({ top: (st % oneGroupHeight) + oneGroupHeight, behavior: 'auto' });\n requestAnimationFrame(() => { isResetting.current = false; });\n }\n }, [loop, oneGroupHeight]);\n\n const handleClick = (num: number) => {\n if (disabledItems.includes(num)) return;\n clickedRef.current = true;\n onChange(num);\n };\n\n const isPending = pendingValue !== null;\n const isCommitted = value !== null && pendingValue === null;\n\n const cellCls = (num: number) => {\n const isSelected = num === displayValue;\n return classNames(`${prefixCls}__cell`, {\n [`${prefixCls}__cell_selected`]: isSelected && isCommitted,\n [`${prefixCls}__cell_pending`]: isSelected && isPending,\n [`${prefixCls}__cell_disabled`]: disabledItems.includes(num),\n });\n };\n\n if (loop) {\n const copies = [0, 1, 2];\n return (\n <div className={`${prefixCls}__column`} ref={panelRef} onScroll={handleScroll}>\n <ul className={`${prefixCls}__column-list`}>\n {copies.map((copyIdx) =>\n items.map((num, i) => (\n <li\n key={`c${copyIdx}-${i}`}\n className={cellCls(num)}\n onClick={() => handleClick(num)}>\n {String(num).padStart(2, '0')}\n </li>\n ))\n )}\n </ul>\n </div>\n );\n }\n\n return (\n <div className={`${prefixCls}__column`} ref={panelRef}>\n <ul className={`${prefixCls}__column-list`}>\n {items.map((num) => (\n <li\n key={num}\n ref={(el) => {\n if (el) itemRefs.current.set(num, el);\n }}\n className={cellCls(num)}\n onClick={() => handleClick(num)}>\n {String(num).padStart(2, '0')}\n </li>\n ))}\n </ul>\n </div>\n );\n};\n\nexport default TimePanel;\n"],"mappings":"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"}
|
|
@@ -8,6 +8,11 @@ import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "r
|
|
|
8
8
|
import classNames from "classnames";
|
|
9
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
//#region src/time-picker/time-picker.tsx
|
|
11
|
+
const EMPTY_PENDING = {
|
|
12
|
+
h: null,
|
|
13
|
+
m: null,
|
|
14
|
+
s: null
|
|
15
|
+
};
|
|
11
16
|
function formatTime(date, format, use12Hours) {
|
|
12
17
|
let h = date.getHours();
|
|
13
18
|
const m = String(date.getMinutes()).padStart(2, "0");
|
|
@@ -35,6 +40,7 @@ const TimePicker = (props) => {
|
|
|
35
40
|
const { defaultValue, value, open: controlledOpen, format = "HH:mm:ss", use12Hours = false, hourStep = 1, minuteStep = 1, secondStep = 1, disabled = false, placeholder = locale.TimePicker.selectTime, allowClear = true, size = "md", inputReadOnly = true, disabledTime, hideDisabledOptions = false, loop = false, showNow = true, renderExtraFooter, suffixIcon, onChange, onOpenChange, className, style, prefixCls: customisedCls } = props;
|
|
36
41
|
const prefixCls = getPrefixCls("time-picker", useContext(ConfigContext).prefixCls, customisedCls);
|
|
37
42
|
const [date, setDate] = useState(value ?? defaultValue ?? null);
|
|
43
|
+
const [pending, setPending] = useState(EMPTY_PENDING);
|
|
38
44
|
const [open, setOpen] = useState(false);
|
|
39
45
|
const wrapperRef = useRef(null);
|
|
40
46
|
const dropdownRef = useRef(null);
|
|
@@ -51,6 +57,7 @@ const TimePicker = (props) => {
|
|
|
51
57
|
if (wrapperRef.current?.contains(target) || dropdownRef.current?.contains(target)) return;
|
|
52
58
|
if (controlledOpen === void 0) setOpen(false);
|
|
53
59
|
onOpenChange?.(false);
|
|
60
|
+
setPending(EMPTY_PENDING);
|
|
54
61
|
};
|
|
55
62
|
document.addEventListener("click", listener);
|
|
56
63
|
return () => document.removeEventListener("click", listener);
|
|
@@ -58,43 +65,51 @@ const TimePicker = (props) => {
|
|
|
58
65
|
const toggleOpen = useCallback((val) => {
|
|
59
66
|
if (controlledOpen === void 0) setOpen(val);
|
|
60
67
|
onOpenChange?.(val);
|
|
68
|
+
if (!val) setPending(EMPTY_PENDING);
|
|
61
69
|
}, [controlledOpen, onOpenChange]);
|
|
62
|
-
|
|
70
|
+
/** Build a Date from committed date + pending overrides */
|
|
71
|
+
const buildDate = useCallback((p) => {
|
|
63
72
|
const base = date ? new Date(date) : new Date(0, 0, 0, 0, 0, 0, 0);
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
if (p.h !== null) base.setHours(p.h);
|
|
74
|
+
if (p.m !== null) base.setMinutes(p.m);
|
|
75
|
+
if (p.s !== null) base.setSeconds(p.s);
|
|
76
|
+
return base;
|
|
77
|
+
}, [date]);
|
|
78
|
+
const updatePending = useCallback((type, num) => {
|
|
79
|
+
setPending((prev) => ({
|
|
80
|
+
...prev,
|
|
81
|
+
[type]: num
|
|
82
|
+
}));
|
|
83
|
+
}, []);
|
|
84
|
+
const commit = useCallback((newDate) => {
|
|
85
|
+
if (value === void 0) setDate(newDate);
|
|
86
|
+
onChange?.(newDate);
|
|
87
|
+
setPending(EMPTY_PENDING);
|
|
88
|
+
}, [value, onChange]);
|
|
74
89
|
const handleClear = (e) => {
|
|
75
90
|
e.stopPropagation();
|
|
76
91
|
if (value === void 0) setDate(null);
|
|
77
92
|
onChange?.(null);
|
|
93
|
+
setPending(EMPTY_PENDING);
|
|
78
94
|
toggleOpen(false);
|
|
79
95
|
};
|
|
80
96
|
const handleNow = () => {
|
|
81
|
-
|
|
82
|
-
if (value === void 0) setDate(now);
|
|
83
|
-
onChange?.(now);
|
|
97
|
+
commit(/* @__PURE__ */ new Date());
|
|
84
98
|
toggleOpen(false);
|
|
85
99
|
};
|
|
86
100
|
const handleOk = () => {
|
|
101
|
+
if (pending.h !== null || pending.m !== null || pending.s !== null) commit(buildDate(pending));
|
|
87
102
|
toggleOpen(false);
|
|
88
103
|
};
|
|
104
|
+
const effectiveHour = pending.h ?? date?.getHours() ?? 0;
|
|
105
|
+
const effectiveMinute = pending.m ?? date?.getMinutes() ?? 0;
|
|
89
106
|
const disabled12 = useMemo(() => disabledTime?.() ?? {}, [disabledTime]);
|
|
90
107
|
const disabledHours = useMemo(() => disabled12.disabledHours?.() ?? [], [disabled12]);
|
|
91
|
-
const
|
|
92
|
-
const
|
|
93
|
-
const currentMinute = date?.getMinutes() ?? 0;
|
|
94
|
-
const disabledSeconds = useMemo(() => disabled12.disabledSeconds?.(currentHour, currentMinute) ?? [], [
|
|
108
|
+
const disabledMinutes = useMemo(() => disabled12.disabledMinutes?.(effectiveHour) ?? [], [disabled12, effectiveHour]);
|
|
109
|
+
const disabledSeconds = useMemo(() => disabled12.disabledSeconds?.(effectiveHour, effectiveMinute) ?? [], [
|
|
95
110
|
disabled12,
|
|
96
|
-
|
|
97
|
-
|
|
111
|
+
effectiveHour,
|
|
112
|
+
effectiveMinute
|
|
98
113
|
]);
|
|
99
114
|
const hours = generateSteps(24, hourStep);
|
|
100
115
|
const minutes = generateSteps(60, minuteStep);
|
|
@@ -102,12 +117,15 @@ const TimePicker = (props) => {
|
|
|
102
117
|
const filteredHours = hideDisabledOptions ? hours.filter((h) => !disabledHours.includes(h)) : hours;
|
|
103
118
|
const filteredMinutes = hideDisabledOptions ? minutes.filter((m) => !disabledMinutes.includes(m)) : minutes;
|
|
104
119
|
const filteredSeconds = hideDisabledOptions ? seconds.filter((s) => !disabledSeconds.includes(s)) : seconds;
|
|
105
|
-
const
|
|
106
|
-
const
|
|
120
|
+
const hasPending = pending.h !== null || pending.m !== null || pending.s !== null;
|
|
121
|
+
const effectiveDate = (hasPending ? buildDate(pending) : null) ?? date;
|
|
122
|
+
const hasValue = effectiveDate !== null;
|
|
123
|
+
const displayValue = hasValue ? formatTime(effectiveDate, format, use12Hours) : "";
|
|
107
124
|
const cls = classNames(prefixCls, className, `${prefixCls}_${size}`, {
|
|
108
125
|
[`${prefixCls}_disabled`]: disabled,
|
|
109
126
|
[`${prefixCls}_open`]: isOpen,
|
|
110
|
-
[`${prefixCls}_has-value`]: hasValue
|
|
127
|
+
[`${prefixCls}_has-value`]: hasValue,
|
|
128
|
+
[`${prefixCls}_pending`]: hasPending
|
|
111
129
|
});
|
|
112
130
|
const renderOverlay = () => /* @__PURE__ */ jsxs("div", {
|
|
113
131
|
className: `${prefixCls}__dropdown`,
|
|
@@ -117,27 +135,30 @@ const TimePicker = (props) => {
|
|
|
117
135
|
children: [
|
|
118
136
|
/* @__PURE__ */ jsx(TimePanel, {
|
|
119
137
|
prefixCls,
|
|
120
|
-
value: date?.getHours() ??
|
|
138
|
+
value: date?.getHours() ?? null,
|
|
139
|
+
pendingValue: pending.h,
|
|
121
140
|
items: filteredHours,
|
|
122
141
|
disabledItems: hideDisabledOptions ? [] : disabledHours,
|
|
123
142
|
loop,
|
|
124
|
-
onChange: (h) =>
|
|
143
|
+
onChange: (h) => updatePending("h", h)
|
|
125
144
|
}),
|
|
126
145
|
showsMinutes(format) && /* @__PURE__ */ jsx(TimePanel, {
|
|
127
146
|
prefixCls,
|
|
128
|
-
value: date?.getMinutes() ??
|
|
147
|
+
value: date?.getMinutes() ?? null,
|
|
148
|
+
pendingValue: pending.m,
|
|
129
149
|
items: filteredMinutes,
|
|
130
150
|
disabledItems: hideDisabledOptions ? [] : disabledMinutes,
|
|
131
151
|
loop,
|
|
132
|
-
onChange: (m) =>
|
|
152
|
+
onChange: (m) => updatePending("m", m)
|
|
133
153
|
}),
|
|
134
154
|
showsSeconds(format) && /* @__PURE__ */ jsx(TimePanel, {
|
|
135
155
|
prefixCls,
|
|
136
|
-
value: date?.getSeconds() ??
|
|
156
|
+
value: date?.getSeconds() ?? null,
|
|
157
|
+
pendingValue: pending.s,
|
|
137
158
|
items: filteredSeconds,
|
|
138
159
|
disabledItems: hideDisabledOptions ? [] : disabledSeconds,
|
|
139
160
|
loop,
|
|
140
|
-
onChange: (s) =>
|
|
161
|
+
onChange: (s) => updatePending("s", s)
|
|
141
162
|
})
|
|
142
163
|
]
|
|
143
164
|
}), /* @__PURE__ */ jsxs("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-picker.js","names":["Popup"],"sources":["../../src/time-picker/time-picker.tsx"],"sourcesContent":["import { useEffect, useState, useRef, useCallback, useContext, useMemo } from 'react';\nimport classNames from 'classnames';\nimport { ConfigContext } from '../config-provider/config-context';\nimport { getPrefixCls } from '../_utils/general';\nimport { useLocale } from '../_utils/use-locale';\nimport { ClockIcon, ClearIcon } from '../_utils/components';\nimport Popup from '../popup';\nimport TimePanel from './time-panel';\nimport { TimePickerProps } from './types';\n\nfunction formatTime(date: Date, format: string, use12Hours: boolean): string {\n let h = date.getHours();\n const m = String(date.getMinutes()).padStart(2, '0');\n const s = String(date.getSeconds()).padStart(2, '0');\n let period = '';\n\n if (use12Hours) {\n period = h >= 12 ? ' PM' : ' AM';\n h = h % 12 || 12;\n }\n\n return format\n .replace('HH', String(h).padStart(2, '0'))\n .replace('H', String(h))\n .replace('mm', m)\n .replace('ss', s) + period;\n}\n\nfunction generateSteps(count: number, step: number): number[] {\n const items: number[] = [];\n for (let i = 0; i < count; i += step) {\n items.push(i);\n }\n return items;\n}\n\nfunction showsSeconds(format: string): boolean {\n return format.includes('ss') || format.includes('s');\n}\n\nfunction showsMinutes(format: string): boolean {\n return format.includes('mm') || format.includes('m');\n}\n\nconst TimePicker = (props: TimePickerProps): React.ReactElement => {\n const locale = useLocale();\n const {\n defaultValue,\n value,\n open: controlledOpen,\n format = 'HH:mm:ss',\n use12Hours = false,\n hourStep = 1,\n minuteStep = 1,\n secondStep = 1,\n disabled = false,\n placeholder = locale.TimePicker.selectTime,\n allowClear = true,\n size = 'md',\n inputReadOnly = true,\n disabledTime,\n hideDisabledOptions = false,\n loop = false,\n showNow = true,\n renderExtraFooter,\n suffixIcon,\n onChange,\n onOpenChange,\n className,\n style,\n prefixCls: customisedCls,\n } = props;\n\n const configContext = useContext(ConfigContext);\n const prefixCls = getPrefixCls('time-picker', configContext.prefixCls, customisedCls);\n\n const [date, setDate] = useState<Date | null>(value ?? defaultValue ?? null);\n const [open, setOpen] = useState(false);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const isOpen = controlledOpen ?? open;\n\n // Controlled value\n useEffect(() => {\n if (value !== undefined) setDate(value);\n }, [value]);\n\n useEffect(() => {\n if (controlledOpen !== undefined) setOpen(controlledOpen);\n }, [controlledOpen]);\n\n useEffect(() => {\n const listener = (event: MouseEvent) => {\n const target = event.target as HTMLElement;\n if (wrapperRef.current?.contains(target) || dropdownRef.current?.contains(target)) return;\n if (controlledOpen === undefined) setOpen(false);\n onOpenChange?.(false);\n };\n document.addEventListener('click', listener);\n return () => document.removeEventListener('click', listener);\n }, [controlledOpen, onOpenChange]);\n\n const toggleOpen = useCallback((val: boolean) => {\n if (controlledOpen === undefined) setOpen(val);\n onOpenChange?.(val);\n }, [controlledOpen, onOpenChange]);\n\n const updateTime = useCallback((type: 'h' | 'm' | 's', num: number) => {\n const base = date ? new Date(date) : new Date(0, 0, 0, 0, 0, 0, 0);\n if (type === 'h') base.setHours(num);\n else if (type === 'm') base.setMinutes(num);\n else base.setSeconds(num);\n\n if (value === undefined) setDate(base);\n onChange?.(base);\n }, [date, value, onChange]);\n\n const handleClear = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (value === undefined) setDate(null);\n onChange?.(null);\n toggleOpen(false);\n };\n\n const handleNow = () => {\n const now = new Date();\n if (value === undefined) setDate(now);\n onChange?.(now);\n toggleOpen(false);\n };\n\n const handleOk = () => {\n toggleOpen(false);\n };\n\n // Disabled time calculation\n const disabled12 = useMemo(() => disabledTime?.() ?? {}, [disabledTime]);\n const disabledHours = useMemo(() => disabled12.disabledHours?.() ?? [], [disabled12]);\n const currentHour = date?.getHours() ?? 0;\n const disabledMinutes = useMemo(\n () => disabled12.disabledMinutes?.(currentHour) ?? [],\n [disabled12, currentHour]\n );\n const currentMinute = date?.getMinutes() ?? 0;\n const disabledSeconds = useMemo(\n () => disabled12.disabledSeconds?.(currentHour, currentMinute) ?? [],\n [disabled12, currentHour, currentMinute]\n );\n\n const hours = generateSteps(24, hourStep);\n const minutes = generateSteps(60, minuteStep);\n const seconds = generateSteps(60, secondStep);\n\n const filteredHours = hideDisabledOptions ? hours.filter((h) => !disabledHours.includes(h)) : hours;\n const filteredMinutes = hideDisabledOptions ? minutes.filter((m) => !disabledMinutes.includes(m)) : minutes;\n const filteredSeconds = hideDisabledOptions ? seconds.filter((s) => !disabledSeconds.includes(s)) : seconds;\n\n const hasValue = date !== null;\n const displayValue = hasValue ? formatTime(date, format, use12Hours) : '';\n\n const cls = classNames(prefixCls, className, `${prefixCls}_${size}`, {\n [`${prefixCls}_disabled`]: disabled,\n [`${prefixCls}_open`]: isOpen,\n [`${prefixCls}_has-value`]: hasValue,\n });\n\n const renderOverlay = () => (\n <div className={`${prefixCls}__dropdown`} ref={dropdownRef}>\n <div className={`${prefixCls}__panel`}>\n <TimePanel\n prefixCls={prefixCls}\n value={date?.getHours() ?? 0}\n items={filteredHours}\n disabledItems={hideDisabledOptions ? [] : disabledHours}\n loop={loop}\n onChange={(h) => updateTime('h', h)}\n />\n {showsMinutes(format) && (\n <TimePanel\n prefixCls={prefixCls}\n value={date?.getMinutes() ?? 0}\n items={filteredMinutes}\n disabledItems={hideDisabledOptions ? [] : disabledMinutes}\n loop={loop}\n onChange={(m) => updateTime('m', m)}\n />\n )}\n {showsSeconds(format) && (\n <TimePanel\n prefixCls={prefixCls}\n value={date?.getSeconds() ?? 0}\n items={filteredSeconds}\n disabledItems={hideDisabledOptions ? [] : disabledSeconds}\n loop={loop}\n onChange={(s) => updateTime('s', s)}\n />\n )}\n </div>\n <div className={`${prefixCls}__footer`}>\n {renderExtraFooter && <div className={`${prefixCls}__extra-footer`}>{renderExtraFooter()}</div>}\n <div className={`${prefixCls}__footer-actions`}>\n {showNow && <a className={`${prefixCls}__now-btn`} onClick={handleNow}>{locale.TimePicker.now}</a>}\n <button type=\"button\" className={`${prefixCls}__ok-btn`} onClick={handleOk}>{locale.TimePicker.okText}</button>\n </div>\n </div>\n </div>\n );\n\n return (\n <div className={cls} style={style} ref={wrapperRef}>\n <Popup\n trigger=\"manual\"\n placement=\"bottom-start\"\n arrow={false}\n visible={isOpen}\n content={renderOverlay()}>\n <div\n className={`${prefixCls}__input`}\n onClick={() => !disabled && toggleOpen(!isOpen)}>\n <input\n className={`${prefixCls}__input-field`}\n readOnly={inputReadOnly}\n disabled={disabled}\n placeholder={placeholder}\n value={displayValue}\n aria-expanded={isOpen}\n aria-haspopup=\"dialog\"\n onKeyDown={(e) => {\n if (e.key === 'Escape' && isOpen) toggleOpen(false);\n }}\n />\n <span className={`${prefixCls}__suffix`}>\n {allowClear && hasValue && !disabled ? (\n <button type=\"button\" className={`${prefixCls}__clear`} onClick={handleClear} aria-label=\"Clear time\">\n <ClearIcon size=\"1em\" />\n </button>\n ) : null}\n <span className={`${prefixCls}__icon`}>\n {suffixIcon ?? <ClockIcon size=\"1em\" />}\n </span>\n </span>\n </div>\n </Popup>\n </div>\n );\n};\n\nTimePicker.displayName = 'TimePicker';\n\nexport default TimePicker;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"time-picker.js","names":["Popup"],"sources":["../../src/time-picker/time-picker.tsx"],"sourcesContent":["import { useEffect, useState, useRef, useCallback, useContext, useMemo } from 'react';\nimport classNames from 'classnames';\nimport { ConfigContext } from '../config-provider/config-context';\nimport { getPrefixCls } from '../_utils/general';\nimport { useLocale } from '../_utils/use-locale';\nimport { ClockIcon, ClearIcon } from '../_utils/components';\nimport Popup from '../popup';\nimport TimePanel from './time-panel';\nimport { TimePickerProps } from './types';\n\ninterface PendingTime {\n h: number | null;\n m: number | null;\n s: number | null;\n}\n\nconst EMPTY_PENDING: PendingTime = { h: null, m: null, s: null };\n\nfunction formatTime(date: Date, format: string, use12Hours: boolean): string {\n let h = date.getHours();\n const m = String(date.getMinutes()).padStart(2, '0');\n const s = String(date.getSeconds()).padStart(2, '0');\n let period = '';\n\n if (use12Hours) {\n period = h >= 12 ? ' PM' : ' AM';\n h = h % 12 || 12;\n }\n\n return format\n .replace('HH', String(h).padStart(2, '0'))\n .replace('H', String(h))\n .replace('mm', m)\n .replace('ss', s) + period;\n}\n\nfunction generateSteps(count: number, step: number): number[] {\n const items: number[] = [];\n for (let i = 0; i < count; i += step) {\n items.push(i);\n }\n return items;\n}\n\nfunction showsSeconds(format: string): boolean {\n return format.includes('ss') || format.includes('s');\n}\n\nfunction showsMinutes(format: string): boolean {\n return format.includes('mm') || format.includes('m');\n}\n\nconst TimePicker = (props: TimePickerProps): React.ReactElement => {\n const locale = useLocale();\n const {\n defaultValue,\n value,\n open: controlledOpen,\n format = 'HH:mm:ss',\n use12Hours = false,\n hourStep = 1,\n minuteStep = 1,\n secondStep = 1,\n disabled = false,\n placeholder = locale.TimePicker.selectTime,\n allowClear = true,\n size = 'md',\n inputReadOnly = true,\n disabledTime,\n hideDisabledOptions = false,\n loop = false,\n showNow = true,\n renderExtraFooter,\n suffixIcon,\n onChange,\n onOpenChange,\n className,\n style,\n prefixCls: customisedCls,\n } = props;\n\n const configContext = useContext(ConfigContext);\n const prefixCls = getPrefixCls('time-picker', configContext.prefixCls, customisedCls);\n\n const [date, setDate] = useState<Date | null>(value ?? defaultValue ?? null);\n const [pending, setPending] = useState<PendingTime>(EMPTY_PENDING);\n const [open, setOpen] = useState(false);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const isOpen = controlledOpen ?? open;\n\n // Controlled value\n useEffect(() => {\n if (value !== undefined) setDate(value);\n }, [value]);\n\n useEffect(() => {\n if (controlledOpen !== undefined) setOpen(controlledOpen);\n }, [controlledOpen]);\n\n useEffect(() => {\n const listener = (event: MouseEvent) => {\n const target = event.target as HTMLElement;\n if (wrapperRef.current?.contains(target) || dropdownRef.current?.contains(target)) return;\n if (controlledOpen === undefined) setOpen(false);\n onOpenChange?.(false);\n setPending(EMPTY_PENDING);\n };\n document.addEventListener('click', listener);\n return () => document.removeEventListener('click', listener);\n }, [controlledOpen, onOpenChange]);\n\n const toggleOpen = useCallback((val: boolean) => {\n if (controlledOpen === undefined) setOpen(val);\n onOpenChange?.(val);\n if (!val) setPending(EMPTY_PENDING);\n }, [controlledOpen, onOpenChange]);\n\n /** Build a Date from committed date + pending overrides */\n const buildDate = useCallback((p: PendingTime): Date => {\n const base = date ? new Date(date) : new Date(0, 0, 0, 0, 0, 0, 0);\n if (p.h !== null) base.setHours(p.h);\n if (p.m !== null) base.setMinutes(p.m);\n if (p.s !== null) base.setSeconds(p.s);\n return base;\n }, [date]);\n\n const updatePending = useCallback((type: 'h' | 'm' | 's', num: number) => {\n setPending((prev) => ({ ...prev, [type]: num }));\n }, []);\n\n const commit = useCallback((newDate: Date) => {\n if (value === undefined) setDate(newDate);\n onChange?.(newDate);\n setPending(EMPTY_PENDING);\n }, [value, onChange]);\n\n const handleClear = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (value === undefined) setDate(null);\n onChange?.(null);\n setPending(EMPTY_PENDING);\n toggleOpen(false);\n };\n\n const handleNow = () => {\n const now = new Date();\n commit(now);\n toggleOpen(false);\n };\n\n const handleOk = () => {\n if (pending.h !== null || pending.m !== null || pending.s !== null) {\n commit(buildDate(pending));\n }\n toggleOpen(false);\n };\n\n // Disabled time calculation — use pending values when available\n const effectiveHour = pending.h ?? date?.getHours() ?? 0;\n const effectiveMinute = pending.m ?? date?.getMinutes() ?? 0;\n\n const disabled12 = useMemo(() => disabledTime?.() ?? {}, [disabledTime]);\n const disabledHours = useMemo(() => disabled12.disabledHours?.() ?? [], [disabled12]);\n const disabledMinutes = useMemo(\n () => disabled12.disabledMinutes?.(effectiveHour) ?? [],\n [disabled12, effectiveHour]\n );\n const disabledSeconds = useMemo(\n () => disabled12.disabledSeconds?.(effectiveHour, effectiveMinute) ?? [],\n [disabled12, effectiveHour, effectiveMinute]\n );\n\n const hours = generateSteps(24, hourStep);\n const minutes = generateSteps(60, minuteStep);\n const seconds = generateSteps(60, secondStep);\n\n const filteredHours = hideDisabledOptions ? hours.filter((h) => !disabledHours.includes(h)) : hours;\n const filteredMinutes = hideDisabledOptions ? minutes.filter((m) => !disabledMinutes.includes(m)) : minutes;\n const filteredSeconds = hideDisabledOptions ? seconds.filter((s) => !disabledSeconds.includes(s)) : seconds;\n\n const hasPending = pending.h !== null || pending.m !== null || pending.s !== null;\n const previewDate = hasPending ? buildDate(pending) : null;\n const effectiveDate = previewDate ?? date;\n const hasValue = effectiveDate !== null;\n const displayValue = hasValue ? formatTime(effectiveDate, format, use12Hours) : '';\n\n const cls = classNames(prefixCls, className, `${prefixCls}_${size}`, {\n [`${prefixCls}_disabled`]: disabled,\n [`${prefixCls}_open`]: isOpen,\n [`${prefixCls}_has-value`]: hasValue,\n [`${prefixCls}_pending`]: hasPending,\n });\n\n const renderOverlay = () => (\n <div className={`${prefixCls}__dropdown`} ref={dropdownRef}>\n <div className={`${prefixCls}__panel`}>\n <TimePanel\n prefixCls={prefixCls}\n value={date?.getHours() ?? null}\n pendingValue={pending.h}\n items={filteredHours}\n disabledItems={hideDisabledOptions ? [] : disabledHours}\n loop={loop}\n onChange={(h) => updatePending('h', h)}\n />\n {showsMinutes(format) && (\n <TimePanel\n prefixCls={prefixCls}\n value={date?.getMinutes() ?? null}\n pendingValue={pending.m}\n items={filteredMinutes}\n disabledItems={hideDisabledOptions ? [] : disabledMinutes}\n loop={loop}\n onChange={(m) => updatePending('m', m)}\n />\n )}\n {showsSeconds(format) && (\n <TimePanel\n prefixCls={prefixCls}\n value={date?.getSeconds() ?? null}\n pendingValue={pending.s}\n items={filteredSeconds}\n disabledItems={hideDisabledOptions ? [] : disabledSeconds}\n loop={loop}\n onChange={(s) => updatePending('s', s)}\n />\n )}\n </div>\n <div className={`${prefixCls}__footer`}>\n {renderExtraFooter && <div className={`${prefixCls}__extra-footer`}>{renderExtraFooter()}</div>}\n <div className={`${prefixCls}__footer-actions`}>\n {showNow && <a className={`${prefixCls}__now-btn`} onClick={handleNow}>{locale.TimePicker.now}</a>}\n <button type=\"button\" className={`${prefixCls}__ok-btn`} onClick={handleOk}>{locale.TimePicker.okText}</button>\n </div>\n </div>\n </div>\n );\n\n return (\n <div className={cls} style={style} ref={wrapperRef}>\n <Popup\n trigger=\"manual\"\n placement=\"bottom-start\"\n arrow={false}\n visible={isOpen}\n content={renderOverlay()}>\n <div\n className={`${prefixCls}__input`}\n onClick={() => !disabled && toggleOpen(!isOpen)}>\n <input\n className={`${prefixCls}__input-field`}\n readOnly={inputReadOnly}\n disabled={disabled}\n placeholder={placeholder}\n value={displayValue}\n aria-expanded={isOpen}\n aria-haspopup=\"dialog\"\n onKeyDown={(e) => {\n if (e.key === 'Escape' && isOpen) toggleOpen(false);\n }}\n />\n <span className={`${prefixCls}__suffix`}>\n {allowClear && hasValue && !disabled ? (\n <button type=\"button\" className={`${prefixCls}__clear`} onClick={handleClear} aria-label=\"Clear time\">\n <ClearIcon size=\"1em\" />\n </button>\n ) : null}\n <span className={`${prefixCls}__icon`}>\n {suffixIcon ?? <ClockIcon size=\"1em\" />}\n </span>\n </span>\n </div>\n </Popup>\n </div>\n );\n};\n\nTimePicker.displayName = 'TimePicker';\n\nexport default TimePicker;\n"],"mappings":"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"}
|
package/es/transition/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/transition/index.tsx"],"sourcesContent":["import Transition from './transition';\n\nexport type { AnimationName, TransitionProps } from './transition';\nexport default Transition;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/transition/index.tsx"],"sourcesContent":["import Transition from './transition';\n\nexport type { AnimationName, TransitionProps } from './transition';\nexport { default as useTransition } from './use-transition';\nexport type { TransitionState, UseTransitionOptions, UseTransitionResult } from './use-transition';\nexport default Transition;\n"],"mappings":";;;AAKA,IAAA,qBAAe"}
|
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { CSSTransitionProps } from "react-transition-group/CSSTransition";
|
|
3
2
|
|
|
4
3
|
//#region src/transition/transition.d.ts
|
|
5
4
|
type AnimationName = 'zoom-center-top' | 'zoom-center-bottom' | 'zoom-center-left' | 'zoom-center-right' | 'zoom-top-start' | 'zoom-top' | 'zoom-top-end' | 'zoom-bottom-start' | 'zoom-bottom' | 'zoom-bottom-end' | 'zoom-left-start' | 'zoom-left' | 'zoom-left-end' | 'zoom-right-start' | 'zoom-right' | 'zoom-right-end' | 'slide-up' | 'slide-down';
|
|
6
5
|
type TransitionProps = {
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
in?: boolean;
|
|
7
|
+
timeout?: number | {
|
|
8
|
+
enter: number;
|
|
9
|
+
exit: number;
|
|
10
|
+
};
|
|
11
|
+
appear?: boolean;
|
|
12
|
+
unmountOnExit?: boolean;
|
|
13
|
+
mountOnEnter?: boolean; /** Animation prefix */
|
|
14
|
+
prefix?: string; /** Preset animation name */
|
|
15
|
+
animation?: AnimationName; /** Custom class name base (overrides prefix + animation) */
|
|
16
|
+
classNames?: string; /** Prevent the transition conflict with the inner component */
|
|
9
17
|
wrapper?: boolean;
|
|
18
|
+
nodeRef?: React.RefObject<HTMLElement | null>;
|
|
19
|
+
onEnter?: () => void;
|
|
20
|
+
onEntering?: () => void;
|
|
21
|
+
onEntered?: () => void;
|
|
22
|
+
onExit?: () => void;
|
|
23
|
+
onExiting?: () => void;
|
|
24
|
+
onExited?: () => void;
|
|
10
25
|
children?: React.ReactNode;
|
|
11
|
-
}
|
|
26
|
+
};
|
|
12
27
|
declare const Transition: {
|
|
13
|
-
(props: TransitionProps): React.ReactElement;
|
|
28
|
+
(props: TransitionProps): React.ReactElement | null;
|
|
14
29
|
displayName: string;
|
|
15
30
|
};
|
|
16
31
|
//#endregion
|
|
@@ -1,18 +1,43 @@
|
|
|
1
|
-
import "
|
|
1
|
+
import useTransition from "./use-transition.js";
|
|
2
|
+
import React from "react";
|
|
2
3
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { CSSTransition } from "react-transition-group";
|
|
4
4
|
//#region src/transition/transition.tsx
|
|
5
|
+
function getTransitionClasses(base, state) {
|
|
6
|
+
switch (state) {
|
|
7
|
+
case "enter": return `${base}-enter`;
|
|
8
|
+
case "entering": return `${base}-enter ${base}-enter-active`;
|
|
9
|
+
case "entered": return `${base}-enter-done`;
|
|
10
|
+
case "exit": return `${base}-exit`;
|
|
11
|
+
case "exiting": return `${base}-exit ${base}-exit-active`;
|
|
12
|
+
case "exited": return `${base}-exit-done`;
|
|
13
|
+
default: return "";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
5
16
|
const Transition = (props) => {
|
|
6
|
-
const { timeout = 300, unmountOnExit = true, appear = true, prefix = "ty", animation, classNames, nodeRef, children, wrapper,
|
|
7
|
-
|
|
8
|
-
|
|
17
|
+
const { in: inProp = false, timeout = 300, unmountOnExit = true, mountOnEnter, appear = true, prefix = "ty", animation, classNames: classNamesProp, nodeRef, children, wrapper, onEnter, onEntering, onEntered, onExit, onExiting, onExited } = props;
|
|
18
|
+
const { state, shouldMount } = useTransition({
|
|
19
|
+
in: inProp,
|
|
9
20
|
timeout,
|
|
10
21
|
appear,
|
|
11
22
|
unmountOnExit,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
23
|
+
mountOnEnter,
|
|
24
|
+
onEnter,
|
|
25
|
+
onEntering,
|
|
26
|
+
onEntered,
|
|
27
|
+
onExit,
|
|
28
|
+
onExiting,
|
|
29
|
+
onExited,
|
|
30
|
+
nodeRef
|
|
15
31
|
});
|
|
32
|
+
if (!shouldMount) return null;
|
|
33
|
+
const transitionClasses = getTransitionClasses(classNamesProp ? classNamesProp : `${prefix}-${animation}`, state);
|
|
34
|
+
const child = wrapper ? /* @__PURE__ */ jsx("div", { children }) : children;
|
|
35
|
+
if (React.isValidElement(child)) {
|
|
36
|
+
const existingClassName = child.props.className || "";
|
|
37
|
+
const mergedClassName = existingClassName ? `${existingClassName} ${transitionClasses}`.trim() : transitionClasses;
|
|
38
|
+
return React.cloneElement(child, { className: mergedClassName || void 0 });
|
|
39
|
+
}
|
|
40
|
+
return child;
|
|
16
41
|
};
|
|
17
42
|
Transition.displayName = "Transition";
|
|
18
43
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transition.js","names":[],"sources":["../../src/transition/transition.tsx"],"sourcesContent":["import React from 'react';\nimport
|
|
1
|
+
{"version":3,"file":"transition.js","names":[],"sources":["../../src/transition/transition.tsx"],"sourcesContent":["import React from 'react';\nimport useTransition, { TransitionState } from './use-transition';\n\nexport type AnimationName =\n | 'zoom-center-top'\n | 'zoom-center-bottom'\n | 'zoom-center-left'\n | 'zoom-center-right'\n | 'zoom-top-start'\n | 'zoom-top'\n | 'zoom-top-end'\n | 'zoom-bottom-start'\n | 'zoom-bottom'\n | 'zoom-bottom-end'\n | 'zoom-left-start'\n | 'zoom-left'\n | 'zoom-left-end'\n | 'zoom-right-start'\n | 'zoom-right'\n | 'zoom-right-end'\n | 'slide-up'\n | 'slide-down';\n\nexport type TransitionProps = {\n in?: boolean;\n timeout?: number | { enter: number; exit: number };\n appear?: boolean;\n unmountOnExit?: boolean;\n mountOnEnter?: boolean;\n\n /** Animation prefix */\n prefix?: string;\n\n /** Preset animation name */\n animation?: AnimationName;\n\n /** Custom class name base (overrides prefix + animation) */\n classNames?: string;\n\n /** Prevent the transition conflict with the inner component */\n wrapper?: boolean;\n\n nodeRef?: React.RefObject<HTMLElement | null>;\n\n onEnter?: () => void;\n onEntering?: () => void;\n onEntered?: () => void;\n onExit?: () => void;\n onExiting?: () => void;\n onExited?: () => void;\n\n children?: React.ReactNode;\n};\n\nfunction getTransitionClasses(base: string, state: TransitionState): string {\n switch (state) {\n case 'enter':\n return `${base}-enter`;\n case 'entering':\n return `${base}-enter ${base}-enter-active`;\n case 'entered':\n return `${base}-enter-done`;\n case 'exit':\n return `${base}-exit`;\n case 'exiting':\n return `${base}-exit ${base}-exit-active`;\n case 'exited':\n return `${base}-exit-done`;\n default:\n return '';\n }\n}\n\nconst Transition = (props: TransitionProps): React.ReactElement | null => {\n const {\n in: inProp = false,\n timeout = 300,\n unmountOnExit = true,\n mountOnEnter,\n appear = true,\n prefix = 'ty',\n animation,\n classNames: classNamesProp,\n nodeRef,\n children,\n wrapper,\n onEnter,\n onEntering,\n onEntered,\n onExit,\n onExiting,\n onExited,\n } = props;\n\n const { state, shouldMount } = useTransition({\n in: inProp,\n timeout,\n appear,\n unmountOnExit,\n mountOnEnter,\n onEnter,\n onEntering,\n onEntered,\n onExit,\n onExiting,\n onExited,\n nodeRef,\n });\n\n if (!shouldMount) {\n return null;\n }\n\n const base = classNamesProp ? classNamesProp : `${prefix}-${animation}`;\n const transitionClasses = getTransitionClasses(base, state);\n\n const child = wrapper ? <div>{children}</div> : children;\n\n if (React.isValidElement(child)) {\n const existingClassName = (child.props as { className?: string }).className || '';\n const mergedClassName = existingClassName\n ? `${existingClassName} ${transitionClasses}`.trim()\n : transitionClasses;\n\n return React.cloneElement(child as React.ReactElement<{ className?: string }>, {\n className: mergedClassName || undefined,\n });\n }\n\n return child as React.ReactElement;\n};\n\nTransition.displayName = 'Transition';\n\nexport default Transition;\n"],"mappings":";;;;AAsDA,SAAS,qBAAqB,MAAc,OAAgC;AAC1E,SAAQ,OAAR;EACE,KAAK,QACH,QAAO,GAAG,KAAK;EACjB,KAAK,WACH,QAAO,GAAG,KAAK,SAAS,KAAK;EAC/B,KAAK,UACH,QAAO,GAAG,KAAK;EACjB,KAAK,OACH,QAAO,GAAG,KAAK;EACjB,KAAK,UACH,QAAO,GAAG,KAAK,QAAQ,KAAK;EAC9B,KAAK,SACH,QAAO,GAAG,KAAK;EACjB,QACE,QAAO;;;AAIb,MAAM,cAAc,UAAsD;CACxE,MAAM,EACJ,IAAI,SAAS,OACb,UAAU,KACV,gBAAgB,MAChB,cACA,SAAS,MACT,SAAS,MACT,WACA,YAAY,gBACZ,SACA,UACA,SACA,SACA,YACA,WACA,QACA,WACA,aACE;CAEJ,MAAM,EAAE,OAAO,gBAAgB,cAAc;EAC3C,IAAI;EACJ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;AAEF,KAAI,CAAC,YACH,QAAO;CAIT,MAAM,oBAAoB,qBADb,iBAAiB,iBAAiB,GAAG,OAAO,GAAG,aACP,MAAM;CAE3D,MAAM,QAAQ,UAAU,oBAAC,OAAD,EAAM,UAAe,CAAA,GAAG;AAEhD,KAAI,MAAM,eAAe,MAAM,EAAE;EAC/B,MAAM,oBAAqB,MAAM,MAAiC,aAAa;EAC/E,MAAM,kBAAkB,oBACpB,GAAG,kBAAkB,GAAG,oBAAoB,MAAM,GAClD;AAEJ,SAAO,MAAM,aAAa,OAAqD,EAC7E,WAAW,mBAAmB,KAAA,GAC/B,CAAC;;AAGJ,QAAO;;AAGT,WAAW,cAAc"}
|