UNPKG

rlayers

Version:

React Components for OpenLayers

154 lines 6.56 kB
import React from 'react'; import { createRoot } from 'react-dom/client'; import { LRUCache } from 'lru-cache'; import Style from 'ol/style/Style'; import { RContext } from '../context'; import debug from '../debug'; import { flushSync } from 'react-dom'; export const useRStyle = () => React.useRef(undefined); export const createRStyle = () => React.createRef(); /** * A style, all other style components must be descendants of `RStyle` * * It can be used with a React reference - `RStyleRef` which is a shortcut for * `React.RefObject<RStyle>` and a subtype of `RStyleLike` * * Or it can also be nested inside a vector layer to be * automatically assigned as the default style of that layer * * This is the only component that does not have to be part of an `RMap` * * It provides the special `RStyle` context */ class RStyle extends React.PureComponent { constructor(props) { super(props); this.style = (f, r) => { if (this.ol !== this.style) return this.ol; let hash; if (this.cache) { hash = this.props.cacheId(f, r); const style = this.cache.get(hash); if (style) return style; } const style = new Style({ zIndex: this.props.zIndex }); const reactElement = (React.createElement(RContext.Provider, { value: Object.assign(Object.assign({}, this.context), { style }) }, this.props.render(f, r))); const root = createRoot(document.createElement('div')); // React 18 renders asynchronously while OpenLayers does not // support an asynchronous StyleFunction flushSync(() => { root.render(reactElement); }); if (this.cache) this.cache.set(hash, style); return style; }; if (props.render) this.ol = this.style; else this.ol = new Style({ zIndex: props.zIndex }); if (props.render && props.cacheSize && props.cacheId) this.cache = new LRUCache({ max: props.cacheSize }); } componentDidMount() { this.refresh(); } componentDidUpdate(prevProps, prev, snap) { if (this.props !== prevProps) { debug('willRefresh', this, prevProps, this.props); this.refresh(prevProps); } } refresh(prevProps) { var _a, _b, _c, _d, _e, _f, _g; if (!prevProps || (prevProps === null || prevProps === void 0 ? void 0 : prevProps.render) !== this.props.render) { if ((_a = this.context) === null || _a === void 0 ? void 0 : _a.styleArray) { if (this.ol === this.style) throw new Error('An RStyleArray must contain only static RStyles'); if (!this.context.styleArray.includes(this.ol)) this.context.styleArray.push(this.ol); } else if ((_c = (_b = this.context) === null || _b === void 0 ? void 0 : _b.feature) === null || _c === void 0 ? void 0 : _c.setStyle) { this.context.feature.setStyle(this.ol); } else if ((_e = (_d = this.context) === null || _d === void 0 ? void 0 : _d.vectorlayer) === null || _e === void 0 ? void 0 : _e.setStyle) { this.context.vectorlayer.setStyle(this.ol); } else if ((_g = (_f = this.context) === null || _f === void 0 ? void 0 : _f.vectortilelayer) === null || _g === void 0 ? void 0 : _g.setStyle) { this.context.vectortilelayer.setStyle(this.ol); } if (this.cache) this.cache.clear(); } if (this.ol instanceof Style && (!prevProps || prevProps.zIndex !== this.props.zIndex)) this.ol.setZIndex(this.props.zIndex); } render() { if (this.props.render) return null; return (React.createElement("div", { className: '_rlayers_RStyle' }, React.createElement(RContext.Provider, { value: Object.assign(Object.assign({}, this.context), { style: this.ol }) }, this.props.children))); } /** This is a static function that will return an * OpenLayers-compatible `StyleLike` from an `RStyleLike`. * * @param {RStyleLike} style * @public */ static getStyle(style) { // style is undefined or null if (style === null || style === undefined) return style; // style is RStyle or RStyleArray if (typeof style.style === 'function') return (f, r) => style.style(f, r); // style is a React.RefObject // React.RefObjects are just plain JS objects after JS transpilation */ if (Object.keys(style).includes('current')) return (f, r) => style.current.style(f, r); // style is an OpenLayers StyleLike return style; } /** This is a static function that will return an * OpenLayers-compatible `Style` from a static `RStyleLike`. * This discards the reference and the returned style won't * be updated if the referenced `<RStyle>` is updated. * * It throws if the reference is a dynamic style. * * @param {RStyleLike} style * @public */ static getStyleStatic(style) { // style is undefined or null if (style === null || style === undefined) return style; let asRStyle; // style is RStyle or RStyleArray if (typeof style.style === 'function') asRStyle = style; // style is a React.RefObject // React.RefObjects are just plain JS objects after JS transpilation if (Object.keys(style).includes('current')) { asRStyle = style.current; if (asRStyle === undefined || asRStyle === null) return undefined; } if (asRStyle) { // style is a static RStyle or RStyleArray or reference if (asRStyle.ol !== undefined && typeof asRStyle.ol !== 'function') return asRStyle.ol; // style is a dynamic RStyle or RStyleArray or reference throw new TypeError('RStyle is dynamic and cannot be converted to Style'); } // style is an OpenLayers StyleLike if (typeof style === 'function') throw new TypeError('StyleLike is dynamic and cannot be converted to Style'); return style; } } RStyle.contextType = RContext; export default RStyle; //# sourceMappingURL=RStyle.js.map