typescript fixes, replayer close error, show page toggle fix.

This commit is contained in:
Francis Cao committed 2026-06-17 10:02:12 -07:00
1 parent 10dced1049
commit f3ce0e64ca
15 files changed
+67 -28

No files matched your search

@@ -23,7 +23,7 @@ export function TestConsolePage({ websiteId }: { websiteId: string }) {
test: 'test-data',
boolean: true,
booleanError: 'true',
time: new Date(),
time: new Date().toISOString(),
user: `user${Math.round(Math.random() * 10)}`,
number: 1,
number2: Math.random() * 100,
@@ -87,7 +87,7 @@ export function TestConsolePage({ websiteId }: { websiteId: string }) {
test: 'test-data',
boolean: true,
booleanError: 'true',
time: new Date(),
time: new Date().toISOString(),
time2: new Date().toISOString(),
nested: {
test: 'test-data',
-1
View File
@@ -10,7 +10,6 @@ export function LinkEditButton({ linkId }: { linkId: string }) {
return (
<LinkButton
href={renderUrl(`/links/${linkId}/edit`, false)}
title={t(labels.edit)}
aria-label={t(labels.edit)}
variant="quiet"
>
@@ -10,7 +10,6 @@ export function PixelEditButton({ pixelId }: { pixelId: string }) {
return (
<LinkButton
href={renderUrl(`/pixels/${pixelId}/edit`, false)}
title={t(labels.edit)}
aria-label={t(labels.edit)}
variant="quiet"
>
@@ -269,8 +269,8 @@ function ClickHeatmapView({
const hasSnapshot = Boolean(snapshot);
useEffect(() => {
setSnapshotReady(!(showPage && hasSnapshot));
}, [hasSnapshot, showPage, snapshot?.id]);
setSnapshotReady(!hasSnapshot);
}, [hasSnapshot, snapshot?.id]);
const overlayGutter = Math.max(48, Math.round((viewport?.width ?? 1920) * 0.04));
const maxPointX = visible.reduce((max, point) => Math.max(max, point.pageX), 0);
const maxPointY = visible.reduce((max, point) => Math.max(max, point.pageY), 0);
@@ -425,8 +425,8 @@ function ScrollHeatmapView({
const hasSnapshot = Boolean(snapshot);
useEffect(() => {
setSnapshotReady(!(showPage && hasSnapshot));
}, [hasSnapshot, showPage, snapshot?.id]);
setSnapshotReady(!hasSnapshot);
}, [hasSnapshot, snapshot?.id]);
const {
buckets = [],
totalSessions = 0,
@@ -1,4 +1,4 @@
import thenby from 'thenby';
import { firstBy } from 'thenby';
import { useMessages, useWebsite } from '@/components/hooks';
import { ListTable } from '@/components/metrics/ListTable';
import { percentFilter } from '@/lib/filters';
@@ -26,7 +26,7 @@ export function RealtimePaths({ data }: { data: any }) {
y: urls[key],
};
})
.sort(thenby.firstBy('y', -1))
.sort(firstBy('y', -1))
.slice(0, limit),
);
@@ -1,7 +1,7 @@
import thenby from 'thenby';
import { useMessages, useWebsite } from '@/components/hooks';
import { ListTable } from '@/components/metrics/ListTable';
import { percentFilter } from '@/lib/filters';
import { firstBy } from 'thenby';
export function RealtimeReferrers({ data }: { data: any }) {
const website = useWebsite();
@@ -26,7 +26,7 @@ export function RealtimeReferrers({ data }: { data: any }) {
y: referrers[key],
};
})
.sort(thenby.firstBy('y', -1))
.sort(firstBy('y', -1))
.slice(0, limit),
);
@@ -8,6 +8,21 @@ import 'rrweb-player/dist/style.css';
const DEFAULT_REPLAY_ASPECT_RATIO = 9 / 16;
function destroyReplayPlayer(player: { $destroy?: () => void } | null) {
if (!player) {
return;
}
try {
player.$destroy?.();
} catch (error) {
// rrweb-player alpha teardown can throw after it loses its inner replayer instance.
if (!(error instanceof TypeError) || !error.message.includes('pause is not a function')) {
throw error;
}
}
}
export function ReplayPlayer({ events }: { events: any[] }) {
const playerRootRef = useRef<HTMLDivElement>(null);
const playerRef = useRef<any>(null);
@@ -34,7 +49,7 @@ export function ReplayPlayer({ events }: { events: any[] }) {
setPlayerError(false);
if (playerRef.current) {
playerRef.current.$destroy?.();
destroyReplayPlayer(playerRef.current);
playerRef.current = null;
}
@@ -89,7 +104,7 @@ export function ReplayPlayer({ events }: { events: any[] }) {
cancelled = true;
if (playerRef.current) {
playerRef.current.$destroy?.();
destroyReplayPlayer(playerRef.current);
playerRef.current = null;
}
+1 -1
View File
@@ -20,7 +20,7 @@ vi.mock('@/lib/response', () => ({
ok: () => new Response(null, { status: 200 }),
}));
const redisMock = redis as {
const redisMock = redis as unknown as {
enabled: boolean;
client: {
del: ReturnType<typeof vi.fn>;
+1 -1
View File
@@ -32,7 +32,7 @@ export function CopyButton({ value, label = 'Copy' }: { value: string; label?: s
};
return (
<Button variant="quiet" onPress={handleCopy} title={label} aria-label={label}>
<Button variant="quiet" onPress={handleCopy} aria-label={label}>
<Icon size="sm">{copied ? <Check /> : <Copy />}</Icon>
</Button>
);
+2 -2
View File
@@ -3,9 +3,9 @@ import type { ErrorInfo, ReactNode } from 'react';
import { ErrorBoundary as Boundary } from 'react-error-boundary';
import { useMessages } from '@/components/hooks';
const logError = (error: Error, info: ErrorInfo) => {
const logError = (error: unknown, info: ErrorInfo) => {
// eslint-disable-next-line no-console
console.error(error, info.componentStack);
console.error(error instanceof Error ? error : new Error(String(error)), info.componentStack);
};
export function ErrorBoundary({ children }: { children: ReactNode }) {
+2 -3
View File
@@ -23,15 +23,14 @@ export function FilterLink({ type, value, label, externalUrl, icon }: FilterLink
<Row
alignItems="center"
gap
fontWeight={active && selected ? 'bold' : undefined}
color={active && !selected ? 'muted' : undefined}
onMouseOver={() => setShowLink(true)}
onMouseOut={() => setShowLink(false)}
>
{icon}
{!value && `(${label || t(labels.unknown)})`}
{!value && <Text weight={active && selected ? 'bold' : undefined}>({label || t(labels.unknown)})</Text>}
{value && (
<Text title={label || value} truncate>
<Text title={label || value} truncate weight={active && selected ? 'bold' : undefined}>
<Link href={updateParams({ [type]: `eq.${value}` })} replace>
{label || value}
</Link>
+1 -1
View File
@@ -5,7 +5,7 @@ export const KAFKA = 'kafka';
export const KAFKA_PRODUCER = 'kafka-producer';
// Fixes issue with converting bigint values
BigInt.prototype.toJSON = function () {
(BigInt.prototype as unknown as { toJSON(): number }).toJSON = function () {
return Number(this);
};
+5 -1
View File
@@ -4,6 +4,10 @@ import type { Filter, Operator, PropertyFilter, QueryFilters, QueryOptions } fro
const VALID_OPERATORS: Operator[] = Object.values(OPERATORS);
const VALID_EVENT_DATA_TYPES = Object.values(DATA_TYPE);
function isValidEventDataType(value: number): value is (typeof VALID_EVENT_DATA_TYPES)[number] {
return VALID_EVENT_DATA_TYPES.includes(value as (typeof VALID_EVENT_DATA_TYPES)[number]);
}
function resolveOperator(value?: string): Operator | undefined {
if (!value) {
return undefined;
@@ -126,7 +130,7 @@ export function parsePropertyFilters(
if (
!operator ||
(explicitDataType !== undefined && !VALID_EVENT_DATA_TYPES.includes(explicitDataType))
(explicitDataType !== undefined && !isValidEventDataType(explicitDataType))
) {
return [];
}
+4 -2
View File
@@ -8,9 +8,11 @@ import {
type ReactNode,
} from 'react';
type ReactElementWithChildren = ReactElement<{ children?: ReactNode }>;
export function getFragmentChildren(children: ReactNode) {
return (children as ReactElement)?.type === Fragment
? (children as ReactElement).props.children
return (children as ReactElementWithChildren)?.type === Fragment
? (children as ReactElementWithChildren).props.children
: children;
}
+24 -3
View File
@@ -66,7 +66,7 @@ export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
* - Objects have a max of 50 properties. Arrays are considered 1 property.
*/
export interface EventData {
[key: string]: number | string | EventData | number[] | string[] | EventData[];
[key: string]: boolean | number | string | EventData | boolean[] | number[] | string[] | EventData[];
}
export type EventProperties = {
@@ -146,8 +146,29 @@ export type UmamiTracker = {
*/
(eventFunction: CustomEventFunction): Promise<string>;
};
identify: {
/**
* Identify a visitor with optional associated data.
*
* @example ```
* umami.identify('user-123', { plan: 'pro' });
* ```
*/
(id: string, data?: EventData): Promise<string>;
/**
* Associate data with the current visitor without setting an identity string.
*
* @example ```
* umami.identify({ plan: 'pro' });
* ```
*/
(data: EventData): Promise<string>;
};
};
export interface Window {
umami: UmamiTracker;
declare global {
interface Window {
umami: UmamiTracker;
}
}