diff --git a/dist/index.html b/dist/index.html
index dc20e8a..1ed5ab3 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -12,7 +12,8 @@
-
+
+
+ return
{
btnz.map(([Icon, fcn, txt], idx) => (
-
+
))
}
diff --git a/src/reducer.js b/src/react/reducer.js
similarity index 98%
rename from src/reducer.js
rename to src/react/reducer.js
index f4a193a..20101e1 100644
--- a/src/reducer.js
+++ b/src/react/reducer.js
@@ -11,6 +11,9 @@ export const preloadedState = {
tree: {},
order: {},
},
+ ui: {
+ toolTipImmediate: false
+ }
}
export function reducer(state = {}, action) {
diff --git a/src/react/toolTip.jsx b/src/react/toolTip.jsx
new file mode 100644
index 0000000..e3ae4f5
--- /dev/null
+++ b/src/react/toolTip.jsx
@@ -0,0 +1,86 @@
+import React, { useEffect, useRef, useState } from 'react';
+
+export const ToolTip = () => {
+ /**
+ * Fires when new element is mouseovered, checks if it has a tooltip attribute
+ * If it does, updates and unhides tooltip element after a preset timeout.
+ * The timout is reset if user moves off of the tooltipped element
+ *
+ * Unfortunately, new mouseover fires for svg children, which clears the
+ * tooltip state. We add hacky lines labelled svg workaround to bubbleup / ignore
+ * svg children mouseovers. We use prevTooltip ref check if new svg
+ * child mouseover is novel. If it's not, we ignore the event
+ */
+
+ const [state, setState] = useState(null)
+
+ const ref = useRef()
+
+ const activated = useRef(false)
+ const timeout = useRef(null)
+
+ const prevTooltip = useRef(null) // svg workaround
+
+ useEffect(() => {
+
+ const svgChildren = ['path', 'g', 'rect', 'circle']; // svg workaround
+
+ document.addEventListener('mouseover', (e) => {
+ let node = e.target;
+
+ while (svgChildren.includes(node.nodeName)) { // svg workaround
+ node = node.parentElement // svg workaround
+ } // svg workaround
+
+ const tooltip = node.getAttribute("tooltip")
+
+ if (tooltip == prevTooltip.current) return // svg workaround
+ prevTooltip.current = tooltip // svg workaround
+
+ clearTimeout(timeout.current)
+
+ if (tooltip) {
+ let { left, top, width, height } = node.getBoundingClientRect()
+ left = left + width / 2 - getTextWidth(tooltip) / 2 - 4 // 4 is padding
+ top = top + height + 6 // 6 is arrow height/width
+
+ setState(tooltip)
+
+ if (activated.current) {
+ ref.current.setAttribute('style', `left:${left}px; top:${top}px; visibility:visible`)
+ } else {
+ timeout.current = setTimeout(() => {
+ ref.current.setAttribute('style', `left:${left}px; top:${top}px; visibility:visible`)
+ activated.current = true
+ }, 1000);
+ }
+
+ } else {
+
+ ref.current.setAttribute('style', `visibility:hidden`)
+ activated.current = false
+
+ }
+
+ })
+
+
+ }, [])
+
+
+ return
+
+}
+
+
+function getTextWidth(text, font = "16px sans-serif") {
+ // re-use canvas object for better performance
+ let canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
+ let context = canvas.getContext("2d");
+ context.font = font;
+ let metrics = context.measureText(text);
+ return metrics.width;
+}
diff --git a/src/treeEntry.jsx b/src/react/tree.jsx
similarity index 100%
rename from src/treeEntry.jsx
rename to src/react/tree.jsx
diff --git a/webpack.common.js b/webpack.common.js
index 9d42bb3..2743dfe 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -4,7 +4,7 @@ const tailwindcss = require('tailwindcss')
module.exports = {
entry: {
- app: './src/app.jsx',
+ app: './src/react/app.jsx',
scene: './src/Scene.js',
},
output: {