@alifd/chat 0.3.3 → 0.3.5

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.
@@ -1,11 +1,15 @@
1
1
  import type { BalloonProps } from '../types';
2
2
  /**
3
- * 自动调整弹层 align 位置逻辑
3
+ * 自动调整弹层 align 位置逻辑,设置Balloon 组件中的align参数
4
4
  */
5
- export declare function useAutoAlign(_dom: HTMLElement | null | undefined, trigger: HTMLElement | null, { enable, defaultAlign, }: {
5
+ export declare function useAutoAlign(_dom: HTMLElement | null | undefined, // 弹层dom
6
+ trigger: HTMLElement | null, // 触发器dom
7
+ { enable, defaultAlign, defaultMaxHeight }: {
6
8
  enable?: boolean;
7
9
  defaultAlign: BalloonProps['align'];
10
+ defaultMaxHeight?: number;
8
11
  }): {
9
12
  align: "b" | "br" | "rt" | "tr" | "t" | "r" | "l" | "tl" | "bl" | "lt" | "lb" | "rb" | undefined;
10
13
  update: (dom?: HTMLElement | null | undefined) => void;
14
+ maxHeight: number;
11
15
  };
@@ -1,45 +1,64 @@
1
1
  import { useState } from 'react';
2
- import { getNearlyEdge, isInScreen } from '../util';
2
+ import { getNearlyEdge, isInScreen, getScreenSize } from '../util';
3
3
  import { useThrottle } from '../../utils';
4
+ const DEFAULT_PANE_OFFSET = 20;
5
+ const DEFAULT_EDGE_OFFSET = 10;
6
+ const { height: screenHeight } = getScreenSize();
4
7
  /**
5
- * 自动调整弹层 align 位置逻辑
8
+ * 自动调整弹层 align 位置逻辑,设置Balloon 组件中的align参数
6
9
  */
7
- export function useAutoAlign(_dom, trigger, { enable, defaultAlign, }) {
10
+ export function useAutoAlign(_dom, // 弹层dom
11
+ trigger, // 触发器dom
12
+ { enable, defaultAlign, defaultMaxHeight }) {
8
13
  const [align, setAlign] = useState(defaultAlign);
14
+ const [maxHeight, setMaxHeight] = useState(defaultMaxHeight || screenHeight);
9
15
  const update = (dom = _dom) => {
10
16
  if (!enable || !dom || !trigger) {
11
17
  return;
12
18
  }
13
- if (isInScreen(dom)) {
19
+ const domScrollHeight = dom === null || dom === void 0 ? void 0 : dom.scrollHeight;
20
+ const domClientHeight = dom === null || dom === void 0 ? void 0 : dom.clientHeight;
21
+ // 如果元素没有超出屏幕区域不进行位置调整
22
+ if (isInScreen(dom) && domScrollHeight <= domClientHeight) {
14
23
  return;
15
24
  }
16
25
  const [edge, subEdge] = getNearlyEdge(trigger, ['top', 'right', 'bottom', 'left']);
26
+ const { left, top, width, height } = trigger.getBoundingClientRect();
17
27
  let newAlign = align;
28
+ let newMaxHeight = maxHeight;
18
29
  switch (edge) {
19
30
  case 'top': {
20
31
  newAlign = subEdge === 'left' ? 'bl' : 'br';
32
+ newMaxHeight = screenHeight - top - height - DEFAULT_PANE_OFFSET - DEFAULT_EDGE_OFFSET;
21
33
  break;
22
34
  }
23
35
  case 'right': {
24
36
  newAlign = subEdge === 'top' ? 'lt' : 'lb';
37
+ newMaxHeight = subEdge === 'top' ? screenHeight - top - DEFAULT_EDGE_OFFSET : top + height - DEFAULT_EDGE_OFFSET;
25
38
  break;
26
39
  }
27
40
  case 'bottom': {
28
41
  newAlign = subEdge === 'left' ? 'tl' : 'tr';
42
+ newMaxHeight = top - DEFAULT_PANE_OFFSET - DEFAULT_EDGE_OFFSET;
29
43
  break;
30
44
  }
31
45
  case 'left': {
32
46
  newAlign = subEdge === 'top' ? 'rt' : 'rb';
47
+ newMaxHeight = subEdge === 'top' ? screenHeight - top - DEFAULT_EDGE_OFFSET : top + height - DEFAULT_EDGE_OFFSET;
33
48
  break;
34
49
  }
35
50
  }
36
51
  if (newAlign !== align) {
37
52
  setAlign(newAlign);
38
53
  }
54
+ if (newMaxHeight !== maxHeight) {
55
+ setMaxHeight(newMaxHeight);
56
+ }
39
57
  };
40
58
  const throttleUpdate = useThrottle(update, 100);
41
59
  return {
42
60
  align,
43
61
  update: throttleUpdate,
62
+ maxHeight
44
63
  };
45
64
  }
@@ -151,7 +151,7 @@ export interface FloatButtonProps extends CommonProps {
151
151
  */
152
152
  safeAreaMargin?: Margin;
153
153
  /**
154
- * 默认位置
154
+ * 默认位置, 会根据defaultPosition值计算悬浮球的初始位置
155
155
  */
156
156
  defaultPosition?: {
157
157
  top?: number | string;
@@ -42,7 +42,7 @@ const FloatButton = forwardRef((props, ref) => {
42
42
  setEl(elRef.current);
43
43
  setTriggerEl(triggerRef.current);
44
44
  }, []);
45
- const { align: currentAlign, update: _updateAlign } = useAutoAlign(el === null || el === void 0 ? void 0 : el.querySelector(`.${cls}-popup`), triggerEl, {
45
+ const { align: currentAlign, update: _updateAlign, maxHeight: currentMaxHeight } = useAutoAlign(el === null || el === void 0 ? void 0 : el.querySelector(`.${cls}-popup`), triggerEl, {
46
46
  enable: autoAlign,
47
47
  defaultAlign: align,
48
48
  });
@@ -96,13 +96,13 @@ const FloatButton = forwardRef((props, ref) => {
96
96
  },
97
97
  onDraging(_, e) {
98
98
  draggedRef.current = true;
99
- updateAlign();
100
99
  handleMove(e);
101
100
  if (isHideRef.current) {
102
101
  return false;
103
102
  }
104
103
  },
105
104
  onDragend() {
105
+ updateAlign();
106
106
  if (!isHideRef.current) {
107
107
  updateNestleEdge();
108
108
  }
@@ -116,13 +116,15 @@ const FloatButton = forwardRef((props, ref) => {
116
116
  onVisibleChange(v, type);
117
117
  };
118
118
  const renderBalloon = () => {
119
+ const popupClassName = cs(`${cls}-popup`, (balloonProps === null || balloonProps === void 0 ? void 0 : balloonProps.popupClassName) || '');
120
+ const popupStyle = Object.assign({ maxHeight: `${currentMaxHeight}px`, overflow: 'auto' }, ((balloonProps === null || balloonProps === void 0 ? void 0 : balloonProps.popupStyle) || {}));
119
121
  return (React.createElement(Balloon, Object.assign({ visible: visible, onVisibleChange: handleVisibleChange, popupProps: {
120
122
  afterOpen() {
121
123
  var _a, _b;
122
124
  updateAlign();
123
125
  (_b = (_a = balloonProps === null || balloonProps === void 0 ? void 0 : balloonProps.popupProps) === null || _a === void 0 ? void 0 : _a.afterClose) === null || _b === void 0 ? void 0 : _b.call(_a);
124
126
  },
125
- }, popupClassName: `${cls}-popup`, trigger: trigger, popupContainer: () => el, triggerType: triggerType, align: currentAlign, v2: true, closable: showClose, autoAdjust: false }, balloonProps), children));
127
+ }, trigger: trigger, popupContainer: () => el, triggerType: triggerType, align: currentAlign, v2: true, closable: showClose, autoAdjust: false }, balloonProps, { popupClassName: popupClassName, popupStyle: popupStyle }), children));
126
128
  };
127
129
  const renderView = () => {
128
130
  if (typeof _renderView === 'function') {
package/es/index.js CHANGED
@@ -20,4 +20,4 @@ export { default as CardLoading } from './card-loading';
20
20
  export { default as Origin } from './origin';
21
21
  export { default as Loading } from './loading';
22
22
  export { default as Drawer } from './drawer';
23
- export const version = '0.3.3';
23
+ export const version = '0.3.5';
@@ -1,11 +1,15 @@
1
1
  import type { BalloonProps } from '../types';
2
2
  /**
3
- * 自动调整弹层 align 位置逻辑
3
+ * 自动调整弹层 align 位置逻辑,设置Balloon 组件中的align参数
4
4
  */
5
- export declare function useAutoAlign(_dom: HTMLElement | null | undefined, trigger: HTMLElement | null, { enable, defaultAlign, }: {
5
+ export declare function useAutoAlign(_dom: HTMLElement | null | undefined, // 弹层dom
6
+ trigger: HTMLElement | null, // 触发器dom
7
+ { enable, defaultAlign, defaultMaxHeight }: {
6
8
  enable?: boolean;
7
9
  defaultAlign: BalloonProps['align'];
10
+ defaultMaxHeight?: number;
8
11
  }): {
9
12
  align: "b" | "br" | "rt" | "tr" | "t" | "r" | "l" | "tl" | "bl" | "lt" | "lb" | "rb" | undefined;
10
13
  update: (dom?: HTMLElement | null | undefined) => void;
14
+ maxHeight: number;
11
15
  };
@@ -4,45 +4,64 @@ exports.useAutoAlign = useAutoAlign;
4
4
  const react_1 = require("react");
5
5
  const util_1 = require("../util");
6
6
  const utils_1 = require("../../utils");
7
+ const DEFAULT_PANE_OFFSET = 20;
8
+ const DEFAULT_EDGE_OFFSET = 10;
9
+ const { height: screenHeight } = (0, util_1.getScreenSize)();
7
10
  /**
8
- * 自动调整弹层 align 位置逻辑
11
+ * 自动调整弹层 align 位置逻辑,设置Balloon 组件中的align参数
9
12
  */
10
- function useAutoAlign(_dom, trigger, { enable, defaultAlign, }) {
13
+ function useAutoAlign(_dom, // 弹层dom
14
+ trigger, // 触发器dom
15
+ { enable, defaultAlign, defaultMaxHeight }) {
11
16
  const [align, setAlign] = (0, react_1.useState)(defaultAlign);
17
+ const [maxHeight, setMaxHeight] = (0, react_1.useState)(defaultMaxHeight || screenHeight);
12
18
  const update = (dom = _dom) => {
13
19
  if (!enable || !dom || !trigger) {
14
20
  return;
15
21
  }
16
- if ((0, util_1.isInScreen)(dom)) {
22
+ const domScrollHeight = dom === null || dom === void 0 ? void 0 : dom.scrollHeight;
23
+ const domClientHeight = dom === null || dom === void 0 ? void 0 : dom.clientHeight;
24
+ // 如果元素没有超出屏幕区域不进行位置调整
25
+ if ((0, util_1.isInScreen)(dom) && domScrollHeight <= domClientHeight) {
17
26
  return;
18
27
  }
19
28
  const [edge, subEdge] = (0, util_1.getNearlyEdge)(trigger, ['top', 'right', 'bottom', 'left']);
29
+ const { left, top, width, height } = trigger.getBoundingClientRect();
20
30
  let newAlign = align;
31
+ let newMaxHeight = maxHeight;
21
32
  switch (edge) {
22
33
  case 'top': {
23
34
  newAlign = subEdge === 'left' ? 'bl' : 'br';
35
+ newMaxHeight = screenHeight - top - height - DEFAULT_PANE_OFFSET - DEFAULT_EDGE_OFFSET;
24
36
  break;
25
37
  }
26
38
  case 'right': {
27
39
  newAlign = subEdge === 'top' ? 'lt' : 'lb';
40
+ newMaxHeight = subEdge === 'top' ? screenHeight - top - DEFAULT_EDGE_OFFSET : top + height - DEFAULT_EDGE_OFFSET;
28
41
  break;
29
42
  }
30
43
  case 'bottom': {
31
44
  newAlign = subEdge === 'left' ? 'tl' : 'tr';
45
+ newMaxHeight = top - DEFAULT_PANE_OFFSET - DEFAULT_EDGE_OFFSET;
32
46
  break;
33
47
  }
34
48
  case 'left': {
35
49
  newAlign = subEdge === 'top' ? 'rt' : 'rb';
50
+ newMaxHeight = subEdge === 'top' ? screenHeight - top - DEFAULT_EDGE_OFFSET : top + height - DEFAULT_EDGE_OFFSET;
36
51
  break;
37
52
  }
38
53
  }
39
54
  if (newAlign !== align) {
40
55
  setAlign(newAlign);
41
56
  }
57
+ if (newMaxHeight !== maxHeight) {
58
+ setMaxHeight(newMaxHeight);
59
+ }
42
60
  };
43
61
  const throttleUpdate = (0, utils_1.useThrottle)(update, 100);
44
62
  return {
45
63
  align,
46
64
  update: throttleUpdate,
65
+ maxHeight
47
66
  };
48
67
  }
@@ -151,7 +151,7 @@ export interface FloatButtonProps extends CommonProps {
151
151
  */
152
152
  safeAreaMargin?: Margin;
153
153
  /**
154
- * 默认位置
154
+ * 默认位置, 会根据defaultPosition值计算悬浮球的初始位置
155
155
  */
156
156
  defaultPosition?: {
157
157
  top?: number | string;
@@ -44,7 +44,7 @@ const FloatButton = (0, react_1.forwardRef)((props, ref) => {
44
44
  setEl(elRef.current);
45
45
  setTriggerEl(triggerRef.current);
46
46
  }, []);
47
- const { align: currentAlign, update: _updateAlign } = (0, useAutoAlign_1.useAutoAlign)(el === null || el === void 0 ? void 0 : el.querySelector(`.${cls}-popup`), triggerEl, {
47
+ const { align: currentAlign, update: _updateAlign, maxHeight: currentMaxHeight } = (0, useAutoAlign_1.useAutoAlign)(el === null || el === void 0 ? void 0 : el.querySelector(`.${cls}-popup`), triggerEl, {
48
48
  enable: autoAlign,
49
49
  defaultAlign: align,
50
50
  });
@@ -98,13 +98,13 @@ const FloatButton = (0, react_1.forwardRef)((props, ref) => {
98
98
  },
99
99
  onDraging(_, e) {
100
100
  draggedRef.current = true;
101
- updateAlign();
102
101
  handleMove(e);
103
102
  if (isHideRef.current) {
104
103
  return false;
105
104
  }
106
105
  },
107
106
  onDragend() {
107
+ updateAlign();
108
108
  if (!isHideRef.current) {
109
109
  updateNestleEdge();
110
110
  }
@@ -118,13 +118,15 @@ const FloatButton = (0, react_1.forwardRef)((props, ref) => {
118
118
  onVisibleChange(v, type);
119
119
  };
120
120
  const renderBalloon = () => {
121
+ const popupClassName = (0, classnames_1.default)(`${cls}-popup`, (balloonProps === null || balloonProps === void 0 ? void 0 : balloonProps.popupClassName) || '');
122
+ const popupStyle = Object.assign({ maxHeight: `${currentMaxHeight}px`, overflow: 'auto' }, ((balloonProps === null || balloonProps === void 0 ? void 0 : balloonProps.popupStyle) || {}));
121
123
  return (react_1.default.createElement(next_1.Balloon, Object.assign({ visible: visible, onVisibleChange: handleVisibleChange, popupProps: {
122
124
  afterOpen() {
123
125
  var _a, _b;
124
126
  updateAlign();
125
127
  (_b = (_a = balloonProps === null || balloonProps === void 0 ? void 0 : balloonProps.popupProps) === null || _a === void 0 ? void 0 : _a.afterClose) === null || _b === void 0 ? void 0 : _b.call(_a);
126
128
  },
127
- }, popupClassName: `${cls}-popup`, trigger: trigger, popupContainer: () => el, triggerType: triggerType, align: currentAlign, v2: true, closable: showClose, autoAdjust: false }, balloonProps), children));
129
+ }, trigger: trigger, popupContainer: () => el, triggerType: triggerType, align: currentAlign, v2: true, closable: showClose, autoAdjust: false }, balloonProps, { popupClassName: popupClassName, popupStyle: popupStyle }), children));
128
130
  };
129
131
  const renderView = () => {
130
132
  if (typeof _renderView === 'function') {
package/lib/index.js CHANGED
@@ -46,4 +46,4 @@ var loading_1 = require("./loading");
46
46
  Object.defineProperty(exports, "Loading", { enumerable: true, get: function () { return tslib_1.__importDefault(loading_1).default; } });
47
47
  var drawer_1 = require("./drawer");
48
48
  Object.defineProperty(exports, "Drawer", { enumerable: true, get: function () { return tslib_1.__importDefault(drawer_1).default; } });
49
- exports.version = '0.3.3';
49
+ exports.version = '0.3.5';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alifd/chat",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "A configurable component library for chat built on React.",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",