UNPKG

@atlaskit/renderer

Version:
224 lines • 9.25 kB
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); };