@trackunit/react-map 0.2.48-alpha-90b6c9b97dd.0 → 0.2.48
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/index.cjs.js +12 -6
- package/index.esm.js +13 -7
- package/package.json +10 -10
- package/src/panel/Panel.d.ts +2 -1
- package/src/panel/PanelIconButton.d.ts +3 -2
package/index.cjs.js
CHANGED
|
@@ -700,12 +700,13 @@ const SHAPE_STYLE_DEFAULTS = {
|
|
|
700
700
|
const PANEL_ICON_BUTTON_CLASS_NAME = tailwindMerge.twMerge("inline-flex h-7 w-7 shrink-0 cursor-pointer items-center justify-center rounded-md border-0 bg-transparent p-1.5 text-neutral-600", "hover:bg-black/5 hover:text-neutral-700", "active:bg-black/10 active:text-neutral-800", "focus-visible:bg-black/10 focus-visible:text-neutral-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1", "disabled:cursor-not-allowed disabled:bg-transparent disabled:text-neutral-400");
|
|
701
701
|
/**
|
|
702
702
|
* Lightweight ghost icon button for map panel chrome. Skips `IconButton`'s
|
|
703
|
-
*
|
|
703
|
+
* Button stack so icon glyphs paint on the same frame as panel content, but
|
|
704
|
+
* still wraps the trigger in the shared `Tooltip` for hover labels.
|
|
704
705
|
*
|
|
705
706
|
* Consumers should pass decorative icons with `ariaHidden` and rely on
|
|
706
|
-
* `aria-label`
|
|
707
|
+
* `aria-label` for accessible naming and tooltip text.
|
|
707
708
|
*/
|
|
708
|
-
const PanelIconButton = ({ "aria-label": ariaLabel, children, disabled = false, onClick, "data-testid": dataTestId, }) => (jsxRuntime.jsx("button", { "aria-label": ariaLabel, className: PANEL_ICON_BUTTON_CLASS_NAME, "data-testid": dataTestId, disabled: disabled, onClick: onClick,
|
|
709
|
+
const PanelIconButton = ({ "aria-label": ariaLabel, children, disabled = false, onClick, "data-testid": dataTestId, }) => (jsxRuntime.jsx(reactComponents.Tooltip, { delayed: true, disabled: disabled, interactable: false, label: ariaLabel, children: jsxRuntime.jsx("button", { "aria-label": ariaLabel, className: PANEL_ICON_BUTTON_CLASS_NAME, "data-testid": dataTestId, disabled: disabled, onClick: onClick, type: "button", children: children }) }));
|
|
709
710
|
|
|
710
711
|
/**
|
|
711
712
|
* CSS `max-height` of the Panel shell — `min(320px, 40vh)`.
|
|
@@ -823,7 +824,8 @@ const PANEL_SCROLL_INTERNAL_CLASS_NAME = "flex flex-1 min-h-0 flex-col overflow-
|
|
|
823
824
|
* "" — element is in DOM (for Floating UI to measure) but hidden via
|
|
824
825
|
* CSS `visibility: hidden` so the pre-commit translate(0,0)
|
|
825
826
|
* position is never visible.
|
|
826
|
-
* "open" —
|
|
827
|
+
* "open" — appears instantly once placement is committed (no enter
|
|
828
|
+
* animation — see docs/adr/0027-instant-panel-first-paint.md).
|
|
827
829
|
* "closing" — fades out during the EXIT_DURATION_MS window before unmount.
|
|
828
830
|
*
|
|
829
831
|
* @internal
|
|
@@ -972,9 +974,9 @@ const Panel = ({ anchor, placement = DEFAULT_PLACEMENT$1, onDismiss, closeLabel
|
|
|
972
974
|
if (effectiveAnchor === null) {
|
|
973
975
|
return null;
|
|
974
976
|
}
|
|
975
|
-
// data-panel drives the CSS
|
|
977
|
+
// data-panel drives the CSS visibility state machine (Panel.css):
|
|
976
978
|
// "" — pre-commit: visibility:hidden so translate(0,0) is never seen
|
|
977
|
-
// "open" —
|
|
979
|
+
// "open" — instant appearance (no enter animation)
|
|
978
980
|
// "closing" — fade out before unmount
|
|
979
981
|
const panelState = isClosing ? "closing" : isCommitted ? "open" : "";
|
|
980
982
|
return (jsxRuntime.jsxs("div", { className: PANEL_SHELL_CLASS_NAME, "data-panel": panelState, ref: mergedShellRef, style: floatingStyles, ...getFloatingProps(), "aria-label": ariaLabel, children: [jsxRuntime.jsx("div", { className: PANEL_CHROME_CLASS_NAME, style: { maxHeight: `min(${PANEL_MAX_HEIGHT_PX}px, ${PANEL_MAX_HEIGHT_VH}vh)` }, children: jsxRuntime.jsx("div", { className: scrollSlotClassName, "data-testid": "panel-scroll-slot", ref: scrollRef, children: children }) }), onClickDismiss !== undefined ? (jsxRuntime.jsx("div", { className: "absolute right-0 top-0 z-10 -translate-y-1/2 translate-x-1/2 rounded-2xl border border-neutral-300 bg-white shadow-sm", children: jsxRuntime.jsx(PanelIconButton, { "aria-label": closeLabel, "data-testid": "panel-close-button", onClick: onClickDismiss, children: jsxRuntime.jsx(reactComponents.Icon, { ariaHidden: true, className: "text-neutral-700", name: "XMark", size: "small" }) }) })) : null] }));
|
|
@@ -2063,6 +2065,10 @@ const computePlacement = (triggerEl, containerEl) => {
|
|
|
2063
2065
|
const usePopoverPlacement = (triggerRef, containerRef, options = {}) => {
|
|
2064
2066
|
const { skip = false } = options;
|
|
2065
2067
|
const [placement, setPlacement] = react.useState(DEFAULT_PLACEMENT);
|
|
2068
|
+
// Post-paint measurement is sufficient: both callers invoke this hook where
|
|
2069
|
+
// the always-mounted trigger renders, so placement settles with the map —
|
|
2070
|
+
// long before a popover can open. A layout effect would only add pre-paint
|
|
2071
|
+
// measurement work during map load (SAGA-675 review).
|
|
2066
2072
|
react.useEffect(() => {
|
|
2067
2073
|
if (skip) {
|
|
2068
2074
|
return;
|
package/index.esm.js
CHANGED
|
@@ -4,7 +4,7 @@ import { INITIAL_CAMERA_STATE, INITIAL_MAP_STATUS, KEYBOARD_PAN_AMOUNT, KEYBOARD
|
|
|
4
4
|
export { ANCHOR_SELECTOR, DEFAULT_MAP_APPEARANCE, HIT_SURFACE_SELECTOR, INITIAL_CAMERA_STATE, INITIAL_INTERACTION_STATE, INITIAL_MAP_STATE, INITIAL_MAP_STATUS, computeMarkerDomPortalZIndex, defineAdapter, geometryTypeToShapeType, mapAppearanceSchema, mapThemeSchema, mapTypeSchema } from '@trackunit/react-map-adapter-shared';
|
|
5
5
|
import { useSyncExternalStore, useMemo, useState, useRef, useCallback, useLayoutEffect, useEffect, useReducer, createContext, useContext, memo, Suspense, useId, Fragment as Fragment$1, forwardRef } from 'react';
|
|
6
6
|
import { cvaMerge } from '@trackunit/css-class-variance-utilities';
|
|
7
|
-
import { useMergeRefs, Icon, Spinner, Text, useMeasure, useContainerBreakpoints, useDebounce, useWatch, useKeyboardShortcut,
|
|
7
|
+
import { Tooltip, useMergeRefs, Icon, Spinner, Text, useMeasure, useContainerBreakpoints, useDebounce, useWatch, useKeyboardShortcut, IconButton, ToggleGroup as ToggleGroup$1, useIsFullscreen, Popover, PopoverTrigger, PopoverContent, MoreMenu, useHover as useHover$1, cvaInteractableItem, useLocalStorageReducer } from '@trackunit/react-components';
|
|
8
8
|
import { twMerge } from 'tailwind-merge';
|
|
9
9
|
import { useFloating, autoUpdate, offset, flip, useHover, safePolygon, useInteractions, shift, hide, useDismiss, useRole } from '@floating-ui/react';
|
|
10
10
|
import { createPortal } from 'react-dom';
|
|
@@ -699,12 +699,13 @@ const SHAPE_STYLE_DEFAULTS = {
|
|
|
699
699
|
const PANEL_ICON_BUTTON_CLASS_NAME = twMerge("inline-flex h-7 w-7 shrink-0 cursor-pointer items-center justify-center rounded-md border-0 bg-transparent p-1.5 text-neutral-600", "hover:bg-black/5 hover:text-neutral-700", "active:bg-black/10 active:text-neutral-800", "focus-visible:bg-black/10 focus-visible:text-neutral-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1", "disabled:cursor-not-allowed disabled:bg-transparent disabled:text-neutral-400");
|
|
700
700
|
/**
|
|
701
701
|
* Lightweight ghost icon button for map panel chrome. Skips `IconButton`'s
|
|
702
|
-
*
|
|
702
|
+
* Button stack so icon glyphs paint on the same frame as panel content, but
|
|
703
|
+
* still wraps the trigger in the shared `Tooltip` for hover labels.
|
|
703
704
|
*
|
|
704
705
|
* Consumers should pass decorative icons with `ariaHidden` and rely on
|
|
705
|
-
* `aria-label`
|
|
706
|
+
* `aria-label` for accessible naming and tooltip text.
|
|
706
707
|
*/
|
|
707
|
-
const PanelIconButton = ({ "aria-label": ariaLabel, children, disabled = false, onClick, "data-testid": dataTestId, }) => (jsx("button", { "aria-label": ariaLabel, className: PANEL_ICON_BUTTON_CLASS_NAME, "data-testid": dataTestId, disabled: disabled, onClick: onClick,
|
|
708
|
+
const PanelIconButton = ({ "aria-label": ariaLabel, children, disabled = false, onClick, "data-testid": dataTestId, }) => (jsx(Tooltip, { delayed: true, disabled: disabled, interactable: false, label: ariaLabel, children: jsx("button", { "aria-label": ariaLabel, className: PANEL_ICON_BUTTON_CLASS_NAME, "data-testid": dataTestId, disabled: disabled, onClick: onClick, type: "button", children: children }) }));
|
|
708
709
|
|
|
709
710
|
/**
|
|
710
711
|
* CSS `max-height` of the Panel shell — `min(320px, 40vh)`.
|
|
@@ -822,7 +823,8 @@ const PANEL_SCROLL_INTERNAL_CLASS_NAME = "flex flex-1 min-h-0 flex-col overflow-
|
|
|
822
823
|
* "" — element is in DOM (for Floating UI to measure) but hidden via
|
|
823
824
|
* CSS `visibility: hidden` so the pre-commit translate(0,0)
|
|
824
825
|
* position is never visible.
|
|
825
|
-
* "open" —
|
|
826
|
+
* "open" — appears instantly once placement is committed (no enter
|
|
827
|
+
* animation — see docs/adr/0027-instant-panel-first-paint.md).
|
|
826
828
|
* "closing" — fades out during the EXIT_DURATION_MS window before unmount.
|
|
827
829
|
*
|
|
828
830
|
* @internal
|
|
@@ -971,9 +973,9 @@ const Panel = ({ anchor, placement = DEFAULT_PLACEMENT$1, onDismiss, closeLabel
|
|
|
971
973
|
if (effectiveAnchor === null) {
|
|
972
974
|
return null;
|
|
973
975
|
}
|
|
974
|
-
// data-panel drives the CSS
|
|
976
|
+
// data-panel drives the CSS visibility state machine (Panel.css):
|
|
975
977
|
// "" — pre-commit: visibility:hidden so translate(0,0) is never seen
|
|
976
|
-
// "open" —
|
|
978
|
+
// "open" — instant appearance (no enter animation)
|
|
977
979
|
// "closing" — fade out before unmount
|
|
978
980
|
const panelState = isClosing ? "closing" : isCommitted ? "open" : "";
|
|
979
981
|
return (jsxs("div", { className: PANEL_SHELL_CLASS_NAME, "data-panel": panelState, ref: mergedShellRef, style: floatingStyles, ...getFloatingProps(), "aria-label": ariaLabel, children: [jsx("div", { className: PANEL_CHROME_CLASS_NAME, style: { maxHeight: `min(${PANEL_MAX_HEIGHT_PX}px, ${PANEL_MAX_HEIGHT_VH}vh)` }, children: jsx("div", { className: scrollSlotClassName, "data-testid": "panel-scroll-slot", ref: scrollRef, children: children }) }), onClickDismiss !== undefined ? (jsx("div", { className: "absolute right-0 top-0 z-10 -translate-y-1/2 translate-x-1/2 rounded-2xl border border-neutral-300 bg-white shadow-sm", children: jsx(PanelIconButton, { "aria-label": closeLabel, "data-testid": "panel-close-button", onClick: onClickDismiss, children: jsx(Icon, { ariaHidden: true, className: "text-neutral-700", name: "XMark", size: "small" }) }) })) : null] }));
|
|
@@ -2062,6 +2064,10 @@ const computePlacement = (triggerEl, containerEl) => {
|
|
|
2062
2064
|
const usePopoverPlacement = (triggerRef, containerRef, options = {}) => {
|
|
2063
2065
|
const { skip = false } = options;
|
|
2064
2066
|
const [placement, setPlacement] = useState(DEFAULT_PLACEMENT);
|
|
2067
|
+
// Post-paint measurement is sufficient: both callers invoke this hook where
|
|
2068
|
+
// the always-mounted trigger renders, so placement settles with the map —
|
|
2069
|
+
// long before a popover can open. A layout effect would only add pre-paint
|
|
2070
|
+
// measurement work during map load (SAGA-675 review).
|
|
2065
2071
|
useEffect(() => {
|
|
2066
2072
|
if (skip) {
|
|
2067
2073
|
return;
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-map",
|
|
3
|
-
"version": "0.2.48
|
|
3
|
+
"version": "0.2.48",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=24.x"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@trackunit/react-components": "2.4.2
|
|
11
|
-
"@trackunit/css-class-variance-utilities": "1.13.92
|
|
12
|
-
"@trackunit/react-form-components": "2.3.8
|
|
13
|
-
"@trackunit/react-core-hooks": "1.19.7
|
|
14
|
-
"@trackunit/geo-json-utils": "1.14.95
|
|
15
|
-
"@trackunit/i18n-library-translation": "2.2.7
|
|
10
|
+
"@trackunit/react-components": "2.4.2",
|
|
11
|
+
"@trackunit/css-class-variance-utilities": "1.13.92",
|
|
12
|
+
"@trackunit/react-form-components": "2.3.8",
|
|
13
|
+
"@trackunit/react-core-hooks": "1.19.7",
|
|
14
|
+
"@trackunit/geo-json-utils": "1.14.95",
|
|
15
|
+
"@trackunit/i18n-library-translation": "2.2.7",
|
|
16
16
|
"react-minimal-pie-chart": "^8.4.0",
|
|
17
|
-
"@trackunit/react-map-adapter-shared": "0.0.76
|
|
18
|
-
"@trackunit/react-map-color-utils": "0.0.61
|
|
19
|
-
"@trackunit/ui-design-tokens": "1.13.91
|
|
17
|
+
"@trackunit/react-map-adapter-shared": "0.0.76",
|
|
18
|
+
"@trackunit/react-map-color-utils": "0.0.61",
|
|
19
|
+
"@trackunit/ui-design-tokens": "1.13.91",
|
|
20
20
|
"@floating-ui/react": "^0.26.25",
|
|
21
21
|
"es-toolkit": "^1.39.10",
|
|
22
22
|
"tailwind-merge": "^2.0.0",
|
package/src/panel/Panel.d.ts
CHANGED
|
@@ -56,7 +56,8 @@ export type PanelProps = Readonly<{
|
|
|
56
56
|
* "" — element is in DOM (for Floating UI to measure) but hidden via
|
|
57
57
|
* CSS `visibility: hidden` so the pre-commit translate(0,0)
|
|
58
58
|
* position is never visible.
|
|
59
|
-
* "open" —
|
|
59
|
+
* "open" — appears instantly once placement is committed (no enter
|
|
60
|
+
* animation — see docs/adr/0027-instant-panel-first-paint.md).
|
|
60
61
|
* "closing" — fades out during the EXIT_DURATION_MS window before unmount.
|
|
61
62
|
*
|
|
62
63
|
* @internal
|
|
@@ -8,9 +8,10 @@ export type PanelIconButtonProps = Readonly<{
|
|
|
8
8
|
}>;
|
|
9
9
|
/**
|
|
10
10
|
* Lightweight ghost icon button for map panel chrome. Skips `IconButton`'s
|
|
11
|
-
*
|
|
11
|
+
* Button stack so icon glyphs paint on the same frame as panel content, but
|
|
12
|
+
* still wraps the trigger in the shared `Tooltip` for hover labels.
|
|
12
13
|
*
|
|
13
14
|
* Consumers should pass decorative icons with `ariaHidden` and rely on
|
|
14
|
-
* `aria-label`
|
|
15
|
+
* `aria-label` for accessible naming and tooltip text.
|
|
15
16
|
*/
|
|
16
17
|
export declare const PanelIconButton: ({ "aria-label": ariaLabel, children, disabled, onClick, "data-testid": dataTestId, }: PanelIconButtonProps) => ReactElement;
|