@atlaskit/editor-plugin-mentions
Version:
Mentions plugin for @atlaskit/editor-core
193 lines (186 loc) • 8.19 kB
JavaScript
/* disabledTooltipRenderer.tsx generated by @compiled/babel-plugin v0.39.1 */
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.disabledTooltipRenderer = void 0;
require("./disabledTooltipRenderer.compiled.css");
var _runtime = require("@compiled/react/runtime");
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = _interopRequireWildcard(require("react"));
var _bindEventListener = require("bind-event-listener");
var _v = _interopRequireDefault(require("uuid/v4"));
var _tooltip = _interopRequireDefault(require("@atlaskit/tooltip"));
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- mirror existing renderer pattern
var styles = {
hiddenTrigger: "_1e0cglyw"
};
/**
* ADS `<Tooltip>` hands us a ref via its render-prop child. That ref may be
* either a callback ref or a mutable ref object — React supports both shapes
* and ADS's typing keeps both possible. This helper assigns the supplied
* element to whichever ref shape was provided so the tooltip ends up using
* the chip's bounding box for positioning and its DOM for trigger events.
*/
var assignRef = function assignRef(ref, element) {
if (typeof ref === 'function') {
ref(element);
} else if (ref) {
ref.current = element;
}
};
/**
* Names of the React-style trigger-prop handlers we forward from ADS
* `<Tooltip>` onto the chip element.
*/
/**
* Maps each React-style trigger-prop handler ADS `<Tooltip>` hands us in its
* render-prop callback to the DOM event name we attach to the chip via
* `bind-event-listener`. The chip lives in the ProseMirror document and is
* not a React child of the tooltip, so we have to bridge React handlers to
* native event listeners ourselves.
*
* Names are listed in the same order ADS internally registers them.
*/
var TRIGGER_EVENT_MAP = [['onMouseOver', 'mouseover'], ['onMouseOut', 'mouseout'], ['onMouseMove', 'mousemove'], ['onMouseDown', 'mousedown'], ['onFocus', 'focusin'], ['onBlur', 'focusout']];
/**
* Anchors an ADS `<Tooltip>` to a ProseMirror chip element that is **not** a
* React child of the tooltip. The chip itself stays in the PM document; this
* renderer mounts an always-present React subtree via `portalProviderAPI` whose
* sole job is to host the tooltip and forward the ADS-provided trigger ref +
* event handlers onto the chip.
*
* The forwarding is deliberate: ADS `<Tooltip>` expects to attach its hover /
* focus / blur listeners to its render-prop child, but our render-prop child
* is a `display: none` placeholder span that no real event can reach. We bridge
* those listeners to the chip via `addEventListener` so the tooltip opens and
* closes in response to the user actually interacting with the chip — keyboard
* focus, mouse hover, screen-reader focus, the lot.
*/
/**
* Hook that mirrors ADS Tooltip's React trigger props onto a DOM element
* which is not a React child of the tooltip. Re-attaches whenever ADS hands
* us a fresh set of props (which happens on every render of the render-prop
* child) and cleans up on unmount.
*
* We use `bind-event-listener`'s `bindAll` rather than raw
* `addEventListener` / `removeEventListener` calls so the lifetime of every
* subscription is paired with a single `UnbindFn` — the AFM-mandated pattern
* for keeping listener bookkeeping leak-free.
*/
var useBridgedTriggerListeners = function useBridgedTriggerListeners(chip, triggerProps) {
(0, _react.useEffect)(function () {
// Build the bindAll bindings array out of only the handlers ADS actually
// supplied. Each React handler is wrapped in a thin adapter so the
// listener signature matches the native `EventListener` shape; ADS
// handlers ignore the synthetic-event-only fields they don't use
// (target, currentTarget), so passing the raw DOM event through
// `unknown` is safe in practice.
var bindings = TRIGGER_EVENT_MAP.flatMap(function (_ref) {
var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
propName = _ref2[0],
eventName = _ref2[1];
var handler = triggerProps[propName];
if (!handler) {
return [];
}
return [{
type: eventName,
listener: function listener(event) {
handler(event);
}
}];
});
if (bindings.length === 0) {
return;
}
var unbind = (0, _bindEventListener.bindAll)(chip, bindings);
return unbind;
}, [chip, triggerProps]);
};
var AnchoredTooltip = function AnchoredTooltip(_ref3) {
var subscribe = _ref3.subscribe,
getInitialTooltip = _ref3.getInitialTooltip,
referenceElement = _ref3.referenceElement;
var _useState = (0, _react.useState)(getInitialTooltip),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
tooltip = _useState2[0],
setTooltipState = _useState2[1];
(0, _react.useEffect)(function () {
return subscribe(setTooltipState);
}, [subscribe]);
if (!tooltip) {
return null;
}
return /*#__PURE__*/_react.default.createElement(_tooltip.default, {
content: tooltip,
position: "top"
}, function (tooltipProps) {
return /*#__PURE__*/_react.default.createElement(TriggerBridge, {
referenceElement: referenceElement,
tooltipProps: tooltipProps
});
});
};
/**
* Render-prop child for ADS `<Tooltip>`. The element it returns is a
* `display: none` placeholder that satisfies the render-prop API; the
* real trigger surface is the chip in the PM document, which receives
* both the ADS ref and the bridged event listeners via the side-effects
* declared on this component.
*/
var TriggerBridge = function TriggerBridge(_ref4) {
var referenceElement = _ref4.referenceElement,
tooltipProps = _ref4.tooltipProps;
useBridgedTriggerListeners(referenceElement, tooltipProps);
return /*#__PURE__*/_react.default.createElement("span", {
ref: function ref() {
return assignRef(tooltipProps.ref, referenceElement);
},
"aria-hidden": "true",
className: (0, _runtime.ax)([styles.hiddenTrigger])
});
};
var disabledTooltipRenderer = exports.disabledTooltipRenderer = function disabledTooltipRenderer(_ref5) {
var chipElement = _ref5.chipElement,
portalProviderAPI = _ref5.portalProviderAPI;
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- mirror existing renderer pattern
var key = (0, _v.default)();
var currentTooltip;
var listeners = new Set();
var broadcast = function broadcast() {
listeners.forEach(function (listener) {
return listener(currentTooltip);
});
};
var getInitialTooltip = function getInitialTooltip() {
return currentTooltip;
};
var subscribe = function subscribe(listener) {
listeners.add(listener);
return function () {
listeners.delete(listener);
};
};
var renderElement = function renderElement() {
return /*#__PURE__*/_react.default.createElement(AnchoredTooltip, {
referenceElement: chipElement,
getInitialTooltip: getInitialTooltip,
subscribe: subscribe
});
};
portalProviderAPI.render(renderElement, chipElement, key);
return {
setTooltip: function setTooltip(text) {
currentTooltip = text;
broadcast();
},
destroy: function destroy() {
portalProviderAPI.remove(key);
listeners.clear();
}
};
};