UNPKG

@gechiui/block-editor

Version:
149 lines (138 loc) 4.65 kB
import { createElement } from "@gechiui/element"; /** * External dependencies */ import classnames from 'classnames'; /** * GeChiUI dependencies */ import { AsyncModeProvider, useSelect } from '@gechiui/data'; import { useViewportMatch, useMergeRefs } from '@gechiui/compose'; import { createContext, useState, useMemo } from '@gechiui/element'; /** * Internal dependencies */ import BlockListBlock from './block'; import BlockListAppender from '../block-list-appender'; import { useInBetweenInserter } from './use-in-between-inserter'; import { store as blockEditorStore } from '../../store'; import { usePreParsePatterns } from '../../utils/pre-parse-patterns'; import { LayoutProvider, defaultLayout } from './layout'; import BlockToolsBackCompat from '../block-tools/back-compat'; import { useBlockSelectionClearer } from '../block-selection-clearer'; import { useInnerBlocksProps } from '../inner-blocks'; import { BlockEditContextProvider, DEFAULT_BLOCK_EDIT_CONTEXT } from '../block-edit/context'; const elementContext = createContext(); export const IntersectionObserver = createContext(); function Root(_ref) { let { className, ...settings } = _ref; const [element, setElement] = useState(); const isLargeViewport = useViewportMatch('medium'); const { isOutlineMode, isFocusMode, isNavigationMode } = useSelect(select => { const { getSettings, isNavigationMode: _isNavigationMode } = select(blockEditorStore); const { outlineMode, focusMode } = getSettings(); return { isOutlineMode: outlineMode, isFocusMode: focusMode, isNavigationMode: _isNavigationMode() }; }, []); const innerBlocksProps = useInnerBlocksProps({ ref: useMergeRefs([useBlockSelectionClearer(), useInBetweenInserter(), setElement]), className: classnames('is-root-container', className, { 'is-outline-mode': isOutlineMode, 'is-focus-mode': isFocusMode && isLargeViewport, 'is-navigate-mode': isNavigationMode }) }, settings); return createElement(elementContext.Provider, { value: element }, createElement("div", innerBlocksProps)); } export default function BlockList(settings) { usePreParsePatterns(); return createElement(BlockToolsBackCompat, null, createElement(BlockEditContextProvider, { value: DEFAULT_BLOCK_EDIT_CONTEXT }, createElement(Root, settings))); } BlockList.__unstableElementContext = elementContext; function Items(_ref2) { let { placeholder, rootClientId, renderAppender, __experimentalAppenderTagName, __experimentalLayout: layout = defaultLayout } = _ref2; const [intersectingBlocks, setIntersectingBlocks] = useState(new Set()); const intersectionObserver = useMemo(() => { const { IntersectionObserver: Observer } = window; if (!Observer) { return; } return new Observer(entries => { setIntersectingBlocks(oldIntersectingBlocks => { const newIntersectingBlocks = new Set(oldIntersectingBlocks); for (const entry of entries) { const clientId = entry.target.getAttribute('data-block'); const action = entry.isIntersecting ? 'add' : 'delete'; newIntersectingBlocks[action](clientId); } return newIntersectingBlocks; }); }); }, [setIntersectingBlocks]); const { order, selectedBlocks } = useSelect(select => { const { getBlockOrder, getSelectedBlockClientIds } = select(blockEditorStore); return { order: getBlockOrder(rootClientId), selectedBlocks: getSelectedBlockClientIds() }; }, [rootClientId]); return createElement(LayoutProvider, { value: layout }, createElement(IntersectionObserver.Provider, { value: intersectionObserver }, order.map(clientId => createElement(AsyncModeProvider, { key: clientId, value: // Only provide data asynchronously if the block is // not visible and not selected. !intersectingBlocks.has(clientId) && !selectedBlocks.includes(clientId) }, createElement(BlockListBlock, { rootClientId: rootClientId, clientId: clientId })))), order.length < 1 && placeholder, createElement(BlockListAppender, { tagName: __experimentalAppenderTagName, rootClientId: rootClientId, renderAppender: renderAppender })); } export function BlockListItems(props) { // This component needs to always be synchronous as it's the one changing // the async mode depending on the block selection. return createElement(AsyncModeProvider, { value: false }, createElement(Items, props)); } //# sourceMappingURL=index.js.map