@weasel-js/labkit 1.7.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/_dts/{CanvasStackContext-D2jnIwfk.d.ts → CanvasStackContext-Cjy6I-Iv.d.ts} +4 -1
- package/dist/_dts/{Stage-CCWfQQWM.d.ts → Stage-D6t7o0pF.d.ts} +3 -2
- package/dist/_dts/{index-CsYqUHD3.d.ts → index-BTmaRy6a.d.ts} +10 -6
- package/dist/_dts/{types-CSm9jgol.d.ts → index-DCMA4Fy1.d.ts} +59 -113
- package/dist/_dts/{types-CRPSGFAp.d.ts → types-BUBSIZuV.d.ts} +8 -7
- package/dist/_dts/{useTrialState-CTZPgeZ7.d.ts → useTrialState-Bh8bzFgE.d.ts} +1 -1
- package/dist/canvas/index.d.ts +8 -6
- package/dist/canvas/index.js +6 -6
- package/dist/chrome/index.d.ts +7 -5
- package/dist/chrome/index.js +10 -9
- package/dist/chunk-2ES4W47N.js +8 -0
- package/dist/chunk-2ES4W47N.js.map +1 -0
- package/dist/{chunk-WPLAANH4.js → chunk-2N7UBSS2.js} +12 -12
- package/dist/chunk-2N7UBSS2.js.map +1 -0
- package/dist/chunk-4KSC7NXL.js +15491 -0
- package/dist/chunk-4KSC7NXL.js.map +1 -0
- package/dist/{chunk-7BO7HNGF.js → chunk-CEGFXTBD.js} +8 -61
- package/dist/chunk-CEGFXTBD.js.map +1 -0
- package/dist/{chunk-275JRRVD.js → chunk-E23Q6A3Y.js} +232 -37
- package/dist/chunk-E23Q6A3Y.js.map +1 -0
- package/dist/{chunk-GOZLNM4L.js → chunk-E6NARGU7.js} +5 -5
- package/dist/{chunk-GOZLNM4L.js.map → chunk-E6NARGU7.js.map} +1 -1
- package/dist/{chunk-IJJUK4FU.js → chunk-EESJUSYR.js} +5 -6
- package/dist/chunk-EESJUSYR.js.map +1 -0
- package/dist/{chunk-HXXTULDN.js → chunk-EFXRM6XQ.js} +8 -11
- package/dist/chunk-EFXRM6XQ.js.map +1 -0
- package/dist/chunk-F4ACIK7Z.js +210 -0
- package/dist/chunk-F4ACIK7Z.js.map +1 -0
- package/dist/{chunk-FMK7UQ6V.js → chunk-FB4MIZOO.js} +61 -44
- package/dist/chunk-FB4MIZOO.js.map +1 -0
- package/dist/{chunk-AWQG7FCC.js → chunk-FG3EXZDV.js} +3 -3
- package/dist/{chunk-AWQG7FCC.js.map → chunk-FG3EXZDV.js.map} +1 -1
- package/dist/{chunk-I5DUQ5HM.js → chunk-GAHELLJT.js} +75 -72
- package/dist/chunk-GAHELLJT.js.map +1 -0
- package/dist/{chunk-YT75VYRD.js → chunk-IBVRMHW5.js} +5 -5
- package/dist/{chunk-YT75VYRD.js.map → chunk-IBVRMHW5.js.map} +1 -1
- package/dist/{chunk-T5IBSPAM.js → chunk-JFOJESJF.js} +33 -23
- package/dist/chunk-JFOJESJF.js.map +1 -0
- package/dist/{chunk-RWNDDKOH.js → chunk-PMLZP7RT.js} +18 -15
- package/dist/chunk-PMLZP7RT.js.map +1 -0
- package/dist/{chunk-Y23G2VZL.js → chunk-READTDQX.js} +2 -2
- package/dist/chunk-READTDQX.js.map +1 -0
- package/dist/{chunk-JVBYV6TL.js → chunk-ROGJWDQA.js} +3 -3
- package/dist/{chunk-JVBYV6TL.js.map → chunk-ROGJWDQA.js.map} +1 -1
- package/dist/{chunk-ZIFPHIWZ.js → chunk-T6DLGEJB.js} +12 -14
- package/dist/chunk-T6DLGEJB.js.map +1 -0
- package/dist/{chunk-24W5VEJW.js → chunk-ULYYNWGP.js} +2 -2
- package/dist/{chunk-24W5VEJW.js.map → chunk-ULYYNWGP.js.map} +1 -1
- package/dist/{chunk-UNAZSLWE.js → chunk-VYVGVBGY.js} +17 -20
- package/dist/chunk-VYVGVBGY.js.map +1 -0
- package/dist/{chunk-KMJ7RWD3.js → chunk-WLMDTI2Q.js} +3 -3
- package/dist/{chunk-KMJ7RWD3.js.map → chunk-WLMDTI2Q.js.map} +1 -1
- package/dist/{chunk-J7OWWTCW.js → chunk-XE5HJOPL.js} +5 -6
- package/dist/chunk-XE5HJOPL.js.map +1 -0
- package/dist/chunk-XVUKDSYV.js +38 -0
- package/dist/chunk-XVUKDSYV.js.map +1 -0
- package/dist/{chunk-FZ7YFQN7.js → chunk-YCFKW5RX.js} +3 -3
- package/dist/chunk-YCFKW5RX.js.map +1 -0
- package/dist/{chunk-CQLQPQ4P.js → chunk-ZQIHJXP4.js} +2 -2
- package/dist/chunk-ZQIHJXP4.js.map +1 -0
- package/dist/config/index.d.ts +18 -10
- package/dist/config/index.js +4 -4
- package/dist/controls/index.d.ts +4 -7
- package/dist/controls/index.js +6 -5
- package/dist/dragdrop/index.d.ts +23 -3
- package/dist/dragdrop/index.js +4 -3
- package/dist/fonts/oswald-tabular-digits.woff2 +0 -0
- package/dist/index.d.ts +60 -714
- package/dist/index.js +357 -334
- package/dist/index.js.map +1 -1
- package/dist/job/index.d.ts +8 -0
- package/dist/job/index.js +1 -1
- package/dist/layers/index.d.ts +6 -5
- package/dist/layers/index.js +3 -2
- package/dist/loupe/index.d.ts +100 -30
- package/dist/loupe/index.js +585 -6
- package/dist/loupe/index.js.map +1 -1
- package/dist/overview/index.d.ts +4 -2
- package/dist/overview/index.js +15 -14
- package/dist/overview/index.js.map +1 -1
- package/dist/passthrough/weasel-canvas.d.ts +2 -0
- package/dist/passthrough/weasel-ui.d.ts +2 -2871
- package/dist/passthrough/weasel-ui.js +3 -2
- package/dist/primitives/index.d.ts +213 -3
- package/dist/primitives/index.js +8 -7
- package/dist/state/index.d.ts +7 -5
- package/dist/state/index.js +6 -6
- package/dist/styles.css +60 -44
- package/dist/surface/index.d.ts +10 -2
- package/dist/surface/index.js +1 -1
- package/dist/undo/index.d.ts +5 -3
- package/package.json +11 -11
- package/src/annotations/AnnotationOverlay.abandon.test.tsx +143 -0
- package/src/annotations/AnnotationOverlay.tsx +50 -31
- package/src/annotations/Annotations.overlay.test.tsx +31 -0
- package/src/annotations/capture.browser.test.ts +41 -0
- package/src/annotations/capture.ts +14 -7
- package/src/annotations/drawOne.ts +2 -2
- package/src/annotations/frac.test.ts +44 -1
- package/src/annotations/frac.ts +46 -18
- package/src/annotations/index.ts +1 -0
- package/src/annotations/paint.test.ts +74 -33
- package/src/annotations/paint.ts +70 -32
- package/src/annotations/store.test.ts +212 -2
- package/src/annotations/store.ts +130 -27
- package/src/annotations/svgNodes.test.ts +22 -10
- package/src/annotations/svgNodes.ts +3 -3
- package/src/annotations/types.ts +29 -10
- package/src/canvas/CameraInput.test.tsx +30 -0
- package/src/canvas/CameraInput.tsx +16 -15
- package/src/canvas/CanvasStack.tsx +5 -5
- package/src/canvas/CanvasStackContext.ts +4 -1
- package/src/canvas/Stage.tsx +3 -3
- package/src/canvas/cameraRegistry.ts +1 -0
- package/src/canvas/worldSpec.ts +3 -1
- package/src/chrome/builtins.test.ts +7 -6
- package/src/chrome/builtins.tsx +5 -1
- package/src/chrome/index.ts +1 -1
- package/src/chrome/merge.test.ts +5 -0
- package/src/chrome/merge.ts +4 -2
- package/src/chrome/regions/PaletteRegion.test.tsx +2 -3
- package/src/chrome/regions/PaletteRegion.tsx +3 -4
- package/src/chrome/regions/ViewportRegion.browser.test.less +6 -0
- package/src/chrome/regions/ViewportRegion.browser.test.tsx +38 -0
- package/src/chrome/regions/ViewportRegion.less +6 -0
- package/src/chrome/regions/ViewportRegion.tsx +10 -4
- package/src/chrome/types.ts +4 -2
- package/src/config/auto.ts +1 -0
- package/src/config/builder.ts +6 -0
- package/src/config/types.ts +2 -1
- package/src/controls/ControlPanel.test.tsx +37 -3
- package/src/controls/ControlPanel.tsx +12 -3
- package/src/dragdrop/DragDropRuntime.tsx +22 -13
- package/src/dragdrop/DragGhost.tsx +3 -0
- package/src/dragdrop/Palette.tsx +2 -0
- package/src/index.test.ts +5 -0
- package/src/index.ts +1 -1
- package/src/instrument/types.ts +0 -6
- package/src/job/useJob.ts +14 -9
- package/src/lab/Lab.tsx +5 -1
- package/src/lab/LabShell.less +1 -0
- package/src/lab/LabSwitcher.browser.test.tsx +27 -0
- package/src/lab/LabSwitcher.less +2 -0
- package/src/lab/LabZoom.tsx +4 -4
- package/src/lab/Workspace.tsx +48 -52
- package/src/loupe/AGENTS.md +28 -15
- package/src/loupe/CanvasLoupe.tsx +2 -3
- package/src/loupe/DomLoupe.tsx +1 -7
- package/src/loupe/Loupe.less +16 -0
- package/src/loupe/TrialLoupe.tsx +120 -57
- package/src/loupe/index.ts +1 -6
- package/src/loupe/types.test.ts +3 -3
- package/src/loupe/types.ts +24 -27
- package/src/loupe/useLoupe.test.tsx +29 -4
- package/src/loupe/useLoupe.ts +20 -17
- package/src/overview/OverviewMarks.tsx +12 -4
- package/src/overview/TrialOverview.tsx +3 -3
- package/src/passthrough/weasel-ui.test.ts +1 -1
- package/src/passthrough/weasel-ui.ts +1 -1
- package/src/primitives/FloatingPanel.tsx +7 -3
- package/src/primitives/JobProgress.less +1 -0
- package/src/primitives/Readout.test.tsx +2 -2
- package/src/primitives/Split.tsx +69 -41
- package/src/primitives/Toolbar.tsx +3 -3
- package/src/primitives/ZoomControl.less +1 -2
- package/src/specimen/Specimen.tsx +0 -1
- package/src/state/undock.ts +3 -0
- package/src/state/useOpenOnce.ts +20 -16
- package/src/state/view.ts +1 -0
- package/src/surface/index.ts +1 -1
- package/src/surface/useTiledSurface.test.tsx +14 -0
- package/src/surface/useTiledSurface.ts +11 -3
- package/src/trial/Trial.annotations.test.tsx +73 -0
- package/src/trial/Trial.less +0 -16
- package/src/trial/Trial.loupe.test.tsx +28 -11
- package/src/trial/Trial.tsx +74 -62
- package/src/trial/TrialChrome.tsx +6 -3
- package/src/trial/index.ts +2 -0
- package/src/trial/loupeSwitch.ts +15 -0
- package/dist/_dts/LayerList.d-DiuEArKq.d.ts +0 -83
- package/dist/_dts/PrefsRow.d-TOZ7BgD9.d.ts +0 -79
- package/dist/_dts/PropertyPanel.d-D-1paCbE.d.ts +0 -141
- package/dist/_dts/Select.d-Bensr_MT.d.ts +0 -579
- package/dist/_dts/index-B2Yj5aA0.d.ts +0 -274
- package/dist/chunk-275JRRVD.js.map +0 -1
- package/dist/chunk-4LJSC7MB.js +0 -143
- package/dist/chunk-4LJSC7MB.js.map +0 -1
- package/dist/chunk-7BO7HNGF.js.map +0 -1
- package/dist/chunk-CQLQPQ4P.js.map +0 -1
- package/dist/chunk-FMK7UQ6V.js.map +0 -1
- package/dist/chunk-FZ7YFQN7.js.map +0 -1
- package/dist/chunk-HXXTULDN.js.map +0 -1
- package/dist/chunk-I5DUQ5HM.js.map +0 -1
- package/dist/chunk-IJJUK4FU.js.map +0 -1
- package/dist/chunk-J7OWWTCW.js.map +0 -1
- package/dist/chunk-M7HP3FTK.js +0 -549
- package/dist/chunk-M7HP3FTK.js.map +0 -1
- package/dist/chunk-MIM5R4ZT.js +0 -14972
- package/dist/chunk-MIM5R4ZT.js.map +0 -1
- package/dist/chunk-RWNDDKOH.js.map +0 -1
- package/dist/chunk-T5IBSPAM.js.map +0 -1
- package/dist/chunk-UNAZSLWE.js.map +0 -1
- package/dist/chunk-WPLAANH4.js.map +0 -1
- package/dist/chunk-Y23G2VZL.js.map +0 -1
- package/dist/chunk-ZIFPHIWZ.js.map +0 -1
- package/src/primitives/useRovingTabIndex.test.ts +0 -48
- package/src/primitives/useRovingTabIndex.ts +0 -88
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/surface/composeRects.ts","../src/surface/deviceRect.ts","../src/surface/useTiledSurface.ts"],"names":[],"mappings":"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","file":"chunk-IJJUK4FU.js","sourcesContent":["import type { Box, Rect } from './rect';\n\n/** Every tile's box expressed against the container's origin. */\nexport function composeRects(container: Box, tiles: ReadonlyMap<string, Box>): Map<string, Rect> {\n const out = new Map<string, Rect>();\n for (const [id, tile] of tiles) {\n out.set(id, {\n x: tile.left - container.left,\n y: tile.top - container.top,\n w: tile.width,\n h: tile.height,\n });\n }\n return out;\n}\n\nexport function rectsEqual(a: Rect | undefined, b: Rect): boolean {\n return a !== undefined && a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;\n}\n","import type { Rect } from './rect';\n\n/**\n * A DOM rect as a GL viewport rect: origin at the bottom-left, every edge snapped\n * to the device-pixel grid. Still CSS pixels, because three.js applies its own\n * pixel ratio — snapping here is what stops a tile and its neighbour rounding\n * apart and leaving a hairline column between them.\n */\nexport function toDeviceRect(rect: Rect, surfaceHeight: number, dpr: number): Rect {\n const snap = (v: number) => Math.round(v * dpr) / dpr;\n const x = snap(rect.x);\n const y = snap(surfaceHeight - rect.y - rect.h);\n return {\n x,\n y,\n w: snap(rect.x + rect.w) - x,\n h: snap(surfaceHeight - rect.y) - y,\n };\n}\n","import { useVisibleRaf } from '@weasel-js/core';\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { composeRects, rectsEqual } from './composeRects';\nimport type { Box, Rect } from './rect';\n\n/** What a surface owner is handed once per animation frame. `rects` carries every\n * tile, not only the dirty ones: a scissored draw has to know where it is drawing\n * relative to a surface that may have resized under it.\n *\n * Its keys are what `useTileId` returns — `<trial>/<id>` for a tile registered\n * inside a trial — not the bare id the tile was named with. */\nexport interface SurfaceFrame {\n dirty: ReadonlySet<string>;\n rects: ReadonlyMap<string, Rect>;\n dpr: number;\n size: { width: number; height: number };\n /** The tile geometry changed this frame — a tile moved, resized, appeared or\n * went away, or the dpr did. Every tile is dirty on such a frame, but the\n * pixels a tile vacated are in no tile's scissor now, so the owner clears\n * the whole buffer. `<Lab>` does; a host owning its own surface must too. */\n retiled: boolean;\n}\n\n/** The invalidators and the two ref callbacks that publish geometry. */\nexport interface SurfaceHandle {\n /** Mark one tile for redraw. */\n invalidate: (id: string) => void;\n /** Mark every tile — what a resize or a tile-set change means. */\n invalidateAll: () => void;\n /** Re-measure before the next frame. The escape hatch for a host that knows it\n * moved something a ResizeObserver cannot see. */\n invalidateRects: () => void;\n registerTile: (id: string, el: HTMLElement | null) => void;\n /** Register a tenant's whole-buffer clear. Every one registered runs, before\n * any painter, on a frame where the tile geometry changed — the pixels a\n * tile vacated are in no scissor now, and only the context that drew them\n * can erase them. Backend-agnostic by necessity: labkit owns the canvas,\n * never the context. */\n registerClear: (id: string, clear: SurfaceClear) => () => void;\n /** Subscribe a tile to the frames it is dirty on. A tile paints on its own\n * loop, so this is how the surface wakes one: a resize of the shared buffer\n * clears every tile, not only the one that moved. */\n registerPainter: (id: string, paint: TilePainter) => () => void;\n containerRef: (el: HTMLElement | null) => void;\n /** The element tile rects are measured against, and so the one a tile's own\n * chrome positions itself inside. Null before the owner attaches it. */\n getContainer: () => HTMLElement | null;\n}\n\n/** What a tile's painter is handed: where it sits on the surface now, and the\n * frame that dirtied it. */\nexport type TilePainter = (rect: Rect, frame: SurfaceFrame) => void;\n\n/** Erase the whole shared buffer. Device pixels, because that is what a GL\n * viewport takes. */\nexport type SurfaceClear = (size: { width: number; height: number }, dpr: number) => void;\n\nexport interface UseTiledSurfaceOptions {\n onFrame: (frame: SurfaceFrame) => void;\n}\n\nexport function useTiledSurface({ onFrame }: UseTiledSurfaceOptions): SurfaceHandle {\n const container = useRef<HTMLElement | null>(null);\n const tiles = useRef(new Map<string, HTMLElement>());\n const rects = useRef(new Map<string, Rect>());\n const dirty = useRef(new Set<string>());\n const painters = useRef(new Map<string, TilePainter>());\n const clears = useRef(new Map<string, SurfaceClear>());\n const needsMeasure = useRef(true);\n const observer = useRef<ResizeObserver | null>(null);\n const lastDpr = useRef(0);\n\n // Held in a ref so a caller passing an inline closure does not re-create every\n // callback below on each render.\n const onFrameRef = useRef(onFrame);\n onFrameRef.current = onFrame;\n\n const measure = useCallback((): boolean => {\n const el = container.current;\n if (!el) return false;\n const boxes = new Map<string, Box>();\n for (const [id, tile] of tiles.current) boxes.set(id, tile.getBoundingClientRect());\n const next = composeRects(el.getBoundingClientRect(), boxes);\n let changed = next.size !== rects.current.size;\n for (const [id, rect] of next) {\n if (!rectsEqual(rects.current.get(id), rect)) changed = true;\n }\n rects.current = next;\n return changed;\n }, []);\n\n const frameLoop = useVisibleRaf(\n () => {\n const el = container.current;\n if (!el) {\n dirty.current.clear();\n return;\n }\n let retiled = false;\n if (needsMeasure.current) {\n needsMeasure.current = false;\n if (measure()) {\n retiled = true;\n for (const id of rects.current.keys()) dirty.current.add(id);\n // Geometry that changed may still be moving: a panel whose size has\n // settled while its position animates gives `ResizeObserver` nothing\n // more to report, and the tile would hold the frame it was caught\n // mid-flight at. Measure again next frame, and keep going until a\n // measurement finds nothing moved.\n needsMeasure.current = true;\n schedule();\n }\n }\n const dpr = globalThis.devicePixelRatio ?? 1;\n if (dpr !== lastDpr.current) {\n lastDpr.current = dpr;\n retiled = true;\n for (const id of rects.current.keys()) dirty.current.add(id);\n }\n if (dirty.current.size === 0) return;\n const box = el.getBoundingClientRect();\n const frame: SurfaceFrame = {\n dirty: new Set(dirty.current),\n rects: new Map(rects.current),\n dpr,\n size: { width: box.width, height: box.height },\n retiled,\n };\n // Cleared before the owner runs, not after the painters: sizing the\n // buffer blanks every tile, so the owner answers with `invalidateAll`,\n // and a set cleared at the end of the frame would swallow it.\n dirty.current.clear();\n onFrameRef.current(frame);\n // After the owner sized the buffer, before anything paints into it.\n if (retiled) {\n for (const clear of clears.current.values()) clear(frame.size, dpr);\n }\n // After the owner, which is what resized the buffer this frame — and\n // whatever it just dirtied paints now rather than a frame later.\n const painting = new Set(frame.dirty);\n for (const id of dirty.current) painting.add(id);\n dirty.current.clear();\n const paintFrame: SurfaceFrame = { ...frame, dirty: painting };\n for (const id of painting) {\n const rect = frame.rects.get(id);\n if (rect) painters.current.get(id)?.(rect, paintFrame);\n }\n },\n // The host attaches its container through `containerRef`, which may land\n // well after this hook's first effect; the gate re-resolves it per request.\n { target: () => container.current },\n );\n\n const schedule = useCallback(() => {\n frameLoop.request();\n }, [frameLoop]);\n\n const invalidate = useCallback(\n (id: string) => {\n dirty.current.add(id);\n schedule();\n },\n [schedule],\n );\n\n const invalidateAll = useCallback(() => {\n for (const id of tiles.current.keys()) dirty.current.add(id);\n schedule();\n }, [schedule]);\n\n const invalidateRects = useCallback(() => {\n needsMeasure.current = true;\n schedule();\n }, [schedule]);\n\n const registerTile = useCallback(\n (id: string, el: HTMLElement | null) => {\n const known = tiles.current.get(id);\n if (known === el) return;\n if (known) observer.current?.unobserve(known);\n if (el) {\n tiles.current.set(id, el);\n observer.current?.observe(el);\n } else {\n tiles.current.delete(id);\n rects.current.delete(id);\n dirty.current.delete(id);\n }\n needsMeasure.current = true;\n schedule();\n },\n [schedule],\n );\n\n const registerClear = useCallback((id: string, clear: SurfaceClear) => {\n clears.current.set(id, clear);\n return () => {\n if (clears.current.get(id) === clear) clears.current.delete(id);\n };\n }, []);\n\n const registerPainter = useCallback((id: string, paint: TilePainter) => {\n painters.current.set(id, paint);\n return () => {\n if (painters.current.get(id) === paint) painters.current.delete(id);\n };\n }, []);\n\n const getContainer = useCallback(() => container.current, []);\n\n const containerRef = useCallback(\n (el: HTMLElement | null) => {\n if (container.current === el) return;\n if (container.current) observer.current?.unobserve(container.current);\n container.current = el;\n if (el) observer.current?.observe(el);\n needsMeasure.current = true;\n schedule();\n },\n [schedule],\n );\n\n useEffect(() => {\n const ro = new ResizeObserver(() => {\n needsMeasure.current = true;\n schedule();\n });\n observer.current = ro;\n if (container.current) ro.observe(container.current);\n for (const el of tiles.current.values()) ro.observe(el);\n return () => {\n ro.disconnect();\n observer.current = null;\n frameLoop.cancel();\n };\n }, [schedule, frameLoop]);\n\n return useMemo(\n () => ({\n invalidate,\n invalidateAll,\n invalidateRects,\n registerTile,\n registerClear,\n registerPainter,\n containerRef,\n getContainer,\n }),\n [\n invalidate,\n invalidateAll,\n invalidateRects,\n registerTile,\n registerClear,\n registerPainter,\n containerRef,\n getContainer,\n ],\n );\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/primitives/FloatingPanel.tsx"],"names":[],"mappings":"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","file":"chunk-J7OWWTCW.js","sourcesContent":["import { openPointerSession, type PointerSession, pastDragThreshold } from '@weasel-js/core';\nimport type React from 'react';\nimport { type CSSProperties, type ReactNode, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n type Corner,\n DEFAULT_ANCHOR,\n DEFAULT_INSET,\n FLOATING_DRAG_PREFIX,\n type FloatingPlacement,\n floatingStrategy,\n} from 'windease';\nimport { usePersistedState } from '../state/usePersistedState';\n\n/** The strategy holds a map keyed by item id; a panel is always a lone item. */\nconst ITEM_ID = 'panel';\n\n/** Props for `<FloatingPanel>`. */\nexport interface FloatingPanelProps {\n children: ReactNode;\n /** Corner it rests in before it has ever been dragged. Default `'bottom-left'`. */\n anchor?: Corner;\n /** Corners that may capture it. Default: all four. */\n snapCorners?: readonly Corner[];\n /** Pixels in from a corner when snapped. Default 12. */\n inset?: number;\n /** Name to remember its position under, through `usePersistedState` — so it\n * is remembered only inside a lab or a `<Persistence>`. Omit to forget on\n * reload. */\n persist?: string;\n className?: string;\n}\n\n/**\n * The panel's footprint is its border box — `contentRect` excludes padding and\n * border, which would place a panel that then overflows its corner by exactly\n * that much.\n */\nfunction borderBoxOf(entry: ResizeObserverEntry): { w: number; h: number } {\n const box = entry.borderBoxSize?.[0];\n if (box) return { w: box.inlineSize, h: box.blockSize };\n return { w: entry.contentRect.width, h: entry.contentRect.height };\n}\n\n/** A pointerdown on one of these is the child's, not a drag. */\nfunction isInteractive(target: EventTarget | null): boolean {\n if (!(target instanceof Element)) return false;\n return target.closest('input, button, a, select, textarea, [data-no-drag]') !== null;\n}\n\n/**\n * A draggable box that floats over its offset parent and snaps to its corners.\n *\n * Drives windease's `floatingStrategy` as a pure function rather than mounting a\n * windease container: a lab overlay has one item and no zone tree, so the node\n * model would be all cost. Pointer handling is therefore this component's, and\n * windease's own affordance rendering never participates.\n */\nexport function FloatingPanel({\n children,\n anchor = DEFAULT_ANCHOR,\n snapCorners,\n inset = DEFAULT_INSET,\n persist,\n className,\n}: FloatingPanelProps) {\n const ref = useRef<HTMLDivElement>(null);\n const strategy = useMemo(() => floatingStrategy(), []);\n const options = useMemo(() => ({ defaultAnchor: anchor, inset }), [anchor, inset]);\n\n const [container, setContainer] = useState({ w: 0, h: 0 });\n const [size, setSize] = useState({ w: 0, h: 0 });\n const [place, setPlace] = usePersistedState<FloatingPlacement>(persist, () => ({\n x: 0,\n y: 0,\n anchor,\n }));\n\n const item = useMemo(\n () => ({\n id: ITEM_ID,\n meta: { floating: true, ...(snapCorners ? { snapCorners: [...snapCorners] } : {}) },\n natural: size,\n }),\n [size, snapCorners],\n );\n\n useEffect(() => {\n const el = ref.current;\n const parent = el?.offsetParent ?? el?.parentElement;\n if (!el || !parent) return;\n // Sizes come off the entry, not the DOM: jsdom reports 0 for every\n // clientWidth/offsetWidth, and an unmeasured item is withheld from layout.\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n if (entry.target === parent) {\n setContainer({ w: entry.contentRect.width, h: entry.contentRect.height });\n } else {\n setSize(borderBoxOf(entry));\n }\n }\n });\n observer.observe(parent);\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n\n const rect = strategy\n .layout({\n items: [item],\n container,\n state: { at: { [ITEM_ID]: place }, inner: undefined },\n options,\n })\n .placements.get(ITEM_ID);\n\n const dragging = useRef<{ x: number; y: number } | null>(null);\n const session = useRef<PointerSession | null>(null);\n const [isDragging, setDragging] = useState(false);\n // A drag outlives the render that started it, so the reducer's inputs are\n // read here and not from that render's closure — a container resized\n // mid-drag would otherwise place the panel against its old box.\n const layout = useRef({ container, options, item });\n layout.current = { container, options, item };\n\n useEffect(() => () => session.current?.cancel(), []);\n\n const onPointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if (isInteractive(e.target)) return;\n // The canvas stack underneath owns pan/zoom on the same pointer events.\n e.stopPropagation();\n const origin = e.currentTarget;\n const pointerId = e.pointerId;\n const start = { x: e.clientX, y: e.clientY };\n\n const end = () => {\n session.current = null;\n if (!dragging.current) return;\n dragging.current = null;\n setDragging(false);\n try {\n origin.releasePointerCapture?.(pointerId);\n } catch {\n // Capture is already gone whenever the session ended by losing it.\n }\n };\n\n // Armed, not capturing. Capture retargets mouseup to this element, and the\n // browser then synthesizes no `click` on the child under the cursor — so\n // capturing on press makes every non-native control in the panel dead to a\n // real mouse, silently. `isInteractive` only exempts the names it lists; a\n // `role=\"button\"` span, a react-aria control or a canvas is not among them.\n session.current = openPointerSession(\n origin,\n e,\n {\n onMove: (ev) => {\n if (!dragging.current) {\n if (!pastDragThreshold({ clientX: start.x, clientY: start.y }, ev)) return;\n dragging.current = { ...start };\n setDragging(true);\n origin.setPointerCapture?.(pointerId);\n }\n const from = dragging.current;\n const dx = ev.clientX - from.x;\n const dy = ev.clientY - from.y;\n if (dx === 0 && dy === 0) return;\n dragging.current = { x: ev.clientX, y: ev.clientY };\n const { container: box, options: opts, item: only } = layout.current;\n setPlace(\n (prev) =>\n strategy.reduce?.(\n { at: { [ITEM_ID]: prev }, inner: undefined },\n {\n affordanceId: `${FLOATING_DRAG_PREFIX}${ITEM_ID}`,\n kind: 'drag',\n payload: { dx, dy },\n },\n { container: box, options: opts, items: [only] },\n ).at[ITEM_ID] ?? prev,\n );\n },\n onEnd: end,\n onCancel: end,\n },\n { capture: false },\n );\n };\n\n return (\n <div\n className={className ? `lk-floating-panel ${className}` : 'lk-floating-panel'}\n data-dragging={isDragging ? 'true' : undefined}\n data-placed={rect ? 'true' : undefined}\n onPointerDown={onPointerDown}\n ref={ref}\n style={\n {\n position: 'absolute',\n left: `${rect?.x ?? 0}px`,\n top: `${rect?.y ?? 0}px`,\n } as CSSProperties\n }\n >\n {children}\n </div>\n );\n}\n"]}
|
package/dist/chunk-M7HP3FTK.js
DELETED
|
@@ -1,549 +0,0 @@
|
|
|
1
|
-
import { centerOn, zoomAt } from './chunk-JVBYV6TL.js';
|
|
2
|
-
import { screenToWorld } from './chunk-AWQG7FCC.js';
|
|
3
|
-
import { CameraContext, CameraScope } from './chunk-UNAZSLWE.js';
|
|
4
|
-
import { resolveFrame, DEFAULT_FRAME } from './chunk-24W5VEJW.js';
|
|
5
|
-
import { CanvasStackContext } from './chunk-CQLQPQ4P.js';
|
|
6
|
-
import { useVisibleRaf, useActionsRegistry, useGestureDispatcher, normalizeZoom } from '@weasel-js/core';
|
|
7
|
-
import { useRef, useEffect, useContext, useReducer, useCallback, useMemo, useState } from 'react';
|
|
8
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
9
|
-
|
|
10
|
-
// src/loupe/canvasLens.ts
|
|
11
|
-
function lensCamera(aim, outer, outerFrame, factor, diameter, worldSpec) {
|
|
12
|
-
const size = { width: diameter, height: diameter };
|
|
13
|
-
const frame = resolveFrame(worldSpec, size);
|
|
14
|
-
const world = screenToWorld(aim, outer, outerFrame);
|
|
15
|
-
return { view: centerOn(world, outer.zoom * factor, size, frame), frame };
|
|
16
|
-
}
|
|
17
|
-
function lensSourceRect(aim, factor, diameter, dpr) {
|
|
18
|
-
const span = diameter / factor;
|
|
19
|
-
return {
|
|
20
|
-
sx: (aim.x - span / 2) * dpr,
|
|
21
|
-
sy: (aim.y - span / 2) * dpr,
|
|
22
|
-
sw: span * dpr,
|
|
23
|
-
sh: span * dpr
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
function sampleStack(layers, canvases, p, dpr) {
|
|
27
|
-
for (let i = layers.length - 1; i >= 0; i--) {
|
|
28
|
-
const layer = layers[i];
|
|
29
|
-
if (!layer.visible) continue;
|
|
30
|
-
const canvas = canvases.get(layer.id);
|
|
31
|
-
if (!canvas) continue;
|
|
32
|
-
const ctx = canvas.getContext("2d", { willReadFrequently: true });
|
|
33
|
-
if (!ctx) continue;
|
|
34
|
-
const x = Math.floor(p.x * dpr);
|
|
35
|
-
const y = Math.floor(p.y * dpr);
|
|
36
|
-
if (x < 0 || y < 0 || x >= canvas.width || y >= canvas.height) continue;
|
|
37
|
-
const [r, g, b, a] = ctx.getImageData(x, y, 1, 1).data;
|
|
38
|
-
if (a === 0) continue;
|
|
39
|
-
return `#${[r, g, b].map((c) => c.toString(16).padStart(2, "0")).join("")}`;
|
|
40
|
-
}
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
function drawCanvasLens(ctx, opts) {
|
|
44
|
-
const { aim, factor, diameter, dpr, mode, outer, layers, canvases } = opts;
|
|
45
|
-
ctx.save();
|
|
46
|
-
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
47
|
-
ctx.clearRect(0, 0, diameter, diameter);
|
|
48
|
-
if (mode === "pixel") {
|
|
49
|
-
const { sx, sy, sw, sh } = lensSourceRect(aim, factor, diameter, dpr);
|
|
50
|
-
ctx.imageSmoothingEnabled = false;
|
|
51
|
-
for (const layer of layers) {
|
|
52
|
-
if (!layer.visible) continue;
|
|
53
|
-
const canvas = canvases.get(layer.id);
|
|
54
|
-
if (!canvas || canvas.width === 0 || canvas.height === 0) continue;
|
|
55
|
-
ctx.drawImage(canvas, sx, sy, sw, sh, 0, 0, diameter, diameter);
|
|
56
|
-
}
|
|
57
|
-
ctx.restore();
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const lens = lensCamera(
|
|
61
|
-
aim,
|
|
62
|
-
outer,
|
|
63
|
-
opts.outerFrame ?? DEFAULT_FRAME,
|
|
64
|
-
factor,
|
|
65
|
-
diameter,
|
|
66
|
-
opts.worldSpec
|
|
67
|
-
);
|
|
68
|
-
for (const layer of layers) {
|
|
69
|
-
if (!layer.visible) continue;
|
|
70
|
-
ctx.save();
|
|
71
|
-
layer.render(ctx, lens.view, lens.frame);
|
|
72
|
-
ctx.restore();
|
|
73
|
-
}
|
|
74
|
-
ctx.restore();
|
|
75
|
-
}
|
|
76
|
-
function CanvasLoupe({
|
|
77
|
-
aim,
|
|
78
|
-
factor,
|
|
79
|
-
mode,
|
|
80
|
-
diameter,
|
|
81
|
-
surface,
|
|
82
|
-
view,
|
|
83
|
-
frame,
|
|
84
|
-
worldSpec
|
|
85
|
-
}) {
|
|
86
|
-
const canvasRef = useRef(null);
|
|
87
|
-
const dpr = surface.size.dpr;
|
|
88
|
-
const args = { aim, factor, mode, diameter, dpr, view, frame, worldSpec, surface };
|
|
89
|
-
const argsRef = useRef(args);
|
|
90
|
-
argsRef.current = args;
|
|
91
|
-
const loop = useVisibleRaf(
|
|
92
|
-
() => {
|
|
93
|
-
loop.request();
|
|
94
|
-
const canvas = canvasRef.current;
|
|
95
|
-
const ctx = canvas?.getContext("2d");
|
|
96
|
-
const canvases = argsRef.current.surface.canvases.current;
|
|
97
|
-
if (!ctx || !canvases) return;
|
|
98
|
-
const a = argsRef.current;
|
|
99
|
-
drawCanvasLens(ctx, {
|
|
100
|
-
aim: a.aim,
|
|
101
|
-
factor: a.factor,
|
|
102
|
-
diameter: a.diameter,
|
|
103
|
-
dpr: a.dpr,
|
|
104
|
-
mode: a.mode,
|
|
105
|
-
outer: a.view,
|
|
106
|
-
outerFrame: a.frame,
|
|
107
|
-
worldSpec: a.worldSpec,
|
|
108
|
-
layers: a.surface.layers,
|
|
109
|
-
canvases
|
|
110
|
-
});
|
|
111
|
-
},
|
|
112
|
-
{ target: canvasRef }
|
|
113
|
-
);
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
loop.request();
|
|
116
|
-
return () => loop.cancel();
|
|
117
|
-
}, [loop]);
|
|
118
|
-
return /* @__PURE__ */ jsx(
|
|
119
|
-
"canvas",
|
|
120
|
-
{
|
|
121
|
-
ref: canvasRef,
|
|
122
|
-
className: "lk-loupe__canvas",
|
|
123
|
-
width: Math.max(1, Math.round(diameter * dpr)),
|
|
124
|
-
height: Math.max(1, Math.round(diameter * dpr))
|
|
125
|
-
}
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
function DomLoupe({
|
|
129
|
-
aim,
|
|
130
|
-
factor,
|
|
131
|
-
mode,
|
|
132
|
-
diameter,
|
|
133
|
-
size,
|
|
134
|
-
view,
|
|
135
|
-
frame,
|
|
136
|
-
state,
|
|
137
|
-
config,
|
|
138
|
-
render
|
|
139
|
-
}) {
|
|
140
|
-
const style = {
|
|
141
|
-
width: `${size.width}px`,
|
|
142
|
-
height: `${size.height}px`,
|
|
143
|
-
transform: `translate(${diameter / 2 - aim.x}px, ${diameter / 2 - aim.y}px)`
|
|
144
|
-
};
|
|
145
|
-
return /* @__PURE__ */ jsx("div", { className: "lk-loupe__stage", style, children: render({
|
|
146
|
-
state,
|
|
147
|
-
config,
|
|
148
|
-
view: zoomAt(view, factor, aim, { frame }),
|
|
149
|
-
factor,
|
|
150
|
-
mode,
|
|
151
|
-
size
|
|
152
|
-
}) });
|
|
153
|
-
}
|
|
154
|
-
function LoupeBubble({ aim, diameter, hostRef, children }) {
|
|
155
|
-
const style = {
|
|
156
|
-
width: `${diameter}px`,
|
|
157
|
-
height: `${diameter}px`,
|
|
158
|
-
transform: `translate(${aim.x - diameter / 2}px, ${aim.y - diameter / 2}px)`
|
|
159
|
-
};
|
|
160
|
-
return /* @__PURE__ */ jsx("div", { ref: hostRef, className: "lk-loupe", style, "aria-hidden": "true", children });
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// src/loupe/loupeActions.ts
|
|
164
|
-
var LOUPE_PEEK_ID = "loupe.peek";
|
|
165
|
-
var LOUPE_MAGNIFY_ID = "loupe.magnify";
|
|
166
|
-
var WHEEL_RATE = 2e-3;
|
|
167
|
-
function createLoupeActions(input, peekKey) {
|
|
168
|
-
const magnify = {
|
|
169
|
-
id: LOUPE_MAGNIFY_ID,
|
|
170
|
-
label: "Magnify (loupe)",
|
|
171
|
-
group: "loupe",
|
|
172
|
-
// Hotkey scope, so while the lens is up it outranks the trial camera's
|
|
173
|
-
// wheel zoom on the same dispatcher; while it is down `enabled` declines
|
|
174
|
-
// and the zoom runs.
|
|
175
|
-
scope: "hotkey",
|
|
176
|
-
// Every modifier optional: the lens claims the wheel whenever it is up,
|
|
177
|
-
// which is what the hand-rolled capture-phase listener did. A bare spec
|
|
178
|
-
// would forbid modifiers and hand Cmd+wheel back to the lab mid-peek.
|
|
179
|
-
defaultBinding: [
|
|
180
|
-
{
|
|
181
|
-
spec: {
|
|
182
|
-
kind: "wheel",
|
|
183
|
-
mods: { alt: "optional", ctrl: "optional", meta: "optional", shift: "optional" }
|
|
184
|
-
},
|
|
185
|
-
opts: {}
|
|
186
|
-
}
|
|
187
|
-
],
|
|
188
|
-
enabled: () => input.shown() ? true : "not-applicable",
|
|
189
|
-
invoker: {
|
|
190
|
-
timing: "immediate",
|
|
191
|
-
run(_deps, params) {
|
|
192
|
-
input.magnifyBy(params?.deltaY ?? 0);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
if (peekKey === null) return [magnify];
|
|
197
|
-
const peek = {
|
|
198
|
-
id: LOUPE_PEEK_ID,
|
|
199
|
-
label: "Peek (loupe)",
|
|
200
|
-
group: "loupe",
|
|
201
|
-
// Hotkey scope: peeking must beat whatever the lab's active tool binds to
|
|
202
|
-
// the same key, the way every other held-key trigger does.
|
|
203
|
-
scope: "hotkey",
|
|
204
|
-
// Every modifier optional because the peek key may BE one: the keydown
|
|
205
|
-
// that carries `Alt` — the default — also reports `altKey: true`, and the
|
|
206
|
-
// matcher forbids any modifier a spec does not name.
|
|
207
|
-
defaultBinding: [
|
|
208
|
-
{
|
|
209
|
-
spec: {
|
|
210
|
-
kind: "key-held",
|
|
211
|
-
key: peekKey,
|
|
212
|
-
mods: { alt: "optional", ctrl: "optional", meta: "optional", shift: "optional" }
|
|
213
|
-
},
|
|
214
|
-
opts: {}
|
|
215
|
-
}
|
|
216
|
-
],
|
|
217
|
-
invoker: {
|
|
218
|
-
timing: "ongoing",
|
|
219
|
-
start() {
|
|
220
|
-
input.setPeeking(true);
|
|
221
|
-
return { onEnd: () => input.setPeeking(false) };
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
return [peek, magnify];
|
|
226
|
-
}
|
|
227
|
-
var NO_TOOLS = /* @__PURE__ */ new Map();
|
|
228
|
-
var CHANNELS = { pointer: false, contextMenu: false, ingest: false };
|
|
229
|
-
function LoupeDispatch({
|
|
230
|
-
hostRef,
|
|
231
|
-
input,
|
|
232
|
-
peekKey,
|
|
233
|
-
registry,
|
|
234
|
-
ownDispatcher
|
|
235
|
-
}) {
|
|
236
|
-
const actions = useMemo(() => createLoupeActions(input, peekKey), [input, peekKey]);
|
|
237
|
-
useEffect(() => {
|
|
238
|
-
const offs = actions.map((a) => registry.register(a));
|
|
239
|
-
return () => {
|
|
240
|
-
for (const off of offs) off();
|
|
241
|
-
};
|
|
242
|
-
}, [registry, actions]);
|
|
243
|
-
useGestureDispatcher({
|
|
244
|
-
canvasRef: hostRef,
|
|
245
|
-
actions: registry,
|
|
246
|
-
entriesById: NO_TOOLS,
|
|
247
|
-
channels: CHANNELS,
|
|
248
|
-
enabled: ownDispatcher
|
|
249
|
-
});
|
|
250
|
-
return null;
|
|
251
|
-
}
|
|
252
|
-
function LoupeGestures(props) {
|
|
253
|
-
const registry = useActionsRegistry();
|
|
254
|
-
const camera = useContext(CameraContext);
|
|
255
|
-
if (!registry) return null;
|
|
256
|
-
return /* @__PURE__ */ jsx(LoupeDispatch, { ...props, registry, ownDispatcher: camera === null });
|
|
257
|
-
}
|
|
258
|
-
var ZERO = { width: 0, height: 0 };
|
|
259
|
-
function useHostSize(ref) {
|
|
260
|
-
const [size, setSize] = useState(ZERO);
|
|
261
|
-
useEffect(() => {
|
|
262
|
-
const el = ref.current;
|
|
263
|
-
if (!el) return;
|
|
264
|
-
const update = () => {
|
|
265
|
-
const rect = el.getBoundingClientRect();
|
|
266
|
-
setSize(
|
|
267
|
-
(prev) => prev.width === rect.width && prev.height === rect.height ? prev : { width: rect.width, height: rect.height }
|
|
268
|
-
);
|
|
269
|
-
};
|
|
270
|
-
update();
|
|
271
|
-
if (typeof ResizeObserver === "undefined") return;
|
|
272
|
-
const ro = new ResizeObserver(update);
|
|
273
|
-
ro.observe(el);
|
|
274
|
-
return () => ro.disconnect();
|
|
275
|
-
}, [ref]);
|
|
276
|
-
return size;
|
|
277
|
-
}
|
|
278
|
-
function loupeSourcePoint(p, rect, aim, factor) {
|
|
279
|
-
return {
|
|
280
|
-
x: aim.x + (p.x - (rect.x + rect.w / 2)) / factor,
|
|
281
|
-
y: aim.y + (p.y - (rect.y + rect.h / 2)) / factor
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
function createLoupeModel(opts) {
|
|
285
|
-
const { surface } = opts;
|
|
286
|
-
let mode = opts.mode ?? "vector";
|
|
287
|
-
let factor = normalizeZoom(opts.factor ?? 8);
|
|
288
|
-
let aim = { x: 0, y: 0 };
|
|
289
|
-
let color = null;
|
|
290
|
-
let disposed = false;
|
|
291
|
-
let aimUnsampled = false;
|
|
292
|
-
const clamp = (n) => normalizeZoom(Math.min(
|
|
293
|
-
opts.maxFactor ?? Number.POSITIVE_INFINITY,
|
|
294
|
-
Math.max(opts.minFactor ?? Number.NEGATIVE_INFINITY, n)
|
|
295
|
-
));
|
|
296
|
-
const sampleColor = () => {
|
|
297
|
-
const hex = surface.sample(aim);
|
|
298
|
-
if (hex === null || hex === color) return;
|
|
299
|
-
color = hex;
|
|
300
|
-
opts.onColorChange?.(hex);
|
|
301
|
-
};
|
|
302
|
-
const unsubscribeFrame = surface.subscribeFrame?.(() => {
|
|
303
|
-
if (!aimUnsampled) return;
|
|
304
|
-
aimUnsampled = false;
|
|
305
|
-
sampleColor();
|
|
306
|
-
});
|
|
307
|
-
const teardown = () => {
|
|
308
|
-
if (disposed) return;
|
|
309
|
-
disposed = true;
|
|
310
|
-
unsubscribeFrame?.();
|
|
311
|
-
opts.onDispose?.();
|
|
312
|
-
};
|
|
313
|
-
return {
|
|
314
|
-
get mode() {
|
|
315
|
-
return mode;
|
|
316
|
-
},
|
|
317
|
-
get factor() {
|
|
318
|
-
return factor;
|
|
319
|
-
},
|
|
320
|
-
get aim() {
|
|
321
|
-
return aim;
|
|
322
|
-
},
|
|
323
|
-
get color() {
|
|
324
|
-
return color;
|
|
325
|
-
},
|
|
326
|
-
setMode(next) {
|
|
327
|
-
if (disposed || next === mode) return;
|
|
328
|
-
mode = next;
|
|
329
|
-
surface.changed();
|
|
330
|
-
},
|
|
331
|
-
setFactor(next) {
|
|
332
|
-
if (disposed) return;
|
|
333
|
-
factor = clamp(next);
|
|
334
|
-
surface.changed();
|
|
335
|
-
},
|
|
336
|
-
aimAt(p) {
|
|
337
|
-
if (disposed) return;
|
|
338
|
-
if (surface.gone()) {
|
|
339
|
-
teardown();
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
if (surface.hidden()) return;
|
|
343
|
-
if (surface.covers(p)) return;
|
|
344
|
-
aim = p;
|
|
345
|
-
if (unsubscribeFrame) aimUnsampled = true;
|
|
346
|
-
else sampleColor();
|
|
347
|
-
surface.changed();
|
|
348
|
-
},
|
|
349
|
-
pick(p) {
|
|
350
|
-
if (disposed) return null;
|
|
351
|
-
let at = aim;
|
|
352
|
-
if (p) {
|
|
353
|
-
const rect = surface.lens();
|
|
354
|
-
if (!rect) return null;
|
|
355
|
-
at = loupeSourcePoint(p, rect, aim, factor);
|
|
356
|
-
if (surface.covers(at)) return null;
|
|
357
|
-
}
|
|
358
|
-
const hex = surface.sample(at);
|
|
359
|
-
if (hex !== null) opts.onPick?.(hex);
|
|
360
|
-
return hex;
|
|
361
|
-
},
|
|
362
|
-
dispose: teardown
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
function useLoupe({ capability, hostRef, enabled, sample }) {
|
|
366
|
-
const [, bump] = useReducer((n) => n + 1, 0);
|
|
367
|
-
const overRef = useRef(false);
|
|
368
|
-
const peekingRef = useRef(false);
|
|
369
|
-
const enabledRef = useRef(enabled);
|
|
370
|
-
enabledRef.current = enabled;
|
|
371
|
-
const sampleRef = useRef(sample);
|
|
372
|
-
sampleRef.current = sample;
|
|
373
|
-
const onColorChangeRef = useRef(capability.onColorChange);
|
|
374
|
-
onColorChangeRef.current = capability.onColorChange;
|
|
375
|
-
const shown = useCallback(
|
|
376
|
-
() => overRef.current && (enabledRef.current || peekingRef.current),
|
|
377
|
-
[]
|
|
378
|
-
);
|
|
379
|
-
const modelRef = useRef(null);
|
|
380
|
-
if (modelRef.current === null) {
|
|
381
|
-
modelRef.current = createLoupeModel({
|
|
382
|
-
mode: capability.mode,
|
|
383
|
-
factor: capability.factor,
|
|
384
|
-
minFactor: capability.minFactor,
|
|
385
|
-
maxFactor: capability.maxFactor,
|
|
386
|
-
onColorChange: (hex) => onColorChangeRef.current?.(hex),
|
|
387
|
-
surface: {
|
|
388
|
-
lens: () => {
|
|
389
|
-
const d = diameterRef.current;
|
|
390
|
-
const { x, y } = modelRef.current?.aim ?? { x: 0, y: 0 };
|
|
391
|
-
return { x: x - d / 2, y: y - d / 2, w: d, h: d };
|
|
392
|
-
},
|
|
393
|
-
// The lens follows the pointer and is painted over the host rather than
|
|
394
|
-
// into it, so it is never part of the picture being magnified.
|
|
395
|
-
covers: () => false,
|
|
396
|
-
sample: (p) => sampleRef.current?.(p) ?? null,
|
|
397
|
-
hidden: () => !shown(),
|
|
398
|
-
gone: () => goneRef.current,
|
|
399
|
-
changed: bump
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
const model = modelRef.current;
|
|
404
|
-
const diameterRef = useRef(capability.diameter);
|
|
405
|
-
diameterRef.current = capability.diameter;
|
|
406
|
-
const goneRef = useRef(false);
|
|
407
|
-
useEffect(() => {
|
|
408
|
-
goneRef.current = false;
|
|
409
|
-
return () => {
|
|
410
|
-
goneRef.current = true;
|
|
411
|
-
};
|
|
412
|
-
}, []);
|
|
413
|
-
useEffect(() => {
|
|
414
|
-
if (!enabled && !peekingRef.current) bump();
|
|
415
|
-
}, [enabled]);
|
|
416
|
-
useEffect(() => {
|
|
417
|
-
const host = hostRef.current;
|
|
418
|
-
if (!host) return;
|
|
419
|
-
const onPointerMove = (e) => {
|
|
420
|
-
overRef.current = true;
|
|
421
|
-
const rect = host.getBoundingClientRect();
|
|
422
|
-
model.aimAt({ x: e.clientX - rect.left, y: e.clientY - rect.top });
|
|
423
|
-
if (!shown()) return;
|
|
424
|
-
bump();
|
|
425
|
-
};
|
|
426
|
-
const onPointerLeave = () => {
|
|
427
|
-
overRef.current = false;
|
|
428
|
-
bump();
|
|
429
|
-
};
|
|
430
|
-
host.addEventListener("pointermove", onPointerMove);
|
|
431
|
-
host.addEventListener("pointerleave", onPointerLeave);
|
|
432
|
-
return () => {
|
|
433
|
-
host.removeEventListener("pointermove", onPointerMove);
|
|
434
|
-
host.removeEventListener("pointerleave", onPointerLeave);
|
|
435
|
-
};
|
|
436
|
-
}, [hostRef, model, shown]);
|
|
437
|
-
const inputRef = useRef(null);
|
|
438
|
-
if (inputRef.current === null) {
|
|
439
|
-
inputRef.current = {
|
|
440
|
-
shown,
|
|
441
|
-
setPeeking: (on) => {
|
|
442
|
-
if (peekingRef.current === on) return;
|
|
443
|
-
peekingRef.current = on;
|
|
444
|
-
bump();
|
|
445
|
-
},
|
|
446
|
-
magnifyBy: (deltaY) => {
|
|
447
|
-
const m = modelRef.current;
|
|
448
|
-
if (m) m.setFactor(m.factor * Math.exp(-deltaY * WHEEL_RATE));
|
|
449
|
-
}
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
return {
|
|
453
|
-
visible: shown(),
|
|
454
|
-
aim: model.aim,
|
|
455
|
-
factor: model.factor,
|
|
456
|
-
mode: model.mode,
|
|
457
|
-
color: model.color,
|
|
458
|
-
setMode: model.setMode,
|
|
459
|
-
setFactor: model.setFactor,
|
|
460
|
-
pick: model.pick,
|
|
461
|
-
input: inputRef.current
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
var NO_HOST = { current: null };
|
|
465
|
-
function TrialLoupe({
|
|
466
|
-
capability,
|
|
467
|
-
enabled,
|
|
468
|
-
state,
|
|
469
|
-
config,
|
|
470
|
-
view,
|
|
471
|
-
worldSpec,
|
|
472
|
-
hostRef
|
|
473
|
-
}) {
|
|
474
|
-
const stack = useContext(CanvasStackContext);
|
|
475
|
-
const surface = capability.render ? void 0 : stack?.surface;
|
|
476
|
-
const host = surface?.element ?? hostRef ?? NO_HOST;
|
|
477
|
-
const sample = useMemo(() => {
|
|
478
|
-
if (!surface) return void 0;
|
|
479
|
-
return (p) => {
|
|
480
|
-
const canvases = surface.canvases.current;
|
|
481
|
-
return canvases ? sampleStack(surface.layers, canvases, p, surface.size.dpr) : null;
|
|
482
|
-
};
|
|
483
|
-
}, [surface]);
|
|
484
|
-
const loupe = useLoupe({ capability, hostRef: host, enabled, sample });
|
|
485
|
-
const measured = useHostSize(host);
|
|
486
|
-
const size = surface?.size ?? measured;
|
|
487
|
-
const gestures = /* @__PURE__ */ jsx(CameraScope, { children: /* @__PURE__ */ jsx(LoupeGestures, { hostRef: host, input: loupe.input, peekKey: capability.peekKey ?? null }) });
|
|
488
|
-
if (!loupe.visible) return gestures;
|
|
489
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
490
|
-
gestures,
|
|
491
|
-
/* @__PURE__ */ jsx(LoupeBubble, { aim: loupe.aim, diameter: capability.diameter, children: capability.render ? /* @__PURE__ */ jsx(
|
|
492
|
-
DomLoupe,
|
|
493
|
-
{
|
|
494
|
-
aim: loupe.aim,
|
|
495
|
-
factor: loupe.factor,
|
|
496
|
-
mode: loupe.mode,
|
|
497
|
-
diameter: capability.diameter,
|
|
498
|
-
size,
|
|
499
|
-
view,
|
|
500
|
-
frame: stack?.frame,
|
|
501
|
-
state,
|
|
502
|
-
config,
|
|
503
|
-
render: capability.render
|
|
504
|
-
}
|
|
505
|
-
) : surface && stack ? /* @__PURE__ */ jsx(
|
|
506
|
-
CanvasLoupe,
|
|
507
|
-
{
|
|
508
|
-
aim: loupe.aim,
|
|
509
|
-
factor: loupe.factor,
|
|
510
|
-
mode: loupe.mode,
|
|
511
|
-
diameter: capability.diameter,
|
|
512
|
-
surface,
|
|
513
|
-
view: stack.view,
|
|
514
|
-
frame: stack.frame,
|
|
515
|
-
worldSpec
|
|
516
|
-
}
|
|
517
|
-
) : null })
|
|
518
|
-
] });
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
// src/loupe/types.ts
|
|
522
|
-
var LOUPE_DEFAULTS = {
|
|
523
|
-
factor: 6,
|
|
524
|
-
minFactor: 2,
|
|
525
|
-
maxFactor: 32,
|
|
526
|
-
mode: "vector",
|
|
527
|
-
diameter: 200,
|
|
528
|
-
peekKey: "Alt"
|
|
529
|
-
};
|
|
530
|
-
function resolveLoupe(declared) {
|
|
531
|
-
const cap = declared === true ? {} : declared;
|
|
532
|
-
const minFactor = cap.minFactor ?? LOUPE_DEFAULTS.minFactor;
|
|
533
|
-
const maxFactor = cap.maxFactor ?? LOUPE_DEFAULTS.maxFactor;
|
|
534
|
-
return {
|
|
535
|
-
render: cap.render,
|
|
536
|
-
onColorChange: cap.onColorChange,
|
|
537
|
-
minFactor,
|
|
538
|
-
maxFactor,
|
|
539
|
-
factor: Math.min(maxFactor, Math.max(minFactor, cap.factor ?? LOUPE_DEFAULTS.factor)),
|
|
540
|
-
diameter: cap.diameter ?? LOUPE_DEFAULTS.diameter,
|
|
541
|
-
peekKey: cap.peekKey === void 0 ? LOUPE_DEFAULTS.peekKey : cap.peekKey,
|
|
542
|
-
// A DOM loupe has no framebuffer, so `pixel` would have nothing to enlarge.
|
|
543
|
-
mode: cap.render ? "vector" : cap.mode ?? LOUPE_DEFAULTS.mode
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
export { CanvasLoupe, DomLoupe, LOUPE_DEFAULTS, LOUPE_MAGNIFY_ID, LOUPE_PEEK_ID, LoupeBubble, LoupeGestures, TrialLoupe, createLoupeActions, drawCanvasLens, lensCamera, lensSourceRect, resolveLoupe, sampleStack, useLoupe };
|
|
548
|
-
//# sourceMappingURL=chunk-M7HP3FTK.js.map
|
|
549
|
-
//# sourceMappingURL=chunk-M7HP3FTK.js.map
|