Skip to content

Commit 8c2d210

Browse files
authored
Refactor element state model to support reactive framework integration (#85)
* wip * fix demo pages * fixes * block snapshot * removed "last" prefix * rename internal to entry * add tests for subscribe/getsnapshot * add derived map view * fix jsdocs above manager * fix lifecycle bugs and add tests for it * fix reregistering elements with new data * refactor element overlay * formatting and eslint fixes
1 parent dcbbdbe commit 8c2d210

40 files changed

Lines changed: 2307 additions & 1684 deletions

packages/devpage-react/src/components/MainWrapper.tsx

Lines changed: 71 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -2,115 +2,89 @@ import ForesightButtonVisibility from "./test-buttons/ForesightButtonVisibility"
22
import ForesightButtonResizeable from "./test-buttons/ForesightButtonResizeable"
33
import ForesightButtonRemoveable from "./test-buttons/ForesightButtonRemoveable"
44
import ForesightButtonNoName from "./test-buttons/ForesightButtonNoName"
5-
import { useResetKey } from "../stores/ButtonStateStore"
6-
import { ForesightManager } from "js.foresight"
7-
import { useEffect } from "react"
5+
import {
6+
useButtonActions,
7+
useIsRemoved,
8+
useIsResized,
9+
useIsVisible,
10+
useResetKey,
11+
} from "../stores/ButtonStateStore"
812
import ForesightButtonError from "./test-buttons/ForesightButtonError"
913
import { Navigation } from "./Navigation"
10-
import ForesightReactiveButton from "./test-buttons/ForesightReactiveButton"
1114

12-
export const Main = () => {
13-
const resetKey = useResetKey()
15+
type SectionProps = {
16+
title: string
17+
toggleLabel?: string
18+
toggleOn?: boolean
19+
onToggle?: () => void
20+
children: React.ReactNode
21+
}
1422

15-
useEffect(() => {
16-
const handleCallbackFired = () => {}
23+
function Section({ title, toggleLabel, toggleOn, onToggle, children }: SectionProps) {
24+
return (
25+
<section className="border-t border-gray-300 pb-8">
26+
<div className="sticky top-12 z-[5] -mx-6 px-6 py-4 bg-stone-50/95 backdrop-blur flex items-center justify-between mb-6">
27+
<h3 className="text-lg font-semibold text-gray-900">{title}</h3>
28+
{toggleLabel && onToggle && (
29+
<button
30+
onClick={onToggle}
31+
className="px-2 py-1 text-xs border border-gray-400 text-gray-800 hover:bg-gray-100"
32+
>
33+
{toggleLabel}: {toggleOn ? "on" : "off"}
34+
</button>
35+
)}
36+
</div>
37+
{children}
38+
</section>
39+
)
40+
}
1741

18-
ForesightManager.instance.addEventListener("callbackCompleted", handleCallbackFired)
42+
export const Main = () => {
43+
const resetKey = useResetKey()
44+
const actions = useButtonActions()
45+
const isVisible = useIsVisible()
46+
const isRemoved = useIsRemoved()
47+
const isResized = useIsResized()
1948

20-
return () => {
21-
ForesightManager.instance.removeEventListener("callbackCompleted", handleCallbackFired)
22-
}
23-
}, [])
2449
return (
25-
<div
26-
key={resetKey}
27-
className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50 font-sans"
28-
>
50+
<div key={resetKey} className="min-h-screen bg-stone-50 text-gray-900">
2951
<Navigation />
3052

31-
{/* Test Buttons Section */}
32-
<div className="max-w-full mx-auto px-6 py-12">
33-
<div className="text-center mb-12">
34-
<h2 className="text-3xl font-bold text-gray-900 mb-4">Interactive Test Buttons</h2>
35-
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
36-
Each button demonstrates different ForesightJS behaviors and configurations. Hover over
37-
them to trigger predictive callbacks and observe the interactions.
38-
</p>
39-
</div>
53+
<main className="max-w-6xl mx-auto px-6 pb-16">
54+
<Section
55+
title="Resizable elements"
56+
toggleLabel="Resize"
57+
toggleOn={isResized}
58+
onToggle={actions.toggleResized}
59+
>
60+
<ForesightButtonResizeable name="resizeable" />
61+
</Section>
4062

41-
<div className="space-y-12">
42-
{/* Dynamic Behavior Group */}
43-
<div className="bg-white/70 backdrop-blur-sm rounded-2xl p-8 border border-gray-200/50 shadow-lg">
44-
<div className="flex items-center gap-3 mb-6">
45-
<div className="w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center">
46-
<svg
47-
className="w-5 h-5 text-blue-600"
48-
fill="none"
49-
stroke="currentColor"
50-
viewBox="0 0 24 24"
51-
>
52-
<path
53-
strokeLinecap="round"
54-
strokeLinejoin="round"
55-
strokeWidth={2}
56-
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
57-
/>
58-
</svg>
59-
</div>
60-
<h3 className="text-2xl font-semibold text-gray-900">Dynamic Behavior</h3>
61-
</div>
62-
<p className="text-gray-600 mb-8">
63-
Test elements with dynamic properties like resizing, removal, and visibility
64-
</p>
65-
<div className="mb-8">
66-
<h4 className="text-lg font-medium text-gray-800 mb-4">Resizable Elements</h4>
67-
<ForesightButtonResizeable name="resizeable" />
68-
</div>
69-
<div className="mb-8">
70-
<h4 className="text-lg font-medium text-gray-800 mb-4">Removable Elements</h4>
71-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
72-
<ForesightButtonRemoveable name="removeable" />
73-
<ForesightButtonRemoveable name="removeable2" />
74-
<ForesightButtonRemoveable name="removeable3" />
75-
</div>
76-
</div>
77-
<div>
78-
<h4 className="text-lg font-medium text-gray-800 mb-4">Visibility Elements</h4>
79-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
80-
<ForesightButtonVisibility name="visibility" />
81-
</div>
82-
</div>
83-
</div>
63+
<Section
64+
title="Removable elements"
65+
toggleLabel="Remove"
66+
toggleOn={isRemoved}
67+
onToggle={actions.toggleRemoved}
68+
>
69+
<ForesightButtonRemoveable name="removeable" />
70+
</Section>
71+
72+
<Section
73+
title="Visibility elements"
74+
toggleLabel="Visible"
75+
toggleOn={isVisible}
76+
onToggle={actions.toggleVisibility}
77+
>
78+
<ForesightButtonVisibility name="visibility" />
79+
</Section>
8480

85-
{/* Edge Cases Group */}
86-
<div className="bg-white/70 backdrop-blur-sm rounded-2xl p-8 border border-gray-200/50 shadow-lg">
87-
<div className="flex items-center gap-3 mb-6">
88-
<div className="w-10 h-10 bg-red-100 rounded-lg flex items-center justify-center">
89-
<svg
90-
className="w-5 h-5 text-red-600"
91-
fill="none"
92-
stroke="currentColor"
93-
viewBox="0 0 24 24"
94-
>
95-
<path
96-
strokeLinecap="round"
97-
strokeLinejoin="round"
98-
strokeWidth={2}
99-
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.863-.833-2.632 0L4.232 15.5c-.77.833.192 2.5 1.732 2.5z"
100-
/>
101-
</svg>
102-
</div>
103-
<h3 className="text-2xl font-semibold text-gray-900">Edge Cases</h3>
104-
</div>
105-
<p className="text-gray-600 mb-8">Test error handling and unusual configurations</p>
106-
<div className="grid grid-cols-2 md:grid-cols-2 gap-8">
107-
<ForesightButtonError name="callback error" />
108-
<ForesightButtonNoName />
109-
<ForesightReactiveButton name="reactive 3s" />
110-
</div>
81+
<Section title="Edge cases">
82+
<div className="flex flex-wrap gap-x-6 gap-y-8">
83+
<ForesightButtonError name="callback error" />
84+
<ForesightButtonNoName />
11185
</div>
112-
</div>
113-
</div>
86+
</Section>
87+
</main>
11488
</div>
11589
)
11690
}
Lines changed: 45 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,56 @@
11
import { Link } from "react-router-dom"
2-
import {
3-
useButtonActions,
4-
useIsRemoved,
5-
useIsResized,
6-
useIsVisible,
7-
} from "../stores/ButtonStateStore"
2+
import { useButtonActions, useReactivateAfter } from "../stores/ButtonStateStore"
83
import { useDebug } from "../contexts/DebugContext"
94

105
export const Navigation = () => {
116
const actions = useButtonActions()
12-
const isVisible = useIsVisible()
13-
const isRemoved = useIsRemoved()
14-
const isResized = useIsResized()
7+
const reactivateAfter = useReactivateAfter()
158
const { isDebugActive, toggleDebug } = useDebug()
169

1710
return (
18-
<div className="bg-white/80 backdrop-blur-sm border-b border-gray-200/50 sticky top-0 z-10">
19-
<div className="max-w-7xl mx-auto px-6 py-3">
20-
<div className="flex items-center justify-between">
21-
<div className="text-left">
22-
<h1 className="text-xl font-bold text-gray-900">
23-
<Link to="/" className="hover:text-blue-600 transition-colors">
24-
ForesightJS Dev
25-
</Link>
26-
</h1>
27-
</div>
28-
<div className="flex items-center gap-2">
29-
<button
30-
onClick={actions.toggleVisibility}
31-
className={`px-3 py-1 rounded-md text-xs font-medium transition-colors ${
32-
isVisible
33-
? "bg-green-500 hover:bg-green-600 text-white"
34-
: "bg-red-500 hover:bg-red-600 text-white"
35-
}`}
36-
>
37-
Visible: {isVisible ? "ON" : "OFF"}
38-
</button>
39-
<button
40-
onClick={actions.toggleResized}
41-
className={`px-3 py-1 rounded-md text-xs font-medium transition-colors ${
42-
isResized
43-
? "bg-green-500 hover:bg-green-600 text-white"
44-
: "bg-red-500 hover:bg-red-600 text-white"
45-
}`}
46-
>
47-
Resize: {isResized ? "ON" : "OFF"}
48-
</button>
49-
<button
50-
onClick={actions.toggleRemoved}
51-
className={`px-3 py-1 rounded-md text-xs font-medium transition-colors ${
52-
isRemoved
53-
? "bg-green-500 hover:bg-green-600 text-white"
54-
: "bg-red-500 hover:bg-red-600 text-white"
55-
}`}
56-
>
57-
Remove: {isRemoved ? "ON" : "OFF"}
58-
</button>
59-
<button
60-
onClick={toggleDebug}
61-
className={`px-3 py-1 rounded-md text-xs font-medium transition-colors ${
62-
isDebugActive
63-
? "bg-green-600 hover:bg-green-700 text-white"
64-
: "bg-gray-600 hover:bg-gray-700 text-white"
65-
}`}
66-
title="⚠️ Warning: Debug mode may impact performance with many elements"
67-
>
68-
{isDebugActive ? "Debug ON" : "Debug OFF"}
69-
</button>
70-
<button
71-
onClick={actions.resetAll}
72-
className="px-3 py-1 rounded-md text-xs font-medium bg-orange-500 hover:bg-orange-600 text-white transition-colors"
73-
>
74-
Reset
75-
</button>
76-
<div className="w-px h-6 bg-gray-300 mx-2"></div>
77-
<Link
78-
to="/"
79-
className="bg-slate-600 hover:bg-slate-700 text-white px-3 py-2 rounded-lg font-medium transition-colors text-sm"
80-
>
81-
🏠 Home
82-
</Link>
83-
<Link
84-
to="/images"
85-
className="bg-blue-600 hover:bg-blue-700 text-white px-3 py-2 rounded-lg font-medium transition-colors text-sm"
86-
>
87-
🖼️ Images
88-
</Link>
89-
<Link
90-
to="/mass"
91-
className="bg-purple-600 hover:bg-purple-700 text-white px-3 py-2 rounded-lg font-medium transition-colors text-sm"
92-
>
93-
📊 Mass Test
94-
</Link>
95-
</div>
96-
</div>
11+
<header className="bg-white border-b border-gray-300 sticky top-0 z-10">
12+
<div className="max-w-6xl mx-auto px-6 py-3 flex items-center justify-between">
13+
<Link to="/" className="text-base font-semibold text-gray-900">
14+
ForesightJS Dev
15+
</Link>
16+
<nav className="flex items-center gap-4 text-sm">
17+
<Link to="/" className="text-gray-700 hover:text-gray-900">
18+
Home
19+
</Link>
20+
<Link to="/images" className="text-gray-700 hover:text-gray-900">
21+
Images
22+
</Link>
23+
<Link to="/mass" className="text-gray-700 hover:text-gray-900">
24+
Mass test
25+
</Link>
26+
<span className="w-px h-5 bg-gray-300" />
27+
<label className="flex items-center gap-1 text-xs text-gray-700">
28+
Reactivate
29+
<input
30+
type="number"
31+
min={0}
32+
step={500}
33+
value={reactivateAfter}
34+
onChange={e => actions.setReactivateAfter(Number(e.target.value))}
35+
className="w-20 px-1 py-0.5 text-xs border border-gray-400"
36+
/>
37+
ms
38+
</label>
39+
<button
40+
onClick={toggleDebug}
41+
className="px-2 py-1 text-xs border border-gray-400 text-gray-800 hover:bg-gray-100"
42+
title="Toggle ForesightDevtools control panel"
43+
>
44+
Debug: {isDebugActive ? "on" : "off"}
45+
</button>
46+
<button
47+
onClick={actions.resetAll}
48+
className="px-2 py-1 text-xs border border-gray-400 text-gray-800 hover:bg-gray-100"
49+
>
50+
Reset
51+
</button>
52+
</nav>
9753
</div>
98-
</div>
54+
</header>
9955
)
10056
}

0 commit comments

Comments
 (0)