|
8 | 8 | getRelativePatternPosition, |
9 | 9 | } from './functions' |
10 | 10 | import { useStableFunction } from './hooks' |
| 11 | +import { Preview } from './preview' |
11 | 12 | import { AbsolutePattern, AbsolutePoint, NumberPair, RelativePattern, State } from './types' |
12 | 13 |
|
13 | 14 | const getDraftState = (state: State, draftClick: DraftClick, mousePosition: AbsolutePoint): State => { |
@@ -59,7 +60,23 @@ const BASE_STATE = { |
59 | 60 | patterns: [], |
60 | 61 | } |
61 | 62 |
|
| 63 | +const PreviewButton: React.FC<{ onClick: () => void; children: React.ReactNode }> = ({ |
| 64 | + onClick, |
| 65 | + children, |
| 66 | +}) => { |
| 67 | + return ( |
| 68 | + <button |
| 69 | + className='text-amber-300 hover:text-black cursor-pointer p-2 hover:bg-amber-300' |
| 70 | + type='button' |
| 71 | + onClick={onClick} |
| 72 | + > |
| 73 | + {children} |
| 74 | + </button> |
| 75 | + ) |
| 76 | +} |
| 77 | + |
62 | 78 | function App() { |
| 79 | + const [previewOpen, setPreviewOpen] = useState(false) |
63 | 80 | const [canvasEl, setCanvasEl] = useState<HTMLCanvasElement | null>(null) |
64 | 81 | const mousePositionRef = useRef<AbsolutePoint>(BASE_MOUSE_POSITION) |
65 | 82 |
|
@@ -145,45 +162,75 @@ function App() { |
145 | 162 | }, [draftClick, state, resizeCount, ctx]) |
146 | 163 |
|
147 | 164 | return ( |
148 | | - <canvas |
149 | | - className='w-full h-full' |
150 | | - ref={setCanvasEl} |
151 | | - onPointerDown={e => { |
152 | | - if (!ctx) return |
153 | | - |
154 | | - const mousePoint = getMousePoint(ctx, e) |
155 | | - |
156 | | - // create draft screen based on current cursor position |
157 | | - setDraftClick({ |
158 | | - anchor: mousePoint, |
159 | | - clickedPath: findClickedScreenOrPattern(state, mousePoint), |
160 | | - }) |
161 | | - }} |
162 | | - onPointerUp={e => { |
163 | | - if (!ctx) return |
164 | | - if (!draftClick) return |
165 | | - |
166 | | - // reset origin. note: this is async so we can still use the value below. |
167 | | - setDraftClick(undefined) |
168 | | - |
169 | | - const mousePoint = getMousePoint(ctx, e) |
170 | | - |
171 | | - const [x1, y1] = draftClick.anchor |
172 | | - const [x2, y2] = mousePoint |
173 | | - |
174 | | - // validate size, ignore drawings that are too small (arbitrary) |
175 | | - // todo: convert to viewport size and check pixels |
176 | | - if (Math.abs(x2 - x1) < 0.01) return |
177 | | - if (Math.abs(y2 - y1) < 0.01) return |
178 | | - |
179 | | - setState(prevState => getDraftState(prevState, draftClick, mousePoint)) |
180 | | - }} |
181 | | - onPointerMove={e => { |
182 | | - if (!ctx) return |
183 | | - |
184 | | - mousePositionRef.current = getMousePoint(ctx, e) |
185 | | - }} |
186 | | - /> |
| 165 | + <div className='size-full flex'> |
| 166 | + {previewOpen ? ( |
| 167 | + <div className='flex-1/3 border-r-amber-300 border-r-1'> |
| 168 | + <div className='flex gap-2 items-center justify-between'> |
| 169 | + <h2 className='text-amber-300'>preview (wip)</h2> |
| 170 | + <PreviewButton onClick={() => setPreviewOpen(false)}>x</PreviewButton> |
| 171 | + </div> |
| 172 | + <Preview state={state} /> |
| 173 | + </div> |
| 174 | + ) : ( |
| 175 | + <div className=' border-r-amber-300 border-r-1'> |
| 176 | + <PreviewButton onClick={() => setPreviewOpen(true)}>></PreviewButton> |
| 177 | + </div> |
| 178 | + )} |
| 179 | + <div className='flex-2/3'> |
| 180 | + <canvas |
| 181 | + className='size-full' |
| 182 | + ref={setCanvasEl} |
| 183 | + onPointerDown={e => { |
| 184 | + if (!ctx) return |
| 185 | + |
| 186 | + const mousePoint = getMousePoint(ctx, e) |
| 187 | + |
| 188 | + console.log( |
| 189 | + 'pointerdown', |
| 190 | + e.clientX, |
| 191 | + e.width, |
| 192 | + e.pageX, |
| 193 | + e.screenX, |
| 194 | + e.movementX, |
| 195 | + ctx.canvas.width, |
| 196 | + ctx.canvas.clientWidth, |
| 197 | + e, |
| 198 | + getMousePoint(ctx, e) |
| 199 | + ) |
| 200 | + |
| 201 | + // create draft screen based on current cursor position |
| 202 | + setDraftClick({ |
| 203 | + anchor: mousePoint, |
| 204 | + clickedPath: findClickedScreenOrPattern(state, mousePoint), |
| 205 | + }) |
| 206 | + }} |
| 207 | + onPointerUp={e => { |
| 208 | + if (!ctx) return |
| 209 | + if (!draftClick) return |
| 210 | + |
| 211 | + // reset origin. note: this is async so we can still use the value below. |
| 212 | + setDraftClick(undefined) |
| 213 | + |
| 214 | + const mousePoint = getMousePoint(ctx, e) |
| 215 | + |
| 216 | + const [x1, y1] = draftClick.anchor |
| 217 | + const [x2, y2] = mousePoint |
| 218 | + |
| 219 | + // validate size, ignore drawings that are too small (arbitrary) |
| 220 | + // todo: convert to viewport size and check pixels |
| 221 | + if (Math.abs(x2 - x1) < 0.01) return |
| 222 | + if (Math.abs(y2 - y1) < 0.01) return |
| 223 | + |
| 224 | + setState(prevState => getDraftState(prevState, draftClick, mousePoint)) |
| 225 | + }} |
| 226 | + onPointerMove={e => { |
| 227 | + if (!ctx) return |
| 228 | + |
| 229 | + mousePositionRef.current = getMousePoint(ctx, e) |
| 230 | + }} |
| 231 | + /> |
| 232 | + </div> |
| 233 | + </div> |
187 | 234 | ) |
188 | 235 | } |
189 | 236 |
|
|
0 commit comments