@rio-cloud/rio-uikit 2.3.0-beta.2 → 2.3.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/Marker.js +9 -5
- package/Table.js +10 -9
- package/TableNext.js +10 -9
- package/TableRowActionsDropdown.d.ts +2 -0
- package/TableRowActionsDropdown.js +5 -0
- package/TableRowActionsDropdown.js.map +1 -0
- package/components/analyticsAnalysisOverlay/AnalyticsAnalysisBanner.d.ts +38 -3
- package/components/analyticsAnalysisOverlay/AnalyticsAnalysisBanner.js +104 -109
- package/components/analyticsAnalysisOverlay/AnalyticsAnalysisBanner.js.map +1 -1
- package/components/analyticsAnalysisOverlay/AnalyticsAnalysisOverlay.d.ts +24 -5
- package/components/analyticsAnalysisOverlay/AnalyticsAnalysisOverlay.js +60 -56
- package/components/analyticsAnalysisOverlay/AnalyticsAnalysisOverlay.js.map +1 -1
- package/components/datepicker/DayPicker.js +72 -70
- package/components/datepicker/DayPicker.js.map +1 -1
- package/components/datepicker/DayPickerDropdown.d.ts +1 -0
- package/components/datepicker/DayPickerDropdown.js +61 -48
- package/components/datepicker/DayPickerDropdown.js.map +1 -1
- package/components/datepicker/useStackedDayPickerCalendars.js +26 -26
- package/components/datepicker/useStackedDayPickerCalendars.js.map +1 -1
- package/components/dropdown/ButtonDropdown.d.ts +4 -0
- package/components/dropdown/ButtonDropdown.js +82 -80
- package/components/dropdown/ButtonDropdown.js.map +1 -1
- package/components/listMenu/ListMenu.d.ts +8 -0
- package/components/listMenu/ListMenu.js +74 -66
- package/components/listMenu/ListMenu.js.map +1 -1
- package/components/map/components/Map.js +207 -156
- package/components/map/components/Map.js.map +1 -1
- package/components/map/components/MapContext.d.ts +3 -0
- package/components/map/components/MapContext.js +9 -6
- package/components/map/components/MapContext.js.map +1 -1
- package/components/map/components/features/MapZoom.js +19 -19
- package/components/map/components/features/MapZoom.js.map +1 -1
- package/components/map/components/features/Route.d.ts +65 -1
- package/components/map/components/features/Route.js +184 -98
- package/components/map/components/features/Route.js.map +1 -1
- package/components/map/components/features/basics/Marker.d.ts +21 -1
- package/components/map/components/features/basics/Marker.js +99 -40
- package/components/map/components/features/basics/Marker.js.map +1 -1
- package/components/map/components/features/basics/Polygon.d.ts +24 -1
- package/components/map/components/features/basics/Polygon.js +72 -19
- package/components/map/components/features/basics/Polygon.js.map +1 -1
- package/components/map/components/features/basics/Polyline.d.ts +29 -0
- package/components/map/components/features/basics/Polyline.js +69 -39
- package/components/map/components/features/basics/Polyline.js.map +1 -1
- package/components/map/components/features/layers/MarkerLayer.js +8 -8
- package/components/map/components/features/layers/MarkerLayer.js.map +1 -1
- package/components/map/components/features/layers/clustering/SimpleClusterLayer.js +13 -6
- package/components/map/components/features/layers/clustering/SimpleClusterLayer.js.map +1 -1
- package/components/map/utils/clustering.d.ts +1 -1
- package/components/map/utils/clustering.js +30 -30
- package/components/map/utils/clustering.js.map +1 -1
- package/components/map/utils/mapTypes.d.ts +141 -0
- package/components/map/utils/mapTypes.js.map +1 -1
- package/components/map/utils/mapUtils.d.ts +2 -0
- package/components/map/utils/mapUtils.js +4 -0
- package/components/map/utils/mapUtils.js.map +1 -1
- package/components/mapMarker/ClusterMapMarker.d.ts +2 -0
- package/components/mapMarker/ClusterMapMarker.js.map +1 -1
- package/components/mapMarker/SingleMapMarker.d.ts +2 -0
- package/components/mapMarker/SingleMapMarker.js.map +1 -1
- package/components/selects/ClearButton.js +9 -7
- package/components/selects/ClearButton.js.map +1 -1
- package/components/table/Table.d.ts +3 -1
- package/components/table/Table.js +239 -216
- package/components/table/Table.js.map +1 -1
- package/components/table/Table.types.d.ts +62 -4
- package/components/table/TableColumn.d.ts +8 -1
- package/components/table/TableColumn.js +66 -64
- package/components/table/TableColumn.js.map +1 -1
- package/components/table/TableExpandedRow.d.ts +4 -0
- package/components/table/TableExpandedRow.js +70 -67
- package/components/table/TableExpandedRow.js.map +1 -1
- package/components/table/TableGroupRow.d.ts +3 -1
- package/components/table/TableGroupRow.js +15 -14
- package/components/table/TableGroupRow.js.map +1 -1
- package/components/table/TableHeader.d.ts +9 -0
- package/components/table/TableHeader.js +110 -81
- package/components/table/TableHeader.js.map +1 -1
- package/components/table/TableHeaderColumn.d.ts +11 -1
- package/components/table/TableHeaderColumn.js +63 -58
- package/components/table/TableHeaderColumn.js.map +1 -1
- package/components/table/TableRow.d.ts +12 -0
- package/components/table/TableRow.js +78 -74
- package/components/table/TableRow.js.map +1 -1
- package/components/table/TableRowActionsDropdown.d.ts +11 -0
- package/components/table/TableRowActionsDropdown.js +22 -0
- package/components/table/TableRowActionsDropdown.js.map +1 -0
- package/components/table/TableStickyRowButton.d.ts +25 -0
- package/components/table/TableStickyRowButton.js +32 -0
- package/components/table/TableStickyRowButton.js.map +1 -0
- package/components/table/TableToolbar.d.ts +24 -3
- package/components/table/TableToolbar.js +78 -37
- package/components/table/TableToolbar.js.map +1 -1
- package/components/table/TableViewToggles.js +5 -5
- package/components/table/TableViewToggles.js.map +1 -1
- package/components/table/context/TableInteractionContext.d.ts +3 -0
- package/components/table/context/TableInteractionContext.js.map +1 -1
- package/components/table/context/TableLayoutContext.d.ts +1 -0
- package/components/table/context/TableLayoutContext.js.map +1 -1
- package/components/table/context/TableRenderContext.d.ts +1 -0
- package/components/table/context/TableRenderContext.js.map +1 -1
- package/components/table/layout/useHorizontalSectionSync.d.ts +2 -1
- package/components/table/layout/useHorizontalSectionSync.js +32 -31
- package/components/table/layout/useHorizontalSectionSync.js.map +1 -1
- package/components/table/layout/useMeasuredColumnMaxWidths.js +52 -54
- package/components/table/layout/useMeasuredColumnMaxWidths.js.map +1 -1
- package/components/table/layout/useTableLayout.d.ts +6 -2
- package/components/table/layout/useTableLayout.js +61 -48
- package/components/table/layout/useTableLayout.js.map +1 -1
- package/components/table/layout/useTableVirtualization.js +51 -56
- package/components/table/layout/useTableVirtualization.js.map +1 -1
- package/components/table/model/resolveResponsiveViewType.d.ts +2 -0
- package/components/table/model/resolveResponsiveViewType.js +27 -0
- package/components/table/model/resolveResponsiveViewType.js.map +1 -0
- package/components/table/render/header/TableDraggableHeaderCell.js +38 -36
- package/components/table/render/header/TableDraggableHeaderCell.js.map +1 -1
- package/components/table/render/header/TableHeader.types.d.ts +2 -0
- package/components/table/render/header/TableHeaderCellContent.js +16 -16
- package/components/table/render/header/TableHeaderCellContent.js.map +1 -1
- package/components/table/render/header/TableHeaderSelectionCell.d.ts +1 -0
- package/components/table/render/header/TableHeaderSelectionCell.js +13 -12
- package/components/table/render/header/TableHeaderSelectionCell.js.map +1 -1
- package/components/table/render/header/TableStaticHeaderCell.js +31 -29
- package/components/table/render/header/TableStaticHeaderCell.js.map +1 -1
- package/components/table/render/header/resolveHeaderCellClassName.d.ts +1 -0
- package/components/table/render/header/resolveHeaderCellClassName.js +10 -9
- package/components/table/render/header/resolveHeaderCellClassName.js.map +1 -1
- package/components/table/runtime/useResolvedRenderColumns.d.ts +4 -4
- package/components/table/runtime/useResolvedRenderColumns.js +13 -13
- package/components/table/runtime/useResolvedRenderColumns.js.map +1 -1
- package/components/table/runtime/useResolvedRenderHeader.d.ts +1 -1
- package/components/table/runtime/useResolvedRenderHeader.js.map +1 -1
- package/components/table/runtime/useResponsiveResolvedViewType.d.ts +23 -0
- package/components/table/runtime/useResponsiveResolvedViewType.js +22 -0
- package/components/table/runtime/useResponsiveResolvedViewType.js.map +1 -0
- package/components/table/selection/useInternalTableSelectionState.d.ts +2 -0
- package/components/table/selection/useInternalTableSelectionState.js +27 -17
- package/components/table/selection/useInternalTableSelectionState.js.map +1 -1
- package/components/table/selection/useTableSelection.d.ts +5 -1
- package/components/table/selection/useTableSelection.js +37 -26
- package/components/table/selection/useTableSelection.js.map +1 -1
- package/components/table/shared/parsePixelSize.d.ts +2 -0
- package/components/table/shared/parsePixelSize.js +13 -0
- package/components/table/shared/parsePixelSize.js.map +1 -0
- package/hooks/useDraggableElement.d.ts +27 -5
- package/hooks/useDraggableElement.js +100 -23
- package/hooks/useDraggableElement.js.map +1 -1
- package/hooks/usePopperDropdown.d.ts +1 -0
- package/hooks/usePopperDropdown.js +15 -12
- package/hooks/usePopperDropdown.js.map +1 -1
- package/hooks/useResizeObserver.d.ts +25 -6
- package/hooks/useResizeObserver.js +20 -18
- package/hooks/useResizeObserver.js.map +1 -1
- package/package.json +10 -10
- package/utils/analytics/createAnalyticsOverlayTooltip.js.map +1 -1
- package/utils/init/initConfig.js +5 -5
- package/utils/init/initConfig.js.map +1 -1
- package/version.d.ts +1 -1
- package/version.js +2 -2
- package/version.js.map +1 -1
|
@@ -1,49 +1,126 @@
|
|
|
1
|
-
import { useState as
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { useState as M, useRef as C, useEffect as Y, useCallback as H, useLayoutEffect as N } from "react";
|
|
2
|
+
import { createPortal as O } from "react-dom";
|
|
3
|
+
import { getOrCreatePortalRoot as W } from "../utils/portalRoot.js";
|
|
4
|
+
const y = 4, v = "is-dragging", s = (a, e, o) => Math.min(o, Math.max(e, a)), R = (a) => a?.current?.getBoundingClientRect() ?? null, I = (a, e, o) => a === "container" && o ? {
|
|
5
|
+
top: s(
|
|
6
|
+
(o.height - e.height) / 2,
|
|
7
|
+
0,
|
|
8
|
+
Math.max(0, o.height - e.height)
|
|
9
|
+
),
|
|
10
|
+
left: s(
|
|
11
|
+
(o.width - e.width) / 2,
|
|
12
|
+
0,
|
|
13
|
+
Math.max(0, o.width - e.width)
|
|
14
|
+
)
|
|
15
|
+
} : {
|
|
16
|
+
top: s(
|
|
17
|
+
(window.innerHeight - e.height) / 2,
|
|
18
|
+
0,
|
|
19
|
+
Math.max(0, window.innerHeight - e.height)
|
|
20
|
+
),
|
|
21
|
+
left: s(
|
|
22
|
+
(window.innerWidth - e.width) / 2,
|
|
23
|
+
0,
|
|
24
|
+
Math.max(0, window.innerWidth - e.width)
|
|
25
|
+
)
|
|
26
|
+
}, j = (a = {}) => {
|
|
27
|
+
const { positioning: e = "viewport", initialPosition: o, collisionContainerRef: d } = a, [u, D] = M(!1), [g, p] = M({ top: 0, left: 0, hasDragged: !1 }), [x, L] = M(null), h = C(null), w = C(null), c = e === "viewport";
|
|
28
|
+
Y(() => {
|
|
29
|
+
if (!c) {
|
|
30
|
+
L(null);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
L(W());
|
|
34
|
+
}, [c]);
|
|
35
|
+
const S = H(
|
|
36
|
+
(t, r) => {
|
|
37
|
+
if (!c)
|
|
38
|
+
return t;
|
|
39
|
+
const n = r ?? x;
|
|
40
|
+
return n ? O(t, n) : null;
|
|
41
|
+
},
|
|
42
|
+
[c, x]
|
|
43
|
+
);
|
|
44
|
+
N(() => {
|
|
45
|
+
if (g.hasDragged || !o)
|
|
46
|
+
return;
|
|
47
|
+
const t = h.current;
|
|
48
|
+
if (!t)
|
|
49
|
+
return;
|
|
50
|
+
const r = o === "center" ? I(
|
|
51
|
+
e,
|
|
52
|
+
t.getBoundingClientRect(),
|
|
53
|
+
R(d)
|
|
54
|
+
) : o;
|
|
55
|
+
p(
|
|
56
|
+
(n) => n.top === r.top && n.left === r.left ? n : { top: r.top, left: r.left, hasDragged: !1 }
|
|
57
|
+
);
|
|
58
|
+
}, [d, o, g.hasDragged, e]);
|
|
59
|
+
const T = H((t) => {
|
|
4
60
|
if (t.button !== 0)
|
|
5
61
|
return;
|
|
6
62
|
t.preventDefault(), t.stopPropagation();
|
|
7
|
-
const r =
|
|
63
|
+
const r = h.current;
|
|
8
64
|
if (!r)
|
|
9
65
|
return;
|
|
10
66
|
const n = r.getBoundingClientRect();
|
|
11
|
-
|
|
67
|
+
w.current = {
|
|
12
68
|
offsetX: t.clientX - n.left,
|
|
13
69
|
offsetY: t.clientY - n.top,
|
|
14
70
|
startX: t.clientX,
|
|
15
71
|
startY: t.clientY,
|
|
16
72
|
hasMoved: !1
|
|
17
|
-
},
|
|
73
|
+
}, D(!0);
|
|
18
74
|
}, []);
|
|
19
|
-
return
|
|
20
|
-
if (!
|
|
75
|
+
return Y(() => {
|
|
76
|
+
if (!u)
|
|
21
77
|
return;
|
|
22
78
|
const t = document.documentElement;
|
|
23
|
-
t.classList.add(
|
|
24
|
-
const r = (
|
|
25
|
-
const
|
|
26
|
-
if (!
|
|
79
|
+
t.classList.add(v);
|
|
80
|
+
const r = (B) => {
|
|
81
|
+
const i = w.current, P = h.current;
|
|
82
|
+
if (!i || !P)
|
|
83
|
+
return;
|
|
84
|
+
const { clientX: m, clientY: E } = B, _ = Math.hypot(m - i.startX, E - i.startY);
|
|
85
|
+
if (!i.hasMoved && _ < y)
|
|
27
86
|
return;
|
|
28
|
-
|
|
29
|
-
|
|
87
|
+
i.hasMoved || (i.hasMoved = !0);
|
|
88
|
+
const f = P.getBoundingClientRect(), l = R(d);
|
|
89
|
+
if (e === "container" && l) {
|
|
90
|
+
const A = s(
|
|
91
|
+
m - l.left - i.offsetX,
|
|
92
|
+
0,
|
|
93
|
+
Math.max(0, l.width - f.width)
|
|
94
|
+
), G = s(
|
|
95
|
+
E - l.top - i.offsetY,
|
|
96
|
+
0,
|
|
97
|
+
Math.max(0, l.height - f.height)
|
|
98
|
+
);
|
|
99
|
+
p({
|
|
100
|
+
top: G,
|
|
101
|
+
left: A,
|
|
102
|
+
hasDragged: !0
|
|
103
|
+
});
|
|
30
104
|
return;
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
top:
|
|
35
|
-
|
|
105
|
+
}
|
|
106
|
+
const X = {
|
|
107
|
+
left: s(m - i.offsetX, 0, Math.max(0, window.innerWidth - f.width)),
|
|
108
|
+
top: s(E - i.offsetY, 0, Math.max(0, window.innerHeight - f.height))
|
|
109
|
+
};
|
|
110
|
+
p({
|
|
111
|
+
top: X.top,
|
|
112
|
+
left: X.left,
|
|
36
113
|
hasDragged: !0
|
|
37
114
|
});
|
|
38
115
|
}, n = () => {
|
|
39
|
-
t.classList.remove(
|
|
116
|
+
t.classList.remove(v), D(!1), w.current = null;
|
|
40
117
|
};
|
|
41
118
|
return window.addEventListener("pointermove", r), window.addEventListener("pointerup", n), window.addEventListener("pointercancel", n), () => {
|
|
42
|
-
window.removeEventListener("pointermove", r), window.removeEventListener("pointerup", n), window.removeEventListener("pointercancel", n), t.classList.remove(
|
|
119
|
+
window.removeEventListener("pointermove", r), window.removeEventListener("pointerup", n), window.removeEventListener("pointercancel", n), t.classList.remove(v);
|
|
43
120
|
};
|
|
44
|
-
}, [
|
|
121
|
+
}, [d, u, e]), { draggableRef: h, isDragging: u, position: g, onDragHandleDown: T, renderElement: S };
|
|
45
122
|
};
|
|
46
123
|
export {
|
|
47
|
-
|
|
124
|
+
j as default
|
|
48
125
|
};
|
|
49
126
|
//# sourceMappingURL=useDraggableElement.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDraggableElement.js","sources":["../../src/hooks/useDraggableElement.ts"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type MutableRefObject,\n type PointerEvent as ReactPointerEvent,\n} from 'react';\n\nexport type DraggablePosition = {\n /**\n * Top offset in pixels relative to the viewport.\n */\n top: number;\n\n /**\n * Left offset in pixels relative to the viewport.\n */\n left: number;\n\n /**\n * Indicates whether the element has been moved by dragging at least once.\n */\n hasDragged: boolean;\n};\n\nexport type UseDraggableResult<T extends HTMLElement> = {\n /**\n * Ref that must be attached to the draggable element container.\n */\n draggableRef: MutableRefObject<T | null>;\n\n /**\n * Indicates whether a drag interaction is currently active.\n */\n isDragging: boolean;\n\n /**\n * Current draggable coordinates and drag-state metadata.\n */\n position: DraggablePosition;\n\n /**\n * Pointer down handler for the dedicated drag handle element.\n */\n onDragHandlePointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n};\n\ntype DraggableState = {\n offsetX: number;\n offsetY: number;\n startX: number;\n startY: number;\n hasMoved: boolean;\n};\n\nconst MOVEMENT_THRESHOLD_PX = 4;\nconst DRAGGING_CLASS_NAME = 'is-dragging';\n\nconst clampToRange = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));\n\nconst useDraggableElement = <T extends HTMLElement = HTMLDivElement>(): UseDraggableResult<T> => {\n const [isDragging, setIsDragging] = useState(false);\n const [position, setPosition] = useState<DraggablePosition>({ top: 0, left: 0, hasDragged: false });\n\n const draggableRef = useRef<T | null>(null);\n const dragStateRef = useRef<DraggableState | null>(null);\n\n const onDragHandlePointerDown = useCallback((event: ReactPointerEvent<HTMLElement>) => {\n if (event.button !== 0) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n const draggableElement = draggableRef.current;\n if (!draggableElement) {\n return;\n }\n\n const rect = draggableElement.getBoundingClientRect();\n dragStateRef.current = {\n offsetX: event.clientX - rect.left,\n offsetY: event.clientY - rect.top,\n startX: event.clientX,\n startY: event.clientY,\n hasMoved: false,\n };\n setIsDragging(true);\n }, []);\n\n useEffect(() => {\n if (!isDragging) {\n return;\n }\n\n const rootElement = document.documentElement;\n rootElement.classList.add(DRAGGING_CLASS_NAME);\n\n const handlePointerMove = (event: PointerEvent) => {\n const dragState = dragStateRef.current;\n const draggableElement = draggableRef.current;\n if (!dragState || !draggableElement) {\n return;\n }\n\n const movedDistance = Math.hypot(event.clientX - dragState.startX, event.clientY - dragState.startY);\n if (!dragState.hasMoved && movedDistance < MOVEMENT_THRESHOLD_PX) {\n return;\n }\n\n if (!dragState.hasMoved) {\n dragState.hasMoved = true;\n }\n\n const rect = draggableElement.getBoundingClientRect();\n const maxLeft = Math.max(0, window.innerWidth - rect.width);\n const maxTop = Math.max(0, window.innerHeight - rect.height);\n const nextLeft = clampToRange(event.clientX - dragState.offsetX, 0, maxLeft);\n const nextTop = clampToRange(event.clientY - dragState.offsetY, 0, maxTop);\n\n setPosition({\n top: nextTop,\n left: nextLeft,\n hasDragged: true,\n });\n };\n\n const handlePointerRelease = () => {\n rootElement.classList.remove(DRAGGING_CLASS_NAME);\n setIsDragging(false);\n dragStateRef.current = null;\n };\n\n window.addEventListener('pointermove', handlePointerMove);\n window.addEventListener('pointerup', handlePointerRelease);\n window.addEventListener('pointercancel', handlePointerRelease);\n\n return () => {\n window.removeEventListener('pointermove', handlePointerMove);\n window.removeEventListener('pointerup', handlePointerRelease);\n window.removeEventListener('pointercancel', handlePointerRelease);\n rootElement.classList.remove(DRAGGING_CLASS_NAME);\n };\n }, [isDragging]);\n\n return { draggableRef, isDragging, position, onDragHandlePointerDown };\n};\n\nexport default useDraggableElement;\n"],"names":["MOVEMENT_THRESHOLD_PX","DRAGGING_CLASS_NAME","clampToRange","value","min","max","useDraggableElement","isDragging","setIsDragging","useState","position","setPosition","draggableRef","useRef","dragStateRef","onDragHandlePointerDown","useCallback","event","draggableElement","rect","useEffect","rootElement","handlePointerMove","dragState","movedDistance","maxLeft","maxTop","nextLeft","nextTop","handlePointerRelease"],"mappings":";AAwDA,MAAMA,IAAwB,GACxBC,IAAsB,eAEtBC,IAAe,CAACC,GAAeC,GAAaC,MAAgB,KAAK,IAAIA,GAAK,KAAK,IAAID,GAAKD,CAAK,CAAC,GAE9FG,IAAsB,MAAqE;AAC7F,QAAM,CAACC,GAAYC,CAAa,IAAIC,EAAS,EAAK,GAC5C,CAACC,GAAUC,CAAW,IAAIF,EAA4B,EAAE,KAAK,GAAG,MAAM,GAAG,YAAY,GAAA,CAAO,GAE5FG,IAAeC,EAAiB,IAAI,GACpCC,IAAeD,EAA8B,IAAI,GAEjDE,IAA0BC,EAAY,CAACC,MAA0C;AACnF,QAAIA,EAAM,WAAW;AACjB;AAGJ,IAAAA,EAAM,eAAA,GACNA,EAAM,gBAAA;AAEN,UAAMC,IAAmBN,EAAa;AACtC,QAAI,CAACM;AACD;AAGJ,UAAMC,IAAOD,EAAiB,sBAAA;AAC9B,IAAAJ,EAAa,UAAU;AAAA,MACnB,SAASG,EAAM,UAAUE,EAAK;AAAA,MAC9B,SAASF,EAAM,UAAUE,EAAK;AAAA,MAC9B,QAAQF,EAAM;AAAA,MACd,QAAQA,EAAM;AAAA,MACd,UAAU;AAAA,IAAA,GAEdT,EAAc,EAAI;AAAA,EACtB,GAAG,CAAA,CAAE;AAEL,SAAAY,EAAU,MAAM;AACZ,QAAI,CAACb;AACD;AAGJ,UAAMc,IAAc,SAAS;AAC7B,IAAAA,EAAY,UAAU,IAAIpB,CAAmB;AAE7C,UAAMqB,IAAoB,CAACL,MAAwB;AAC/C,YAAMM,IAAYT,EAAa,SACzBI,IAAmBN,EAAa;AACtC,UAAI,CAACW,KAAa,CAACL;AACf;AAGJ,YAAMM,IAAgB,KAAK,MAAMP,EAAM,UAAUM,EAAU,QAAQN,EAAM,UAAUM,EAAU,MAAM;AACnG,UAAI,CAACA,EAAU,YAAYC,IAAgBxB;AACvC;AAGJ,MAAKuB,EAAU,aACXA,EAAU,WAAW;AAGzB,YAAMJ,IAAOD,EAAiB,sBAAA,GACxBO,IAAU,KAAK,IAAI,GAAG,OAAO,aAAaN,EAAK,KAAK,GACpDO,IAAS,KAAK,IAAI,GAAG,OAAO,cAAcP,EAAK,MAAM,GACrDQ,IAAWzB,EAAae,EAAM,UAAUM,EAAU,SAAS,GAAGE,CAAO,GACrEG,IAAU1B,EAAae,EAAM,UAAUM,EAAU,SAAS,GAAGG,CAAM;AAEzE,MAAAf,EAAY;AAAA,QACR,KAAKiB;AAAA,QACL,MAAMD;AAAA,QACN,YAAY;AAAA,MAAA,CACf;AAAA,IACL,GAEME,IAAuB,MAAM;AAC/B,MAAAR,EAAY,UAAU,OAAOpB,CAAmB,GAChDO,EAAc,EAAK,GACnBM,EAAa,UAAU;AAAA,IAC3B;AAEA,kBAAO,iBAAiB,eAAeQ,CAAiB,GACxD,OAAO,iBAAiB,aAAaO,CAAoB,GACzD,OAAO,iBAAiB,iBAAiBA,CAAoB,GAEtD,MAAM;AACT,aAAO,oBAAoB,eAAeP,CAAiB,GAC3D,OAAO,oBAAoB,aAAaO,CAAoB,GAC5D,OAAO,oBAAoB,iBAAiBA,CAAoB,GAChER,EAAY,UAAU,OAAOpB,CAAmB;AAAA,IACpD;AAAA,EACJ,GAAG,CAACM,CAAU,CAAC,GAER,EAAE,cAAAK,GAAc,YAAAL,GAAY,UAAAG,GAAU,yBAAAK,EAAA;AACjD;"}
|
|
1
|
+
{"version":3,"file":"useDraggableElement.js","sources":["../../src/hooks/useDraggableElement.ts"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type MutableRefObject,\n type PointerEvent as ReactPointerEvent,\n type ReactNode,\n type RefObject,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { getOrCreatePortalRoot } from '../utils/portalRoot';\n\nexport type DraggablePosition = {\n /**\n * Top offset in pixels relative to the active positioning context.\n */\n top: number;\n\n /**\n * Left offset in pixels relative to the active positioning context.\n */\n left: number;\n\n /**\n * Indicates whether the element has been moved by dragging at least once.\n */\n hasDragged: boolean;\n};\n\nexport type UseDraggableResult<T extends HTMLElement> = {\n /**\n * Ref that must be attached to the draggable element container.\n */\n draggableRef: MutableRefObject<T | null>;\n\n /**\n * Indicates whether a drag interaction is currently active.\n */\n isDragging: boolean;\n\n /**\n * Current draggable coordinates and drag-state metadata.\n */\n position: DraggablePosition;\n\n /**\n * Pointer down handler for the dedicated drag handle element.\n */\n onDragHandleDown: (event: ReactPointerEvent<HTMLElement>) => void;\n\n /**\n * Renders the provided element through the shared portal root in viewport mode.\n * An optional custom target can be passed for specialized overlay hosts.\n * In container mode, the element is returned unchanged and this helper is usually not needed.\n */\n renderElement: (element: ReactNode, target?: HTMLElement | null) => ReactNode;\n};\n\nexport type UseDraggableElementOptions = {\n /**\n * Defines whether drag coordinates are resolved against the viewport or a collision container.\n * Viewport mode also enables portal rendering via `renderElement`.\n */\n positioning?: 'viewport' | 'container';\n\n /**\n * Optional initial position for the draggable element.\n * Use `center` to center the element inside the active positioning context on mount.\n */\n initialPosition?: 'center' | Pick<DraggablePosition, 'top' | 'left'>;\n\n /**\n * Optional container whose visible client rect is used as the drag boundary in container mode.\n */\n collisionContainerRef?: RefObject<HTMLElement | null>;\n};\n\ntype DraggableState = {\n offsetX: number;\n offsetY: number;\n startX: number;\n startY: number;\n hasMoved: boolean;\n};\n\nconst MOVEMENT_THRESHOLD_PX = 4;\nconst DRAGGING_CLASS_NAME = 'is-dragging';\n\nconst clampToRange = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));\n\nconst resolveCollisionContainerRect = (collisionContainerRef?: RefObject<HTMLElement | null>) =>\n collisionContainerRef?.current?.getBoundingClientRect() ?? null;\n\nconst resolveCenteredPosition = (\n positioning: UseDraggableElementOptions['positioning'],\n draggableRect: DOMRect,\n collisionContainerRect: DOMRect | null\n) => {\n if (positioning === 'container' && collisionContainerRect) {\n return {\n top: clampToRange(\n (collisionContainerRect.height - draggableRect.height) / 2,\n 0,\n Math.max(0, collisionContainerRect.height - draggableRect.height)\n ),\n left: clampToRange(\n (collisionContainerRect.width - draggableRect.width) / 2,\n 0,\n Math.max(0, collisionContainerRect.width - draggableRect.width)\n ),\n };\n }\n\n return {\n top: clampToRange(\n (window.innerHeight - draggableRect.height) / 2,\n 0,\n Math.max(0, window.innerHeight - draggableRect.height)\n ),\n left: clampToRange(\n (window.innerWidth - draggableRect.width) / 2,\n 0,\n Math.max(0, window.innerWidth - draggableRect.width)\n ),\n };\n};\n\nconst useDraggableElement = <T extends HTMLElement = HTMLDivElement>(\n options: UseDraggableElementOptions = {}\n): UseDraggableResult<T> => {\n const { positioning = 'viewport', initialPosition, collisionContainerRef } = options;\n\n const [isDragging, setIsDragging] = useState(false);\n const [position, setPosition] = useState<DraggablePosition>({ top: 0, left: 0, hasDragged: false });\n const [portalRoot, setPortalRoot] = useState<HTMLElement | null>(null);\n\n const draggableRef = useRef<T | null>(null);\n const dragStateRef = useRef<DraggableState | null>(null);\n const portalEnabled = positioning === 'viewport';\n\n useEffect(() => {\n if (!portalEnabled) {\n setPortalRoot(null);\n return;\n }\n\n setPortalRoot(getOrCreatePortalRoot());\n }, [portalEnabled]);\n\n const renderElement = useCallback(\n (element: ReactNode, target?: HTMLElement | null) => {\n if (!portalEnabled) {\n return element;\n }\n\n const renderTarget = target ?? portalRoot;\n return renderTarget ? createPortal(element, renderTarget) : null;\n },\n [portalEnabled, portalRoot]\n );\n\n useLayoutEffect(() => {\n if (position.hasDragged || !initialPosition) {\n return;\n }\n\n const draggableElement = draggableRef.current;\n if (!draggableElement) {\n return;\n }\n\n const nextPosition =\n initialPosition === 'center'\n ? resolveCenteredPosition(\n positioning,\n draggableElement.getBoundingClientRect(),\n resolveCollisionContainerRect(collisionContainerRef)\n )\n : initialPosition;\n\n setPosition(currentPosition =>\n currentPosition.top === nextPosition.top && currentPosition.left === nextPosition.left\n ? currentPosition\n : { top: nextPosition.top, left: nextPosition.left, hasDragged: false }\n );\n }, [collisionContainerRef, initialPosition, position.hasDragged, positioning]);\n\n const onDragHandleDown = useCallback((event: ReactPointerEvent<HTMLElement>) => {\n if (event.button !== 0) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n const draggableElement = draggableRef.current;\n if (!draggableElement) {\n return;\n }\n\n const rect = draggableElement.getBoundingClientRect();\n dragStateRef.current = {\n offsetX: event.clientX - rect.left,\n offsetY: event.clientY - rect.top,\n startX: event.clientX,\n startY: event.clientY,\n hasMoved: false,\n };\n setIsDragging(true);\n }, []);\n\n useEffect(() => {\n if (!isDragging) {\n return;\n }\n\n const rootElement = document.documentElement;\n rootElement.classList.add(DRAGGING_CLASS_NAME);\n\n const handlePointerMove = (event: PointerEvent) => {\n const dragState = dragStateRef.current;\n const draggableElement = draggableRef.current;\n if (!dragState || !draggableElement) {\n return;\n }\n\n const { clientX, clientY } = event;\n\n const movedDistance = Math.hypot(clientX - dragState.startX, clientY - dragState.startY);\n if (!dragState.hasMoved && movedDistance < MOVEMENT_THRESHOLD_PX) {\n return;\n }\n\n if (!dragState.hasMoved) {\n dragState.hasMoved = true;\n }\n\n const rect = draggableElement.getBoundingClientRect();\n const collisionContainerRect = resolveCollisionContainerRect(collisionContainerRef);\n\n if (positioning === 'container' && collisionContainerRect) {\n const nextLeftPos = clampToRange(\n clientX - collisionContainerRect.left - dragState.offsetX,\n 0,\n Math.max(0, collisionContainerRect.width - rect.width)\n );\n\n const nextTopPos = clampToRange(\n clientY - collisionContainerRect.top - dragState.offsetY,\n 0,\n Math.max(0, collisionContainerRect.height - rect.height)\n );\n\n setPosition({\n top: nextTopPos,\n left: nextLeftPos,\n hasDragged: true,\n });\n\n return;\n }\n\n const nextPosition = {\n left: clampToRange(clientX - dragState.offsetX, 0, Math.max(0, window.innerWidth - rect.width)),\n top: clampToRange(clientY - dragState.offsetY, 0, Math.max(0, window.innerHeight - rect.height)),\n };\n\n setPosition({\n top: nextPosition.top,\n left: nextPosition.left,\n hasDragged: true,\n });\n };\n\n const handlePointerRelease = () => {\n rootElement.classList.remove(DRAGGING_CLASS_NAME);\n setIsDragging(false);\n dragStateRef.current = null;\n };\n\n window.addEventListener('pointermove', handlePointerMove);\n window.addEventListener('pointerup', handlePointerRelease);\n window.addEventListener('pointercancel', handlePointerRelease);\n\n return () => {\n window.removeEventListener('pointermove', handlePointerMove);\n window.removeEventListener('pointerup', handlePointerRelease);\n window.removeEventListener('pointercancel', handlePointerRelease);\n rootElement.classList.remove(DRAGGING_CLASS_NAME);\n };\n }, [collisionContainerRef, isDragging, positioning]);\n\n return { draggableRef, isDragging, position, onDragHandleDown, renderElement };\n};\n\nexport default useDraggableElement;\n"],"names":["MOVEMENT_THRESHOLD_PX","DRAGGING_CLASS_NAME","clampToRange","value","min","max","resolveCollisionContainerRect","collisionContainerRef","resolveCenteredPosition","positioning","draggableRect","collisionContainerRect","useDraggableElement","options","initialPosition","isDragging","setIsDragging","useState","position","setPosition","portalRoot","setPortalRoot","draggableRef","useRef","dragStateRef","portalEnabled","useEffect","getOrCreatePortalRoot","renderElement","useCallback","element","target","renderTarget","createPortal","useLayoutEffect","draggableElement","nextPosition","currentPosition","onDragHandleDown","event","rect","rootElement","handlePointerMove","dragState","clientX","clientY","movedDistance","nextLeftPos","nextTopPos","handlePointerRelease"],"mappings":"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"}
|
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
import { useRef as
|
|
2
|
-
import { usePopper as
|
|
3
|
-
const
|
|
4
|
-
const
|
|
1
|
+
import { useRef as d, useState as o, useCallback as i } from "react";
|
|
2
|
+
import { usePopper as b } from "react-popper";
|
|
3
|
+
const R = ({ placement: s = "bottom-start" } = {}) => {
|
|
4
|
+
const p = d(null), [r, n] = o(null), [l, t] = o(!1), e = b(p.current, r, {
|
|
5
5
|
placement: s
|
|
6
|
-
})
|
|
6
|
+
}), u = () => t(!0), c = () => t(!1), a = () => t((m) => !m), f = i(() => {
|
|
7
|
+
e.update?.();
|
|
8
|
+
}, [e.update]);
|
|
7
9
|
return {
|
|
8
10
|
isOpen: l,
|
|
9
|
-
open:
|
|
10
|
-
close:
|
|
11
|
-
toggle:
|
|
12
|
-
|
|
11
|
+
open: u,
|
|
12
|
+
close: c,
|
|
13
|
+
toggle: a,
|
|
14
|
+
update: f,
|
|
15
|
+
referenceRef: p,
|
|
13
16
|
popperElementRef: n,
|
|
14
|
-
popperStyles:
|
|
15
|
-
popperAttributes:
|
|
17
|
+
popperStyles: e.styles.popper,
|
|
18
|
+
popperAttributes: e.attributes.popper
|
|
16
19
|
};
|
|
17
20
|
};
|
|
18
21
|
export {
|
|
19
|
-
|
|
22
|
+
R as default
|
|
20
23
|
};
|
|
21
24
|
//# sourceMappingURL=usePopperDropdown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePopperDropdown.js","sources":["../../src/hooks/usePopperDropdown.ts"],"sourcesContent":["import { type CSSProperties, useRef, useState } from 'react';\nimport { usePopper } from 'react-popper';\n\ntype UsePopperDropdownResult = {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n referenceRef: any;\n popperElementRef: (el: HTMLElement | null) => void;\n popperStyles: CSSProperties;\n popperAttributes: Record<string, any>;\n};\n\ntype UsePopperDropdownParams = {\n placement?: 'bottom-start' | 'bottom-end';\n};\n\nconst usePopperDropdown = ({ placement = 'bottom-start' }: UsePopperDropdownParams = {}) => {\n const referenceRef = useRef<HTMLElement>(null);\n const [popperElement, setPopperElement] = useState<HTMLElement | null>(null);\n const [isOpen, setIsOpen] = useState(false);\n\n const popper = usePopper(referenceRef.current, popperElement, {\n placement,\n });\n\n const open = () => setIsOpen(true);\n const close = () => setIsOpen(false);\n const toggle = () => setIsOpen(prev => !prev);\n\n return {\n isOpen,\n open,\n close,\n toggle,\n referenceRef,\n popperElementRef: setPopperElement,\n popperStyles: popper.styles.popper,\n popperAttributes: popper.attributes.popper,\n } as UsePopperDropdownResult;\n};\n\nexport default usePopperDropdown;\n"],"names":["usePopperDropdown","placement","referenceRef","useRef","popperElement","setPopperElement","useState","isOpen","setIsOpen","popper","usePopper","prev"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"usePopperDropdown.js","sources":["../../src/hooks/usePopperDropdown.ts"],"sourcesContent":["import { type CSSProperties, useCallback, useRef, useState } from 'react';\nimport { usePopper } from 'react-popper';\n\ntype UsePopperDropdownResult = {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n update: () => void;\n referenceRef: any;\n popperElementRef: (el: HTMLElement | null) => void;\n popperStyles: CSSProperties;\n popperAttributes: Record<string, any>;\n};\n\ntype UsePopperDropdownParams = {\n placement?: 'bottom-start' | 'bottom-end';\n};\n\nconst usePopperDropdown = ({ placement = 'bottom-start' }: UsePopperDropdownParams = {}) => {\n const referenceRef = useRef<HTMLElement>(null);\n const [popperElement, setPopperElement] = useState<HTMLElement | null>(null);\n const [isOpen, setIsOpen] = useState(false);\n\n const popper = usePopper(referenceRef.current, popperElement, {\n placement,\n });\n\n const open = () => setIsOpen(true);\n const close = () => setIsOpen(false);\n const toggle = () => setIsOpen(prev => !prev);\n const update = useCallback(() => {\n void popper.update?.();\n }, [popper.update]);\n\n return {\n isOpen,\n open,\n close,\n toggle,\n update,\n referenceRef,\n popperElementRef: setPopperElement,\n popperStyles: popper.styles.popper,\n popperAttributes: popper.attributes.popper,\n } as UsePopperDropdownResult;\n};\n\nexport default usePopperDropdown;\n"],"names":["usePopperDropdown","placement","referenceRef","useRef","popperElement","setPopperElement","useState","isOpen","setIsOpen","popper","usePopper","open","close","toggle","prev","update","useCallback"],"mappings":";;AAmBA,MAAMA,IAAoB,CAAC,EAAE,WAAAC,IAAY,eAAA,IAA4C,CAAA,MAAO;AACxF,QAAMC,IAAeC,EAAoB,IAAI,GACvC,CAACC,GAAeC,CAAgB,IAAIC,EAA6B,IAAI,GACrE,CAACC,GAAQC,CAAS,IAAIF,EAAS,EAAK,GAEpCG,IAASC,EAAUR,EAAa,SAASE,GAAe;AAAA,IAC1D,WAAAH;AAAA,EAAA,CACH,GAEKU,IAAO,MAAMH,EAAU,EAAI,GAC3BI,IAAQ,MAAMJ,EAAU,EAAK,GAC7BK,IAAS,MAAML,EAAU,CAAAM,MAAQ,CAACA,CAAI,GACtCC,IAASC,EAAY,MAAM;AAC7B,IAAKP,EAAO,SAAA;AAAA,EAChB,GAAG,CAACA,EAAO,MAAM,CAAC;AAElB,SAAO;AAAA,IACH,QAAAF;AAAA,IACA,MAAAI;AAAA,IACA,OAAAC;AAAA,IACA,QAAAC;AAAA,IACA,QAAAE;AAAA,IACA,cAAAb;AAAA,IACA,kBAAkBG;AAAA,IAClB,cAAcI,EAAO,OAAO;AAAA,IAC5B,kBAAkBA,EAAO,WAAW;AAAA,EAAA;AAE5C;"}
|
|
@@ -1,10 +1,29 @@
|
|
|
1
1
|
import { MutableRefObject } from 'react';
|
|
2
|
-
|
|
3
|
-
* Custom hook for observing element resize.
|
|
4
|
-
* @returns
|
|
5
|
-
*/
|
|
6
|
-
declare const useResizeObserver: <T extends HTMLElement = HTMLDivElement>() => [MutableRefObject<T | null>, ResizeObserverEntry | null, {
|
|
2
|
+
export type UseResizeObserverSize = {
|
|
7
3
|
blockSize: number | undefined;
|
|
8
4
|
inlineSize: number | undefined;
|
|
9
|
-
}
|
|
5
|
+
};
|
|
6
|
+
export type UseResizeObserverReturn<T extends HTMLElement = HTMLDivElement> = [
|
|
7
|
+
MutableRefObject<T | null>,
|
|
8
|
+
ResizeObserverEntry | null,
|
|
9
|
+
UseResizeObserverSize
|
|
10
|
+
];
|
|
11
|
+
/**
|
|
12
|
+
* Observes size changes of an element with `ResizeObserver`.
|
|
13
|
+
*
|
|
14
|
+
* Use the returned `ref` for the common case where the hook owns the observed element.
|
|
15
|
+
* Alternatively, pass an existing element via `observedElement` to observe it directly.
|
|
16
|
+
*
|
|
17
|
+
* The third tuple item exposes `inlineSize` and `blockSize` with a `borderBoxSize` first
|
|
18
|
+
* strategy and falls back to `contentRect` when needed.
|
|
19
|
+
*
|
|
20
|
+
* @template T The observed element type. Defaults to `HTMLDivElement`.
|
|
21
|
+
* @param observedElement Optional existing DOM element to observe instead of the returned ref target.
|
|
22
|
+
* @returns `[ref, observerEntry, size]`
|
|
23
|
+
*
|
|
24
|
+
* `ref` is the ref object for the observed element when the hook owns that element.
|
|
25
|
+
* `observerEntry` is `null` until the first resize notification arrives.
|
|
26
|
+
* `size` contains `inlineSize` and `blockSize`, preferring `borderBoxSize` and falling back to `contentRect`.
|
|
27
|
+
*/
|
|
28
|
+
declare const useResizeObserver: <T extends HTMLElement = HTMLDivElement>(observedElement?: T | null) => UseResizeObserverReturn<T>;
|
|
10
29
|
export default useResizeObserver;
|
|
@@ -1,26 +1,28 @@
|
|
|
1
|
-
import { useState as
|
|
1
|
+
import { useState as k, useRef as a, useCallback as d, useLayoutEffect as v } from "react";
|
|
2
2
|
const c = (e) => {
|
|
3
|
-
const
|
|
3
|
+
const t = e?.borderBoxSize?.at(0);
|
|
4
4
|
return {
|
|
5
|
-
blockSize:
|
|
6
|
-
inlineSize:
|
|
5
|
+
blockSize: t?.blockSize ?? e?.contentRect.height,
|
|
6
|
+
inlineSize: t?.inlineSize ?? e?.contentRect.width
|
|
7
7
|
};
|
|
8
|
-
},
|
|
9
|
-
const [
|
|
10
|
-
o.current = new ResizeObserver(([
|
|
11
|
-
|
|
12
|
-
if (!
|
|
13
|
-
return
|
|
14
|
-
const
|
|
15
|
-
return
|
|
8
|
+
}, g = (e) => {
|
|
9
|
+
const [t, f] = k(null), s = a(null), o = a(null), r = d(() => o.current?.disconnect(), []), l = d(() => {
|
|
10
|
+
o.current = new ResizeObserver(([n]) => {
|
|
11
|
+
f((i) => {
|
|
12
|
+
if (!i)
|
|
13
|
+
return n;
|
|
14
|
+
const b = c(i), u = c(n);
|
|
15
|
+
return i.target === n.target && b.blockSize === u.blockSize && b.inlineSize === u.inlineSize ? i : n;
|
|
16
16
|
});
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
});
|
|
18
|
+
const S = e ?? s.current;
|
|
19
|
+
S && o.current.observe(S);
|
|
20
|
+
}, [e]);
|
|
21
|
+
v(() => (r(), l(), () => r()), [r, l]);
|
|
22
|
+
const z = c(t);
|
|
21
23
|
return [
|
|
24
|
+
s,
|
|
22
25
|
t,
|
|
23
|
-
e,
|
|
24
26
|
{
|
|
25
27
|
blockSize: z.blockSize,
|
|
26
28
|
inlineSize: z.inlineSize
|
|
@@ -28,6 +30,6 @@ const c = (e) => {
|
|
|
28
30
|
];
|
|
29
31
|
};
|
|
30
32
|
export {
|
|
31
|
-
|
|
33
|
+
g as default
|
|
32
34
|
};
|
|
33
35
|
//# sourceMappingURL=useResizeObserver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useResizeObserver.js","sources":["../../src/hooks/useResizeObserver.ts"],"sourcesContent":["// inspired from https://tobbelindstrom.com/blog/resize-observer-hook/\n\nimport { useRef, useLayoutEffect, useState, useCallback, type MutableRefObject } from 'react';\n\nconst getObservedSize = (entry: ResizeObserverEntry | null) => {\n const borderBoxSize = entry?.borderBoxSize?.at(0);\n\n return {\n blockSize: borderBoxSize?.blockSize ?? entry?.contentRect.height,\n inlineSize: borderBoxSize?.inlineSize ?? entry?.contentRect.width,\n };\n};\n\
|
|
1
|
+
{"version":3,"file":"useResizeObserver.js","sources":["../../src/hooks/useResizeObserver.ts"],"sourcesContent":["// inspired from https://tobbelindstrom.com/blog/resize-observer-hook/\n\nimport { useRef, useLayoutEffect, useState, useCallback, type MutableRefObject } from 'react';\n\nconst getObservedSize = (entry: ResizeObserverEntry | null) => {\n const borderBoxSize = entry?.borderBoxSize?.at(0);\n\n return {\n blockSize: borderBoxSize?.blockSize ?? entry?.contentRect.height,\n inlineSize: borderBoxSize?.inlineSize ?? entry?.contentRect.width,\n };\n};\n\nexport type UseResizeObserverSize = {\n blockSize: number | undefined;\n inlineSize: number | undefined;\n};\n\nexport type UseResizeObserverReturn<T extends HTMLElement = HTMLDivElement> = [\n MutableRefObject<T | null>,\n ResizeObserverEntry | null,\n UseResizeObserverSize,\n];\n\n/**\n * Observes size changes of an element with `ResizeObserver`.\n *\n * Use the returned `ref` for the common case where the hook owns the observed element.\n * Alternatively, pass an existing element via `observedElement` to observe it directly.\n *\n * The third tuple item exposes `inlineSize` and `blockSize` with a `borderBoxSize` first\n * strategy and falls back to `contentRect` when needed.\n *\n * @template T The observed element type. Defaults to `HTMLDivElement`.\n * @param observedElement Optional existing DOM element to observe instead of the returned ref target.\n * @returns `[ref, observerEntry, size]`\n *\n * `ref` is the ref object for the observed element when the hook owns that element.\n * `observerEntry` is `null` until the first resize notification arrives.\n * `size` contains `inlineSize` and `blockSize`, preferring `borderBoxSize` and falling back to `contentRect`.\n */\nconst useResizeObserver = <T extends HTMLElement = HTMLDivElement>(\n observedElement?: T | null\n): UseResizeObserverReturn<T> => {\n const [observerEntry, setObserverEntry] = useState<ResizeObserverEntry | null>(null);\n\n const nodeRef = useRef<T | null>(null);\n\n const observer = useRef<ResizeObserver | null>(null);\n\n const disconnect = useCallback(() => observer.current?.disconnect(), []);\n\n const observe = useCallback(() => {\n observer.current = new ResizeObserver(([entry]) => {\n setObserverEntry(previousEntry => {\n if (!previousEntry) {\n return entry;\n }\n\n const previousSize = getObservedSize(previousEntry);\n const nextSize = getObservedSize(entry);\n\n return previousEntry.target === entry.target &&\n previousSize.blockSize === nextSize.blockSize &&\n previousSize.inlineSize === nextSize.inlineSize\n ? previousEntry\n : entry;\n });\n });\n const targetElement = observedElement ?? nodeRef.current;\n\n if (targetElement) {\n observer.current.observe(targetElement);\n }\n }, [observedElement]);\n\n useLayoutEffect(() => {\n disconnect();\n observe();\n return () => disconnect();\n }, [disconnect, observe]);\n\n const observedSize = getObservedSize(observerEntry);\n\n return [\n nodeRef,\n observerEntry,\n {\n blockSize: observedSize.blockSize,\n inlineSize: observedSize.inlineSize,\n },\n ];\n};\nexport default useResizeObserver;\n"],"names":["getObservedSize","entry","borderBoxSize","useResizeObserver","observedElement","observerEntry","setObserverEntry","useState","nodeRef","useRef","observer","disconnect","useCallback","observe","previousEntry","previousSize","nextSize","targetElement","useLayoutEffect","observedSize"],"mappings":";AAIA,MAAMA,IAAkB,CAACC,MAAsC;AAC3D,QAAMC,IAAgBD,GAAO,eAAe,GAAG,CAAC;AAEhD,SAAO;AAAA,IACH,WAAWC,GAAe,aAAaD,GAAO,YAAY;AAAA,IAC1D,YAAYC,GAAe,cAAcD,GAAO,YAAY;AAAA,EAAA;AAEpE,GA8BME,IAAoB,CACtBC,MAC6B;AAC7B,QAAM,CAACC,GAAeC,CAAgB,IAAIC,EAAqC,IAAI,GAE7EC,IAAUC,EAAiB,IAAI,GAE/BC,IAAWD,EAA8B,IAAI,GAE7CE,IAAaC,EAAY,MAAMF,EAAS,SAAS,WAAA,GAAc,EAAE,GAEjEG,IAAUD,EAAY,MAAM;AAC9B,IAAAF,EAAS,UAAU,IAAI,eAAe,CAAC,CAACT,CAAK,MAAM;AAC/C,MAAAK,EAAiB,CAAAQ,MAAiB;AAC9B,YAAI,CAACA;AACD,iBAAOb;AAGX,cAAMc,IAAef,EAAgBc,CAAa,GAC5CE,IAAWhB,EAAgBC,CAAK;AAEtC,eAAOa,EAAc,WAAWb,EAAM,UAClCc,EAAa,cAAcC,EAAS,aACpCD,EAAa,eAAeC,EAAS,aACnCF,IACAb;AAAA,MACV,CAAC;AAAA,IACL,CAAC;AACD,UAAMgB,IAAgBb,KAAmBI,EAAQ;AAEjD,IAAIS,KACAP,EAAS,QAAQ,QAAQO,CAAa;AAAA,EAE9C,GAAG,CAACb,CAAe,CAAC;AAEpB,EAAAc,EAAgB,OACZP,EAAA,GACAE,EAAA,GACO,MAAMF,EAAA,IACd,CAACA,GAAYE,CAAO,CAAC;AAExB,QAAMM,IAAenB,EAAgBK,CAAa;AAElD,SAAO;AAAA,IACHG;AAAA,IACAH;AAAA,IACA;AAAA,MACI,WAAWc,EAAa;AAAA,MACxB,YAAYA,EAAa;AAAA,IAAA;AAAA,EAC7B;AAER;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rio-cloud/rio-uikit",
|
|
3
|
-
"version": "2.3.0
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "The RIO UIKIT component library",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@biomejs/biome": "2.4.
|
|
49
|
+
"@biomejs/biome": "2.4.12",
|
|
50
50
|
"@rio-cloud/biome-config": "1.2.0",
|
|
51
51
|
"@rio-cloud/vite-plugin-frontend-license-check": "3.0.0",
|
|
52
52
|
"@testing-library/dom": "10.4.1",
|
|
@@ -60,15 +60,15 @@
|
|
|
60
60
|
"@types/react-redux": "7.1.34",
|
|
61
61
|
"@types/resize-observer-browser": "0.1.11",
|
|
62
62
|
"@vitejs/plugin-react": "5.1.4",
|
|
63
|
-
"@vitest/coverage-v8": "^4.1.
|
|
64
|
-
"autoprefixer": "10.
|
|
63
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
64
|
+
"autoprefixer": "10.5.0",
|
|
65
65
|
"backstopjs": "6.3.25",
|
|
66
|
-
"dotenv": "17.
|
|
66
|
+
"dotenv": "17.4.2",
|
|
67
67
|
"glob": "13.0.6",
|
|
68
|
-
"happy-dom": "20.
|
|
68
|
+
"happy-dom": "20.9.0",
|
|
69
69
|
"jsdom": "27.4.0",
|
|
70
70
|
"jsdom-global": "3.0.2",
|
|
71
|
-
"postcss": "8.5.
|
|
71
|
+
"postcss": "8.5.10",
|
|
72
72
|
"postcss-preset-env": "8.5.1",
|
|
73
73
|
"postcss-short": "5.0.0",
|
|
74
74
|
"pre-commit": "1.2.2",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"react-dom": "18.0.0",
|
|
77
77
|
"react-intl": "7.1.14",
|
|
78
78
|
"rollup-plugin-copy": "3.5.0",
|
|
79
|
-
"sass": "1.
|
|
79
|
+
"sass": "1.99.0",
|
|
80
80
|
"strip-ansi": "7.2.0",
|
|
81
81
|
"svgo": "4.0.1",
|
|
82
82
|
"typescript": "5.9.3",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"@dnd-kit/utilities": "3.2.2",
|
|
98
98
|
"@formkit/auto-animate": "0.9.0",
|
|
99
99
|
"@popperjs/core": "2.11.8",
|
|
100
|
-
"@tanstack/react-virtual": "3.13.
|
|
100
|
+
"@tanstack/react-virtual": "3.13.24",
|
|
101
101
|
"date-fns": "4.1.0",
|
|
102
102
|
"driver.js": "1.4.0",
|
|
103
103
|
"es-toolkit": "1.45.1",
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"react-onclickoutside": "6.13.2",
|
|
120
120
|
"react-popper": "2.3.0",
|
|
121
121
|
"react-toastify": "11.0.5",
|
|
122
|
-
"recharts": "3.8.
|
|
122
|
+
"recharts": "3.8.1",
|
|
123
123
|
"tiny-invariant": "1.3.3",
|
|
124
124
|
"tslib": "2.8.1"
|
|
125
125
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createAnalyticsOverlayTooltip.js","sources":["../../../src/utils/analytics/createAnalyticsOverlayTooltip.ts"],"sourcesContent":["type AnalyticsOverlayTooltipTrackingData = {\n eventAction: string;\n eventLabel: string;\n eventTrigger: 'click' | 'visibility';\n};\n\nconst CAMPAIGN_QUERY_PARAM_CONFIG = [\n { queryParam: 'utm_source', label: 'Source' },\n { queryParam: 'utm_medium', label: 'Medium' },\n { queryParam: 'utm_campaign', label: 'Campaign' },\n { queryParam: 'utm_content', label: 'Content' },\n { queryParam: 'utm_term', label: 'Term' },\n] as const;\n\ntype CampaignQueryParam = (typeof CAMPAIGN_QUERY_PARAM_CONFIG)[number]['queryParam'];\ntype AnalyticsOverlayTooltipCampaignData = Partial<Record<CampaignQueryParam, string>>;\n\ntype CreateAnalyticsOverlayTooltipProps = {\n overlayRoot: HTMLElement;\n trackingData: AnalyticsOverlayTooltipTrackingData;\n totalEventCount: number;\n totalUserCount: number;\n analyticsTotalUsers: number | null;\n clickEvent: MouseEvent;\n trackedElement: HTMLElement;\n};\n\nconst numberFormatter = new Intl.NumberFormat('en-US', {\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n});\n\nconst createIcon = (iconClass: string, sizeClass: string) => {\n const icon = document.createElement('span');\n icon.classList.add('rioglyph', iconClass, sizeClass);\n return icon;\n};\n\nconst createTitle = (props: { iconClass: string; text: string }) => {\n const { iconClass, text } = props;\n const title = document.createElement('div');\n title.classList.add(\n 'display-flex',\n 'align-items-center',\n 'gap-5',\n 'text-medium',\n 'text-size-16',\n 'line-height-16',\n 'margin-bottom--3'\n );\n title.appendChild(createIcon(iconClass, 'text-size-16'));\n\n const titleText = document.createElement('span');\n titleText.textContent = text;\n title.appendChild(titleText);\n\n return title;\n};\n\nconst createPanel = () => {\n const panel = document.createElement('div');\n panel.classList.add('rounded', 'padding-10', 'bg-decent', 'display-flex', 'flex-column', 'gap-5', 'shadow-accent');\n return panel;\n};\n\nconst createInfoRow = (props: { iconClass: string; label: string; right: Node | string }) => {\n const { iconClass, label, right } = props;\n\n const row = document.createElement('div');\n row.classList.add('display-flex', 'align-items-center', 'gap-5');\n\n const leftContainer = document.createElement('div');\n leftContainer.classList.add('display-flex', 'align-items-center', 'gap-5', 'min-width-80');\n\n const icon = createIcon(iconClass, 'text-size-14');\n leftContainer.appendChild(icon);\n\n const labelNode = document.createElement('div');\n labelNode.classList.add('text-medium');\n labelNode.textContent = label;\n leftContainer.appendChild(labelNode);\n row.appendChild(leftContainer);\n\n const rightContainer = document.createElement('div');\n rightContainer.classList.add('flex-1-1', 'text-right');\n\n if (typeof right === 'string') {\n const rightText = document.createElement('div');\n rightText.classList.add('word-break-all', 'text-bold');\n rightText.textContent = right;\n rightContainer.appendChild(rightText);\n } else {\n rightContainer.appendChild(right);\n }\n\n row.appendChild(rightContainer);\n return row;\n};\n\nconst formatPercentage = (value: number | null) => (value === null ? 'n/a' : `${numberFormatter.format(value)}%`);\n\nconst getUrlParsingBaseHref = () => {\n if (typeof window !== 'undefined' && /^https?:/i.test(window.location.href)) {\n return window.location.href;\n }\n\n return 'https://rio.cloud';\n};\n\nexport const extractCampaignTrackingDataFromHref = (\n href: string,\n baseHref = getUrlParsingBaseHref()\n): AnalyticsOverlayTooltipCampaignData | null => {\n try {\n const url = new URL(href, baseHref);\n const campaignData: AnalyticsOverlayTooltipCampaignData = {};\n\n CAMPAIGN_QUERY_PARAM_CONFIG.forEach(({ queryParam }) => {\n const value = url.searchParams.get(queryParam)?.trim();\n if (value) {\n campaignData[queryParam] = value;\n }\n });\n\n return Object.keys(campaignData).length > 0 ? campaignData : null;\n } catch {\n return null;\n }\n};\n\nexport const extractCampaignTrackingDataFromElement = (trackedElement: HTMLElement) => {\n const anchorElement = trackedElement.closest<HTMLAnchorElement>('a[href]');\n const href = trackedElement.getAttribute('href')?.trim() ?? anchorElement?.href?.trim();\n\n if (!href) {\n return null;\n }\n\n return extractCampaignTrackingDataFromHref(href);\n};\n\nconst calculateAllUsersRatePercentage = (props: {\n eventTrigger: 'click' | 'visibility';\n totalEventCount: number;\n analyticsTotalUsers: number | null;\n}) => {\n const { eventTrigger, totalEventCount, analyticsTotalUsers } = props;\n\n if (analyticsTotalUsers === null || analyticsTotalUsers <= 0) {\n return null;\n }\n\n if (eventTrigger === 'click' || eventTrigger === 'visibility') {\n return (totalEventCount / analyticsTotalUsers) * 100;\n }\n\n return null;\n};\n\nexport const createAnalyticsOverlayTooltip = (props: CreateAnalyticsOverlayTooltipProps) => {\n const {\n overlayRoot,\n trackingData,\n totalEventCount,\n totalUserCount,\n analyticsTotalUsers,\n clickEvent,\n trackedElement,\n } = props;\n const tooltip = document.createElement('div');\n tooltip.setAttribute('data-analytics-overlay-tooltip', 'true');\n tooltip.classList.add(\n 'position-fixed',\n 'pointer-events-all',\n 'z-index-max',\n 'rounded',\n 'padding-15',\n 'shadow-focused',\n 'bg-secondary',\n 'text-color-white',\n 'max-width-350',\n 'width-100pct',\n 'word-break-all',\n 'display-flex',\n 'flex-column',\n 'gap-10',\n 'line-height-125rel'\n );\n\n const metricLabel = trackingData.eventTrigger === 'click' ? 'Clicks' : 'Views';\n const metricIconClass = trackingData.eventTrigger === 'click' ? 'rioglyph-click' : 'rioglyph-eye-open';\n const elementRateLabel = trackingData.eventTrigger === 'click' ? 'Click rate' : 'View rate';\n\n const elementRatePercentage = totalUserCount > 0 ? (totalEventCount / totalUserCount) * 100 : null;\n const allUsersRatePercentage = calculateAllUsersRatePercentage({\n eventTrigger: trackingData.eventTrigger,\n totalEventCount,\n analyticsTotalUsers,\n });\n const interactionRateAllUsersPercentage =\n analyticsTotalUsers !== null && analyticsTotalUsers > 0 ? (totalUserCount / analyticsTotalUsers) * 100 : null;\n\n const overallTitle = createTitle({\n iconClass: 'rioglyph-user',\n text: 'Event users',\n });\n tooltip.appendChild(overallTitle);\n\n const overallPanel = createPanel();\n overallPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-user',\n label: 'Event users',\n right: `${numberFormatter.format(totalUserCount)}`,\n })\n );\n if (analyticsTotalUsers !== null) {\n overallPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-user-group',\n label: 'Total users',\n right: `${numberFormatter.format(analyticsTotalUsers)}`,\n })\n );\n\n overallPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-bar-chart-box',\n label: 'Event rate (all users)',\n right: formatPercentage(interactionRateAllUsersPercentage),\n })\n );\n }\n tooltip.appendChild(overallPanel);\n\n const performanceTitle = createTitle({\n iconClass: 'rioglyph-stats',\n text: 'Element performance',\n });\n tooltip.appendChild(performanceTitle);\n\n const performancePanel = createPanel();\n performancePanel.appendChild(\n createInfoRow({\n iconClass: metricIconClass,\n label: metricLabel,\n right: `${numberFormatter.format(totalEventCount)}`,\n })\n );\n performancePanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-bar-chart-box',\n label: elementRateLabel,\n right: formatPercentage(elementRatePercentage),\n })\n );\n if (trackingData.eventTrigger === 'click' && analyticsTotalUsers !== null) {\n performancePanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-bar-chart-box',\n label: 'Click rate (all users)',\n right: formatPercentage(allUsersRatePercentage),\n })\n );\n }\n if (trackingData.eventTrigger === 'visibility' && analyticsTotalUsers !== null) {\n performancePanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-bar-chart-box',\n label: 'View rate (all users)',\n right: formatPercentage(allUsersRatePercentage),\n })\n );\n }\n tooltip.appendChild(performancePanel);\n\n const attributesHeader = createTitle({\n iconClass: 'rioglyph-info-sign',\n text: 'Tracking Attributes',\n });\n tooltip.appendChild(attributesHeader);\n\n const attributesPanel = createPanel();\n attributesPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-cog',\n label: 'Action',\n right: trackingData.eventAction,\n })\n );\n attributesPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-emergency-stop',\n label: 'Trigger',\n right: trackingData.eventTrigger,\n })\n );\n attributesPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-tag',\n label: 'Label',\n right: trackingData.eventLabel,\n })\n );\n tooltip.appendChild(attributesPanel);\n\n const campaignData = extractCampaignTrackingDataFromElement(trackedElement);\n if (campaignData) {\n const campaignHeader = createTitle({\n iconClass: 'rioglyph-megaphone',\n text: 'Campaign',\n });\n tooltip.appendChild(campaignHeader);\n\n const campaignPanel = createPanel();\n CAMPAIGN_QUERY_PARAM_CONFIG.forEach(({ queryParam, label }) => {\n const value = campaignData[queryParam];\n if (!value) {\n return;\n }\n\n campaignPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-tag',\n label,\n right: value,\n })\n );\n });\n\n tooltip.appendChild(campaignPanel);\n }\n\n const pointerOffset = 12;\n const viewportPadding = 8;\n overlayRoot.appendChild(tooltip);\n\n let left = clickEvent.clientX + pointerOffset;\n let top = clickEvent.clientY + pointerOffset;\n const maxLeft = window.innerWidth - tooltip.offsetWidth - viewportPadding;\n const maxTop = window.innerHeight - tooltip.offsetHeight - viewportPadding;\n left = Math.max(viewportPadding, Math.min(left, maxLeft));\n top = Math.max(viewportPadding, Math.min(top, maxTop));\n\n tooltip.style.left = `${left}px`;\n tooltip.style.top = `${top}px`;\n\n return tooltip;\n};\n\nexport type {\n AnalyticsOverlayTooltipCampaignData,\n AnalyticsOverlayTooltipTrackingData,\n CreateAnalyticsOverlayTooltipProps,\n};\n"],"names":["CAMPAIGN_QUERY_PARAM_CONFIG","numberFormatter","createIcon","iconClass","sizeClass","icon","createTitle","props","text","title","titleText","createPanel","panel","createInfoRow","label","right","row","leftContainer","labelNode","rightContainer","rightText","formatPercentage","value","getUrlParsingBaseHref","extractCampaignTrackingDataFromHref","href","baseHref","url","campaignData","queryParam","extractCampaignTrackingDataFromElement","trackedElement","anchorElement","calculateAllUsersRatePercentage","eventTrigger","totalEventCount","analyticsTotalUsers","createAnalyticsOverlayTooltip","overlayRoot","trackingData","totalUserCount","clickEvent","tooltip","metricLabel","metricIconClass","elementRateLabel","elementRatePercentage","allUsersRatePercentage","interactionRateAllUsersPercentage","overallTitle","overallPanel","performanceTitle","performancePanel","attributesHeader","attributesPanel","campaignHeader","campaignPanel","pointerOffset","viewportPadding","left","top","maxLeft","maxTop"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createAnalyticsOverlayTooltip.js","sources":["../../../src/utils/analytics/createAnalyticsOverlayTooltip.ts"],"sourcesContent":["type AnalyticsOverlayTooltipTrackingData = {\n eventAction: string;\n eventLabel: string;\n eventTrigger: 'click' | 'visibility';\n};\n\nconst CAMPAIGN_QUERY_PARAM_CONFIG = [\n { queryParam: 'utm_source', label: 'Source' },\n { queryParam: 'utm_medium', label: 'Medium' },\n { queryParam: 'utm_campaign', label: 'Campaign' },\n { queryParam: 'utm_content', label: 'Content' },\n { queryParam: 'utm_term', label: 'Term' },\n] as const;\n\ntype CampaignQueryParam = (typeof CAMPAIGN_QUERY_PARAM_CONFIG)[number]['queryParam'];\ntype AnalyticsOverlayTooltipCampaignData = Partial<Record<CampaignQueryParam, string>>;\n\ntype CreateAnalyticsOverlayTooltipProps = {\n overlayRoot: HTMLElement;\n trackingData: AnalyticsOverlayTooltipTrackingData;\n totalEventCount: number;\n totalUserCount: number;\n analyticsTotalUsers: number | null;\n clickEvent: MouseEvent;\n trackedElement: HTMLElement;\n};\n\nconst numberFormatter = new Intl.NumberFormat('en-US', {\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n});\n\nconst createIcon = (iconClass: string, sizeClass: string) => {\n const icon = document.createElement('span');\n icon.classList.add('rioglyph', iconClass, sizeClass);\n return icon;\n};\n\nconst createTitle = (props: { iconClass: string; text: string }) => {\n const { iconClass, text } = props;\n const title = document.createElement('div');\n title.classList.add(\n 'display-flex',\n 'align-items-center',\n 'gap-5',\n 'text-medium',\n 'text-size-16',\n 'line-height-16',\n 'margin-bottom--3'\n );\n title.appendChild(createIcon(iconClass, 'text-size-16'));\n\n const titleText = document.createElement('span');\n titleText.textContent = text;\n title.appendChild(titleText);\n\n return title;\n};\n\nconst createPanel = () => {\n const panel = document.createElement('div');\n panel.classList.add('rounded', 'padding-10', 'bg-decent', 'display-flex', 'flex-column', 'gap-5', 'shadow-accent');\n return panel;\n};\n\nconst createInfoRow = (props: { iconClass: string; label: string; right: Node | string }) => {\n const { iconClass, label, right } = props;\n\n const row = document.createElement('div');\n row.classList.add('display-flex', 'align-items-center', 'gap-5');\n\n const leftContainer = document.createElement('div');\n leftContainer.classList.add('display-flex', 'align-items-center', 'gap-5', 'min-width-80');\n\n const icon = createIcon(iconClass, 'text-size-14');\n leftContainer.appendChild(icon);\n\n const labelNode = document.createElement('div');\n labelNode.classList.add('text-medium');\n labelNode.textContent = label;\n leftContainer.appendChild(labelNode);\n row.appendChild(leftContainer);\n\n const rightContainer = document.createElement('div');\n rightContainer.classList.add('flex-1-1', 'text-right');\n\n if (typeof right === 'string') {\n const rightText = document.createElement('div');\n rightText.classList.add('word-break-all', 'text-bold');\n rightText.textContent = right;\n rightContainer.appendChild(rightText);\n } else {\n rightContainer.appendChild(right);\n }\n\n row.appendChild(rightContainer);\n return row;\n};\n\nconst formatPercentage = (value: number | null) => (value === null ? 'n/a' : `${numberFormatter.format(value)}%`);\n\nconst getUrlParsingBaseHref = () => {\n if (typeof window !== 'undefined' && /^https?:/i.test(window.location.href)) {\n return window.location.href;\n }\n\n return 'https://rio.cloud';\n};\n\nexport const extractCampaignTrackingDataFromHref = (\n href: string,\n baseHref = getUrlParsingBaseHref()\n): AnalyticsOverlayTooltipCampaignData | null => {\n try {\n const url = new URL(href, baseHref);\n const campaignData: AnalyticsOverlayTooltipCampaignData = {};\n\n CAMPAIGN_QUERY_PARAM_CONFIG.forEach(({ queryParam }) => {\n const value = url.searchParams.get(queryParam)?.trim();\n if (value) {\n campaignData[queryParam] = value;\n }\n });\n\n return Object.keys(campaignData).length > 0 ? campaignData : null;\n } catch {\n return null;\n }\n};\n\nexport const extractCampaignTrackingDataFromElement = (trackedElement: HTMLElement) => {\n const anchorElement = trackedElement.closest<HTMLAnchorElement>('a[href]');\n const href = trackedElement.getAttribute('href')?.trim() ?? anchorElement?.href?.trim();\n\n if (!href) {\n return null;\n }\n\n return extractCampaignTrackingDataFromHref(href);\n};\n\nconst calculateAllUsersRatePercentage = (props: {\n eventTrigger: 'click' | 'visibility';\n totalEventCount: number;\n analyticsTotalUsers: number | null;\n}) => {\n const { eventTrigger, totalEventCount, analyticsTotalUsers } = props;\n\n if (analyticsTotalUsers === null || analyticsTotalUsers <= 0) {\n return null;\n }\n\n if (eventTrigger === 'click' || eventTrigger === 'visibility') {\n return (totalEventCount / analyticsTotalUsers) * 100;\n }\n\n return null;\n};\n\nexport const createAnalyticsOverlayTooltip = (props: CreateAnalyticsOverlayTooltipProps) => {\n const {\n overlayRoot,\n trackingData,\n totalEventCount,\n totalUserCount,\n analyticsTotalUsers,\n clickEvent,\n trackedElement,\n } = props;\n\n const tooltip = document.createElement('div');\n\n tooltip.setAttribute('data-analytics-overlay-tooltip', 'true');\n\n tooltip.classList.add(\n 'position-fixed',\n 'pointer-events-all',\n 'z-index-max',\n 'rounded',\n 'padding-15',\n 'shadow-focused',\n 'bg-secondary',\n 'text-color-white',\n 'max-width-350',\n 'width-100pct',\n 'word-break-all',\n 'display-flex',\n 'flex-column',\n 'gap-10',\n 'line-height-125rel'\n );\n\n const metricLabel = trackingData.eventTrigger === 'click' ? 'Clicks' : 'Views';\n const metricIconClass = trackingData.eventTrigger === 'click' ? 'rioglyph-click' : 'rioglyph-eye-open';\n const elementRateLabel = trackingData.eventTrigger === 'click' ? 'Click rate' : 'View rate';\n\n const elementRatePercentage = totalUserCount > 0 ? (totalEventCount / totalUserCount) * 100 : null;\n\n const allUsersRatePercentage = calculateAllUsersRatePercentage({\n eventTrigger: trackingData.eventTrigger,\n totalEventCount,\n analyticsTotalUsers,\n });\n\n const interactionRateAllUsersPercentage =\n analyticsTotalUsers !== null && analyticsTotalUsers > 0 ? (totalUserCount / analyticsTotalUsers) * 100 : null;\n\n const overallTitle = createTitle({\n iconClass: 'rioglyph-user',\n text: 'Event users',\n });\n tooltip.appendChild(overallTitle);\n\n const overallPanel = createPanel();\n overallPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-user',\n label: 'Event users',\n right: `${numberFormatter.format(totalUserCount)}`,\n })\n );\n\n if (analyticsTotalUsers !== null) {\n overallPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-user-group',\n label: 'Total users',\n right: `${numberFormatter.format(analyticsTotalUsers)}`,\n })\n );\n\n overallPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-bar-chart-box',\n label: 'Event rate (all users)',\n right: formatPercentage(interactionRateAllUsersPercentage),\n })\n );\n }\n tooltip.appendChild(overallPanel);\n\n const performanceTitle = createTitle({\n iconClass: 'rioglyph-stats',\n text: 'Element performance',\n });\n tooltip.appendChild(performanceTitle);\n\n const performancePanel = createPanel();\n performancePanel.appendChild(\n createInfoRow({\n iconClass: metricIconClass,\n label: metricLabel,\n right: `${numberFormatter.format(totalEventCount)}`,\n })\n );\n performancePanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-bar-chart-box',\n label: elementRateLabel,\n right: formatPercentage(elementRatePercentage),\n })\n );\n\n if (trackingData.eventTrigger === 'click' && analyticsTotalUsers !== null) {\n performancePanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-bar-chart-box',\n label: 'Click rate (all users)',\n right: formatPercentage(allUsersRatePercentage),\n })\n );\n }\n\n if (trackingData.eventTrigger === 'visibility' && analyticsTotalUsers !== null) {\n performancePanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-bar-chart-box',\n label: 'View rate (all users)',\n right: formatPercentage(allUsersRatePercentage),\n })\n );\n }\n tooltip.appendChild(performancePanel);\n\n const attributesHeader = createTitle({\n iconClass: 'rioglyph-info-sign',\n text: 'Tracking Attributes',\n });\n tooltip.appendChild(attributesHeader);\n\n const attributesPanel = createPanel();\n attributesPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-cog',\n label: 'Action',\n right: trackingData.eventAction,\n })\n );\n attributesPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-emergency-stop',\n label: 'Trigger',\n right: trackingData.eventTrigger,\n })\n );\n attributesPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-tag',\n label: 'Label',\n right: trackingData.eventLabel,\n })\n );\n tooltip.appendChild(attributesPanel);\n\n const campaignData = extractCampaignTrackingDataFromElement(trackedElement);\n if (campaignData) {\n const campaignHeader = createTitle({\n iconClass: 'rioglyph-megaphone',\n text: 'Campaign',\n });\n tooltip.appendChild(campaignHeader);\n\n const campaignPanel = createPanel();\n CAMPAIGN_QUERY_PARAM_CONFIG.forEach(({ queryParam, label }) => {\n const value = campaignData[queryParam];\n if (!value) {\n return;\n }\n\n campaignPanel.appendChild(\n createInfoRow({\n iconClass: 'rioglyph-tag',\n label,\n right: value,\n })\n );\n });\n\n tooltip.appendChild(campaignPanel);\n }\n\n const pointerOffset = 12;\n const viewportPadding = 8;\n overlayRoot.appendChild(tooltip);\n\n let left = clickEvent.clientX + pointerOffset;\n let top = clickEvent.clientY + pointerOffset;\n const maxLeft = window.innerWidth - tooltip.offsetWidth - viewportPadding;\n const maxTop = window.innerHeight - tooltip.offsetHeight - viewportPadding;\n left = Math.max(viewportPadding, Math.min(left, maxLeft));\n top = Math.max(viewportPadding, Math.min(top, maxTop));\n\n tooltip.style.left = `${left}px`;\n tooltip.style.top = `${top}px`;\n\n return tooltip;\n};\n\nexport type {\n AnalyticsOverlayTooltipCampaignData,\n AnalyticsOverlayTooltipTrackingData,\n CreateAnalyticsOverlayTooltipProps,\n};\n"],"names":["CAMPAIGN_QUERY_PARAM_CONFIG","numberFormatter","createIcon","iconClass","sizeClass","icon","createTitle","props","text","title","titleText","createPanel","panel","createInfoRow","label","right","row","leftContainer","labelNode","rightContainer","rightText","formatPercentage","value","getUrlParsingBaseHref","extractCampaignTrackingDataFromHref","href","baseHref","url","campaignData","queryParam","extractCampaignTrackingDataFromElement","trackedElement","anchorElement","calculateAllUsersRatePercentage","eventTrigger","totalEventCount","analyticsTotalUsers","createAnalyticsOverlayTooltip","overlayRoot","trackingData","totalUserCount","clickEvent","tooltip","metricLabel","metricIconClass","elementRateLabel","elementRatePercentage","allUsersRatePercentage","interactionRateAllUsersPercentage","overallTitle","overallPanel","performanceTitle","performancePanel","attributesHeader","attributesPanel","campaignHeader","campaignPanel","pointerOffset","viewportPadding","left","top","maxLeft","maxTop"],"mappings":"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"}
|
package/utils/init/initConfig.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import o from "process";
|
|
2
2
|
import { inIframe as s } from "../deviceUtils.js";
|
|
3
|
-
o.env.NODE_ENV === "production" || location.protocol.startsWith("https");
|
|
4
|
-
const e = o.env.NODE_ENV === "test", c = s(), i = (t) => !e && console.debug(t);
|
|
3
|
+
const c = o.env.NODE_ENV === "production" || location.protocol.startsWith("https"), r = o.env.NODE_ENV === "test", i = s(), p = (t) => !r && console.debug(t);
|
|
5
4
|
export {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
p as debug,
|
|
6
|
+
i as isInIframe,
|
|
7
|
+
c as isProd,
|
|
8
|
+
r as isTest
|
|
9
9
|
};
|
|
10
10
|
//# sourceMappingURL=initConfig.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initConfig.js","sources":["../../../src/utils/init/initConfig.ts"],"sourcesContent":["import process from 'process';\n\nimport { inIframe } from '../deviceUtils';\n\n// Note: using import.meta.env.DEV does not work here due to backward compatibility with webpack and jest setups\nexport const isProd = process.env.NODE_ENV === 'production' || location.protocol.startsWith('https');\nexport const isTest = process.env.NODE_ENV === 'test';\n\nexport const isInIframe = inIframe();\n\nexport const debug = (message: string) => !isTest && console.debug(message);\n"],"names":["process","isTest","isInIframe","inIframe","debug","message"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"initConfig.js","sources":["../../../src/utils/init/initConfig.ts"],"sourcesContent":["import process from 'process';\n\nimport { inIframe } from '../deviceUtils';\n\n// Note: using import.meta.env.DEV does not work here due to backward compatibility with webpack and jest setups\nexport const isProd = process.env.NODE_ENV === 'production' || location.protocol.startsWith('https');\nexport const isTest = process.env.NODE_ENV === 'test';\n\nexport const isInIframe = inIframe();\n\nexport const debug = (message: string) => !isTest && console.debug(message);\n"],"names":["isProd","process","isTest","isInIframe","inIframe","debug","message"],"mappings":";;AAKO,MAAMA,IAASC,EAAQ,IAAI,aAAa,gBAAgB,SAAS,SAAS,WAAW,OAAO,GACtFC,IAASD,EAAQ,IAAI,aAAa,QAElCE,IAAaC,EAAA,GAEbC,IAAQ,CAACC,MAAoB,CAACJ,KAAU,QAAQ,MAAMI,CAAO;"}
|
package/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version: "2.3.0
|
|
1
|
+
export const version: "2.3.0";
|
package/version.js
CHANGED
package/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sources":["../src/version.js"],"sourcesContent":["export const version = '2.3.0
|
|
1
|
+
{"version":3,"file":"version.js","sources":["../src/version.js"],"sourcesContent":["export const version = '2.3.0';\n"],"names":["version"],"mappings":"AAAY,MAACA,IAAU;"}
|