{"version":3,"file":"react-tether.cjs","sources":["../src/react-tether.tsx"],"sourcesContent":["import React, { Component, isValidElement } from \"react\";\nimport type { RefObject } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport Tether from \"tether\";\n\ntype TetherEvent = \"repositioned\" | \"update\";\ntype TetherEventHandler = (event?: { top: string; left: \"string\" }) => void;\n\ninterface ReactTetherProps extends Tether.ITetherOptions {\n\t// A HTML tag name. This is the element created in the DOM to contain the tethered component\n\trenderElementTag?: string;\n\n\t// Either a CSS selector to pass to document.querySelector or a DOM node\n\t// This is the location in the DOM the parent render element is created in\n\t// and the tethered component is rendered to\n\trenderElementTo?: string | HTMLElement;\n\n\t// Render prop for the element to be tethered to. This is rendered in place\n\t// of the ReactTether component\n\trenderTarget: (ref: React.RefObject<any>) => void;\n\t// Render prop for the element to be tethered. This is rendered inside the element\n\t// provided by renderElementTo or the end of the body via a React Portal.\n\t// It's wrapped in an element defined by renderElementTag\n\trenderElement?: (ref: React.RefObject<any>) => void;\n\n\t// The id prop for the renderElement defined by renderElementTag\n\tid?: string;\n\n\t// The className prop for the renderElement defined by renderElementTag\n\tclassName?: string;\n\n\t// The style prop for the renderElement defined by renderElementTag\n\tstyle?: Partial<CSSStyleDeclaration>;\n\n\t// Called on Tethers update event\n\tonUpdate?: TetherEventHandler;\n\n\t// Called on Tethers repositioned event\n\tonRepositioned?: TetherEventHandler;\n}\n\nexport default class ReactTether extends Component<ReactTetherProps> {\n\t// The DOM node of the target, obtained using ref in the render prop\n\t_targetNode: RefObject<HTMLElement> = React.createRef();\n\n\t// The DOM node of the element, obtained using ref in the render prop\n\t_elementNode: RefObject<HTMLElement> = React.createRef();\n\n\t_elementParentNode: HTMLElement | null = null;\n\n\t_tetherInstance: Tether | null = null;\n\n\toverride componentDidMount() {\n\t\tthis._createContainer();\n\t\t// The container is created after mounting\n\t\t// so we need to force an update to\n\t\t// enable tether\n\t\t// Cannot move _createContainer into the constructor\n\t\t// because of is a side effect: https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects\n\t\tthis.forceUpdate();\n\t}\n\n\toverride componentDidUpdate(previousProps: ReactTetherProps) {\n\t\t// If the container related props have changed, then update the container\n\t\tif (\n\t\t\tpreviousProps.renderElementTag !== this.props.renderElementTag ||\n\t\t\tpreviousProps.renderElementTo !== this.props.renderElementTo\n\t\t) {\n\t\t\tthis._createContainer();\n\t\t}\n\n\t\t// Verify if className props have changed\n\t\tif (\n\t\t\tthis._elementParentNode &&\n\t\t\tpreviousProps.className !== this.props.className\n\t\t) {\n\t\t\t// Add a bunch of checks against weird classNames\n\t\t\tconst previousClasses = (previousProps.className || \"\")\n\t\t\t\t.split(\" \")\n\t\t\t\t.filter((value) => value.length > 0);\n\t\t\tconst currClasses = (this.props.className || \"\")\n\t\t\t\t.split(\" \")\n\t\t\t\t.filter((value) => value.length > 0);\n\n\t\t\tthis._elementParentNode.classList.remove(...previousClasses);\n\t\t\tthis._elementParentNode.classList.add(...currClasses);\n\t\t}\n\n\t\tthis._update();\n\t}\n\n\toverride componentWillUnmount() {\n\t\tthis._destroy();\n\t}\n\n\tgetTetherInstance() {\n\t\treturn this._tetherInstance;\n\t}\n\n\tdisable() {\n\t\tthis._tetherInstance?.disable();\n\t}\n\n\tenable() {\n\t\tthis._tetherInstance?.enable();\n\t}\n\n\ton(event: TetherEvent, handler: TetherEventHandler, ctx?: unknown) {\n\t\t// @ts-expect-error -- TS types are incomplete\n\t\tthis._tetherInstance.on(event, handler, ctx);\n\t}\n\n\tonce(event: TetherEvent, handler: TetherEventHandler, ctx?: unknown) {\n\t\t// @ts-expect-error -- TS types are incomplete\n\t\tthis._tetherInstance.once(event, handler, ctx);\n\t}\n\n\toff(event: TetherEvent, handler: TetherEventHandler) {\n\t\t// @ts-expect-error -- TS types are incomplete\n\t\tthis._tetherInstance.off(event, handler);\n\t}\n\n\tposition() {\n\t\tthis._tetherInstance?.position();\n\t}\n\n\t_runRenders() {\n\t\t// To obtain the components, we run the render functions and pass in the ref\n\t\t// Later, when the component is mounted, the ref functions will be called\n\t\t// and trigger a tether update\n\t\tlet targetComponent =\n\t\t\ttypeof this.props.renderTarget === \"function\"\n\t\t\t\t? this.props.renderTarget(this._targetNode)\n\t\t\t\t: null;\n\t\tlet elementComponent =\n\t\t\ttypeof this.props.renderElement === \"function\"\n\t\t\t\t? this.props.renderElement(this._elementNode)\n\t\t\t\t: null;\n\n\t\t// Check if what has been returned is a valid react element\n\t\tif (!isValidElement(targetComponent)) {\n\t\t\ttargetComponent = null;\n\t\t}\n\n\t\tif (!isValidElement(elementComponent)) {\n\t\t\telementComponent = null;\n\t\t}\n\n\t\treturn {\n\t\t\ttargetComponent,\n\t\t\telementComponent,\n\t\t};\n\t}\n\n\t_createTetherInstance(tetherOptions: Tether.ITetherOptions) {\n\t\tif (this._tetherInstance) {\n\t\t\tthis._destroy();\n\t\t}\n\n\t\tthis._tetherInstance = new Tether(tetherOptions);\n\t\tthis._registerEventListeners();\n\t}\n\n\t_destroyTetherInstance() {\n\t\tif (this._tetherInstance) {\n\t\t\tthis._tetherInstance.destroy();\n\t\t\tthis._tetherInstance = null;\n\t\t}\n\t}\n\n\t_registerEventListeners() {\n\t\tthis.on(\"update\", (...args) => {\n\t\t\treturn this.props.onUpdate && this.props.onUpdate.apply(this, args);\n\t\t});\n\n\t\tthis.on(\"repositioned\", (...args) => {\n\t\t\treturn (\n\t\t\t\tthis.props.onRepositioned && this.props.onRepositioned.apply(this, args)\n\t\t\t);\n\t\t});\n\t}\n\n\tget _renderNode() {\n\t\tconst { renderElementTo } = this.props;\n\t\tif (typeof renderElementTo === \"string\") {\n\t\t\treturn document.querySelector(renderElementTo);\n\t\t}\n\n\t\treturn renderElementTo || document.body;\n\t}\n\n\t_destroy() {\n\t\tthis._destroyTetherInstance();\n\t\tthis._removeContainer();\n\t}\n\n\t_createContainer() {\n\t\t// Create element node container if it hasn't been yet\n\t\tthis._removeContainer();\n\n\t\tconst { renderElementTag = \"div\", className } = this.props;\n\n\t\t// Create a node that we can stick our content Component in\n\t\tthis._elementParentNode = document.createElement(renderElementTag);\n\t\tthis._elementParentNode.className = className || \"\";\n\t}\n\n\t_addContainerToDOM() {\n\t\t// Append node to the render node\n\t\tif (\n\t\t\tthis._elementParentNode &&\n\t\t\tthis._renderNode &&\n\t\t\tthis._elementParentNode.parentNode !== this._renderNode\n\t\t) {\n\t\t\tthis._renderNode.append(this._elementParentNode);\n\t\t}\n\t}\n\n\t_removeContainer() {\n\t\tif (this._elementParentNode && this._elementParentNode.parentNode) {\n\t\t\tthis._elementParentNode.remove();\n\t\t}\n\t}\n\n\t_update() {\n\t\t// If no element component provided, bail out\n\t\tconst shouldDestroy =\n\t\t\t!this._elementNode.current || !this._targetNode.current;\n\n\t\tif (shouldDestroy) {\n\t\t\t// Destroy Tether element if it has been created\n\t\t\tthis._destroy();\n\t\t\treturn;\n\t\t}\n\n\t\tthis._updateTether();\n\t}\n\n\t_updateTether() {\n\t\tconst {\n\t\t\t// Unused, just making sure not to pass it to tether\n\t\t\tonUpdate,\n\t\t\tonRepositioned,\n\n\t\t\trenderElement,\n\t\t\trenderElementTag,\n\t\t\trenderElementTo,\n\t\t\trenderTarget,\n\n\t\t\tclassName, // This prop is specific to this._elementParentNode\n\t\t\tid, // This prop is specific to this._elementParentNode\n\t\t\tstyle, // This prop is specific to this._elementParentNode\n\n\t\t\t// Tether options\n\t\t\t...options\n\t\t} = this.props;\n\t\tconst tetherOptions = {\n\t\t\ttarget: this._targetNode.current,\n\t\t\telement: this._elementParentNode,\n\t\t\t...options,\n\t\t};\n\n\t\tconst idString = id || \"\";\n\t\tif (this._elementParentNode && this._elementParentNode.id !== idString) {\n\t\t\tthis._elementParentNode.id = idString;\n\t\t}\n\n\t\tif (this._elementParentNode && style) {\n\t\t\tconst elementStyle = this._elementParentNode.style;\n\t\t\tfor (const key in style) {\n\t\t\t\tif (elementStyle[key] !== style[key]) {\n\t\t\t\t\tlet val = style[key];\n\t\t\t\t\tif (val) {\n\t\t\t\t\t\telementStyle[key] = val;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._addContainerToDOM();\n\n\t\tif (this._tetherInstance) {\n\t\t\tthis._tetherInstance.setOptions(tetherOptions);\n\t\t} else {\n\t\t\tthis._createTetherInstance(tetherOptions);\n\t\t}\n\n\t\tthis._tetherInstance?.position();\n\t}\n\n\toverride render() {\n\t\tconst { targetComponent, elementComponent } = this._runRenders();\n\n\t\tif (!targetComponent) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (\n\t\t\t<React.Fragment>\n\t\t\t\t{targetComponent}\n\t\t\t\t{elementComponent &&\n\t\t\t\t\tthis._elementParentNode &&\n\t\t\t\t\tReactDOM.createPortal(elementComponent, this._elementParentNode)}\n\t\t\t</React.Fragment>\n\t\t);\n\t}\n}\n"],"names":["_excluded","_Component","ReactTether","_len","_this2","arguments","length","args","Array","_key","call","apply","this","concat","_targetNode","React","createRef","_elementNode","_elementParentNode","_tetherInstance","_proto","prototype","componentDidMount","_createContainer","forceUpdate","componentDidUpdate","previousProps","renderElementTag","props","renderElementTo","className","_this$_elementParentN","_this$_elementParentN2","previousClasses","split","filter","value","currClasses","classList","remove","add","_update","componentWillUnmount","_destroy","getTetherInstance","disable","_this$_tetherInstance","enable","_this$_tetherInstance2","on","event","handler","ctx","once","off","position","_this$_tetherInstance3","_runRenders","targetComponent","renderTarget","elementComponent","renderElement","isValidElement","_createTetherInstance","tetherOptions","Tether","_registerEventListeners","_destroyTetherInstance","destroy","_this","onUpdate","slice","onRepositioned","_removeContainer","_this$props","_this$props$renderEle","document","createElement","_addContainerToDOM","_renderNode","parentNode","append","current","_updateTether","_this$_tetherInstance4","_this$props2","id","style","options","_objectWithoutPropertiesLoose","_extends","target","element","idString","elementStyle","key","val","setOptions","render","_this$_runRenders","Fragment","ReactDOM","createPortal","get","querySelector","body","Component"],"mappings":"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"}