@clayui/tooltip
Advanced tools
Comparing version 3.27.0 to 3.28.0
@@ -6,2 +6,9 @@ # Change Log | ||
# [3.28.0](https://github.com/liferay/clay/compare/v3.27.0...v3.28.0) (2021-05-19) | ||
### Features | ||
- **@clayui/tooltip:** Add the new ContainerProps API ([728600c](https://github.com/liferay/clay/commit/728600c)) | ||
- **@clayui/tooltip:** update logic to handle scoping and a global listener ([1c83d30](https://github.com/liferay/clay/commit/1c83d30)) | ||
# [3.27.0](https://github.com/liferay/clay/compare/v3.26.0...v3.27.0) (2021-05-05) | ||
@@ -8,0 +15,0 @@ |
@@ -0,1 +1,2 @@ | ||
import { IPortalBaseProps } from '@clayui/shared'; | ||
import React from 'react'; | ||
@@ -6,8 +7,17 @@ declare type TContentRenderer = (props: { | ||
}) => React.ReactElement | React.ReactNode; | ||
declare const TooltipProvider: React.FunctionComponent<{ | ||
interface IPropsBase { | ||
autoAlign?: boolean; | ||
children: React.ReactElement; | ||
containerProps?: IPortalBaseProps; | ||
contentRenderer?: TContentRenderer; | ||
delay?: number; | ||
}>; | ||
} | ||
interface IPropsWithChildren extends IPropsBase { | ||
children: React.ReactElement; | ||
scope?: never; | ||
} | ||
interface IPropsWithScope extends IPropsBase { | ||
children?: never; | ||
scope: string; | ||
} | ||
declare const TooltipProvider: React.FunctionComponent<IPropsWithChildren | IPropsWithScope>; | ||
export default TooltipProvider; |
@@ -72,4 +72,7 @@ "use strict"; | ||
message: '', | ||
setAsHTML: false, | ||
show: false | ||
}; | ||
var TRIGGER_HIDE_EVENTS = ['mouseout', 'mouseup', 'pointerup', 'touchend']; | ||
var TRIGGER_SHOW_EVENTS = ['mouseover', 'mouseup', 'pointerdown', 'touchstart']; | ||
@@ -135,2 +138,4 @@ var reducer = function reducer(state, _ref) { | ||
children = _ref2.children, | ||
_ref2$containerProps = _ref2.containerProps, | ||
containerProps = _ref2$containerProps === void 0 ? {} : _ref2$containerProps, | ||
_ref2$contentRenderer = _ref2.contentRenderer, | ||
@@ -141,3 +146,4 @@ contentRenderer = _ref2$contentRenderer === void 0 ? function (props) { | ||
_ref2$delay = _ref2.delay, | ||
delay = _ref2$delay === void 0 ? 600 : _ref2$delay; | ||
delay = _ref2$delay === void 0 ? 600 : _ref2$delay, | ||
scope = _ref2.scope; | ||
@@ -150,2 +156,3 @@ var _React$useReducer = _react.default.useReducer(reducer, initialState), | ||
message = _React$useReducer2$$m === void 0 ? '' : _React$useReducer2$$m, | ||
setAsHTML = _React$useReducer2$.setAsHTML, | ||
show = _React$useReducer2$.show, | ||
@@ -163,45 +170,66 @@ dispatch = _React$useReducer2[1]; // Using `any` type since TS incorrectly infers setTimeout to be from NodeJS | ||
var handleHide = (0, _react.useCallback)(function (_ref3) { | ||
var target = _ref3.target; | ||
var saveTitle = (0, _react.useCallback)(function (element) { | ||
titleNodeRef.current = element; | ||
var title = element.getAttribute('title'); | ||
if (!titleNodeRef.current) { | ||
return; | ||
if (title) { | ||
element.setAttribute('data-restore-title', title); | ||
element.removeAttribute('title'); | ||
} else if (element.tagName === 'svg') { | ||
var titleTag = element.querySelector('title'); | ||
if (titleTag) { | ||
element.setAttribute('data-restore-title', titleTag.innerHTML); | ||
titleTag.remove(); | ||
} | ||
} | ||
}, []); | ||
var restoreTitle = (0, _react.useCallback)(function () { | ||
var element = titleNodeRef.current; | ||
var dataTitle = titleNodeRef.current.getAttribute('data-title'); | ||
if (element) { | ||
var title = element.getAttribute('data-restore-title'); | ||
if (dataTitle) { | ||
document.removeEventListener('keyup', handleEsc, true); | ||
target.removeEventListener('click', handleHide); | ||
titleNodeRef.current.setAttribute('title', dataTitle); | ||
titleNodeRef.current.removeAttribute('data-title'); | ||
if (title) { | ||
if (element.tagName === 'svg') { | ||
var titleTag = document.createElement('title'); | ||
titleTag.innerHTML = title; | ||
element.appendChild(titleTag); | ||
} else { | ||
element.setAttribute('title', title); | ||
} | ||
element.removeAttribute('data-restore-title'); | ||
} | ||
titleNodeRef.current = null; | ||
targetRef.current = null; | ||
dispatch({ | ||
type: 'hide' | ||
}); | ||
clearTimeout(timeoutIdRef.current); | ||
} | ||
}, []); | ||
var handleEsc = (0, _react.useCallback)(function (event) { | ||
if (event.key === _shared.Keys.Esc) { | ||
event.stopImmediatePropagation(); | ||
handleHide(event); | ||
var handleHide = (0, _react.useCallback)(function () { | ||
dispatch({ | ||
type: 'hide' | ||
}); | ||
clearTimeout(timeoutIdRef.current); | ||
restoreTitle(); | ||
if (targetRef.current) { | ||
targetRef.current.removeEventListener('click', handleHide); | ||
targetRef.current = null; | ||
} | ||
}, []); | ||
var handleShow = (0, _react.useCallback)(function (_ref4) { | ||
var target = _ref4.target; | ||
var hasTitle = target && target.hasAttribute('title'); | ||
var titleNode = hasTitle ? target : closestAncestor(target, '[title]'); | ||
var title = titleNode && titleNode.getAttribute('title'); | ||
var handleShow = (0, _react.useCallback)(function (_ref3) { | ||
var target = _ref3.target; | ||
targetRef.current = target; | ||
var hasTitle = target && (target.hasAttribute('title') || target.hasAttribute('data-title')); | ||
var titleNode = hasTitle ? target : closestAncestor(target, '[title], [data-title]'); | ||
if (title) { | ||
titleNodeRef.current = titleNode; | ||
targetRef.current = target; | ||
document.addEventListener('keyup', handleEsc, true); | ||
if (titleNode) { | ||
target.addEventListener('click', handleHide); | ||
titleNode.setAttribute('data-title', title); | ||
titleNode.removeAttribute('title'); | ||
var title = titleNode.getAttribute('title') || titleNode.getAttribute('data-title') || ''; | ||
saveTitle(titleNode); | ||
var customDelay = titleNode.getAttribute('data-tooltip-delay'); | ||
var newAlign = titleNode.getAttribute('data-tooltip-align'); | ||
var _setAsHTML = !!titleNode.getAttribute('data-title-set-as-html'); | ||
timeoutIdRef.current = setTimeout(function () { | ||
@@ -211,2 +239,3 @@ dispatch({ | ||
message: title, | ||
setAsHTML: _setAsHTML, | ||
type: 'show' | ||
@@ -219,2 +248,37 @@ }); | ||
_react.default.useEffect(function () { | ||
var handleEsc = function handleEsc(event) { | ||
if (show && event.key === _shared.Keys.Esc) { | ||
event.stopImmediatePropagation(); | ||
handleHide(); | ||
} | ||
}; | ||
document.addEventListener('keyup', handleEsc, true); | ||
return function () { | ||
return document.removeEventListener('keyup', handleEsc, true); | ||
}; | ||
}, [show]); | ||
_react.default.useEffect(function () { | ||
if (scope) { | ||
var disposeShowEvents = TRIGGER_SHOW_EVENTS.map(function (eventName) { | ||
return (0, _shared.delegate)(document.body, eventName, scope, handleShow); | ||
}); | ||
var disposeHideEvents = TRIGGER_HIDE_EVENTS.map(function (eventName) { | ||
return (0, _shared.delegate)(document.body, eventName, scope, handleHide); | ||
}); | ||
return function () { | ||
disposeShowEvents.forEach(function (_ref4) { | ||
var dispose = _ref4.dispose; | ||
return dispose(); | ||
}); | ||
disposeHideEvents.forEach(function (_ref5) { | ||
var dispose = _ref5.dispose; | ||
return dispose(); | ||
}); | ||
}; | ||
} | ||
}, []); | ||
_react.default.useEffect(function () { | ||
if (titleNodeRef.current && tooltipRef.current) { | ||
@@ -240,11 +304,18 @@ var points = ALIGNMENTS_MAP[align || 'top']; | ||
"production" !== "production" ? (0, _warning.default)(children.type !== _react.default.Fragment, '<TooltipProvider />: React Fragment is not allowed as a child to TooltipProvider. Child must be a single HTML element.') : void 0; | ||
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, show && /*#__PURE__*/_react.default.createElement(_shared.ClayPortal, null, /*#__PURE__*/_react.default.createElement(_Tooltip.default, { | ||
"production" !== "production" ? (0, _warning.default)(!children && !scope, '<TooltipProvider />: You must use at least one of the following props: `children` or `scope`.') : void 0; | ||
"production" !== "production" ? (0, _warning.default)(children && scope, '<TooltipProvider />: If you want to use `scope`, use <TooltipProvider /> as a singleton and do not pass `children`.') : void 0; | ||
"production" !== "production" ? (0, _warning.default)((children === null || children === void 0 ? void 0 : children.type) !== _react.default.Fragment, '<TooltipProvider />: React Fragment is not allowed as a child to TooltipProvider. Child must be a single HTML element that accepts `onMouseOver` and `onMouseOut`.') : void 0; | ||
var titleContent = contentRenderer({ | ||
targetNode: targetRef.current, | ||
title: message | ||
}); | ||
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, show && /*#__PURE__*/_react.default.createElement(_shared.ClayPortal, containerProps, /*#__PURE__*/_react.default.createElement(_Tooltip.default, { | ||
alignPosition: align, | ||
ref: tooltipRef, | ||
show: true | ||
}, contentRenderer({ | ||
targetNode: targetRef.current, | ||
title: message | ||
}))), /*#__PURE__*/_react.default.cloneElement(children, _objectSpread(_objectSpread({}, children.props), {}, { | ||
}, setAsHTML && typeof titleContent === 'string' ? /*#__PURE__*/_react.default.createElement("span", { | ||
dangerouslySetInnerHTML: { | ||
__html: titleContent | ||
} | ||
}) : titleContent)), scope ? children : children && /*#__PURE__*/_react.default.cloneElement(children, _objectSpread(_objectSpread({}, children.props), {}, { | ||
onMouseOut: handleHide, | ||
@@ -251,0 +322,0 @@ onMouseOver: handleShow |
{ | ||
"name": "@clayui/tooltip", | ||
"version": "3.27.0", | ||
"version": "3.28.0", | ||
"description": "ClayTooltip component", | ||
@@ -29,3 +29,3 @@ "license": "BSD-3-Clause", | ||
"dependencies": { | ||
"@clayui/shared": "^3.27.0", | ||
"@clayui/shared": "^3.28.0", | ||
"classnames": "^2.2.6", | ||
@@ -43,3 +43,3 @@ "dom-align": "^1.10.2", | ||
], | ||
"gitHead": "6ee32869e2f42a392edfc6ad0d9f9d746891d685" | ||
"gitHead": "dfce61d2ca779673ed2214aa5ff4ca71a1fa22bf" | ||
} |
Sorry, the diff of this file is not supported yet
40169
801
Updated@clayui/shared@^3.28.0