inspect-ai 0.3.99__py3-none-any.whl → 0.3.101__py3-none-any.whl
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.
- inspect_ai/_cli/eval.py +2 -1
- inspect_ai/_display/core/config.py +11 -5
- inspect_ai/_display/core/panel.py +66 -2
- inspect_ai/_display/core/textual.py +5 -2
- inspect_ai/_display/plain/display.py +1 -0
- inspect_ai/_display/rich/display.py +2 -2
- inspect_ai/_display/textual/widgets/transcript.py +37 -9
- inspect_ai/_eval/eval.py +13 -1
- inspect_ai/_eval/evalset.py +3 -2
- inspect_ai/_eval/run.py +2 -0
- inspect_ai/_eval/score.py +2 -4
- inspect_ai/_eval/task/log.py +3 -1
- inspect_ai/_eval/task/run.py +59 -81
- inspect_ai/_util/content.py +11 -6
- inspect_ai/_util/interrupt.py +2 -2
- inspect_ai/_util/text.py +7 -0
- inspect_ai/_util/working.py +8 -37
- inspect_ai/_view/__init__.py +0 -0
- inspect_ai/_view/schema.py +2 -1
- inspect_ai/_view/www/CLAUDE.md +15 -0
- inspect_ai/_view/www/dist/assets/index.css +307 -171
- inspect_ai/_view/www/dist/assets/index.js +24733 -21641
- inspect_ai/_view/www/log-schema.json +77 -3
- inspect_ai/_view/www/package.json +9 -5
- inspect_ai/_view/www/src/@types/log.d.ts +9 -0
- inspect_ai/_view/www/src/app/App.tsx +1 -15
- inspect_ai/_view/www/src/app/appearance/icons.ts +4 -1
- inspect_ai/_view/www/src/app/content/MetaDataGrid.tsx +24 -6
- inspect_ai/_view/www/src/app/content/MetadataGrid.module.css +0 -5
- inspect_ai/_view/www/src/app/content/RenderedContent.tsx +220 -205
- inspect_ai/_view/www/src/app/log-view/LogViewContainer.tsx +2 -1
- inspect_ai/_view/www/src/app/log-view/tabs/SamplesTab.tsx +5 -0
- inspect_ai/_view/www/src/app/log-view/tabs/grouping.ts +4 -4
- inspect_ai/_view/www/src/app/routing/navigationHooks.ts +22 -25
- inspect_ai/_view/www/src/app/routing/url.ts +84 -4
- inspect_ai/_view/www/src/app/samples/InlineSampleDisplay.module.css +0 -5
- inspect_ai/_view/www/src/app/samples/SampleDialog.module.css +1 -1
- inspect_ai/_view/www/src/app/samples/SampleDisplay.module.css +7 -0
- inspect_ai/_view/www/src/app/samples/SampleDisplay.tsx +24 -17
- inspect_ai/_view/www/src/app/samples/SampleSummaryView.module.css +1 -2
- inspect_ai/_view/www/src/app/samples/chat/ChatMessage.tsx +8 -6
- inspect_ai/_view/www/src/app/samples/chat/ChatMessageRow.tsx +0 -4
- inspect_ai/_view/www/src/app/samples/chat/ChatViewVirtualList.tsx +3 -2
- inspect_ai/_view/www/src/app/samples/chat/MessageContent.tsx +2 -0
- inspect_ai/_view/www/src/app/samples/chat/MessageContents.tsx +2 -0
- inspect_ai/_view/www/src/app/samples/chat/messages.ts +1 -0
- inspect_ai/_view/www/src/app/samples/chat/tools/ToolCallView.tsx +1 -0
- inspect_ai/_view/www/src/app/samples/list/SampleList.tsx +17 -5
- inspect_ai/_view/www/src/app/samples/list/SampleRow.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/ErrorEventView.tsx +1 -2
- inspect_ai/_view/www/src/app/samples/transcript/InfoEventView.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/InputEventView.tsx +1 -2
- inspect_ai/_view/www/src/app/samples/transcript/ModelEventView.module.css +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/ModelEventView.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/SampleInitEventView.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/SampleLimitEventView.tsx +3 -2
- inspect_ai/_view/www/src/app/samples/transcript/SandboxEventView.tsx +4 -5
- inspect_ai/_view/www/src/app/samples/transcript/ScoreEventView.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/SpanEventView.tsx +1 -2
- inspect_ai/_view/www/src/app/samples/transcript/StepEventView.tsx +1 -3
- inspect_ai/_view/www/src/app/samples/transcript/SubtaskEventView.tsx +1 -2
- inspect_ai/_view/www/src/app/samples/transcript/ToolEventView.tsx +3 -4
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptPanel.module.css +42 -0
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptPanel.tsx +77 -0
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualList.tsx +27 -71
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualListComponent.module.css +13 -3
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualListComponent.tsx +27 -2
- inspect_ai/_view/www/src/app/samples/transcript/event/EventPanel.module.css +1 -0
- inspect_ai/_view/www/src/app/samples/transcript/event/EventPanel.tsx +21 -22
- inspect_ai/_view/www/src/app/samples/transcript/outline/OutlineRow.module.css +45 -0
- inspect_ai/_view/www/src/app/samples/transcript/outline/OutlineRow.tsx +223 -0
- inspect_ai/_view/www/src/app/samples/transcript/outline/TranscriptOutline.module.css +10 -0
- inspect_ai/_view/www/src/app/samples/transcript/outline/TranscriptOutline.tsx +258 -0
- inspect_ai/_view/www/src/app/samples/transcript/outline/tree-visitors.ts +187 -0
- inspect_ai/_view/www/src/app/samples/transcript/state/StateEventRenderers.tsx +8 -1
- inspect_ai/_view/www/src/app/samples/transcript/state/StateEventView.tsx +3 -4
- inspect_ai/_view/www/src/app/samples/transcript/transform/hooks.ts +78 -0
- inspect_ai/_view/www/src/app/samples/transcript/transform/treeify.ts +340 -135
- inspect_ai/_view/www/src/app/samples/transcript/transform/utils.ts +3 -0
- inspect_ai/_view/www/src/app/samples/transcript/types.ts +2 -0
- inspect_ai/_view/www/src/app/types.ts +5 -1
- inspect_ai/_view/www/src/client/api/api-browser.ts +2 -2
- inspect_ai/_view/www/src/components/LiveVirtualList.tsx +6 -1
- inspect_ai/_view/www/src/components/MarkdownDiv.tsx +1 -1
- inspect_ai/_view/www/src/components/PopOver.tsx +422 -0
- inspect_ai/_view/www/src/components/PulsingDots.module.css +9 -9
- inspect_ai/_view/www/src/components/PulsingDots.tsx +4 -1
- inspect_ai/_view/www/src/components/StickyScroll.tsx +183 -0
- inspect_ai/_view/www/src/components/TabSet.tsx +4 -0
- inspect_ai/_view/www/src/state/hooks.ts +52 -2
- inspect_ai/_view/www/src/state/logSlice.ts +4 -3
- inspect_ai/_view/www/src/state/samplePolling.ts +8 -0
- inspect_ai/_view/www/src/state/sampleSlice.ts +53 -9
- inspect_ai/_view/www/src/state/scrolling.ts +152 -0
- inspect_ai/_view/www/src/utils/attachments.ts +7 -0
- inspect_ai/_view/www/src/utils/python.ts +18 -0
- inspect_ai/_view/www/yarn.lock +290 -33
- inspect_ai/agent/_react.py +12 -7
- inspect_ai/agent/_run.py +2 -3
- inspect_ai/analysis/beta/__init__.py +2 -0
- inspect_ai/analysis/beta/_dataframe/samples/table.py +19 -18
- inspect_ai/dataset/_sources/csv.py +2 -6
- inspect_ai/dataset/_sources/hf.py +2 -6
- inspect_ai/dataset/_sources/json.py +2 -6
- inspect_ai/dataset/_util.py +23 -0
- inspect_ai/log/_log.py +1 -1
- inspect_ai/log/_recorders/eval.py +4 -3
- inspect_ai/log/_recorders/file.py +2 -9
- inspect_ai/log/_recorders/json.py +1 -0
- inspect_ai/log/_recorders/recorder.py +1 -0
- inspect_ai/log/_transcript.py +1 -1
- inspect_ai/model/_call_tools.py +6 -2
- inspect_ai/model/_openai.py +1 -1
- inspect_ai/model/_openai_responses.py +85 -41
- inspect_ai/model/_openai_web_search.py +38 -0
- inspect_ai/model/_providers/azureai.py +72 -3
- inspect_ai/model/_providers/openai.py +4 -1
- inspect_ai/model/_providers/openai_responses.py +5 -1
- inspect_ai/scorer/_metric.py +1 -2
- inspect_ai/scorer/_reducer/reducer.py +1 -1
- inspect_ai/solver/_task_state.py +2 -2
- inspect_ai/tool/_tool.py +6 -2
- inspect_ai/tool/_tool_def.py +27 -4
- inspect_ai/tool/_tool_info.py +2 -0
- inspect_ai/tool/_tools/_web_search/_google.py +43 -15
- inspect_ai/tool/_tools/_web_search/_tavily.py +46 -13
- inspect_ai/tool/_tools/_web_search/_web_search.py +214 -45
- inspect_ai/util/__init__.py +4 -0
- inspect_ai/util/_json.py +3 -0
- inspect_ai/util/_limit.py +230 -20
- inspect_ai/util/_sandbox/docker/compose.py +20 -11
- inspect_ai/util/_span.py +1 -1
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.101.dist-info}/METADATA +3 -3
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.101.dist-info}/RECORD +138 -124
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.101.dist-info}/WHEEL +1 -1
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.101.dist-info}/entry_points.txt +0 -0
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.101.dist-info}/licenses/LICENSE +0 -0
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.101.dist-info}/top_level.txt +0 -0
@@ -92,10 +92,14 @@ export interface SampleState {
|
|
92
92
|
sampleError: Error | undefined;
|
93
93
|
sampleNeedsReload: number;
|
94
94
|
|
95
|
+
visiblePopover?: string;
|
96
|
+
|
95
97
|
// Events and attachments
|
96
98
|
runningEvents: Event[];
|
97
|
-
collapsedEvents: Record<string,
|
99
|
+
collapsedEvents: Record<string, Record<string, boolean>> | null;
|
98
100
|
collapsedIdBuckets: Record<string, Record<string, boolean>>;
|
101
|
+
|
102
|
+
selectedOutlineId?: string;
|
99
103
|
}
|
100
104
|
|
101
105
|
export type Event =
|
@@ -113,11 +113,11 @@ async function eval_log_sample_data(
|
|
113
113
|
params.append("log", log_file);
|
114
114
|
params.append("id", String(id));
|
115
115
|
params.append("epoch", String(epoch));
|
116
|
-
if (last_event) {
|
116
|
+
if (last_event !== undefined) {
|
117
117
|
params.append("last-event-id", String(last_event));
|
118
118
|
}
|
119
119
|
|
120
|
-
if (last_attachment) {
|
120
|
+
if (last_attachment !== undefined) {
|
121
121
|
params.append("after-attachment-id", String(last_attachment));
|
122
122
|
}
|
123
123
|
|
@@ -36,6 +36,9 @@ interface LiveVirtualListProps<T> {
|
|
36
36
|
// The initial index to scroll to when loading
|
37
37
|
initialTopMostItemIndex?: number;
|
38
38
|
|
39
|
+
// The offset to use when scrolling items
|
40
|
+
offsetTop?: number;
|
41
|
+
|
39
42
|
components?: Components<T>;
|
40
43
|
}
|
41
44
|
|
@@ -51,6 +54,7 @@ export const LiveVirtualList = <T,>({
|
|
51
54
|
live,
|
52
55
|
showProgress,
|
53
56
|
initialTopMostItemIndex,
|
57
|
+
offsetTop,
|
54
58
|
components,
|
55
59
|
}: LiveVirtualListProps<T>) => {
|
56
60
|
// The list handle and list state management
|
@@ -170,7 +174,8 @@ export const LiveVirtualList = <T,>({
|
|
170
174
|
listHandle.current?.scrollToIndex({
|
171
175
|
index: initialTopMostItemIndex,
|
172
176
|
align: "start",
|
173
|
-
behavior: "
|
177
|
+
behavior: "smooth",
|
178
|
+
offset: offsetTop ? -offsetTop : undefined,
|
174
179
|
});
|
175
180
|
}, 50);
|
176
181
|
|
@@ -59,7 +59,7 @@ export const MarkdownDiv = forwardRef<HTMLDivElement, MarkdownDivProps>(
|
|
59
59
|
ref={ref}
|
60
60
|
dangerouslySetInnerHTML={markup}
|
61
61
|
style={style}
|
62
|
-
className={clsx(className, "markdown-content"
|
62
|
+
className={clsx(className, "markdown-content")}
|
63
63
|
/>
|
64
64
|
);
|
65
65
|
},
|
@@ -0,0 +1,422 @@
|
|
1
|
+
import { Placement } from "@popperjs/core";
|
2
|
+
import clsx from "clsx";
|
3
|
+
import React, {
|
4
|
+
CSSProperties,
|
5
|
+
ReactNode,
|
6
|
+
useEffect,
|
7
|
+
useRef,
|
8
|
+
useState,
|
9
|
+
} from "react";
|
10
|
+
import { createPortal } from "react-dom";
|
11
|
+
import { usePopper } from "react-popper";
|
12
|
+
|
13
|
+
interface PopOverProps {
|
14
|
+
id: string;
|
15
|
+
isOpen: boolean;
|
16
|
+
positionEl: HTMLElement | null;
|
17
|
+
placement?: Placement;
|
18
|
+
showArrow?: boolean;
|
19
|
+
offset?: [number, number];
|
20
|
+
usePortal?: boolean;
|
21
|
+
hoverDelay?: number;
|
22
|
+
|
23
|
+
className?: string | string[];
|
24
|
+
arrowClassName?: string | string[];
|
25
|
+
|
26
|
+
children: ReactNode;
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* A controlled Popper component for displaying content relative to a reference element
|
31
|
+
*/
|
32
|
+
export const PopOver: React.FC<PopOverProps> = ({
|
33
|
+
id,
|
34
|
+
isOpen,
|
35
|
+
positionEl,
|
36
|
+
children,
|
37
|
+
placement = "bottom",
|
38
|
+
showArrow = true,
|
39
|
+
offset = [0, 8],
|
40
|
+
className = "",
|
41
|
+
arrowClassName = "",
|
42
|
+
usePortal = true,
|
43
|
+
hoverDelay = 250,
|
44
|
+
}) => {
|
45
|
+
const popperRef = useRef<HTMLDivElement | null>(null);
|
46
|
+
const arrowRef = useRef<HTMLDivElement | null>(null);
|
47
|
+
const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(
|
48
|
+
null,
|
49
|
+
);
|
50
|
+
|
51
|
+
// For delayed hover functionality
|
52
|
+
const [shouldShowPopover, setShouldShowPopover] = useState(false);
|
53
|
+
const hoverTimerRef = useRef<number | null>(null);
|
54
|
+
const isMouseMovingRef = useRef(false);
|
55
|
+
|
56
|
+
// Setup hover timer and mouse movement detection
|
57
|
+
useEffect(() => {
|
58
|
+
if (!isOpen || hoverDelay <= 0) {
|
59
|
+
setShouldShowPopover(isOpen);
|
60
|
+
return;
|
61
|
+
}
|
62
|
+
|
63
|
+
const handleMouseMove = () => {
|
64
|
+
isMouseMovingRef.current = true;
|
65
|
+
|
66
|
+
// Clear any existing timer when mouse moves
|
67
|
+
if (hoverTimerRef.current !== null) {
|
68
|
+
window.clearTimeout(hoverTimerRef.current);
|
69
|
+
}
|
70
|
+
|
71
|
+
// Start a new timer to check if mouse has stopped moving
|
72
|
+
hoverTimerRef.current = window.setTimeout(() => {
|
73
|
+
if (isOpen) {
|
74
|
+
isMouseMovingRef.current = false;
|
75
|
+
setShouldShowPopover(true);
|
76
|
+
}
|
77
|
+
}, hoverDelay);
|
78
|
+
};
|
79
|
+
|
80
|
+
const handleMouseLeave = () => {
|
81
|
+
if (hoverTimerRef.current !== null) {
|
82
|
+
window.clearTimeout(hoverTimerRef.current);
|
83
|
+
}
|
84
|
+
isMouseMovingRef.current = false;
|
85
|
+
setShouldShowPopover(false);
|
86
|
+
};
|
87
|
+
|
88
|
+
const handleMouseDown = () => {
|
89
|
+
// Cancel popover on any mouse down
|
90
|
+
if (hoverTimerRef.current !== null) {
|
91
|
+
window.clearTimeout(hoverTimerRef.current);
|
92
|
+
}
|
93
|
+
setShouldShowPopover(false);
|
94
|
+
};
|
95
|
+
|
96
|
+
// Add event listeners to the positionEl (the trigger element)
|
97
|
+
if (positionEl && isOpen) {
|
98
|
+
positionEl.addEventListener("mousemove", handleMouseMove);
|
99
|
+
positionEl.addEventListener("mouseleave", handleMouseLeave);
|
100
|
+
|
101
|
+
// Add document-wide mousedown listener to dismiss on interaction
|
102
|
+
document.addEventListener("mousedown", handleMouseDown);
|
103
|
+
document.addEventListener("click", handleMouseDown);
|
104
|
+
|
105
|
+
// Initial mouse move to start the timer
|
106
|
+
handleMouseMove();
|
107
|
+
} else {
|
108
|
+
setShouldShowPopover(false);
|
109
|
+
}
|
110
|
+
|
111
|
+
return () => {
|
112
|
+
if (positionEl) {
|
113
|
+
positionEl.removeEventListener("mousemove", handleMouseMove);
|
114
|
+
positionEl.removeEventListener("mouseleave", handleMouseLeave);
|
115
|
+
}
|
116
|
+
|
117
|
+
// Clean up the document mousedown listener
|
118
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
119
|
+
|
120
|
+
document.removeEventListener("click", handleMouseDown);
|
121
|
+
|
122
|
+
if (hoverTimerRef.current !== null) {
|
123
|
+
window.clearTimeout(hoverTimerRef.current);
|
124
|
+
}
|
125
|
+
};
|
126
|
+
}, [isOpen, positionEl, hoverDelay]);
|
127
|
+
|
128
|
+
// Effect to create portal container when needed
|
129
|
+
useEffect(() => {
|
130
|
+
// Only create portal when the popover is open
|
131
|
+
if (usePortal && isOpen && shouldShowPopover) {
|
132
|
+
let container = document.getElementById(id);
|
133
|
+
|
134
|
+
if (!container) {
|
135
|
+
container = document.createElement("div");
|
136
|
+
container.id = id;
|
137
|
+
container.style.position = "absolute";
|
138
|
+
container.style.top = "0";
|
139
|
+
container.style.left = "0";
|
140
|
+
container.style.zIndex = "9999";
|
141
|
+
container.style.width = "0";
|
142
|
+
container.style.height = "0";
|
143
|
+
container.style.overflow = "visible";
|
144
|
+
|
145
|
+
document.body.appendChild(container);
|
146
|
+
}
|
147
|
+
|
148
|
+
setPortalContainer(container);
|
149
|
+
|
150
|
+
return () => {
|
151
|
+
// Clean up only when unmounting or when the popover closes
|
152
|
+
if (document.body.contains(container)) {
|
153
|
+
document.body.removeChild(container);
|
154
|
+
setPortalContainer(null);
|
155
|
+
}
|
156
|
+
};
|
157
|
+
}
|
158
|
+
|
159
|
+
return undefined;
|
160
|
+
}, [usePortal, isOpen, shouldShowPopover, id]);
|
161
|
+
|
162
|
+
// Configure modifiers for popper
|
163
|
+
const modifiers = [
|
164
|
+
{ name: "offset", options: { offset } },
|
165
|
+
{ name: "preventOverflow", options: { padding: 8 } },
|
166
|
+
{
|
167
|
+
name: "arrow",
|
168
|
+
enabled: showArrow,
|
169
|
+
options: {
|
170
|
+
element: arrowRef.current,
|
171
|
+
padding: 5, // This keeps the arrow from getting too close to the corner
|
172
|
+
},
|
173
|
+
},
|
174
|
+
{
|
175
|
+
name: "computeStyles",
|
176
|
+
options: {
|
177
|
+
gpuAcceleration: false,
|
178
|
+
adaptive: true,
|
179
|
+
},
|
180
|
+
},
|
181
|
+
// Ensure popper is positioned correctly with respect to its reference element
|
182
|
+
{
|
183
|
+
name: "flip",
|
184
|
+
options: {
|
185
|
+
fallbackPlacements: ["top", "right", "bottom", "left"],
|
186
|
+
},
|
187
|
+
},
|
188
|
+
];
|
189
|
+
|
190
|
+
// Use popper hook with modifiers
|
191
|
+
const { styles, attributes, state, update } = usePopper(
|
192
|
+
positionEl,
|
193
|
+
popperRef.current,
|
194
|
+
{
|
195
|
+
placement,
|
196
|
+
strategy: "fixed",
|
197
|
+
modifiers,
|
198
|
+
},
|
199
|
+
);
|
200
|
+
|
201
|
+
// Force update when needed refs change
|
202
|
+
useEffect(() => {
|
203
|
+
if (update && isOpen && shouldShowPopover) {
|
204
|
+
// Need to delay the update slightly to ensure refs are properly set
|
205
|
+
const timer = setTimeout(() => {
|
206
|
+
update();
|
207
|
+
}, 10);
|
208
|
+
return () => clearTimeout(timer);
|
209
|
+
}
|
210
|
+
}, [update, isOpen, shouldShowPopover, showArrow, arrowRef.current]);
|
211
|
+
|
212
|
+
// Define arrow data-* attribute based on placement
|
213
|
+
const getArrowDataPlacement = () => {
|
214
|
+
if (!state || !state.placement) return placement;
|
215
|
+
return state.placement;
|
216
|
+
};
|
217
|
+
|
218
|
+
// Get the actual placement from Popper state
|
219
|
+
const actualPlacement = state?.placement || placement;
|
220
|
+
|
221
|
+
// For a CSS triangle, we use the border trick
|
222
|
+
// A CSS triangle doesn't need separate border styling like a rotated square would
|
223
|
+
|
224
|
+
// Popper container styles
|
225
|
+
const defaultPopperStyles: CSSProperties = {
|
226
|
+
backgroundColor: "var(--bs-body-bg)",
|
227
|
+
padding: "12px",
|
228
|
+
borderRadius: "4px",
|
229
|
+
boxShadow: "0 2px 10px rgba(0,0,0,0.1)",
|
230
|
+
border: "1px solid #eee",
|
231
|
+
zIndex: 1200,
|
232
|
+
position: "relative",
|
233
|
+
// Apply opacity transition to smooth the appearance
|
234
|
+
opacity: state?.placement ? 1 : 0,
|
235
|
+
transition: "opacity 0.1s",
|
236
|
+
};
|
237
|
+
|
238
|
+
// Early return if not open or should not show due to hover delay
|
239
|
+
if (!isOpen || (hoverDelay > 0 && !shouldShowPopover)) {
|
240
|
+
return null;
|
241
|
+
}
|
242
|
+
|
243
|
+
// For position-aware rendering
|
244
|
+
const positionedStyle =
|
245
|
+
state && state.styles && state.styles.popper
|
246
|
+
? {
|
247
|
+
...styles.popper,
|
248
|
+
opacity: 1,
|
249
|
+
}
|
250
|
+
: {
|
251
|
+
...styles.popper,
|
252
|
+
opacity: 0,
|
253
|
+
// Position offscreen initially to prevent flicker
|
254
|
+
position: "fixed" as const,
|
255
|
+
top: "-9999px",
|
256
|
+
left: "-9999px",
|
257
|
+
};
|
258
|
+
|
259
|
+
// Create the popper content with position-aware styles
|
260
|
+
const popperContent = (
|
261
|
+
<div
|
262
|
+
ref={popperRef}
|
263
|
+
style={{ ...defaultPopperStyles, ...positionedStyle }}
|
264
|
+
className={clsx(className)}
|
265
|
+
{...attributes.popper}
|
266
|
+
>
|
267
|
+
{children}
|
268
|
+
|
269
|
+
{showArrow && (
|
270
|
+
<>
|
271
|
+
{/* Invisible div for Popper.js to use as reference */}
|
272
|
+
<div
|
273
|
+
ref={arrowRef}
|
274
|
+
style={{ position: "absolute", visibility: "hidden" }}
|
275
|
+
data-placement={getArrowDataPlacement()}
|
276
|
+
/>
|
277
|
+
|
278
|
+
{/* Arrow container - positioned by Popper */}
|
279
|
+
<div
|
280
|
+
className={clsx("popper-arrow-container", arrowClassName)}
|
281
|
+
style={{
|
282
|
+
...styles.arrow,
|
283
|
+
position: "absolute",
|
284
|
+
zIndex: 1,
|
285
|
+
// Size and positioning based on placement - smaller arrow
|
286
|
+
...(actualPlacement.startsWith("top") && {
|
287
|
+
bottom: "-8px",
|
288
|
+
width: "16px",
|
289
|
+
height: "8px",
|
290
|
+
}),
|
291
|
+
...(actualPlacement.startsWith("bottom") && {
|
292
|
+
top: "-8px",
|
293
|
+
width: "16px",
|
294
|
+
height: "8px",
|
295
|
+
}),
|
296
|
+
...(actualPlacement.startsWith("left") && {
|
297
|
+
right: "-8px",
|
298
|
+
width: "8px",
|
299
|
+
height: "16px",
|
300
|
+
}),
|
301
|
+
...(actualPlacement.startsWith("right") && {
|
302
|
+
left: "-8px",
|
303
|
+
width: "8px",
|
304
|
+
height: "16px",
|
305
|
+
}),
|
306
|
+
// Content positioning
|
307
|
+
overflow: "hidden",
|
308
|
+
}}
|
309
|
+
>
|
310
|
+
{/* Border element (rendered behind) */}
|
311
|
+
{actualPlacement.startsWith("top") && (
|
312
|
+
<div
|
313
|
+
style={{
|
314
|
+
position: "absolute",
|
315
|
+
width: 0,
|
316
|
+
height: 0,
|
317
|
+
borderStyle: "solid",
|
318
|
+
borderWidth: "8px 8px 0 8px",
|
319
|
+
borderColor: "#eee transparent transparent transparent",
|
320
|
+
top: "0px",
|
321
|
+
left: "0px",
|
322
|
+
}}
|
323
|
+
/>
|
324
|
+
)}
|
325
|
+
{actualPlacement.startsWith("bottom") && (
|
326
|
+
<div
|
327
|
+
style={{
|
328
|
+
position: "absolute",
|
329
|
+
width: 0,
|
330
|
+
height: 0,
|
331
|
+
borderStyle: "solid",
|
332
|
+
borderWidth: "0 8px 8px 8px",
|
333
|
+
borderColor: "transparent transparent #eee transparent",
|
334
|
+
top: "0px",
|
335
|
+
left: "0px",
|
336
|
+
}}
|
337
|
+
/>
|
338
|
+
)}
|
339
|
+
{actualPlacement.startsWith("left") && (
|
340
|
+
<div
|
341
|
+
style={{
|
342
|
+
position: "absolute",
|
343
|
+
width: 0,
|
344
|
+
height: 0,
|
345
|
+
borderStyle: "solid",
|
346
|
+
borderWidth: "8px 0 8px 8px",
|
347
|
+
borderColor: "transparent transparent transparent #eee",
|
348
|
+
top: "0px",
|
349
|
+
left: "0px",
|
350
|
+
}}
|
351
|
+
/>
|
352
|
+
)}
|
353
|
+
{actualPlacement.startsWith("right") && (
|
354
|
+
<div
|
355
|
+
style={{
|
356
|
+
position: "absolute",
|
357
|
+
width: 0,
|
358
|
+
height: 0,
|
359
|
+
borderStyle: "solid",
|
360
|
+
borderWidth: "8px 8px 8px 0",
|
361
|
+
borderColor: "transparent #eee transparent transparent",
|
362
|
+
top: "0px",
|
363
|
+
left: "0px",
|
364
|
+
}}
|
365
|
+
/>
|
366
|
+
)}
|
367
|
+
|
368
|
+
{/* Actual triangle created with CSS borders, slightly smaller and offset to create border effect */}
|
369
|
+
<div
|
370
|
+
style={{
|
371
|
+
position: "absolute",
|
372
|
+
width: 0,
|
373
|
+
height: 0,
|
374
|
+
borderStyle: "solid",
|
375
|
+
backgroundColor: "transparent",
|
376
|
+
// Position relative to border triangle
|
377
|
+
left: "0px",
|
378
|
+
zIndex: 1,
|
379
|
+
|
380
|
+
// Top placement - pointing down
|
381
|
+
...(actualPlacement.startsWith("top") && {
|
382
|
+
borderWidth: "7px 7px 0 7px",
|
383
|
+
borderColor: "white transparent transparent transparent",
|
384
|
+
top: "0px",
|
385
|
+
}),
|
386
|
+
|
387
|
+
// Bottom placement - pointing up
|
388
|
+
...(actualPlacement.startsWith("bottom") && {
|
389
|
+
borderWidth: "0 7px 7px 7px",
|
390
|
+
borderColor: "transparent transparent white transparent",
|
391
|
+
top: "1px",
|
392
|
+
}),
|
393
|
+
|
394
|
+
// Left placement - pointing right
|
395
|
+
...(actualPlacement.startsWith("left") && {
|
396
|
+
borderWidth: "7px 0 7px 7px",
|
397
|
+
borderColor: "transparent transparent transparent white",
|
398
|
+
left: "0px",
|
399
|
+
}),
|
400
|
+
|
401
|
+
// Right placement - pointing left
|
402
|
+
...(actualPlacement.startsWith("right") && {
|
403
|
+
borderWidth: "7px 7px 7px 0",
|
404
|
+
borderColor: "transparent white transparent transparent",
|
405
|
+
left: "1px",
|
406
|
+
}),
|
407
|
+
}}
|
408
|
+
/>
|
409
|
+
</div>
|
410
|
+
</>
|
411
|
+
)}
|
412
|
+
</div>
|
413
|
+
);
|
414
|
+
|
415
|
+
// If using portal and the container exists, render through the portal
|
416
|
+
if (usePortal && portalContainer) {
|
417
|
+
return createPortal(popperContent, portalContainer);
|
418
|
+
}
|
419
|
+
|
420
|
+
// Otherwise render normally
|
421
|
+
return popperContent;
|
422
|
+
};
|
@@ -13,7 +13,7 @@
|
|
13
13
|
}
|
14
14
|
|
15
15
|
.small .dotsContainer {
|
16
|
-
column-gap:
|
16
|
+
column-gap: 2px;
|
17
17
|
}
|
18
18
|
|
19
19
|
.medium .dotsContainer {
|
@@ -34,16 +34,16 @@
|
|
34
34
|
}
|
35
35
|
|
36
36
|
.subtle {
|
37
|
-
background-color: var(--bs-
|
37
|
+
background-color: var(--bs-secondary-bg-subtle);
|
38
38
|
}
|
39
39
|
|
40
40
|
.primary {
|
41
|
-
background-color: var(--bs-
|
41
|
+
background-color: var(--bs-secondary);
|
42
42
|
}
|
43
43
|
|
44
44
|
.small .dot {
|
45
|
-
width:
|
46
|
-
height:
|
45
|
+
width: 3px;
|
46
|
+
height: 3px;
|
47
47
|
}
|
48
48
|
|
49
49
|
.medium .dot {
|
@@ -71,11 +71,11 @@
|
|
71
71
|
@keyframes pulse {
|
72
72
|
0%,
|
73
73
|
100% {
|
74
|
-
transform: scale(
|
75
|
-
opacity: 0.
|
74
|
+
transform: scale(0.7);
|
75
|
+
opacity: 0.4;
|
76
76
|
}
|
77
77
|
50% {
|
78
|
-
transform: scale(1
|
79
|
-
opacity:
|
78
|
+
transform: scale(1);
|
79
|
+
opacity: 0.8;
|
80
80
|
}
|
81
81
|
}
|
@@ -7,6 +7,7 @@ interface PulsingDotsProps {
|
|
7
7
|
dotsCount?: number;
|
8
8
|
subtle?: boolean;
|
9
9
|
size?: "small" | "medium" | "large";
|
10
|
+
className?: string | string[];
|
10
11
|
}
|
11
12
|
|
12
13
|
export const PulsingDots: FC<PulsingDotsProps> = ({
|
@@ -14,6 +15,7 @@ export const PulsingDots: FC<PulsingDotsProps> = ({
|
|
14
15
|
dotsCount = 3,
|
15
16
|
subtle = true,
|
16
17
|
size = "small",
|
18
|
+
className,
|
17
19
|
}) => {
|
18
20
|
return (
|
19
21
|
<div
|
@@ -24,6 +26,7 @@ export const PulsingDots: FC<PulsingDotsProps> = ({
|
|
24
26
|
: size === "medium"
|
25
27
|
? styles.medium
|
26
28
|
: styles.large,
|
29
|
+
className,
|
27
30
|
)}
|
28
31
|
role="status"
|
29
32
|
>
|
@@ -35,7 +38,7 @@ export const PulsingDots: FC<PulsingDotsProps> = ({
|
|
35
38
|
styles.dot,
|
36
39
|
subtle ? styles.subtle : styles.primary,
|
37
40
|
)}
|
38
|
-
style={{ animationDelay: `${index * 0.
|
41
|
+
style={{ animationDelay: `${index * 0.2}s` }}
|
39
42
|
/>
|
40
43
|
))}
|
41
44
|
</div>
|