@weasel-js/labkit 1.5.1 → 1.6.0
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 -7
- package/dist/_dts/{CanvasStackContext-CJNMS6mz.d.ts → CanvasStackContext-DQgcH1ny.d.ts} +1 -1
- package/dist/_dts/LayerList.d-2c9yup5Y.d.ts +83 -0
- package/dist/_dts/{PrefsForm.d-DPy9I8It.d.ts → PrefsRow.d-DFpPIeIC.d.ts} +16 -1
- package/dist/_dts/{Select.d-Gwr8fLpK.d.ts → Select.d-BchGMC2Y.d.ts} +129 -12
- package/dist/_dts/{frac-B4okC2lX.d.ts → frac-DTRq7Xpb.d.ts} +31 -13
- package/dist/_dts/inDialog-D5ZKGjiD.d.ts +23 -0
- package/dist/_dts/{index-CSJoj4LC.d.ts → index-B0--8PEM.d.ts} +5 -4
- package/dist/_dts/index-DINmCuLA.d.ts +453 -0
- package/dist/_dts/number.d-OeQYQoUO.d.ts +28 -0
- package/dist/_dts/{types-DzoNY1pO.d.ts → types-B7y8hX1D.d.ts} +6 -6
- package/dist/_dts/{usePanZoom-Pzf9f2jh.d.ts → usePanZoom-Bq73pwFe.d.ts} +4 -47
- package/dist/_dts/{useTrialState-uLlmaccn.d.ts → useTrialState-CP4jfuKl.d.ts} +1 -1
- package/dist/canvas/index.d.ts +6 -5
- package/dist/canvas/index.js +1 -1
- package/dist/chrome/index.d.ts +5 -4
- package/dist/chrome/index.js +7 -7
- package/dist/chunk-2RVCB2PT.js +3 -0
- package/dist/chunk-2RVCB2PT.js.map +1 -0
- package/dist/{chunk-UN4U4P63.js → chunk-3FI7Y4R4.js} +9 -9
- package/dist/chunk-3FI7Y4R4.js.map +1 -0
- package/dist/{chunk-7PFH3CNM.js → chunk-AWH3SRPW.js} +31 -5
- package/dist/chunk-AWH3SRPW.js.map +1 -0
- package/dist/{chunk-ZDHY47EV.js → chunk-BVL7Y574.js} +25 -9
- package/dist/chunk-BVL7Y574.js.map +1 -0
- package/dist/{chunk-IHUVQ3TX.js → chunk-H5VIV7MQ.js} +31 -27
- package/dist/chunk-H5VIV7MQ.js.map +1 -0
- package/dist/chunk-HFRE4QQV.js +400 -0
- package/dist/chunk-HFRE4QQV.js.map +1 -0
- package/dist/{chunk-IXTQI7JX.js → chunk-MOLIUNVH.js} +4 -4
- package/dist/{chunk-IXTQI7JX.js.map → chunk-MOLIUNVH.js.map} +1 -1
- package/dist/{chunk-CEIUBPPW.js → chunk-TT5C5S6R.js} +3 -86
- package/dist/chunk-TT5C5S6R.js.map +1 -0
- package/dist/chunk-USO6TERP.js +90 -0
- package/dist/chunk-USO6TERP.js.map +1 -0
- package/dist/{chunk-PHK4W562.js → chunk-VQ47KWD5.js} +3 -3
- package/dist/{chunk-PHK4W562.js.map → chunk-VQ47KWD5.js.map} +1 -1
- package/dist/chunk-WUJXJC5O.js +14568 -0
- package/dist/chunk-WUJXJC5O.js.map +1 -0
- package/dist/{chunk-EHGVROVV.js → chunk-ZORVNOKX.js} +6 -25
- package/dist/chunk-ZORVNOKX.js.map +1 -0
- package/dist/config/index.d.ts +53 -11
- package/dist/config/index.js +5 -5
- package/dist/controls/index.d.ts +6 -3
- package/dist/controls/index.js +4 -4
- package/dist/dragdrop/index.d.ts +4 -3
- package/dist/index.d.ts +139 -114
- package/dist/index.js +470 -479
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +6 -35
- package/dist/layers/index.js +2 -3
- package/dist/loupe/index.d.ts +6 -5
- package/dist/passthrough/weasel-ui.d.ts +421 -215
- package/dist/passthrough/weasel-ui.js +1 -1
- package/dist/primitives/index.d.ts +2 -13
- package/dist/primitives/index.js +4 -4
- package/dist/state/index.d.ts +6 -5
- package/dist/state/index.js +5 -5
- package/dist/styles.css +410 -190
- package/dist/undo/index.d.ts +4 -3
- package/package.json +9 -13
- package/src/annotations/frac.test.ts +7 -0
- package/src/annotations/paint.test.ts +21 -0
- package/src/annotations/paint.ts +12 -0
- package/src/annotations/store.test.ts +31 -0
- package/src/annotations/types.ts +3 -2
- package/src/canvas/Stage.test.tsx +18 -0
- package/src/canvas/index.ts +0 -9
- package/src/chrome/labTypes.ts +1 -1
- package/src/chrome/regions/PaletteRegion.test.tsx +18 -0
- package/src/chrome/regions/PaletteRegion.tsx +5 -4
- package/src/chrome/regions/SidebarRegion.less +197 -0
- package/src/chrome/regions/SidebarRegion.test.tsx +20 -0
- package/src/chrome/regions/SidebarRegion.tsx +7 -2
- package/src/chrome/regions/TitleBarRegion.tsx +1 -1
- package/src/chrome/types.ts +13 -4
- package/src/config/autoConfig.ts +2 -2
- package/src/config/builder.ts +23 -5
- package/src/config/entry.test.ts +8 -0
- package/src/config/index.ts +2 -0
- package/src/config/rules.ts +2 -0
- package/src/config/sectionTree.test.ts +146 -0
- package/src/config/sectionTree.ts +124 -0
- package/src/config/types.ts +4 -4
- package/src/controls/AutoControls.stories.tsx +6 -6
- package/src/controls/ControlPanel.less +27 -0
- package/src/controls/ControlPanel.stories.tsx +95 -1
- package/src/controls/ControlPanel.test.tsx +82 -112
- package/src/controls/ControlPanel.tsx +159 -396
- package/src/controls/inDialog.test.tsx +82 -0
- package/src/controls/inDialog.tsx +46 -0
- package/src/controls/index.ts +1 -0
- package/src/index.test.ts +0 -2
- package/src/index.ts +14 -35
- package/src/instrument/types.ts +5 -2
- package/src/lab/Lab.nebula.test.tsx +31 -0
- package/src/lab/Lab.tsx +57 -18
- package/src/lab/LabBoundary.test.tsx +66 -0
- package/src/lab/LabBoundary.tsx +56 -0
- package/src/lab/LabHeader.tsx +4 -23
- package/src/lab/LabRoot.tsx +2 -3
- package/src/lab/LabShell.less +0 -1
- package/src/lab/LabShell.stories.tsx +15 -0
- package/src/lab/LabShell.test.tsx +18 -0
- package/src/lab/LabShell.tsx +14 -1
- package/src/lab/LabSwitcher.less +1 -1
- package/src/lab/LabSwitcher.test.tsx +41 -0
- package/src/lab/LabSwitcher.tsx +30 -8
- package/src/lab/index.ts +1 -0
- package/src/layers/AGENTS.md +18 -74
- package/src/layers/index.ts +4 -2
- package/src/passthrough/weasel-ui.ts +25 -10
- package/src/primitives/FpsMeter.less +6 -1
- package/src/primitives/FpsMeter.test.tsx +12 -4
- package/src/primitives/FpsMeter.tsx +6 -1
- package/src/primitives/JobProgress.stories.tsx +1 -1
- package/src/primitives/StatusBar.less +6 -0
- package/src/primitives/index.ts +0 -2
- package/src/specimen/Specimen.tsx +42 -56
- package/src/state/types.ts +8 -2
- package/src/state/view.test.ts +4 -4
- package/src/styles.less +4 -2
- package/src/theme/Interstellar.stories.tsx +8 -9
- package/src/theme/base.less +3 -20
- package/src/theme/interstellar.test.ts +6 -3
- package/src/theme/interstellar.theme.json +0 -56
- package/src/theme/interstellar.ts +2 -2
- package/src/trial/Trial.canvas.test.tsx +9 -5
- package/src/trial/Trial.config.test.tsx +1 -1
- package/src/trial/Trial.tsx +30 -8
- package/dist/_dts/index-BNdz-tNd.d.ts +0 -423
- package/dist/chunk-7PFH3CNM.js.map +0 -1
- package/dist/chunk-CEIUBPPW.js.map +0 -1
- package/dist/chunk-EH7UEQV7.js +0 -590
- package/dist/chunk-EH7UEQV7.js.map +0 -1
- package/dist/chunk-EHGVROVV.js.map +0 -1
- package/dist/chunk-IHUVQ3TX.js.map +0 -1
- package/dist/chunk-MDVTK5U3.js +0 -170
- package/dist/chunk-MDVTK5U3.js.map +0 -1
- package/dist/chunk-PJ7WEQBJ.js +0 -18
- package/dist/chunk-PJ7WEQBJ.js.map +0 -1
- package/dist/chunk-T3EC2DXD.js +0 -12628
- package/dist/chunk-T3EC2DXD.js.map +0 -1
- package/dist/chunk-UN4U4P63.js.map +0 -1
- package/dist/chunk-ZDHY47EV.js.map +0 -1
- package/dist/ui/layers/index.d.ts +0 -66
- package/dist/ui/layers/index.js +0 -3
- package/dist/ui/layers/index.js.map +0 -1
- package/src/canvas/useOrbit.test.ts +0 -167
- package/src/canvas/useOrbit.ts +0 -156
- package/src/lab/useSystemMode.ts +0 -30
- package/src/layers/LayerList.less +0 -93
- package/src/layers/LayerList.stories.tsx +0 -66
- package/src/layers/LayerList.test.tsx +0 -232
- package/src/layers/LayerList.tsx +0 -268
- package/src/primitives/Sidebar.less +0 -112
- package/src/primitives/Sidebar.stories.tsx +0 -38
- package/src/primitives/Sidebar.test.tsx +0 -74
- package/src/primitives/Sidebar.tsx +0 -35
- package/src/ui/layers/index.ts +0 -5
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/canvas/CameraWheelContext.ts","../src/state/view.ts","../src/canvas/useLayerScheduler.ts","../src/canvas/usePanZoom.ts","../src/canvas/CanvasStack.tsx","../src/canvas/Stage.tsx","../src/canvas/useOrbit.ts"],"names":["useRef","useEffect","useContext","jsxs","jsx","DRAG_THRESHOLD","useCallback","openPointerSession"],"mappings":"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","file":"chunk-CEIUBPPW.js","sourcesContent":["import { createContext } from 'react';\n\n/** Where a trial's camera takes a wheel event from outside its own element. */\nexport type CameraWheelSlot = { current: ((e: WheelEvent) => void) | null };\n\n/**\n * The trial's camera, for input that lands outside it. An annotation target's\n * input box is portalled into the surface container, so a wheel over a mark\n * never bubbles through the stage or canvas stack it sits on; the box hands\n * the event here instead.\n */\nexport const CameraWheelContext = createContext<CameraWheelSlot | null>(null);\n","import { normalizeZoom } from '@weasel-js/core';\nimport type { ViewTransform } from '../instrument/types';\n\n/** The 2D view labkit has always shipped, and what a trial gets when it names no\n * other. Re-exported under its own name so a consumer can say which it means. */\nexport type ViewTransform2D = ViewTransform;\n\nexport const DEFAULT_VIEW: ViewTransform2D = { zoom: 1, pan: { x: 0, y: 0 } };\n\n/** A trial's view is opaque to labkit, so anything that needs the 2D shape — the\n * zoom chrome, `CanvasStack` — asks for it and handles not getting it. */\nexport function as2DView(view: unknown): ViewTransform2D | null {\n if (typeof view !== 'object' || view === null) return null;\n const v = view as Partial<ViewTransform2D>;\n if (typeof v.zoom !== 'number') return null;\n if (typeof v.pan !== 'object' || v.pan === null) return null;\n if (typeof v.pan.x !== 'number' || typeof v.pan.y !== 'number') return null;\n return normalize2DView({ zoom: v.zoom, pan: { x: v.pan.x, y: v.pan.y } });\n}\n\n/** `view` inside the invariant every view holds: a zoom that is not a finite\n * number of at least `ZOOM_FLOOR` becomes the floor, and a non-finite pan\n * becomes 0. Returns `view` itself when it already holds. */\nexport function normalize2DView(view: ViewTransform2D): ViewTransform2D {\n const zoom = normalizeZoom(view.zoom);\n const x = Number.isFinite(view.pan.x) ? view.pan.x : 0;\n const y = Number.isFinite(view.pan.y) ? view.pan.y : 0;\n if (zoom === view.zoom && x === view.pan.x && y === view.pan.y) return view;\n return { zoom, pan: { x, y } };\n}\n\n/** `view` at a new zoom, through the same rule. */\nexport function withZoom(view: ViewTransform2D, zoom: number): ViewTransform2D {\n return normalize2DView({ zoom, pan: view.pan });\n}\n","import { useVisibleRaf } from '@weasel-js/core';\nimport { type RefObject, useEffect, useRef } from 'react';\nimport type { ViewTransform } from '../instrument/types';\nimport { DEFAULT_FRAME, type WorldFrame } from './worldSpec';\n\n/** One layer of a canvas stack: its id, whether it is currently shown, and how\n * it paints itself. */\nexport interface CanvasLayerDescriptor {\n id: string;\n visible: boolean;\n render: (ctx: CanvasRenderingContext2D, view: ViewTransform, frame: WorldFrame) => void;\n}\n\ninterface SchedulerOptions {\n layers: CanvasLayerDescriptor[];\n view: ViewTransform;\n /** The instrument's coordinate system, resolved against `size`. */\n frame?: WorldFrame;\n canvasRefs: RefObject<Map<string, HTMLCanvasElement>>;\n size: { width: number; height: number; dpr: number };\n /** The element the stack occupies. Given one, the scheduler also stops while\n * the stack sits outside the viewport. */\n host?: RefObject<Element | null>;\n}\n\nexport function useLayerScheduler({\n layers,\n view,\n frame = DEFAULT_FRAME,\n canvasRefs,\n size,\n host,\n}: SchedulerOptions): void {\n const dirty = useRef<Set<string>>(new Set());\n const lastRenderRef = useRef<Map<string, CanvasLayerDescriptor['render']>>(new Map());\n\n useEffect(() => {\n for (const layer of layers) {\n const prev = lastRenderRef.current.get(layer.id);\n if (prev !== layer.render) dirty.current.add(layer.id);\n lastRenderRef.current.set(layer.id, layer.render);\n }\n for (const id of [...lastRenderRef.current.keys()]) {\n if (!layers.find((l) => l.id === id)) lastRenderRef.current.delete(id);\n }\n }, [layers]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: re-mark dirty when view or size changes\n useEffect(() => {\n for (const layer of layers) dirty.current.add(layer.id);\n }, [view, frame, size, layers]);\n\n // Painting only what is dirty is not the same as doing nothing: a hidden tab\n // still commits React updates, and the effect above marks every layer dirty\n // on any view or size change. The gate is what actually stops the work.\n const frameLoop = useVisibleRaf(\n () => {\n if (dirty.current.size === 0) return;\n const map = canvasRefs.current;\n if (!map) {\n dirty.current.clear();\n return;\n }\n for (const layer of layers) {\n if (!dirty.current.has(layer.id)) continue;\n if (!layer.visible) continue;\n const canvas = map.get(layer.id);\n if (!canvas) continue;\n const ctx = canvas.getContext('2d');\n if (!ctx) continue;\n ctx.save();\n ctx.setTransform(size.dpr, 0, 0, size.dpr, 0, 0);\n ctx.clearRect(0, 0, size.width, size.height);\n layer.render(ctx, view, frame);\n ctx.restore();\n }\n dirty.current.clear();\n },\n { target: host },\n );\n\n useEffect(() => {\n if (dirty.current.size > 0) frameLoop.request();\n });\n}\n","import { openPointerSession, type PointerSession } from '@weasel-js/core';\nimport {\n type PointerEvent as ReactPointerEvent,\n useCallback,\n useEffect,\n useRef,\n type WheelEvent,\n} from 'react';\nimport type { ViewTransform } from '../instrument/types';\nimport { normalize2DView } from '../state/view';\nimport { zoomAt } from './camera';\nimport { DEFAULT_FRAME, type WorldFrame } from './worldSpec';\n\nexport interface UsePanZoomOptions {\n view: ViewTransform;\n onViewChange: (v: ViewTransform) => void;\n /** The opening `view.zoom` always stays reachable, widening these past\n * whatever is passed here if it would otherwise exclude it. */\n minZoom?: number;\n maxZoom?: number;\n /** The instrument's coordinate system, resolved against the viewport. The\n * wheel anchors in this frame; omitting it anchors at the element's\n * top-left, which is what labkit did before a frame could be declared. */\n frame?: WorldFrame;\n /** A primary-button press released without ever crossing the drag\n * threshold. The pointer session owns the release, so the gesture's end is\n * reported here rather than left for a consumer's own `onPointerUp`. */\n onTap?: (e: PointerEvent) => void;\n}\n\nexport interface PanZoomHandlers {\n /** Zoom about the pointer. `anchor` is the element the pointer position is\n * measured against, for an event whose `currentTarget` is some other box. */\n onWheel: (e: WheelEvent<HTMLElement> | globalThis.WheelEvent, anchor?: Element) => void;\n onPointerDown: (e: ReactPointerEvent<HTMLElement>) => void;\n isDragging: () => boolean;\n}\n\ninterface DragState {\n startScreenX: number;\n startScreenY: number;\n startPan: { x: number; y: number };\n moved: boolean;\n}\n\nconst DRAG_THRESHOLD = 3;\n\nfunction isPositiveFinite(n: number): boolean {\n return Number.isFinite(n) && n > 0;\n}\n\nexport function usePanZoom({\n view,\n onViewChange,\n minZoom = 0.1,\n maxZoom = 32,\n frame = DEFAULT_FRAME,\n onTap,\n}: UsePanZoomOptions): PanZoomHandlers {\n const dragRef = useRef<DragState | null>(null);\n const sessionRef = useRef<PointerSession | null>(null);\n const viewRef = useRef(normalize2DView(view));\n viewRef.current = normalize2DView(view);\n const onViewChangeRef = useRef(onViewChange);\n onViewChangeRef.current = onViewChange;\n const onTapRef = useRef(onTap);\n onTapRef.current = onTap;\n // Captured once, from the view the canvas opened at — not the current view,\n // which would let a prior zoom-out shrink the range and trap the opening\n // view unreachable behind it.\n const initialZoomRef = useRef(isPositiveFinite(view.zoom) ? view.zoom : null);\n\n // Written ahead of the render so a second event inside one commit steps\n // from this one; the render-time assignment above still lets the prop win.\n const commit = useCallback((next: ViewTransform) => {\n viewRef.current = normalize2DView(next);\n onViewChangeRef.current(next);\n }, []);\n\n const onWheel = useCallback(\n (e: WheelEvent<HTMLElement> | globalThis.WheelEvent, anchor?: Element) => {\n const el = anchor ?? (e.currentTarget as Element | null);\n if (!el) return;\n e.preventDefault();\n const rect = el.getBoundingClientRect();\n const initialZoom = initialZoomRef.current;\n commit(\n zoomAt(\n viewRef.current,\n Math.exp(-e.deltaY * 0.001),\n { x: e.clientX - rect.left, y: e.clientY - rect.top },\n {\n frame,\n min: initialZoom == null ? minZoom : Math.min(minZoom, initialZoom),\n max: initialZoom == null ? maxZoom : Math.max(maxZoom, initialZoom),\n },\n ),\n );\n },\n [commit, minZoom, maxZoom, frame],\n );\n\n const clearDrag = useCallback(() => {\n dragRef.current = null;\n sessionRef.current = null;\n }, []);\n\n const onPointerDown = useCallback(\n (e: ReactPointerEvent<HTMLElement>) => {\n if (e.button !== 0) return;\n const drag: DragState = {\n startScreenX: e.clientX,\n startScreenY: e.clientY,\n startPan: { ...viewRef.current.pan },\n moved: false,\n };\n dragRef.current = drag;\n sessionRef.current = openPointerSession(e.currentTarget, e, {\n onMove: (ev) => {\n const dx = ev.clientX - drag.startScreenX;\n const dy = ev.clientY - drag.startScreenY;\n if (!drag.moved && Math.hypot(dx, dy) < DRAG_THRESHOLD) return;\n drag.moved = true;\n commit({\n zoom: viewRef.current.zoom,\n pan: { x: drag.startPan.x + dx, y: drag.startPan.y + dy },\n });\n },\n onEnd: (ev) => {\n const tapped = !drag.moved;\n clearDrag();\n if (tapped) onTapRef.current?.(ev);\n },\n // A cancelled pan keeps whatever it had already applied: every move\n // was committed as it arrived, so there is nothing left to undo.\n onCancel: clearDrag,\n });\n },\n [clearDrag, commit],\n );\n\n useEffect(() => () => sessionRef.current?.cancel(), []);\n\n const isDragging = useCallback(() => dragRef.current?.moved === true, []);\n\n return { onWheel, onPointerDown, isDragging };\n}\n","import {\n type CSSProperties,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { Point, ViewTransform } from '../instrument/types';\nimport { normalize2DView } from '../state/view';\nimport { CameraWheelContext } from './CameraWheelContext';\nimport { CanvasStackContext } from './CanvasStackContext';\nimport { screenToWorld } from './canvasCoords';\nimport { type CanvasLayerDescriptor, useLayerScheduler } from './useLayerScheduler';\nimport { usePanZoom } from './usePanZoom';\nimport { resolveFrame, type ViewportSize, type WorldSpec } from './worldSpec';\n\n/** Props for `<CanvasStack>`. */\nexport interface CanvasStackProps {\n layers: CanvasLayerDescriptor[];\n view: ViewTransform;\n onViewChange: (v: ViewTransform) => void;\n /** The instrument's coordinate system. Omitted, world (0,0) sits at the\n * element's top-left with y running down. */\n worldSpec?: WorldSpec;\n minZoom?: number;\n maxZoom?: number;\n width?: number | string;\n height?: number | string;\n className?: string;\n /** Fired whenever the stack is measured, so a consumer can place a view that\n * only makes sense in terms of the viewport. */\n onResize?: (size: ViewportSize) => void;\n onHitTest?: (worldPos: Point) => void;\n children?: ReactNode;\n}\n\n/** Stacks one `<canvas>` per layer and drives them from a shared view, so a\n * layer that changes rarely is not redrawn with one that changes every frame.\n * Handles sizing, device pixel ratio, and pan/zoom. */\nexport function CanvasStack({\n layers,\n view: viewProp,\n onViewChange,\n worldSpec,\n minZoom,\n maxZoom,\n width = '100%',\n height = '100%',\n className,\n onResize,\n onHitTest,\n children,\n}: CanvasStackProps) {\n const view = normalize2DView(viewProp);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const canvasMap = useRef<Map<string, HTMLCanvasElement>>(new Map());\n const [size, setSize] = useState({ width: 0, height: 0, dpr: 1 });\n\n const setCanvasRef = (id: string, el: HTMLCanvasElement | null): void => {\n if (el) canvasMap.current.set(id, el);\n else canvasMap.current.delete(id);\n };\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const update = () => {\n const rect = el.getBoundingClientRect();\n const dpr = window.devicePixelRatio ?? 1;\n setSize((prev) => {\n if (prev.width === rect.width && prev.height === rect.height && prev.dpr === dpr) {\n return prev;\n }\n return { width: rect.width, height: rect.height, dpr };\n });\n };\n update();\n if (typeof ResizeObserver === 'undefined') return;\n const ro = new ResizeObserver(update);\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n const onResizeRef = useRef(onResize);\n onResizeRef.current = onResize;\n useEffect(() => {\n if (size.width === 0 && size.height === 0) return;\n onResizeRef.current?.({ width: size.width, height: size.height });\n }, [size.width, size.height]);\n\n const frame = useMemo(() => resolveFrame(worldSpec, size), [worldSpec, size]);\n\n const onTap = (e: PointerEvent) => {\n const el = containerRef.current;\n if (!onHitTest || !el) return;\n const rect = el.getBoundingClientRect();\n onHitTest(screenToWorld({ x: e.clientX - rect.left, y: e.clientY - rect.top }, view, frame));\n };\n\n const handlers = usePanZoom({ view: viewProp, onViewChange, minZoom, maxZoom, frame, onTap });\n const onWheelRef = useRef(handlers.onWheel);\n onWheelRef.current = handlers.onWheel;\n const wheelSlot = useContext(CameraWheelContext);\n\n // Bound by hand because React registers wheel listeners passive, where\n // `preventDefault` is refused and the page scrolls under the zoom.\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const wheel = (e: WheelEvent): void => onWheelRef.current(e, el);\n el.addEventListener('wheel', wheel, { passive: false });\n if (wheelSlot) wheelSlot.current = wheel;\n return () => {\n el.removeEventListener('wheel', wheel);\n if (wheelSlot?.current === wheel) wheelSlot.current = null;\n };\n }, [wheelSlot]);\n useLayerScheduler({ layers, view, frame, canvasRefs: canvasMap, size, host: containerRef });\n\n const ctxValue = useMemo(\n () => ({\n view,\n frame,\n surface: { element: containerRef, size, canvases: canvasMap, layers },\n }),\n [view, frame, size, layers],\n );\n\n const containerStyle: CSSProperties = { width, height };\n const canvasPx = {\n width: Math.max(0, Math.round(size.width * size.dpr)),\n height: Math.max(0, Math.round(size.height * size.dpr)),\n };\n const canvasCss: CSSProperties = {\n width: size.width,\n height: size.height,\n };\n\n return (\n <CanvasStackContext.Provider value={ctxValue}>\n <div\n ref={containerRef}\n className={className ? `lk-canvas-stack ${className}` : 'lk-canvas-stack'}\n style={containerStyle}\n onPointerDown={handlers.onPointerDown}\n >\n {layers.map((layer) => (\n <canvas\n key={layer.id}\n ref={(el) => setCanvasRef(layer.id, el)}\n className=\"lk-canvas-stack__canvas\"\n width={canvasPx.width}\n height={canvasPx.height}\n style={{ ...canvasCss, display: layer.visible ? 'block' : 'none' }}\n />\n ))}\n <div className=\"lk-canvas-stack__overlay\">{children}</div>\n </div>\n </CanvasStackContext.Provider>\n );\n}\n","import { type CSSProperties, type ReactNode, useContext, useEffect, useRef } from 'react';\nimport type { ViewTransform } from '../instrument/types';\nimport { normalize2DView } from '../state/view';\nimport { useSurfaceOptional } from '../surface/useSurfaceTile';\nimport { CameraWheelContext } from './CameraWheelContext';\nimport { usePanZoom } from './usePanZoom';\nimport type { ViewportSize } from './worldSpec';\n\n/** Props for `<Stage>`. */\nexport interface StageProps {\n /** The content's own size in CSS pixels, at zoom 1. */\n size: ViewportSize;\n view: ViewTransform;\n onViewChange: (v: ViewTransform) => void;\n minZoom?: number;\n maxZoom?: number;\n /** Fired whenever the stage's viewport is measured at a non-zero size. */\n onResize?: (viewport: ViewportSize) => void;\n /** Handed the viewport element, for a consumer tracking the pointer over it. */\n hostRef?: { current: HTMLDivElement | null };\n /** Drawn over the content in viewport pixels, outside the camera. */\n overlay?: ReactNode;\n children?: ReactNode;\n}\n\n/**\n * The camera a stage opens at: the content centered in its viewport, shrunk to\n * fit if it has to be and never enlarged past its own size.\n */\nexport function fitStage(size: ViewportSize, viewport: ViewportSize): ViewTransform {\n if (!(size.width > 0 && size.height > 0 && viewport.width > 0 && viewport.height > 0)) {\n return { zoom: 1, pan: { x: 0, y: 0 } };\n }\n const zoom = Math.min(1, viewport.width / size.width, viewport.height / size.height);\n return {\n zoom,\n pan: {\n x: (viewport.width - size.width * zoom) / 2,\n y: (viewport.height - size.height * zoom) / 2,\n },\n };\n}\n\n/**\n * DOM content of a fixed size, panned and zoomed by a camera — what\n * `<CanvasStack>` is for layers drawn to a canvas. The content is laid out at\n * its own size and transformed, so everything inside keeps its layout and a\n * measurement of any element in it reports where it is actually drawn.\n */\nexport function Stage({\n size,\n view: viewProp,\n onViewChange,\n minZoom,\n maxZoom,\n onResize,\n hostRef,\n overlay,\n children,\n}: StageProps) {\n const view = normalize2DView(viewProp);\n const host = useRef<HTMLDivElement | null>(null);\n const surface = useSurfaceOptional();\n const handlers = usePanZoom({ view: viewProp, onViewChange, minZoom, maxZoom });\n const onWheelRef = useRef(handlers.onWheel);\n onWheelRef.current = handlers.onWheel;\n const wheelSlot = useContext(CameraWheelContext);\n\n // Bound by hand because React registers wheel listeners passive, where\n // `preventDefault` is refused and the page scrolls under the zoom.\n useEffect(() => {\n const el = host.current;\n if (!el) return;\n const wheel = (e: WheelEvent): void => onWheelRef.current(e, el);\n el.addEventListener('wheel', wheel, { passive: false });\n if (wheelSlot) wheelSlot.current = wheel;\n return () => {\n el.removeEventListener('wheel', wheel);\n if (wheelSlot?.current === wheel) wheelSlot.current = null;\n };\n }, [wheelSlot]);\n\n const onResizeRef = useRef(onResize);\n onResizeRef.current = onResize;\n useEffect(() => {\n const el = host.current;\n if (!el) return;\n const measure = () => {\n const rect = el.getBoundingClientRect();\n if (rect.width > 0 && rect.height > 0) {\n onResizeRef.current?.({ width: rect.width, height: rect.height });\n }\n };\n measure();\n if (typeof ResizeObserver === 'undefined') return;\n const ro = new ResizeObserver(measure);\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n // A transform moves every tile inside the content without resizing anything,\n // and a ResizeObserver reports only resizes.\n // biome-ignore lint/correctness/useExhaustiveDependencies: the camera is the trigger, not an input — the effect re-measures whenever it moves.\n useEffect(() => {\n surface?.invalidateRects();\n }, [surface, view.zoom, view.pan.x, view.pan.y]);\n\n // The camera changes every frame of a pan, and a transform has nowhere to\n // live but the element's own style: set as custom properties the stylesheet\n // reads.\n const camera = {\n ['--lk-stage-x' as string]: `${view.pan.x}px`,\n ['--lk-stage-y' as string]: `${view.pan.y}px`,\n ['--lk-stage-zoom' as string]: String(view.zoom),\n ['--lk-stage-w' as string]: `${size.width}px`,\n ['--lk-stage-h' as string]: `${size.height}px`,\n } as CSSProperties;\n\n return (\n <div\n ref={(el) => {\n host.current = el;\n if (hostRef) hostRef.current = el;\n }}\n className=\"lk-stage\"\n onPointerDown={handlers.onPointerDown}\n >\n <div className=\"lk-stage__content\" style={camera}>\n {children}\n </div>\n {overlay}\n </div>\n );\n}\n","import { openPointerSession, type PointerSession } from '@weasel-js/core';\nimport {\n type PointerEvent as ReactPointerEvent,\n useCallback,\n useEffect,\n useRef,\n type WheelEvent,\n} from 'react';\n\n/** A point in the space the instrument works in. */\nexport interface Vec3 {\n x: number;\n y: number;\n z: number;\n}\n\n/** An orbit camera as a trial view: where it looks from, and what it looks at.\n * labkit does not turn this into a matrix — the host's renderer does. */\nexport interface OrbitView {\n yaw: number;\n pitch: number;\n distance: number;\n target: Vec3;\n}\n\n/** Just short of the pole. At exactly ±PI/2 the azimuth is undefined and the\n * camera rolls, which reads as the model jumping rather than as a limit. */\nexport const PITCH_LIMIT = Math.PI / 2 - 0.01;\n\nconst YAW_PER_PX = 0.008;\nconst PITCH_PER_PX = 0.008;\nconst DISTANCE_PER_NOTCH = 0.0015;\nconst DRAG_THRESHOLD = 3;\n\nexport function clampPitch(pitch: number): number {\n return Math.min(PITCH_LIMIT, Math.max(-PITCH_LIMIT, pitch));\n}\n\nexport function wrapYaw(yaw: number): number {\n const wrapped = ((((yaw + Math.PI) % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI)) - Math.PI;\n return wrapped === -Math.PI ? Math.PI : wrapped;\n}\n\n/** The view a drag of (dx, dy) from `start` produces. Absolute against the drag\n * start, so it can be re-applied any number of times without compounding. */\nexport function orbitAfterDrag(start: OrbitView, dx: number, dy: number): OrbitView {\n return {\n ...start,\n yaw: wrapYaw(start.yaw + dx * YAW_PER_PX),\n pitch: clampPitch(start.pitch + dy * PITCH_PER_PX),\n };\n}\n\n/** Multiplicative, so one notch covers the same proportion of the distance\n * whether the camera is near or far. */\nexport function orbitAfterWheel(\n view: OrbitView,\n deltaY: number,\n minDistance: number,\n maxDistance: number,\n): OrbitView {\n const factor = Math.exp(deltaY * DISTANCE_PER_NOTCH);\n return {\n ...view,\n distance: Math.min(maxDistance, Math.max(minDistance, view.distance * factor)),\n };\n}\n\nexport interface UseOrbitOptions {\n view: OrbitView;\n onViewChange: (v: OrbitView) => void;\n /** Restored on double-click. Defaults to the view the hook first saw. */\n home?: OrbitView;\n minDistance?: number;\n maxDistance?: number;\n}\n\nexport interface OrbitHandlers {\n onWheel: (e: WheelEvent<HTMLElement>) => void;\n onPointerDown: (e: ReactPointerEvent<HTMLElement>) => void;\n onDoubleClick: () => void;\n isDragging: () => boolean;\n}\n\ninterface DragState {\n startX: number;\n startY: number;\n startView: OrbitView;\n moved: boolean;\n}\n\n/** Pointer gestures over an orbit view: drag to turn, wheel or pinch to dolly,\n * double-click to go home. The 3D peer of `usePanZoom`. */\nexport function useOrbit({\n view,\n onViewChange,\n home,\n minDistance = 0.1,\n maxDistance = 1000,\n}: UseOrbitOptions): OrbitHandlers {\n const dragRef = useRef<DragState | null>(null);\n const sessionRef = useRef<PointerSession | null>(null);\n const viewRef = useRef(view);\n viewRef.current = view;\n const onViewChangeRef = useRef(onViewChange);\n onViewChangeRef.current = onViewChange;\n const homeRef = useRef(home ?? view);\n if (home) homeRef.current = home;\n\n const onWheel = useCallback(\n (e: WheelEvent<HTMLElement>) => {\n e.preventDefault();\n onViewChange(orbitAfterWheel(viewRef.current, e.deltaY, minDistance, maxDistance));\n },\n [onViewChange, minDistance, maxDistance],\n );\n\n const clearDrag = useCallback(() => {\n dragRef.current = null;\n sessionRef.current = null;\n }, []);\n\n const onPointerDown = useCallback(\n (e: ReactPointerEvent<HTMLElement>) => {\n if (e.button !== 0) return;\n const drag: DragState = {\n startX: e.clientX,\n startY: e.clientY,\n startView: viewRef.current,\n moved: false,\n };\n dragRef.current = drag;\n sessionRef.current = openPointerSession(e.currentTarget, e, {\n onMove: (ev) => {\n const dx = ev.clientX - drag.startX;\n const dy = ev.clientY - drag.startY;\n if (!drag.moved && Math.hypot(dx, dy) < DRAG_THRESHOLD) return;\n drag.moved = true;\n onViewChangeRef.current(orbitAfterDrag(drag.startView, dx, dy));\n },\n onEnd: clearDrag,\n // A cancelled turn keeps where it got to: every move was committed as\n // it arrived, so there is nothing left to undo.\n onCancel: clearDrag,\n });\n },\n [clearDrag],\n );\n\n useEffect(() => () => sessionRef.current?.cancel(), []);\n\n const onDoubleClick = useCallback(() => onViewChange(homeRef.current), [onViewChange]);\n const isDragging = useCallback(() => dragRef.current?.moved === true, []);\n\n return { onWheel, onPointerDown, onDoubleClick, isDragging };\n}\n"]}
|
package/dist/chunk-EH7UEQV7.js
DELETED
|
@@ -1,590 +0,0 @@
|
|
|
1
|
-
import { fromConfigFields, isLeafVisible } from './chunk-PHK4W562.js';
|
|
2
|
-
import { resolveAutoConfig, schemaNodeAtPath, valueAtPath, auto } from './chunk-7PFH3CNM.js';
|
|
3
|
-
import { k, J, n3, j2, L3, U, H, z2, R2, F2, V, g, a4, e2, B } from './chunk-T3EC2DXD.js';
|
|
4
|
-
import { isBuiltinToolPref } from '@weasel-js/core';
|
|
5
|
-
import { useMemo, useState, useRef, useEffect, Fragment as Fragment$1 } from 'react';
|
|
6
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
|
-
|
|
8
|
-
var gridOf = (pack) => pack === "one-up" ? "auto-color" : "pairs";
|
|
9
|
-
function sectionRows(section, rows) {
|
|
10
|
-
return {
|
|
11
|
-
pack: section.pack ?? rows.pack,
|
|
12
|
-
layout: section.layout ?? rows.layout,
|
|
13
|
-
grid: section.pack ? gridOf(section.pack) : rows.grid
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
var NO_AUTO = /* @__PURE__ */ new Set();
|
|
17
|
-
function ControlPanel({
|
|
18
|
-
schema,
|
|
19
|
-
fields,
|
|
20
|
-
config,
|
|
21
|
-
setConfig,
|
|
22
|
-
renderers,
|
|
23
|
-
pack = "pairs",
|
|
24
|
-
layout,
|
|
25
|
-
density,
|
|
26
|
-
align,
|
|
27
|
-
collapse,
|
|
28
|
-
collapsed,
|
|
29
|
-
onCollapse,
|
|
30
|
-
auto: given,
|
|
31
|
-
showHidden = false,
|
|
32
|
-
className
|
|
33
|
-
}) {
|
|
34
|
-
const resolved = useMemo(() => schema ?? fromConfigFields(fields ?? []), [schema, fields]);
|
|
35
|
-
const [ownAuto, setOwnAuto] = useState(NO_AUTO);
|
|
36
|
-
const auto2 = given ?? ownAuto;
|
|
37
|
-
const setRowAuto = (path, next, value) => {
|
|
38
|
-
if (given) {
|
|
39
|
-
setConfig(path, next ? auto : value);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
setOwnAuto((prev) => {
|
|
43
|
-
const now = new Set(prev);
|
|
44
|
-
if (next) now.add(path);
|
|
45
|
-
else now.delete(path);
|
|
46
|
-
return now;
|
|
47
|
-
});
|
|
48
|
-
if (!next) setConfig(path, value);
|
|
49
|
-
};
|
|
50
|
-
const shown = useMemo(
|
|
51
|
-
() => auto2 && auto2.size > 0 ? resolveAutoConfig(resolved, config, auto2) : config,
|
|
52
|
-
[resolved, config, auto2]
|
|
53
|
-
);
|
|
54
|
-
const listRef = useRef(null);
|
|
55
|
-
const toggles = useRef(/* @__PURE__ */ new Map());
|
|
56
|
-
useEffect(() => {
|
|
57
|
-
const host = listRef.current;
|
|
58
|
-
if (!host) return;
|
|
59
|
-
const onDown = (e2) => {
|
|
60
|
-
if (!e2.shiftKey) return;
|
|
61
|
-
const row = e2.target?.closest("[data-auto-path]");
|
|
62
|
-
const path = row?.getAttribute("data-auto-path");
|
|
63
|
-
const toggle = path ? toggles.current.get(path) : void 0;
|
|
64
|
-
if (!toggle) return;
|
|
65
|
-
e2.preventDefault();
|
|
66
|
-
e2.stopPropagation();
|
|
67
|
-
toggle();
|
|
68
|
-
};
|
|
69
|
-
host.addEventListener("pointerdown", onDown, true);
|
|
70
|
-
return () => host.removeEventListener("pointerdown", onDown, true);
|
|
71
|
-
}, []);
|
|
72
|
-
const gridPack = gridOf(pack);
|
|
73
|
-
const folds = collapse !== void 0 || collapsed !== void 0 || onCollapse !== void 0 || resolved.sections.some((s) => s.collapsed !== void 0);
|
|
74
|
-
const startsFolded = collapse === "closed";
|
|
75
|
-
const fold = (key, declared, grid = gridPack) => ({
|
|
76
|
-
pack: grid,
|
|
77
|
-
collapsible: folds,
|
|
78
|
-
defaultCollapsed: declared ?? startsFolded,
|
|
79
|
-
collapsed: collapsed ? collapsed[key] ?? declared ?? startsFolded : void 0,
|
|
80
|
-
onCollapsedChange: onCollapse ? (next) => onCollapse(key, next) : void 0
|
|
81
|
-
});
|
|
82
|
-
const node = (path, rows) => {
|
|
83
|
-
const found = schemaNodeAtPath(resolved.group, path);
|
|
84
|
-
if (!found) return null;
|
|
85
|
-
if (!isLeafVisible(resolved, path, config, showHidden)) return null;
|
|
86
|
-
if (n3(found)) {
|
|
87
|
-
return /* @__PURE__ */ jsx(
|
|
88
|
-
ControlRow,
|
|
89
|
-
{
|
|
90
|
-
path,
|
|
91
|
-
leaf: found,
|
|
92
|
-
resolved,
|
|
93
|
-
config,
|
|
94
|
-
shown,
|
|
95
|
-
setConfig,
|
|
96
|
-
renderers,
|
|
97
|
-
pack: rows.pack,
|
|
98
|
-
layout: rows.layout,
|
|
99
|
-
auto: auto2,
|
|
100
|
-
setRowAuto,
|
|
101
|
-
toggles: toggles.current
|
|
102
|
-
},
|
|
103
|
-
path
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
if (found.name === "") return /* @__PURE__ */ jsx(Fragment$1, { children: body(found, path, rows) }, path);
|
|
107
|
-
return /* @__PURE__ */ jsx(J, { title: found.name, ...fold(path, void 0, rows.grid), children: body(found, path, rows) }, path);
|
|
108
|
-
};
|
|
109
|
-
const pairable = (path) => {
|
|
110
|
-
const found = schemaNodeAtPath(resolved.group, path);
|
|
111
|
-
if (!found || !n3(found)) return void 0;
|
|
112
|
-
const pair = extra(found, "pair");
|
|
113
|
-
if (pair === void 0) return void 0;
|
|
114
|
-
if (!isLeafVisible(resolved, path, config, showHidden))
|
|
115
|
-
return void 0;
|
|
116
|
-
if (renderers?.[path] ?? resolved.renderers[path] ?? renderers?.[found.kind]) return void 0;
|
|
117
|
-
if (!isBuiltinToolPref(found)) return void 0;
|
|
118
|
-
if (found.kind === "paint" || found.kind === "object" || isSliderLeaf(found)) return void 0;
|
|
119
|
-
return { leaf: found, pair };
|
|
120
|
-
};
|
|
121
|
-
const rowsFor = (paths, rows) => {
|
|
122
|
-
const out = [];
|
|
123
|
-
for (let i = 0; i < paths.length; ) {
|
|
124
|
-
const head = pairable(paths[i]);
|
|
125
|
-
if (!head) {
|
|
126
|
-
out.push(node(paths[i], rows));
|
|
127
|
-
i += 1;
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
const { pair } = head;
|
|
131
|
-
const cells = [{ path: paths[i], leaf: head.leaf }];
|
|
132
|
-
let j2 = i + 1;
|
|
133
|
-
for (; j2 < paths.length; j2 += 1) {
|
|
134
|
-
const next = pairable(paths[j2]);
|
|
135
|
-
if (!next || next.pair !== pair) break;
|
|
136
|
-
cells.push({ path: paths[j2], leaf: next.leaf });
|
|
137
|
-
}
|
|
138
|
-
out.push(
|
|
139
|
-
/* @__PURE__ */ jsx(
|
|
140
|
-
PairedRow,
|
|
141
|
-
{
|
|
142
|
-
label: pair,
|
|
143
|
-
cells,
|
|
144
|
-
shown,
|
|
145
|
-
setConfig,
|
|
146
|
-
layout: rows.layout
|
|
147
|
-
},
|
|
148
|
-
paths[i]
|
|
149
|
-
)
|
|
150
|
-
);
|
|
151
|
-
i = j2;
|
|
152
|
-
}
|
|
153
|
-
return out;
|
|
154
|
-
};
|
|
155
|
-
const body = (group, at, rows) => {
|
|
156
|
-
const sections = resolved.sections.filter((s) => s.at === at);
|
|
157
|
-
const sectioned = new Set(sections.flatMap((s) => s.paths));
|
|
158
|
-
const paths = Object.keys(group.children).map((key) => at === "" ? key : `${at}.${key}`);
|
|
159
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
160
|
-
rowsFor(
|
|
161
|
-
paths.filter((p) => !sectioned.has(p)),
|
|
162
|
-
rows
|
|
163
|
-
),
|
|
164
|
-
sections.map((section) => {
|
|
165
|
-
const inner = sectionRows(section, rows);
|
|
166
|
-
return /* @__PURE__ */ jsx(
|
|
167
|
-
J,
|
|
168
|
-
{
|
|
169
|
-
title: section.label,
|
|
170
|
-
...fold(sectionKey(section), section.collapsed, inner.grid),
|
|
171
|
-
children: rowsFor(section.paths, inner)
|
|
172
|
-
},
|
|
173
|
-
sectionKey(section)
|
|
174
|
-
);
|
|
175
|
-
})
|
|
176
|
-
] });
|
|
177
|
-
};
|
|
178
|
-
return /* @__PURE__ */ jsx("div", { ref: listRef, children: /* @__PURE__ */ jsx(
|
|
179
|
-
k,
|
|
180
|
-
{
|
|
181
|
-
pack: gridPack,
|
|
182
|
-
density,
|
|
183
|
-
align,
|
|
184
|
-
className: className ? `lk-control-panel ${className}` : "lk-control-panel",
|
|
185
|
-
children: body(resolved.group, "", { pack, layout, grid: gridPack })
|
|
186
|
-
}
|
|
187
|
-
) });
|
|
188
|
-
}
|
|
189
|
-
function sectionKey(section) {
|
|
190
|
-
return section.at === "" ? section.label : `${section.at}.${section.label}`;
|
|
191
|
-
}
|
|
192
|
-
function isSliderLeaf(leaf) {
|
|
193
|
-
return leaf.kind === "number" && extra(leaf, "control") === "slider" && extra(leaf, "min") !== void 0 && extra(leaf, "max") !== void 0;
|
|
194
|
-
}
|
|
195
|
-
function extra(leaf, key) {
|
|
196
|
-
return leaf[key];
|
|
197
|
-
}
|
|
198
|
-
function ControlRow({
|
|
199
|
-
path,
|
|
200
|
-
leaf,
|
|
201
|
-
resolved,
|
|
202
|
-
config,
|
|
203
|
-
shown,
|
|
204
|
-
setConfig,
|
|
205
|
-
renderers,
|
|
206
|
-
pack,
|
|
207
|
-
layout,
|
|
208
|
-
auto: auto2,
|
|
209
|
-
setRowAuto,
|
|
210
|
-
toggles
|
|
211
|
-
}) {
|
|
212
|
-
const write = (value2) => setConfig(path, value2);
|
|
213
|
-
const fallback = extra(leaf, "default");
|
|
214
|
-
const pinned = valueAtPath(config, path) ?? fallback;
|
|
215
|
-
const isAutoRow = auto2?.has(path) ?? false;
|
|
216
|
-
const canAuto = !extra(leaf, "manual");
|
|
217
|
-
const resolvedValue = isAutoRow ? valueAtPath(shown, path) : void 0;
|
|
218
|
-
const value = resolvedValue ?? pinned;
|
|
219
|
-
const setAuto = (next) => setRowAuto(path, next, value);
|
|
220
|
-
const onAutoChange = canAuto ? setAuto : void 0;
|
|
221
|
-
const readsItsOwnValue = !isSliderLeaf(leaf);
|
|
222
|
-
const readoutValue = leaf.kind === "number" && typeof resolvedValue === "number" ? numberField(leaf, resolvedValue).shown : resolvedValue;
|
|
223
|
-
const autoReadout = !isAutoRow ? void 0 : resolvedValue === void 0 || readsItsOwnValue ? "auto" : `auto \xB7 ${String(readoutValue)}`;
|
|
224
|
-
const autoProps = { auto: isAutoRow, onAutoChange, "data-auto-path": canAuto ? path : void 0 };
|
|
225
|
-
useEffect(() => {
|
|
226
|
-
if (!canAuto) return;
|
|
227
|
-
toggles.set(path, () => setAuto(!isAutoRow));
|
|
228
|
-
return () => {
|
|
229
|
-
toggles.delete(path);
|
|
230
|
-
};
|
|
231
|
-
});
|
|
232
|
-
const custom = renderers?.[path] ?? resolved.renderers[path] ?? renderers?.[leaf.kind];
|
|
233
|
-
if (custom) return custom({ path, pref: leaf, value, setValue: write, auto: isAutoRow, setAuto });
|
|
234
|
-
const label = leaf.name;
|
|
235
|
-
const description = leaf.description;
|
|
236
|
-
const read = () => value;
|
|
237
|
-
const wide = pack === "auto";
|
|
238
|
-
if (!isBuiltinToolPref(leaf))
|
|
239
|
-
return /* @__PURE__ */ jsx(UnwiredRow, { label, kind: leaf.kind, description });
|
|
240
|
-
switch (leaf.kind) {
|
|
241
|
-
case "number": {
|
|
242
|
-
const field = numberField(leaf, read());
|
|
243
|
-
const suffix = extra(leaf, "suffix") ?? field.unit?.suffix;
|
|
244
|
-
const notation = extra(leaf, "format");
|
|
245
|
-
if (isSliderLeaf(leaf)) {
|
|
246
|
-
return /* @__PURE__ */ jsx(
|
|
247
|
-
F2,
|
|
248
|
-
{
|
|
249
|
-
label,
|
|
250
|
-
value: field.shown,
|
|
251
|
-
min: field.min,
|
|
252
|
-
max: field.max,
|
|
253
|
-
step: field.step,
|
|
254
|
-
notation,
|
|
255
|
-
unit: suffix,
|
|
256
|
-
onChange: (n2) => write(field.store(n2)),
|
|
257
|
-
readout: autoReadout,
|
|
258
|
-
layout,
|
|
259
|
-
span: wide,
|
|
260
|
-
description,
|
|
261
|
-
...autoProps
|
|
262
|
-
}
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
return /* @__PURE__ */ jsx(
|
|
266
|
-
V,
|
|
267
|
-
{
|
|
268
|
-
label,
|
|
269
|
-
value: field.shown,
|
|
270
|
-
min: field.min,
|
|
271
|
-
max: field.max,
|
|
272
|
-
step: field.step,
|
|
273
|
-
unit: suffix,
|
|
274
|
-
onChange: (n2) => write(field.store(n2)),
|
|
275
|
-
readout: autoReadout,
|
|
276
|
-
layout,
|
|
277
|
-
description,
|
|
278
|
-
...autoProps
|
|
279
|
-
}
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
case "boolean": {
|
|
283
|
-
const Row = extra(leaf, "control") === "switch" ? z2 : R2;
|
|
284
|
-
return /* @__PURE__ */ jsx(
|
|
285
|
-
Row,
|
|
286
|
-
{
|
|
287
|
-
label,
|
|
288
|
-
value: read(),
|
|
289
|
-
onChange: write,
|
|
290
|
-
readout: autoReadout,
|
|
291
|
-
layout,
|
|
292
|
-
description,
|
|
293
|
-
...autoProps
|
|
294
|
-
}
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
case "enum": {
|
|
298
|
-
const options = extra(leaf, "options") ?? [];
|
|
299
|
-
const segmented = extra(leaf, "control") === "radio";
|
|
300
|
-
const Row = segmented ? U : H;
|
|
301
|
-
return /* @__PURE__ */ jsx(
|
|
302
|
-
Row,
|
|
303
|
-
{
|
|
304
|
-
label,
|
|
305
|
-
value: read(),
|
|
306
|
-
options,
|
|
307
|
-
onChange: write,
|
|
308
|
-
readout: autoReadout,
|
|
309
|
-
layout,
|
|
310
|
-
span: segmented && wide,
|
|
311
|
-
description,
|
|
312
|
-
...autoProps
|
|
313
|
-
}
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
case "string":
|
|
317
|
-
return /* @__PURE__ */ jsx(
|
|
318
|
-
DebouncedTextRow,
|
|
319
|
-
{
|
|
320
|
-
leaf,
|
|
321
|
-
label,
|
|
322
|
-
value: read(),
|
|
323
|
-
write,
|
|
324
|
-
readout: autoReadout,
|
|
325
|
-
layout,
|
|
326
|
-
span: wide,
|
|
327
|
-
description,
|
|
328
|
-
...autoProps
|
|
329
|
-
}
|
|
330
|
-
);
|
|
331
|
-
case "color": {
|
|
332
|
-
const common = {
|
|
333
|
-
label,
|
|
334
|
-
readout: autoReadout,
|
|
335
|
-
layout,
|
|
336
|
-
description,
|
|
337
|
-
...autoProps
|
|
338
|
-
};
|
|
339
|
-
if (extra(leaf, "alpha") !== true)
|
|
340
|
-
return /* @__PURE__ */ jsx(L3, { ...common, value: read(), onChange: write });
|
|
341
|
-
const { rgb, alpha } = splitHexAlpha(read());
|
|
342
|
-
return /* @__PURE__ */ jsx(
|
|
343
|
-
L3,
|
|
344
|
-
{
|
|
345
|
-
...common,
|
|
346
|
-
value: rgb,
|
|
347
|
-
onChange: (next) => write(joinHexAlpha(next, alpha)),
|
|
348
|
-
alpha,
|
|
349
|
-
onAlphaChange: (next) => write(joinHexAlpha(rgb, next))
|
|
350
|
-
}
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
case "paint":
|
|
354
|
-
case "object":
|
|
355
|
-
return /* @__PURE__ */ jsx(UnwiredRow, { label, kind: leaf.kind, description });
|
|
356
|
-
default: {
|
|
357
|
-
const _exhaustive = leaf;
|
|
358
|
-
throw new Error(
|
|
359
|
-
`ControlPanel: no control for built-in pref kind "${_exhaustive.kind}"`
|
|
360
|
-
);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
function UnwiredRow({
|
|
365
|
-
label,
|
|
366
|
-
kind,
|
|
367
|
-
description
|
|
368
|
-
}) {
|
|
369
|
-
return /* @__PURE__ */ jsx(j2, { label, description, children: /* @__PURE__ */ jsxs("span", { className: "lk-control-panel__unknown", children: [
|
|
370
|
-
"no control for \u201C",
|
|
371
|
-
kind,
|
|
372
|
-
"\u201D"
|
|
373
|
-
] }) });
|
|
374
|
-
}
|
|
375
|
-
function DebouncedTextRow({
|
|
376
|
-
leaf,
|
|
377
|
-
label,
|
|
378
|
-
value,
|
|
379
|
-
write,
|
|
380
|
-
layout,
|
|
381
|
-
span,
|
|
382
|
-
description,
|
|
383
|
-
readout,
|
|
384
|
-
auto: auto2,
|
|
385
|
-
onAutoChange,
|
|
386
|
-
"data-auto-path": autoPath
|
|
387
|
-
}) {
|
|
388
|
-
const text = useDebouncedText(
|
|
389
|
-
value,
|
|
390
|
-
write,
|
|
391
|
-
extra(leaf, "debounceMs") ?? 150
|
|
392
|
-
);
|
|
393
|
-
return /* @__PURE__ */ jsx(
|
|
394
|
-
B,
|
|
395
|
-
{
|
|
396
|
-
label,
|
|
397
|
-
readout,
|
|
398
|
-
layout,
|
|
399
|
-
span,
|
|
400
|
-
description,
|
|
401
|
-
auto: auto2,
|
|
402
|
-
onAutoChange,
|
|
403
|
-
"data-auto-path": autoPath,
|
|
404
|
-
value: text.local,
|
|
405
|
-
placeholder: extra(leaf, "placeholder"),
|
|
406
|
-
maxLength: extra(leaf, "maxLength"),
|
|
407
|
-
onChange: text.type
|
|
408
|
-
}
|
|
409
|
-
);
|
|
410
|
-
}
|
|
411
|
-
function numberField(leaf, value) {
|
|
412
|
-
const unit = extra(leaf, "unit");
|
|
413
|
-
const bounds = unit ? e2(leaf) : {
|
|
414
|
-
min: extra(leaf, "min"),
|
|
415
|
-
max: extra(leaf, "max"),
|
|
416
|
-
step: extra(leaf, "step")
|
|
417
|
-
};
|
|
418
|
-
const lo = bounds.min ?? Number.NEGATIVE_INFINITY;
|
|
419
|
-
const hi = bounds.max ?? Number.POSITIVE_INFINITY;
|
|
420
|
-
return {
|
|
421
|
-
unit,
|
|
422
|
-
min: bounds.min,
|
|
423
|
-
max: bounds.max,
|
|
424
|
-
step: bounds.step,
|
|
425
|
-
shown: unit ? unit.toDisplay(value) : value,
|
|
426
|
-
store: (shown) => {
|
|
427
|
-
const clamped = Math.min(hi, Math.max(lo, shown));
|
|
428
|
-
return unit ? unit.fromDisplay(clamped) : clamped;
|
|
429
|
-
}
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
function splitHexAlpha(value) {
|
|
433
|
-
const digits = /^#([0-9a-f]{3,8})$/i.exec(value?.trim() ?? "")?.[1];
|
|
434
|
-
const twice = (s) => s.split("").map((c) => c + c).join("");
|
|
435
|
-
const byte = (s) => Number.parseInt(s, 16) / 255;
|
|
436
|
-
switch (digits?.length) {
|
|
437
|
-
case 3:
|
|
438
|
-
return { rgb: `#${twice(digits)}`, alpha: 1 };
|
|
439
|
-
case 4:
|
|
440
|
-
return { rgb: `#${twice(digits.slice(0, 3))}`, alpha: byte(twice(digits.slice(3))) };
|
|
441
|
-
case 6:
|
|
442
|
-
return { rgb: `#${digits}`, alpha: 1 };
|
|
443
|
-
case 8:
|
|
444
|
-
return { rgb: `#${digits.slice(0, 6)}`, alpha: byte(digits.slice(6)) };
|
|
445
|
-
default:
|
|
446
|
-
return { rgb: "#000000", alpha: 1 };
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
function joinHexAlpha(rgb, alpha) {
|
|
450
|
-
const byte = Math.max(0, Math.min(255, Math.round(alpha * 255)));
|
|
451
|
-
return `${rgb}${byte.toString(16).padStart(2, "0")}`;
|
|
452
|
-
}
|
|
453
|
-
function PairedRow({
|
|
454
|
-
label,
|
|
455
|
-
cells,
|
|
456
|
-
shown,
|
|
457
|
-
setConfig,
|
|
458
|
-
layout
|
|
459
|
-
}) {
|
|
460
|
-
return /* @__PURE__ */ jsx(j2, { group: true, label, layout, children: cells.map(({ path, leaf }) => /* @__PURE__ */ jsx(
|
|
461
|
-
PairCell,
|
|
462
|
-
{
|
|
463
|
-
leaf,
|
|
464
|
-
value: valueAtPath(shown, path) ?? extra(leaf, "default"),
|
|
465
|
-
write: (value) => setConfig(path, value)
|
|
466
|
-
},
|
|
467
|
-
path
|
|
468
|
-
)) });
|
|
469
|
-
}
|
|
470
|
-
function PairCell({
|
|
471
|
-
leaf,
|
|
472
|
-
value,
|
|
473
|
-
write
|
|
474
|
-
}) {
|
|
475
|
-
const name = leaf.name;
|
|
476
|
-
const title = leaf.description;
|
|
477
|
-
const text = useDebouncedText(
|
|
478
|
-
typeof value === "string" ? value : "",
|
|
479
|
-
write,
|
|
480
|
-
extra(leaf, "debounceMs") ?? 150
|
|
481
|
-
);
|
|
482
|
-
switch (leaf.kind) {
|
|
483
|
-
case "number": {
|
|
484
|
-
const field = numberField(leaf, typeof value === "number" ? value : 0);
|
|
485
|
-
return /* @__PURE__ */ jsx(
|
|
486
|
-
"input",
|
|
487
|
-
{
|
|
488
|
-
type: "number",
|
|
489
|
-
"aria-label": name,
|
|
490
|
-
title,
|
|
491
|
-
value: field.shown,
|
|
492
|
-
min: field.min,
|
|
493
|
-
max: field.max,
|
|
494
|
-
step: field.step,
|
|
495
|
-
onChange: (e2) => {
|
|
496
|
-
const n2 = Number(e2.target.value);
|
|
497
|
-
if (e2.target.value !== "" && Number.isFinite(n2)) write(field.store(n2));
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
);
|
|
501
|
-
}
|
|
502
|
-
case "boolean":
|
|
503
|
-
return extra(leaf, "control") === "switch" ? /* @__PURE__ */ jsx(a4, { "aria-label": name, isSelected: value === true, onChange: write }) : /* @__PURE__ */ jsx(
|
|
504
|
-
"input",
|
|
505
|
-
{
|
|
506
|
-
type: "checkbox",
|
|
507
|
-
"aria-label": name,
|
|
508
|
-
title,
|
|
509
|
-
checked: value === true,
|
|
510
|
-
onChange: (e2) => write(e2.target.checked)
|
|
511
|
-
}
|
|
512
|
-
);
|
|
513
|
-
case "string":
|
|
514
|
-
return /* @__PURE__ */ jsx(
|
|
515
|
-
"input",
|
|
516
|
-
{
|
|
517
|
-
type: "text",
|
|
518
|
-
"aria-label": name,
|
|
519
|
-
title,
|
|
520
|
-
value: text.local,
|
|
521
|
-
placeholder: extra(leaf, "placeholder"),
|
|
522
|
-
maxLength: extra(leaf, "maxLength"),
|
|
523
|
-
onChange: (e2) => text.type(e2.target.value)
|
|
524
|
-
}
|
|
525
|
-
);
|
|
526
|
-
case "color": {
|
|
527
|
-
const { rgb, alpha } = splitHexAlpha(typeof value === "string" ? value : "");
|
|
528
|
-
const carriesAlpha = extra(leaf, "alpha") === true;
|
|
529
|
-
return /* @__PURE__ */ jsx(
|
|
530
|
-
"input",
|
|
531
|
-
{
|
|
532
|
-
type: "color",
|
|
533
|
-
"aria-label": name,
|
|
534
|
-
title,
|
|
535
|
-
value: rgb,
|
|
536
|
-
onChange: (e2) => write(carriesAlpha ? joinHexAlpha(e2.target.value, alpha) : e2.target.value)
|
|
537
|
-
}
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
case "enum": {
|
|
541
|
-
const options = extra(leaf, "options") ?? [];
|
|
542
|
-
return /* @__PURE__ */ jsx("span", { title, children: /* @__PURE__ */ jsx(
|
|
543
|
-
g,
|
|
544
|
-
{
|
|
545
|
-
variant: "bare",
|
|
546
|
-
"aria-label": name,
|
|
547
|
-
options,
|
|
548
|
-
selectedKey: typeof value === "string" ? value : null,
|
|
549
|
-
onSelectionChange: write
|
|
550
|
-
}
|
|
551
|
-
) });
|
|
552
|
-
}
|
|
553
|
-
default:
|
|
554
|
-
return null;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
function useDebouncedText(value, write, debounceMs) {
|
|
558
|
-
const [local, setLocal] = useState(value);
|
|
559
|
-
const timer = useRef(null);
|
|
560
|
-
const lastExternal = useRef(value);
|
|
561
|
-
useEffect(() => {
|
|
562
|
-
if (value !== lastExternal.current) {
|
|
563
|
-
lastExternal.current = value;
|
|
564
|
-
setLocal(value);
|
|
565
|
-
}
|
|
566
|
-
}, [value]);
|
|
567
|
-
useEffect(
|
|
568
|
-
() => () => {
|
|
569
|
-
if (timer.current) clearTimeout(timer.current);
|
|
570
|
-
},
|
|
571
|
-
[]
|
|
572
|
-
);
|
|
573
|
-
return {
|
|
574
|
-
local,
|
|
575
|
-
type: (next) => {
|
|
576
|
-
setLocal(next);
|
|
577
|
-
if (timer.current) clearTimeout(timer.current);
|
|
578
|
-
const commit = () => {
|
|
579
|
-
lastExternal.current = next;
|
|
580
|
-
write(next);
|
|
581
|
-
};
|
|
582
|
-
if (debounceMs === 0) commit();
|
|
583
|
-
else timer.current = setTimeout(commit, debounceMs);
|
|
584
|
-
}
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
export { ControlPanel };
|
|
589
|
-
//# sourceMappingURL=chunk-EH7UEQV7.js.map
|
|
590
|
-
//# sourceMappingURL=chunk-EH7UEQV7.js.map
|