clxx 2.1.7 → 3.0.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.
Files changed (75) hide show
  1. package/AGENTS.md +2 -1
  2. package/README.md +147 -22
  3. package/build/Alert/Wrapper.js +12 -14
  4. package/build/Alert/style.js +44 -25
  5. package/build/AutoGrid/index.js +21 -15
  6. package/build/CarouselNotice/index.d.ts +19 -11
  7. package/build/CarouselNotice/index.js +80 -74
  8. package/build/CarouselNotice/style.js +14 -4
  9. package/build/CitySelect/index.js +81 -71
  10. package/build/CitySelect/style.js +22 -56
  11. package/build/Clickable/index.js +7 -0
  12. package/build/Container/index.d.ts +12 -4
  13. package/build/Container/index.js +94 -89
  14. package/build/Countdowner/index.js +4 -2
  15. package/build/DatePicker/Column.d.ts +9 -0
  16. package/build/DatePicker/Column.js +330 -0
  17. package/build/DatePicker/index.d.ts +32 -0
  18. package/build/DatePicker/index.js +230 -0
  19. package/build/DatePicker/style.d.ts +6 -0
  20. package/build/DatePicker/style.js +130 -0
  21. package/build/Dialog/Wrapper.d.ts +0 -1
  22. package/build/Dialog/Wrapper.js +22 -12
  23. package/build/Dialog/index.d.ts +7 -1
  24. package/build/Dialog/index.js +57 -32
  25. package/build/Dialog/style.js +6 -2
  26. package/build/Effect/useInterval.js +6 -3
  27. package/build/Fixed/index.js +13 -22
  28. package/build/Flex/FlexItem.d.ts +11 -0
  29. package/build/Flex/FlexItem.js +26 -0
  30. package/build/Flex/index.d.ts +2 -10
  31. package/build/Flex/index.js +12 -22
  32. package/build/Indicator/index.d.ts +9 -6
  33. package/build/Indicator/index.js +34 -37
  34. package/build/Indicator/style.d.ts +4 -3
  35. package/build/Indicator/style.js +8 -13
  36. package/build/Loading/Wrapper.js +2 -1
  37. package/build/Loading/style.js +9 -12
  38. package/build/Overlay/index.js +6 -1
  39. package/build/RegionPicker/data.d.ts +6 -0
  40. package/build/RegionPicker/data.js +14486 -0
  41. package/build/RegionPicker/index.d.ts +33 -0
  42. package/build/RegionPicker/index.js +205 -0
  43. package/build/RegionPicker/style.d.ts +4 -0
  44. package/build/RegionPicker/style.js +187 -0
  45. package/build/SafeArea/index.js +14 -17
  46. package/build/ScrollView/index.d.ts +23 -11
  47. package/build/ScrollView/index.js +132 -118
  48. package/build/ScrollView/style.d.ts +1 -1
  49. package/build/ScrollView/style.js +33 -22
  50. package/build/Toast/Toast.d.ts +0 -1
  51. package/build/Toast/Toast.js +6 -4
  52. package/build/Toast/style.d.ts +3 -10
  53. package/build/Toast/style.js +41 -45
  54. package/build/index.d.ts +3 -0
  55. package/build/index.js +7 -1
  56. package/build/utils/color.d.ts +5 -0
  57. package/build/utils/color.js +18 -0
  58. package/build/utils/dom.js +4 -3
  59. package/build/utils/theme.d.ts +2 -0
  60. package/build/utils/theme.js +7 -0
  61. package/package.json +1 -1
  62. package/test/src/date-picker/index.jsx +119 -0
  63. package/test/src/index/index.jsx +2 -0
  64. package/test/src/index.jsx +1 -0
  65. package/test/src/loading/index.jsx +2 -2
  66. package/test/src/region-picker/index.jsx +120 -0
  67. package/test/src/scrollview/BasicSection.jsx +56 -0
  68. package/test/src/scrollview/CustomLoadingSection.jsx +53 -0
  69. package/test/src/scrollview/HeightModeSection.jsx +42 -0
  70. package/test/src/scrollview/ImperativeSection.jsx +56 -0
  71. package/test/src/scrollview/NotScrollableSection.jsx +32 -0
  72. package/test/src/scrollview/PerfSection.jsx +34 -0
  73. package/test/src/scrollview/index.css +92 -8
  74. package/test/src/scrollview/index.jsx +13 -45
  75. package/test/src/toast/index.jsx +1 -0
@@ -11,30 +11,16 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  return t;
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.ScrollView = ScrollView;
14
+ exports.ScrollView = void 0;
15
15
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
16
16
  const react_1 = require("react");
17
- const Indicator_1 = require("../Indicator");
18
- const Row_1 = require("../Flex/Row");
19
17
  const style_1 = require("./style");
20
- function ScrollView(props) {
21
- const { children, height, reachTopThreshold = 50, onReachTop, reachBottomThreshold = 50, onReachBottom, showLoading = true, loadingContent, onScroll, scrollThrottle = 16, containerStyle, wrapperStyle, loadingStyle } = props, attrs = __rest(props, ["children", "height", "reachTopThreshold", "onReachTop", "reachBottomThreshold", "onReachBottom", "showLoading", "loadingContent", "onScroll", "scrollThrottle", "containerStyle", "wrapperStyle", "loadingStyle"]);
22
- // 容器高度
23
- const heightStyle = {};
24
- if (height) {
25
- heightStyle.height = height;
26
- }
27
- // 滚动容器
28
- const container = (0, react_1.useRef)(null);
29
- // 当前滚动到顶部的距离
30
- const lastScrollTop = (0, react_1.useRef)(0);
31
- // 防止重复触发的标记
32
- const hasReachedTop = (0, react_1.useRef)(false);
33
- const hasReachedBottom = (0, react_1.useRef)(false);
34
- // 节流控制
35
- const throttleTimer = (0, react_1.useRef)(undefined);
36
- const lastCallTime = (0, react_1.useRef)(0);
37
- // 使用 ref 保存所有滚动处理需要的 props,彻底消除陈旧闭包
18
+ exports.ScrollView = (0, react_1.forwardRef)(function ScrollView(props, ref) {
19
+ const { children, height, reachTopThreshold = 50, onReachTop, reachBottomThreshold = 50, onReachBottom, showLoading = true, loadingContent, onScroll, containerStyle, wrapperStyle, loadingStyle, style: userStyle } = props, attrs = __rest(props, ["children", "height", "reachTopThreshold", "onReachTop", "reachBottomThreshold", "onReachBottom", "showLoading", "loadingContent", "onScroll", "containerStyle", "wrapperStyle", "loadingStyle", "style"]);
20
+ // 滚动容器与内容包装层
21
+ const containerRef = (0, react_1.useRef)(null);
22
+ const wrapperRef = (0, react_1.useRef)(null);
23
+ // ref 持有最新的回调与阈值,处理函数引用稳定,避免 listener 反复绑定 / 闭包过期
38
24
  const propsRef = (0, react_1.useRef)({
39
25
  onScroll,
40
26
  onReachTop,
@@ -49,53 +35,37 @@ function ScrollView(props) {
49
35
  reachTopThreshold,
50
36
  reachBottomThreshold,
51
37
  };
52
- // container 是否有滚动条
53
- const [hasScrollBar, setHasScrollBar] = (0, react_1.useState)(false);
54
- // 检查是否有滚动条
55
- const checkScrollBar = (0, react_1.useCallback)(() => {
56
- if (container.current) {
57
- const hasScroll = container.current.scrollHeight > container.current.clientHeight;
58
- setHasScrollBar(hasScroll);
59
- }
60
- }, []);
61
- // 使用 ResizeObserver 监听内容高度变化
62
- (0, react_1.useLayoutEffect)(() => {
63
- const containerEl = container.current;
64
- if (!containerEl)
65
- return;
66
- // 初始检查
67
- checkScrollBar();
68
- // 使用 ResizeObserver 监听尺寸变化
69
- const resizeObserver = new ResizeObserver(() => {
70
- checkScrollBar();
71
- });
72
- // 观察容器和内容
73
- resizeObserver.observe(containerEl);
74
- if (containerEl.firstElementChild) {
75
- resizeObserver.observe(containerEl.firstElementChild);
76
- }
77
- return () => {
78
- resizeObserver.disconnect();
79
- };
80
- }, [checkScrollBar]);
81
- // 核心滚动处理逻辑
82
- // 所有外部值从 ref 读取,deps 为空,引用永远稳定,不存在闭包过期问题
38
+ // 上次 scrollTop(推断方向)
39
+ const lastScrollTopRef = (0, react_1.useRef)(0);
40
+ // 上次方向;delta==0 时沿用,避免水平滚动 / ResizeObserver / 浮点抖动误判
41
+ const lastDirectionRef = (0, react_1.useRef)("downward");
42
+ // 阈值边界防抖:避免在阈值带内反复触发
43
+ const reachedTopRef = (0, react_1.useRef)(false);
44
+ const reachedBottomRef = (0, react_1.useRef)(false);
45
+ // RAF 节流相关
46
+ const rafIdRef = (0, react_1.useRef)(null);
47
+ const pendingEventRef = (0, react_1.useRef)(null);
48
+ // 是否真的可滚动;用于决定是否显示底部 loading
49
+ const [scrollable, setScrollable] = (0, react_1.useState)(false);
50
+ // 真正处理一次滚动(始终从 DOM 读最新位置,避免依赖陈旧 event)
83
51
  const processScroll = (0, react_1.useCallback)((rawEvent) => {
84
- const box = container.current;
52
+ const box = containerRef.current;
85
53
  if (!box)
86
54
  return;
87
55
  const { onScroll, onReachTop, onReachBottom, reachTopThreshold, reachBottomThreshold, } = propsRef.current;
88
56
  const scrollTop = box.scrollTop;
89
57
  const contentHeight = box.scrollHeight;
90
- // clientHeight 即可视区域高度(不含 border),无需 Math.min(clientHeight, offsetHeight)
91
58
  const containerHeight = box.clientHeight;
92
- const maxScroll = contentHeight - containerHeight;
93
- // 防止零位移时误判方向(如内容变化触发的 scroll 事件)
94
- if (scrollTop === lastScrollTop.current && lastScrollTop.current !== 0) {
95
- return;
96
- }
97
- // scrollTop 增大 => 向下滚动;相等(初始 0→0)视为向下
98
- const direction = scrollTop >= lastScrollTop.current ? "downward" : "upward";
59
+ const maxScroll = Math.max(0, contentHeight - containerHeight);
60
+ const last = lastScrollTopRef.current;
61
+ const delta = scrollTop - last;
62
+ // 0.5 容差屏蔽 hi-DPI 浮点抖动;|delta|<=0.5 视为无方向变化,沿用上次
63
+ let direction = lastDirectionRef.current;
64
+ if (delta < -0.5)
65
+ direction = "upward";
66
+ else if (delta > 0.5)
67
+ direction = "downward";
68
+ lastDirectionRef.current = direction;
99
69
  const event = {
100
70
  containerHeight,
101
71
  contentHeight,
@@ -105,81 +75,125 @@ function ScrollView(props) {
105
75
  rawEvent,
106
76
  };
107
77
  onScroll === null || onScroll === void 0 ? void 0 : onScroll(event);
108
- // 触顶逻辑(防止重复触发)
78
+ // 触顶:仅在向上滚动且进入阈值带时触发一次
109
79
  if (direction === "upward" && scrollTop <= reachTopThreshold) {
110
- if (!hasReachedTop.current) {
111
- hasReachedTop.current = true;
112
- hasReachedBottom.current = false;
80
+ if (!reachedTopRef.current) {
81
+ reachedTopRef.current = true;
82
+ reachedBottomRef.current = false;
113
83
  onReachTop === null || onReachTop === void 0 ? void 0 : onReachTop(event);
114
84
  }
115
85
  }
116
86
  else if (scrollTop > reachTopThreshold) {
117
- hasReachedTop.current = false;
87
+ // 离开阈值带后允许下次再次触发
88
+ reachedTopRef.current = false;
118
89
  }
119
- // 触底逻辑(防止重复触发)
90
+ // 触底:仅在确实可滚动且向下滚动进入阈值带时触发一次
120
91
  if (direction === "downward" &&
121
92
  maxScroll > 0 &&
122
93
  scrollTop >= maxScroll - reachBottomThreshold) {
123
- if (!hasReachedBottom.current) {
124
- hasReachedBottom.current = true;
125
- hasReachedTop.current = false;
94
+ if (!reachedBottomRef.current) {
95
+ reachedBottomRef.current = true;
96
+ reachedTopRef.current = false;
126
97
  onReachBottom === null || onReachBottom === void 0 ? void 0 : onReachBottom(event);
127
98
  }
128
99
  }
129
100
  else if (scrollTop < maxScroll - reachBottomThreshold) {
130
- hasReachedBottom.current = false;
101
+ reachedBottomRef.current = false;
131
102
  }
132
- lastScrollTop.current = scrollTop;
103
+ lastScrollTopRef.current = scrollTop;
133
104
  }, []);
134
- // 节流滚动回调(leading + trailing)
135
- const scrollCallback = (0, react_1.useCallback)((rawEvent) => {
136
- // 不节流时直接执行
137
- if (scrollThrottle <= 0) {
138
- processScroll(rawEvent);
105
+ // RAF 节流:连续滚动期间一帧只处理一次,最后一次 scroll 也会被处理(pending 会触发)
106
+ const scheduleProcess = (0, react_1.useCallback)((rawEvent) => {
107
+ pendingEventRef.current = rawEvent;
108
+ if (rafIdRef.current !== null)
139
109
  return;
140
- }
141
- const now = Date.now();
142
- const elapsed = now - lastCallTime.current;
143
- if (elapsed >= scrollThrottle) {
144
- // 前沿立即执行
145
- lastCallTime.current = now;
146
- processScroll(rawEvent);
147
- // 消除挂起的尾部定时器
148
- if (throttleTimer.current !== undefined) {
149
- clearTimeout(throttleTimer.current);
150
- throttleTimer.current = undefined;
151
- }
152
- }
153
- else {
154
- // 尾部调用:按剩余时间调度,保证滚动停止后最终状态被处理
155
- if (throttleTimer.current !== undefined) {
156
- clearTimeout(throttleTimer.current);
157
- }
158
- throttleTimer.current = window.setTimeout(() => {
159
- lastCallTime.current = Date.now();
160
- throttleTimer.current = undefined;
161
- // 尾部调用不传 rawEvent(已过期),processScroll 从 DOM 读取实时位置
162
- processScroll();
163
- }, scrollThrottle - elapsed);
164
- }
165
- }, [scrollThrottle, processScroll]);
166
- // 清理节流定时器
110
+ rafIdRef.current = requestAnimationFrame(() => {
111
+ rafIdRef.current = null;
112
+ const ev = pendingEventRef.current;
113
+ pendingEventRef.current = null;
114
+ processScroll(ev !== null && ev !== void 0 ? ev : undefined);
115
+ });
116
+ }, [processScroll]);
117
+ // 直接绑定原生 scroll 事件(passive: true),避免 React 合成事件中介
167
118
  (0, react_1.useEffect)(() => {
119
+ const box = containerRef.current;
120
+ if (!box)
121
+ return;
122
+ // 用 DOM 当前位置初始化 lastScrollTop,兼容路由切回 / SSR 恢复滚动位置
123
+ lastScrollTopRef.current = box.scrollTop;
124
+ const handler = (e) => scheduleProcess(e);
125
+ box.addEventListener("scroll", handler, { passive: true });
168
126
  return () => {
169
- if (throttleTimer.current !== undefined) {
170
- clearTimeout(throttleTimer.current);
127
+ box.removeEventListener("scroll", handler);
128
+ if (rafIdRef.current !== null) {
129
+ cancelAnimationFrame(rafIdRef.current);
130
+ rafIdRef.current = null;
171
131
  }
132
+ pendingEventRef.current = null;
172
133
  };
134
+ }, [scheduleProcess]);
135
+ // 监听容器与内容尺寸变化,自动维护 scrollable
136
+ (0, react_1.useLayoutEffect)(() => {
137
+ const box = containerRef.current;
138
+ const wrap = wrapperRef.current;
139
+ if (!box || !wrap)
140
+ return;
141
+ const update = () => {
142
+ // +1 容差:屏蔽 hi-DPI 下 scrollHeight = clientHeight + 0.5 之类的误判
143
+ const next = box.scrollHeight - box.clientHeight > 1;
144
+ setScrollable((prev) => (prev === next ? prev : next));
145
+ };
146
+ update();
147
+ // 旧浏览器无 ResizeObserver 时降级:仅初始检测一次
148
+ if (typeof ResizeObserver === "undefined")
149
+ return;
150
+ const ro = new ResizeObserver(update);
151
+ ro.observe(box);
152
+ ro.observe(wrap);
153
+ return () => ro.disconnect();
173
154
  }, []);
174
- // loading 内容
175
- let showLoadingContent = null;
176
- if (showLoading) {
177
- if (!loadingContent) {
178
- showLoadingContent = ((0, jsx_runtime_1.jsxs)(Row_1.RowCenter, { css: [style_1.style.loading, loadingStyle], children: [(0, jsx_runtime_1.jsx)(Indicator_1.Indicator, { barColor: "#333", barCount: 12 }), (0, jsx_runtime_1.jsx)("p", { children: "\u6570\u636E\u52A0\u8F7D\u4E2D..." })] }));
179
- }
180
- else {
181
- showLoadingContent = loadingContent;
182
- }
183
- }
184
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: [style_1.style.container, heightStyle, containerStyle], onScroll: scrollCallback, ref: container }, attrs, { children: [(0, jsx_runtime_1.jsx)("div", { css: wrapperStyle, children: children }), hasScrollBar && showLoadingContent] })));
185
- }
155
+ // 暴露命令式 API
156
+ (0, react_1.useImperativeHandle)(ref, () => ({
157
+ getElement: () => containerRef.current,
158
+ scrollTo: ({ top, behavior = "auto" }) => {
159
+ var _a;
160
+ (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo({ top, behavior });
161
+ },
162
+ scrollToTop: (behavior = "auto") => {
163
+ var _a;
164
+ (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo({ top: 0, behavior });
165
+ },
166
+ scrollToBottom: (behavior = "auto") => {
167
+ const box = containerRef.current;
168
+ if (!box)
169
+ return;
170
+ box.scrollTo({ top: box.scrollHeight, behavior });
171
+ },
172
+ scrollToElement: (target, options = {}) => {
173
+ var _a, _b;
174
+ const box = containerRef.current;
175
+ if (!box)
176
+ return;
177
+ const el = typeof target === "string"
178
+ ? box.querySelector(target)
179
+ : target;
180
+ if (!el || !box.contains(el))
181
+ return;
182
+ // 用 getBoundingClientRect 计算偏移,兼容任意定位上下文
183
+ const top = el.getBoundingClientRect().top -
184
+ box.getBoundingClientRect().top +
185
+ box.scrollTop +
186
+ ((_a = options.offset) !== null && _a !== void 0 ? _a : 0);
187
+ box.scrollTo({ top, behavior: (_b = options.behavior) !== null && _b !== void 0 ? _b : "auto" });
188
+ },
189
+ }), []);
190
+ // 合并 height 与外部传入 style;height 优先级高于 userStyle.height
191
+ const mergedStyle = (0, react_1.useMemo)(() => {
192
+ if (height === undefined)
193
+ return userStyle;
194
+ return Object.assign(Object.assign({}, userStyle), { height });
195
+ }, [height, userStyle]);
196
+ // 默认 loading:iOS 风三点跳动
197
+ const defaultLoading = ((0, jsx_runtime_1.jsxs)("div", { css: [style_1.style.loading, loadingStyle], children: [(0, jsx_runtime_1.jsx)("span", { css: style_1.style.loadingDot }), (0, jsx_runtime_1.jsx)("span", { css: style_1.style.loadingDot }), (0, jsx_runtime_1.jsx)("span", { css: style_1.style.loadingDot })] }));
198
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, attrs, { css: [style_1.style.container, containerStyle], style: mergedStyle, ref: containerRef, children: [(0, jsx_runtime_1.jsx)("div", { ref: wrapperRef, css: wrapperStyle, children: children }), showLoading && scrollable && (loadingContent !== null && loadingContent !== void 0 ? loadingContent : defaultLoading)] })));
199
+ });
@@ -1,2 +1,2 @@
1
- import { Interpolation, Theme } from "@emotion/react";
1
+ import type { Interpolation, Theme } from "@emotion/react";
2
2
  export declare const style: Record<string, Interpolation<Theme>>;
@@ -1,32 +1,43 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.style = void 0;
4
+ const react_1 = require("@emotion/react");
5
+ // 模仿 iOS「正在输入」气泡的三点呼吸节奏
6
+ const dotPulse = (0, react_1.keyframes) `
7
+ 0%, 80%, 100% {
8
+ transform: scale(0.6);
9
+ opacity: 0.35;
10
+ }
11
+ 40% {
12
+ transform: scale(1);
13
+ opacity: 1;
14
+ }
15
+ `;
4
16
  exports.style = {
5
17
  container: {
6
18
  overflow: "auto",
7
19
  height: "100%",
8
20
  WebkitOverflowScrolling: "touch",
9
21
  },
10
- loading: [
11
- {
12
- paddingTop: '.15rem',
13
- paddingBottom: '.15rem',
14
- },
15
- {
16
- "> div": {
17
- width: '.3rem',
18
- height: '.3rem',
19
- },
20
- "> p": [
21
- {
22
- color: "#666",
23
- lineHeight: 1,
24
- },
25
- {
26
- marginLeft: '.16rem',
27
- fontSize: '.24rem',
28
- },
29
- ],
30
- },
31
- ],
22
+ loading: {
23
+ display: "flex",
24
+ alignItems: "center",
25
+ justifyContent: "center",
26
+ gap: ".12rem",
27
+ padding: ".24rem 0",
28
+ },
29
+ loadingDot: (0, react_1.css) `
30
+ width: 0.12rem;
31
+ height: 0.12rem;
32
+ border-radius: 50%;
33
+ background: #c7c7cc;
34
+ animation: ${dotPulse} 1.2s ease-in-out infinite both;
35
+
36
+ &:nth-of-type(1) {
37
+ animation-delay: -0.32s;
38
+ }
39
+ &:nth-of-type(2) {
40
+ animation-delay: -0.16s;
41
+ }
42
+ `,
32
43
  };
@@ -1,4 +1,3 @@
1
- /** @jsx jsx */
2
1
  import { Interpolation, Theme } from "@emotion/react";
3
2
  import React from "react";
4
3
  export interface ToastProps extends Omit<React.HTMLProps<HTMLDivElement>, "content"> {
@@ -68,7 +68,7 @@ function Toast(props) {
68
68
  showContent = (0, jsx_runtime_1.jsx)("div", { css: [middleStyle, contentStyle], children: content });
69
69
  }
70
70
  else {
71
- showContent = ((0, jsx_runtime_1.jsx)("p", { css: [style_1.style.content(radius), middleStyle, contentStyle], children: content }));
71
+ showContent = ((0, jsx_runtime_1.jsx)("p", { css: [style_1.style.content, middleStyle, contentStyle], style: { borderRadius: radius ? radius / 100 + "rem" : 0 }, children: content }));
72
72
  }
73
73
  // toast消失动画结束触发
74
74
  const animationEnd = (event) => {
@@ -77,15 +77,17 @@ function Toast(props) {
77
77
  onHide === null || onHide === void 0 ? void 0 : onHide();
78
78
  }
79
79
  };
80
+ // 位置偏移:所以 top/bottom 作为 inline style、middle 走常量 css
80
81
  let positionStyle;
82
+ let positionInline;
81
83
  if (position === "top") {
82
- positionStyle = style_1.style.top(offsetTop);
84
+ positionInline = { top: offsetTop / 100 + "rem" };
83
85
  }
84
86
  else if (position === "bottom") {
85
- positionStyle = style_1.style.bottom(offsetBottom);
87
+ positionInline = { bottom: offsetBottom / 100 + "rem" };
86
88
  }
87
89
  else {
88
90
  positionStyle = style_1.style.middle;
89
91
  }
90
- return ((0, jsx_runtime_1.jsx)("div", Object.assign({ css: [style_1.style.container(), positionStyle, animation, containerStyle], onAnimationEnd: animationEnd }, attributes, { children: showContent })));
92
+ return ((0, jsx_runtime_1.jsx)("div", Object.assign({}, attributes, { css: [style_1.style.container, positionStyle, animation, containerStyle], style: positionInline, onAnimationEnd: animationEnd, children: showContent })));
91
93
  }
@@ -37,21 +37,14 @@ export declare const bottomHideAnimation: {
37
37
  } & string;
38
38
  /**
39
39
  * 根据位置和类型获取动画
40
- * @param position
41
- * @param type
42
- * @returns
43
40
  */
44
41
  export declare function getAnimation(position: "top" | "middle" | "bottom", type: "show" | "hide"): {
45
42
  keyframes: Keyframes;
46
43
  animation: import("@emotion/react").SerializedStyles;
47
44
  };
48
45
  export declare const style: {
49
- container(): import("@emotion/react").SerializedStyles;
50
- top(offset: number): import("@emotion/react").SerializedStyles;
46
+ container: import("@emotion/react").SerializedStyles;
51
47
  middle: import("@emotion/react").SerializedStyles;
52
- bottom(offset: number): import("@emotion/react").SerializedStyles;
53
- content: (radius?: number) => import("@emotion/react").SerializedStyles;
54
- contentMiddle: {
55
- transform: string;
56
- };
48
+ content: import("@emotion/react").SerializedStyles;
49
+ contentMiddle: import("@emotion/react").SerializedStyles;
57
50
  };
@@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.style = exports.bottomHideAnimation = exports.bottomShowAnimation = exports.topHideAnimation = exports.topShowAnimation = exports.middleHideAnimation = exports.middleShowAnimation = void 0;
4
4
  exports.getAnimation = getAnimation;
5
5
  const react_1 = require("@emotion/react");
6
+ const theme_1 = require("../utils/theme");
7
+ const easing = "cubic-bezier(.22,.61,.36,1)";
6
8
  exports.middleShowAnimation = (0, react_1.keyframes) `
7
9
  from {
8
10
  opacity: 0;
9
- transform: translateX(-50%) scale(0.9);
11
+ transform: translateX(-50%) scale(0.92);
10
12
  }
11
13
  to {
12
14
  opacity: 1;
@@ -20,13 +22,13 @@ exports.middleHideAnimation = (0, react_1.keyframes) `
20
22
  }
21
23
  to {
22
24
  opacity: 0;
23
- transform: translateX(-50%) scale(0.9);
25
+ transform: translateX(-50%) scale(0.92);
24
26
  }
25
27
  `;
26
28
  exports.topShowAnimation = (0, react_1.keyframes) `
27
29
  from {
28
30
  opacity: 0;
29
- transform: translate(-50%, -100%);
31
+ transform: translate(-50%, -120%);
30
32
  }
31
33
  to {
32
34
  opacity: 1;
@@ -40,13 +42,13 @@ exports.topHideAnimation = (0, react_1.keyframes) `
40
42
  }
41
43
  to {
42
44
  opacity: 0;
43
- transform: translate(-50%, -100%);
45
+ transform: translate(-50%, -120%);
44
46
  }
45
47
  `;
46
48
  exports.bottomShowAnimation = (0, react_1.keyframes) `
47
49
  from {
48
50
  opacity: 0;
49
- transform: translate(-50%, 100%);
51
+ transform: translate(-50%, 120%);
50
52
  }
51
53
  to {
52
54
  opacity: 1;
@@ -60,14 +62,11 @@ exports.bottomHideAnimation = (0, react_1.keyframes) `
60
62
  }
61
63
  to {
62
64
  opacity: 0;
63
- transform: translate(-50%, 100%);
65
+ transform: translate(-50%, 120%);
64
66
  }
65
67
  `;
66
68
  /**
67
69
  * 根据位置和类型获取动画
68
- * @param position
69
- * @param type
70
- * @returns
71
70
  */
72
71
  function getAnimation(position, type) {
73
72
  const animation = {
@@ -85,46 +84,43 @@ function getAnimation(position, type) {
85
84
  return {
86
85
  keyframes,
87
86
  animation: (0, react_1.css)({
88
- animation: `${keyframes} 300ms ease`,
87
+ animation: `${keyframes} 260ms ${easing}`,
89
88
  }),
90
89
  };
91
90
  }
92
91
  exports.style = {
93
- container() {
94
- return (0, react_1.css)({
95
- position: "fixed",
96
- left: "50%",
97
- transform: "translateX(-50%)",
98
- zIndex: 9999,
99
- maxWidth: '6rem',
100
- });
101
- },
102
- top(offset) {
103
- return (0, react_1.css)({ top: offset / 100 + 'rem' });
104
- },
92
+ // 容器静态样式:位置偏移由 container 提供,具体 top/bottom 偏移走 inline style。
93
+ container: (0, react_1.css)({
94
+ position: "fixed",
95
+ left: "50%",
96
+ transform: "translateX(-50%)",
97
+ zIndex: 9999,
98
+ maxWidth: "6rem",
99
+ pointerEvents: "none",
100
+ fontFamily: theme_1.fontStack,
101
+ WebkitFontSmoothing: "antialiased",
102
+ MozOsxFontSmoothing: "grayscale",
103
+ }),
105
104
  middle: (0, react_1.css)({ top: "50%" }),
106
- bottom(offset) {
107
- return (0, react_1.css)({ bottom: offset / 100 + 'rem' });
108
- },
109
- content: (radius) => {
110
- return (0, react_1.css)({
111
- position: "relative",
112
- backgroundColor: "rgba(0, 0, 0, .8)",
113
- color: "#fff",
114
- margin: 0,
115
- whiteSpace: "nowrap",
116
- textOverflow: "ellipsis",
117
- overflow: "hidden",
118
- lineHeight: 1,
119
- fontSize: '.26rem',
120
- paddingLeft: '.3rem',
121
- paddingRight: '.3rem',
122
- paddingTop: '.4rem',
123
- paddingBottom: '.4rem',
124
- borderRadius: radius ? radius / 100 + 'rem' : 0,
125
- });
126
- },
127
- contentMiddle: {
105
+ // content 中与 radius 无关的部分作为常量,radius 走 inline style
106
+ content: (0, react_1.css)({
107
+ position: "relative",
108
+ backgroundColor: "rgba(0,0,0,.78)",
109
+ color: "#ffffff",
110
+ margin: 0,
111
+ whiteSpace: "pre-wrap",
112
+ wordBreak: "break-word",
113
+ lineHeight: 1.5,
114
+ fontSize: ".28rem",
115
+ fontWeight: 400,
116
+ letterSpacing: ".01rem",
117
+ textAlign: "center",
118
+ padding: ".2rem .32rem",
119
+ boxShadow: "0 .12rem .32rem rgba(0,0,0,.18)",
120
+ backdropFilter: "blur(20px) saturate(160%)",
121
+ WebkitBackdropFilter: "blur(20px) saturate(160%)",
122
+ }),
123
+ contentMiddle: (0, react_1.css)({
128
124
  transform: `translateY(-50%)`,
129
- },
125
+ }),
130
126
  };
package/build/index.d.ts CHANGED
@@ -32,5 +32,8 @@ export { SafeArea } from './SafeArea';
32
32
  export { AutoGrid } from './AutoGrid';
33
33
  export { showAlert } from './Alert';
34
34
  export { ScrollView } from './ScrollView';
35
+ export type { ScrollViewHandle, ScrollViewProps, ScrollEvent } from './ScrollView';
35
36
  export { CarouselNotice } from './CarouselNotice';
36
37
  export { CitySelect, showCitySelect } from './CitySelect';
38
+ export { DatePicker, showDatePicker } from './DatePicker';
39
+ export { RegionPicker, showRegionPicker } from './RegionPicker';
package/build/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.showUniqToast = exports.showToast = exports.Overlay = exports.Countdowner = exports.ColStart = exports.ColEvenly = exports.ColEnd = exports.ColCenter = exports.ColBetween = exports.ColAround = exports.Col = exports.RowStart = exports.RowEvenly = exports.RowEnd = exports.RowCenter = exports.RowBetween = exports.RowAround = exports.Row = exports.FlexItem = exports.Flex = exports.Container = exports.Ago = exports.useViewport = exports.useWindowResize = exports.useUpdate = exports.useTick = exports.useInterval = exports.createPortalDOM = exports.getHistory = exports.history = exports.createApp = exports.splitValue = exports.normalizeUnit = exports.waitUntil = exports.waitFor = exports.is = exports.defaultScroll = exports.Countdown = exports.calendarTable = exports.registerHostAlias = exports.buildUrlByOption = exports.sendRequest = exports.sugarSend = exports.sendJSON = exports.POST = exports.GET = exports.ago = exports.uniqKey = exports.jsonp = exports.tick = void 0;
4
- exports.showCitySelect = exports.CitySelect = exports.CarouselNotice = exports.ScrollView = exports.showAlert = exports.AutoGrid = exports.SafeArea = exports.showLoadingAtLeast = exports.showLoading = exports.Indicator = exports.Clickable = exports.showDialog = void 0;
4
+ exports.showRegionPicker = exports.RegionPicker = exports.showDatePicker = exports.DatePicker = exports.showCitySelect = exports.CitySelect = exports.CarouselNotice = exports.ScrollView = exports.showAlert = exports.AutoGrid = exports.SafeArea = exports.showLoadingAtLeast = exports.showLoading = exports.Indicator = exports.Clickable = exports.showDialog = void 0;
5
5
  var tick_1 = require("./utils/tick");
6
6
  Object.defineProperty(exports, "tick", { enumerable: true, get: function () { return tick_1.tick; } });
7
7
  var jsonp_1 = require("./utils/jsonp");
@@ -100,3 +100,9 @@ Object.defineProperty(exports, "CarouselNotice", { enumerable: true, get: functi
100
100
  var CitySelect_1 = require("./CitySelect");
101
101
  Object.defineProperty(exports, "CitySelect", { enumerable: true, get: function () { return CitySelect_1.CitySelect; } });
102
102
  Object.defineProperty(exports, "showCitySelect", { enumerable: true, get: function () { return CitySelect_1.showCitySelect; } });
103
+ var DatePicker_1 = require("./DatePicker");
104
+ Object.defineProperty(exports, "DatePicker", { enumerable: true, get: function () { return DatePicker_1.DatePicker; } });
105
+ Object.defineProperty(exports, "showDatePicker", { enumerable: true, get: function () { return DatePicker_1.showDatePicker; } });
106
+ var RegionPicker_1 = require("./RegionPicker");
107
+ Object.defineProperty(exports, "RegionPicker", { enumerable: true, get: function () { return RegionPicker_1.RegionPicker; } });
108
+ Object.defineProperty(exports, "showRegionPicker", { enumerable: true, get: function () { return RegionPicker_1.showRegionPicker; } });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 将 #rrggbb 颜色按比例变暗;amount 取值 0~1
3
+ * 例:darken("#2f7dff", 0.15) → #2a6cd9(用于派生交互态色)
4
+ */
5
+ export declare function darken(hex: string, amount: number): string;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.darken = darken;
4
+ /**
5
+ * 将 #rrggbb 颜色按比例变暗;amount 取值 0~1
6
+ * 例:darken("#2f7dff", 0.15) → #2a6cd9(用于派生交互态色)
7
+ */
8
+ function darken(hex, amount) {
9
+ const m = hex.replace("#", "");
10
+ if (m.length !== 6)
11
+ return hex;
12
+ const r = parseInt(m.slice(0, 2), 16);
13
+ const g = parseInt(m.slice(2, 4), 16);
14
+ const b = parseInt(m.slice(4, 6), 16);
15
+ const factor = (v) => Math.max(0, Math.min(255, Math.round(v * (1 - amount))));
16
+ const toHex = (v) => factor(v).toString(16).padStart(2, "0");
17
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
18
+ }