@clayui/tooltip 3.65.0 → 3.67.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.
@@ -9,6 +9,8 @@ exports.default = void 0;
9
9
 
10
10
  var _shared = require("@clayui/shared");
11
11
 
12
+ var _domAlign = require("dom-align");
13
+
12
14
  var _react = _interopRequireWildcard(require("react"));
13
15
 
14
16
  var _warning = _interopRequireDefault(require("warning"));
@@ -66,6 +68,20 @@ var ALIGNMENTS_INVERSE_MAP = {
66
68
  tlbl: 'bottom-left',
67
69
  trbr: 'bottom-right'
68
70
  };
71
+ var BOTTOM_OFFSET = [0, 7];
72
+ var LEFT_OFFSET = [-7, 0];
73
+ var RIGHT_OFFSET = [7, 0];
74
+ var TOP_OFFSET = [0, -7];
75
+ var OFFSET_MAP = {
76
+ bctc: TOP_OFFSET,
77
+ bltl: TOP_OFFSET,
78
+ brtr: TOP_OFFSET,
79
+ clcr: RIGHT_OFFSET,
80
+ crcl: LEFT_OFFSET,
81
+ tcbc: BOTTOM_OFFSET,
82
+ tlbl: BOTTOM_OFFSET,
83
+ trbr: BOTTOM_OFFSET
84
+ };
69
85
 
70
86
  var ALIGNMENTS_FORCE_MAP = _objectSpread(_objectSpread({}, ALIGNMENTS_INVERSE_MAP), {}, {
71
87
  bctc: 'top-left',
@@ -97,6 +113,7 @@ var reducer = function reducer(state, _ref) {
97
113
  case 'hide':
98
114
  return _objectSpread(_objectSpread({}, state), {}, {
99
115
  align: initialState.align,
116
+ floating: undefined,
100
117
  show: false
101
118
  });
102
119
 
@@ -154,12 +171,14 @@ var TooltipProvider = function TooltipProvider(_ref2) {
154
171
  _useReducer2 = _slicedToArray(_useReducer, 2),
155
172
  _useReducer2$ = _useReducer2[0],
156
173
  align = _useReducer2$.align,
174
+ floating = _useReducer2$.floating,
157
175
  _useReducer2$$message = _useReducer2$.message,
158
176
  message = _useReducer2$$message === void 0 ? '' : _useReducer2$$message,
159
177
  setAsHTML = _useReducer2$.setAsHTML,
160
178
  show = _useReducer2$.show,
161
- dispatch = _useReducer2[1]; // Using `any` type since TS incorrectly infers setTimeout to be from NodeJS
179
+ dispatch = _useReducer2[1];
162
180
 
181
+ var mousePosition = (0, _shared.useMousePosition)(20); // Using `any` type since TS incorrectly infers setTimeout to be from NodeJS
163
182
 
164
183
  var timeoutIdRef = (0, _react.useRef)();
165
184
  var targetRef = (0, _react.useRef)(null);
@@ -220,8 +239,8 @@ var TooltipProvider = function TooltipProvider(_ref2) {
220
239
  targetRef.current = null;
221
240
  }
222
241
  }, []);
223
- var handleShow = (0, _react.useCallback)(function (_ref3) {
224
- var target = _ref3.target;
242
+ var handleShow = (0, _react.useCallback)(function (event) {
243
+ var target = event.target;
225
244
  var hasTitle = target && (target.hasAttribute('title') || target.hasAttribute('data-title'));
226
245
  var titleNode = hasTitle ? target : closestAncestor(target, '[title], [data-title]');
227
246
 
@@ -235,10 +254,12 @@ var TooltipProvider = function TooltipProvider(_ref2) {
235
254
 
236
255
  var _setAsHTML = !!titleNode.getAttribute('data-title-set-as-html');
237
256
 
257
+ var isFloating = titleNode.getAttribute('data-tooltip-floating');
238
258
  clearTimeout(timeoutIdRef.current);
239
259
  timeoutIdRef.current = setTimeout(function () {
240
260
  dispatch({
241
261
  align: newAlign || align,
262
+ floating: Boolean(isFloating),
242
263
  message: title,
243
264
  setAsHTML: _setAsHTML,
244
265
  type: 'show'
@@ -268,19 +289,36 @@ var TooltipProvider = function TooltipProvider(_ref2) {
268
289
  return (0, _shared.delegate)(document.body, eventName, "".concat(scope, ", .tooltip"), handleHide);
269
290
  });
270
291
  return function () {
271
- disposeShowEvents.forEach(function (_ref4) {
272
- var dispose = _ref4.dispose;
292
+ disposeShowEvents.forEach(function (_ref3) {
293
+ var dispose = _ref3.dispose;
273
294
  return dispose();
274
295
  });
275
- disposeHideEvents.forEach(function (_ref5) {
276
- var dispose = _ref5.dispose;
296
+ disposeHideEvents.forEach(function (_ref4) {
297
+ var dispose = _ref4.dispose;
277
298
  return dispose();
278
299
  });
279
300
  };
280
301
  }
281
- }, []);
302
+ }, [handleShow]);
303
+ (0, _react.useEffect)(function () {
304
+ if (tooltipRef.current && show && floating) {
305
+ var points = ALIGNMENTS_MAP[align || 'top'];
306
+
307
+ var _mousePosition = _slicedToArray(mousePosition, 2),
308
+ clientX = _mousePosition[0],
309
+ clientY = _mousePosition[1];
310
+
311
+ (0, _domAlign.alignPoint)(tooltipRef.current, {
312
+ clientX: clientX,
313
+ clientY: clientY
314
+ }, {
315
+ offset: OFFSET_MAP[points.join('')],
316
+ points: points
317
+ });
318
+ }
319
+ }, [mousePosition, show, floating]);
282
320
  (0, _react.useEffect)(function () {
283
- if (titleNodeRef.current && tooltipRef.current) {
321
+ if (titleNodeRef.current && tooltipRef.current && !floating) {
284
322
  var points = ALIGNMENTS_MAP[align || 'top'];
285
323
  var alignment = (0, _shared.doAlign)({
286
324
  overflow: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clayui/tooltip",
3
- "version": "3.65.0",
3
+ "version": "3.67.0",
4
4
  "description": "ClayTooltip component",
5
5
  "license": "BSD-3-Clause",
6
6
  "repository": "https://github.com/liferay/clay",
@@ -26,8 +26,9 @@
26
26
  "react"
27
27
  ],
28
28
  "dependencies": {
29
- "@clayui/shared": "^3.65.0",
29
+ "@clayui/shared": "^3.67.0",
30
30
  "classnames": "^2.2.6",
31
+ "dom-align": "^1.12.2",
31
32
  "warning": "^4.0.3"
32
33
  },
33
34
  "peerDependencies": {
@@ -38,5 +39,5 @@
38
39
  "browserslist": [
39
40
  "extends browserslist-config-clay"
40
41
  ],
41
- "gitHead": "603f05c8d617d98e29f0456b5d6618f9a95ce740"
42
+ "gitHead": "71e84490088d72afb0240a7ef69cde23a6d5dd19"
42
43
  }
@@ -9,7 +9,9 @@ import {
9
9
  Keys,
10
10
  delegate,
11
11
  doAlign,
12
+ useMousePosition,
12
13
  } from '@clayui/shared';
14
+ import {alignPoint} from 'dom-align';
13
15
  import React, {useCallback, useEffect, useReducer, useRef} from 'react';
14
16
  import warning from 'warning';
15
17
 
@@ -48,6 +50,22 @@ const ALIGNMENTS_INVERSE_MAP = {
48
50
  trbr: 'bottom-right',
49
51
  } as const;
50
52
 
53
+ const BOTTOM_OFFSET = [0, 7] as const;
54
+ const LEFT_OFFSET = [-7, 0] as const;
55
+ const RIGHT_OFFSET = [7, 0] as const;
56
+ const TOP_OFFSET = [0, -7] as const;
57
+
58
+ const OFFSET_MAP = {
59
+ bctc: TOP_OFFSET,
60
+ bltl: TOP_OFFSET,
61
+ brtr: TOP_OFFSET,
62
+ clcr: RIGHT_OFFSET,
63
+ crcl: LEFT_OFFSET,
64
+ tcbc: BOTTOM_OFFSET,
65
+ tlbl: BOTTOM_OFFSET,
66
+ trbr: BOTTOM_OFFSET,
67
+ };
68
+
51
69
  const ALIGNMENTS_FORCE_MAP = {
52
70
  ...ALIGNMENTS_INVERSE_MAP,
53
71
  bctc: 'top-left',
@@ -56,6 +74,7 @@ const ALIGNMENTS_FORCE_MAP = {
56
74
 
57
75
  interface IState {
58
76
  align?: typeof ALIGNMENTS[number];
77
+ floating?: boolean;
59
78
  message?: string;
60
79
  show?: boolean;
61
80
  setAsHTML?: boolean;
@@ -97,6 +116,7 @@ const reducer = (state: IState, {type, ...payload}: IAction): IState => {
97
116
  return {
98
117
  ...state,
99
118
  align: initialState.align,
119
+ floating: undefined,
100
120
  show: false,
101
121
  };
102
122
  default:
@@ -191,10 +211,10 @@ const TooltipProvider = ({
191
211
  delay = 600,
192
212
  scope,
193
213
  }: IPropsWithChildren | IPropsWithScope) => {
194
- const [{align, message = '', setAsHTML, show}, dispatch] = useReducer(
195
- reducer,
196
- initialState
197
- );
214
+ const [{align, floating, message = '', setAsHTML, show}, dispatch] =
215
+ useReducer(reducer, initialState);
216
+
217
+ const mousePosition = useMousePosition(20);
198
218
 
199
219
  // Using `any` type since TS incorrectly infers setTimeout to be from NodeJS
200
220
  const timeoutIdRef = useRef<any>();
@@ -267,50 +287,62 @@ const TooltipProvider = ({
267
287
  }
268
288
  }, []);
269
289
 
270
- const handleShow = useCallback(({target}: {target: HTMLElement}) => {
271
- const hasTitle =
272
- target &&
273
- (target.hasAttribute('title') || target.hasAttribute('data-title'));
290
+ const handleShow = useCallback(
291
+ (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
292
+ const target = event!.target as HTMLElement;
274
293
 
275
- const titleNode = hasTitle
276
- ? target
277
- : closestAncestor(target, '[title], [data-title]');
294
+ const hasTitle =
295
+ target &&
296
+ (target.hasAttribute('title') ||
297
+ target.hasAttribute('data-title'));
278
298
 
279
- if (titleNode) {
280
- targetRef.current = target;
299
+ const titleNode = hasTitle
300
+ ? target
301
+ : closestAncestor(target, '[title], [data-title]');
281
302
 
282
- target.addEventListener('click', handleHide);
303
+ if (titleNode) {
304
+ targetRef.current = target;
283
305
 
284
- const title =
285
- titleNode.getAttribute('title') ||
286
- titleNode.getAttribute('data-title') ||
287
- '';
306
+ target.addEventListener('click', handleHide);
288
307
 
289
- saveTitle(titleNode);
308
+ const title =
309
+ titleNode.getAttribute('title') ||
310
+ titleNode.getAttribute('data-title') ||
311
+ '';
290
312
 
291
- const customDelay = titleNode.getAttribute('data-tooltip-delay');
292
- const newAlign = titleNode.getAttribute(
293
- 'data-tooltip-align'
294
- ) as typeof align;
295
- const setAsHTML = !!titleNode.getAttribute(
296
- 'data-title-set-as-html'
297
- );
313
+ saveTitle(titleNode);
298
314
 
299
- clearTimeout(timeoutIdRef.current);
315
+ const customDelay =
316
+ titleNode.getAttribute('data-tooltip-delay');
317
+ const newAlign = titleNode.getAttribute(
318
+ 'data-tooltip-align'
319
+ ) as typeof align;
320
+ const setAsHTML = !!titleNode.getAttribute(
321
+ 'data-title-set-as-html'
322
+ );
300
323
 
301
- timeoutIdRef.current = setTimeout(
302
- () => {
303
- dispatch({
304
- align: newAlign || align,
305
- message: title,
306
- setAsHTML,
307
- type: 'show',
308
- });
309
- },
310
- customDelay ? Number(customDelay) : delay
311
- );
312
- }
313
- }, []);
324
+ const isFloating = titleNode.getAttribute(
325
+ 'data-tooltip-floating'
326
+ );
327
+
328
+ clearTimeout(timeoutIdRef.current);
329
+
330
+ timeoutIdRef.current = setTimeout(
331
+ () => {
332
+ dispatch({
333
+ align: newAlign || align,
334
+ floating: Boolean(isFloating),
335
+ message: title,
336
+ setAsHTML,
337
+ type: 'show',
338
+ });
339
+ },
340
+ customDelay ? Number(customDelay) : delay
341
+ );
342
+ }
343
+ },
344
+ []
345
+ );
314
346
 
315
347
  useEffect(() => {
316
348
  const handleEsc = (event: KeyboardEvent) => {
@@ -345,12 +377,39 @@ const TooltipProvider = ({
345
377
  disposeHideEvents.forEach(({dispose}) => dispose());
346
378
  };
347
379
  }
348
- }, []);
380
+ }, [handleShow]);
381
+
382
+ useEffect(() => {
383
+ if (
384
+ (tooltipRef as React.RefObject<HTMLDivElement>).current &&
385
+ show &&
386
+ floating
387
+ ) {
388
+ const points = ALIGNMENTS_MAP[align || 'top'] as [string, string];
389
+
390
+ const [clientX, clientY] = mousePosition;
391
+
392
+ alignPoint(
393
+ (tooltipRef as React.RefObject<HTMLDivElement>).current!,
394
+ {
395
+ clientX,
396
+ clientY,
397
+ },
398
+ {
399
+ offset: OFFSET_MAP[
400
+ points.join('') as keyof typeof OFFSET_MAP
401
+ ] as [number, number],
402
+ points,
403
+ }
404
+ );
405
+ }
406
+ }, [mousePosition, show, floating]);
349
407
 
350
408
  useEffect(() => {
351
409
  if (
352
410
  titleNodeRef.current &&
353
- (tooltipRef as React.RefObject<HTMLDivElement>).current
411
+ (tooltipRef as React.RefObject<HTMLDivElement>).current &&
412
+ !floating
354
413
  ) {
355
414
  const points = ALIGNMENTS_MAP[align || 'top'] as [string, string];
356
415