@12-apps/ui 6.99.0 → 6.100.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/dist/_internal/components/data-display/RegionMap/RegionMap.js +3 -3
- package/dist/_internal/components/data-display/RegionMap/RegionMapDrawing.js +2 -2
- package/dist/_internal/components/data-display/RegionMap/RegionMapPin.js +1 -1
- package/dist/_internal/components/data-display/index.js +3 -3
- package/dist/_internal/components/index.js +3 -3
- package/dist/{chunk-DRYBA76G.js → chunk-7XVT4RME.js} +2 -2
- package/dist/{chunk-DRYBA76G.js.map → chunk-7XVT4RME.js.map} +1 -1
- package/dist/{chunk-AYDVNXGR.js → chunk-LCKUEYU2.js} +2 -2
- package/dist/{chunk-3V5V44UP.js → chunk-YHFLI2FD.js} +2 -2
- package/dist/data-display/RegionMap.js +3 -3
- package/package.json +1 -1
- package/src/components/data-display/RegionMap/RegionMapPin.tsx +1 -1
- /package/dist/{chunk-AYDVNXGR.js.map → chunk-LCKUEYU2.js.map} +0 -0
- /package/dist/{chunk-3V5V44UP.js.map → chunk-YHFLI2FD.js.map} +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
RegionMap
|
|
3
|
-
} from "../../../../chunk-
|
|
3
|
+
} from "../../../../chunk-LCKUEYU2.js";
|
|
4
4
|
import "../../../../chunk-NWUMGE6T.js";
|
|
5
5
|
import "../../../../chunk-BRZKOUEL.js";
|
|
6
6
|
import "../../../../chunk-PBRCKHN3.js";
|
|
7
|
-
import "../../../../chunk-
|
|
7
|
+
import "../../../../chunk-YHFLI2FD.js";
|
|
8
8
|
import "../../../../chunk-J3AWGTJY.js";
|
|
9
|
-
import "../../../../chunk-
|
|
9
|
+
import "../../../../chunk-7XVT4RME.js";
|
|
10
10
|
import "../../../../chunk-KAZWBDIH.js";
|
|
11
11
|
import "../../../../chunk-MNJZPJ5S.js";
|
|
12
12
|
import "../../../../chunk-PUFA7FQ7.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
RegionMapDrawing
|
|
3
|
-
} from "../../../../chunk-
|
|
3
|
+
} from "../../../../chunk-YHFLI2FD.js";
|
|
4
4
|
import "../../../../chunk-J3AWGTJY.js";
|
|
5
|
-
import "../../../../chunk-
|
|
5
|
+
import "../../../../chunk-7XVT4RME.js";
|
|
6
6
|
import "../../../../chunk-MNJZPJ5S.js";
|
|
7
7
|
import "../../../../chunk-YKCAJ2TN.js";
|
|
8
8
|
import "../../../../chunk-PZ5AY32C.js";
|
|
@@ -119,16 +119,16 @@ import "../../../chunk-CB6DTWD5.js";
|
|
|
119
119
|
import "../../../chunk-WGKLBVDZ.js";
|
|
120
120
|
import {
|
|
121
121
|
RegionMap
|
|
122
|
-
} from "../../../chunk-
|
|
122
|
+
} from "../../../chunk-LCKUEYU2.js";
|
|
123
123
|
import "../../../chunk-NWUMGE6T.js";
|
|
124
124
|
import "../../../chunk-BRZKOUEL.js";
|
|
125
125
|
import "../../../chunk-PBRCKHN3.js";
|
|
126
|
-
import "../../../chunk-
|
|
126
|
+
import "../../../chunk-YHFLI2FD.js";
|
|
127
127
|
import "../../../chunk-J3AWGTJY.js";
|
|
128
128
|
import {
|
|
129
129
|
latLngAt,
|
|
130
130
|
scaleMetres
|
|
131
|
-
} from "../../../chunk-
|
|
131
|
+
} from "../../../chunk-7XVT4RME.js";
|
|
132
132
|
import {
|
|
133
133
|
boundsOfRings,
|
|
134
134
|
regionMapView
|
|
@@ -559,16 +559,16 @@ import "../../chunk-CB6DTWD5.js";
|
|
|
559
559
|
import "../../chunk-WGKLBVDZ.js";
|
|
560
560
|
import {
|
|
561
561
|
RegionMap
|
|
562
|
-
} from "../../chunk-
|
|
562
|
+
} from "../../chunk-LCKUEYU2.js";
|
|
563
563
|
import "../../chunk-NWUMGE6T.js";
|
|
564
564
|
import "../../chunk-BRZKOUEL.js";
|
|
565
565
|
import "../../chunk-PBRCKHN3.js";
|
|
566
|
-
import "../../chunk-
|
|
566
|
+
import "../../chunk-YHFLI2FD.js";
|
|
567
567
|
import "../../chunk-J3AWGTJY.js";
|
|
568
568
|
import {
|
|
569
569
|
latLngAt,
|
|
570
570
|
scaleMetres
|
|
571
|
-
} from "../../chunk-
|
|
571
|
+
} from "../../chunk-7XVT4RME.js";
|
|
572
572
|
import {
|
|
573
573
|
boundsOfRings,
|
|
574
574
|
regionMapView
|
|
@@ -266,7 +266,7 @@ function ScaleBar({
|
|
|
266
266
|
"aria-hidden": true,
|
|
267
267
|
sx: { position: "absolute", left: 0, right: 0, bottom: rem(theme, 10), pointerEvents: "none", zIndex: 1 },
|
|
268
268
|
children: [
|
|
269
|
-
/* @__PURE__ */ jsx(Box, { component: "span", sx: { display: "block", ml: rem(theme, 10), fontSize: rem(theme,
|
|
269
|
+
/* @__PURE__ */ jsx(Box, { component: "span", sx: { display: "block", ml: rem(theme, 10), fontSize: rem(theme, 12), color: "text.secondary" }, children: copy.scale(metres) }),
|
|
270
270
|
/* @__PURE__ */ jsx(
|
|
271
271
|
Box,
|
|
272
272
|
{
|
|
@@ -290,4 +290,4 @@ export {
|
|
|
290
290
|
scaleMetres,
|
|
291
291
|
ScaleBar
|
|
292
292
|
};
|
|
293
|
-
//# sourceMappingURL=chunk-
|
|
293
|
+
//# sourceMappingURL=chunk-7XVT4RME.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/data-display/RegionMap/RegionMapPin.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport { alpha, type Theme } from '@mui/material/styles/index.js';\nimport React from 'react';\n\nimport { rem } from '../../../tokens/relative';\n\nimport { METRES_PER_DEGREE, type PlaneBox, type PlanePoint, type Projection } from './RegionMap.helpers';\nimport type { RegionMapModel } from './RegionMap.hooks';\nimport type { RegionMapCenter, RegionMapCopy, RegionMapDot, RegionMapGhost, RegionMapPin } from './RegionMap.types';\n\n/**\n * The movable centre of a `RegionMap` (`pin`, `ghost`, `dots`): a pin the\n * viewer drags with a mouse or one finger, or focuses and nudges with the\n * arrow keys, while the VIEW stays where `center` put it — so the areas never\n * slide under a dragging finger. The circles follow the pin; a dashed ring\n * and dot stay at `ghost`; `dots` are small points (filled or hollow).\n *\n * The pin is HTML over the drawing, at its point by percent like the labels,\n * carrying `data-region-pin` so a host that zooms the drawing's layers can\n * move it with them. Its moves are reported, never applied: the host passes\n * the new point back.\n */\n\n/** The movable centre and what is drawn with it, as the drawing receives it. */\nexport interface Moving {\n center: RegionMapCenter;\n pin?: RegionMapPin;\n ghost?: RegionMapGhost;\n dots?: readonly RegionMapDot[];\n copy: RegionMapCopy;\n}\n\ntype DrawnModel = Pick<RegionMapModel, 'projection' | 'radii'> & { view: PlaneBox };\n\n/**\n * What the movable centre draws inside the SVG: the circles around the pin\n * (else `fallback`, the centre's own circles), the ghost, and the dots.\n */\nexport function PinShapes({ model, moving, testId, theme, fallback }: { model: DrawnModel; moving: Moving | undefined; testId: string; theme: Theme; fallback: React.ReactNode }): React.JSX.Element {\n const { projection, view } = model;\n if (!moving || !projection) return <>{fallback}</>;\n const pinAt = moving.pin ? projection.project([moving.pin.at.latitude, moving.pin.at.longitude]) : null;\n return (\n <>\n {pinAt ? <PinCircles at={pinAt} radii={model.radii} theme={theme} /> : fallback}\n {pinAt && moving.ghost ? <GhostShapes ghost={moving.ghost} pinAt={pinAt} projection={projection} view={view} testId={testId} theme={theme} /> : null}\n {moving.dots ? <Dots dots={moving.dots} projection={projection} view={view} testId={testId} theme={theme} /> : null}\n </>\n );\n}\n\n/** What the movable centre draws over the SVG, in HTML: the pin and the scale bar. */\nexport function PinOverlay({\n model,\n moving,\n svgRef,\n testId,\n theme,\n}: {\n model: DrawnModel;\n moving: Moving | undefined;\n svgRef: React.RefObject<SVGSVGElement | null>;\n testId: string;\n theme: Theme;\n}): React.JSX.Element | null {\n if (!moving || !model.projection) return null;\n return (\n <>\n {moving.pin ? <PinMarker pin={moving.pin} center={moving.center} projection={model.projection} view={model.view} svgRef={svgRef} testId={testId} theme={theme} /> : null}\n <ScaleBar view={model.view} copy={moving.copy} svgRef={svgRef} testId={testId} theme={theme} />\n </>\n );\n}\n\n/** The flat projection's inverse around `center` — it is linear. */\nexport function latLngAt(center: RegionMapCenter, point: PlanePoint): RegionMapCenter {\n const kx = METRES_PER_DEGREE * Math.cos((center.latitude * Math.PI) / 180);\n return { latitude: center.latitude - point.y / METRES_PER_DEGREE, longitude: center.longitude + point.x / kx };\n}\n\n/** A point of the plane as fractions of the view (0..1 across, 0..1 down). */\nfunction fractionOf(view: PlaneBox, point: PlanePoint): { x: number; y: number } {\n return { x: (point.x - view.minX) / view.spanX, y: (point.y - view.minY) / view.spanY };\n}\n\n/** Keep a fraction inside the view, a hair in from its edge (the mock's clamp). */\nconst clampFraction = (value: number): number => Math.min(0.995, Math.max(0.005, value));\n\n/** A plane point kept inside the view by the same clamp a drag gets. */\nfunction clampToView(view: PlaneBox, point: PlanePoint): PlanePoint {\n const at = fractionOf(view, point);\n return { x: view.minX + clampFraction(at.x) * view.spanX, y: view.minY + clampFraction(at.y) * view.spanY };\n}\n\n/** Arrow keys, as metres east and north per press. */\nconst ARROWS: Record<string, [number, number]> = { ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, 1], ArrowDown: [0, -1] };\n\n/** One arrow key: 50 m unless the host says otherwise. */\nconst DEFAULT_STEP_METRES = 50;\n\ninterface PinLayerProps {\n pin: RegionMapPin;\n center: RegionMapCenter;\n projection: Projection;\n view: PlaneBox;\n /** The drawing's SVG, whose on-screen box maps a pointer to the plane (zoomed or not). */\n svgRef: React.RefObject<SVGSVGElement | null>;\n testId: string;\n theme: Theme;\n}\n\n/** The draggable pin, as HTML over the drawing. */\nexport function PinMarker({ pin, center, projection, view, svgRef, testId, theme }: PinLayerProps): React.JSX.Element {\n const ref = React.useRef<HTMLDivElement>(null);\n const live = React.useRef({ pin, center, view });\n live.current = { pin, center, view };\n usePinDrag(ref, svgRef, live);\n const at = fractionOf(view, projection.project([pin.at.latitude, pin.at.longitude]));\n const onKeyDown = (event: React.KeyboardEvent): void => {\n const arrow = ARROWS[event.key];\n if (!arrow || pin.disabled) return;\n event.preventDefault();\n const step = pin.stepMetres ?? DEFAULT_STEP_METRES;\n const plane = projection.project([pin.at.latitude, pin.at.longitude]);\n const next = latLngAt(center, clampToView(view, { x: plane.x + arrow[0] * step, y: plane.y - arrow[1] * step }));\n pin.onMove?.(next);\n pin.onDrop(next);\n };\n return (\n <Box\n ref={ref}\n role=\"button\"\n tabIndex={pin.disabled ? -1 : 0}\n aria-label={pin.ariaLabel}\n aria-disabled={pin.disabled || undefined}\n onKeyDown={onKeyDown}\n data-testid={`${testId}-pin`}\n data-region-pin=\"\"\n style={{ left: `${(at.x * 100).toFixed(3)}%`, top: `${(at.y * 100).toFixed(3)}%` }}\n sx={{\n position: 'absolute',\n transform: 'translate(-50%, -100%)',\n width: rem(theme, 44),\n height: rem(theme, 48),\n display: 'flex',\n alignItems: 'flex-end',\n justifyContent: 'center',\n cursor: pin.disabled ? 'default' : 'grab',\n touchAction: 'none',\n zIndex: 2,\n borderRadius: 1,\n '&:focus-visible': { outline: `${rem(theme, 2)} solid`, outlineColor: 'primary.main', outlineOffset: rem(theme, 2) },\n }}\n >\n <Box component=\"svg\" viewBox=\"0 0 32 42\" aria-hidden=\"true\" sx={{ width: rem(theme, 32), height: rem(theme, 42) }}>\n <path\n d=\"M16 41C16 41 3 25 3 15.5A13 13 0 1 1 29 15.5C29 25 16 41 16 41Z\"\n fill={theme.palette.primary.main}\n stroke={theme.palette.background.paper}\n strokeWidth={2}\n />\n <circle cx=\"16\" cy=\"15.5\" r=\"5\" fill={theme.palette.background.paper} />\n </Box>\n <Box\n component=\"span\"\n aria-hidden\n sx={{\n position: 'absolute',\n left: '88%',\n top: 0,\n px: 0.75,\n borderRadius: 0.5,\n border: 1,\n borderColor: 'divider',\n bgcolor: 'background.paper',\n color: 'text.primary',\n fontSize: rem(theme, 12),\n fontWeight: 600,\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n }}\n >\n {pin.label}\n </Box>\n </Box>\n );\n}\n\n/**\n * The pointer drag: native listeners on the pin, so a host's own listeners on\n * the drawing (a pan, a tap) never see the press; captured, so a finger that\n * leaves the pin keeps dragging it; clamped inside the view.\n */\nfunction usePinDrag(\n ref: React.RefObject<HTMLDivElement | null>,\n svgRef: React.RefObject<SVGSVGElement | null>,\n live: React.RefObject<{ pin: RegionMapPin; center: RegionMapCenter; view: PlaneBox }>,\n): void {\n React.useEffect(() => {\n const element = ref.current;\n if (!element) return undefined;\n let dragging: number | null = null;\n // Where the last move put the pin: a cancelled gesture (a browser may\n // report 0,0 for it) rests there rather than jumping to the corner.\n let last: RegionMapCenter | null = null;\n const pointAt = (event: PointerEvent): RegionMapCenter | null => {\n const box = svgRef.current?.getBoundingClientRect();\n if (!box || box.width === 0 || box.height === 0) return null;\n const { view, center } = live.current;\n if (!Number.isFinite(event.clientX) || !Number.isFinite(event.clientY)) return null;\n const fx = clampFraction((event.clientX - box.left) / box.width);\n const fy = clampFraction((event.clientY - box.top) / box.height);\n return latLngAt(center, { x: view.minX + fx * view.spanX, y: view.minY + fy * view.spanY });\n };\n const down = (event: PointerEvent): void => {\n event.stopPropagation();\n if (live.current.pin.disabled) return;\n event.preventDefault();\n dragging = event.pointerId;\n last = null;\n element.setPointerCapture?.(event.pointerId);\n };\n const move = (event: PointerEvent): void => {\n if (dragging !== event.pointerId) return;\n event.stopPropagation();\n const at = pointAt(event);\n if (!at) return;\n last = at;\n live.current.pin.onMove?.(at);\n };\n const up = (event: PointerEvent): void => {\n if (dragging !== event.pointerId) return;\n event.stopPropagation();\n dragging = null;\n const at = event.type === 'pointercancel' ? last : (pointAt(event) ?? last);\n if (at) live.current.pin.onDrop(at);\n };\n // A click that ends a drag is the drag's, not a tap on the area under it.\n const click = (event: MouseEvent): void => event.stopPropagation();\n element.addEventListener('pointerdown', down);\n element.addEventListener('pointermove', move);\n element.addEventListener('pointerup', up);\n element.addEventListener('pointercancel', up);\n element.addEventListener('click', click);\n return () => {\n element.removeEventListener('pointerdown', down);\n element.removeEventListener('pointermove', move);\n element.removeEventListener('pointerup', up);\n element.removeEventListener('pointercancel', up);\n element.removeEventListener('click', click);\n };\n }, [ref, svgRef, live]);\n}\n\n/** The circles around the pin: solid in the primary colour, faintly filled. */\nexport function PinCircles({ at, radii, theme }: { at: PlanePoint; radii: readonly number[]; theme: Theme }): React.JSX.Element {\n return (\n <>\n {radii.map((radius) => (\n <circle\n key={radius}\n cx={at.x}\n cy={at.y}\n r={radius}\n fill={alpha(theme.palette.primary.main, 0.06)}\n stroke={theme.palette.primary.main}\n strokeWidth={2.25}\n vectorEffect=\"non-scaling-stroke\"\n pointerEvents=\"none\"\n />\n ))}\n </>\n );\n}\n\n/** Where the circles stood: a dashed ring and dot at `ghost`, and a dashed line from it to the pin. */\nexport function GhostShapes({\n ghost,\n pinAt,\n projection,\n view,\n testId,\n theme,\n}: {\n ghost: RegionMapGhost;\n pinAt: PlanePoint;\n projection: Projection;\n view: PlaneBox;\n testId: string;\n theme: Theme;\n}): React.JSX.Element {\n const at = projection.project([ghost.at.latitude, ghost.at.longitude]);\n const stroke = theme.palette.text.secondary;\n const common = { fill: 'none', stroke, vectorEffect: 'non-scaling-stroke', pointerEvents: 'none' } as const;\n return (\n <g data-testid={`${testId}-ghost`}>\n <circle cx={at.x} cy={at.y} r={ghost.radiusMetres} strokeWidth={1.5} strokeDasharray=\"6 5\" {...common} />\n <line x1={at.x} y1={at.y} x2={pinAt.x} y2={pinAt.y} strokeWidth={1.5} strokeDasharray=\"4 4\" {...common} />\n <circle cx={at.x} cy={at.y} r={view.spanX / 110} strokeWidth={2} strokeDasharray=\"3 2\" {...common} fill={alpha(theme.palette.background.paper, 0.7)} />\n </g>\n );\n}\n\n/** The dots: filled with the ink, or hollow (paper with an ink ring). */\nexport function Dots({ dots, projection, view, testId, theme }: { dots: readonly RegionMapDot[]; projection: Projection; view: PlaneBox; testId: string; theme: Theme }): React.JSX.Element {\n return (\n <g data-testid={`${testId}-dots`}>\n {dots.map((dot) => {\n const at = projection.project([dot.at.latitude, dot.at.longitude]);\n return (\n <circle\n key={dot.id}\n cx={at.x}\n cy={at.y}\n r={view.spanX / 150}\n fill={dot.filled ? theme.palette.text.primary : theme.palette.background.paper}\n stroke={theme.palette.text.primary}\n strokeWidth={2}\n vectorEffect=\"non-scaling-stroke\"\n pointerEvents=\"none\"\n data-filled={dot.filled ? 'true' : 'false'}\n />\n );\n })}\n </g>\n );\n}\n\n/** Nice lengths a scale bar may take, in metres. */\nconst SCALE_STEPS = [50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000];\n\n/** The longest nice length that fits in a quarter of the drawing's width. */\nexport function scaleMetres(view: PlaneBox): number {\n const quarter = view.spanX / 4;\n return SCALE_STEPS.filter((step) => step <= quarter).at(-1) ?? SCALE_STEPS[0]!;\n}\n\n/**\n * A scale bar, bottom-left, when the host gives `copy.scale`. It reads what is\n * on screen: a host that zooms the drawing's layers (a CSS scale on the SVG)\n * shows fewer metres per pixel, so after every render the bar compares the\n * SVG's drawn width with its laid-out width — both off the SVG itself — and\n * spans the drawing's own width, so its share of it is a share of the view.\n */\nexport function ScaleBar({\n view,\n copy,\n svgRef,\n testId,\n theme,\n}: {\n view: PlaneBox;\n copy: RegionMapCopy;\n svgRef: React.RefObject<SVGSVGElement | null>;\n testId: string;\n theme: Theme;\n}): React.JSX.Element | null {\n // What the drawing shows on screen: its laid-out width, and its width as\n // drawn (a host's CSS scale on the SVG), both read off the SVG itself.\n const [screen, setScreen] = React.useState({ laidOut: 0, drawn: 0 });\n const wanted = copy.scale !== undefined;\n React.useLayoutEffect(() => {\n if (!wanted) return;\n const svg = svgRef.current;\n const next = { laidOut: svg?.clientWidth ?? 0, drawn: svg?.getBoundingClientRect().width ?? 0 };\n if (next.laidOut !== screen.laidOut || Math.abs(next.drawn - screen.drawn) > 0.5) setScreen(next);\n });\n if (!copy.scale) return null;\n const zoom = screen.laidOut > 0 && screen.drawn > 0 ? screen.drawn / screen.laidOut : 1;\n const metres = scaleMetres({ ...view, spanX: view.spanX / zoom });\n // The bar's share of the drawing's width: metres on screen over the metres the width shows.\n const share = (metres * zoom) / view.spanX;\n return (\n <Box\n data-testid={`${testId}-scale`}\n aria-hidden\n sx={{ position: 'absolute', left: 0, right: 0, bottom: rem(theme, 10), pointerEvents: 'none', zIndex: 1 }}\n >\n <Box component=\"span\" sx={{ display: 'block', ml: rem(theme, 10), fontSize: rem(theme, 11), color: 'text.secondary' }}>\n {copy.scale(metres)}\n </Box>\n <Box\n component=\"span\"\n sx={{ display: 'block', height: rem(theme, 4), ml: rem(theme, 10), width: `${(share * 100).toFixed(2)}%`, borderStyle: 'solid', borderWidth: `0 ${rem(theme, 1.5)} ${rem(theme, 1.5)}`, borderColor: 'text.secondary' }}\n />\n </Box>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/components/data-display/RegionMap/RegionMapPin.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport { alpha, type Theme } from '@mui/material/styles/index.js';\nimport React from 'react';\n\nimport { rem } from '../../../tokens/relative';\n\nimport { METRES_PER_DEGREE, type PlaneBox, type PlanePoint, type Projection } from './RegionMap.helpers';\nimport type { RegionMapModel } from './RegionMap.hooks';\nimport type { RegionMapCenter, RegionMapCopy, RegionMapDot, RegionMapGhost, RegionMapPin } from './RegionMap.types';\n\n/**\n * The movable centre of a `RegionMap` (`pin`, `ghost`, `dots`): a pin the\n * viewer drags with a mouse or one finger, or focuses and nudges with the\n * arrow keys, while the VIEW stays where `center` put it — so the areas never\n * slide under a dragging finger. The circles follow the pin; a dashed ring\n * and dot stay at `ghost`; `dots` are small points (filled or hollow).\n *\n * The pin is HTML over the drawing, at its point by percent like the labels,\n * carrying `data-region-pin` so a host that zooms the drawing's layers can\n * move it with them. Its moves are reported, never applied: the host passes\n * the new point back.\n */\n\n/** The movable centre and what is drawn with it, as the drawing receives it. */\nexport interface Moving {\n center: RegionMapCenter;\n pin?: RegionMapPin;\n ghost?: RegionMapGhost;\n dots?: readonly RegionMapDot[];\n copy: RegionMapCopy;\n}\n\ntype DrawnModel = Pick<RegionMapModel, 'projection' | 'radii'> & { view: PlaneBox };\n\n/**\n * What the movable centre draws inside the SVG: the circles around the pin\n * (else `fallback`, the centre's own circles), the ghost, and the dots.\n */\nexport function PinShapes({ model, moving, testId, theme, fallback }: { model: DrawnModel; moving: Moving | undefined; testId: string; theme: Theme; fallback: React.ReactNode }): React.JSX.Element {\n const { projection, view } = model;\n if (!moving || !projection) return <>{fallback}</>;\n const pinAt = moving.pin ? projection.project([moving.pin.at.latitude, moving.pin.at.longitude]) : null;\n return (\n <>\n {pinAt ? <PinCircles at={pinAt} radii={model.radii} theme={theme} /> : fallback}\n {pinAt && moving.ghost ? <GhostShapes ghost={moving.ghost} pinAt={pinAt} projection={projection} view={view} testId={testId} theme={theme} /> : null}\n {moving.dots ? <Dots dots={moving.dots} projection={projection} view={view} testId={testId} theme={theme} /> : null}\n </>\n );\n}\n\n/** What the movable centre draws over the SVG, in HTML: the pin and the scale bar. */\nexport function PinOverlay({\n model,\n moving,\n svgRef,\n testId,\n theme,\n}: {\n model: DrawnModel;\n moving: Moving | undefined;\n svgRef: React.RefObject<SVGSVGElement | null>;\n testId: string;\n theme: Theme;\n}): React.JSX.Element | null {\n if (!moving || !model.projection) return null;\n return (\n <>\n {moving.pin ? <PinMarker pin={moving.pin} center={moving.center} projection={model.projection} view={model.view} svgRef={svgRef} testId={testId} theme={theme} /> : null}\n <ScaleBar view={model.view} copy={moving.copy} svgRef={svgRef} testId={testId} theme={theme} />\n </>\n );\n}\n\n/** The flat projection's inverse around `center` — it is linear. */\nexport function latLngAt(center: RegionMapCenter, point: PlanePoint): RegionMapCenter {\n const kx = METRES_PER_DEGREE * Math.cos((center.latitude * Math.PI) / 180);\n return { latitude: center.latitude - point.y / METRES_PER_DEGREE, longitude: center.longitude + point.x / kx };\n}\n\n/** A point of the plane as fractions of the view (0..1 across, 0..1 down). */\nfunction fractionOf(view: PlaneBox, point: PlanePoint): { x: number; y: number } {\n return { x: (point.x - view.minX) / view.spanX, y: (point.y - view.minY) / view.spanY };\n}\n\n/** Keep a fraction inside the view, a hair in from its edge (the mock's clamp). */\nconst clampFraction = (value: number): number => Math.min(0.995, Math.max(0.005, value));\n\n/** A plane point kept inside the view by the same clamp a drag gets. */\nfunction clampToView(view: PlaneBox, point: PlanePoint): PlanePoint {\n const at = fractionOf(view, point);\n return { x: view.minX + clampFraction(at.x) * view.spanX, y: view.minY + clampFraction(at.y) * view.spanY };\n}\n\n/** Arrow keys, as metres east and north per press. */\nconst ARROWS: Record<string, [number, number]> = { ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, 1], ArrowDown: [0, -1] };\n\n/** One arrow key: 50 m unless the host says otherwise. */\nconst DEFAULT_STEP_METRES = 50;\n\ninterface PinLayerProps {\n pin: RegionMapPin;\n center: RegionMapCenter;\n projection: Projection;\n view: PlaneBox;\n /** The drawing's SVG, whose on-screen box maps a pointer to the plane (zoomed or not). */\n svgRef: React.RefObject<SVGSVGElement | null>;\n testId: string;\n theme: Theme;\n}\n\n/** The draggable pin, as HTML over the drawing. */\nexport function PinMarker({ pin, center, projection, view, svgRef, testId, theme }: PinLayerProps): React.JSX.Element {\n const ref = React.useRef<HTMLDivElement>(null);\n const live = React.useRef({ pin, center, view });\n live.current = { pin, center, view };\n usePinDrag(ref, svgRef, live);\n const at = fractionOf(view, projection.project([pin.at.latitude, pin.at.longitude]));\n const onKeyDown = (event: React.KeyboardEvent): void => {\n const arrow = ARROWS[event.key];\n if (!arrow || pin.disabled) return;\n event.preventDefault();\n const step = pin.stepMetres ?? DEFAULT_STEP_METRES;\n const plane = projection.project([pin.at.latitude, pin.at.longitude]);\n const next = latLngAt(center, clampToView(view, { x: plane.x + arrow[0] * step, y: plane.y - arrow[1] * step }));\n pin.onMove?.(next);\n pin.onDrop(next);\n };\n return (\n <Box\n ref={ref}\n role=\"button\"\n tabIndex={pin.disabled ? -1 : 0}\n aria-label={pin.ariaLabel}\n aria-disabled={pin.disabled || undefined}\n onKeyDown={onKeyDown}\n data-testid={`${testId}-pin`}\n data-region-pin=\"\"\n style={{ left: `${(at.x * 100).toFixed(3)}%`, top: `${(at.y * 100).toFixed(3)}%` }}\n sx={{\n position: 'absolute',\n transform: 'translate(-50%, -100%)',\n width: rem(theme, 44),\n height: rem(theme, 48),\n display: 'flex',\n alignItems: 'flex-end',\n justifyContent: 'center',\n cursor: pin.disabled ? 'default' : 'grab',\n touchAction: 'none',\n zIndex: 2,\n borderRadius: 1,\n '&:focus-visible': { outline: `${rem(theme, 2)} solid`, outlineColor: 'primary.main', outlineOffset: rem(theme, 2) },\n }}\n >\n <Box component=\"svg\" viewBox=\"0 0 32 42\" aria-hidden=\"true\" sx={{ width: rem(theme, 32), height: rem(theme, 42) }}>\n <path\n d=\"M16 41C16 41 3 25 3 15.5A13 13 0 1 1 29 15.5C29 25 16 41 16 41Z\"\n fill={theme.palette.primary.main}\n stroke={theme.palette.background.paper}\n strokeWidth={2}\n />\n <circle cx=\"16\" cy=\"15.5\" r=\"5\" fill={theme.palette.background.paper} />\n </Box>\n <Box\n component=\"span\"\n aria-hidden\n sx={{\n position: 'absolute',\n left: '88%',\n top: 0,\n px: 0.75,\n borderRadius: 0.5,\n border: 1,\n borderColor: 'divider',\n bgcolor: 'background.paper',\n color: 'text.primary',\n fontSize: rem(theme, 12),\n fontWeight: 600,\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n }}\n >\n {pin.label}\n </Box>\n </Box>\n );\n}\n\n/**\n * The pointer drag: native listeners on the pin, so a host's own listeners on\n * the drawing (a pan, a tap) never see the press; captured, so a finger that\n * leaves the pin keeps dragging it; clamped inside the view.\n */\nfunction usePinDrag(\n ref: React.RefObject<HTMLDivElement | null>,\n svgRef: React.RefObject<SVGSVGElement | null>,\n live: React.RefObject<{ pin: RegionMapPin; center: RegionMapCenter; view: PlaneBox }>,\n): void {\n React.useEffect(() => {\n const element = ref.current;\n if (!element) return undefined;\n let dragging: number | null = null;\n // Where the last move put the pin: a cancelled gesture (a browser may\n // report 0,0 for it) rests there rather than jumping to the corner.\n let last: RegionMapCenter | null = null;\n const pointAt = (event: PointerEvent): RegionMapCenter | null => {\n const box = svgRef.current?.getBoundingClientRect();\n if (!box || box.width === 0 || box.height === 0) return null;\n const { view, center } = live.current;\n if (!Number.isFinite(event.clientX) || !Number.isFinite(event.clientY)) return null;\n const fx = clampFraction((event.clientX - box.left) / box.width);\n const fy = clampFraction((event.clientY - box.top) / box.height);\n return latLngAt(center, { x: view.minX + fx * view.spanX, y: view.minY + fy * view.spanY });\n };\n const down = (event: PointerEvent): void => {\n event.stopPropagation();\n if (live.current.pin.disabled) return;\n event.preventDefault();\n dragging = event.pointerId;\n last = null;\n element.setPointerCapture?.(event.pointerId);\n };\n const move = (event: PointerEvent): void => {\n if (dragging !== event.pointerId) return;\n event.stopPropagation();\n const at = pointAt(event);\n if (!at) return;\n last = at;\n live.current.pin.onMove?.(at);\n };\n const up = (event: PointerEvent): void => {\n if (dragging !== event.pointerId) return;\n event.stopPropagation();\n dragging = null;\n const at = event.type === 'pointercancel' ? last : (pointAt(event) ?? last);\n if (at) live.current.pin.onDrop(at);\n };\n // A click that ends a drag is the drag's, not a tap on the area under it.\n const click = (event: MouseEvent): void => event.stopPropagation();\n element.addEventListener('pointerdown', down);\n element.addEventListener('pointermove', move);\n element.addEventListener('pointerup', up);\n element.addEventListener('pointercancel', up);\n element.addEventListener('click', click);\n return () => {\n element.removeEventListener('pointerdown', down);\n element.removeEventListener('pointermove', move);\n element.removeEventListener('pointerup', up);\n element.removeEventListener('pointercancel', up);\n element.removeEventListener('click', click);\n };\n }, [ref, svgRef, live]);\n}\n\n/** The circles around the pin: solid in the primary colour, faintly filled. */\nexport function PinCircles({ at, radii, theme }: { at: PlanePoint; radii: readonly number[]; theme: Theme }): React.JSX.Element {\n return (\n <>\n {radii.map((radius) => (\n <circle\n key={radius}\n cx={at.x}\n cy={at.y}\n r={radius}\n fill={alpha(theme.palette.primary.main, 0.06)}\n stroke={theme.palette.primary.main}\n strokeWidth={2.25}\n vectorEffect=\"non-scaling-stroke\"\n pointerEvents=\"none\"\n />\n ))}\n </>\n );\n}\n\n/** Where the circles stood: a dashed ring and dot at `ghost`, and a dashed line from it to the pin. */\nexport function GhostShapes({\n ghost,\n pinAt,\n projection,\n view,\n testId,\n theme,\n}: {\n ghost: RegionMapGhost;\n pinAt: PlanePoint;\n projection: Projection;\n view: PlaneBox;\n testId: string;\n theme: Theme;\n}): React.JSX.Element {\n const at = projection.project([ghost.at.latitude, ghost.at.longitude]);\n const stroke = theme.palette.text.secondary;\n const common = { fill: 'none', stroke, vectorEffect: 'non-scaling-stroke', pointerEvents: 'none' } as const;\n return (\n <g data-testid={`${testId}-ghost`}>\n <circle cx={at.x} cy={at.y} r={ghost.radiusMetres} strokeWidth={1.5} strokeDasharray=\"6 5\" {...common} />\n <line x1={at.x} y1={at.y} x2={pinAt.x} y2={pinAt.y} strokeWidth={1.5} strokeDasharray=\"4 4\" {...common} />\n <circle cx={at.x} cy={at.y} r={view.spanX / 110} strokeWidth={2} strokeDasharray=\"3 2\" {...common} fill={alpha(theme.palette.background.paper, 0.7)} />\n </g>\n );\n}\n\n/** The dots: filled with the ink, or hollow (paper with an ink ring). */\nexport function Dots({ dots, projection, view, testId, theme }: { dots: readonly RegionMapDot[]; projection: Projection; view: PlaneBox; testId: string; theme: Theme }): React.JSX.Element {\n return (\n <g data-testid={`${testId}-dots`}>\n {dots.map((dot) => {\n const at = projection.project([dot.at.latitude, dot.at.longitude]);\n return (\n <circle\n key={dot.id}\n cx={at.x}\n cy={at.y}\n r={view.spanX / 150}\n fill={dot.filled ? theme.palette.text.primary : theme.palette.background.paper}\n stroke={theme.palette.text.primary}\n strokeWidth={2}\n vectorEffect=\"non-scaling-stroke\"\n pointerEvents=\"none\"\n data-filled={dot.filled ? 'true' : 'false'}\n />\n );\n })}\n </g>\n );\n}\n\n/** Nice lengths a scale bar may take, in metres. */\nconst SCALE_STEPS = [50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000];\n\n/** The longest nice length that fits in a quarter of the drawing's width. */\nexport function scaleMetres(view: PlaneBox): number {\n const quarter = view.spanX / 4;\n return SCALE_STEPS.filter((step) => step <= quarter).at(-1) ?? SCALE_STEPS[0]!;\n}\n\n/**\n * A scale bar, bottom-left, when the host gives `copy.scale`. It reads what is\n * on screen: a host that zooms the drawing's layers (a CSS scale on the SVG)\n * shows fewer metres per pixel, so after every render the bar compares the\n * SVG's drawn width with its laid-out width — both off the SVG itself — and\n * spans the drawing's own width, so its share of it is a share of the view.\n */\nexport function ScaleBar({\n view,\n copy,\n svgRef,\n testId,\n theme,\n}: {\n view: PlaneBox;\n copy: RegionMapCopy;\n svgRef: React.RefObject<SVGSVGElement | null>;\n testId: string;\n theme: Theme;\n}): React.JSX.Element | null {\n // What the drawing shows on screen: its laid-out width, and its width as\n // drawn (a host's CSS scale on the SVG), both read off the SVG itself.\n const [screen, setScreen] = React.useState({ laidOut: 0, drawn: 0 });\n const wanted = copy.scale !== undefined;\n React.useLayoutEffect(() => {\n if (!wanted) return;\n const svg = svgRef.current;\n const next = { laidOut: svg?.clientWidth ?? 0, drawn: svg?.getBoundingClientRect().width ?? 0 };\n if (next.laidOut !== screen.laidOut || Math.abs(next.drawn - screen.drawn) > 0.5) setScreen(next);\n });\n if (!copy.scale) return null;\n const zoom = screen.laidOut > 0 && screen.drawn > 0 ? screen.drawn / screen.laidOut : 1;\n const metres = scaleMetres({ ...view, spanX: view.spanX / zoom });\n // The bar's share of the drawing's width: metres on screen over the metres the width shows.\n const share = (metres * zoom) / view.spanX;\n return (\n <Box\n data-testid={`${testId}-scale`}\n aria-hidden\n sx={{ position: 'absolute', left: 0, right: 0, bottom: rem(theme, 10), pointerEvents: 'none', zIndex: 1 }}\n >\n <Box component=\"span\" sx={{ display: 'block', ml: rem(theme, 10), fontSize: rem(theme, 12), color: 'text.secondary' }}>\n {copy.scale(metres)}\n </Box>\n <Box\n component=\"span\"\n sx={{ display: 'block', height: rem(theme, 4), ml: rem(theme, 10), width: `${(share * 100).toFixed(2)}%`, borderStyle: 'solid', borderWidth: `0 ${rem(theme, 1.5)} ${rem(theme, 1.5)}`, borderColor: 'text.secondary' }}\n />\n </Box>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "./chunk-PBRCKHN3.js";
|
|
10
10
|
import {
|
|
11
11
|
RegionMapDrawing
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-YHFLI2FD.js";
|
|
13
13
|
|
|
14
14
|
// src/components/data-display/RegionMap/RegionMap.tsx
|
|
15
15
|
import Box from "@mui/material/Box/index.js";
|
|
@@ -84,4 +84,4 @@ function RegionMap({
|
|
|
84
84
|
export {
|
|
85
85
|
RegionMap
|
|
86
86
|
};
|
|
87
|
-
//# sourceMappingURL=chunk-
|
|
87
|
+
//# sourceMappingURL=chunk-LCKUEYU2.js.map
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
PinOverlay,
|
|
7
7
|
PinShapes
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-7XVT4RME.js";
|
|
9
9
|
import {
|
|
10
10
|
labelPosition
|
|
11
11
|
} from "./chunk-MNJZPJ5S.js";
|
|
@@ -254,4 +254,4 @@ function AreaLabel({
|
|
|
254
254
|
export {
|
|
255
255
|
RegionMapDrawing
|
|
256
256
|
};
|
|
257
|
-
//# sourceMappingURL=chunk-
|
|
257
|
+
//# sourceMappingURL=chunk-YHFLI2FD.js.map
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import "../chunk-WGKLBVDZ.js";
|
|
2
2
|
import {
|
|
3
3
|
RegionMap
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-LCKUEYU2.js";
|
|
5
5
|
import "../chunk-NWUMGE6T.js";
|
|
6
6
|
import "../chunk-BRZKOUEL.js";
|
|
7
7
|
import "../chunk-PBRCKHN3.js";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-YHFLI2FD.js";
|
|
9
9
|
import "../chunk-J3AWGTJY.js";
|
|
10
10
|
import {
|
|
11
11
|
latLngAt,
|
|
12
12
|
scaleMetres
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-7XVT4RME.js";
|
|
14
14
|
import {
|
|
15
15
|
boundsOfRings,
|
|
16
16
|
regionMapView
|
package/package.json
CHANGED
|
@@ -376,7 +376,7 @@ export function ScaleBar({
|
|
|
376
376
|
aria-hidden
|
|
377
377
|
sx={{ position: 'absolute', left: 0, right: 0, bottom: rem(theme, 10), pointerEvents: 'none', zIndex: 1 }}
|
|
378
378
|
>
|
|
379
|
-
<Box component="span" sx={{ display: 'block', ml: rem(theme, 10), fontSize: rem(theme,
|
|
379
|
+
<Box component="span" sx={{ display: 'block', ml: rem(theme, 10), fontSize: rem(theme, 12), color: 'text.secondary' }}>
|
|
380
380
|
{copy.scale(metres)}
|
|
381
381
|
</Box>
|
|
382
382
|
<Box
|
|
File without changes
|
|
File without changes
|