@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
|
@@ -10,6 +10,11 @@ let classnames = require("classnames");
|
|
|
10
10
|
classnames = require_runtime.__toESM(classnames);
|
|
11
11
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
12
12
|
//#region src/time-picker/time-picker.tsx
|
|
13
|
+
const EMPTY_PENDING = {
|
|
14
|
+
h: null,
|
|
15
|
+
m: null,
|
|
16
|
+
s: null
|
|
17
|
+
};
|
|
13
18
|
function formatTime(date, format, use12Hours) {
|
|
14
19
|
let h = date.getHours();
|
|
15
20
|
const m = String(date.getMinutes()).padStart(2, "0");
|
|
@@ -37,6 +42,7 @@ const TimePicker = (props) => {
|
|
|
37
42
|
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;
|
|
38
43
|
const prefixCls = require_general.getPrefixCls("time-picker", (0, react.useContext)(require_config_context.ConfigContext).prefixCls, customisedCls);
|
|
39
44
|
const [date, setDate] = (0, react.useState)(value ?? defaultValue ?? null);
|
|
45
|
+
const [pending, setPending] = (0, react.useState)(EMPTY_PENDING);
|
|
40
46
|
const [open, setOpen] = (0, react.useState)(false);
|
|
41
47
|
const wrapperRef = (0, react.useRef)(null);
|
|
42
48
|
const dropdownRef = (0, react.useRef)(null);
|
|
@@ -53,6 +59,7 @@ const TimePicker = (props) => {
|
|
|
53
59
|
if (wrapperRef.current?.contains(target) || dropdownRef.current?.contains(target)) return;
|
|
54
60
|
if (controlledOpen === void 0) setOpen(false);
|
|
55
61
|
onOpenChange?.(false);
|
|
62
|
+
setPending(EMPTY_PENDING);
|
|
56
63
|
};
|
|
57
64
|
document.addEventListener("click", listener);
|
|
58
65
|
return () => document.removeEventListener("click", listener);
|
|
@@ -60,43 +67,51 @@ const TimePicker = (props) => {
|
|
|
60
67
|
const toggleOpen = (0, react.useCallback)((val) => {
|
|
61
68
|
if (controlledOpen === void 0) setOpen(val);
|
|
62
69
|
onOpenChange?.(val);
|
|
70
|
+
if (!val) setPending(EMPTY_PENDING);
|
|
63
71
|
}, [controlledOpen, onOpenChange]);
|
|
64
|
-
|
|
72
|
+
/** Build a Date from committed date + pending overrides */
|
|
73
|
+
const buildDate = (0, react.useCallback)((p) => {
|
|
65
74
|
const base = date ? new Date(date) : new Date(0, 0, 0, 0, 0, 0, 0);
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
if (p.h !== null) base.setHours(p.h);
|
|
76
|
+
if (p.m !== null) base.setMinutes(p.m);
|
|
77
|
+
if (p.s !== null) base.setSeconds(p.s);
|
|
78
|
+
return base;
|
|
79
|
+
}, [date]);
|
|
80
|
+
const updatePending = (0, react.useCallback)((type, num) => {
|
|
81
|
+
setPending((prev) => ({
|
|
82
|
+
...prev,
|
|
83
|
+
[type]: num
|
|
84
|
+
}));
|
|
85
|
+
}, []);
|
|
86
|
+
const commit = (0, react.useCallback)((newDate) => {
|
|
87
|
+
if (value === void 0) setDate(newDate);
|
|
88
|
+
onChange?.(newDate);
|
|
89
|
+
setPending(EMPTY_PENDING);
|
|
90
|
+
}, [value, onChange]);
|
|
76
91
|
const handleClear = (e) => {
|
|
77
92
|
e.stopPropagation();
|
|
78
93
|
if (value === void 0) setDate(null);
|
|
79
94
|
onChange?.(null);
|
|
95
|
+
setPending(EMPTY_PENDING);
|
|
80
96
|
toggleOpen(false);
|
|
81
97
|
};
|
|
82
98
|
const handleNow = () => {
|
|
83
|
-
|
|
84
|
-
if (value === void 0) setDate(now);
|
|
85
|
-
onChange?.(now);
|
|
99
|
+
commit(/* @__PURE__ */ new Date());
|
|
86
100
|
toggleOpen(false);
|
|
87
101
|
};
|
|
88
102
|
const handleOk = () => {
|
|
103
|
+
if (pending.h !== null || pending.m !== null || pending.s !== null) commit(buildDate(pending));
|
|
89
104
|
toggleOpen(false);
|
|
90
105
|
};
|
|
106
|
+
const effectiveHour = pending.h ?? date?.getHours() ?? 0;
|
|
107
|
+
const effectiveMinute = pending.m ?? date?.getMinutes() ?? 0;
|
|
91
108
|
const disabled12 = (0, react.useMemo)(() => disabledTime?.() ?? {}, [disabledTime]);
|
|
92
109
|
const disabledHours = (0, react.useMemo)(() => disabled12.disabledHours?.() ?? [], [disabled12]);
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
const currentMinute = date?.getMinutes() ?? 0;
|
|
96
|
-
const disabledSeconds = (0, react.useMemo)(() => disabled12.disabledSeconds?.(currentHour, currentMinute) ?? [], [
|
|
110
|
+
const disabledMinutes = (0, react.useMemo)(() => disabled12.disabledMinutes?.(effectiveHour) ?? [], [disabled12, effectiveHour]);
|
|
111
|
+
const disabledSeconds = (0, react.useMemo)(() => disabled12.disabledSeconds?.(effectiveHour, effectiveMinute) ?? [], [
|
|
97
112
|
disabled12,
|
|
98
|
-
|
|
99
|
-
|
|
113
|
+
effectiveHour,
|
|
114
|
+
effectiveMinute
|
|
100
115
|
]);
|
|
101
116
|
const hours = generateSteps(24, hourStep);
|
|
102
117
|
const minutes = generateSteps(60, minuteStep);
|
|
@@ -104,12 +119,15 @@ const TimePicker = (props) => {
|
|
|
104
119
|
const filteredHours = hideDisabledOptions ? hours.filter((h) => !disabledHours.includes(h)) : hours;
|
|
105
120
|
const filteredMinutes = hideDisabledOptions ? minutes.filter((m) => !disabledMinutes.includes(m)) : minutes;
|
|
106
121
|
const filteredSeconds = hideDisabledOptions ? seconds.filter((s) => !disabledSeconds.includes(s)) : seconds;
|
|
107
|
-
const
|
|
108
|
-
const
|
|
122
|
+
const hasPending = pending.h !== null || pending.m !== null || pending.s !== null;
|
|
123
|
+
const effectiveDate = (hasPending ? buildDate(pending) : null) ?? date;
|
|
124
|
+
const hasValue = effectiveDate !== null;
|
|
125
|
+
const displayValue = hasValue ? formatTime(effectiveDate, format, use12Hours) : "";
|
|
109
126
|
const cls = (0, classnames.default)(prefixCls, className, `${prefixCls}_${size}`, {
|
|
110
127
|
[`${prefixCls}_disabled`]: disabled,
|
|
111
128
|
[`${prefixCls}_open`]: isOpen,
|
|
112
|
-
[`${prefixCls}_has-value`]: hasValue
|
|
129
|
+
[`${prefixCls}_has-value`]: hasValue,
|
|
130
|
+
[`${prefixCls}_pending`]: hasPending
|
|
113
131
|
});
|
|
114
132
|
const renderOverlay = () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
115
133
|
className: `${prefixCls}__dropdown`,
|
|
@@ -119,27 +137,30 @@ const TimePicker = (props) => {
|
|
|
119
137
|
children: [
|
|
120
138
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_time_panel.default, {
|
|
121
139
|
prefixCls,
|
|
122
|
-
value: date?.getHours() ??
|
|
140
|
+
value: date?.getHours() ?? null,
|
|
141
|
+
pendingValue: pending.h,
|
|
123
142
|
items: filteredHours,
|
|
124
143
|
disabledItems: hideDisabledOptions ? [] : disabledHours,
|
|
125
144
|
loop,
|
|
126
|
-
onChange: (h) =>
|
|
145
|
+
onChange: (h) => updatePending("h", h)
|
|
127
146
|
}),
|
|
128
147
|
showsMinutes(format) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_time_panel.default, {
|
|
129
148
|
prefixCls,
|
|
130
|
-
value: date?.getMinutes() ??
|
|
149
|
+
value: date?.getMinutes() ?? null,
|
|
150
|
+
pendingValue: pending.m,
|
|
131
151
|
items: filteredMinutes,
|
|
132
152
|
disabledItems: hideDisabledOptions ? [] : disabledMinutes,
|
|
133
153
|
loop,
|
|
134
|
-
onChange: (m) =>
|
|
154
|
+
onChange: (m) => updatePending("m", m)
|
|
135
155
|
}),
|
|
136
156
|
showsSeconds(format) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_time_panel.default, {
|
|
137
157
|
prefixCls,
|
|
138
|
-
value: date?.getSeconds() ??
|
|
158
|
+
value: date?.getSeconds() ?? null,
|
|
159
|
+
pendingValue: pending.s,
|
|
139
160
|
items: filteredSeconds,
|
|
140
161
|
disabledItems: hideDisabledOptions ? [] : disabledSeconds,
|
|
141
162
|
loop,
|
|
142
|
-
onChange: (s) =>
|
|
163
|
+
onChange: (s) => updatePending("s", s)
|
|
143
164
|
})
|
|
144
165
|
]
|
|
145
166
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-picker.js","names":["useLocale","getPrefixCls","ConfigContext","TimePanel","Popup","ClearIcon","ClockIcon"],"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":["useLocale","getPrefixCls","ConfigContext","TimePanel","Popup","ClearIcon","ClockIcon"],"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/lib/transition/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["Transition"],"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":["Transition"],"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,gDAAeA"}
|
|
@@ -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,20 +1,45 @@
|
|
|
1
1
|
const require_runtime = require("../_virtual/_rolldown/runtime.js");
|
|
2
|
+
const require_use_transition = require("./use-transition.js");
|
|
2
3
|
let react = require("react");
|
|
3
4
|
react = require_runtime.__toESM(react);
|
|
4
5
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
|
-
let react_transition_group = require("react-transition-group");
|
|
6
6
|
//#region src/transition/transition.tsx
|
|
7
|
+
function getTransitionClasses(base, state) {
|
|
8
|
+
switch (state) {
|
|
9
|
+
case "enter": return `${base}-enter`;
|
|
10
|
+
case "entering": return `${base}-enter ${base}-enter-active`;
|
|
11
|
+
case "entered": return `${base}-enter-done`;
|
|
12
|
+
case "exit": return `${base}-exit`;
|
|
13
|
+
case "exiting": return `${base}-exit ${base}-exit-active`;
|
|
14
|
+
case "exited": return `${base}-exit-done`;
|
|
15
|
+
default: return "";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
7
18
|
const Transition = (props) => {
|
|
8
|
-
const { timeout = 300, unmountOnExit = true, appear = true, prefix = "ty", animation, classNames, nodeRef, children, wrapper,
|
|
9
|
-
|
|
10
|
-
|
|
19
|
+
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;
|
|
20
|
+
const { state, shouldMount } = require_use_transition.default({
|
|
21
|
+
in: inProp,
|
|
11
22
|
timeout,
|
|
12
23
|
appear,
|
|
13
24
|
unmountOnExit,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
25
|
+
mountOnEnter,
|
|
26
|
+
onEnter,
|
|
27
|
+
onEntering,
|
|
28
|
+
onEntered,
|
|
29
|
+
onExit,
|
|
30
|
+
onExiting,
|
|
31
|
+
onExited,
|
|
32
|
+
nodeRef
|
|
17
33
|
});
|
|
34
|
+
if (!shouldMount) return null;
|
|
35
|
+
const transitionClasses = getTransitionClasses(classNamesProp ? classNamesProp : `${prefix}-${animation}`, state);
|
|
36
|
+
const child = wrapper ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children }) : children;
|
|
37
|
+
if (react.default.isValidElement(child)) {
|
|
38
|
+
const existingClassName = child.props.className || "";
|
|
39
|
+
const mergedClassName = existingClassName ? `${existingClassName} ${transitionClasses}`.trim() : transitionClasses;
|
|
40
|
+
return react.default.cloneElement(child, { className: mergedClassName || void 0 });
|
|
41
|
+
}
|
|
42
|
+
return child;
|
|
18
43
|
};
|
|
19
44
|
Transition.displayName = "Transition";
|
|
20
45
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transition.js","names":["
|
|
1
|
+
{"version":3,"file":"transition.js","names":["useTransition","React"],"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,gBAAgBA,uBAAAA,QAAc;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,iBAAA,GAAA,kBAAA,KAAC,OAAD,EAAM,UAAe,CAAA,GAAG;AAEhD,KAAIC,MAAAA,QAAM,eAAe,MAAM,EAAE;EAC/B,MAAM,oBAAqB,MAAM,MAAiC,aAAa;EAC/E,MAAM,kBAAkB,oBACpB,GAAG,kBAAkB,GAAG,oBAAoB,MAAM,GAClD;AAEJ,SAAOA,MAAAA,QAAM,aAAa,OAAqD,EAC7E,WAAW,mBAAmB,KAAA,GAC/B,CAAC;;AAGJ,QAAO;;AAGT,WAAW,cAAc"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
require("../_virtual/_rolldown/runtime.js");
|
|
2
|
+
let react = require("react");
|
|
3
|
+
//#region src/transition/use-transition.ts
|
|
4
|
+
function normalizeTimeout(timeout) {
|
|
5
|
+
if (timeout == null) return {
|
|
6
|
+
enter: 300,
|
|
7
|
+
exit: 300
|
|
8
|
+
};
|
|
9
|
+
if (typeof timeout === "number") return {
|
|
10
|
+
enter: timeout,
|
|
11
|
+
exit: timeout
|
|
12
|
+
};
|
|
13
|
+
return timeout;
|
|
14
|
+
}
|
|
15
|
+
function useTransition(options) {
|
|
16
|
+
const { in: inProp, timeout, appear = true, unmountOnExit = true, mountOnEnter = false, onEnter, onEntering, onEntered, onExit, onExiting, onExited, nodeRef } = options;
|
|
17
|
+
const normalizedTimeout = normalizeTimeout(timeout);
|
|
18
|
+
const getInitialState = () => {
|
|
19
|
+
if (inProp) return appear ? "enter" : "entered";
|
|
20
|
+
if (unmountOnExit || mountOnEnter) return "unmounted";
|
|
21
|
+
return "exited";
|
|
22
|
+
};
|
|
23
|
+
const [state, setState] = (0, react.useState)(getInitialState);
|
|
24
|
+
const rafRef = (0, react.useRef)(0);
|
|
25
|
+
const timerRef = (0, react.useRef)(0);
|
|
26
|
+
const transitionEndRef = (0, react.useRef)(null);
|
|
27
|
+
const initialMountRef = (0, react.useRef)(true);
|
|
28
|
+
const callbacksRef = (0, react.useRef)({
|
|
29
|
+
onEnter,
|
|
30
|
+
onEntering,
|
|
31
|
+
onEntered,
|
|
32
|
+
onExit,
|
|
33
|
+
onExiting,
|
|
34
|
+
onExited
|
|
35
|
+
});
|
|
36
|
+
callbacksRef.current = {
|
|
37
|
+
onEnter,
|
|
38
|
+
onEntering,
|
|
39
|
+
onEntered,
|
|
40
|
+
onExit,
|
|
41
|
+
onExiting,
|
|
42
|
+
onExited
|
|
43
|
+
};
|
|
44
|
+
const cleanup = (0, react.useCallback)(() => {
|
|
45
|
+
if (rafRef.current) {
|
|
46
|
+
cancelAnimationFrame(rafRef.current);
|
|
47
|
+
rafRef.current = 0;
|
|
48
|
+
}
|
|
49
|
+
if (timerRef.current) {
|
|
50
|
+
clearTimeout(timerRef.current);
|
|
51
|
+
timerRef.current = 0;
|
|
52
|
+
}
|
|
53
|
+
if (transitionEndRef.current && nodeRef?.current) {
|
|
54
|
+
nodeRef.current.removeEventListener("transitionend", transitionEndRef.current);
|
|
55
|
+
transitionEndRef.current = null;
|
|
56
|
+
}
|
|
57
|
+
}, [nodeRef]);
|
|
58
|
+
const waitForTransition = (0, react.useCallback)((phase, done) => {
|
|
59
|
+
const safetyDuration = phase === "enter" ? normalizedTimeout.enter : normalizedTimeout.exit;
|
|
60
|
+
if (safetyDuration === 0) {
|
|
61
|
+
done();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const finish = () => {
|
|
65
|
+
cleanup();
|
|
66
|
+
done();
|
|
67
|
+
};
|
|
68
|
+
const node = nodeRef?.current;
|
|
69
|
+
if (node) {
|
|
70
|
+
const handler = (e) => {
|
|
71
|
+
if (e.target === node) finish();
|
|
72
|
+
};
|
|
73
|
+
transitionEndRef.current = handler;
|
|
74
|
+
node.addEventListener("transitionend", handler);
|
|
75
|
+
}
|
|
76
|
+
timerRef.current = window.setTimeout(finish, safetyDuration + 50);
|
|
77
|
+
}, [
|
|
78
|
+
cleanup,
|
|
79
|
+
nodeRef,
|
|
80
|
+
normalizedTimeout.enter,
|
|
81
|
+
normalizedTimeout.exit
|
|
82
|
+
]);
|
|
83
|
+
(0, react.useLayoutEffect)(() => {
|
|
84
|
+
if (state === "enter") {
|
|
85
|
+
callbacksRef.current.onEnter?.();
|
|
86
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
87
|
+
setState("entering");
|
|
88
|
+
callbacksRef.current.onEntering?.();
|
|
89
|
+
waitForTransition("enter", () => {
|
|
90
|
+
setState("entered");
|
|
91
|
+
callbacksRef.current.onEntered?.();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}, [state]);
|
|
96
|
+
(0, react.useLayoutEffect)(() => {
|
|
97
|
+
if (state === "exit") {
|
|
98
|
+
callbacksRef.current.onExit?.();
|
|
99
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
100
|
+
setState("exiting");
|
|
101
|
+
callbacksRef.current.onExiting?.();
|
|
102
|
+
waitForTransition("exit", () => {
|
|
103
|
+
setState((prev) => {
|
|
104
|
+
if (prev === "exiting") {
|
|
105
|
+
callbacksRef.current.onExited?.();
|
|
106
|
+
return unmountOnExit ? "unmounted" : "exited";
|
|
107
|
+
}
|
|
108
|
+
return prev;
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}, [state]);
|
|
114
|
+
(0, react.useEffect)(() => {
|
|
115
|
+
if (initialMountRef.current) {
|
|
116
|
+
initialMountRef.current = false;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (inProp) {
|
|
120
|
+
cleanup();
|
|
121
|
+
setState("enter");
|
|
122
|
+
} else {
|
|
123
|
+
cleanup();
|
|
124
|
+
setState("exit");
|
|
125
|
+
}
|
|
126
|
+
}, [inProp]);
|
|
127
|
+
(0, react.useEffect)(() => {
|
|
128
|
+
return cleanup;
|
|
129
|
+
}, [cleanup]);
|
|
130
|
+
return {
|
|
131
|
+
state,
|
|
132
|
+
shouldMount: state !== "unmounted"
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
exports.default = useTransition;
|
|
137
|
+
|
|
138
|
+
//# sourceMappingURL=use-transition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-transition.js","names":[],"sources":["../../src/transition/use-transition.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\n\nexport type TransitionState =\n | 'unmounted'\n | 'enter'\n | 'entering'\n | 'entered'\n | 'exit'\n | 'exiting'\n | 'exited';\n\nexport interface UseTransitionOptions {\n in: boolean;\n timeout?: number | { enter: number; exit: number };\n appear?: boolean;\n unmountOnExit?: boolean;\n mountOnEnter?: boolean;\n onEnter?: () => void;\n onEntering?: () => void;\n onEntered?: () => void;\n onExit?: () => void;\n onExiting?: () => void;\n onExited?: () => void;\n nodeRef?: React.RefObject<HTMLElement | null>;\n}\n\nexport interface UseTransitionResult {\n state: TransitionState;\n shouldMount: boolean;\n}\n\nfunction normalizeTimeout(\n timeout: number | { enter: number; exit: number } | undefined\n): { enter: number; exit: number } {\n if (timeout == null) return { enter: 300, exit: 300 };\n if (typeof timeout === 'number') return { enter: timeout, exit: timeout };\n return timeout;\n}\n\nfunction useTransition(options: UseTransitionOptions): UseTransitionResult {\n const {\n in: inProp,\n timeout,\n appear = true,\n unmountOnExit = true,\n mountOnEnter = false,\n onEnter,\n onEntering,\n onEntered,\n onExit,\n onExiting,\n onExited,\n nodeRef,\n } = options;\n\n const normalizedTimeout = normalizeTimeout(timeout);\n\n // Determine initial state\n const getInitialState = (): TransitionState => {\n if (inProp) {\n return appear ? 'enter' : 'entered';\n }\n if (unmountOnExit || mountOnEnter) {\n return 'unmounted';\n }\n return 'exited';\n };\n\n const [state, setState] = useState<TransitionState>(getInitialState);\n const rafRef = useRef<number>(0);\n const timerRef = useRef<number>(0);\n const transitionEndRef = useRef<(() => void) | null>(null);\n const initialMountRef = useRef(true);\n\n // Store latest callbacks in refs to avoid re-triggering effects\n const callbacksRef = useRef({\n onEnter,\n onEntering,\n onEntered,\n onExit,\n onExiting,\n onExited,\n });\n callbacksRef.current = {\n onEnter,\n onEntering,\n onEntered,\n onExit,\n onExiting,\n onExited,\n };\n\n const cleanup = useCallback(() => {\n if (rafRef.current) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = 0;\n }\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = 0;\n }\n if (transitionEndRef.current && nodeRef?.current) {\n nodeRef.current.removeEventListener('transitionend', transitionEndRef.current);\n transitionEndRef.current = null;\n }\n }, [nodeRef]);\n\n const waitForTransition = useCallback(\n (phase: 'enter' | 'exit', done: () => void) => {\n const safetyDuration =\n phase === 'enter' ? normalizedTimeout.enter : normalizedTimeout.exit;\n\n // timeout=0 means \"don't wait\" — advance immediately.\n // This matches react-transition-group's behavior where timeout=0\n // skips straight to the done state, letting CSS handle the animation\n // via the base element's transition property.\n if (safetyDuration === 0) {\n done();\n return;\n }\n\n const finish = () => {\n cleanup();\n done();\n };\n\n // Try transitionend listener first\n const node = nodeRef?.current;\n if (node) {\n const handler = (e: Event) => {\n if ((e as TransitionEvent).target === node) {\n finish();\n }\n };\n transitionEndRef.current = handler as () => void;\n node.addEventListener('transitionend', handler);\n }\n\n // Safety timeout fallback\n timerRef.current = window.setTimeout(finish, safetyDuration + 50);\n },\n [cleanup, nodeRef, normalizedTimeout.enter, normalizedTimeout.exit]\n );\n\n // Continue the enter animation after DOM is committed (state === 'enter').\n // useLayoutEffect fires synchronously after DOM mutations, guaranteeing\n // the child is mounted and refs are populated before onEnter runs.\n useLayoutEffect(() => {\n if (state === 'enter') {\n callbacksRef.current.onEnter?.();\n\n // Single rAF: useLayoutEffect runs before paint, so one rAF is enough\n // to ensure the browser has painted the -enter class before we add -enter-active.\n rafRef.current = requestAnimationFrame(() => {\n setState('entering');\n callbacksRef.current.onEntering?.();\n\n waitForTransition('enter', () => {\n setState('entered');\n callbacksRef.current.onEntered?.();\n });\n });\n }\n }, [state]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Continue the exit animation after DOM reflects exit state\n useLayoutEffect(() => {\n if (state === 'exit') {\n callbacksRef.current.onExit?.();\n\n rafRef.current = requestAnimationFrame(() => {\n setState('exiting');\n callbacksRef.current.onExiting?.();\n\n waitForTransition('exit', () => {\n setState((prev) => {\n if (prev === 'exiting') {\n callbacksRef.current.onExited?.();\n return unmountOnExit ? 'unmounted' : 'exited';\n }\n return prev;\n });\n });\n });\n }\n }, [state]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // React to `in` prop changes — only set the initial phase state.\n // The useLayoutEffect above handles the rest after DOM commit.\n useEffect(() => {\n if (initialMountRef.current) {\n initialMountRef.current = false;\n // On initial mount with appear=true, state is already 'enter' from getInitialState,\n // and the useLayoutEffect above will pick it up.\n return;\n }\n\n if (inProp) {\n cleanup();\n setState('enter');\n } else {\n cleanup();\n setState('exit');\n }\n }, [inProp]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Cleanup on unmount\n useEffect(() => {\n return cleanup;\n }, [cleanup]);\n\n const shouldMount = state !== 'unmounted';\n\n return { state, shouldMount };\n}\n\nexport default useTransition;\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const require_runtime = require("../_virtual/_rolldown/runtime.js");
|
|
2
2
|
const require_config_context = require("../config-provider/config-context.js");
|
|
3
3
|
const require_general = require("../_utils/general.js");
|
|
4
|
+
const require_index = require("../transition/index.js");
|
|
4
5
|
const require_use_breakpoint = require("./hooks/use-breakpoint.js");
|
|
5
6
|
const require_use_positions = require("./hooks/use-positions.js");
|
|
6
7
|
let react = require("react");
|
|
@@ -8,7 +9,6 @@ react = require_runtime.__toESM(react);
|
|
|
8
9
|
let classnames = require("classnames");
|
|
9
10
|
classnames = require_runtime.__toESM(classnames);
|
|
10
11
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
11
|
-
let react_transition_group = require("react-transition-group");
|
|
12
12
|
//#region src/waterfall/waterfall.tsx
|
|
13
13
|
const Waterfall = react.default.forwardRef((props, ref) => {
|
|
14
14
|
const { prefixCls: customisedCls, className, style, columns = 3, gutter = 0, items, itemRender, onLayoutChange, ...otherProps } = props;
|
|
@@ -72,6 +72,31 @@ const Waterfall = react.default.forwardRef((props, ref) => {
|
|
|
72
72
|
items,
|
|
73
73
|
onLayoutChange
|
|
74
74
|
]);
|
|
75
|
+
const prevItemsRef = (0, react.useRef)(items || []);
|
|
76
|
+
const [exitingItems, setExitingItems] = (0, react.useState)(/* @__PURE__ */ new Map());
|
|
77
|
+
(0, react.useEffect)(() => {
|
|
78
|
+
const currentKeys = new Set((items || []).map((item, i) => item.key ?? i));
|
|
79
|
+
const removed = /* @__PURE__ */ new Map();
|
|
80
|
+
prevItemsRef.current.forEach((item, index) => {
|
|
81
|
+
const key = item.key ?? index;
|
|
82
|
+
if (!currentKeys.has(key)) removed.set(key, item);
|
|
83
|
+
});
|
|
84
|
+
if (removed.size > 0) setExitingItems((prev) => {
|
|
85
|
+
const next = new Map(prev);
|
|
86
|
+
removed.forEach((item, key) => next.set(key, item));
|
|
87
|
+
return next;
|
|
88
|
+
});
|
|
89
|
+
prevItemsRef.current = items || [];
|
|
90
|
+
}, [items]);
|
|
91
|
+
const handleExited = (0, react.useCallback)((key) => {
|
|
92
|
+
itemRefsMap.current.delete(key);
|
|
93
|
+
setExitingItems((prev) => {
|
|
94
|
+
const next = new Map(prev);
|
|
95
|
+
next.delete(key);
|
|
96
|
+
return next;
|
|
97
|
+
});
|
|
98
|
+
collectItemSizes();
|
|
99
|
+
}, [collectItemSizes]);
|
|
75
100
|
const cls = (0, classnames.default)(prefixCls, className);
|
|
76
101
|
const containerStyle = {
|
|
77
102
|
...style,
|
|
@@ -79,49 +104,47 @@ const Waterfall = react.default.forwardRef((props, ref) => {
|
|
|
79
104
|
height: totalHeight || void 0
|
|
80
105
|
};
|
|
81
106
|
const mergedItems = items || [];
|
|
82
|
-
|
|
107
|
+
const renderItem = (item, index, isExiting) => {
|
|
108
|
+
const key = item.key ?? index;
|
|
109
|
+
const position = itemPositions.get(key);
|
|
110
|
+
const hasPosition = !!position;
|
|
111
|
+
const columnIndex = position?.column ?? 0;
|
|
112
|
+
const itemStyle = {
|
|
113
|
+
position: "absolute",
|
|
114
|
+
width: `calc((100% - ${horizontalGutter * (columnCount - 1)}px) / ${columnCount})`,
|
|
115
|
+
left: `calc((100% - ${horizontalGutter * (columnCount - 1)}px) / ${columnCount} * ${columnIndex} + ${horizontalGutter * columnIndex}px)`,
|
|
116
|
+
top: position?.top ?? 0,
|
|
117
|
+
transition: hasPosition ? "top 0.3s ease, left 0.3s ease, opacity 0.3s ease" : "none",
|
|
118
|
+
opacity: hasPosition ? 1 : 0
|
|
119
|
+
};
|
|
120
|
+
const content = item.children ?? itemRender?.({
|
|
121
|
+
...item,
|
|
122
|
+
index,
|
|
123
|
+
column: columnIndex
|
|
124
|
+
});
|
|
125
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_index.default, {
|
|
126
|
+
in: !isExiting,
|
|
127
|
+
timeout: 300,
|
|
128
|
+
appear: false,
|
|
129
|
+
unmountOnExit: true,
|
|
130
|
+
classNames: `${prefixCls}__item-fade`,
|
|
131
|
+
onExited: () => handleExited(key),
|
|
132
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
133
|
+
ref: (el) => setItemRef(key, el),
|
|
134
|
+
className: `${prefixCls}__item`,
|
|
135
|
+
style: itemStyle,
|
|
136
|
+
children: content
|
|
137
|
+
})
|
|
138
|
+
}, key);
|
|
139
|
+
};
|
|
140
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
83
141
|
ref,
|
|
84
142
|
...otherProps,
|
|
85
143
|
className: cls,
|
|
86
144
|
style: containerStyle,
|
|
87
145
|
onLoad: collectItemSizes,
|
|
88
146
|
onError: collectItemSizes,
|
|
89
|
-
children:
|
|
90
|
-
component: null,
|
|
91
|
-
children: mergedItems.map((item, index) => {
|
|
92
|
-
const key = item.key ?? index;
|
|
93
|
-
const position = itemPositions.get(key);
|
|
94
|
-
const hasPosition = !!position;
|
|
95
|
-
const columnIndex = position?.column ?? 0;
|
|
96
|
-
const itemStyle = {
|
|
97
|
-
position: "absolute",
|
|
98
|
-
width: `calc((100% - ${horizontalGutter * (columnCount - 1)}px) / ${columnCount})`,
|
|
99
|
-
left: `calc((100% - ${horizontalGutter * (columnCount - 1)}px) / ${columnCount} * ${columnIndex} + ${horizontalGutter * columnIndex}px)`,
|
|
100
|
-
top: position?.top ?? 0,
|
|
101
|
-
transition: hasPosition ? "top 0.3s ease, left 0.3s ease, opacity 0.3s ease" : "none",
|
|
102
|
-
opacity: hasPosition ? 1 : 0
|
|
103
|
-
};
|
|
104
|
-
const content = item.children ?? itemRender?.({
|
|
105
|
-
...item,
|
|
106
|
-
index,
|
|
107
|
-
column: columnIndex
|
|
108
|
-
});
|
|
109
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_transition_group.CSSTransition, {
|
|
110
|
-
timeout: 300,
|
|
111
|
-
classNames: `${prefixCls}__item-fade`,
|
|
112
|
-
onExited: () => {
|
|
113
|
-
itemRefsMap.current.delete(key);
|
|
114
|
-
collectItemSizes();
|
|
115
|
-
},
|
|
116
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
117
|
-
ref: (el) => setItemRef(key, el),
|
|
118
|
-
className: `${prefixCls}__item`,
|
|
119
|
-
style: itemStyle,
|
|
120
|
-
children: content
|
|
121
|
-
})
|
|
122
|
-
}, key);
|
|
123
|
-
})
|
|
124
|
-
})
|
|
147
|
+
children: [mergedItems.map((item, index) => renderItem(item, index, false)), Array.from(exitingItems.entries()).map(([key, item]) => renderItem(item, Number(key), true))]
|
|
125
148
|
});
|
|
126
149
|
});
|
|
127
150
|
Waterfall.displayName = "Waterfall";
|