@atlaskit/renderer
Version:
Renderer component
224 lines • 9.25 kB
JavaScript
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import React, { createContext, useCallback, useContext, useMemo, useReducer } from 'react';
var initialState = {
type: null,
selectionRange: null,
hoverRange: null,
selectionDraftRange: null,
hoverDraftRange: null,
selectionDraftDocumentPosition: null,
hoverDraftDocumentPosition: null
};
function reducer(state, action) {
switch (action.type) {
case 'clearSelection':
if (state.selectionRange !== null) {
return _objectSpread(_objectSpread({}, state), {}, {
selectionRange: null,
type: state.type === 'selection' ? null : state.type
});
}
return state;
case 'clearHover':
{
if (state.hoverRange !== null) {
return _objectSpread(_objectSpread({}, state), {}, {
hoverRange: null,
type: state.type === 'hover' ? null : state.type
});
}
return state;
}
case 'setSelection':
if (state.selectionRange !== action.range) {
return _objectSpread(_objectSpread({}, state), {}, {
selectionRange: action.range,
type: 'selection'
});
}
return state;
case 'setHover':
if (state.hoverRange !== action.range) {
return _objectSpread(_objectSpread({}, state), {}, {
hoverRange: action.range,
type: 'hover'
});
}
return state;
case 'promoteSelectionToDraft':
// we should only promote the range to a draft if the current range type is a selection
// we should also store the promotion type, so that a clear will not accidently clear the draft of a
// different type
if (state.selectionDraftRange !== state.selectionRange) {
return _objectSpread(_objectSpread({}, state), {}, {
selectionRange: null,
type: state.type === 'selection' ? null : state.type,
selectionDraftRange: state.selectionRange,
selectionDraftDocumentPosition: action.position
});
}
return state;
case 'promoteHoverToDraft':
if (state.hoverDraftRange !== state.hoverRange) {
return _objectSpread(_objectSpread({}, state), {}, {
hoverRange: null,
type: state.type === 'hover' ? null : state.type,
hoverDraftRange: state.hoverRange,
hoverDraftDocumentPosition: action.position
});
}
return state;
case 'clearSelectionDraft':
if (state.selectionDraftRange !== null) {
return _objectSpread(_objectSpread({}, state), {}, {
selectionDraftRange: null,
selectionDraftDocumentPosition: null
});
}
return state;
case 'clearHoverDraft':
if (state.hoverDraftRange !== null) {
return _objectSpread(_objectSpread({}, state), {}, {
hoverDraftRange: null,
hoverDraftDocumentPosition: null
});
}
return state;
}
}
export var AnnotationRangeStateContext = /*#__PURE__*/createContext({
range: null,
type: null,
selectionDraftRange: null,
hoverDraftRange: null,
selectionDraftDocumentPosition: null,
hoverDraftDocumentPosition: null
});
export var AnnotationRangeDispatchContext = /*#__PURE__*/createContext({
clearSelectionRange: function clearSelectionRange() {},
clearHoverRange: function clearHoverRange() {},
setSelectionRange: function setSelectionRange() {},
promoteSelectionToDraft: function promoteSelectionToDraft() {},
promoteHoverToDraft: function promoteHoverToDraft() {},
clearSelectionDraft: function clearSelectionDraft() {},
clearHoverDraft: function clearHoverDraft() {}
});
export var AnnotationRangeProviderInner = function AnnotationRangeProviderInner(_ref) {
var children = _ref.children,
allowCommentsOnMedia = _ref.allowCommentsOnMedia;
var _useReducer = useReducer(reducer, initialState),
_useReducer2 = _slicedToArray(_useReducer, 2),
_useReducer2$ = _useReducer2[0],
selectionRange = _useReducer2$.selectionRange,
hoverRange = _useReducer2$.hoverRange,
type = _useReducer2$.type,
selectionDraftRange = _useReducer2$.selectionDraftRange,
selectionDraftDocumentPosition = _useReducer2$.selectionDraftDocumentPosition,
hoverDraftRange = _useReducer2$.hoverDraftRange,
hoverDraftDocumentPosition = _useReducer2$.hoverDraftDocumentPosition,
dispatch = _useReducer2[1];
var clearSelectionRange = useCallback(function () {
return dispatch({
type: 'clearSelection'
});
}, []);
var clearHoverRange = useCallback(function () {
return dispatch({
type: 'clearHover'
});
}, []);
var setSelectionRange = useCallback(function (range) {
return dispatch({
type: 'setSelection',
range: range
});
}, []);
var setHoverTarget = useCallback(function (target) {
// the HoverComponent expects an element deeply nested inside media, these classes work with the current implementation
var mediaNode = target.querySelector('.media-card-inline-player, .media-file-card-view');
if (!mediaNode) {
return;
}
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage -- range for media hover highlight
var range = document.createRange();
range.setStartBefore(mediaNode);
range.setEndAfter(mediaNode);
dispatch({
type: 'setHover',
range: range
});
}, []);
var promoteSelectionToDraft = useCallback(function (position) {
dispatch({
type: 'promoteSelectionToDraft',
position: position
});
}, []);
var clearSelectionDraft = useCallback(function () {
dispatch({
type: 'clearSelectionDraft'
});
}, []);
var promoteHoverToDraft = useCallback(function (position) {
dispatch({
type: 'promoteHoverToDraft',
position: position
});
}, []);
var clearHoverDraft = useCallback(function () {
dispatch({
type: 'clearHoverDraft'
});
}, []);
var stateData = useMemo(function () {
return {
// We techinically have two ranges, however we only want to expose one of them at a time, because only one draft
// can be active at a time. The type of range is used to determine which range is active.
range: type === 'selection' ? selectionRange : hoverRange,
type: type,
selectionDraftRange: selectionDraftRange,
hoverDraftRange: hoverDraftRange,
selectionDraftDocumentPosition: selectionDraftDocumentPosition,
hoverDraftDocumentPosition: hoverDraftDocumentPosition
};
}, [selectionRange, hoverRange, type, selectionDraftRange, selectionDraftDocumentPosition, hoverDraftRange, hoverDraftDocumentPosition]);
var dispatchData = useMemo(function () {
return {
clearSelectionRange: clearSelectionRange,
clearHoverRange: clearHoverRange,
setSelectionRange: setSelectionRange,
setHoverTarget: !!allowCommentsOnMedia ? setHoverTarget : undefined,
promoteSelectionToDraft: promoteSelectionToDraft,
promoteHoverToDraft: promoteHoverToDraft,
clearSelectionDraft: clearSelectionDraft,
clearHoverDraft: clearHoverDraft
};
}, [allowCommentsOnMedia, clearSelectionRange, clearHoverRange, setSelectionRange, setHoverTarget, promoteSelectionToDraft, promoteHoverToDraft, clearSelectionDraft, clearHoverDraft]);
return /*#__PURE__*/React.createElement(AnnotationRangeStateContext.Provider, {
value: stateData
}, /*#__PURE__*/React.createElement(AnnotationRangeDispatchContext.Provider, {
value: dispatchData
}, children));
};
export var AnnotationRangeProvider = function AnnotationRangeProvider(_ref2) {
var children = _ref2.children,
allowCommentsOnMedia = _ref2.allowCommentsOnMedia,
isNestedRender = _ref2.isNestedRender;
/*
* If this is a nested render, we do not provide the context
* because it has already been provided higher up the component tree
* and we need the original context to create annotations on extensions.
*/
return isNestedRender ? /*#__PURE__*/React.createElement(React.Fragment, null, children) : /*#__PURE__*/React.createElement(AnnotationRangeProviderInner, {
allowCommentsOnMedia: allowCommentsOnMedia
}, children);
};
export var useAnnotationRangeState = function useAnnotationRangeState() {
return useContext(AnnotationRangeStateContext);
};
export var useAnnotationRangeDispatch = function useAnnotationRangeDispatch() {
return useContext(AnnotationRangeDispatchContext);
};